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