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 = file_inode(f.file);
  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(file_inode(parfilp)->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_flags(0);
 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 = kmem_zalloc(al_hreq.buflen, KM_SLEEP | KM_MAYFAIL);
 426        if (!kbuf) {
 427                kbuf = kmem_zalloc_large(al_hreq.buflen);
 428                if (!kbuf)
 429                        goto out_dput;
 430        }
 431
 432        cursor = (attrlist_cursor_kern_t *)&al_hreq.pos;
 433        error = -xfs_attr_list(XFS_I(dentry->d_inode), kbuf, al_hreq.buflen,
 434                                        al_hreq.flags, cursor);
 435        if (error)
 436                goto out_kfree;
 437
 438        if (copy_to_user(al_hreq.buffer, kbuf, al_hreq.buflen))
 439                error = -EFAULT;
 440
 441 out_kfree:
 442        if (is_vmalloc_addr(kbuf))
 443                kmem_free_large(kbuf);
 444        else
 445                kmem_free(kbuf);
 446 out_dput:
 447        dput(dentry);
 448        return error;
 449}
 450
 451int
 452xfs_attrmulti_attr_get(
 453        struct inode            *inode,
 454        unsigned char           *name,
 455        unsigned char           __user *ubuf,
 456        __uint32_t              *len,
 457        __uint32_t              flags)
 458{
 459        unsigned char           *kbuf;
 460        int                     error = EFAULT;
 461
 462        if (*len > XATTR_SIZE_MAX)
 463                return EINVAL;
 464        kbuf = kmem_zalloc(*len, KM_SLEEP | KM_MAYFAIL);
 465        if (!kbuf) {
 466                kbuf = kmem_zalloc_large(*len);
 467                if (!kbuf)
 468                        return ENOMEM;
 469        }
 470
 471        error = xfs_attr_get(XFS_I(inode), name, kbuf, (int *)len, flags);
 472        if (error)
 473                goto out_kfree;
 474
 475        if (copy_to_user(ubuf, kbuf, *len))
 476                error = EFAULT;
 477
 478 out_kfree:
 479        if (is_vmalloc_addr(kbuf))
 480                kmem_free_large(kbuf);
 481        else
 482                kmem_free(kbuf);
 483        return error;
 484}
 485
 486int
 487xfs_attrmulti_attr_set(
 488        struct inode            *inode,
 489        unsigned char           *name,
 490        const unsigned char     __user *ubuf,
 491        __uint32_t              len,
 492        __uint32_t              flags)
 493{
 494        unsigned char           *kbuf;
 495        int                     error = EFAULT;
 496
 497        if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
 498                return EPERM;
 499        if (len > XATTR_SIZE_MAX)
 500                return EINVAL;
 501
 502        kbuf = memdup_user(ubuf, len);
 503        if (IS_ERR(kbuf))
 504                return PTR_ERR(kbuf);
 505
 506        error = xfs_attr_set(XFS_I(inode), name, kbuf, len, flags);
 507
 508        return error;
 509}
 510
 511int
 512xfs_attrmulti_attr_remove(
 513        struct inode            *inode,
 514        unsigned char           *name,
 515        __uint32_t              flags)
 516{
 517        if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
 518                return EPERM;
 519        return xfs_attr_remove(XFS_I(inode), name, flags);
 520}
 521
 522STATIC int
 523xfs_attrmulti_by_handle(
 524        struct file             *parfilp,
 525        void                    __user *arg)
 526{
 527        int                     error;
 528        xfs_attr_multiop_t      *ops;
 529        xfs_fsop_attrmulti_handlereq_t am_hreq;
 530        struct dentry           *dentry;
 531        unsigned int            i, size;
 532        unsigned char           *attr_name;
 533
 534        if (!capable(CAP_SYS_ADMIN))
 535                return -XFS_ERROR(EPERM);
 536        if (copy_from_user(&am_hreq, arg, sizeof(xfs_fsop_attrmulti_handlereq_t)))
 537                return -XFS_ERROR(EFAULT);
 538
 539        /* overflow check */
 540        if (am_hreq.opcount >= INT_MAX / sizeof(xfs_attr_multiop_t))
 541                return -E2BIG;
 542
 543        dentry = xfs_handlereq_to_dentry(parfilp, &am_hreq.hreq);
 544        if (IS_ERR(dentry))
 545                return PTR_ERR(dentry);
 546
 547        error = E2BIG;
 548        size = am_hreq.opcount * sizeof(xfs_attr_multiop_t);
 549        if (!size || size > 16 * PAGE_SIZE)
 550                goto out_dput;
 551
 552        ops = memdup_user(am_hreq.ops, size);
 553        if (IS_ERR(ops)) {
 554                error = PTR_ERR(ops);
 555                goto out_dput;
 556        }
 557
 558        attr_name = kmalloc(MAXNAMELEN, GFP_KERNEL);
 559        if (!attr_name)
 560                goto out_kfree_ops;
 561
 562        error = 0;
 563        for (i = 0; i < am_hreq.opcount; i++) {
 564                ops[i].am_error = strncpy_from_user((char *)attr_name,
 565                                ops[i].am_attrname, MAXNAMELEN);
 566                if (ops[i].am_error == 0 || ops[i].am_error == MAXNAMELEN)
 567                        error = -ERANGE;
 568                if (ops[i].am_error < 0)
 569                        break;
 570
 571                switch (ops[i].am_opcode) {
 572                case ATTR_OP_GET:
 573                        ops[i].am_error = xfs_attrmulti_attr_get(
 574                                        dentry->d_inode, attr_name,
 575                                        ops[i].am_attrvalue, &ops[i].am_length,
 576                                        ops[i].am_flags);
 577                        break;
 578                case ATTR_OP_SET:
 579                        ops[i].am_error = mnt_want_write_file(parfilp);
 580                        if (ops[i].am_error)
 581                                break;
 582                        ops[i].am_error = xfs_attrmulti_attr_set(
 583                                        dentry->d_inode, attr_name,
 584                                        ops[i].am_attrvalue, ops[i].am_length,
 585                                        ops[i].am_flags);
 586                        mnt_drop_write_file(parfilp);
 587                        break;
 588                case ATTR_OP_REMOVE:
 589                        ops[i].am_error = mnt_want_write_file(parfilp);
 590                        if (ops[i].am_error)
 591                                break;
 592                        ops[i].am_error = xfs_attrmulti_attr_remove(
 593                                        dentry->d_inode, attr_name,
 594                                        ops[i].am_flags);
 595                        mnt_drop_write_file(parfilp);
 596                        break;
 597                default:
 598                        ops[i].am_error = EINVAL;
 599                }
 600        }
 601
 602        if (copy_to_user(am_hreq.ops, ops, size))
 603                error = XFS_ERROR(EFAULT);
 604
 605        kfree(attr_name);
 606 out_kfree_ops:
 607        kfree(ops);
 608 out_dput:
 609        dput(dentry);
 610        return -error;
 611}
 612
 613int
 614xfs_ioc_space(
 615        struct xfs_inode        *ip,
 616        struct inode            *inode,
 617        struct file             *filp,
 618        int                     ioflags,
 619        unsigned int            cmd,
 620        xfs_flock64_t           *bf)
 621{
 622        int                     attr_flags = 0;
 623        int                     error;
 624
 625        /*
 626         * Only allow the sys admin to reserve space unless
 627         * unwritten extents are enabled.
 628         */
 629        if (!xfs_sb_version_hasextflgbit(&ip->i_mount->m_sb) &&
 630            !capable(CAP_SYS_ADMIN))
 631                return -XFS_ERROR(EPERM);
 632
 633        if (inode->i_flags & (S_IMMUTABLE|S_APPEND))
 634                return -XFS_ERROR(EPERM);
 635
 636        if (!(filp->f_mode & FMODE_WRITE))
 637                return -XFS_ERROR(EBADF);
 638
 639        if (!S_ISREG(inode->i_mode))
 640                return -XFS_ERROR(EINVAL);
 641
 642        if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
 643                attr_flags |= XFS_ATTR_NONBLOCK;
 644
 645        if (filp->f_flags & O_DSYNC)
 646                attr_flags |= XFS_ATTR_SYNC;
 647
 648        if (ioflags & IO_INVIS)
 649                attr_flags |= XFS_ATTR_DMI;
 650
 651        error = mnt_want_write_file(filp);
 652        if (error)
 653                return error;
 654        error = xfs_change_file_space(ip, cmd, bf, filp->f_pos, attr_flags);
 655        mnt_drop_write_file(filp);
 656        return -error;
 657}
 658
 659STATIC int
 660xfs_ioc_bulkstat(
 661        xfs_mount_t             *mp,
 662        unsigned int            cmd,
 663        void                    __user *arg)
 664{
 665        xfs_fsop_bulkreq_t      bulkreq;
 666        int                     count;  /* # of records returned */
 667        xfs_ino_t               inlast; /* last inode number */
 668        int                     done;
 669        int                     error;
 670
 671        /* done = 1 if there are more stats to get and if bulkstat */
 672        /* should be called again (unused here, but used in dmapi) */
 673
 674        if (!capable(CAP_SYS_ADMIN))
 675                return -EPERM;
 676
 677        if (XFS_FORCED_SHUTDOWN(mp))
 678                return -XFS_ERROR(EIO);
 679
 680        if (copy_from_user(&bulkreq, arg, sizeof(xfs_fsop_bulkreq_t)))
 681                return -XFS_ERROR(EFAULT);
 682
 683        if (copy_from_user(&inlast, bulkreq.lastip, sizeof(__s64)))
 684                return -XFS_ERROR(EFAULT);
 685
 686        if ((count = bulkreq.icount) <= 0)
 687                return -XFS_ERROR(EINVAL);
 688
 689        if (bulkreq.ubuffer == NULL)
 690                return -XFS_ERROR(EINVAL);
 691
 692        if (cmd == XFS_IOC_FSINUMBERS)
 693                error = xfs_inumbers(mp, &inlast, &count,
 694                                        bulkreq.ubuffer, xfs_inumbers_fmt);
 695        else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE)
 696                error = xfs_bulkstat_single(mp, &inlast,
 697                                                bulkreq.ubuffer, &done);
 698        else    /* XFS_IOC_FSBULKSTAT */
 699                error = xfs_bulkstat(mp, &inlast, &count, xfs_bulkstat_one,
 700                                     sizeof(xfs_bstat_t), bulkreq.ubuffer,
 701                                     &done);
 702
 703        if (error)
 704                return -error;
 705
 706        if (bulkreq.ocount != NULL) {
 707                if (copy_to_user(bulkreq.lastip, &inlast,
 708                                                sizeof(xfs_ino_t)))
 709                        return -XFS_ERROR(EFAULT);
 710
 711                if (copy_to_user(bulkreq.ocount, &count, sizeof(count)))
 712                        return -XFS_ERROR(EFAULT);
 713        }
 714
 715        return 0;
 716}
 717
 718STATIC int
 719xfs_ioc_fsgeometry_v1(
 720        xfs_mount_t             *mp,
 721        void                    __user *arg)
 722{
 723        xfs_fsop_geom_t         fsgeo;
 724        int                     error;
 725
 726        error = xfs_fs_geometry(mp, &fsgeo, 3);
 727        if (error)
 728                return -error;
 729
 730        /*
 731         * Caller should have passed an argument of type
 732         * xfs_fsop_geom_v1_t.  This is a proper subset of the
 733         * xfs_fsop_geom_t that xfs_fs_geometry() fills in.
 734         */
 735        if (copy_to_user(arg, &fsgeo, sizeof(xfs_fsop_geom_v1_t)))
 736                return -XFS_ERROR(EFAULT);
 737        return 0;
 738}
 739
 740STATIC int
 741xfs_ioc_fsgeometry(
 742        xfs_mount_t             *mp,
 743        void                    __user *arg)
 744{
 745        xfs_fsop_geom_t         fsgeo;
 746        int                     error;
 747
 748        error = xfs_fs_geometry(mp, &fsgeo, 4);
 749        if (error)
 750                return -error;
 751
 752        if (copy_to_user(arg, &fsgeo, sizeof(fsgeo)))
 753                return -XFS_ERROR(EFAULT);
 754        return 0;
 755}
 756
 757/*
 758 * Linux extended inode flags interface.
 759 */
 760
 761STATIC unsigned int
 762xfs_merge_ioc_xflags(
 763        unsigned int    flags,
 764        unsigned int    start)
 765{
 766        unsigned int    xflags = start;
 767
 768        if (flags & FS_IMMUTABLE_FL)
 769                xflags |= XFS_XFLAG_IMMUTABLE;
 770        else
 771                xflags &= ~XFS_XFLAG_IMMUTABLE;
 772        if (flags & FS_APPEND_FL)
 773                xflags |= XFS_XFLAG_APPEND;
 774        else
 775                xflags &= ~XFS_XFLAG_APPEND;
 776        if (flags & FS_SYNC_FL)
 777                xflags |= XFS_XFLAG_SYNC;
 778        else
 779                xflags &= ~XFS_XFLAG_SYNC;
 780        if (flags & FS_NOATIME_FL)
 781                xflags |= XFS_XFLAG_NOATIME;
 782        else
 783                xflags &= ~XFS_XFLAG_NOATIME;
 784        if (flags & FS_NODUMP_FL)
 785                xflags |= XFS_XFLAG_NODUMP;
 786        else
 787                xflags &= ~XFS_XFLAG_NODUMP;
 788
 789        return xflags;
 790}
 791
 792STATIC unsigned int
 793xfs_di2lxflags(
 794        __uint16_t      di_flags)
 795{
 796        unsigned int    flags = 0;
 797
 798        if (di_flags & XFS_DIFLAG_IMMUTABLE)
 799                flags |= FS_IMMUTABLE_FL;
 800        if (di_flags & XFS_DIFLAG_APPEND)
 801                flags |= FS_APPEND_FL;
 802        if (di_flags & XFS_DIFLAG_SYNC)
 803                flags |= FS_SYNC_FL;
 804        if (di_flags & XFS_DIFLAG_NOATIME)
 805                flags |= FS_NOATIME_FL;
 806        if (di_flags & XFS_DIFLAG_NODUMP)
 807                flags |= FS_NODUMP_FL;
 808        return flags;
 809}
 810
 811STATIC int
 812xfs_ioc_fsgetxattr(
 813        xfs_inode_t             *ip,
 814        int                     attr,
 815        void                    __user *arg)
 816{
 817        struct fsxattr          fa;
 818
 819        memset(&fa, 0, sizeof(struct fsxattr));
 820
 821        xfs_ilock(ip, XFS_ILOCK_SHARED);
 822        fa.fsx_xflags = xfs_ip2xflags(ip);
 823        fa.fsx_extsize = ip->i_d.di_extsize << ip->i_mount->m_sb.sb_blocklog;
 824        fa.fsx_projid = xfs_get_projid(ip);
 825
 826        if (attr) {
 827                if (ip->i_afp) {
 828                        if (ip->i_afp->if_flags & XFS_IFEXTENTS)
 829                                fa.fsx_nextents = ip->i_afp->if_bytes /
 830                                                        sizeof(xfs_bmbt_rec_t);
 831                        else
 832                                fa.fsx_nextents = ip->i_d.di_anextents;
 833                } else
 834                        fa.fsx_nextents = 0;
 835        } else {
 836                if (ip->i_df.if_flags & XFS_IFEXTENTS)
 837                        fa.fsx_nextents = ip->i_df.if_bytes /
 838                                                sizeof(xfs_bmbt_rec_t);
 839                else
 840                        fa.fsx_nextents = ip->i_d.di_nextents;
 841        }
 842        xfs_iunlock(ip, XFS_ILOCK_SHARED);
 843
 844        if (copy_to_user(arg, &fa, sizeof(fa)))
 845                return -EFAULT;
 846        return 0;
 847}
 848
 849STATIC void
 850xfs_set_diflags(
 851        struct xfs_inode        *ip,
 852        unsigned int            xflags)
 853{
 854        unsigned int            di_flags;
 855
 856        /* can't set PREALLOC this way, just preserve it */
 857        di_flags = (ip->i_d.di_flags & XFS_DIFLAG_PREALLOC);
 858        if (xflags & XFS_XFLAG_IMMUTABLE)
 859                di_flags |= XFS_DIFLAG_IMMUTABLE;
 860        if (xflags & XFS_XFLAG_APPEND)
 861                di_flags |= XFS_DIFLAG_APPEND;
 862        if (xflags & XFS_XFLAG_SYNC)
 863                di_flags |= XFS_DIFLAG_SYNC;
 864        if (xflags & XFS_XFLAG_NOATIME)
 865                di_flags |= XFS_DIFLAG_NOATIME;
 866        if (xflags & XFS_XFLAG_NODUMP)
 867                di_flags |= XFS_DIFLAG_NODUMP;
 868        if (xflags & XFS_XFLAG_PROJINHERIT)
 869                di_flags |= XFS_DIFLAG_PROJINHERIT;
 870        if (xflags & XFS_XFLAG_NODEFRAG)
 871                di_flags |= XFS_DIFLAG_NODEFRAG;
 872        if (xflags & XFS_XFLAG_FILESTREAM)
 873                di_flags |= XFS_DIFLAG_FILESTREAM;
 874        if (S_ISDIR(ip->i_d.di_mode)) {
 875                if (xflags & XFS_XFLAG_RTINHERIT)
 876                        di_flags |= XFS_DIFLAG_RTINHERIT;
 877                if (xflags & XFS_XFLAG_NOSYMLINKS)
 878                        di_flags |= XFS_DIFLAG_NOSYMLINKS;
 879                if (xflags & XFS_XFLAG_EXTSZINHERIT)
 880                        di_flags |= XFS_DIFLAG_EXTSZINHERIT;
 881        } else if (S_ISREG(ip->i_d.di_mode)) {
 882                if (xflags & XFS_XFLAG_REALTIME)
 883                        di_flags |= XFS_DIFLAG_REALTIME;
 884                if (xflags & XFS_XFLAG_EXTSIZE)
 885                        di_flags |= XFS_DIFLAG_EXTSIZE;
 886        }
 887
 888        ip->i_d.di_flags = di_flags;
 889}
 890
 891STATIC void
 892xfs_diflags_to_linux(
 893        struct xfs_inode        *ip)
 894{
 895        struct inode            *inode = VFS_I(ip);
 896        unsigned int            xflags = xfs_ip2xflags(ip);
 897
 898        if (xflags & XFS_XFLAG_IMMUTABLE)
 899                inode->i_flags |= S_IMMUTABLE;
 900        else
 901                inode->i_flags &= ~S_IMMUTABLE;
 902        if (xflags & XFS_XFLAG_APPEND)
 903                inode->i_flags |= S_APPEND;
 904        else
 905                inode->i_flags &= ~S_APPEND;
 906        if (xflags & XFS_XFLAG_SYNC)
 907                inode->i_flags |= S_SYNC;
 908        else
 909                inode->i_flags &= ~S_SYNC;
 910        if (xflags & XFS_XFLAG_NOATIME)
 911                inode->i_flags |= S_NOATIME;
 912        else
 913                inode->i_flags &= ~S_NOATIME;
 914}
 915
 916#define FSX_PROJID      1
 917#define FSX_EXTSIZE     2
 918#define FSX_XFLAGS      4
 919#define FSX_NONBLOCK    8
 920
 921STATIC int
 922xfs_ioctl_setattr(
 923        xfs_inode_t             *ip,
 924        struct fsxattr          *fa,
 925        int                     mask)
 926{
 927        struct xfs_mount        *mp = ip->i_mount;
 928        struct xfs_trans        *tp;
 929        unsigned int            lock_flags = 0;
 930        struct xfs_dquot        *udqp = NULL;
 931        struct xfs_dquot        *pdqp = NULL;
 932        struct xfs_dquot        *olddquot = NULL;
 933        int                     code;
 934
 935        trace_xfs_ioctl_setattr(ip);
 936
 937        if (mp->m_flags & XFS_MOUNT_RDONLY)
 938                return XFS_ERROR(EROFS);
 939        if (XFS_FORCED_SHUTDOWN(mp))
 940                return XFS_ERROR(EIO);
 941
 942        /*
 943         * Disallow 32bit project ids when projid32bit feature is not enabled.
 944         */
 945        if ((mask & FSX_PROJID) && (fa->fsx_projid > (__uint16_t)-1) &&
 946                        !xfs_sb_version_hasprojid32bit(&ip->i_mount->m_sb))
 947                return XFS_ERROR(EINVAL);
 948
 949        /*
 950         * If disk quotas is on, we make sure that the dquots do exist on disk,
 951         * before we start any other transactions. Trying to do this later
 952         * is messy. We don't care to take a readlock to look at the ids
 953         * in inode here, because we can't hold it across the trans_reserve.
 954         * If the IDs do change before we take the ilock, we're covered
 955         * because the i_*dquot fields will get updated anyway.
 956         */
 957        if (XFS_IS_QUOTA_ON(mp) && (mask & FSX_PROJID)) {
 958                code = xfs_qm_vop_dqalloc(ip, ip->i_d.di_uid,
 959                                         ip->i_d.di_gid, fa->fsx_projid,
 960                                         XFS_QMOPT_PQUOTA, &udqp, NULL, &pdqp);
 961                if (code)
 962                        return code;
 963        }
 964
 965        /*
 966         * For the other attributes, we acquire the inode lock and
 967         * first do an error checking pass.
 968         */
 969        tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_NOT_SIZE);
 970        code = xfs_trans_reserve(tp, 0, XFS_ICHANGE_LOG_RES(mp), 0, 0, 0);
 971        if (code)
 972                goto error_return;
 973
 974        lock_flags = XFS_ILOCK_EXCL;
 975        xfs_ilock(ip, lock_flags);
 976
 977        /*
 978         * CAP_FOWNER overrides the following restrictions:
 979         *
 980         * The user ID of the calling process must be equal
 981         * to the file owner ID, except in cases where the
 982         * CAP_FSETID capability is applicable.
 983         */
 984        if (current_fsuid() != ip->i_d.di_uid && !capable(CAP_FOWNER)) {
 985                code = XFS_ERROR(EPERM);
 986                goto error_return;
 987        }
 988
 989        /*
 990         * Do a quota reservation only if projid is actually going to change.
 991         */
 992        if (mask & FSX_PROJID) {
 993                if (XFS_IS_QUOTA_RUNNING(mp) &&
 994                    XFS_IS_PQUOTA_ON(mp) &&
 995                    xfs_get_projid(ip) != fa->fsx_projid) {
 996                        ASSERT(tp);
 997                        code = xfs_qm_vop_chown_reserve(tp, ip, udqp, NULL,
 998                                                pdqp, capable(CAP_FOWNER) ?
 999                                                XFS_QMOPT_FORCE_RES : 0);
1000                        if (code)       /* out of quota */
1001                                goto error_return;
1002                }
1003        }
1004
1005        if (mask & FSX_EXTSIZE) {
1006                /*
1007                 * Can't change extent size if any extents are allocated.
1008                 */
1009                if (ip->i_d.di_nextents &&
1010                    ((ip->i_d.di_extsize << mp->m_sb.sb_blocklog) !=
1011                     fa->fsx_extsize)) {
1012                        code = XFS_ERROR(EINVAL);       /* EFBIG? */
1013                        goto error_return;
1014                }
1015
1016                /*
1017                 * Extent size must be a multiple of the appropriate block
1018                 * size, if set at all. It must also be smaller than the
1019                 * maximum extent size supported by the filesystem.
1020                 *
1021                 * Also, for non-realtime files, limit the extent size hint to
1022                 * half the size of the AGs in the filesystem so alignment
1023                 * doesn't result in extents larger than an AG.
1024                 */
1025                if (fa->fsx_extsize != 0) {
1026                        xfs_extlen_t    size;
1027                        xfs_fsblock_t   extsize_fsb;
1028
1029                        extsize_fsb = XFS_B_TO_FSB(mp, fa->fsx_extsize);
1030                        if (extsize_fsb > MAXEXTLEN) {
1031                                code = XFS_ERROR(EINVAL);
1032                                goto error_return;
1033                        }
1034
1035                        if (XFS_IS_REALTIME_INODE(ip) ||
1036                            ((mask & FSX_XFLAGS) &&
1037                            (fa->fsx_xflags & XFS_XFLAG_REALTIME))) {
1038                                size = mp->m_sb.sb_rextsize <<
1039                                       mp->m_sb.sb_blocklog;
1040                        } else {
1041                                size = mp->m_sb.sb_blocksize;
1042                                if (extsize_fsb > mp->m_sb.sb_agblocks / 2) {
1043                                        code = XFS_ERROR(EINVAL);
1044                                        goto error_return;
1045                                }
1046                        }
1047
1048                        if (fa->fsx_extsize % size) {
1049                                code = XFS_ERROR(EINVAL);
1050                                goto error_return;
1051                        }
1052                }
1053        }
1054
1055
1056        if (mask & FSX_XFLAGS) {
1057                /*
1058                 * Can't change realtime flag if any extents are allocated.
1059                 */
1060                if ((ip->i_d.di_nextents || ip->i_delayed_blks) &&
1061                    (XFS_IS_REALTIME_INODE(ip)) !=
1062                    (fa->fsx_xflags & XFS_XFLAG_REALTIME)) {
1063                        code = XFS_ERROR(EINVAL);       /* EFBIG? */
1064                        goto error_return;
1065                }
1066
1067                /*
1068                 * If realtime flag is set then must have realtime data.
1069                 */
1070                if ((fa->fsx_xflags & XFS_XFLAG_REALTIME)) {
1071                        if ((mp->m_sb.sb_rblocks == 0) ||
1072                            (mp->m_sb.sb_rextsize == 0) ||
1073                            (ip->i_d.di_extsize % mp->m_sb.sb_rextsize)) {
1074                                code = XFS_ERROR(EINVAL);
1075                                goto error_return;
1076                        }
1077                }
1078
1079                /*
1080                 * Can't modify an immutable/append-only file unless
1081                 * we have appropriate permission.
1082                 */
1083                if ((ip->i_d.di_flags &
1084                                (XFS_DIFLAG_IMMUTABLE|XFS_DIFLAG_APPEND) ||
1085                     (fa->fsx_xflags &
1086                                (XFS_XFLAG_IMMUTABLE | XFS_XFLAG_APPEND))) &&
1087                    !capable(CAP_LINUX_IMMUTABLE)) {
1088                        code = XFS_ERROR(EPERM);
1089                        goto error_return;
1090                }
1091        }
1092
1093        xfs_trans_ijoin(tp, ip, 0);
1094
1095        /*
1096         * Change file ownership.  Must be the owner or privileged.
1097         */
1098        if (mask & FSX_PROJID) {
1099                /*
1100                 * CAP_FSETID overrides the following restrictions:
1101                 *
1102                 * The set-user-ID and set-group-ID bits of a file will be
1103                 * cleared upon successful return from chown()
1104                 */
1105                if ((ip->i_d.di_mode & (S_ISUID|S_ISGID)) &&
1106                    !capable(CAP_FSETID))
1107                        ip->i_d.di_mode &= ~(S_ISUID|S_ISGID);
1108
1109                /*
1110                 * Change the ownerships and register quota modifications
1111                 * in the transaction.
1112                 */
1113                if (xfs_get_projid(ip) != fa->fsx_projid) {
1114                        if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_PQUOTA_ON(mp)) {
1115                                olddquot = xfs_qm_vop_chown(tp, ip,
1116                                                        &ip->i_pdquot, pdqp);
1117                        }
1118                        xfs_set_projid(ip, fa->fsx_projid);
1119
1120                        /*
1121                         * We may have to rev the inode as well as
1122                         * the superblock version number since projids didn't
1123                         * exist before DINODE_VERSION_2 and SB_VERSION_NLINK.
1124                         */
1125                        if (ip->i_d.di_version == 1)
1126                                xfs_bump_ino_vers2(tp, ip);
1127                }
1128
1129        }
1130
1131        if (mask & FSX_EXTSIZE)
1132                ip->i_d.di_extsize = fa->fsx_extsize >> mp->m_sb.sb_blocklog;
1133        if (mask & FSX_XFLAGS) {
1134                xfs_set_diflags(ip, fa->fsx_xflags);
1135                xfs_diflags_to_linux(ip);
1136        }
1137
1138        xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG);
1139        xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
1140
1141        XFS_STATS_INC(xs_ig_attrchg);
1142
1143        /*
1144         * If this is a synchronous mount, make sure that the
1145         * transaction goes to disk before returning to the user.
1146         * This is slightly sub-optimal in that truncates require
1147         * two sync transactions instead of one for wsync filesystems.
1148         * One for the truncate and one for the timestamps since we
1149         * don't want to change the timestamps unless we're sure the
1150         * truncate worked.  Truncates are less than 1% of the laddis
1151         * mix so this probably isn't worth the trouble to optimize.
1152         */
1153        if (mp->m_flags & XFS_MOUNT_WSYNC)
1154                xfs_trans_set_sync(tp);
1155        code = xfs_trans_commit(tp, 0);
1156        xfs_iunlock(ip, lock_flags);
1157
1158        /*
1159         * Release any dquot(s) the inode had kept before chown.
1160         */
1161        xfs_qm_dqrele(olddquot);
1162        xfs_qm_dqrele(udqp);
1163        xfs_qm_dqrele(pdqp);
1164
1165        return code;
1166
1167 error_return:
1168        xfs_qm_dqrele(udqp);
1169        xfs_qm_dqrele(pdqp);
1170        xfs_trans_cancel(tp, 0);
1171        if (lock_flags)
1172                xfs_iunlock(ip, lock_flags);
1173        return code;
1174}
1175
1176STATIC int
1177xfs_ioc_fssetxattr(
1178        xfs_inode_t             *ip,
1179        struct file             *filp,
1180        void                    __user *arg)
1181{
1182        struct fsxattr          fa;
1183        unsigned int            mask;
1184        int error;
1185
1186        if (copy_from_user(&fa, arg, sizeof(fa)))
1187                return -EFAULT;
1188
1189        mask = FSX_XFLAGS | FSX_EXTSIZE | FSX_PROJID;
1190        if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
1191                mask |= FSX_NONBLOCK;
1192
1193        error = mnt_want_write_file(filp);
1194        if (error)
1195                return error;
1196        error = xfs_ioctl_setattr(ip, &fa, mask);
1197        mnt_drop_write_file(filp);
1198        return -error;
1199}
1200
1201STATIC int
1202xfs_ioc_getxflags(
1203        xfs_inode_t             *ip,
1204        void                    __user *arg)
1205{
1206        unsigned int            flags;
1207
1208        flags = xfs_di2lxflags(ip->i_d.di_flags);
1209        if (copy_to_user(arg, &flags, sizeof(flags)))
1210                return -EFAULT;
1211        return 0;
1212}
1213
1214STATIC int
1215xfs_ioc_setxflags(
1216        xfs_inode_t             *ip,
1217        struct file             *filp,
1218        void                    __user *arg)
1219{
1220        struct fsxattr          fa;
1221        unsigned int            flags;
1222        unsigned int            mask;
1223        int error;
1224
1225        if (copy_from_user(&flags, arg, sizeof(flags)))
1226                return -EFAULT;
1227
1228        if (flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL | \
1229                      FS_NOATIME_FL | FS_NODUMP_FL | \
1230                      FS_SYNC_FL))
1231                return -EOPNOTSUPP;
1232
1233        mask = FSX_XFLAGS;
1234        if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
1235                mask |= FSX_NONBLOCK;
1236        fa.fsx_xflags = xfs_merge_ioc_xflags(flags, xfs_ip2xflags(ip));
1237
1238        error = mnt_want_write_file(filp);
1239        if (error)
1240                return error;
1241        error = xfs_ioctl_setattr(ip, &fa, mask);
1242        mnt_drop_write_file(filp);
1243        return -error;
1244}
1245
1246STATIC int
1247xfs_getbmap_format(void **ap, struct getbmapx *bmv, int *full)
1248{
1249        struct getbmap __user   *base = *ap;
1250
1251        /* copy only getbmap portion (not getbmapx) */
1252        if (copy_to_user(base, bmv, sizeof(struct getbmap)))
1253                return XFS_ERROR(EFAULT);
1254
1255        *ap += sizeof(struct getbmap);
1256        return 0;
1257}
1258
1259STATIC int
1260xfs_ioc_getbmap(
1261        struct xfs_inode        *ip,
1262        int                     ioflags,
1263        unsigned int            cmd,
1264        void                    __user *arg)
1265{
1266        struct getbmapx         bmx;
1267        int                     error;
1268
1269        if (copy_from_user(&bmx, arg, sizeof(struct getbmapx)))
1270                return -XFS_ERROR(EFAULT);
1271
1272        if (bmx.bmv_count < 2)
1273                return -XFS_ERROR(EINVAL);
1274
1275        bmx.bmv_iflags = (cmd == XFS_IOC_GETBMAPA ? BMV_IF_ATTRFORK : 0);
1276        if (ioflags & IO_INVIS)
1277                bmx.bmv_iflags |= BMV_IF_NO_DMAPI_READ;
1278
1279        error = xfs_getbmap(ip, &bmx, xfs_getbmap_format,
1280                            (struct getbmap *)arg+1);
1281        if (error)
1282                return -error;
1283
1284        /* copy back header - only size of getbmap */
1285        if (copy_to_user(arg, &bmx, sizeof(struct getbmap)))
1286                return -XFS_ERROR(EFAULT);
1287        return 0;
1288}
1289
1290STATIC int
1291xfs_getbmapx_format(void **ap, struct getbmapx *bmv, int *full)
1292{
1293        struct getbmapx __user  *base = *ap;
1294
1295        if (copy_to_user(base, bmv, sizeof(struct getbmapx)))
1296                return XFS_ERROR(EFAULT);
1297
1298        *ap += sizeof(struct getbmapx);
1299        return 0;
1300}
1301
1302STATIC int
1303xfs_ioc_getbmapx(
1304        struct xfs_inode        *ip,
1305        void                    __user *arg)
1306{
1307        struct getbmapx         bmx;
1308        int                     error;
1309
1310        if (copy_from_user(&bmx, arg, sizeof(bmx)))
1311                return -XFS_ERROR(EFAULT);
1312
1313        if (bmx.bmv_count < 2)
1314                return -XFS_ERROR(EINVAL);
1315
1316        if (bmx.bmv_iflags & (~BMV_IF_VALID))
1317                return -XFS_ERROR(EINVAL);
1318
1319        error = xfs_getbmap(ip, &bmx, xfs_getbmapx_format,
1320                            (struct getbmapx *)arg+1);
1321        if (error)
1322                return -error;
1323
1324        /* copy back header */
1325        if (copy_to_user(arg, &bmx, sizeof(struct getbmapx)))
1326                return -XFS_ERROR(EFAULT);
1327
1328        return 0;
1329}
1330
1331/*
1332 * Note: some of the ioctl's return positive numbers as a
1333 * byte count indicating success, such as readlink_by_handle.
1334 * So we don't "sign flip" like most other routines.  This means
1335 * true errors need to be returned as a negative value.
1336 */
1337long
1338xfs_file_ioctl(
1339        struct file             *filp,
1340        unsigned int            cmd,
1341        unsigned long           p)
1342{
1343        struct inode            *inode = file_inode(filp);
1344        struct xfs_inode        *ip = XFS_I(inode);
1345        struct xfs_mount        *mp = ip->i_mount;
1346        void                    __user *arg = (void __user *)p;
1347        int                     ioflags = 0;
1348        int                     error;
1349
1350        if (filp->f_mode & FMODE_NOCMTIME)
1351                ioflags |= IO_INVIS;
1352
1353        trace_xfs_file_ioctl(ip);
1354
1355        switch (cmd) {
1356        case FITRIM:
1357                return xfs_ioc_trim(mp, arg);
1358        case XFS_IOC_ALLOCSP:
1359        case XFS_IOC_FREESP:
1360        case XFS_IOC_RESVSP:
1361        case XFS_IOC_UNRESVSP:
1362        case XFS_IOC_ALLOCSP64:
1363        case XFS_IOC_FREESP64:
1364        case XFS_IOC_RESVSP64:
1365        case XFS_IOC_UNRESVSP64:
1366        case XFS_IOC_ZERO_RANGE: {
1367                xfs_flock64_t           bf;
1368
1369                if (copy_from_user(&bf, arg, sizeof(bf)))
1370                        return -XFS_ERROR(EFAULT);
1371                return xfs_ioc_space(ip, inode, filp, ioflags, cmd, &bf);
1372        }
1373        case XFS_IOC_DIOINFO: {
1374                struct dioattr  da;
1375                xfs_buftarg_t   *target =
1376                        XFS_IS_REALTIME_INODE(ip) ?
1377                        mp->m_rtdev_targp : mp->m_ddev_targp;
1378
1379                da.d_mem = da.d_miniosz = 1 << target->bt_sshift;
1380                da.d_maxiosz = INT_MAX & ~(da.d_miniosz - 1);
1381
1382                if (copy_to_user(arg, &da, sizeof(da)))
1383                        return -XFS_ERROR(EFAULT);
1384                return 0;
1385        }
1386
1387        case XFS_IOC_FSBULKSTAT_SINGLE:
1388        case XFS_IOC_FSBULKSTAT:
1389        case XFS_IOC_FSINUMBERS:
1390                return xfs_ioc_bulkstat(mp, cmd, arg);
1391
1392        case XFS_IOC_FSGEOMETRY_V1:
1393                return xfs_ioc_fsgeometry_v1(mp, arg);
1394
1395        case XFS_IOC_FSGEOMETRY:
1396                return xfs_ioc_fsgeometry(mp, arg);
1397
1398        case XFS_IOC_GETVERSION:
1399                return put_user(inode->i_generation, (int __user *)arg);
1400
1401        case XFS_IOC_FSGETXATTR:
1402                return xfs_ioc_fsgetxattr(ip, 0, arg);
1403        case XFS_IOC_FSGETXATTRA:
1404                return xfs_ioc_fsgetxattr(ip, 1, arg);
1405        case XFS_IOC_FSSETXATTR:
1406                return xfs_ioc_fssetxattr(ip, filp, arg);
1407        case XFS_IOC_GETXFLAGS:
1408                return xfs_ioc_getxflags(ip, arg);
1409        case XFS_IOC_SETXFLAGS:
1410                return xfs_ioc_setxflags(ip, filp, arg);
1411
1412        case XFS_IOC_FSSETDM: {
1413                struct fsdmidata        dmi;
1414
1415                if (copy_from_user(&dmi, arg, sizeof(dmi)))
1416                        return -XFS_ERROR(EFAULT);
1417
1418                error = mnt_want_write_file(filp);
1419                if (error)
1420                        return error;
1421
1422                error = xfs_set_dmattrs(ip, dmi.fsd_dmevmask,
1423                                dmi.fsd_dmstate);
1424                mnt_drop_write_file(filp);
1425                return -error;
1426        }
1427
1428        case XFS_IOC_GETBMAP:
1429        case XFS_IOC_GETBMAPA:
1430                return xfs_ioc_getbmap(ip, ioflags, cmd, arg);
1431
1432        case XFS_IOC_GETBMAPX:
1433                return xfs_ioc_getbmapx(ip, arg);
1434
1435        case XFS_IOC_FD_TO_HANDLE:
1436        case XFS_IOC_PATH_TO_HANDLE:
1437        case XFS_IOC_PATH_TO_FSHANDLE: {
1438                xfs_fsop_handlereq_t    hreq;
1439
1440                if (copy_from_user(&hreq, arg, sizeof(hreq)))
1441                        return -XFS_ERROR(EFAULT);
1442                return xfs_find_handle(cmd, &hreq);
1443        }
1444        case XFS_IOC_OPEN_BY_HANDLE: {
1445                xfs_fsop_handlereq_t    hreq;
1446
1447                if (copy_from_user(&hreq, arg, sizeof(xfs_fsop_handlereq_t)))
1448                        return -XFS_ERROR(EFAULT);
1449                return xfs_open_by_handle(filp, &hreq);
1450        }
1451        case XFS_IOC_FSSETDM_BY_HANDLE:
1452                return xfs_fssetdm_by_handle(filp, arg);
1453
1454        case XFS_IOC_READLINK_BY_HANDLE: {
1455                xfs_fsop_handlereq_t    hreq;
1456
1457                if (copy_from_user(&hreq, arg, sizeof(xfs_fsop_handlereq_t)))
1458                        return -XFS_ERROR(EFAULT);
1459                return xfs_readlink_by_handle(filp, &hreq);
1460        }
1461        case XFS_IOC_ATTRLIST_BY_HANDLE:
1462                return xfs_attrlist_by_handle(filp, arg);
1463
1464        case XFS_IOC_ATTRMULTI_BY_HANDLE:
1465                return xfs_attrmulti_by_handle(filp, arg);
1466
1467        case XFS_IOC_SWAPEXT: {
1468                struct xfs_swapext      sxp;
1469
1470                if (copy_from_user(&sxp, arg, sizeof(xfs_swapext_t)))
1471                        return -XFS_ERROR(EFAULT);
1472                error = mnt_want_write_file(filp);
1473                if (error)
1474                        return error;
1475                error = xfs_swapext(&sxp);
1476                mnt_drop_write_file(filp);
1477                return -error;
1478        }
1479
1480        case XFS_IOC_FSCOUNTS: {
1481                xfs_fsop_counts_t out;
1482
1483                error = xfs_fs_counts(mp, &out);
1484                if (error)
1485                        return -error;
1486
1487                if (copy_to_user(arg, &out, sizeof(out)))
1488                        return -XFS_ERROR(EFAULT);
1489                return 0;
1490        }
1491
1492        case XFS_IOC_SET_RESBLKS: {
1493                xfs_fsop_resblks_t inout;
1494                __uint64_t         in;
1495
1496                if (!capable(CAP_SYS_ADMIN))
1497                        return -EPERM;
1498
1499                if (mp->m_flags & XFS_MOUNT_RDONLY)
1500                        return -XFS_ERROR(EROFS);
1501
1502                if (copy_from_user(&inout, arg, sizeof(inout)))
1503                        return -XFS_ERROR(EFAULT);
1504
1505                error = mnt_want_write_file(filp);
1506                if (error)
1507                        return error;
1508
1509                /* input parameter is passed in resblks field of structure */
1510                in = inout.resblks;
1511                error = xfs_reserve_blocks(mp, &in, &inout);
1512                mnt_drop_write_file(filp);
1513                if (error)
1514                        return -error;
1515
1516                if (copy_to_user(arg, &inout, sizeof(inout)))
1517                        return -XFS_ERROR(EFAULT);
1518                return 0;
1519        }
1520
1521        case XFS_IOC_GET_RESBLKS: {
1522                xfs_fsop_resblks_t out;
1523
1524                if (!capable(CAP_SYS_ADMIN))
1525                        return -EPERM;
1526
1527                error = xfs_reserve_blocks(mp, NULL, &out);
1528                if (error)
1529                        return -error;
1530
1531                if (copy_to_user(arg, &out, sizeof(out)))
1532                        return -XFS_ERROR(EFAULT);
1533
1534                return 0;
1535        }
1536
1537        case XFS_IOC_FSGROWFSDATA: {
1538                xfs_growfs_data_t in;
1539
1540                if (copy_from_user(&in, arg, sizeof(in)))
1541                        return -XFS_ERROR(EFAULT);
1542
1543                error = mnt_want_write_file(filp);
1544                if (error)
1545                        return error;
1546                error = xfs_growfs_data(mp, &in);
1547                mnt_drop_write_file(filp);
1548                return -error;
1549        }
1550
1551        case XFS_IOC_FSGROWFSLOG: {
1552                xfs_growfs_log_t in;
1553
1554                if (copy_from_user(&in, arg, sizeof(in)))
1555                        return -XFS_ERROR(EFAULT);
1556
1557                error = mnt_want_write_file(filp);
1558                if (error)
1559                        return error;
1560                error = xfs_growfs_log(mp, &in);
1561                mnt_drop_write_file(filp);
1562                return -error;
1563        }
1564
1565        case XFS_IOC_FSGROWFSRT: {
1566                xfs_growfs_rt_t in;
1567
1568                if (copy_from_user(&in, arg, sizeof(in)))
1569                        return -XFS_ERROR(EFAULT);
1570
1571                error = mnt_want_write_file(filp);
1572                if (error)
1573                        return error;
1574                error = xfs_growfs_rt(mp, &in);
1575                mnt_drop_write_file(filp);
1576                return -error;
1577        }
1578
1579        case XFS_IOC_GOINGDOWN: {
1580                __uint32_t in;
1581
1582                if (!capable(CAP_SYS_ADMIN))
1583                        return -EPERM;
1584
1585                if (get_user(in, (__uint32_t __user *)arg))
1586                        return -XFS_ERROR(EFAULT);
1587
1588                error = xfs_fs_goingdown(mp, in);
1589                return -error;
1590        }
1591
1592        case XFS_IOC_ERROR_INJECTION: {
1593                xfs_error_injection_t in;
1594
1595                if (!capable(CAP_SYS_ADMIN))
1596                        return -EPERM;
1597
1598                if (copy_from_user(&in, arg, sizeof(in)))
1599                        return -XFS_ERROR(EFAULT);
1600
1601                error = xfs_errortag_add(in.errtag, mp);
1602                return -error;
1603        }
1604
1605        case XFS_IOC_ERROR_CLEARALL:
1606                if (!capable(CAP_SYS_ADMIN))
1607                        return -EPERM;
1608
1609                error = xfs_errortag_clearall(mp, 1);
1610                return -error;
1611
1612        case XFS_IOC_FREE_EOFBLOCKS: {
1613                struct xfs_eofblocks eofb;
1614
1615                if (copy_from_user(&eofb, arg, sizeof(eofb)))
1616                        return -XFS_ERROR(EFAULT);
1617
1618                if (eofb.eof_version != XFS_EOFBLOCKS_VERSION)
1619                        return -XFS_ERROR(EINVAL);
1620
1621                if (eofb.eof_flags & ~XFS_EOF_FLAGS_VALID)
1622                        return -XFS_ERROR(EINVAL);
1623
1624                if (memchr_inv(&eofb.pad32, 0, sizeof(eofb.pad32)) ||
1625                    memchr_inv(eofb.pad64, 0, sizeof(eofb.pad64)))
1626                        return -XFS_ERROR(EINVAL);
1627
1628                error = xfs_icache_free_eofblocks(mp, &eofb);
1629                return -error;
1630        }
1631
1632        default:
1633                return -ENOTTY;
1634        }
1635}
1636
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.