xfs_ioctl.c revision 153323
1/* 2 * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms of version 2 of the GNU General Public License as 6 * published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it would be useful, but 9 * WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 11 * 12 * Further, this software is distributed without any warranty that it is 13 * free of the rightful claim of any third person regarding infringement 14 * or the like. Any license provided herein, whether implied or 15 * otherwise, applies only to this software file. Patent licenses, if 16 * any, provided herein do not apply to combinations of this program with 17 * other software, or any other product whatsoever. 18 * 19 * You should have received a copy of the GNU General Public License along 20 * with this program; if not, write the Free Software Foundation, Inc., 59 21 * Temple Place - Suite 330, Boston MA 02111-1307, USA. 22 * 23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, 24 * Mountain View, CA 94043, or: 25 * 26 * http://www.sgi.com 27 * 28 * For further information regarding this notice, see: 29 * 30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ 31 */ 32 33#include "xfs.h" 34 35#include "xfs_fs.h" 36#include "xfs_inum.h" 37#include "xfs_log.h" 38#include "xfs_trans.h" 39#include "xfs_sb.h" 40#include "xfs_dir.h" 41#include "xfs_dir2.h" 42#include "xfs_alloc.h" 43#include "xfs_dmapi.h" 44#include "xfs_mount.h" 45#include "xfs_alloc_btree.h" 46#include "xfs_bmap_btree.h" 47#include "xfs_ialloc_btree.h" 48#include "xfs_btree.h" 49#include "xfs_ialloc.h" 50#include "xfs_attr_sf.h" 51#include "xfs_dir_sf.h" 52#include "xfs_dir2_sf.h" 53#include "xfs_dinode.h" 54#include "xfs_inode.h" 55#include "xfs_bmap.h" 56#include "xfs_bit.h" 57#include "xfs_rtalloc.h" 58#include "xfs_error.h" 59#include "xfs_itable.h" 60#include "xfs_rw.h" 61#include "xfs_acl.h" 62#include "xfs_cap.h" 63#include "xfs_mac.h" 64#include "xfs_attr.h" 65#include "xfs_buf_item.h" 66#include "xfs_utils.h" 67#include "xfs_dfrag.h" 68#include "xfs_fsops.h" 69 70 71#if XXXKAN 72/* 73 * ioctl commands that are used by Linux filesystems 74 */ 75#define XFS_IOC_GETXFLAGS _IOR('f', 1, long) 76#define XFS_IOC_SETXFLAGS _IOW('f', 2, long) 77#define XFS_IOC_GETVERSION _IOR('v', 1, long) 78 79 80/* 81 * xfs_find_handle maps from userspace xfs_fsop_handlereq structure to 82 * a file or fs handle. 83 * 84 * XFS_IOC_PATH_TO_FSHANDLE 85 * returns fs handle for a mount point or path within that mount point 86 * XFS_IOC_FD_TO_HANDLE 87 * returns full handle for a FD opened in user space 88 * XFS_IOC_PATH_TO_HANDLE 89 * returns full handle for a path 90 */ 91STATIC int 92xfs_find_handle( 93 unsigned int cmd, 94 unsigned long arg) 95{ 96 int hsize; 97 xfs_handle_t handle; 98 xfs_fsop_handlereq_t hreq; 99 struct xfs_vnode *vp; 100 struct thread *td = curthread; 101 102 if (copy_from_user(&hreq, (xfs_fsop_handlereq_t *)arg, sizeof(hreq))) 103 return XFS_ERROR(EFAULT); 104 105 memset((char *)&handle, 0, sizeof(handle)); 106 107 switch (cmd) { 108 case XFS_IOC_PATH_TO_FSHANDLE: 109 case XFS_IOC_PATH_TO_HANDLE: { 110 struct nameidata nd; 111 int error; 112 113 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, 114 UIO_USERSPACE, hreq.path, td); 115 error = namei(&nd); 116 if (error) 117 return error; 118 NDFREE(&nd, NDF_ONLY_PNBUF); 119 break; 120 } 121 122 case XFS_IOC_FD_TO_HANDLE: { 123 struct file *file; 124 125 error = getvnode(td->td_proc->p_fd, hreq.fd, &file); 126 if (error) 127 return error; 128 129 error = vget(vp, LK_EXCLUSIVE, td); 130 if (error) { 131 fdrop(file); 132 return error; 133 } 134 fdrop(file); 135 break; 136 } 137 138 default: 139 ASSERT(0); 140 return XFS_ERROR(EINVAL); 141 } 142 143 if (inode->i_sb->s_magic != XFS_SB_MAGIC) { 144 /* we're not in XFS anymore, Toto */ 145 iput(inode); 146 return XFS_ERROR(EINVAL); 147 } 148 149 /* we need the vnode */ 150 vp = LINVFS_GET_VP(inode); 151 if (vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK) { 152 iput(inode); 153 return XFS_ERROR(EBADF); 154 } 155 156 /* now we can grab the fsid */ 157 memcpy(&handle.ha_fsid, vp->v_vfsp->vfs_altfsid, sizeof(xfs_fsid_t)); 158 hsize = sizeof(xfs_fsid_t); 159 160 if (cmd != XFS_IOC_PATH_TO_FSHANDLE) { 161 xfs_inode_t *ip; 162 bhv_desc_t *bhv; 163 int lock_mode; 164 165 /* need to get access to the xfs_inode to read the generation */ 166 bhv = vn_bhv_lookup_unlocked(VN_BHV_HEAD(vp), &xfs_vnodeops); 167 ASSERT(bhv); 168 ip = XFS_BHVTOI(bhv); 169 ASSERT(ip); 170 lock_mode = xfs_ilock_map_shared(ip); 171 172 /* fill in fid section of handle from inode */ 173 handle.ha_fid.xfs_fid_len = sizeof(xfs_fid_t) - 174 sizeof(handle.ha_fid.xfs_fid_len); 175 handle.ha_fid.xfs_fid_pad = 0; 176 handle.ha_fid.xfs_fid_gen = ip->i_d.di_gen; 177 handle.ha_fid.xfs_fid_ino = ip->i_ino; 178 179 xfs_iunlock_map_shared(ip, lock_mode); 180 181 hsize = XFS_HSIZE(handle); 182 } 183 184 /* now copy our handle into the user buffer & write out the size */ 185 if (copy_to_user((xfs_handle_t *)hreq.ohandle, &handle, hsize) || 186 copy_to_user(hreq.ohandlen, &hsize, sizeof(__s32))) { 187 iput(inode); 188 return -XFS_ERROR(EFAULT); 189 } 190 191 iput(inode); 192 return 0; 193} 194 195 196/* 197 * Convert userspace handle data into vnode (and inode). 198 * We [ab]use the fact that all the fsop_handlereq ioctl calls 199 * have a data structure argument whose first component is always 200 * a xfs_fsop_handlereq_t, so we can cast to and from this type. 201 * This allows us to optimise the copy_from_user calls and gives 202 * a handy, shared routine. 203 * 204 * If no error, caller must always VN_RELE the returned vp. 205 */ 206STATIC int 207xfs_vget_fsop_handlereq( 208 xfs_mount_t *mp, 209 struct inode *parinode, /* parent inode pointer */ 210 int cap, /* capability level for op */ 211 unsigned long arg, /* userspace data pointer */ 212 unsigned long size, /* size of expected struct */ 213 /* output arguments */ 214 xfs_fsop_handlereq_t *hreq, 215 vnode_t **vp, 216 struct inode **inode) 217{ 218 void *hanp; 219 size_t hlen; 220 xfs_fid_t *xfid; 221 xfs_handle_t *handlep; 222 xfs_handle_t handle; 223 xfs_inode_t *ip; 224 struct inode *inodep; 225 vnode_t *vpp; 226 xfs_ino_t ino; 227 __u32 igen; 228 int error; 229 230 if (!capable(cap)) 231 return XFS_ERROR(EPERM); 232 233 /* 234 * Only allow handle opens under a directory. 235 */ 236 if (!S_ISDIR(parinode->i_mode)) 237 return XFS_ERROR(ENOTDIR); 238 239 /* 240 * Copy the handle down from the user and validate 241 * that it looks to be in the correct format. 242 */ 243 if (copy_from_user(hreq, (struct xfs_fsop_handlereq *)arg, size)) 244 return XFS_ERROR(EFAULT); 245 246 hanp = hreq->ihandle; 247 hlen = hreq->ihandlen; 248 handlep = &handle; 249 250 if (hlen < sizeof(handlep->ha_fsid) || hlen > sizeof(*handlep)) 251 return XFS_ERROR(EINVAL); 252 if (copy_from_user(handlep, hanp, hlen)) 253 return XFS_ERROR(EFAULT); 254 if (hlen < sizeof(*handlep)) 255 memset(((char *)handlep) + hlen, 0, sizeof(*handlep) - hlen); 256 if (hlen > sizeof(handlep->ha_fsid)) { 257 if (handlep->ha_fid.xfs_fid_len != 258 (hlen - sizeof(handlep->ha_fsid) 259 - sizeof(handlep->ha_fid.xfs_fid_len)) 260 || handlep->ha_fid.xfs_fid_pad) 261 return XFS_ERROR(EINVAL); 262 } 263 264 /* 265 * Crack the handle, obtain the inode # & generation # 266 */ 267 xfid = (struct xfs_fid *)&handlep->ha_fid; 268 if (xfid->xfs_fid_len == sizeof(*xfid) - sizeof(xfid->xfs_fid_len)) { 269 ino = xfid->xfs_fid_ino; 270 igen = xfid->xfs_fid_gen; 271 } else { 272 return XFS_ERROR(EINVAL); 273 } 274 275 /* 276 * Get the XFS inode, building a vnode to go with it. 277 */ 278 error = xfs_iget(mp, NULL, ino, XFS_ILOCK_SHARED, &ip, 0); 279 if (error) 280 return error; 281 if (ip == NULL) 282 return XFS_ERROR(EIO); 283 if (ip->i_d.di_mode == 0 || ip->i_d.di_gen != igen) { 284 xfs_iput_new(ip, XFS_ILOCK_SHARED); 285 return XFS_ERROR(ENOENT); 286 } 287 288 vpp = XFS_ITOV(ip); 289 inodep = LINVFS_GET_IP(vpp); 290 xfs_iunlock(ip, XFS_ILOCK_SHARED); 291 292 *vp = vpp; 293 *inode = inodep; 294 return 0; 295} 296 297STATIC int 298xfs_open_by_handle( 299 xfs_mount_t *mp, 300 unsigned long arg, 301 struct file *parfilp, 302 struct inode *parinode) 303{ 304 int error; 305 int new_fd; 306 int permflag; 307 struct file *filp; 308 struct inode *inode; 309 struct dentry *dentry; 310 vnode_t *vp; 311 xfs_fsop_handlereq_t hreq; 312 313 error = xfs_vget_fsop_handlereq(mp, parinode, CAP_SYS_ADMIN, arg, 314 sizeof(xfs_fsop_handlereq_t), 315 &hreq, &vp, &inode); 316 if (error) 317 return -error; 318 319 /* Restrict xfs_open_by_handle to directories & regular files. */ 320 if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) { 321 iput(inode); 322 return -XFS_ERROR(EINVAL); 323 } 324 325#if BITS_PER_LONG != 32 326 hreq.oflags |= O_LARGEFILE; 327#endif 328 /* Put open permission in namei format. */ 329 permflag = hreq.oflags; 330 if ((permflag+1) & O_ACCMODE) 331 permflag++; 332 if (permflag & O_TRUNC) 333 permflag |= 2; 334 335 if ((!(permflag & O_APPEND) || (permflag & O_TRUNC)) && 336 (permflag & FMODE_WRITE) && IS_APPEND(inode)) { 337 iput(inode); 338 return -XFS_ERROR(EPERM); 339 } 340 341 if ((permflag & FMODE_WRITE) && IS_IMMUTABLE(inode)) { 342 iput(inode); 343 return -XFS_ERROR(EACCES); 344 } 345 346 /* Can't write directories. */ 347 if ( S_ISDIR(inode->i_mode) && (permflag & FMODE_WRITE)) { 348 iput(inode); 349 return -XFS_ERROR(EISDIR); 350 } 351 352 if ((new_fd = get_unused_fd()) < 0) { 353 iput(inode); 354 return new_fd; 355 } 356 357 dentry = d_alloc_anon(inode); 358 if (dentry == NULL) { 359 iput(inode); 360 put_unused_fd(new_fd); 361 return -XFS_ERROR(ENOMEM); 362 } 363 364 /* Ensure umount returns EBUSY on umounts while this file is open. */ 365 mntget(parfilp->f_vfsmnt); 366 367 /* Create file pointer. */ 368 filp = dentry_open(dentry, parfilp->f_vfsmnt, hreq.oflags); 369 if (IS_ERR(filp)) { 370 put_unused_fd(new_fd); 371 return -XFS_ERROR(-PTR_ERR(filp)); 372 } 373 if (inode->i_mode & S_IFREG) 374 filp->f_op = &linvfs_invis_file_operations; 375 376 fd_install(new_fd, filp); 377 return new_fd; 378} 379 380STATIC int 381xfs_readlink_by_handle( 382 xfs_mount_t *mp, 383 unsigned long arg, 384 struct file *parfilp, 385 struct inode *parinode) 386{ 387 int error; 388 struct iovec aiov; 389 struct uio auio; 390 struct inode *inode; 391 xfs_fsop_handlereq_t hreq; 392 vnode_t *vp; 393 __u32 olen; 394 395 error = xfs_vget_fsop_handlereq(mp, parinode, CAP_SYS_ADMIN, arg, 396 sizeof(xfs_fsop_handlereq_t), 397 &hreq, &vp, &inode); 398 if (error) 399 return -error; 400 401 /* Restrict this handle operation to symlinks only. */ 402 if (vp->v_type != VLNK) { 403 VN_RELE(vp); 404 return -XFS_ERROR(EINVAL); 405 } 406 407 if (copy_from_user(&olen, hreq.ohandlen, sizeof(__u32))) { 408 VN_RELE(vp); 409 return -XFS_ERROR(EFAULT); 410 } 411 aiov.iov_len = olen; 412 aiov.iov_base = hreq.ohandle; 413 414 auio.uio_iov = &aiov; 415 auio.uio_iovcnt = 1; 416 auio.uio_offset = 0; 417 auio.uio_segflg = UIO_USERSPACE; 418 auio.uio_resid = olen; 419 420 VOP_READLINK(vp, &auio, IO_INVIS, NULL, error); 421 422 VN_RELE(vp); 423 return (olen - auio.uio_resid); 424} 425 426STATIC int 427xfs_fssetdm_by_handle( 428 xfs_mount_t *mp, 429 unsigned long arg, 430 struct file *parfilp, 431 struct inode *parinode) 432{ 433 int error; 434 struct fsdmidata fsd; 435 xfs_fsop_setdm_handlereq_t dmhreq; 436 struct inode *inode; 437 bhv_desc_t *bdp; 438 vnode_t *vp; 439 440 error = xfs_vget_fsop_handlereq(mp, parinode, CAP_MKNOD, arg, 441 sizeof(xfs_fsop_setdm_handlereq_t), 442 (xfs_fsop_handlereq_t *)&dmhreq, 443 &vp, &inode); 444 if (error) 445 return -error; 446 447 if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) { 448 VN_RELE(vp); 449 return -XFS_ERROR(EPERM); 450 } 451 452 if (copy_from_user(&fsd, dmhreq.data, sizeof(fsd))) { 453 VN_RELE(vp); 454 return -XFS_ERROR(EFAULT); 455 } 456 457 bdp = bhv_base_unlocked(VN_BHV_HEAD(vp)); 458 error = xfs_set_dmattrs(bdp, fsd.fsd_dmevmask, fsd.fsd_dmstate, NULL); 459 460 VN_RELE(vp); 461 if (error) 462 return -error; 463 return 0; 464} 465 466STATIC int 467xfs_attrlist_by_handle( 468 xfs_mount_t *mp, 469 unsigned long arg, 470 struct file *parfilp, 471 struct inode *parinode) 472{ 473 int error; 474 attrlist_cursor_kern_t *cursor; 475 xfs_fsop_attrlist_handlereq_t al_hreq; 476 struct inode *inode; 477 vnode_t *vp; 478 479 error = xfs_vget_fsop_handlereq(mp, parinode, CAP_SYS_ADMIN, arg, 480 sizeof(xfs_fsop_attrlist_handlereq_t), 481 (xfs_fsop_handlereq_t *)&al_hreq, 482 &vp, &inode); 483 if (error) 484 return -error; 485 486 cursor = (attrlist_cursor_kern_t *)&al_hreq.pos; 487 VOP_ATTR_LIST(vp, al_hreq.buffer, al_hreq.buflen, al_hreq.flags, 488 cursor, NULL, error); 489 VN_RELE(vp); 490 if (error) 491 return -error; 492 return 0; 493} 494 495STATIC int 496xfs_attrmulti_by_handle( 497 xfs_mount_t *mp, 498 unsigned long arg, 499 struct file *parfilp, 500 struct inode *parinode) 501{ 502 int error; 503 xfs_attr_multiop_t *ops; 504 xfs_fsop_attrmulti_handlereq_t am_hreq; 505 struct inode *inode; 506 vnode_t *vp; 507 int i, size; 508 509 error = xfs_vget_fsop_handlereq(mp, parinode, CAP_SYS_ADMIN, arg, 510 sizeof(xfs_fsop_attrmulti_handlereq_t), 511 (xfs_fsop_handlereq_t *)&am_hreq, 512 &vp, &inode); 513 if (error) 514 return -error; 515 516 size = am_hreq.opcount * sizeof(attr_multiop_t); 517 ops = (xfs_attr_multiop_t *)kmalloc(size, GFP_KERNEL); 518 if (!ops) { 519 VN_RELE(vp); 520 return -XFS_ERROR(ENOMEM); 521 } 522 523 if (copy_from_user(ops, am_hreq.ops, size)) { 524 kfree(ops); 525 VN_RELE(vp); 526 return -XFS_ERROR(EFAULT); 527 } 528 529 for (i = 0; i < am_hreq.opcount; i++) { 530 switch(ops[i].am_opcode) { 531 case ATTR_OP_GET: 532 VOP_ATTR_GET(vp,ops[i].am_attrname, ops[i].am_attrvalue, 533 &ops[i].am_length, ops[i].am_flags, 534 NULL, ops[i].am_error); 535 break; 536 case ATTR_OP_SET: 537 if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) { 538 ops[i].am_error = EPERM; 539 break; 540 } 541 VOP_ATTR_SET(vp,ops[i].am_attrname, ops[i].am_attrvalue, 542 ops[i].am_length, ops[i].am_flags, 543 NULL, ops[i].am_error); 544 break; 545 case ATTR_OP_REMOVE: 546 if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) { 547 ops[i].am_error = EPERM; 548 break; 549 } 550 VOP_ATTR_REMOVE(vp, ops[i].am_attrname, ops[i].am_flags, 551 NULL, ops[i].am_error); 552 break; 553 default: 554 ops[i].am_error = EINVAL; 555 } 556 } 557 558 if (copy_to_user(am_hreq.ops, ops, size)) 559 error = -XFS_ERROR(EFAULT); 560 561 kfree(ops); 562 VN_RELE(vp); 563 return error; 564} 565 566/* prototypes for a few of the stack-hungry cases that have 567 * their own functions. Functions are defined after their use 568 * so gcc doesn't get fancy and inline them with -03 */ 569 570STATIC int 571xfs_ioc_space( 572 bhv_desc_t *bdp, 573 vnode_t *vp, 574 struct file *filp, 575 int flags, 576 unsigned int cmd, 577 unsigned long arg); 578 579STATIC int 580xfs_ioc_bulkstat( 581 xfs_mount_t *mp, 582 unsigned int cmd, 583 unsigned long arg); 584 585STATIC int 586xfs_ioc_fsgeometry_v1( 587 xfs_mount_t *mp, 588 unsigned long arg); 589 590STATIC int 591xfs_ioc_fsgeometry( 592 xfs_mount_t *mp, 593 unsigned long arg); 594 595STATIC int 596xfs_ioc_xattr( 597 vnode_t *vp, 598 xfs_inode_t *ip, 599 struct file *filp, 600 unsigned int cmd, 601 unsigned long arg); 602 603STATIC int 604xfs_ioc_getbmap( 605 bhv_desc_t *bdp, 606 struct file *filp, 607 int flags, 608 unsigned int cmd, 609 unsigned long arg); 610 611STATIC int 612xfs_ioc_getbmapx( 613 bhv_desc_t *bdp, 614 unsigned long arg); 615 616int 617xfs_ioctl( 618 bhv_desc_t *bdp, 619 struct inode *inode, 620 struct file *filp, 621 int ioflags, 622 unsigned int cmd, 623 unsigned long arg) 624{ 625 int error; 626 vnode_t *vp; 627 xfs_inode_t *ip; 628 xfs_mount_t *mp; 629 630 vp = LINVFS_GET_VP(inode); 631 632 vn_trace_entry(vp, "xfs_ioctl", (inst_t *)__return_address); 633 634 ip = XFS_BHVTOI(bdp); 635 mp = ip->i_mount; 636 637 switch (cmd) { 638 639 case XFS_IOC_ALLOCSP: 640 case XFS_IOC_FREESP: 641 case XFS_IOC_RESVSP: 642 case XFS_IOC_UNRESVSP: 643 case XFS_IOC_ALLOCSP64: 644 case XFS_IOC_FREESP64: 645 case XFS_IOC_RESVSP64: 646 case XFS_IOC_UNRESVSP64: 647 /* 648 * Only allow the sys admin to reserve space unless 649 * unwritten extents are enabled. 650 */ 651 if (!XFS_SB_VERSION_HASEXTFLGBIT(&mp->m_sb) && 652 !capable(CAP_SYS_ADMIN)) 653 return -EPERM; 654 655 return xfs_ioc_space(bdp, vp, filp, ioflags, cmd, arg); 656 657 case XFS_IOC_DIOINFO: { 658 struct dioattr da; 659 660 da.d_miniosz = mp->m_sb.sb_blocksize; 661 da.d_mem = mp->m_sb.sb_blocksize; 662 663 /* 664 * this only really needs to be BBSIZE. 665 * it is set to the file system block size to 666 * avoid having to do block zeroing on short writes. 667 */ 668 da.d_maxiosz = XFS_FSB_TO_B(mp, 669 XFS_B_TO_FSBT(mp, KIO_MAX_ATOMIC_IO << 10)); 670 671 if (copy_to_user((struct dioattr *)arg, &da, sizeof(da))) 672 return -XFS_ERROR(EFAULT); 673 return 0; 674 } 675 676 case XFS_IOC_FSBULKSTAT_SINGLE: 677 case XFS_IOC_FSBULKSTAT: 678 case XFS_IOC_FSINUMBERS: 679 return xfs_ioc_bulkstat(mp, cmd, arg); 680 681 case XFS_IOC_FSGEOMETRY_V1: 682 return xfs_ioc_fsgeometry_v1(mp, arg); 683 684 case XFS_IOC_FSGEOMETRY: 685 return xfs_ioc_fsgeometry(mp, arg); 686 687 case XFS_IOC_GETVERSION: 688 case XFS_IOC_GETXFLAGS: 689 case XFS_IOC_SETXFLAGS: 690 case XFS_IOC_FSGETXATTR: 691 case XFS_IOC_FSSETXATTR: 692 case XFS_IOC_FSGETXATTRA: 693 return xfs_ioc_xattr(vp, ip, filp, cmd, arg); 694 695 case XFS_IOC_FSSETDM: { 696 struct fsdmidata dmi; 697 698 if (copy_from_user(&dmi, (struct fsdmidata *)arg, sizeof(dmi))) 699 return -XFS_ERROR(EFAULT); 700 701 error = xfs_set_dmattrs(bdp, dmi.fsd_dmevmask, dmi.fsd_dmstate, 702 NULL); 703 return -error; 704 } 705 706 case XFS_IOC_GETBMAP: 707 case XFS_IOC_GETBMAPA: 708 return xfs_ioc_getbmap(bdp, filp, ioflags, cmd, arg); 709 710 case XFS_IOC_GETBMAPX: 711 return xfs_ioc_getbmapx(bdp, arg); 712 713 case XFS_IOC_FD_TO_HANDLE: 714 case XFS_IOC_PATH_TO_HANDLE: 715 case XFS_IOC_PATH_TO_FSHANDLE: 716 return xfs_find_handle(cmd, arg); 717 718 case XFS_IOC_OPEN_BY_HANDLE: 719 return xfs_open_by_handle(mp, arg, filp, inode); 720 721 case XFS_IOC_FSSETDM_BY_HANDLE: 722 return xfs_fssetdm_by_handle(mp, arg, filp, inode); 723 724 case XFS_IOC_READLINK_BY_HANDLE: 725 return xfs_readlink_by_handle(mp, arg, filp, inode); 726 727 case XFS_IOC_ATTRLIST_BY_HANDLE: 728 return xfs_attrlist_by_handle(mp, arg, filp, inode); 729 730 case XFS_IOC_ATTRMULTI_BY_HANDLE: 731 return xfs_attrmulti_by_handle(mp, arg, filp, inode); 732 733 case XFS_IOC_SWAPEXT: { 734 error = xfs_swapext((struct xfs_swapext *)arg); 735 return -error; 736 } 737 738 case XFS_IOC_FSCOUNTS: { 739 xfs_fsop_counts_t out; 740 741 error = xfs_fs_counts(mp, &out); 742 if (error) 743 return -error; 744 745 if (copy_to_user((char *)arg, &out, sizeof(out))) 746 return -XFS_ERROR(EFAULT); 747 return 0; 748 } 749 750 case XFS_IOC_SET_RESBLKS: { 751 xfs_fsop_resblks_t inout; 752 __uint64_t in; 753 754 if (!capable(CAP_SYS_ADMIN)) 755 return -EPERM; 756 757 if (copy_from_user(&inout, (char *)arg, sizeof(inout))) 758 return -XFS_ERROR(EFAULT); 759 760 /* input parameter is passed in resblks field of structure */ 761 in = inout.resblks; 762 error = xfs_reserve_blocks(mp, &in, &inout); 763 if (error) 764 return -error; 765 766 if (copy_to_user((char *)arg, &inout, sizeof(inout))) 767 return -XFS_ERROR(EFAULT); 768 return 0; 769 } 770 771 case XFS_IOC_GET_RESBLKS: { 772 xfs_fsop_resblks_t out; 773 774 if (!capable(CAP_SYS_ADMIN)) 775 return -EPERM; 776 777 error = xfs_reserve_blocks(mp, NULL, &out); 778 if (error) 779 return -error; 780 781 if (copy_to_user((char *)arg, &out, sizeof(out))) 782 return -XFS_ERROR(EFAULT); 783 784 return 0; 785 } 786 787 case XFS_IOC_FSGROWFSDATA: { 788 xfs_growfs_data_t in; 789 790 if (!capable(CAP_SYS_ADMIN)) 791 return -EPERM; 792 793 if (copy_from_user(&in, (char *)arg, sizeof(in))) 794 return -XFS_ERROR(EFAULT); 795 796 error = xfs_growfs_data(mp, &in); 797 return -error; 798 } 799 800 case XFS_IOC_FSGROWFSLOG: { 801 xfs_growfs_log_t in; 802 803 if (!capable(CAP_SYS_ADMIN)) 804 return -EPERM; 805 806 if (copy_from_user(&in, (char *)arg, sizeof(in))) 807 return -XFS_ERROR(EFAULT); 808 809 error = xfs_growfs_log(mp, &in); 810 return -error; 811 } 812 813 case XFS_IOC_FSGROWFSRT: { 814 xfs_growfs_rt_t in; 815 816 if (!capable(CAP_SYS_ADMIN)) 817 return -EPERM; 818 819 if (copy_from_user(&in, (char *)arg, sizeof(in))) 820 return -XFS_ERROR(EFAULT); 821 822 error = xfs_growfs_rt(mp, &in); 823 return -error; 824 } 825 826 case XFS_IOC_FREEZE: 827 if (!capable(CAP_SYS_ADMIN)) 828 return -EPERM; 829 xfs_fs_freeze(mp); 830 return 0; 831 832 case XFS_IOC_THAW: 833 if (!capable(CAP_SYS_ADMIN)) 834 return -EPERM; 835 xfs_fs_thaw(mp); 836 return 0; 837 838 case XFS_IOC_GOINGDOWN: { 839 __uint32_t in; 840 841 if (!capable(CAP_SYS_ADMIN)) 842 return -EPERM; 843 844 if (get_user(in, (__uint32_t *)arg)) 845 return -XFS_ERROR(EFAULT); 846 847 error = xfs_fs_goingdown(mp, in); 848 return -error; 849 } 850 851 case XFS_IOC_ERROR_INJECTION: { 852 xfs_error_injection_t in; 853 854 if (copy_from_user(&in, (char *)arg, sizeof(in))) 855 return -XFS_ERROR(EFAULT); 856 857 error = xfs_errortag_add(in.errtag, mp); 858 return -error; 859 } 860 861 case XFS_IOC_ERROR_CLEARALL: 862 error = xfs_errortag_clearall(mp); 863 return -error; 864 865 default: 866 return -ENOTTY; 867 } 868} 869 870STATIC int 871xfs_ioc_space( 872 bhv_desc_t *bdp, 873 vnode_t *vp, 874 struct file *filp, 875 int ioflags, 876 unsigned int cmd, 877 unsigned long arg) 878{ 879 xfs_flock64_t bf; 880 int attr_flags = 0; 881 int error; 882 883 if (vp->v_inode.i_flags & (S_IMMUTABLE|S_APPEND)) 884 return -XFS_ERROR(EPERM); 885 886 if (filp->f_flags & O_RDONLY) 887 return -XFS_ERROR(EBADF); 888 889 if (vp->v_type != VREG) 890 return -XFS_ERROR(EINVAL); 891 892 if (copy_from_user(&bf, (xfs_flock64_t *)arg, sizeof(bf))) 893 return -XFS_ERROR(EFAULT); 894 895 if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) 896 attr_flags |= ATTR_NONBLOCK; 897 if (ioflags & IO_INVIS) 898 attr_flags |= ATTR_DMI; 899 900 error = xfs_change_file_space(bdp, cmd, &bf, filp->f_pos, 901 NULL, attr_flags); 902 return -error; 903} 904 905STATIC int 906xfs_ioc_bulkstat( 907 xfs_mount_t *mp, 908 unsigned int cmd, 909 unsigned long arg) 910{ 911 xfs_fsop_bulkreq_t bulkreq; 912 int count; /* # of records returned */ 913 xfs_ino_t inlast; /* last inode number */ 914 int done; 915 int error; 916 917 /* done = 1 if there are more stats to get and if bulkstat */ 918 /* should be called again (unused here, but used in dmapi) */ 919 920 if (!capable(CAP_SYS_ADMIN)) 921 return -EPERM; 922 923 if (XFS_FORCED_SHUTDOWN(mp)) 924 return -XFS_ERROR(EIO); 925 926 if (copy_from_user(&bulkreq, (xfs_fsop_bulkreq_t *)arg, 927 sizeof(xfs_fsop_bulkreq_t))) 928 return -XFS_ERROR(EFAULT); 929 930 if (copy_from_user(&inlast, (__s64 *)bulkreq.lastip, 931 sizeof(__s64))) 932 return -XFS_ERROR(EFAULT); 933 934 if ((count = bulkreq.icount) <= 0) 935 return -XFS_ERROR(EINVAL); 936 937 if (cmd == XFS_IOC_FSINUMBERS) 938 error = xfs_inumbers(mp, NULL, &inlast, &count, 939 bulkreq.ubuffer); 940 else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE) 941 error = xfs_bulkstat_single(mp, &inlast, 942 bulkreq.ubuffer, &done); 943 else { /* XFS_IOC_FSBULKSTAT */ 944 if (count == 1 && inlast != 0) { 945 inlast++; 946 error = xfs_bulkstat_single(mp, &inlast, 947 bulkreq.ubuffer, &done); 948 } else { 949 error = xfs_bulkstat(mp, NULL, &inlast, &count, 950 (bulkstat_one_pf)xfs_bulkstat_one, NULL, 951 sizeof(xfs_bstat_t), bulkreq.ubuffer, 952 BULKSTAT_FG_QUICK, &done); 953 } 954 } 955 956 if (error) 957 return -error; 958 959 if (bulkreq.ocount != NULL) { 960 if (copy_to_user((xfs_ino_t *)bulkreq.lastip, &inlast, 961 sizeof(xfs_ino_t))) 962 return -XFS_ERROR(EFAULT); 963 964 if (copy_to_user((__s32 *)bulkreq.ocount, &count, 965 sizeof(count))) 966 return -XFS_ERROR(EFAULT); 967 } 968 969 return 0; 970} 971 972STATIC int 973xfs_ioc_fsgeometry_v1( 974 xfs_mount_t *mp, 975 unsigned long arg) 976{ 977 xfs_fsop_geom_v1_t fsgeo; 978 int error; 979 980 error = xfs_fs_geometry(mp, (xfs_fsop_geom_t *)&fsgeo, 3); 981 if (error) 982 return -error; 983 984 if (copy_to_user((xfs_fsop_geom_t *)arg, &fsgeo, sizeof(fsgeo))) 985 return -XFS_ERROR(EFAULT); 986 return 0; 987} 988 989STATIC int 990xfs_ioc_fsgeometry( 991 xfs_mount_t *mp, 992 unsigned long arg) 993{ 994 xfs_fsop_geom_t fsgeo; 995 int error; 996 997 error = xfs_fs_geometry(mp, &fsgeo, 4); 998 if (error) 999 return -error; 1000 1001 if (copy_to_user((xfs_fsop_geom_t *)arg, &fsgeo, sizeof(fsgeo))) 1002 return -XFS_ERROR(EFAULT); 1003 return 0; 1004} 1005 1006/* 1007 * Linux extended inode flags interface. 1008 */ 1009#define LINUX_XFLAG_SYNC 0x00000008 /* Synchronous updates */ 1010#define LINUX_XFLAG_IMMUTABLE 0x00000010 /* Immutable file */ 1011#define LINUX_XFLAG_APPEND 0x00000020 /* writes to file may only append */ 1012#define LINUX_XFLAG_NODUMP 0x00000040 /* do not dump file */ 1013#define LINUX_XFLAG_NOATIME 0x00000080 /* do not update atime */ 1014 1015STATIC unsigned int 1016xfs_merge_ioc_xflags( 1017 unsigned int flags, 1018 unsigned int start) 1019{ 1020 unsigned int xflags = start; 1021 1022 if (flags & LINUX_XFLAG_IMMUTABLE) 1023 xflags |= XFS_XFLAG_IMMUTABLE; 1024 else 1025 xflags &= ~XFS_XFLAG_IMMUTABLE; 1026 if (flags & LINUX_XFLAG_APPEND) 1027 xflags |= XFS_XFLAG_APPEND; 1028 else 1029 xflags &= ~XFS_XFLAG_APPEND; 1030 if (flags & LINUX_XFLAG_SYNC) 1031 xflags |= XFS_XFLAG_SYNC; 1032 else 1033 xflags &= ~XFS_XFLAG_SYNC; 1034 if (flags & LINUX_XFLAG_NOATIME) 1035 xflags |= XFS_XFLAG_NOATIME; 1036 else 1037 xflags &= ~XFS_XFLAG_NOATIME; 1038 if (flags & LINUX_XFLAG_NODUMP) 1039 xflags |= XFS_XFLAG_NODUMP; 1040 else 1041 xflags &= ~XFS_XFLAG_NODUMP; 1042 1043 return xflags; 1044} 1045 1046STATIC int 1047xfs_ioc_xattr( 1048 vnode_t *vp, 1049 xfs_inode_t *ip, 1050 struct file *filp, 1051 unsigned int cmd, 1052 unsigned long arg) 1053{ 1054 struct fsxattr fa; 1055 vattr_t va; 1056 int error; 1057 int attr_flags; 1058 unsigned int flags; 1059 1060 switch (cmd) { 1061 case XFS_IOC_FSGETXATTR: { 1062 va.va_mask = XFS_AT_XFLAGS|XFS_AT_EXTSIZE|XFS_AT_NEXTENTS; 1063 VOP_GETATTR(vp, &va, 0, NULL, error); 1064 if (error) 1065 return -error; 1066 1067 fa.fsx_xflags = va.va_xflags; 1068 fa.fsx_extsize = va.va_extsize; 1069 fa.fsx_nextents = va.va_nextents; 1070 1071 if (copy_to_user((struct fsxattr *)arg, &fa, sizeof(fa))) 1072 return -XFS_ERROR(EFAULT); 1073 return 0; 1074 } 1075 1076 case XFS_IOC_FSSETXATTR: { 1077 if (copy_from_user(&fa, (struct fsxattr *)arg, sizeof(fa))) 1078 return -XFS_ERROR(EFAULT); 1079 1080 attr_flags = 0; 1081 if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) 1082 attr_flags |= ATTR_NONBLOCK; 1083 1084 va.va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE; 1085 va.va_xflags = fa.fsx_xflags; 1086 va.va_extsize = fa.fsx_extsize; 1087 1088 VOP_SETATTR(vp, &va, attr_flags, NULL, error); 1089 if (!error) 1090 vn_revalidate(vp); /* update Linux inode flags */ 1091 return -error; 1092 } 1093 1094 case XFS_IOC_FSGETXATTRA: { 1095 va.va_mask = XFS_AT_XFLAGS|XFS_AT_EXTSIZE|XFS_AT_ANEXTENTS; 1096 VOP_GETATTR(vp, &va, 0, NULL, error); 1097 if (error) 1098 return -error; 1099 1100 fa.fsx_xflags = va.va_xflags; 1101 fa.fsx_extsize = va.va_extsize; 1102 fa.fsx_nextents = va.va_anextents; 1103 1104 if (copy_to_user((struct fsxattr *)arg, &fa, sizeof(fa))) 1105 return -XFS_ERROR(EFAULT); 1106 return 0; 1107 } 1108 1109 case XFS_IOC_GETXFLAGS: { 1110 flags = 0; 1111 if (ip->i_d.di_flags & XFS_XFLAG_IMMUTABLE) 1112 flags |= LINUX_XFLAG_IMMUTABLE; 1113 if (ip->i_d.di_flags & XFS_XFLAG_APPEND) 1114 flags |= LINUX_XFLAG_APPEND; 1115 if (ip->i_d.di_flags & XFS_XFLAG_SYNC) 1116 flags |= LINUX_XFLAG_SYNC; 1117 if (ip->i_d.di_flags & XFS_XFLAG_NOATIME) 1118 flags |= LINUX_XFLAG_NOATIME; 1119 if (ip->i_d.di_flags & XFS_XFLAG_NODUMP) 1120 flags |= LINUX_XFLAG_NODUMP; 1121 if (copy_to_user((unsigned int *)arg, &flags, sizeof(flags))) 1122 return -XFS_ERROR(EFAULT); 1123 return 0; 1124 } 1125 1126 case XFS_IOC_SETXFLAGS: { 1127 if (copy_from_user(&flags, (unsigned int *)arg, sizeof(flags))) 1128 return -XFS_ERROR(EFAULT); 1129 1130 if (flags & ~(LINUX_XFLAG_IMMUTABLE | LINUX_XFLAG_APPEND | \ 1131 LINUX_XFLAG_NOATIME | LINUX_XFLAG_NODUMP | \ 1132 LINUX_XFLAG_SYNC)) 1133 return -XFS_ERROR(EOPNOTSUPP); 1134 1135 attr_flags = 0; 1136 if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) 1137 attr_flags |= ATTR_NONBLOCK; 1138 1139 va.va_mask = XFS_AT_XFLAGS; 1140 va.va_xflags = xfs_merge_ioc_xflags(flags, ip->i_d.di_flags); 1141 1142 VOP_SETATTR(vp, &va, attr_flags, NULL, error); 1143 if (!error) 1144 vn_revalidate(vp); /* update Linux inode flags */ 1145 return -error; 1146 } 1147 1148 case XFS_IOC_GETVERSION: { 1149 flags = LINVFS_GET_IP(vp)->i_generation; 1150 if (copy_to_user((unsigned int *)arg, &flags, sizeof(flags))) 1151 return -XFS_ERROR(EFAULT); 1152 return 0; 1153 } 1154 1155 default: 1156 return -ENOTTY; 1157 } 1158} 1159 1160STATIC int 1161xfs_ioc_getbmap( 1162 bhv_desc_t *bdp, 1163 struct file *filp, 1164 int ioflags, 1165 unsigned int cmd, 1166 unsigned long arg) 1167{ 1168 struct getbmap bm; 1169 int iflags; 1170 int error; 1171 1172 if (copy_from_user(&bm, (struct getbmap *)arg, sizeof(bm))) 1173 return -XFS_ERROR(EFAULT); 1174 1175 if (bm.bmv_count < 2) 1176 return -XFS_ERROR(EINVAL); 1177 1178 iflags = (cmd == XFS_IOC_GETBMAPA ? BMV_IF_ATTRFORK : 0); 1179 if (ioflags & IO_INVIS) 1180 iflags |= BMV_IF_NO_DMAPI_READ; 1181 1182 error = xfs_getbmap(bdp, &bm, (struct getbmap *)arg+1, iflags); 1183 if (error) 1184 return -error; 1185 1186 if (copy_to_user((struct getbmap *)arg, &bm, sizeof(bm))) 1187 return -XFS_ERROR(EFAULT); 1188 return 0; 1189} 1190 1191STATIC int 1192xfs_ioc_getbmapx( 1193 bhv_desc_t *bdp, 1194 unsigned long arg) 1195{ 1196 struct getbmapx bmx; 1197 struct getbmap bm; 1198 int iflags; 1199 int error; 1200 1201 if (copy_from_user(&bmx, (struct getbmapx *)arg, sizeof(bmx))) 1202 return -XFS_ERROR(EFAULT); 1203 1204 if (bmx.bmv_count < 2) 1205 return -XFS_ERROR(EINVAL); 1206 1207 /* 1208 * Map input getbmapx structure to a getbmap 1209 * structure for xfs_getbmap. 1210 */ 1211 GETBMAP_CONVERT(bmx, bm); 1212 1213 iflags = bmx.bmv_iflags; 1214 1215 if (iflags & (~BMV_IF_VALID)) 1216 return -XFS_ERROR(EINVAL); 1217 1218 iflags |= BMV_IF_EXTENDED; 1219 1220 error = xfs_getbmap(bdp, &bm, (struct getbmapx *)arg+1, iflags); 1221 if (error) 1222 return -error; 1223 1224 GETBMAP_CONVERT(bm, bmx); 1225 1226 if (copy_to_user((struct getbmapx *)arg, &bmx, sizeof(bmx))) 1227 return -XFS_ERROR(EFAULT); 1228 1229 return 0; 1230} 1231 1232#endif 1233 1234int 1235xfs_ioctl( 1236 bhv_desc_t *bdp, 1237 struct inode *inode, 1238 struct file *filp, 1239 int ioflags, 1240 unsigned int cmd, 1241 unsigned long arg) 1242{ 1243 return EINVAL; 1244} 1245