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 <quentin.bouget@cea.fr>
Change-Id: Ic7e83c7fdf924363ed59a0681267d960e660db6d
Reviewed-on: https://review.whamcloud.com/36292
Reviewed-by: James Simmons <jsimmons@infradead.org>
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
/* # include <sys/quota.h> - this causes complaints about caddr_t */
# include <sys/stat.h>
# include <linux/lustre/lustre_fiemap.h>
/* # include <sys/quota.h> - this causes complaints about caddr_t */
# include <sys/stat.h>
# include <linux/lustre/lustre_fiemap.h>
+# define FILEID_LUSTRE 0x97 /* for name_to_handle_at() (and llapi_fd2fid()) */
#endif /* __KERNEL__ */
/* Handle older distros */
#endif /* __KERNEL__ */
/* Handle older distros */
return fid->f_seq == 0 && fid->f_oid == 0;
}
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. */
/* 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. */
-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)
{
static struct dentry *
ll_iget_for_nfs(struct super_block *sb, struct lu_fid *fid, struct lu_fid *parent)
{
struct inode *parent)
{
#endif
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;
RETURN(FILEID_INVALID);
}
RETURN(FILEID_INVALID);
}
- nfs_fid->lnf_child = *ll_inode2fid(inode);
+ lfh->lfh_child = *ll_inode2fid(inode);
- nfs_fid->lnf_parent = *ll_inode2fid(parent);
+ lfh->lfh_parent = *ll_inode2fid(parent);
- fid_zero(&nfs_fid->lnf_parent);
+ fid_zero(&lfh->lfh_parent);
*plen = fileid_len;
RETURN(FILEID_LUSTRE);
*plen = fileid_len;
RETURN(FILEID_LUSTRE);
static struct dentry *ll_fh_to_dentry(struct super_block *sb, struct fid *fid,
int fh_len, int fh_type)
{
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));
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)
{
}
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));
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)
}
int ll_dir_get_parent_fid(struct inode *dir, struct lu_fid *parent_fid)
-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)
{
int llapi_get_mdt_index_by_fid(int fd, const struct lu_fid *fid,
int *mdt_index)
{
+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 llapi_fd2fid(int fd, struct lu_fid *fid)
{
+ 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));
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;
+ 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;
}
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;
rc = fid_from_lma(path, -1, fid);
return rc;