diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-12-30 20:48:25 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-12-30 20:48:25 -0500 |
commit | 6a94cb73064c952255336cc57731904174b2c58f (patch) | |
tree | d19cc835db0a21e01909a92772868e1ad96f99ff /fs/xfs/linux-2.6/xfs_ioctl.c | |
parent | f57fa1d6a6b3414e853d3d17e339ac48816e4406 (diff) | |
parent | 0a8c5395f90f06d128247844b2515c8bf3f2826b (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.c | 223 |
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 | */ |
71 | STATIC int | 71 | int |
72 | xfs_find_handle( | 72 | xfs_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 | ||
252 | STATIC int | 248 | int |
253 | xfs_open_by_handle( | 249 | xfs_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 | ||
366 | STATIC int | 360 | int |
367 | xfs_readlink_by_handle( | 361 | xfs_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 | ||
504 | STATIC int | 495 | int |
505 | xfs_attrmulti_attr_get( | 496 | xfs_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 | ||
533 | STATIC int | 524 | int |
534 | xfs_attrmulti_attr_set( | 525 | xfs_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 | ||
563 | STATIC int | 554 | int |
564 | xfs_attrmulti_attr_remove( | 555 | xfs_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 | ||
665 | STATIC int | 656 | int |
666 | xfs_ioc_space( | 657 | xfs_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 | ||
1258 | STATIC int | 1248 | STATIC int |
1249 | xfs_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 | |||
1261 | STATIC int | ||
1259 | xfs_ioc_getbmap( | 1262 | xfs_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 | ||
1288 | STATIC int | 1292 | STATIC int |
1293 | xfs_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 | |||
1304 | STATIC int | ||
1289 | xfs_ioc_getbmapx( | 1305 | xfs_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 | ||
1329 | int | 1333 | /* |
1330 | xfs_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 | */ | ||
1339 | long | ||
1340 | xfs_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 | ||