Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

exportfs: Return the minimum required handle size

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>

authored by

Aneesh Kumar K.V and committed by
Al Viro
5fe0c237 c8b91acc

+59 -18
+6 -2
fs/btrfs/export.c
··· 21 21 int len = *max_len; 22 22 int type; 23 23 24 - if ((len < BTRFS_FID_SIZE_NON_CONNECTABLE) || 25 - (connectable && len < BTRFS_FID_SIZE_CONNECTABLE)) 24 + if (connectable && (len < BTRFS_FID_SIZE_CONNECTABLE)) { 25 + *max_len = BTRFS_FID_SIZE_CONNECTABLE; 26 26 return 255; 27 + } else if (len < BTRFS_FID_SIZE_NON_CONNECTABLE) { 28 + *max_len = BTRFS_FID_SIZE_NON_CONNECTABLE; 29 + return 255; 30 + } 27 31 28 32 len = BTRFS_FID_SIZE_NON_CONNECTABLE; 29 33 type = FILEID_BTRFS_WITHOUT_PARENT;
+7 -2
fs/exportfs/expfs.c
··· 320 320 struct inode * inode = dentry->d_inode; 321 321 int len = *max_len; 322 322 int type = FILEID_INO32_GEN; 323 - 324 - if (len < 2 || (connectable && len < 4)) 323 + 324 + if (connectable && (len < 4)) { 325 + *max_len = 4; 325 326 return 255; 327 + } else if (len < 2) { 328 + *max_len = 2; 329 + return 255; 330 + } 326 331 327 332 len = 2; 328 333 fid->i32.ino = inode->i_ino;
+3 -1
fs/fat/inode.c
··· 757 757 struct inode *inode = de->d_inode; 758 758 u32 ipos_h, ipos_m, ipos_l; 759 759 760 - if (len < 5) 760 + if (len < 5) { 761 + *lenp = 5; 761 762 return 255; /* no room */ 763 + } 762 764 763 765 ipos_h = MSDOS_I(inode)->i_pos >> 8; 764 766 ipos_m = (MSDOS_I(inode)->i_pos & 0xf0) << 24;
+3 -1
fs/fuse/inode.c
··· 637 637 u64 nodeid; 638 638 u32 generation; 639 639 640 - if (*max_len < len) 640 + if (*max_len < len) { 641 + *max_len = len; 641 642 return 255; 643 + } 642 644 643 645 nodeid = get_fuse_inode(inode)->nodeid; 644 646 generation = inode->i_generation;
+6 -2
fs/gfs2/export.c
··· 36 36 struct super_block *sb = inode->i_sb; 37 37 struct gfs2_inode *ip = GFS2_I(inode); 38 38 39 - if (*len < GFS2_SMALL_FH_SIZE || 40 - (connectable && *len < GFS2_LARGE_FH_SIZE)) 39 + if (connectable && (*len < GFS2_LARGE_FH_SIZE)) { 40 + *len = GFS2_LARGE_FH_SIZE; 41 41 return 255; 42 + } else if (*len < GFS2_SMALL_FH_SIZE) { 43 + *len = GFS2_SMALL_FH_SIZE; 44 + return 255; 45 + } 42 46 43 47 fh[0] = cpu_to_be32(ip->i_no_formal_ino >> 32); 44 48 fh[1] = cpu_to_be32(ip->i_no_formal_ino & 0xFFFFFFFF);
+6 -2
fs/isofs/export.c
··· 124 124 * offset of the inode and the upper 16 bits of fh32[1] to 125 125 * hold the offset of the parent. 126 126 */ 127 - 128 - if (len < 3 || (connectable && len < 5)) 127 + if (connectable && (len < 5)) { 128 + *max_len = 5; 129 129 return 255; 130 + } else if (len < 3) { 131 + *max_len = 3; 132 + return 255; 133 + } 130 134 131 135 len = 3; 132 136 fh32[0] = ei->i_iget5_block;
+6 -2
fs/ocfs2/export.c
··· 197 197 dentry->d_name.len, dentry->d_name.name, 198 198 fh, len, connectable); 199 199 200 - if (len < 3 || (connectable && len < 6)) { 201 - mlog(ML_ERROR, "fh buffer is too small for encoding\n"); 200 + if (connectable && (len < 6)) { 201 + *max_len = 6; 202 + type = 255; 203 + goto bail; 204 + } else if (len < 3) { 205 + *max_len = 3; 202 206 type = 255; 203 207 goto bail; 204 208 }
+6 -1
fs/reiserfs/inode.c
··· 1593 1593 struct inode *inode = dentry->d_inode; 1594 1594 int maxlen = *lenp; 1595 1595 1596 - if (maxlen < 3) 1596 + if (need_parent && (maxlen < 5)) { 1597 + *lenp = 5; 1597 1598 return 255; 1599 + } else if (maxlen < 3) { 1600 + *lenp = 3; 1601 + return 255; 1602 + } 1598 1603 1599 1604 data[0] = inode->i_ino; 1600 1605 data[1] = le32_to_cpu(INODE_PKEY(inode)->k_dir_id);
+6 -1
fs/udf/namei.c
··· 1286 1286 struct fid *fid = (struct fid *)fh; 1287 1287 int type = FILEID_UDF_WITHOUT_PARENT; 1288 1288 1289 - if (len < 3 || (connectable && len < 5)) 1289 + if (connectable && (len < 5)) { 1290 + *lenp = 5; 1290 1291 return 255; 1292 + } else if (len < 3) { 1293 + *lenp = 3; 1294 + return 255; 1295 + } 1291 1296 1292 1297 *lenp = 3; 1293 1298 fid->udf.block = location.logicalBlockNum;
+3 -1
fs/xfs/linux-2.6/xfs_export.c
··· 89 89 * seven combinations work. The real answer is "don't use v2". 90 90 */ 91 91 len = xfs_fileid_length(fileid_type); 92 - if (*max_len < len) 92 + if (*max_len < len) { 93 + *max_len = len; 93 94 return 255; 95 + } 94 96 *max_len = len; 95 97 96 98 switch (fileid_type) {
+4 -2
include/linux/exportfs.h
··· 121 121 * set, the encode_fh() should store sufficient information so that a good 122 122 * attempt can be made to find not only the file but also it's place in the 123 123 * filesystem. This typically means storing a reference to de->d_parent in 124 - * the filehandle fragment. encode_fh() should return the number of bytes 125 - * stored or a negative error code such as %-ENOSPC 124 + * the filehandle fragment. encode_fh() should return the fileid_type on 125 + * success and on error returns 255 (if the space needed to encode fh is 126 + * greater than @max_len*4 bytes). On error @max_len contains the minimum 127 + * size(in 4 byte unit) needed to encode the file handle. 126 128 * 127 129 * fh_to_dentry: 128 130 * @fh_to_dentry is given a &struct super_block (@sb) and a file handle
+3 -1
mm/shmem.c
··· 2144 2144 { 2145 2145 struct inode *inode = dentry->d_inode; 2146 2146 2147 - if (*len < 3) 2147 + if (*len < 3) { 2148 + *len = 3; 2148 2149 return 255; 2150 + } 2149 2151 2150 2152 if (inode_unhashed(inode)) { 2151 2153 /* Unfortunately insert_inode_hash is not idempotent,