Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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