mirror of
https://github.com/torvalds/linux.git
synced 2024-11-21 19:41:42 +00:00
xfs: split out handle management helpers a bit
Split out the functions that generate file/fs handles and map them back into dentries in preparation for the GETPARENTS ioctl next. Signed-off-by: Darrick J. Wong <djwong@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
parent
af69d852df
commit
b8c9d4253d
@ -633,7 +633,9 @@ typedef struct xfs_fsop_attrmulti_handlereq {
|
||||
/*
|
||||
* per machine unique filesystem identifier types.
|
||||
*/
|
||||
typedef struct { __u32 val[2]; } xfs_fsid_t; /* file system id type */
|
||||
typedef struct xfs_fsid {
|
||||
__u32 val[2]; /* file system id type */
|
||||
} xfs_fsid_t;
|
||||
|
||||
typedef struct xfs_fid {
|
||||
__u16 fid_len; /* length of remainder */
|
||||
|
@ -30,6 +30,42 @@
|
||||
|
||||
#include <linux/namei.h>
|
||||
|
||||
static inline size_t
|
||||
xfs_filehandle_fid_len(void)
|
||||
{
|
||||
struct xfs_handle *handle = NULL;
|
||||
|
||||
return sizeof(struct xfs_fid) - sizeof(handle->ha_fid.fid_len);
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
xfs_filehandle_init(
|
||||
struct xfs_mount *mp,
|
||||
xfs_ino_t ino,
|
||||
uint32_t gen,
|
||||
struct xfs_handle *handle)
|
||||
{
|
||||
memcpy(&handle->ha_fsid, mp->m_fixedfsid, sizeof(struct xfs_fsid));
|
||||
|
||||
handle->ha_fid.fid_len = xfs_filehandle_fid_len();
|
||||
handle->ha_fid.fid_pad = 0;
|
||||
handle->ha_fid.fid_gen = gen;
|
||||
handle->ha_fid.fid_ino = ino;
|
||||
|
||||
return sizeof(struct xfs_handle);
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
xfs_fshandle_init(
|
||||
struct xfs_mount *mp,
|
||||
struct xfs_handle *handle)
|
||||
{
|
||||
memcpy(&handle->ha_fsid, mp->m_fixedfsid, sizeof(struct xfs_fsid));
|
||||
memset(&handle->ha_fid, 0, sizeof(handle->ha_fid));
|
||||
|
||||
return sizeof(struct xfs_fsid);
|
||||
}
|
||||
|
||||
/*
|
||||
* xfs_find_handle maps from userspace xfs_fsop_handlereq structure to
|
||||
* a file or fs handle.
|
||||
@ -84,20 +120,11 @@ xfs_find_handle(
|
||||
|
||||
memcpy(&handle.ha_fsid, ip->i_mount->m_fixedfsid, sizeof(xfs_fsid_t));
|
||||
|
||||
if (cmd == XFS_IOC_PATH_TO_FSHANDLE) {
|
||||
/*
|
||||
* This handle only contains an fsid, zero the rest.
|
||||
*/
|
||||
memset(&handle.ha_fid, 0, sizeof(handle.ha_fid));
|
||||
hsize = sizeof(xfs_fsid_t);
|
||||
} else {
|
||||
handle.ha_fid.fid_len = sizeof(xfs_fid_t) -
|
||||
sizeof(handle.ha_fid.fid_len);
|
||||
handle.ha_fid.fid_pad = 0;
|
||||
handle.ha_fid.fid_gen = inode->i_generation;
|
||||
handle.ha_fid.fid_ino = ip->i_ino;
|
||||
hsize = sizeof(xfs_handle_t);
|
||||
}
|
||||
if (cmd == XFS_IOC_PATH_TO_FSHANDLE)
|
||||
hsize = xfs_fshandle_init(ip->i_mount, &handle);
|
||||
else
|
||||
hsize = xfs_filehandle_init(ip->i_mount, ip->i_ino,
|
||||
inode->i_generation, &handle);
|
||||
|
||||
error = -EFAULT;
|
||||
if (copy_to_user(hreq->ohandle, &handle, hsize) ||
|
||||
@ -126,6 +153,31 @@ xfs_handle_acceptable(
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Convert handle already copied to kernel space into a dentry. */
|
||||
static struct dentry *
|
||||
xfs_khandle_to_dentry(
|
||||
struct file *file,
|
||||
struct xfs_handle *handle)
|
||||
{
|
||||
struct xfs_fid64 fid = {
|
||||
.ino = handle->ha_fid.fid_ino,
|
||||
.gen = handle->ha_fid.fid_gen,
|
||||
};
|
||||
|
||||
/*
|
||||
* Only allow handle opens under a directory.
|
||||
*/
|
||||
if (!S_ISDIR(file_inode(file)->i_mode))
|
||||
return ERR_PTR(-ENOTDIR);
|
||||
|
||||
if (handle->ha_fid.fid_len != xfs_filehandle_fid_len())
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
return exportfs_decode_fh(file->f_path.mnt, (struct fid *)&fid, 3,
|
||||
FILEID_INO32_GEN | XFS_FILEID_TYPE_64FLAG,
|
||||
xfs_handle_acceptable, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert userspace handle data into a dentry.
|
||||
*/
|
||||
@ -136,29 +188,13 @@ xfs_handle_to_dentry(
|
||||
u32 hlen)
|
||||
{
|
||||
xfs_handle_t handle;
|
||||
struct xfs_fid64 fid;
|
||||
|
||||
/*
|
||||
* Only allow handle opens under a directory.
|
||||
*/
|
||||
if (!S_ISDIR(file_inode(parfilp)->i_mode))
|
||||
return ERR_PTR(-ENOTDIR);
|
||||
|
||||
if (hlen != sizeof(xfs_handle_t))
|
||||
return ERR_PTR(-EINVAL);
|
||||
if (copy_from_user(&handle, uhandle, hlen))
|
||||
return ERR_PTR(-EFAULT);
|
||||
if (handle.ha_fid.fid_len !=
|
||||
sizeof(handle.ha_fid) - sizeof(handle.ha_fid.fid_len))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
memset(&fid, 0, sizeof(struct fid));
|
||||
fid.ino = handle.ha_fid.fid_ino;
|
||||
fid.gen = handle.ha_fid.fid_gen;
|
||||
|
||||
return exportfs_decode_fh(parfilp->f_path.mnt, (struct fid *)&fid, 3,
|
||||
FILEID_INO32_GEN | XFS_FILEID_TYPE_64FLAG,
|
||||
xfs_handle_acceptable, NULL);
|
||||
return xfs_khandle_to_dentry(parfilp, &handle);
|
||||
}
|
||||
|
||||
STATIC struct dentry *
|
||||
|
Loading…
Reference in New Issue
Block a user