summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/exportfs/expfs.c32
-rw-r--r--include/linux/exportfs.h10
2 files changed, 36 insertions, 6 deletions
diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c
index 8f883c4758f5..7d9fdcc187b7 100644
--- a/fs/exportfs/expfs.c
+++ b/fs/exportfs/expfs.c
@@ -383,6 +383,32 @@ int generic_encode_ino32_fh(struct inode *inode, __u32 *fh, int *max_len,
}
EXPORT_SYMBOL_GPL(generic_encode_ino32_fh);
+#define FILEID_INO64_GEN_LEN 3
+
+/**
+ * exportfs_encode_ino64_fid - encode non-decodeable 64bit ino file id
+ * @inode: the object to encode
+ * @fid: where to store the file handle fragment
+ * @max_len: maximum length to store there (in 4 byte units)
+ *
+ * This generic function is used to encode a non-decodeable file id for
+ * fanotify for filesystems that do not support NFS export.
+ */
+static int exportfs_encode_ino64_fid(struct inode *inode, struct fid *fid,
+ int *max_len)
+{
+ if (*max_len < FILEID_INO64_GEN_LEN) {
+ *max_len = FILEID_INO64_GEN_LEN;
+ return FILEID_INVALID;
+ }
+
+ fid->i64.ino = inode->i_ino;
+ fid->i64.gen = inode->i_generation;
+ *max_len = FILEID_INO64_GEN_LEN;
+
+ return FILEID_INO64_GEN;
+}
+
/**
* exportfs_encode_inode_fh - encode a file handle from inode
* @inode: the object to encode
@@ -401,10 +427,10 @@ int exportfs_encode_inode_fh(struct inode *inode, struct fid *fid,
if (!exportfs_can_encode_fh(nop, flags))
return -EOPNOTSUPP;
- if (nop && nop->encode_fh)
- return nop->encode_fh(inode, fid->raw, max_len, parent);
+ if (!nop && (flags & EXPORT_FH_FID))
+ return exportfs_encode_ino64_fid(inode, fid, max_len);
- return -EOPNOTSUPP;
+ return nop->encode_fh(inode, fid->raw, max_len, parent);
}
EXPORT_SYMBOL_GPL(exportfs_encode_inode_fh);
diff --git a/include/linux/exportfs.h b/include/linux/exportfs.h
index 4119d3ee72eb..21bae8bfeef1 100644
--- a/include/linux/exportfs.h
+++ b/include/linux/exportfs.h
@@ -134,7 +134,11 @@ struct fid {
u32 parent_ino;
u32 parent_gen;
} i32;
- struct {
+ struct {
+ u64 ino;
+ u32 gen;
+ } __packed i64;
+ struct {
u32 block;
u16 partref;
u16 parent_partref;
@@ -246,7 +250,7 @@ extern int exportfs_encode_fh(struct dentry *dentry, struct fid *fid,
static inline bool exportfs_can_encode_fid(const struct export_operations *nop)
{
- return nop && nop->encode_fh;
+ return !nop || nop->encode_fh;
}
static inline bool exportfs_can_decode_fh(const struct export_operations *nop)
@@ -259,7 +263,7 @@ static inline bool exportfs_can_encode_fh(const struct export_operations *nop,
{
/*
* If a non-decodeable file handle was requested, we only need to make
- * sure that filesystem can encode file handles.
+ * sure that filesystem did not opt-out of encoding fid.
*/
if (fh_flags & EXPORT_FH_FID)
return exportfs_can_encode_fid(nop);