aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/linux-2.6/xfs_ioctl.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-12-30 20:48:25 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2008-12-30 20:48:25 -0500
commit6a94cb73064c952255336cc57731904174b2c58f (patch)
treed19cc835db0a21e01909a92772868e1ad96f99ff /fs/xfs/linux-2.6/xfs_ioctl.c
parentf57fa1d6a6b3414e853d3d17e339ac48816e4406 (diff)
parent0a8c5395f90f06d128247844b2515c8bf3f2826b (diff)
Merge branch 'for-linus' of git://oss.sgi.com/xfs/xfs
* 'for-linus' of git://oss.sgi.com/xfs/xfs: (184 commits) [XFS] Fix race in xfs_write() between direct and buffered I/O with DMAPI [XFS] handle unaligned data in xfs_bmbt_disk_get_all [XFS] avoid memory allocations in xfs_fs_vcmn_err [XFS] Fix speculative allocation beyond eof [XFS] Remove XFS_BUF_SHUT() and friends [XFS] Use the incore inode size in xfs_file_readdir() [XFS] set b_error from bio error in xfs_buf_bio_end_io [XFS] use inode_change_ok for setattr permission checking [XFS] add a FMODE flag to make XFS invisible I/O less hacky [XFS] resync headers with libxfs [XFS] simplify projid check in xfs_rename [XFS] replace b_fspriv with b_mount [XFS] Remove unused tracing code [XFS] Remove unnecessary assertion [XFS] Remove unused variable in ktrace_free() [XFS] Check return value of xfs_buf_get_noaddr() [XFS] Fix hang after disallowed rename across directory quota domains [XFS] Fix compile with CONFIG_COMPAT enabled move inode tracing out of xfs_vnode. move vn_iowait / vn_iowake into xfs_aops.c ...
Diffstat (limited to 'fs/xfs/linux-2.6/xfs_ioctl.c')
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl.c223
1 files changed, 120 insertions, 103 deletions
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c
index 281cbd5a25cf..67205f6198ba 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl.c
@@ -68,26 +68,22 @@
68 * XFS_IOC_PATH_TO_HANDLE 68 * XFS_IOC_PATH_TO_HANDLE
69 * returns full handle for a path 69 * returns full handle for a path
70 */ 70 */
71STATIC int 71int
72xfs_find_handle( 72xfs_find_handle(
73 unsigned int cmd, 73 unsigned int cmd,
74 void __user *arg) 74 xfs_fsop_handlereq_t *hreq)
75{ 75{
76 int hsize; 76 int hsize;
77 xfs_handle_t handle; 77 xfs_handle_t handle;
78 xfs_fsop_handlereq_t hreq;
79 struct inode *inode; 78 struct inode *inode;
80 79
81 if (copy_from_user(&hreq, arg, sizeof(hreq)))
82 return -XFS_ERROR(EFAULT);
83
84 memset((char *)&handle, 0, sizeof(handle)); 80 memset((char *)&handle, 0, sizeof(handle));
85 81
86 switch (cmd) { 82 switch (cmd) {
87 case XFS_IOC_PATH_TO_FSHANDLE: 83 case XFS_IOC_PATH_TO_FSHANDLE:
88 case XFS_IOC_PATH_TO_HANDLE: { 84 case XFS_IOC_PATH_TO_HANDLE: {
89 struct path path; 85 struct path path;
90 int error = user_lpath((const char __user *)hreq.path, &path); 86 int error = user_lpath((const char __user *)hreq->path, &path);
91 if (error) 87 if (error)
92 return error; 88 return error;
93 89
@@ -101,7 +97,7 @@ xfs_find_handle(
101 case XFS_IOC_FD_TO_HANDLE: { 97 case XFS_IOC_FD_TO_HANDLE: {
102 struct file *file; 98 struct file *file;
103 99
104 file = fget(hreq.fd); 100 file = fget(hreq->fd);
105 if (!file) 101 if (!file)
106 return -EBADF; 102 return -EBADF;
107 103
@@ -158,8 +154,8 @@ xfs_find_handle(
158 } 154 }
159 155
160 /* now copy our handle into the user buffer & write out the size */ 156 /* now copy our handle into the user buffer & write out the size */
161 if (copy_to_user(hreq.ohandle, &handle, hsize) || 157 if (copy_to_user(hreq->ohandle, &handle, hsize) ||
162 copy_to_user(hreq.ohandlen, &hsize, sizeof(__s32))) { 158 copy_to_user(hreq->ohandlen, &hsize, sizeof(__s32))) {
163 iput(inode); 159 iput(inode);
164 return -XFS_ERROR(EFAULT); 160 return -XFS_ERROR(EFAULT);
165 } 161 }
@@ -249,10 +245,10 @@ xfs_vget_fsop_handlereq(
249 return 0; 245 return 0;
250} 246}
251 247
252STATIC int 248int
253xfs_open_by_handle( 249xfs_open_by_handle(
254 xfs_mount_t *mp, 250 xfs_mount_t *mp,
255 void __user *arg, 251 xfs_fsop_handlereq_t *hreq,
256 struct file *parfilp, 252 struct file *parfilp,
257 struct inode *parinode) 253 struct inode *parinode)
258{ 254{
@@ -263,14 +259,11 @@ xfs_open_by_handle(
263 struct file *filp; 259 struct file *filp;
264 struct inode *inode; 260 struct inode *inode;
265 struct dentry *dentry; 261 struct dentry *dentry;
266 xfs_fsop_handlereq_t hreq;
267 262
268 if (!capable(CAP_SYS_ADMIN)) 263 if (!capable(CAP_SYS_ADMIN))
269 return -XFS_ERROR(EPERM); 264 return -XFS_ERROR(EPERM);
270 if (copy_from_user(&hreq, arg, sizeof(xfs_fsop_handlereq_t)))
271 return -XFS_ERROR(EFAULT);
272 265
273 error = xfs_vget_fsop_handlereq(mp, parinode, &hreq, &inode); 266 error = xfs_vget_fsop_handlereq(mp, parinode, hreq, &inode);
274 if (error) 267 if (error)
275 return -error; 268 return -error;
276 269
@@ -281,10 +274,10 @@ xfs_open_by_handle(
281 } 274 }
282 275
283#if BITS_PER_LONG != 32 276#if BITS_PER_LONG != 32
284 hreq.oflags |= O_LARGEFILE; 277 hreq->oflags |= O_LARGEFILE;
285#endif 278#endif
286 /* Put open permission in namei format. */ 279 /* Put open permission in namei format. */
287 permflag = hreq.oflags; 280 permflag = hreq->oflags;
288 if ((permflag+1) & O_ACCMODE) 281 if ((permflag+1) & O_ACCMODE)
289 permflag++; 282 permflag++;
290 if (permflag & O_TRUNC) 283 if (permflag & O_TRUNC)
@@ -322,15 +315,16 @@ xfs_open_by_handle(
322 mntget(parfilp->f_path.mnt); 315 mntget(parfilp->f_path.mnt);
323 316
324 /* Create file pointer. */ 317 /* Create file pointer. */
325 filp = dentry_open(dentry, parfilp->f_path.mnt, hreq.oflags, cred); 318 filp = dentry_open(dentry, parfilp->f_path.mnt, hreq->oflags, cred);
326 if (IS_ERR(filp)) { 319 if (IS_ERR(filp)) {
327 put_unused_fd(new_fd); 320 put_unused_fd(new_fd);
328 return -XFS_ERROR(-PTR_ERR(filp)); 321 return -XFS_ERROR(-PTR_ERR(filp));
329 } 322 }
323
330 if (inode->i_mode & S_IFREG) { 324 if (inode->i_mode & S_IFREG) {
331 /* invisible operation should not change atime */ 325 /* invisible operation should not change atime */
332 filp->f_flags |= O_NOATIME; 326 filp->f_flags |= O_NOATIME;
333 filp->f_op = &xfs_invis_file_operations; 327 filp->f_mode |= FMODE_NOCMTIME;
334 } 328 }
335 329
336 fd_install(new_fd, filp); 330 fd_install(new_fd, filp);
@@ -363,24 +357,21 @@ do_readlink(
363} 357}
364 358
365 359
366STATIC int 360int
367xfs_readlink_by_handle( 361xfs_readlink_by_handle(
368 xfs_mount_t *mp, 362 xfs_mount_t *mp,
369 void __user *arg, 363 xfs_fsop_handlereq_t *hreq,
370 struct inode *parinode) 364 struct inode *parinode)
371{ 365{
372 struct inode *inode; 366 struct inode *inode;
373 xfs_fsop_handlereq_t hreq;
374 __u32 olen; 367 __u32 olen;
375 void *link; 368 void *link;
376 int error; 369 int error;
377 370
378 if (!capable(CAP_SYS_ADMIN)) 371 if (!capable(CAP_SYS_ADMIN))
379 return -XFS_ERROR(EPERM); 372 return -XFS_ERROR(EPERM);
380 if (copy_from_user(&hreq, arg, sizeof(xfs_fsop_handlereq_t)))
381 return -XFS_ERROR(EFAULT);
382 373
383 error = xfs_vget_fsop_handlereq(mp, parinode, &hreq, &inode); 374 error = xfs_vget_fsop_handlereq(mp, parinode, hreq, &inode);
384 if (error) 375 if (error)
385 return -error; 376 return -error;
386 377
@@ -390,7 +381,7 @@ xfs_readlink_by_handle(
390 goto out_iput; 381 goto out_iput;
391 } 382 }
392 383
393 if (copy_from_user(&olen, hreq.ohandlen, sizeof(__u32))) { 384 if (copy_from_user(&olen, hreq->ohandlen, sizeof(__u32))) {
394 error = -XFS_ERROR(EFAULT); 385 error = -XFS_ERROR(EFAULT);
395 goto out_iput; 386 goto out_iput;
396 } 387 }
@@ -402,7 +393,7 @@ xfs_readlink_by_handle(
402 error = -xfs_readlink(XFS_I(inode), link); 393 error = -xfs_readlink(XFS_I(inode), link);
403 if (error) 394 if (error)
404 goto out_kfree; 395 goto out_kfree;
405 error = do_readlink(hreq.ohandle, olen, link); 396 error = do_readlink(hreq->ohandle, olen, link);
406 if (error) 397 if (error)
407 goto out_kfree; 398 goto out_kfree;
408 399
@@ -501,7 +492,7 @@ xfs_attrlist_by_handle(
501 return -error; 492 return -error;
502} 493}
503 494
504STATIC int 495int
505xfs_attrmulti_attr_get( 496xfs_attrmulti_attr_get(
506 struct inode *inode, 497 struct inode *inode,
507 char *name, 498 char *name,
@@ -530,7 +521,7 @@ xfs_attrmulti_attr_get(
530 return error; 521 return error;
531} 522}
532 523
533STATIC int 524int
534xfs_attrmulti_attr_set( 525xfs_attrmulti_attr_set(
535 struct inode *inode, 526 struct inode *inode,
536 char *name, 527 char *name,
@@ -560,7 +551,7 @@ xfs_attrmulti_attr_set(
560 return error; 551 return error;
561} 552}
562 553
563STATIC int 554int
564xfs_attrmulti_attr_remove( 555xfs_attrmulti_attr_remove(
565 struct inode *inode, 556 struct inode *inode,
566 char *name, 557 char *name,
@@ -662,19 +653,26 @@ xfs_attrmulti_by_handle(
662 return -error; 653 return -error;
663} 654}
664 655
665STATIC int 656int
666xfs_ioc_space( 657xfs_ioc_space(
667 struct xfs_inode *ip, 658 struct xfs_inode *ip,
668 struct inode *inode, 659 struct inode *inode,
669 struct file *filp, 660 struct file *filp,
670 int ioflags, 661 int ioflags,
671 unsigned int cmd, 662 unsigned int cmd,
672 void __user *arg) 663 xfs_flock64_t *bf)
673{ 664{
674 xfs_flock64_t bf;
675 int attr_flags = 0; 665 int attr_flags = 0;
676 int error; 666 int error;
677 667
668 /*
669 * Only allow the sys admin to reserve space unless
670 * unwritten extents are enabled.
671 */
672 if (!xfs_sb_version_hasextflgbit(&ip->i_mount->m_sb) &&
673 !capable(CAP_SYS_ADMIN))
674 return -XFS_ERROR(EPERM);
675
678 if (inode->i_flags & (S_IMMUTABLE|S_APPEND)) 676 if (inode->i_flags & (S_IMMUTABLE|S_APPEND))
679 return -XFS_ERROR(EPERM); 677 return -XFS_ERROR(EPERM);
680 678
@@ -684,16 +682,12 @@ xfs_ioc_space(
684 if (!S_ISREG(inode->i_mode)) 682 if (!S_ISREG(inode->i_mode))
685 return -XFS_ERROR(EINVAL); 683 return -XFS_ERROR(EINVAL);
686 684
687 if (copy_from_user(&bf, arg, sizeof(bf)))
688 return -XFS_ERROR(EFAULT);
689
690 if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) 685 if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
691 attr_flags |= XFS_ATTR_NONBLOCK; 686 attr_flags |= XFS_ATTR_NONBLOCK;
692 if (ioflags & IO_INVIS) 687 if (ioflags & IO_INVIS)
693 attr_flags |= XFS_ATTR_DMI; 688 attr_flags |= XFS_ATTR_DMI;
694 689
695 error = xfs_change_file_space(ip, cmd, &bf, filp->f_pos, 690 error = xfs_change_file_space(ip, cmd, bf, filp->f_pos, attr_flags);
696 NULL, attr_flags);
697 return -error; 691 return -error;
698} 692}
699 693
@@ -1105,10 +1099,6 @@ xfs_ioctl_setattr(
1105 1099
1106 /* 1100 /*
1107 * Change file ownership. Must be the owner or privileged. 1101 * Change file ownership. Must be the owner or privileged.
1108 * If the system was configured with the "restricted_chown"
1109 * option, the owner is not permitted to give away the file,
1110 * and can change the group id only to a group of which he
1111 * or she is a member.
1112 */ 1102 */
1113 if (mask & FSX_PROJID) { 1103 if (mask & FSX_PROJID) {
1114 /* 1104 /*
@@ -1137,7 +1127,7 @@ xfs_ioctl_setattr(
1137 * the superblock version number since projids didn't 1127 * the superblock version number since projids didn't
1138 * exist before DINODE_VERSION_2 and SB_VERSION_NLINK. 1128 * exist before DINODE_VERSION_2 and SB_VERSION_NLINK.
1139 */ 1129 */
1140 if (ip->i_d.di_version == XFS_DINODE_VERSION_1) 1130 if (ip->i_d.di_version == 1)
1141 xfs_bump_ino_vers2(tp, ip); 1131 xfs_bump_ino_vers2(tp, ip);
1142 } 1132 }
1143 1133
@@ -1256,43 +1246,67 @@ xfs_ioc_setxflags(
1256} 1246}
1257 1247
1258STATIC int 1248STATIC int
1249xfs_getbmap_format(void **ap, struct getbmapx *bmv, int *full)
1250{
1251 struct getbmap __user *base = *ap;
1252
1253 /* copy only getbmap portion (not getbmapx) */
1254 if (copy_to_user(base, bmv, sizeof(struct getbmap)))
1255 return XFS_ERROR(EFAULT);
1256
1257 *ap += sizeof(struct getbmap);
1258 return 0;
1259}
1260
1261STATIC int
1259xfs_ioc_getbmap( 1262xfs_ioc_getbmap(
1260 struct xfs_inode *ip, 1263 struct xfs_inode *ip,
1261 int ioflags, 1264 int ioflags,
1262 unsigned int cmd, 1265 unsigned int cmd,
1263 void __user *arg) 1266 void __user *arg)
1264{ 1267{
1265 struct getbmap bm; 1268 struct getbmapx bmx;
1266 int iflags;
1267 int error; 1269 int error;
1268 1270
1269 if (copy_from_user(&bm, arg, sizeof(bm))) 1271 if (copy_from_user(&bmx, arg, sizeof(struct getbmapx)))
1270 return -XFS_ERROR(EFAULT); 1272 return -XFS_ERROR(EFAULT);
1271 1273
1272 if (bm.bmv_count < 2) 1274 if (bmx.bmv_count < 2)
1273 return -XFS_ERROR(EINVAL); 1275 return -XFS_ERROR(EINVAL);
1274 1276
1275 iflags = (cmd == XFS_IOC_GETBMAPA ? BMV_IF_ATTRFORK : 0); 1277 bmx.bmv_iflags = (cmd == XFS_IOC_GETBMAPA ? BMV_IF_ATTRFORK : 0);
1276 if (ioflags & IO_INVIS) 1278 if (ioflags & IO_INVIS)
1277 iflags |= BMV_IF_NO_DMAPI_READ; 1279 bmx.bmv_iflags |= BMV_IF_NO_DMAPI_READ;
1278 1280
1279 error = xfs_getbmap(ip, &bm, (struct getbmap __user *)arg+1, iflags); 1281 error = xfs_getbmap(ip, &bmx, xfs_getbmap_format,
1282 (struct getbmap *)arg+1);
1280 if (error) 1283 if (error)
1281 return -error; 1284 return -error;
1282 1285
1283 if (copy_to_user(arg, &bm, sizeof(bm))) 1286 /* copy back header - only size of getbmap */
1287 if (copy_to_user(arg, &bmx, sizeof(struct getbmap)))
1284 return -XFS_ERROR(EFAULT); 1288 return -XFS_ERROR(EFAULT);
1285 return 0; 1289 return 0;
1286} 1290}
1287 1291
1288STATIC int 1292STATIC int
1293xfs_getbmapx_format(void **ap, struct getbmapx *bmv, int *full)
1294{
1295 struct getbmapx __user *base = *ap;
1296
1297 if (copy_to_user(base, bmv, sizeof(struct getbmapx)))
1298 return XFS_ERROR(EFAULT);
1299
1300 *ap += sizeof(struct getbmapx);
1301 return 0;
1302}
1303
1304STATIC int
1289xfs_ioc_getbmapx( 1305xfs_ioc_getbmapx(
1290 struct xfs_inode *ip, 1306 struct xfs_inode *ip,
1291 void __user *arg) 1307 void __user *arg)
1292{ 1308{
1293 struct getbmapx bmx; 1309 struct getbmapx bmx;
1294 struct getbmap bm;
1295 int iflags;
1296 int error; 1310 int error;
1297 1311
1298 if (copy_from_user(&bmx, arg, sizeof(bmx))) 1312 if (copy_from_user(&bmx, arg, sizeof(bmx)))
@@ -1301,46 +1315,46 @@ xfs_ioc_getbmapx(
1301 if (bmx.bmv_count < 2) 1315 if (bmx.bmv_count < 2)
1302 return -XFS_ERROR(EINVAL); 1316 return -XFS_ERROR(EINVAL);
1303 1317
1304 /* 1318 if (bmx.bmv_iflags & (~BMV_IF_VALID))
1305 * Map input getbmapx structure to a getbmap
1306 * structure for xfs_getbmap.
1307 */
1308 GETBMAP_CONVERT(bmx, bm);
1309
1310 iflags = bmx.bmv_iflags;
1311
1312 if (iflags & (~BMV_IF_VALID))
1313 return -XFS_ERROR(EINVAL); 1319 return -XFS_ERROR(EINVAL);
1314 1320
1315 iflags |= BMV_IF_EXTENDED; 1321 error = xfs_getbmap(ip, &bmx, xfs_getbmapx_format,
1316 1322 (struct getbmapx *)arg+1);
1317 error = xfs_getbmap(ip, &bm, (struct getbmapx __user *)arg+1, iflags);
1318 if (error) 1323 if (error)
1319 return -error; 1324 return -error;
1320 1325
1321 GETBMAP_CONVERT(bm, bmx); 1326 /* copy back header */
1322 1327 if (copy_to_user(arg, &bmx, sizeof(struct getbmapx)))
1323 if (copy_to_user(arg, &bmx, sizeof(bmx)))
1324 return -XFS_ERROR(EFAULT); 1328 return -XFS_ERROR(EFAULT);
1325 1329
1326 return 0; 1330 return 0;
1327} 1331}
1328 1332
1329int 1333/*
1330xfs_ioctl( 1334 * Note: some of the ioctl's return positive numbers as a
1331 xfs_inode_t *ip, 1335 * byte count indicating success, such as readlink_by_handle.
1336 * So we don't "sign flip" like most other routines. This means
1337 * true errors need to be returned as a negative value.
1338 */
1339long
1340xfs_file_ioctl(
1332 struct file *filp, 1341 struct file *filp,
1333 int ioflags,
1334 unsigned int cmd, 1342 unsigned int cmd,
1335 void __user *arg) 1343 unsigned long p)
1336{ 1344{
1337 struct inode *inode = filp->f_path.dentry->d_inode; 1345 struct inode *inode = filp->f_path.dentry->d_inode;
1338 xfs_mount_t *mp = ip->i_mount; 1346 struct xfs_inode *ip = XFS_I(inode);
1347 struct xfs_mount *mp = ip->i_mount;
1348 void __user *arg = (void __user *)p;
1349 int ioflags = 0;
1339 int error; 1350 int error;
1340 1351
1341 xfs_itrace_entry(XFS_I(inode)); 1352 if (filp->f_mode & FMODE_NOCMTIME)
1342 switch (cmd) { 1353 ioflags |= IO_INVIS;
1343 1354
1355 xfs_itrace_entry(ip);
1356
1357 switch (cmd) {
1344 case XFS_IOC_ALLOCSP: 1358 case XFS_IOC_ALLOCSP:
1345 case XFS_IOC_FREESP: 1359 case XFS_IOC_FREESP:
1346 case XFS_IOC_RESVSP: 1360 case XFS_IOC_RESVSP:
@@ -1348,17 +1362,13 @@ xfs_ioctl(
1348 case XFS_IOC_ALLOCSP64: 1362 case XFS_IOC_ALLOCSP64:
1349 case XFS_IOC_FREESP64: 1363 case XFS_IOC_FREESP64:
1350 case XFS_IOC_RESVSP64: 1364 case XFS_IOC_RESVSP64:
1351 case XFS_IOC_UNRESVSP64: 1365 case XFS_IOC_UNRESVSP64: {
1352 /* 1366 xfs_flock64_t bf;
1353 * Only allow the sys admin to reserve space unless
1354 * unwritten extents are enabled.
1355 */
1356 if (!xfs_sb_version_hasextflgbit(&mp->m_sb) &&
1357 !capable(CAP_SYS_ADMIN))
1358 return -EPERM;
1359
1360 return xfs_ioc_space(ip, inode, filp, ioflags, cmd, arg);
1361 1367
1368 if (copy_from_user(&bf, arg, sizeof(bf)))
1369 return -XFS_ERROR(EFAULT);
1370 return xfs_ioc_space(ip, inode, filp, ioflags, cmd, &bf);
1371 }
1362 case XFS_IOC_DIOINFO: { 1372 case XFS_IOC_DIOINFO: {
1363 struct dioattr da; 1373 struct dioattr da;
1364 xfs_buftarg_t *target = 1374 xfs_buftarg_t *target =
@@ -1418,18 +1428,30 @@ xfs_ioctl(
1418 1428
1419 case XFS_IOC_FD_TO_HANDLE: 1429 case XFS_IOC_FD_TO_HANDLE:
1420 case XFS_IOC_PATH_TO_HANDLE: 1430 case XFS_IOC_PATH_TO_HANDLE:
1421 case XFS_IOC_PATH_TO_FSHANDLE: 1431 case XFS_IOC_PATH_TO_FSHANDLE: {
1422 return xfs_find_handle(cmd, arg); 1432 xfs_fsop_handlereq_t hreq;
1423 1433
1424 case XFS_IOC_OPEN_BY_HANDLE: 1434 if (copy_from_user(&hreq, arg, sizeof(hreq)))
1425 return xfs_open_by_handle(mp, arg, filp, inode); 1435 return -XFS_ERROR(EFAULT);
1436 return xfs_find_handle(cmd, &hreq);
1437 }
1438 case XFS_IOC_OPEN_BY_HANDLE: {
1439 xfs_fsop_handlereq_t hreq;
1426 1440
1441 if (copy_from_user(&hreq, arg, sizeof(xfs_fsop_handlereq_t)))
1442 return -XFS_ERROR(EFAULT);
1443 return xfs_open_by_handle(mp, &hreq, filp, inode);
1444 }
1427 case XFS_IOC_FSSETDM_BY_HANDLE: 1445 case XFS_IOC_FSSETDM_BY_HANDLE:
1428 return xfs_fssetdm_by_handle(mp, arg, inode); 1446 return xfs_fssetdm_by_handle(mp, arg, inode);
1429 1447
1430 case XFS_IOC_READLINK_BY_HANDLE: 1448 case XFS_IOC_READLINK_BY_HANDLE: {
1431 return xfs_readlink_by_handle(mp, arg, inode); 1449 xfs_fsop_handlereq_t hreq;
1432 1450
1451 if (copy_from_user(&hreq, arg, sizeof(xfs_fsop_handlereq_t)))
1452 return -XFS_ERROR(EFAULT);
1453 return xfs_readlink_by_handle(mp, &hreq, inode);
1454 }
1433 case XFS_IOC_ATTRLIST_BY_HANDLE: 1455 case XFS_IOC_ATTRLIST_BY_HANDLE:
1434 return xfs_attrlist_by_handle(mp, arg, inode); 1456 return xfs_attrlist_by_handle(mp, arg, inode);
1435 1457
@@ -1437,7 +1459,11 @@ xfs_ioctl(
1437 return xfs_attrmulti_by_handle(mp, arg, filp, inode); 1459 return xfs_attrmulti_by_handle(mp, arg, filp, inode);
1438 1460
1439 case XFS_IOC_SWAPEXT: { 1461 case XFS_IOC_SWAPEXT: {
1440 error = xfs_swapext((struct xfs_swapext __user *)arg); 1462 struct xfs_swapext sxp;
1463
1464 if (copy_from_user(&sxp, arg, sizeof(xfs_swapext_t)))
1465 return -XFS_ERROR(EFAULT);
1466 error = xfs_swapext(&sxp);
1441 return -error; 1467 return -error;
1442 } 1468 }
1443 1469
@@ -1493,9 +1519,6 @@ xfs_ioctl(
1493 case XFS_IOC_FSGROWFSDATA: { 1519 case XFS_IOC_FSGROWFSDATA: {
1494 xfs_growfs_data_t in; 1520 xfs_growfs_data_t in;
1495 1521
1496 if (!capable(CAP_SYS_ADMIN))
1497 return -EPERM;
1498
1499 if (copy_from_user(&in, arg, sizeof(in))) 1522 if (copy_from_user(&in, arg, sizeof(in)))
1500 return -XFS_ERROR(EFAULT); 1523 return -XFS_ERROR(EFAULT);
1501 1524
@@ -1506,9 +1529,6 @@ xfs_ioctl(
1506 case XFS_IOC_FSGROWFSLOG: { 1529 case XFS_IOC_FSGROWFSLOG: {
1507 xfs_growfs_log_t in; 1530 xfs_growfs_log_t in;
1508 1531
1509 if (!capable(CAP_SYS_ADMIN))
1510 return -EPERM;
1511
1512 if (copy_from_user(&in, arg, sizeof(in))) 1532 if (copy_from_user(&in, arg, sizeof(in)))
1513 return -XFS_ERROR(EFAULT); 1533 return -XFS_ERROR(EFAULT);
1514 1534
@@ -1519,9 +1539,6 @@ xfs_ioctl(
1519 case XFS_IOC_FSGROWFSRT: { 1539 case XFS_IOC_FSGROWFSRT: {
1520 xfs_growfs_rt_t in; 1540 xfs_growfs_rt_t in;
1521 1541
1522 if (!capable(CAP_SYS_ADMIN))
1523 return -EPERM;
1524
1525 if (copy_from_user(&in, arg, sizeof(in))) 1542 if (copy_from_user(&in, arg, sizeof(in)))
1526 return -XFS_ERROR(EFAULT); 1543 return -XFS_ERROR(EFAULT);
1527 1544