diff options
author | sandeen@sandeen.net <sandeen@sandeen.net> | 2008-11-25 22:20:15 -0500 |
---|---|---|
committer | Lachlan McIlroy <lachlan@redback.melbourne.sgi.com> | 2008-12-02 01:17:07 -0500 |
commit | 28750975ace79c547407a84d3969cbed516be8f8 (patch) | |
tree | 79707c1e3c304ec7a11ea920cda38760d0248d5c /fs | |
parent | ebeecd2b04645a4b79e1bc00d69cf4f98e03a684 (diff) |
[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>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_ioctl.c | 6 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_ioctl.h | 23 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_ioctl32.c | 94 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_ioctl32.h | 20 |
4 files changed, 136 insertions, 7 deletions
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c index 498d3e15843b..c8f1e632ba94 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl.c +++ b/fs/xfs/linux-2.6/xfs_ioctl.c | |||
@@ -490,7 +490,7 @@ xfs_attrlist_by_handle( | |||
490 | return -error; | 490 | return -error; |
491 | } | 491 | } |
492 | 492 | ||
493 | STATIC int | 493 | int |
494 | xfs_attrmulti_attr_get( | 494 | xfs_attrmulti_attr_get( |
495 | struct inode *inode, | 495 | struct inode *inode, |
496 | char *name, | 496 | char *name, |
@@ -519,7 +519,7 @@ xfs_attrmulti_attr_get( | |||
519 | return error; | 519 | return error; |
520 | } | 520 | } |
521 | 521 | ||
522 | STATIC int | 522 | int |
523 | xfs_attrmulti_attr_set( | 523 | xfs_attrmulti_attr_set( |
524 | struct inode *inode, | 524 | struct inode *inode, |
525 | char *name, | 525 | char *name, |
@@ -549,7 +549,7 @@ xfs_attrmulti_attr_set( | |||
549 | return error; | 549 | return error; |
550 | } | 550 | } |
551 | 551 | ||
552 | STATIC int | 552 | int |
553 | xfs_attrmulti_attr_remove( | 553 | xfs_attrmulti_attr_remove( |
554 | struct inode *inode, | 554 | struct inode *inode, |
555 | char *name, | 555 | char *name, |
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.h b/fs/xfs/linux-2.6/xfs_ioctl.h index 2df849f49a5e..f67dc69381e8 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl.h +++ b/fs/xfs/linux-2.6/xfs_ioctl.h | |||
@@ -44,4 +44,27 @@ xfs_readlink_by_handle( | |||
44 | xfs_mount_t *mp, | 44 | xfs_mount_t *mp, |
45 | xfs_fsop_handlereq_t *hreq, | 45 | xfs_fsop_handlereq_t *hreq, |
46 | struct inode *parinode); | 46 | struct inode *parinode); |
47 | |||
48 | extern int | ||
49 | xfs_attrmulti_attr_get( | ||
50 | struct inode *inode, | ||
51 | char *name, | ||
52 | char __user *ubuf, | ||
53 | __uint32_t *len, | ||
54 | __uint32_t flags); | ||
55 | |||
56 | extern int | ||
57 | xfs_attrmulti_attr_set( | ||
58 | struct inode *inode, | ||
59 | char *name, | ||
60 | const char __user *ubuf, | ||
61 | __uint32_t len, | ||
62 | __uint32_t flags); | ||
63 | |||
64 | extern int | ||
65 | xfs_attrmulti_attr_remove( | ||
66 | struct inode *inode, | ||
67 | char *name, | ||
68 | __uint32_t flags); | ||
69 | |||
47 | #endif | 70 | #endif |
diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.c b/fs/xfs/linux-2.6/xfs_ioctl32.c index e7eb0d7e0d56..17993352aa64 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl32.c +++ b/fs/xfs/linux-2.6/xfs_ioctl32.c | |||
@@ -476,6 +476,93 @@ xfs_compat_attrlist_by_handle( | |||
476 | return -error; | 476 | return -error; |
477 | } | 477 | } |
478 | 478 | ||
479 | STATIC int | ||
480 | xfs_compat_attrmulti_by_handle( | ||
481 | xfs_mount_t *mp, | ||
482 | void __user *arg, | ||
483 | struct inode *parinode) | ||
484 | { | ||
485 | int error; | ||
486 | compat_xfs_attr_multiop_t *ops; | ||
487 | compat_xfs_fsop_attrmulti_handlereq_t am_hreq; | ||
488 | struct inode *inode; | ||
489 | unsigned int i, size; | ||
490 | char *attr_name; | ||
491 | |||
492 | if (!capable(CAP_SYS_ADMIN)) | ||
493 | return -XFS_ERROR(EPERM); | ||
494 | if (copy_from_user(&am_hreq, arg, | ||
495 | sizeof(compat_xfs_fsop_attrmulti_handlereq_t))) | ||
496 | return -XFS_ERROR(EFAULT); | ||
497 | |||
498 | error = xfs_vget_fsop_handlereq_compat(mp, parinode, &am_hreq.hreq, | ||
499 | &inode); | ||
500 | if (error) | ||
501 | goto out; | ||
502 | |||
503 | error = E2BIG; | ||
504 | size = am_hreq.opcount * sizeof(compat_xfs_attr_multiop_t); | ||
505 | if (!size || size > 16 * PAGE_SIZE) | ||
506 | goto out_vn_rele; | ||
507 | |||
508 | error = ENOMEM; | ||
509 | ops = kmalloc(size, GFP_KERNEL); | ||
510 | if (!ops) | ||
511 | goto out_vn_rele; | ||
512 | |||
513 | error = EFAULT; | ||
514 | if (copy_from_user(ops, compat_ptr(am_hreq.ops), size)) | ||
515 | goto out_kfree_ops; | ||
516 | |||
517 | attr_name = kmalloc(MAXNAMELEN, GFP_KERNEL); | ||
518 | if (!attr_name) | ||
519 | goto out_kfree_ops; | ||
520 | |||
521 | |||
522 | error = 0; | ||
523 | for (i = 0; i < am_hreq.opcount; i++) { | ||
524 | ops[i].am_error = strncpy_from_user(attr_name, | ||
525 | compat_ptr(ops[i].am_attrname), | ||
526 | MAXNAMELEN); | ||
527 | if (ops[i].am_error == 0 || ops[i].am_error == MAXNAMELEN) | ||
528 | error = -ERANGE; | ||
529 | if (ops[i].am_error < 0) | ||
530 | break; | ||
531 | |||
532 | switch (ops[i].am_opcode) { | ||
533 | case ATTR_OP_GET: | ||
534 | ops[i].am_error = xfs_attrmulti_attr_get(inode, | ||
535 | attr_name, | ||
536 | compat_ptr(ops[i].am_attrvalue), | ||
537 | &ops[i].am_length, ops[i].am_flags); | ||
538 | break; | ||
539 | case ATTR_OP_SET: | ||
540 | ops[i].am_error = xfs_attrmulti_attr_set(inode, | ||
541 | attr_name, | ||
542 | compat_ptr(ops[i].am_attrvalue), | ||
543 | ops[i].am_length, ops[i].am_flags); | ||
544 | break; | ||
545 | case ATTR_OP_REMOVE: | ||
546 | ops[i].am_error = xfs_attrmulti_attr_remove(inode, | ||
547 | attr_name, ops[i].am_flags); | ||
548 | break; | ||
549 | default: | ||
550 | ops[i].am_error = EINVAL; | ||
551 | } | ||
552 | } | ||
553 | |||
554 | if (copy_to_user(compat_ptr(am_hreq.ops), ops, size)) | ||
555 | error = XFS_ERROR(EFAULT); | ||
556 | |||
557 | kfree(attr_name); | ||
558 | out_kfree_ops: | ||
559 | kfree(ops); | ||
560 | out_vn_rele: | ||
561 | iput(inode); | ||
562 | out: | ||
563 | return -error; | ||
564 | } | ||
565 | |||
479 | STATIC long | 566 | STATIC long |
480 | xfs_compat_ioctl( | 567 | xfs_compat_ioctl( |
481 | xfs_inode_t *ip, | 568 | xfs_inode_t *ip, |
@@ -499,10 +586,7 @@ xfs_compat_ioctl( | |||
499 | case XFS_IOC_GETBMAP: | 586 | case XFS_IOC_GETBMAP: |
500 | case XFS_IOC_GETBMAPA: | 587 | case XFS_IOC_GETBMAPA: |
501 | case XFS_IOC_GETBMAPX: | 588 | case XFS_IOC_GETBMAPX: |
502 | /* not handled | 589 | /* case XFS_IOC_FSSETDM_BY_HANDLE: not handled */ |
503 | case XFS_IOC_FSSETDM_BY_HANDLE: | ||
504 | case XFS_IOC_ATTRMULTI_BY_HANDLE: | ||
505 | */ | ||
506 | case XFS_IOC_FSCOUNTS: | 590 | case XFS_IOC_FSCOUNTS: |
507 | case XFS_IOC_SET_RESBLKS: | 591 | case XFS_IOC_SET_RESBLKS: |
508 | case XFS_IOC_GET_RESBLKS: | 592 | case XFS_IOC_GET_RESBLKS: |
@@ -610,6 +694,8 @@ xfs_compat_ioctl( | |||
610 | } | 694 | } |
611 | case XFS_IOC_ATTRLIST_BY_HANDLE_32: | 695 | case XFS_IOC_ATTRLIST_BY_HANDLE_32: |
612 | return xfs_compat_attrlist_by_handle(mp, arg, inode); | 696 | return xfs_compat_attrlist_by_handle(mp, arg, inode); |
697 | case XFS_IOC_ATTRMULTI_BY_HANDLE_32: | ||
698 | return xfs_compat_attrmulti_by_handle(mp, arg, inode); | ||
613 | default: | 699 | default: |
614 | return -XFS_ERROR(ENOIOCTLCMD); | 700 | return -XFS_ERROR(ENOIOCTLCMD); |
615 | } | 701 | } |
diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.h b/fs/xfs/linux-2.6/xfs_ioctl32.h index bbf3a2cd8a7d..785e7ec318cf 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl32.h +++ b/fs/xfs/linux-2.6/xfs_ioctl32.h | |||
@@ -135,6 +135,26 @@ typedef struct compat_xfs_fsop_attrlist_handlereq { | |||
135 | #define XFS_IOC_ATTRLIST_BY_HANDLE_32 \ | 135 | #define XFS_IOC_ATTRLIST_BY_HANDLE_32 \ |
136 | _IOW('X', 122, struct compat_xfs_fsop_attrlist_handlereq) | 136 | _IOW('X', 122, struct compat_xfs_fsop_attrlist_handlereq) |
137 | 137 | ||
138 | /* am_opcodes defined in xfs_fs.h */ | ||
139 | typedef struct compat_xfs_attr_multiop { | ||
140 | __u32 am_opcode; | ||
141 | __s32 am_error; | ||
142 | compat_uptr_t am_attrname; | ||
143 | compat_uptr_t am_attrvalue; | ||
144 | __u32 am_length; | ||
145 | __u32 am_flags; | ||
146 | } compat_xfs_attr_multiop_t; | ||
147 | |||
148 | typedef struct compat_xfs_fsop_attrmulti_handlereq { | ||
149 | struct compat_xfs_fsop_handlereq hreq; /* handle interface structure */ | ||
150 | __u32 opcount;/* count of following multiop */ | ||
151 | /* ptr to compat_xfs_attr_multiop */ | ||
152 | compat_uptr_t ops; /* attr_multi data */ | ||
153 | } compat_xfs_fsop_attrmulti_handlereq_t; | ||
154 | |||
155 | #define XFS_IOC_ATTRMULTI_BY_HANDLE_32 \ | ||
156 | _IOW('X', 123, struct compat_xfs_fsop_attrmulti_handlereq) | ||
157 | |||
138 | #ifdef BROKEN_X86_ALIGNMENT | 158 | #ifdef BROKEN_X86_ALIGNMENT |
139 | /* on ia32 l_start is on a 32-bit boundary */ | 159 | /* on ia32 l_start is on a 32-bit boundary */ |
140 | typedef struct compat_xfs_flock64 { | 160 | typedef struct compat_xfs_flock64 { |