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