exportfs: Return the minimum required handle size
authorAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Sat, 29 Jan 2011 13:13:25 +0000 (18:43 +0530)
committerAl Viro <viro@zeniv.linux.org.uk>
Mon, 14 Mar 2011 13:15:28 +0000 (09:15 -0400)
The exportfs encode handle function should return the minimum required
handle size. This helps user to find out the handle size by passing 0
handle size in the first step and then redoing to the call again with
the returned handle size value.

Acked-by: Serge Hallyn <serue@us.ibm.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
12 files changed:
fs/btrfs/export.c
fs/exportfs/expfs.c
fs/fat/inode.c
fs/fuse/inode.c
fs/gfs2/export.c
fs/isofs/export.c
fs/ocfs2/export.c
fs/reiserfs/inode.c
fs/udf/namei.c
fs/xfs/linux-2.6/xfs_export.c
include/linux/exportfs.h
mm/shmem.c

index ff27d7a477b2012d1cd900164c6596ed77a9efb2..b4ffad859adb31a5ad5d8628a1fd6a10adae06ec 100644 (file)
@@ -21,9 +21,13 @@ static int btrfs_encode_fh(struct dentry *dentry, u32 *fh, int *max_len,
        int len = *max_len;
        int type;
 
-       if ((len < BTRFS_FID_SIZE_NON_CONNECTABLE) ||
-           (connectable && len < BTRFS_FID_SIZE_CONNECTABLE))
+       if (connectable && (len < BTRFS_FID_SIZE_CONNECTABLE)) {
+               *max_len = BTRFS_FID_SIZE_CONNECTABLE;
                return 255;
+       } else if (len < BTRFS_FID_SIZE_NON_CONNECTABLE) {
+               *max_len = BTRFS_FID_SIZE_NON_CONNECTABLE;
+               return 255;
+       }
 
        len  = BTRFS_FID_SIZE_NON_CONNECTABLE;
        type = FILEID_BTRFS_WITHOUT_PARENT;
index 4b6825740dd5e6cfcf38918d3c8e477a677e94a4..cfe55731b6dc4216168229a55e448ff428c8609f 100644 (file)
@@ -320,9 +320,14 @@ static int export_encode_fh(struct dentry *dentry, struct fid *fid,
        struct inode * inode = dentry->d_inode;
        int len = *max_len;
        int type = FILEID_INO32_GEN;
-       
-       if (len < 2 || (connectable && len < 4))
+
+       if (connectable && (len < 4)) {
+               *max_len = 4;
+               return 255;
+       } else if (len < 2) {
+               *max_len = 2;
                return 255;
+       }
 
        len = 2;
        fid->i32.ino = inode->i_ino;
index 86753fe10bd1d7a47d551dba030ee45013e5fbbe..0e277ec4b6120663795086b3a0cc80c4d1fcc813 100644 (file)
@@ -757,8 +757,10 @@ fat_encode_fh(struct dentry *de, __u32 *fh, int *lenp, int connectable)
        struct inode *inode =  de->d_inode;
        u32 ipos_h, ipos_m, ipos_l;
 
-       if (len < 5)
+       if (len < 5) {
+               *lenp = 5;
                return 255; /* no room */
+       }
 
        ipos_h = MSDOS_I(inode)->i_pos >> 8;
        ipos_m = (MSDOS_I(inode)->i_pos & 0xf0) << 24;
index 9e3f68cc1bd1338e2c8a6f73de6646fface53be7..051b1a084528b382201ae2a5dd3f7c536a60122c 100644 (file)
@@ -637,8 +637,10 @@ static int fuse_encode_fh(struct dentry *dentry, u32 *fh, int *max_len,
        u64 nodeid;
        u32 generation;
 
-       if (*max_len < len)
+       if (*max_len < len) {
+               *max_len = len;
                return  255;
+       }
 
        nodeid = get_fuse_inode(inode)->nodeid;
        generation = inode->i_generation;
index 9023db8184f91ba758bae3c2a981e0a8180d2dfb..b5a5e60df0d5294ea237da99a231416fe800e5b4 100644 (file)
@@ -36,9 +36,13 @@ static int gfs2_encode_fh(struct dentry *dentry, __u32 *p, int *len,
        struct super_block *sb = inode->i_sb;
        struct gfs2_inode *ip = GFS2_I(inode);
 
-       if (*len < GFS2_SMALL_FH_SIZE ||
-           (connectable && *len < GFS2_LARGE_FH_SIZE))
+       if (connectable && (*len < GFS2_LARGE_FH_SIZE)) {
+               *len = GFS2_LARGE_FH_SIZE;
                return 255;
+       } else if (*len < GFS2_SMALL_FH_SIZE) {
+               *len = GFS2_SMALL_FH_SIZE;
+               return 255;
+       }
 
        fh[0] = cpu_to_be32(ip->i_no_formal_ino >> 32);
        fh[1] = cpu_to_be32(ip->i_no_formal_ino & 0xFFFFFFFF);
index ed752cb3847426f108803af94566ba79d80786ed..dd4687ff30d09900a14f113aec870007cfcfb7f0 100644 (file)
@@ -124,9 +124,13 @@ isofs_export_encode_fh(struct dentry *dentry,
         * offset of the inode and the upper 16 bits of fh32[1] to
         * hold the offset of the parent.
         */
-
-       if (len < 3 || (connectable && len < 5))
+       if (connectable && (len < 5)) {
+               *max_len = 5;
+               return 255;
+       } else if (len < 3) {
+               *max_len = 3;
                return 255;
+       }
 
        len = 3;
        fh32[0] = ei->i_iget5_block;
index 5dbc3062b4fd0757792c2f048d8a8a2c647b5b34..254652a9b542687e1a08e0e52d7b28db20ed6ba3 100644 (file)
@@ -197,8 +197,12 @@ static int ocfs2_encode_fh(struct dentry *dentry, u32 *fh_in, int *max_len,
                   dentry->d_name.len, dentry->d_name.name,
                   fh, len, connectable);
 
-       if (len < 3 || (connectable && len < 6)) {
-               mlog(ML_ERROR, "fh buffer is too small for encoding\n");
+       if (connectable && (len < 6)) {
+               *max_len = 6;
+               type = 255;
+               goto bail;
+       } else if (len < 3) {
+               *max_len = 3;
                type = 255;
                goto bail;
        }
index 0bae036831e2ca2aeeae94eb78d74f2aa769b54d..1bba24bad82080382e3007a10da67b85305d88db 100644 (file)
@@ -1593,8 +1593,13 @@ int reiserfs_encode_fh(struct dentry *dentry, __u32 * data, int *lenp,
        struct inode *inode = dentry->d_inode;
        int maxlen = *lenp;
 
-       if (maxlen < 3)
+       if (need_parent && (maxlen < 5)) {
+               *lenp = 5;
                return 255;
+       } else if (maxlen < 3) {
+               *lenp = 3;
+               return 255;
+       }
 
        data[0] = inode->i_ino;
        data[1] = le32_to_cpu(INODE_PKEY(inode)->k_dir_id);
index b7c338d5e9df35f9c30d36538c1dd85dfbf7268e..f1dce848ef966ea1853c9f50ce2d9cc997114a18 100644 (file)
@@ -1286,8 +1286,13 @@ static int udf_encode_fh(struct dentry *de, __u32 *fh, int *lenp,
        struct fid *fid = (struct fid *)fh;
        int type = FILEID_UDF_WITHOUT_PARENT;
 
-       if (len < 3 || (connectable && len < 5))
+       if (connectable && (len < 5)) {
+               *lenp = 5;
+               return 255;
+       } else if (len < 3) {
+               *lenp = 3;
                return 255;
+       }
 
        *lenp = 3;
        fid->udf.block = location.logicalBlockNum;
index fc0114da7fdd07b86440b2326c9b76a97c96b229..f4f878fc008316e816c24de3cdb1b86908ce9b52 100644 (file)
@@ -89,8 +89,10 @@ xfs_fs_encode_fh(
         * seven combinations work.  The real answer is "don't use v2".
         */
        len = xfs_fileid_length(fileid_type);
-       if (*max_len < len)
+       if (*max_len < len) {
+               *max_len = len;
                return 255;
+       }
        *max_len = len;
 
        switch (fileid_type) {
index 28028988c8627dbc6c065335ba6ca7d9c5bb64ee..65afdfd31b7ba3c1502b734016832bc8db01cee4 100644 (file)
@@ -121,8 +121,10 @@ struct fid {
  *    set, the encode_fh() should store sufficient information so that a good
  *    attempt can be made to find not only the file but also it's place in the
  *    filesystem.   This typically means storing a reference to de->d_parent in
- *    the filehandle fragment.  encode_fh() should return the number of bytes
- *    stored or a negative error code such as %-ENOSPC
+ *    the filehandle fragment.  encode_fh() should return the fileid_type on
+ *    success and on error returns 255 (if the space needed to encode fh is
+ *    greater than @max_len*4 bytes). On error @max_len contains the minimum
+ *    size(in 4 byte unit) needed to encode the file handle.
  *
  * fh_to_dentry:
  *    @fh_to_dentry is given a &struct super_block (@sb) and a file handle
index 5ee67c9906022a15b566711da17b8c78e65fa16d..3437b65d6d6e76e71aedbe5ed02f851f400133cf 100644 (file)
@@ -2144,8 +2144,10 @@ static int shmem_encode_fh(struct dentry *dentry, __u32 *fh, int *len,
 {
        struct inode *inode = dentry->d_inode;
 
-       if (*len < 3)
+       if (*len < 3) {
+               *len = 3;
                return 255;
+       }
 
        if (inode_unhashed(inode)) {
                /* Unfortunately insert_inode_hash is not idempotent,