1 /* 2 * Copyright (c) 2000-2005 Silicon Graphics, Inc. 3 * All Rights Reserved. 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it would be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write the Free Software Foundation, 16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 */ 18 #include "xfs.h" 19 #include "xfs_fs.h" 20 #include "xfs_bit.h" 21 #include "xfs_log.h" 22 #include "xfs_inum.h" 23 #include "xfs_trans.h" 24 #include "xfs_sb.h" 25 #include "xfs_ag.h" 26 #include "xfs_alloc.h" 27 #include "xfs_mount.h" 28 #include "xfs_bmap_btree.h" 29 #include "xfs_dinode.h" 30 #include "xfs_inode.h" 31 #include "xfs_ioctl.h" 32 #include "xfs_rtalloc.h" 33 #include "xfs_itable.h" 34 #include "xfs_error.h" 35 #include "xfs_attr.h" 36 #include "xfs_bmap.h" 37 #include "xfs_buf_item.h" 38 #include "xfs_utils.h" 39 #include "xfs_dfrag.h" 40 #include "xfs_fsops.h" 41 #include "xfs_vnodeops.h" 42 #include "xfs_discard.h" 43 #include "xfs_quota.h" 44 #include "xfs_inode_item.h" 45 #include "xfs_export.h" 46 #include "xfs_trace.h" 47 48 #include <linux/capability.h> 49 #include <linux/dcache.h> 50 #include <linux/mount.h> 51 #include <linux/namei.h> 52 #include <linux/pagemap.h> 53 #include <linux/slab.h> 54 #include <linux/exportfs.h> 55 56 /* 57 * xfs_find_handle maps from userspace xfs_fsop_handlereq structure to 58 * a file or fs handle. 59 * 60 * XFS_IOC_PATH_TO_FSHANDLE 61 * returns fs handle for a mount point or path within that mount point 62 * XFS_IOC_FD_TO_HANDLE 63 * returns full handle for a FD opened in user space 64 * XFS_IOC_PATH_TO_HANDLE 65 * returns full handle for a path 66 */ 67 int 68 xfs_find_handle( 69 unsigned int cmd, 70 xfs_fsop_handlereq_t *hreq) 71 { 72 int hsize; 73 xfs_handle_t handle; 74 struct inode *inode; 75 struct file *file = NULL; 76 struct path path; 77 int error; 78 struct xfs_inode *ip; 79 80 if (cmd == XFS_IOC_FD_TO_HANDLE) { 81 file = fget(hreq->fd); 82 if (!file) 83 return -EBADF; 84 inode = file->f_path.dentry->d_inode; 85 } else { 86 error = user_lpath((const char __user *)hreq->path, &path); 87 if (error) 88 return error; 89 inode = path.dentry->d_inode; 90 } 91 ip = XFS_I(inode); 92 93 /* 94 * We can only generate handles for inodes residing on a XFS filesystem, 95 * and only for regular files, directories or symbolic links. 96 */ 97 error = -EINVAL; 98 if (inode->i_sb->s_magic != XFS_SB_MAGIC) 99 goto out_put; 100 101 error = -EBADF; 102 if (!S_ISREG(inode->i_mode) && 103 !S_ISDIR(inode->i_mode) && 104 !S_ISLNK(inode->i_mode)) 105 goto out_put; 106 107 108 memcpy(&handle.ha_fsid, ip->i_mount->m_fixedfsid, sizeof(xfs_fsid_t)); 109 110 if (cmd == XFS_IOC_PATH_TO_FSHANDLE) { 111 /* 112 * This handle only contains an fsid, zero the rest. 113 */ 114 memset(&handle.ha_fid, 0, sizeof(handle.ha_fid)); 115 hsize = sizeof(xfs_fsid_t); 116 } else { 117 int lock_mode; 118 119 lock_mode = xfs_ilock_map_shared(ip); 120 handle.ha_fid.fid_len = sizeof(xfs_fid_t) - 121 sizeof(handle.ha_fid.fid_len); 122 handle.ha_fid.fid_pad = 0; 123 handle.ha_fid.fid_gen = ip->i_d.di_gen; 124 handle.ha_fid.fid_ino = ip->i_ino; 125 xfs_iunlock_map_shared(ip, lock_mode); 126 127 hsize = XFS_HSIZE(handle); 128 } 129 130 error = -EFAULT; 131 if (copy_to_user(hreq->ohandle, &handle, hsize) || 132 copy_to_user(hreq->ohandlen, &hsize, sizeof(__s32))) 133 goto out_put; 134 135 error = 0; 136 137 out_put: 138 if (cmd == XFS_IOC_FD_TO_HANDLE) 139 fput(file); 140 else 141 path_put(&path); 142 return error; 143 } 144 145 /* 146 * No need to do permission checks on the various pathname components 147 * as the handle operations are privileged. 148 */ 149 STATIC int 150 xfs_handle_acceptable( 151 void *context, 152 struct dentry *dentry) 153 { 154 return 1; 155 } 156 157 /* 158 * Convert userspace handle data into a dentry. 159 */ 160 struct dentry * 161 xfs_handle_to_dentry( 162 struct file *parfilp, 163 void __user *uhandle, 164 u32 hlen) 165 { 166 xfs_handle_t handle; 167 struct xfs_fid64 fid; 168 169 /* 170 * Only allow handle opens under a directory. 171 */ 172 if (!S_ISDIR(parfilp->f_path.dentry->d_inode->i_mode)) 173 return ERR_PTR(-ENOTDIR); 174 175 if (hlen != sizeof(xfs_handle_t)) 176 return ERR_PTR(-EINVAL); 177 if (copy_from_user(&handle, uhandle, hlen)) 178 return ERR_PTR(-EFAULT); 179 if (handle.ha_fid.fid_len != 180 sizeof(handle.ha_fid) - sizeof(handle.ha_fid.fid_len)) 181 return ERR_PTR(-EINVAL); 182 183 memset(&fid, 0, sizeof(struct fid)); 184 fid.ino = handle.ha_fid.fid_ino; 185 fid.gen = handle.ha_fid.fid_gen; 186 187 return exportfs_decode_fh(parfilp->f_path.mnt, (struct fid *)&fid, 3, 188 FILEID_INO32_GEN | XFS_FILEID_TYPE_64FLAG, 189 xfs_handle_acceptable, NULL); 190 } 191 192 STATIC struct dentry * 193 xfs_handlereq_to_dentry( 194 struct file *parfilp, 195 xfs_fsop_handlereq_t *hreq) 196 { 197 return xfs_handle_to_dentry(parfilp, hreq->ihandle, hreq->ihandlen); 198 } 199 200 int 201 xfs_open_by_handle( 202 struct file *parfilp, 203 xfs_fsop_handlereq_t *hreq) 204 { 205 const struct cred *cred = current_cred(); 206 int error; 207 int fd; 208 int permflag; 209 struct file *filp; 210 struct inode *inode; 211 struct dentry *dentry; 212 213 if (!capable(CAP_SYS_ADMIN)) 214 return -XFS_ERROR(EPERM); 215 216 dentry = xfs_handlereq_to_dentry(parfilp, hreq); 217 if (IS_ERR(dentry)) 218 return PTR_ERR(dentry); 219 inode = dentry->d_inode; 220 221 /* Restrict xfs_open_by_handle to directories & regular files. */ 222 if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) { 223 error = -XFS_ERROR(EPERM); 224 goto out_dput; 225 } 226 227 #if BITS_PER_LONG != 32 228 hreq->oflags |= O_LARGEFILE; 229 #endif 230 231 /* Put open permission in namei format. */ 232 permflag = hreq->oflags; 233 if ((permflag+1) & O_ACCMODE) 234 permflag++; 235 if (permflag & O_TRUNC) 236 permflag |= 2; 237 238 if ((!(permflag & O_APPEND) || (permflag & O_TRUNC)) && 239 (permflag & FMODE_WRITE) && IS_APPEND(inode)) { 240 error = -XFS_ERROR(EPERM); 241 goto out_dput; 242 } 243 244 if ((permflag & FMODE_WRITE) && IS_IMMUTABLE(inode)) { 245 error = -XFS_ERROR(EACCES); 246 goto out_dput; 247 } 248 249 /* Can't write directories. */ 250 if (S_ISDIR(inode->i_mode) && (permflag & FMODE_WRITE)) { 251 error = -XFS_ERROR(EISDIR); 252 goto out_dput; 253 } 254 255 fd = get_unused_fd(); 256 if (fd < 0) { 257 error = fd; 258 goto out_dput; 259 } 260 261 filp = dentry_open(dentry, mntget(parfilp->f_path.mnt), 262 hreq->oflags, cred); 263 if (IS_ERR(filp)) { 264 put_unused_fd(fd); 265 return PTR_ERR(filp); 266 } 267 268 if (S_ISREG(inode->i_mode)) { 269 filp->f_flags |= O_NOATIME; 270 filp->f_mode |= FMODE_NOCMTIME; 271 } 272 273 fd_install(fd, filp); 274 return fd; 275 276 out_dput: 277 dput(dentry); 278 return error; 279 } 280 281 /* 282 * This is a copy from fs/namei.c:vfs_readlink(), except for removing it's 283 * unused first argument. 284 */ 285 STATIC int 286 do_readlink( 287 char __user *buffer, 288 int buflen, 289 const char *link) 290 { 291 int len; 292 293 len = PTR_ERR(link); 294 if (IS_ERR(link)) 295 goto out; 296 297 len = strlen(link); 298 if (len > (unsigned) buflen) 299 len = buflen; 300 if (copy_to_user(buffer, link, len)) 301 len = -EFAULT; 302 out: 303 return len; 304 } 305 306 307 int 308 xfs_readlink_by_handle( 309 struct file *parfilp, 310 xfs_fsop_handlereq_t *hreq) 311 { 312 struct dentry *dentry; 313 __u32 olen; 314 void *link; 315 int error; 316 317 if (!capable(CAP_SYS_ADMIN)) 318 return -XFS_ERROR(EPERM); 319 320 dentry = xfs_handlereq_to_dentry(parfilp, hreq); 321 if (IS_ERR(dentry)) 322 return PTR_ERR(dentry); 323 324 /* Restrict this handle operation to symlinks only. */ 325 if (!S_ISLNK(dentry->d_inode->i_mode)) { 326 error = -XFS_ERROR(EINVAL); 327 goto out_dput; 328 } 329 330 if (copy_from_user(&olen, hreq->ohandlen, sizeof(__u32))) { 331 error = -XFS_ERROR(EFAULT); 332 goto out_dput; 333 } 334 335 link = kmalloc(MAXPATHLEN+1, GFP_KERNEL); 336 if (!link) { 337 error = -XFS_ERROR(ENOMEM); 338 goto out_dput; 339 } 340 341 error = -xfs_readlink(XFS_I(dentry->d_inode), link); 342 if (error) 343 goto out_kfree; 344 error = do_readlink(hreq->ohandle, olen, link); 345 if (error) 346 goto out_kfree; 347 348 out_kfree: 349 kfree(link); 350 out_dput: 351 dput(dentry); 352 return error; 353 } 354 355 STATIC int 356 xfs_fssetdm_by_handle( 357 struct file *parfilp, 358 void __user *arg) 359 { 360 int error; 361 struct fsdmidata fsd; 362 xfs_fsop_setdm_handlereq_t dmhreq; 363 struct dentry *dentry; 364 365 if (!capable(CAP_MKNOD)) 366 return -XFS_ERROR(EPERM); 367 if (copy_from_user(&dmhreq, arg, sizeof(xfs_fsop_setdm_handlereq_t))) 368 return -XFS_ERROR(EFAULT); 369 370 dentry = xfs_handlereq_to_dentry(parfilp, &dmhreq.hreq); 371 if (IS_ERR(dentry)) 372 return PTR_ERR(dentry); 373 374 if (IS_IMMUTABLE(dentry->d_inode) || IS_APPEND(dentry->d_inode)) { 375 error = -XFS_ERROR(EPERM); 376 goto out; 377 } 378 379 if (copy_from_user(&fsd, dmhreq.data, sizeof(fsd))) { 380 error = -XFS_ERROR(EFAULT); 381 goto out; 382 } 383 384 error = -xfs_set_dmattrs(XFS_I(dentry->d_inode), fsd.fsd_dmevmask, 385 fsd.fsd_dmstate); 386 387 out: 388 dput(dentry); 389 return error; 390 } 391 392 STATIC int 393 xfs_attrlist_by_handle( 394 struct file *parfilp, 395 void __user *arg) 396 { 397 int error = -ENOMEM; 398 attrlist_cursor_kern_t *cursor; 399 xfs_fsop_attrlist_handlereq_t al_hreq; 400 struct dentry *dentry; 401 char *kbuf; 402 403 if (!capable(CAP_SYS_ADMIN)) 404 return -XFS_ERROR(EPERM); 405 if (copy_from_user(&al_hreq, arg, sizeof(xfs_fsop_attrlist_handlereq_t))) 406 return -XFS_ERROR(EFAULT); 407 if (al_hreq.buflen > XATTR_LIST_MAX) 408 return -XFS_ERROR(EINVAL); 409 410 /* 411 * Reject flags, only allow namespaces. 412 */ 413 if (al_hreq.flags & ~(ATTR_ROOT | ATTR_SECURE)) 414 return -XFS_ERROR(EINVAL); 415 416 dentry = xfs_handlereq_to_dentry(parfilp, &al_hreq.hreq); 417 if (IS_ERR(dentry)) 418 return PTR_ERR(dentry); 419 420 kbuf = kzalloc(al_hreq.buflen, GFP_KERNEL); 421 if (!kbuf) 422 goto out_dput; 423 424 cursor = (attrlist_cursor_kern_t *)&al_hreq.pos; 425 error = -xfs_attr_list(XFS_I(dentry->d_inode), kbuf, al_hreq.buflen, 426 al_hreq.flags, cursor); 427 if (error) 428 goto out_kfree; 429 430 if (copy_to_user(al_hreq.buffer, kbuf, al_hreq.buflen)) 431 error = -EFAULT; 432 433 out_kfree: 434 kfree(kbuf); 435 out_dput: 436 dput(dentry); 437 return error; 438 } 439 440 int 441 xfs_attrmulti_attr_get( 442 struct inode *inode, 443 unsigned char *name, 444 unsigned char __user *ubuf, 445 __uint32_t *len, 446 __uint32_t flags) 447 { 448 unsigned char *kbuf; 449 int error = EFAULT; 450 451 if (*len > XATTR_SIZE_MAX) 452 return EINVAL; 453 kbuf = kmalloc(*len, GFP_KERNEL); 454 if (!kbuf) 455 return ENOMEM; 456 457 error = xfs_attr_get(XFS_I(inode), name, kbuf, (int *)len, flags); 458 if (error) 459 goto out_kfree; 460 461 if (copy_to_user(ubuf, kbuf, *len)) 462 error = EFAULT; 463 464 out_kfree: 465 kfree(kbuf); 466 return error; 467 } 468 469 int 470 xfs_attrmulti_attr_set( 471 struct inode *inode, 472 unsigned char *name, 473 const unsigned char __user *ubuf, 474 __uint32_t len, 475 __uint32_t flags) 476 { 477 unsigned char *kbuf; 478 int error = EFAULT; 479 480 if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) 481 return EPERM; 482 if (len > XATTR_SIZE_MAX) 483 return EINVAL; 484 485 kbuf = memdup_user(ubuf, len); 486 if (IS_ERR(kbuf)) 487 return PTR_ERR(kbuf); 488 489 error = xfs_attr_set(XFS_I(inode), name, kbuf, len, flags); 490 491 return error; 492 } 493 494 int 495 xfs_attrmulti_attr_remove( 496 struct inode *inode, 497 unsigned char *name, 498 __uint32_t flags) 499 { 500 if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) 501 return EPERM; 502 return xfs_attr_remove(XFS_I(inode), name, flags); 503 } 504 505 STATIC int 506 xfs_attrmulti_by_handle( 507 struct file *parfilp, 508 void __user *arg) 509 { 510 int error; 511 xfs_attr_multiop_t *ops; 512 xfs_fsop_attrmulti_handlereq_t am_hreq; 513 struct dentry *dentry; 514 unsigned int i, size; 515 unsigned char *attr_name; 516 517 if (!capable(CAP_SYS_ADMIN)) 518 return -XFS_ERROR(EPERM); 519 if (copy_from_user(&am_hreq, arg, sizeof(xfs_fsop_attrmulti_handlereq_t))) 520 return -XFS_ERROR(EFAULT); 521 522 /* overflow check */ 523 if (am_hreq.opcount >= INT_MAX / sizeof(xfs_attr_multiop_t)) 524 return -E2BIG; 525 526 dentry = xfs_handlereq_to_dentry(parfilp, &am_hreq.hreq); 527 if (IS_ERR(dentry)) 528 return PTR_ERR(dentry); 529 530 error = E2BIG; 531 size = am_hreq.opcount * sizeof(xfs_attr_multiop_t); 532 if (!size || size > 16 * PAGE_SIZE) 533 goto out_dput; 534 535 ops = memdup_user(am_hreq.ops, size); 536 if (IS_ERR(ops)) { 537 error = PTR_ERR(ops); 538 goto out_dput; 539 } 540 541 attr_name = kmalloc(MAXNAMELEN, GFP_KERNEL); 542 if (!attr_name) 543 goto out_kfree_ops; 544 545 error = 0; 546 for (i = 0; i < am_hreq.opcount; i++) { 547 ops[i].am_error = strncpy_from_user((char *)attr_name, 548 ops[i].am_attrname, MAXNAMELEN); 549 if (ops[i].am_error == 0 || ops[i].am_error == MAXNAMELEN) 550 error = -ERANGE; 551 if (ops[i].am_error < 0) 552 break; 553 554 switch (ops[i].am_opcode) { 555 case ATTR_OP_GET: 556 ops[i].am_error = xfs_attrmulti_attr_get( 557 dentry->d_inode, attr_name, 558 ops[i].am_attrvalue, &ops[i].am_length, 559 ops[i].am_flags); 560 break; 561 case ATTR_OP_SET: 562 ops[i].am_error = mnt_want_write(parfilp->f_path.mnt); 563 if (ops[i].am_error) 564 break; 565 ops[i].am_error = xfs_attrmulti_attr_set( 566 dentry->d_inode, attr_name, 567 ops[i].am_attrvalue, ops[i].am_length, 568 ops[i].am_flags); 569 mnt_drop_write(parfilp->f_path.mnt); 570 break; 571 case ATTR_OP_REMOVE: 572 ops[i].am_error = mnt_want_write(parfilp->f_path.mnt); 573 if (ops[i].am_error) 574 break; 575 ops[i].am_error = xfs_attrmulti_attr_remove( 576 dentry->d_inode, attr_name, 577 ops[i].am_flags); 578 mnt_drop_write(parfilp->f_path.mnt); 579 break; 580 default: 581 ops[i].am_error = EINVAL; 582 } 583 } 584 585 if (copy_to_user(am_hreq.ops, ops, size)) 586 error = XFS_ERROR(EFAULT); 587 588 kfree(attr_name); 589 out_kfree_ops: 590 kfree(ops); 591 out_dput: 592 dput(dentry); 593 return -error; 594 } 595 596 int 597 xfs_ioc_space( 598 struct xfs_inode *ip, 599 struct inode *inode, 600 struct file *filp, 601 int ioflags, 602 unsigned int cmd, 603 xfs_flock64_t *bf) 604 { 605 int attr_flags = 0; 606 int error; 607 608 /* 609 * Only allow the sys admin to reserve space unless 610 * unwritten extents are enabled. 611 */ 612 if (!xfs_sb_version_hasextflgbit(&ip->i_mount->m_sb) && 613 !capable(CAP_SYS_ADMIN)) 614 return -XFS_ERROR(EPERM); 615 616 if (inode->i_flags & (S_IMMUTABLE|S_APPEND)) 617 return -XFS_ERROR(EPERM); 618 619 if (!(filp->f_mode & FMODE_WRITE)) 620 return -XFS_ERROR(EBADF); 621 622 if (!S_ISREG(inode->i_mode)) 623 return -XFS_ERROR(EINVAL); 624 625 if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) 626 attr_flags |= XFS_ATTR_NONBLOCK; 627 628 if (filp->f_flags & O_DSYNC) 629 attr_flags |= XFS_ATTR_SYNC; 630 631 if (ioflags & IO_INVIS) 632 attr_flags |= XFS_ATTR_DMI; 633 634 error = xfs_change_file_space(ip, cmd, bf, filp->f_pos, attr_flags); 635 return -error; 636 } 637 638 STATIC int 639 xfs_ioc_bulkstat( 640 xfs_mount_t *mp, 641 unsigned int cmd, 642 void __user *arg) 643 { 644 xfs_fsop_bulkreq_t bulkreq; 645 int count; /* # of records returned */ 646 xfs_ino_t inlast; /* last inode number */ 647 int done; 648 int error; 649 650 /* done = 1 if there are more stats to get and if bulkstat */ 651 /* should be called again (unused here, but used in dmapi) */ 652 653 if (!capable(CAP_SYS_ADMIN)) 654 return -EPERM; 655 656 if (XFS_FORCED_SHUTDOWN(mp)) 657 return -XFS_ERROR(EIO); 658 659 if (copy_from_user(&bulkreq, arg, sizeof(xfs_fsop_bulkreq_t))) 660 return -XFS_ERROR(EFAULT); 661 662 if (copy_from_user(&inlast, bulkreq.lastip, sizeof(__s64))) 663 return -XFS_ERROR(EFAULT); 664 665 if ((count = bulkreq.icount) <= 0) 666 return -XFS_ERROR(EINVAL); 667 668 if (bulkreq.ubuffer == NULL) 669 return -XFS_ERROR(EINVAL); 670 671 if (cmd == XFS_IOC_FSINUMBERS) 672 error = xfs_inumbers(mp, &inlast, &count, 673 bulkreq.ubuffer, xfs_inumbers_fmt); 674 else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE) 675 error = xfs_bulkstat_single(mp, &inlast, 676 bulkreq.ubuffer, &done); 677 else /* XFS_IOC_FSBULKSTAT */ 678 error = xfs_bulkstat(mp, &inlast, &count, xfs_bulkstat_one, 679 sizeof(xfs_bstat_t), bulkreq.ubuffer, 680 &done); 681 682 if (error) 683 return -error; 684 685 if (bulkreq.ocount != NULL) { 686 if (copy_to_user(bulkreq.lastip, &inlast, 687 sizeof(xfs_ino_t))) 688 return -XFS_ERROR(EFAULT); 689 690 if (copy_to_user(bulkreq.ocount, &count, sizeof(count))) 691 return -XFS_ERROR(EFAULT); 692 } 693 694 return 0; 695 } 696 697 STATIC int 698 xfs_ioc_fsgeometry_v1( 699 xfs_mount_t *mp, 700 void __user *arg) 701 { 702 xfs_fsop_geom_t fsgeo; 703 int error; 704 705 error = xfs_fs_geometry(mp, &fsgeo, 3); 706 if (error) 707 return -error; 708 709 /* 710 * Caller should have passed an argument of type 711 * xfs_fsop_geom_v1_t. This is a proper subset of the 712 * xfs_fsop_geom_t that xfs_fs_geometry() fills in. 713 */ 714 if (copy_to_user(arg, &fsgeo, sizeof(xfs_fsop_geom_v1_t))) 715 return -XFS_ERROR(EFAULT); 716 return 0; 717 } 718 719 STATIC int 720 xfs_ioc_fsgeometry( 721 xfs_mount_t *mp, 722 void __user *arg) 723 { 724 xfs_fsop_geom_t fsgeo; 725 int error; 726 727 error = xfs_fs_geometry(mp, &fsgeo, 4); 728 if (error) 729 return -error; 730 731 if (copy_to_user(arg, &fsgeo, sizeof(fsgeo))) 732 return -XFS_ERROR(EFAULT); 733 return 0; 734 } 735 736 /* 737 * Linux extended inode flags interface. 738 */ 739 740 STATIC unsigned int 741 xfs_merge_ioc_xflags( 742 unsigned int flags, 743 unsigned int start) 744 { 745 unsigned int xflags = start; 746 747 if (flags & FS_IMMUTABLE_FL) 748 xflags |= XFS_XFLAG_IMMUTABLE; 749 else 750 xflags &= ~XFS_XFLAG_IMMUTABLE; 751 if (flags & FS_APPEND_FL) 752 xflags |= XFS_XFLAG_APPEND; 753 else 754 xflags &= ~XFS_XFLAG_APPEND; 755 if (flags & FS_SYNC_FL) 756 xflags |= XFS_XFLAG_SYNC; 757 else 758 xflags &= ~XFS_XFLAG_SYNC; 759 if (flags & FS_NOATIME_FL) 760 xflags |= XFS_XFLAG_NOATIME; 761 else 762 xflags &= ~XFS_XFLAG_NOATIME; 763 if (flags & FS_NODUMP_FL) 764 xflags |= XFS_XFLAG_NODUMP; 765 else 766 xflags &= ~XFS_XFLAG_NODUMP; 767 768 return xflags; 769 } 770 771 STATIC unsigned int 772 xfs_di2lxflags( 773 __uint16_t di_flags) 774 { 775 unsigned int flags = 0; 776 777 if (di_flags & XFS_DIFLAG_IMMUTABLE) 778 flags |= FS_IMMUTABLE_FL; 779 if (di_flags & XFS_DIFLAG_APPEND) 780 flags |= FS_APPEND_FL; 781 if (di_flags & XFS_DIFLAG_SYNC) 782 flags |= FS_SYNC_FL; 783 if (di_flags & XFS_DIFLAG_NOATIME) 784 flags |= FS_NOATIME_FL; 785 if (di_flags & XFS_DIFLAG_NODUMP) 786 flags |= FS_NODUMP_FL; 787 return flags; 788 } 789 790 STATIC int 791 xfs_ioc_fsgetxattr( 792 xfs_inode_t *ip, 793 int attr, 794 void __user *arg) 795 { 796 struct fsxattr fa; 797 798 memset(&fa, 0, sizeof(struct fsxattr)); 799 800 xfs_ilock(ip, XFS_ILOCK_SHARED); 801 fa.fsx_xflags = xfs_ip2xflags(ip); 802 fa.fsx_extsize = ip->i_d.di_extsize << ip->i_mount->m_sb.sb_blocklog; 803 fa.fsx_projid = xfs_get_projid(ip); 804 805 if (attr) { 806 if (ip->i_afp) { 807 if (ip->i_afp->if_flags & XFS_IFEXTENTS) 808 fa.fsx_nextents = ip->i_afp->if_bytes / 809 sizeof(xfs_bmbt_rec_t); 810 else 811 fa.fsx_nextents = ip->i_d.di_anextents; 812 } else 813 fa.fsx_nextents = 0; 814 } else { 815 if (ip->i_df.if_flags & XFS_IFEXTENTS) 816 fa.fsx_nextents = ip->i_df.if_bytes / 817 sizeof(xfs_bmbt_rec_t); 818 else 819 fa.fsx_nextents = ip->i_d.di_nextents; 820 } 821 xfs_iunlock(ip, XFS_ILOCK_SHARED); 822 823 if (copy_to_user(arg, &fa, sizeof(fa))) 824 return -EFAULT; 825 return 0; 826 } 827 828 STATIC void 829 xfs_set_diflags( 830 struct xfs_inode *ip, 831 unsigned int xflags) 832 { 833 unsigned int di_flags; 834 835 /* can't set PREALLOC this way, just preserve it */ 836 di_flags = (ip->i_d.di_flags & XFS_DIFLAG_PREALLOC); 837 if (xflags & XFS_XFLAG_IMMUTABLE) 838 di_flags |= XFS_DIFLAG_IMMUTABLE; 839 if (xflags & XFS_XFLAG_APPEND) 840 di_flags |= XFS_DIFLAG_APPEND; 841 if (xflags & XFS_XFLAG_SYNC) 842 di_flags |= XFS_DIFLAG_SYNC; 843 if (xflags & XFS_XFLAG_NOATIME) 844 di_flags |= XFS_DIFLAG_NOATIME; 845 if (xflags & XFS_XFLAG_NODUMP) 846 di_flags |= XFS_DIFLAG_NODUMP; 847 if (xflags & XFS_XFLAG_PROJINHERIT) 848 di_flags |= XFS_DIFLAG_PROJINHERIT; 849 if (xflags & XFS_XFLAG_NODEFRAG) 850 di_flags |= XFS_DIFLAG_NODEFRAG; 851 if (xflags & XFS_XFLAG_FILESTREAM) 852 di_flags |= XFS_DIFLAG_FILESTREAM; 853 if (S_ISDIR(ip->i_d.di_mode)) { 854 if (xflags & XFS_XFLAG_RTINHERIT) 855 di_flags |= XFS_DIFLAG_RTINHERIT; 856 if (xflags & XFS_XFLAG_NOSYMLINKS) 857 di_flags |= XFS_DIFLAG_NOSYMLINKS; 858 if (xflags & XFS_XFLAG_EXTSZINHERIT) 859 di_flags |= XFS_DIFLAG_EXTSZINHERIT; 860 } else if (S_ISREG(ip->i_d.di_mode)) { 861 if (xflags & XFS_XFLAG_REALTIME) 862 di_flags |= XFS_DIFLAG_REALTIME; 863 if (xflags & XFS_XFLAG_EXTSIZE) 864 di_flags |= XFS_DIFLAG_EXTSIZE; 865 } 866 867 ip->i_d.di_flags = di_flags; 868 } 869 870 STATIC void 871 xfs_diflags_to_linux( 872 struct xfs_inode *ip) 873 { 874 struct inode *inode = VFS_I(ip); 875 unsigned int xflags = xfs_ip2xflags(ip); 876 877 if (xflags & XFS_XFLAG_IMMUTABLE) 878 inode->i_flags |= S_IMMUTABLE; 879 else 880 inode->i_flags &= ~S_IMMUTABLE; 881 if (xflags & XFS_XFLAG_APPEND) 882 inode->i_flags |= S_APPEND; 883 else 884 inode->i_flags &= ~S_APPEND; 885 if (xflags & XFS_XFLAG_SYNC) 886 inode->i_flags |= S_SYNC; 887 else 888 inode->i_flags &= ~S_SYNC; 889 if (xflags & XFS_XFLAG_NOATIME) 890 inode->i_flags |= S_NOATIME; 891 else 892 inode->i_flags &= ~S_NOATIME; 893 } 894 895 #define FSX_PROJID 1 896 #define FSX_EXTSIZE 2 897 #define FSX_XFLAGS 4 898 #define FSX_NONBLOCK 8 899 900 STATIC int 901 xfs_ioctl_setattr( 902 xfs_inode_t *ip, 903 struct fsxattr *fa, 904 int mask) 905 { 906 struct xfs_mount *mp = ip->i_mount; 907 struct xfs_trans *tp; 908 unsigned int lock_flags = 0; 909 struct xfs_dquot *udqp = NULL; 910 struct xfs_dquot *gdqp = NULL; 911 struct xfs_dquot *olddquot = NULL; 912 int code; 913 914 trace_xfs_ioctl_setattr(ip); 915 916 if (mp->m_flags & XFS_MOUNT_RDONLY) 917 return XFS_ERROR(EROFS); 918 if (XFS_FORCED_SHUTDOWN(mp)) 919 return XFS_ERROR(EIO); 920 921 /* 922 * Disallow 32bit project ids when projid32bit feature is not enabled. 923 */ 924 if ((mask & FSX_PROJID) && (fa->fsx_projid > (__uint16_t)-1) && 925 !xfs_sb_version_hasprojid32bit(&ip->i_mount->m_sb)) 926 return XFS_ERROR(EINVAL); 927 928 /* 929 * If disk quotas is on, we make sure that the dquots do exist on disk, 930 * before we start any other transactions. Trying to do this later 931 * is messy. We don't care to take a readlock to look at the ids 932 * in inode here, because we can't hold it across the trans_reserve. 933 * If the IDs do change before we take the ilock, we're covered 934 * because the i_*dquot fields will get updated anyway. 935 */ 936 if (XFS_IS_QUOTA_ON(mp) && (mask & FSX_PROJID)) { 937 code = xfs_qm_vop_dqalloc(ip, ip->i_d.di_uid, 938 ip->i_d.di_gid, fa->fsx_projid, 939 XFS_QMOPT_PQUOTA, &udqp, &gdqp); 940 if (code) 941 return code; 942 } 943 944 /* 945 * For the other attributes, we acquire the inode lock and 946 * first do an error checking pass. 947 */ 948 tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_NOT_SIZE); 949 code = xfs_trans_reserve(tp, 0, XFS_ICHANGE_LOG_RES(mp), 0, 0, 0); 950 if (code) 951 goto error_return; 952 953 lock_flags = XFS_ILOCK_EXCL; 954 xfs_ilock(ip, lock_flags); 955 956 /* 957 * CAP_FOWNER overrides the following restrictions: 958 * 959 * The user ID of the calling process must be equal 960 * to the file owner ID, except in cases where the 961 * CAP_FSETID capability is applicable. 962 */ 963 if (current_fsuid() != ip->i_d.di_uid && !capable(CAP_FOWNER)) { 964 code = XFS_ERROR(EPERM); 965 goto error_return; 966 } 967 968 /* 969 * Do a quota reservation only if projid is actually going to change. 970 */ 971 if (mask & FSX_PROJID) { 972 if (XFS_IS_QUOTA_RUNNING(mp) && 973 XFS_IS_PQUOTA_ON(mp) && 974 xfs_get_projid(ip) != fa->fsx_projid) { 975 ASSERT(tp); 976 code = xfs_qm_vop_chown_reserve(tp, ip, udqp, gdqp, 977 capable(CAP_FOWNER) ? 978 XFS_QMOPT_FORCE_RES : 0); 979 if (code) /* out of quota */ 980 goto error_return; 981 } 982 } 983 984 if (mask & FSX_EXTSIZE) { 985 /* 986 * Can't change extent size if any extents are allocated. 987 */ 988 if (ip->i_d.di_nextents && 989 ((ip->i_d.di_extsize << mp->m_sb.sb_blocklog) != 990 fa->fsx_extsize)) { 991 code = XFS_ERROR(EINVAL); /* EFBIG? */ 992 goto error_return; 993 } 994 995 /* 996 * Extent size must be a multiple of the appropriate block 997 * size, if set at all. It must also be smaller than the 998 * maximum extent size supported by the filesystem. 999 * 1000 * Also, for non-realtime files, limit the extent size hint to 1001 * half the size of the AGs in the filesystem so alignment 1002 * doesn't result in extents larger than an AG. 1003 */ 1004 if (fa->fsx_extsize != 0) { 1005 xfs_extlen_t size; 1006 xfs_fsblock_t extsize_fsb; 1007 1008 extsize_fsb = XFS_B_TO_FSB(mp, fa->fsx_extsize); 1009 if (extsize_fsb > MAXEXTLEN) { 1010 code = XFS_ERROR(EINVAL); 1011 goto error_return; 1012 } 1013 1014 if (XFS_IS_REALTIME_INODE(ip) || 1015 ((mask & FSX_XFLAGS) && 1016 (fa->fsx_xflags & XFS_XFLAG_REALTIME))) { 1017 size = mp->m_sb.sb_rextsize << 1018 mp->m_sb.sb_blocklog; 1019 } else { 1020 size = mp->m_sb.sb_blocksize; 1021 if (extsize_fsb > mp->m_sb.sb_agblocks / 2) { 1022 code = XFS_ERROR(EINVAL); 1023 goto error_return; 1024 } 1025 } 1026 1027 if (fa->fsx_extsize % size) { 1028 code = XFS_ERROR(EINVAL); 1029 goto error_return; 1030 } 1031 } 1032 } 1033 1034 1035 if (mask & FSX_XFLAGS) { 1036 /* 1037 * Can't change realtime flag if any extents are allocated. 1038 */ 1039 if ((ip->i_d.di_nextents || ip->i_delayed_blks) && 1040 (XFS_IS_REALTIME_INODE(ip)) != 1041 (fa->fsx_xflags & XFS_XFLAG_REALTIME)) { 1042 code = XFS_ERROR(EINVAL); /* EFBIG? */ 1043 goto error_return; 1044 } 1045 1046 /* 1047 * If realtime flag is set then must have realtime data. 1048 */ 1049 if ((fa->fsx_xflags & XFS_XFLAG_REALTIME)) { 1050 if ((mp->m_sb.sb_rblocks == 0) || 1051 (mp->m_sb.sb_rextsize == 0) || 1052 (ip->i_d.di_extsize % mp->m_sb.sb_rextsize)) { 1053 code = XFS_ERROR(EINVAL); 1054 goto error_return; 1055 } 1056 } 1057 1058 /* 1059 * Can't modify an immutable/append-only file unless 1060 * we have appropriate permission. 1061 */ 1062 if ((ip->i_d.di_flags & 1063 (XFS_DIFLAG_IMMUTABLE|XFS_DIFLAG_APPEND) || 1064 (fa->fsx_xflags & 1065 (XFS_XFLAG_IMMUTABLE | XFS_XFLAG_APPEND))) && 1066 !capable(CAP_LINUX_IMMUTABLE)) { 1067 code = XFS_ERROR(EPERM); 1068 goto error_return; 1069 } 1070 } 1071 1072 xfs_trans_ijoin(tp, ip, 0); 1073 1074 /* 1075 * Change file ownership. Must be the owner or privileged. 1076 */ 1077 if (mask & FSX_PROJID) { 1078 /* 1079 * CAP_FSETID overrides the following restrictions: 1080 * 1081 * The set-user-ID and set-group-ID bits of a file will be 1082 * cleared upon successful return from chown() 1083 */ 1084 if ((ip->i_d.di_mode & (S_ISUID|S_ISGID)) && 1085 !capable(CAP_FSETID)) 1086 ip->i_d.di_mode &= ~(S_ISUID|S_ISGID); 1087 1088 /* 1089 * Change the ownerships and register quota modifications 1090 * in the transaction. 1091 */ 1092 if (xfs_get_projid(ip) != fa->fsx_projid) { 1093 if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_PQUOTA_ON(mp)) { 1094 olddquot = xfs_qm_vop_chown(tp, ip, 1095 &ip->i_gdquot, gdqp); 1096 } 1097 xfs_set_projid(ip, fa->fsx_projid); 1098 1099 /* 1100 * We may have to rev the inode as well as 1101 * the superblock version number since projids didn't 1102 * exist before DINODE_VERSION_2 and SB_VERSION_NLINK. 1103 */ 1104 if (ip->i_d.di_version == 1) 1105 xfs_bump_ino_vers2(tp, ip); 1106 } 1107 1108 } 1109 1110 if (mask & FSX_EXTSIZE) 1111 ip->i_d.di_extsize = fa->fsx_extsize >> mp->m_sb.sb_blocklog; 1112 if (mask & FSX_XFLAGS) { 1113 xfs_set_diflags(ip, fa->fsx_xflags); 1114 xfs_diflags_to_linux(ip); 1115 } 1116 1117 xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG); 1118 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); 1119 1120 XFS_STATS_INC(xs_ig_attrchg); 1121 1122 /* 1123 * If this is a synchronous mount, make sure that the 1124 * transaction goes to disk before returning to the user. 1125 * This is slightly sub-optimal in that truncates require 1126 * two sync transactions instead of one for wsync filesystems. 1127 * One for the truncate and one for the timestamps since we 1128 * don't want to change the timestamps unless we're sure the 1129 * truncate worked. Truncates are less than 1% of the laddis 1130 * mix so this probably isn't worth the trouble to optimize. 1131 */ 1132 if (mp->m_flags & XFS_MOUNT_WSYNC) 1133 xfs_trans_set_sync(tp); 1134 code = xfs_trans_commit(tp, 0); 1135 xfs_iunlock(ip, lock_flags); 1136 1137 /* 1138 * Release any dquot(s) the inode had kept before chown. 1139 */ 1140 xfs_qm_dqrele(olddquot); 1141 xfs_qm_dqrele(udqp); 1142 xfs_qm_dqrele(gdqp); 1143 1144 return code; 1145 1146 error_return: 1147 xfs_qm_dqrele(udqp); 1148 xfs_qm_dqrele(gdqp); 1149 xfs_trans_cancel(tp, 0); 1150 if (lock_flags) 1151 xfs_iunlock(ip, lock_flags); 1152 return code; 1153 } 1154 1155 STATIC int 1156 xfs_ioc_fssetxattr( 1157 xfs_inode_t *ip, 1158 struct file *filp, 1159 void __user *arg) 1160 { 1161 struct fsxattr fa; 1162 unsigned int mask; 1163 1164 if (copy_from_user(&fa, arg, sizeof(fa))) 1165 return -EFAULT; 1166 1167 mask = FSX_XFLAGS | FSX_EXTSIZE | FSX_PROJID; 1168 if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) 1169 mask |= FSX_NONBLOCK; 1170 1171 return -xfs_ioctl_setattr(ip, &fa, mask); 1172 } 1173 1174 STATIC int 1175 xfs_ioc_getxflags( 1176 xfs_inode_t *ip, 1177 void __user *arg) 1178 { 1179 unsigned int flags; 1180 1181 flags = xfs_di2lxflags(ip->i_d.di_flags); 1182 if (copy_to_user(arg, &flags, sizeof(flags))) 1183 return -EFAULT; 1184 return 0; 1185 } 1186 1187 STATIC int 1188 xfs_ioc_setxflags( 1189 xfs_inode_t *ip, 1190 struct file *filp, 1191 void __user *arg) 1192 { 1193 struct fsxattr fa; 1194 unsigned int flags; 1195 unsigned int mask; 1196 1197 if (copy_from_user(&flags, arg, sizeof(flags))) 1198 return -EFAULT; 1199 1200 if (flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL | \ 1201 FS_NOATIME_FL | FS_NODUMP_FL | \ 1202 FS_SYNC_FL)) 1203 return -EOPNOTSUPP; 1204 1205 mask = FSX_XFLAGS; 1206 if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) 1207 mask |= FSX_NONBLOCK; 1208 fa.fsx_xflags = xfs_merge_ioc_xflags(flags, xfs_ip2xflags(ip)); 1209 1210 return -xfs_ioctl_setattr(ip, &fa, mask); 1211 } 1212 1213 STATIC int 1214 xfs_getbmap_format(void **ap, struct getbmapx *bmv, int *full) 1215 { 1216 struct getbmap __user *base = *ap; 1217 1218 /* copy only getbmap portion (not getbmapx) */ 1219 if (copy_to_user(base, bmv, sizeof(struct getbmap))) 1220 return XFS_ERROR(EFAULT); 1221 1222 *ap += sizeof(struct getbmap); 1223 return 0; 1224 } 1225 1226 STATIC int 1227 xfs_ioc_getbmap( 1228 struct xfs_inode *ip, 1229 int ioflags, 1230 unsigned int cmd, 1231 void __user *arg) 1232 { 1233 struct getbmapx bmx; 1234 int error; 1235 1236 if (copy_from_user(&bmx, arg, sizeof(struct getbmapx))) 1237 return -XFS_ERROR(EFAULT); 1238 1239 if (bmx.bmv_count < 2) 1240 return -XFS_ERROR(EINVAL); 1241 1242 bmx.bmv_iflags = (cmd == XFS_IOC_GETBMAPA ? BMV_IF_ATTRFORK : 0); 1243 if (ioflags & IO_INVIS) 1244 bmx.bmv_iflags |= BMV_IF_NO_DMAPI_READ; 1245 1246 error = xfs_getbmap(ip, &bmx, xfs_getbmap_format, 1247 (struct getbmap *)arg+1); 1248 if (error) 1249 return -error; 1250 1251 /* copy back header - only size of getbmap */ 1252 if (copy_to_user(arg, &bmx, sizeof(struct getbmap))) 1253 return -XFS_ERROR(EFAULT); 1254 return 0; 1255 } 1256 1257 STATIC int 1258 xfs_getbmapx_format(void **ap, struct getbmapx *bmv, int *full) 1259 { 1260 struct getbmapx __user *base = *ap; 1261 1262 if (copy_to_user(base, bmv, sizeof(struct getbmapx))) 1263 return XFS_ERROR(EFAULT); 1264 1265 *ap += sizeof(struct getbmapx); 1266 return 0; 1267 } 1268 1269 STATIC int 1270 xfs_ioc_getbmapx( 1271 struct xfs_inode *ip, 1272 void __user *arg) 1273 { 1274 struct getbmapx bmx; 1275 int error; 1276 1277 if (copy_from_user(&bmx, arg, sizeof(bmx))) 1278 return -XFS_ERROR(EFAULT); 1279 1280 if (bmx.bmv_count < 2) 1281 return -XFS_ERROR(EINVAL); 1282 1283 if (bmx.bmv_iflags & (~BMV_IF_VALID)) 1284 return -XFS_ERROR(EINVAL); 1285 1286 error = xfs_getbmap(ip, &bmx, xfs_getbmapx_format, 1287 (struct getbmapx *)arg+1); 1288 if (error) 1289 return -error; 1290 1291 /* copy back header */ 1292 if (copy_to_user(arg, &bmx, sizeof(struct getbmapx))) 1293 return -XFS_ERROR(EFAULT); 1294 1295 return 0; 1296 } 1297 1298 /* 1299 * Note: some of the ioctl's return positive numbers as a 1300 * byte count indicating success, such as readlink_by_handle. 1301 * So we don't "sign flip" like most other routines. This means 1302 * true errors need to be returned as a negative value. 1303 */ 1304 long 1305 xfs_file_ioctl( 1306 struct file *filp, 1307 unsigned int cmd, 1308 unsigned long p) 1309 { 1310 struct inode *inode = filp->f_path.dentry->d_inode; 1311 struct xfs_inode *ip = XFS_I(inode); 1312 struct xfs_mount *mp = ip->i_mount; 1313 void __user *arg = (void __user *)p; 1314 int ioflags = 0; 1315 int error; 1316 1317 if (filp->f_mode & FMODE_NOCMTIME) 1318 ioflags |= IO_INVIS; 1319 1320 trace_xfs_file_ioctl(ip); 1321 1322 switch (cmd) { 1323 case FITRIM: 1324 return xfs_ioc_trim(mp, arg); 1325 case XFS_IOC_ALLOCSP: 1326 case XFS_IOC_FREESP: 1327 case XFS_IOC_RESVSP: 1328 case XFS_IOC_UNRESVSP: 1329 case XFS_IOC_ALLOCSP64: 1330 case XFS_IOC_FREESP64: 1331 case XFS_IOC_RESVSP64: 1332 case XFS_IOC_UNRESVSP64: 1333 case XFS_IOC_ZERO_RANGE: { 1334 xfs_flock64_t bf; 1335 1336 if (copy_from_user(&bf, arg, sizeof(bf))) 1337 return -XFS_ERROR(EFAULT); 1338 return xfs_ioc_space(ip, inode, filp, ioflags, cmd, &bf); 1339 } 1340 case XFS_IOC_DIOINFO: { 1341 struct dioattr da; 1342 xfs_buftarg_t *target = 1343 XFS_IS_REALTIME_INODE(ip) ? 1344 mp->m_rtdev_targp : mp->m_ddev_targp; 1345 1346 da.d_mem = da.d_miniosz = 1 << target->bt_sshift; 1347 da.d_maxiosz = INT_MAX & ~(da.d_miniosz - 1); 1348 1349 if (copy_to_user(arg, &da, sizeof(da))) 1350 return -XFS_ERROR(EFAULT); 1351 return 0; 1352 } 1353 1354 case XFS_IOC_FSBULKSTAT_SINGLE: 1355 case XFS_IOC_FSBULKSTAT: 1356 case XFS_IOC_FSINUMBERS: 1357 return xfs_ioc_bulkstat(mp, cmd, arg); 1358 1359 case XFS_IOC_FSGEOMETRY_V1: 1360 return xfs_ioc_fsgeometry_v1(mp, arg); 1361 1362 case XFS_IOC_FSGEOMETRY: 1363 return xfs_ioc_fsgeometry(mp, arg); 1364 1365 case XFS_IOC_GETVERSION: 1366 return put_user(inode->i_generation, (int __user *)arg); 1367 1368 case XFS_IOC_FSGETXATTR: 1369 return xfs_ioc_fsgetxattr(ip, 0, arg); 1370 case XFS_IOC_FSGETXATTRA: 1371 return xfs_ioc_fsgetxattr(ip, 1, arg); 1372 case XFS_IOC_FSSETXATTR: 1373 return xfs_ioc_fssetxattr(ip, filp, arg); 1374 case XFS_IOC_GETXFLAGS: 1375 return xfs_ioc_getxflags(ip, arg); 1376 case XFS_IOC_SETXFLAGS: 1377 return xfs_ioc_setxflags(ip, filp, arg); 1378 1379 case XFS_IOC_FSSETDM: { 1380 struct fsdmidata dmi; 1381 1382 if (copy_from_user(&dmi, arg, sizeof(dmi))) 1383 return -XFS_ERROR(EFAULT); 1384 1385 error = xfs_set_dmattrs(ip, dmi.fsd_dmevmask, 1386 dmi.fsd_dmstate); 1387 return -error; 1388 } 1389 1390 case XFS_IOC_GETBMAP: 1391 case XFS_IOC_GETBMAPA: 1392 return xfs_ioc_getbmap(ip, ioflags, cmd, arg); 1393 1394 case XFS_IOC_GETBMAPX: 1395 return xfs_ioc_getbmapx(ip, arg); 1396 1397 case XFS_IOC_FD_TO_HANDLE: 1398 case XFS_IOC_PATH_TO_HANDLE: 1399 case XFS_IOC_PATH_TO_FSHANDLE: { 1400 xfs_fsop_handlereq_t hreq; 1401 1402 if (copy_from_user(&hreq, arg, sizeof(hreq))) 1403 return -XFS_ERROR(EFAULT); 1404 return xfs_find_handle(cmd, &hreq); 1405 } 1406 case XFS_IOC_OPEN_BY_HANDLE: { 1407 xfs_fsop_handlereq_t hreq; 1408 1409 if (copy_from_user(&hreq, arg, sizeof(xfs_fsop_handlereq_t))) 1410 return -XFS_ERROR(EFAULT); 1411 return xfs_open_by_handle(filp, &hreq); 1412 } 1413 case XFS_IOC_FSSETDM_BY_HANDLE: 1414 return xfs_fssetdm_by_handle(filp, arg); 1415 1416 case XFS_IOC_READLINK_BY_HANDLE: { 1417 xfs_fsop_handlereq_t hreq; 1418 1419 if (copy_from_user(&hreq, arg, sizeof(xfs_fsop_handlereq_t))) 1420 return -XFS_ERROR(EFAULT); 1421 return xfs_readlink_by_handle(filp, &hreq); 1422 } 1423 case XFS_IOC_ATTRLIST_BY_HANDLE: 1424 return xfs_attrlist_by_handle(filp, arg); 1425 1426 case XFS_IOC_ATTRMULTI_BY_HANDLE: 1427 return xfs_attrmulti_by_handle(filp, arg); 1428 1429 case XFS_IOC_SWAPEXT: { 1430 struct xfs_swapext sxp; 1431 1432 if (copy_from_user(&sxp, arg, sizeof(xfs_swapext_t))) 1433 return -XFS_ERROR(EFAULT); 1434 error = xfs_swapext(&sxp); 1435 return -error; 1436 } 1437 1438 case XFS_IOC_FSCOUNTS: { 1439 xfs_fsop_counts_t out; 1440 1441 error = xfs_fs_counts(mp, &out); 1442 if (error) 1443 return -error; 1444 1445 if (copy_to_user(arg, &out, sizeof(out))) 1446 return -XFS_ERROR(EFAULT); 1447 return 0; 1448 } 1449 1450 case XFS_IOC_SET_RESBLKS: { 1451 xfs_fsop_resblks_t inout; 1452 __uint64_t in; 1453 1454 if (!capable(CAP_SYS_ADMIN)) 1455 return -EPERM; 1456 1457 if (mp->m_flags & XFS_MOUNT_RDONLY) 1458 return -XFS_ERROR(EROFS); 1459 1460 if (copy_from_user(&inout, arg, sizeof(inout))) 1461 return -XFS_ERROR(EFAULT); 1462 1463 /* input parameter is passed in resblks field of structure */ 1464 in = inout.resblks; 1465 error = xfs_reserve_blocks(mp, &in, &inout); 1466 if (error) 1467 return -error; 1468 1469 if (copy_to_user(arg, &inout, sizeof(inout))) 1470 return -XFS_ERROR(EFAULT); 1471 return 0; 1472 } 1473 1474 case XFS_IOC_GET_RESBLKS: { 1475 xfs_fsop_resblks_t out; 1476 1477 if (!capable(CAP_SYS_ADMIN)) 1478 return -EPERM; 1479 1480 error = xfs_reserve_blocks(mp, NULL, &out); 1481 if (error) 1482 return -error; 1483 1484 if (copy_to_user(arg, &out, sizeof(out))) 1485 return -XFS_ERROR(EFAULT); 1486 1487 return 0; 1488 } 1489 1490 case XFS_IOC_FSGROWFSDATA: { 1491 xfs_growfs_data_t in; 1492 1493 if (copy_from_user(&in, arg, sizeof(in))) 1494 return -XFS_ERROR(EFAULT); 1495 1496 error = xfs_growfs_data(mp, &in); 1497 return -error; 1498 } 1499 1500 case XFS_IOC_FSGROWFSLOG: { 1501 xfs_growfs_log_t in; 1502 1503 if (copy_from_user(&in, arg, sizeof(in))) 1504 return -XFS_ERROR(EFAULT); 1505 1506 error = xfs_growfs_log(mp, &in); 1507 return -error; 1508 } 1509 1510 case XFS_IOC_FSGROWFSRT: { 1511 xfs_growfs_rt_t in; 1512 1513 if (copy_from_user(&in, arg, sizeof(in))) 1514 return -XFS_ERROR(EFAULT); 1515 1516 error = xfs_growfs_rt(mp, &in); 1517 return -error; 1518 } 1519 1520 case XFS_IOC_GOINGDOWN: { 1521 __uint32_t in; 1522 1523 if (!capable(CAP_SYS_ADMIN)) 1524 return -EPERM; 1525 1526 if (get_user(in, (__uint32_t __user *)arg)) 1527 return -XFS_ERROR(EFAULT); 1528 1529 error = xfs_fs_goingdown(mp, in); 1530 return -error; 1531 } 1532 1533 case XFS_IOC_ERROR_INJECTION: { 1534 xfs_error_injection_t in; 1535 1536 if (!capable(CAP_SYS_ADMIN)) 1537 return -EPERM; 1538 1539 if (copy_from_user(&in, arg, sizeof(in))) 1540 return -XFS_ERROR(EFAULT); 1541 1542 error = xfs_errortag_add(in.errtag, mp); 1543 return -error; 1544 } 1545 1546 case XFS_IOC_ERROR_CLEARALL: 1547 if (!capable(CAP_SYS_ADMIN)) 1548 return -EPERM; 1549 1550 error = xfs_errortag_clearall(mp, 1); 1551 return -error; 1552 1553 default: 1554 return -ENOTTY; 1555 } 1556 } 1557