[XFS] Hook up compat XFS_IOC_ATTRMULTI_BY_HANDLE ioctl handler
Add a compat handler for XFS_IOC_ATTRMULTI_BY_HANDLE Signed-off-by: Eric Sandeen <sandeen@sandeen.net> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Lachlan McIlroy <lachlan@sgi.com>
This commit is contained in:
committed by
Lachlan McIlroy
parent
ebeecd2b04
commit
28750975ac
@@ -490,7 +490,7 @@ xfs_attrlist_by_handle(
|
|||||||
return -error;
|
return -error;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC int
|
int
|
||||||
xfs_attrmulti_attr_get(
|
xfs_attrmulti_attr_get(
|
||||||
struct inode *inode,
|
struct inode *inode,
|
||||||
char *name,
|
char *name,
|
||||||
@@ -519,7 +519,7 @@ xfs_attrmulti_attr_get(
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC int
|
int
|
||||||
xfs_attrmulti_attr_set(
|
xfs_attrmulti_attr_set(
|
||||||
struct inode *inode,
|
struct inode *inode,
|
||||||
char *name,
|
char *name,
|
||||||
@@ -549,7 +549,7 @@ xfs_attrmulti_attr_set(
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC int
|
int
|
||||||
xfs_attrmulti_attr_remove(
|
xfs_attrmulti_attr_remove(
|
||||||
struct inode *inode,
|
struct inode *inode,
|
||||||
char *name,
|
char *name,
|
||||||
|
@@ -44,4 +44,27 @@ xfs_readlink_by_handle(
|
|||||||
xfs_mount_t *mp,
|
xfs_mount_t *mp,
|
||||||
xfs_fsop_handlereq_t *hreq,
|
xfs_fsop_handlereq_t *hreq,
|
||||||
struct inode *parinode);
|
struct inode *parinode);
|
||||||
|
|
||||||
|
extern int
|
||||||
|
xfs_attrmulti_attr_get(
|
||||||
|
struct inode *inode,
|
||||||
|
char *name,
|
||||||
|
char __user *ubuf,
|
||||||
|
__uint32_t *len,
|
||||||
|
__uint32_t flags);
|
||||||
|
|
||||||
|
extern int
|
||||||
|
xfs_attrmulti_attr_set(
|
||||||
|
struct inode *inode,
|
||||||
|
char *name,
|
||||||
|
const char __user *ubuf,
|
||||||
|
__uint32_t len,
|
||||||
|
__uint32_t flags);
|
||||||
|
|
||||||
|
extern int
|
||||||
|
xfs_attrmulti_attr_remove(
|
||||||
|
struct inode *inode,
|
||||||
|
char *name,
|
||||||
|
__uint32_t flags);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -476,6 +476,93 @@ xfs_compat_attrlist_by_handle(
|
|||||||
return -error;
|
return -error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
STATIC int
|
||||||
|
xfs_compat_attrmulti_by_handle(
|
||||||
|
xfs_mount_t *mp,
|
||||||
|
void __user *arg,
|
||||||
|
struct inode *parinode)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
compat_xfs_attr_multiop_t *ops;
|
||||||
|
compat_xfs_fsop_attrmulti_handlereq_t am_hreq;
|
||||||
|
struct inode *inode;
|
||||||
|
unsigned int i, size;
|
||||||
|
char *attr_name;
|
||||||
|
|
||||||
|
if (!capable(CAP_SYS_ADMIN))
|
||||||
|
return -XFS_ERROR(EPERM);
|
||||||
|
if (copy_from_user(&am_hreq, arg,
|
||||||
|
sizeof(compat_xfs_fsop_attrmulti_handlereq_t)))
|
||||||
|
return -XFS_ERROR(EFAULT);
|
||||||
|
|
||||||
|
error = xfs_vget_fsop_handlereq_compat(mp, parinode, &am_hreq.hreq,
|
||||||
|
&inode);
|
||||||
|
if (error)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
error = E2BIG;
|
||||||
|
size = am_hreq.opcount * sizeof(compat_xfs_attr_multiop_t);
|
||||||
|
if (!size || size > 16 * PAGE_SIZE)
|
||||||
|
goto out_vn_rele;
|
||||||
|
|
||||||
|
error = ENOMEM;
|
||||||
|
ops = kmalloc(size, GFP_KERNEL);
|
||||||
|
if (!ops)
|
||||||
|
goto out_vn_rele;
|
||||||
|
|
||||||
|
error = EFAULT;
|
||||||
|
if (copy_from_user(ops, compat_ptr(am_hreq.ops), size))
|
||||||
|
goto out_kfree_ops;
|
||||||
|
|
||||||
|
attr_name = kmalloc(MAXNAMELEN, GFP_KERNEL);
|
||||||
|
if (!attr_name)
|
||||||
|
goto out_kfree_ops;
|
||||||
|
|
||||||
|
|
||||||
|
error = 0;
|
||||||
|
for (i = 0; i < am_hreq.opcount; i++) {
|
||||||
|
ops[i].am_error = strncpy_from_user(attr_name,
|
||||||
|
compat_ptr(ops[i].am_attrname),
|
||||||
|
MAXNAMELEN);
|
||||||
|
if (ops[i].am_error == 0 || ops[i].am_error == MAXNAMELEN)
|
||||||
|
error = -ERANGE;
|
||||||
|
if (ops[i].am_error < 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
switch (ops[i].am_opcode) {
|
||||||
|
case ATTR_OP_GET:
|
||||||
|
ops[i].am_error = xfs_attrmulti_attr_get(inode,
|
||||||
|
attr_name,
|
||||||
|
compat_ptr(ops[i].am_attrvalue),
|
||||||
|
&ops[i].am_length, ops[i].am_flags);
|
||||||
|
break;
|
||||||
|
case ATTR_OP_SET:
|
||||||
|
ops[i].am_error = xfs_attrmulti_attr_set(inode,
|
||||||
|
attr_name,
|
||||||
|
compat_ptr(ops[i].am_attrvalue),
|
||||||
|
ops[i].am_length, ops[i].am_flags);
|
||||||
|
break;
|
||||||
|
case ATTR_OP_REMOVE:
|
||||||
|
ops[i].am_error = xfs_attrmulti_attr_remove(inode,
|
||||||
|
attr_name, ops[i].am_flags);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ops[i].am_error = EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (copy_to_user(compat_ptr(am_hreq.ops), ops, size))
|
||||||
|
error = XFS_ERROR(EFAULT);
|
||||||
|
|
||||||
|
kfree(attr_name);
|
||||||
|
out_kfree_ops:
|
||||||
|
kfree(ops);
|
||||||
|
out_vn_rele:
|
||||||
|
iput(inode);
|
||||||
|
out:
|
||||||
|
return -error;
|
||||||
|
}
|
||||||
|
|
||||||
STATIC long
|
STATIC long
|
||||||
xfs_compat_ioctl(
|
xfs_compat_ioctl(
|
||||||
xfs_inode_t *ip,
|
xfs_inode_t *ip,
|
||||||
@@ -499,10 +586,7 @@ xfs_compat_ioctl(
|
|||||||
case XFS_IOC_GETBMAP:
|
case XFS_IOC_GETBMAP:
|
||||||
case XFS_IOC_GETBMAPA:
|
case XFS_IOC_GETBMAPA:
|
||||||
case XFS_IOC_GETBMAPX:
|
case XFS_IOC_GETBMAPX:
|
||||||
/* not handled
|
/* case XFS_IOC_FSSETDM_BY_HANDLE: not handled */
|
||||||
case XFS_IOC_FSSETDM_BY_HANDLE:
|
|
||||||
case XFS_IOC_ATTRMULTI_BY_HANDLE:
|
|
||||||
*/
|
|
||||||
case XFS_IOC_FSCOUNTS:
|
case XFS_IOC_FSCOUNTS:
|
||||||
case XFS_IOC_SET_RESBLKS:
|
case XFS_IOC_SET_RESBLKS:
|
||||||
case XFS_IOC_GET_RESBLKS:
|
case XFS_IOC_GET_RESBLKS:
|
||||||
@@ -610,6 +694,8 @@ xfs_compat_ioctl(
|
|||||||
}
|
}
|
||||||
case XFS_IOC_ATTRLIST_BY_HANDLE_32:
|
case XFS_IOC_ATTRLIST_BY_HANDLE_32:
|
||||||
return xfs_compat_attrlist_by_handle(mp, arg, inode);
|
return xfs_compat_attrlist_by_handle(mp, arg, inode);
|
||||||
|
case XFS_IOC_ATTRMULTI_BY_HANDLE_32:
|
||||||
|
return xfs_compat_attrmulti_by_handle(mp, arg, inode);
|
||||||
default:
|
default:
|
||||||
return -XFS_ERROR(ENOIOCTLCMD);
|
return -XFS_ERROR(ENOIOCTLCMD);
|
||||||
}
|
}
|
||||||
|
@@ -135,6 +135,26 @@ typedef struct compat_xfs_fsop_attrlist_handlereq {
|
|||||||
#define XFS_IOC_ATTRLIST_BY_HANDLE_32 \
|
#define XFS_IOC_ATTRLIST_BY_HANDLE_32 \
|
||||||
_IOW('X', 122, struct compat_xfs_fsop_attrlist_handlereq)
|
_IOW('X', 122, struct compat_xfs_fsop_attrlist_handlereq)
|
||||||
|
|
||||||
|
/* am_opcodes defined in xfs_fs.h */
|
||||||
|
typedef struct compat_xfs_attr_multiop {
|
||||||
|
__u32 am_opcode;
|
||||||
|
__s32 am_error;
|
||||||
|
compat_uptr_t am_attrname;
|
||||||
|
compat_uptr_t am_attrvalue;
|
||||||
|
__u32 am_length;
|
||||||
|
__u32 am_flags;
|
||||||
|
} compat_xfs_attr_multiop_t;
|
||||||
|
|
||||||
|
typedef struct compat_xfs_fsop_attrmulti_handlereq {
|
||||||
|
struct compat_xfs_fsop_handlereq hreq; /* handle interface structure */
|
||||||
|
__u32 opcount;/* count of following multiop */
|
||||||
|
/* ptr to compat_xfs_attr_multiop */
|
||||||
|
compat_uptr_t ops; /* attr_multi data */
|
||||||
|
} compat_xfs_fsop_attrmulti_handlereq_t;
|
||||||
|
|
||||||
|
#define XFS_IOC_ATTRMULTI_BY_HANDLE_32 \
|
||||||
|
_IOW('X', 123, struct compat_xfs_fsop_attrmulti_handlereq)
|
||||||
|
|
||||||
#ifdef BROKEN_X86_ALIGNMENT
|
#ifdef BROKEN_X86_ALIGNMENT
|
||||||
/* on ia32 l_start is on a 32-bit boundary */
|
/* on ia32 l_start is on a 32-bit boundary */
|
||||||
typedef struct compat_xfs_flock64 {
|
typedef struct compat_xfs_flock64 {
|
||||||
|
Reference in New Issue
Block a user