On Thu, 18 Mar 2010 16:26:42 -0600, Andreas Dilger <adilger@xxxxxxx> wrote: > On 2010-03-18, at 11:09, Aneesh Kumar K.V wrote: > > Example program: > > int main(int argc, char *argv[]) > > { > > ret = syscall(338, argv[1], &fh); > > if (ret) { > > perror("Error:"); > > exit(1); > > } > > dirfd = open("/", O_RDONLY|O_DIRECTORY); > > fd = syscall(339, dirfd, &fh, O_RDONLY); > > > For your example program, it would be useful to include the > system calls so it is easier to see what is going on, like: > > #ifndef HAVE_NAME_TO_HANDLE > static inline int name_to_handle(const char *name, struct file_handle > *fh) > { > return syscall(338, name, fh); > } > > static inline int open_by_handle(int dirfd, struct file_handle *fh, > int flags) > { > return syscall(339, dirfd, fh, flags); > } > #endif > > int main(...) > { > ret = name_to_handle(argv[1], &fh); > : > > dirfd = open("/", O_RDONLY|O_DIRECTORY); > fd = open_by_handle(dirfd, &fh, O_RDONLY); > : > : > } > Updated the sample prg as below. I also needed an additonal kernel patch. Adding the kernel patch also here. #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> #include <sys/types.h> #include <sys/stat.h> #include <string.h> struct file_handle { int handle_size; int handle_type; void *handle; }; static int name_to_handle(const char *name, struct file_handle *fh) { return syscall(338, name, fh); } static int open_by_handle(int dirfd, struct file_handle *fh, int flags) { return syscall(339, dirfd, fh, flags); } int main(int argc, char *argv[]) { int ret; int fd, dirfd; char buf[100]; struct file_handle fh; fh.handle_size = 0; again: if (fh.handle_size) fh.handle = malloc(fh.handle_size); fh.handle_type = 0; errno = 0; ret = name_to_handle(argv[1], &fh); if (ret) { perror("Error:"); printf("Found the handle size needed to be %d\n", fh.handle_size); printf("Trying again..\n"); goto again; exit(1); } dirfd = open("/", O_RDONLY|O_DIRECTORY); fd = open_by_handle(dirfd, &fh, O_RDONLY); if (fd <= 0 ) { perror("Error:"); exit(1); } memset(buf, 0 , 100); while (read(fd, buf, 100) > 0) { printf("%s", buf); memset(buf, 0 , 100); } return 0; } commit 1a1fe3f95295857e8406fcc3943ba6ad4cc2792c Author: Aneesh Kumar K.V <aneesh.kumar@xxxxxxxxxxxxxxxxxx> Date: Fri Mar 19 10:19:17 2010 +0530 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. Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@xxxxxxxxxxxxxxxxxx> diff --git a/fs/btrfs/export.c b/fs/btrfs/export.c index ba5c3fd..db22392 100644 --- a/fs/btrfs/export.c +++ b/fs/btrfs/export.c @@ -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; diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c index e9e1759..cfee0f0 100644 --- a/fs/exportfs/expfs.c +++ b/fs/exportfs/expfs.c @@ -319,9 +319,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; diff --git a/fs/fat/inode.c b/fs/fat/inode.c index fbeecdc..b4c3839 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -738,8 +738,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; diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 1a822ce..a0e90c3 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -638,8 +638,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; diff --git a/fs/gfs2/export.c b/fs/gfs2/export.c index d15876e..4a85b36 100644 --- a/fs/gfs2/export.c +++ b/fs/gfs2/export.c @@ -37,9 +37,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); diff --git a/fs/isofs/export.c b/fs/isofs/export.c index ed752cb..dd4687f 100644 --- a/fs/isofs/export.c +++ b/fs/isofs/export.c @@ -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; diff --git a/fs/ocfs2/export.c b/fs/ocfs2/export.c index 19ad145..250a347 100644 --- a/fs/ocfs2/export.c +++ b/fs/ocfs2/export.c @@ -201,8 +201,14 @@ 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)) { + if (connectable && (len < 6)) { mlog(ML_ERROR, "fh buffer is too small for encoding\n"); + *max_len = 6; + type = 255; + goto bail; + } else if (len < 3) { + mlog(ML_ERROR, "fh buffer is too small for encoding\n"); + *max_len = 3; type = 255; goto bail; } diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index d1da94b..fe1600c 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c @@ -1587,8 +1587,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); diff --git a/fs/udf/namei.c b/fs/udf/namei.c index db423ab..7f6fc85 100644 --- a/fs/udf/namei.c +++ b/fs/udf/namei.c @@ -1360,8 +1360,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; diff --git a/fs/xfs/linux-2.6/xfs_export.c b/fs/xfs/linux-2.6/xfs_export.c index 846b75a..82c0553 100644 --- a/fs/xfs/linux-2.6/xfs_export.c +++ b/fs/xfs/linux-2.6/xfs_export.c @@ -81,8 +81,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) { diff --git a/mm/shmem.c b/mm/shmem.c index eef4ebe..bbeda1c 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -2125,8 +2125,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 (hlist_unhashed(&inode->i_hash)) { /* Unfortunately insert_inode_hash is not idempotent, -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html