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