From: Quentin Bouget Date: Thu, 12 Dec 2019 08:47:23 +0000 (+0100) Subject: LU-12806 llapi: use name_to_handle_at in llapi_fd2fid X-Git-Tag: 2.13.52~96 X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=commitdiff_plain;h=7ff384eee1945440d5cc9a0658750fa3276fba6a LU-12806 llapi: use name_to_handle_at in llapi_fd2fid Reimplement llapi_fd2fid so as to use name_to_handle_at() rather than using an ioctl() call. This patch also updates llapi_fid2path as using file descriptor obtained from a call to open() + O_PATH is valid with name_to_handle_at(), is more efficient and also works for symlinks out of the box. Signed-off-by: Quentin Bouget Change-Id: Ic7e83c7fdf924363ed59a0681267d960e660db6d Reviewed-on: https://review.whamcloud.com/36292 Reviewed-by: James Simmons Tested-by: jenkins Tested-by: Maloo Reviewed-by: Andreas Dilger Reviewed-by: Oleg Drokin --- diff --git a/lustre/include/uapi/linux/lustre/lustre_user.h b/lustre/include/uapi/linux/lustre/lustre_user.h index fdcc379..f90725a 100644 --- a/lustre/include/uapi/linux/lustre/lustre_user.h +++ b/lustre/include/uapi/linux/lustre/lustre_user.h @@ -61,6 +61,7 @@ /* # include - this causes complaints about caddr_t */ # include # include +# define FILEID_LUSTRE 0x97 /* for name_to_handle_at() (and llapi_fd2fid()) */ #endif /* __KERNEL__ */ /* Handle older distros */ @@ -331,6 +332,12 @@ static inline bool fid_is_zero(const struct lu_fid *fid) return fid->f_seq == 0 && fid->f_oid == 0; } +/* The data name_to_handle_at() places in a struct file_handle (at f_handle) */ +struct lustre_file_handle { + struct lu_fid lfh_child; + struct lu_fid lfh_parent; +}; + /* Currently, the filter_fid::ff_parent::f_ver is not the real parent * MDT-object's FID::f_ver, instead it is the OST-object index in its * parent MDT-object's layout EA. */ diff --git a/lustre/llite/llite_nfs.c b/lustre/llite/llite_nfs.c index d291cfa..6f0d511 100644 --- a/lustre/llite/llite_nfs.c +++ b/lustre/llite/llite_nfs.c @@ -112,11 +112,6 @@ struct inode *search_inode_for_lustre(struct super_block *sb, RETURN(inode); } -struct lustre_nfs_fid { - struct lu_fid lnf_child; - struct lu_fid lnf_parent; -}; - static struct dentry * ll_iget_for_nfs(struct super_block *sb, struct lu_fid *fid, struct lu_fid *parent) { @@ -193,8 +188,8 @@ static int ll_encode_fh(struct inode *inode, u32 *fh, int *plen, struct inode *parent) { #endif - int fileid_len = sizeof(struct lustre_nfs_fid) / 4; - struct lustre_nfs_fid *nfs_fid = (void *)fh; + int fileid_len = sizeof(struct lustre_file_handle) / 4; + struct lustre_file_handle *lfh = (void *)fh; ENTRY; @@ -207,11 +202,11 @@ static int ll_encode_fh(struct inode *inode, u32 *fh, int *plen, RETURN(FILEID_INVALID); } - nfs_fid->lnf_child = *ll_inode2fid(inode); + lfh->lfh_child = *ll_inode2fid(inode); if (parent) - nfs_fid->lnf_parent = *ll_inode2fid(parent); + lfh->lfh_parent = *ll_inode2fid(parent); else - fid_zero(&nfs_fid->lnf_parent); + fid_zero(&lfh->lfh_parent); *plen = fileid_len; RETURN(FILEID_LUSTRE); @@ -293,23 +288,23 @@ out: static struct dentry *ll_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len, int fh_type) { - struct lustre_nfs_fid *nfs_fid = (struct lustre_nfs_fid *)fid; + struct lustre_file_handle *lfh = (struct lustre_file_handle *)fid; if (fh_type != FILEID_LUSTRE) RETURN(ERR_PTR(-EPROTO)); - RETURN(ll_iget_for_nfs(sb, &nfs_fid->lnf_child, &nfs_fid->lnf_parent)); + RETURN(ll_iget_for_nfs(sb, &lfh->lfh_child, &lfh->lfh_parent)); } static struct dentry *ll_fh_to_parent(struct super_block *sb, struct fid *fid, int fh_len, int fh_type) { - struct lustre_nfs_fid *nfs_fid = (struct lustre_nfs_fid *)fid; + struct lustre_file_handle *lfh = (struct lustre_file_handle *)fid; if (fh_type != FILEID_LUSTRE) RETURN(ERR_PTR(-EPROTO)); - RETURN(ll_iget_for_nfs(sb, &nfs_fid->lnf_parent, NULL)); + RETURN(ll_iget_for_nfs(sb, &lfh->lfh_parent, NULL)); } int ll_dir_get_parent_fid(struct inode *dir, struct lu_fid *parent_fid) diff --git a/lustre/utils/liblustreapi_fid.c b/lustre/utils/liblustreapi_fid.c index 0034714..3ef7ff9 100644 --- a/lustre/utils/liblustreapi_fid.c +++ b/lustre/utils/liblustreapi_fid.c @@ -293,27 +293,6 @@ out: return rc; } -static int fid_from_lma(const char *path, int fd, struct lu_fid *fid) -{ - char buf[512]; - struct lustre_mdt_attrs *lma; - int rc = -1; - - if (fd >= 0) - rc = fgetxattr(fd, XATTR_NAME_LMA, buf, sizeof(buf)); - else if (path) - rc = lgetxattr(path, XATTR_NAME_LMA, buf, sizeof(buf)); - else - errno = EINVAL; - if (rc < 0) - return -errno; - - lma = (struct lustre_mdt_attrs *)buf; - fid_le_to_cpu(fid, &lma->lma_self_fid); - - return 0; -} - int llapi_get_mdt_index_by_fid(int fd, const struct lu_fid *fid, int *mdt_index) { @@ -329,38 +308,77 @@ int llapi_get_mdt_index_by_fid(int fd, const struct lu_fid *fid, return rc; } +static int fid_from_lma(const char *path, int fd, struct lu_fid *fid) +{ + struct lustre_mdt_attrs *lma; + char buf[512]; + int rc = -1; + + if (path == NULL) + rc = fgetxattr(fd, XATTR_NAME_LMA, buf, sizeof(buf)); + else + rc = lgetxattr(path, XATTR_NAME_LMA, buf, sizeof(buf)); + if (rc < 0) + return -errno; + + lma = (struct lustre_mdt_attrs *)buf; + memcpy(fid, &lma->lma_self_fid, sizeof(lma->lma_self_fid)); + return 0; +} + int llapi_fd2fid(int fd, struct lu_fid *fid) { - int rc; + const struct lustre_file_handle *data; + struct file_handle *handle; + char buffer[sizeof(*handle) + MAX_HANDLE_SZ]; + int mount_id; memset(fid, 0, sizeof(*fid)); - rc = ioctl(fd, LL_IOC_PATH2FID, fid) < 0 ? -errno : 0; - /* Allow extracting the FID from an ldiskfs-mounted filesystem */ - if (rc < 0) { - if (errno == EINVAL || errno == ENOTTY) - rc = fid_from_lma(NULL, fd, fid); - else - rc = -errno; + /* A lustre file handle should always fit in a 128 bytes long buffer + * (which is the value of MAX_HANDLE_SZ at the time this is written) + */ + handle = (struct file_handle *)buffer; + handle->handle_bytes = MAX_HANDLE_SZ; + + if (name_to_handle_at(fd, "", handle, &mount_id, AT_EMPTY_PATH)) { + if (errno == EOVERFLOW) + /* A Lustre file_handle would have fit */ + return -ENOTTY; + return -errno; } - return rc; + if (handle->handle_type != FILEID_LUSTRE) + /* Might be a locally mounted Lustre target */ + return fid_from_lma(NULL, fd, fid); + if (handle->handle_bytes < sizeof(*fid)) + /* Unexpected error try and recover */ + return fid_from_lma(NULL, fd, fid); + + /* Parse the FID out of the handle */ + data = (const struct lustre_file_handle *)handle->f_handle; + memcpy(fid, &data->lfh_child, sizeof(data->lfh_child)); + + return 0; } int llapi_path2fid(const char *path, struct lu_fid *fid) { int fd, rc; - fd = open(path, O_RDONLY | O_NONBLOCK | O_NOFOLLOW); - if (fd >= 0) { - rc = llapi_fd2fid(fd, fid); - close(fd); - } else { - memset(fid, 0, sizeof(*fid)); - rc = -errno; - } + fd = open(path, O_RDONLY | O_PATH | O_CLOEXEC | O_NOFOLLOW); + if (fd < 0) + return -errno; + + rc = llapi_fd2fid(fd, fid); + close(fd); - if (rc == -ELOOP || rc == -ENXIO || rc == -EINVAL || rc == -ENOTTY) + if (rc == -EBADF) + /* Might be a locally mounted Lustre target + * + * Cannot use `fd' as fgetxattr() does not work on file + * descriptor opened with O_PATH + */ rc = fid_from_lma(path, -1, fid); return rc;