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