aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorsandeen@sandeen.net <sandeen@sandeen.net>2008-11-25 22:20:15 -0500
committerLachlan McIlroy <lachlan@redback.melbourne.sgi.com>2008-12-02 01:17:07 -0500
commit28750975ace79c547407a84d3969cbed516be8f8 (patch)
tree79707c1e3c304ec7a11ea920cda38760d0248d5c /fs
parentebeecd2b04645a4b79e1bc00d69cf4f98e03a684 (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.c6
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl.h23
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl32.c94
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl32.h20
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
493STATIC int 493int
494xfs_attrmulti_attr_get( 494xfs_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
522STATIC int 522int
523xfs_attrmulti_attr_set( 523xfs_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
552STATIC int 552int
553xfs_attrmulti_attr_remove( 553xfs_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
48extern int
49xfs_attrmulti_attr_get(
50 struct inode *inode,
51 char *name,
52 char __user *ubuf,
53 __uint32_t *len,
54 __uint32_t flags);
55
56extern 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
64extern int
65xfs_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
479STATIC int
480xfs_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
479STATIC long 566STATIC long
480xfs_compat_ioctl( 567xfs_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 */
139typedef 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
148typedef 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 */
140typedef struct compat_xfs_flock64 { 160typedef struct compat_xfs_flock64 {