LCOV - code coverage report
Current view: top level - fs/xfs - xfs_ioctl.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc3-djwx @ Mon Jul 31 20:08:22 PDT 2023 Lines: 826 993 83.2 %
Date: 2023-07-31 20:08:22 Functions: 41 43 95.3 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /*
       3             :  * Copyright (c) 2000-2005 Silicon Graphics, Inc.
       4             :  * All Rights Reserved.
       5             :  */
       6             : #include "xfs.h"
       7             : #include "xfs_fs.h"
       8             : #include "xfs_shared.h"
       9             : #include "xfs_format.h"
      10             : #include "xfs_log_format.h"
      11             : #include "xfs_trans_resv.h"
      12             : #include "xfs_mount.h"
      13             : #include "xfs_inode.h"
      14             : #include "xfs_rtalloc.h"
      15             : #include "xfs_iwalk.h"
      16             : #include "xfs_itable.h"
      17             : #include "xfs_error.h"
      18             : #include "xfs_da_format.h"
      19             : #include "xfs_da_btree.h"
      20             : #include "xfs_attr.h"
      21             : #include "xfs_bmap.h"
      22             : #include "xfs_bmap_util.h"
      23             : #include "xfs_fsops.h"
      24             : #include "xfs_discard.h"
      25             : #include "xfs_quota.h"
      26             : #include "xfs_export.h"
      27             : #include "xfs_trace.h"
      28             : #include "xfs_icache.h"
      29             : #include "xfs_trans.h"
      30             : #include "xfs_acl.h"
      31             : #include "xfs_btree.h"
      32             : #include <linux/fsmap.h>
      33             : #include "xfs_fsmap.h"
      34             : #include "scrub/xfs_scrub.h"
      35             : #include "xfs_sb.h"
      36             : #include "xfs_ag.h"
      37             : #include "xfs_health.h"
      38             : #include "xfs_reflink.h"
      39             : #include "xfs_ioctl.h"
      40             : #include "xfs_xattr.h"
      41             : 
      42             : #include <linux/mount.h>
      43             : #include <linux/namei.h>
      44             : #include <linux/fileattr.h>
      45             : 
      46             : /*
      47             :  * xfs_find_handle maps from userspace xfs_fsop_handlereq structure to
      48             :  * a file or fs handle.
      49             :  *
      50             :  * XFS_IOC_PATH_TO_FSHANDLE
      51             :  *    returns fs handle for a mount point or path within that mount point
      52             :  * XFS_IOC_FD_TO_HANDLE
      53             :  *    returns full handle for a FD opened in user space
      54             :  * XFS_IOC_PATH_TO_HANDLE
      55             :  *    returns full handle for a path
      56             :  */
      57             : int
      58      207627 : xfs_find_handle(
      59             :         unsigned int            cmd,
      60             :         xfs_fsop_handlereq_t    *hreq)
      61             : {
      62      207627 :         int                     hsize;
      63      207627 :         xfs_handle_t            handle;
      64      207627 :         struct inode            *inode;
      65      207627 :         struct fd               f = {NULL};
      66      207627 :         struct path             path;
      67      207627 :         int                     error;
      68      207627 :         struct xfs_inode        *ip;
      69             : 
      70      207627 :         if (cmd == XFS_IOC_FD_TO_HANDLE) {
      71          11 :                 f = fdget(hreq->fd);
      72          11 :                 if (!f.file)
      73             :                         return -EBADF;
      74          11 :                 inode = file_inode(f.file);
      75             :         } else {
      76      207616 :                 error = user_path_at(AT_FDCWD, hreq->path, 0, &path);
      77      207616 :                 if (error)
      78             :                         return error;
      79      207616 :                 inode = d_inode(path.dentry);
      80             :         }
      81      207627 :         ip = XFS_I(inode);
      82             : 
      83             :         /*
      84             :          * We can only generate handles for inodes residing on a XFS filesystem,
      85             :          * and only for regular files, directories or symbolic links.
      86             :          */
      87      207627 :         error = -EINVAL;
      88      207627 :         if (inode->i_sb->s_magic != XFS_SB_MAGIC)
      89           0 :                 goto out_put;
      90             : 
      91      207627 :         error = -EBADF;
      92      207627 :         if (!S_ISREG(inode->i_mode) &&
      93           0 :             !S_ISDIR(inode->i_mode) &&
      94             :             !S_ISLNK(inode->i_mode))
      95           0 :                 goto out_put;
      96             : 
      97             : 
      98      207627 :         memcpy(&handle.ha_fsid, ip->i_mount->m_fixedfsid, sizeof(xfs_fsid_t));
      99             : 
     100      207627 :         if (cmd == XFS_IOC_PATH_TO_FSHANDLE) {
     101             :                 /*
     102             :                  * This handle only contains an fsid, zero the rest.
     103             :                  */
     104      191022 :                 memset(&handle.ha_fid, 0, sizeof(handle.ha_fid));
     105      191022 :                 hsize = sizeof(xfs_fsid_t);
     106             :         } else {
     107       16605 :                 handle.ha_fid.fid_len = sizeof(xfs_fid_t) -
     108             :                                         sizeof(handle.ha_fid.fid_len);
     109       16605 :                 handle.ha_fid.fid_pad = 0;
     110       16605 :                 handle.ha_fid.fid_gen = inode->i_generation;
     111       16605 :                 handle.ha_fid.fid_ino = ip->i_ino;
     112       16605 :                 hsize = sizeof(xfs_handle_t);
     113             :         }
     114             : 
     115      207627 :         error = -EFAULT;
     116      622881 :         if (copy_to_user(hreq->ohandle, &handle, hsize) ||
     117      207627 :             copy_to_user(hreq->ohandlen, &hsize, sizeof(__s32)))
     118           0 :                 goto out_put;
     119             : 
     120             :         error = 0;
     121             : 
     122      207627 :  out_put:
     123      207627 :         if (cmd == XFS_IOC_FD_TO_HANDLE)
     124          11 :                 fdput(f);
     125             :         else
     126      207616 :                 path_put(&path);
     127             :         return error;
     128             : }
     129             : 
     130             : /*
     131             :  * No need to do permission checks on the various pathname components
     132             :  * as the handle operations are privileged.
     133             :  */
     134             : STATIC int
     135   225981848 : xfs_handle_acceptable(
     136             :         void                    *context,
     137             :         struct dentry           *dentry)
     138             : {
     139   225981848 :         return 1;
     140             : }
     141             : 
     142             : /*
     143             :  * Convert userspace handle data into a dentry.
     144             :  */
     145             : struct dentry *
     146   225416638 : xfs_handle_to_dentry(
     147             :         struct file             *parfilp,
     148             :         void __user             *uhandle,
     149             :         u32                     hlen)
     150             : {
     151   225416638 :         xfs_handle_t            handle;
     152   225416638 :         struct xfs_fid64        fid;
     153             : 
     154             :         /*
     155             :          * Only allow handle opens under a directory.
     156             :          */
     157   225416638 :         if (!S_ISDIR(file_inode(parfilp)->i_mode))
     158             :                 return ERR_PTR(-ENOTDIR);
     159             : 
     160   225457664 :         if (hlen != sizeof(xfs_handle_t))
     161             :                 return ERR_PTR(-EINVAL);
     162   225362766 :         if (copy_from_user(&handle, uhandle, hlen))
     163             :                 return ERR_PTR(-EFAULT);
     164   225480308 :         if (handle.ha_fid.fid_len !=
     165             :             sizeof(handle.ha_fid) - sizeof(handle.ha_fid.fid_len))
     166             :                 return ERR_PTR(-EINVAL);
     167             : 
     168   225850144 :         memset(&fid, 0, sizeof(struct fid));
     169   225850144 :         fid.ino = handle.ha_fid.fid_ino;
     170   225850144 :         fid.gen = handle.ha_fid.fid_gen;
     171             : 
     172   225850144 :         return exportfs_decode_fh(parfilp->f_path.mnt, (struct fid *)&fid, 3,
     173             :                         FILEID_INO32_GEN | XFS_FILEID_TYPE_64FLAG,
     174             :                         xfs_handle_acceptable, NULL);
     175             : }
     176             : 
     177             : STATIC struct dentry *
     178   225500434 : xfs_handlereq_to_dentry(
     179             :         struct file             *parfilp,
     180             :         xfs_fsop_handlereq_t    *hreq)
     181             : {
     182   225500434 :         return xfs_handle_to_dentry(parfilp, hreq->ihandle, hreq->ihandlen);
     183             : }
     184             : 
     185             : int
     186   182746235 : xfs_open_by_handle(
     187             :         struct file             *parfilp,
     188             :         xfs_fsop_handlereq_t    *hreq)
     189             : {
     190   182746235 :         const struct cred       *cred = current_cred();
     191   182746235 :         int                     error;
     192   182746235 :         int                     fd;
     193   182746235 :         int                     permflag;
     194   182746235 :         struct file             *filp;
     195   182746235 :         struct inode            *inode;
     196   182746235 :         struct dentry           *dentry;
     197   182746235 :         fmode_t                 fmode;
     198   182746235 :         struct path             path;
     199             : 
     200   182746235 :         if (!capable(CAP_SYS_ADMIN))
     201             :                 return -EPERM;
     202             : 
     203   182459996 :         dentry = xfs_handlereq_to_dentry(parfilp, hreq);
     204   183398920 :         if (IS_ERR(dentry))
     205       12194 :                 return PTR_ERR(dentry);
     206   183386726 :         inode = d_inode(dentry);
     207             : 
     208             :         /* Restrict xfs_open_by_handle to directories & regular files. */
     209   183386726 :         if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) {
     210           0 :                 error = -EPERM;
     211           0 :                 goto out_dput;
     212             :         }
     213             : 
     214             : #if BITS_PER_LONG != 32
     215   183386726 :         hreq->oflags |= O_LARGEFILE;
     216             : #endif
     217             : 
     218   183386726 :         permflag = hreq->oflags;
     219   183386726 :         fmode = OPEN_FMODE(permflag);
     220   183386726 :         if ((!(permflag & O_APPEND) || (permflag & O_TRUNC)) &&
     221   183386682 :             (fmode & FMODE_WRITE) && IS_APPEND(inode)) {
     222          66 :                 error = -EPERM;
     223          66 :                 goto out_dput;
     224             :         }
     225             : 
     226   183386660 :         if ((fmode & FMODE_WRITE) && IS_IMMUTABLE(inode)) {
     227          88 :                 error = -EPERM;
     228          88 :                 goto out_dput;
     229             :         }
     230             : 
     231             :         /* Can't write directories. */
     232   183386572 :         if (S_ISDIR(inode->i_mode) && (fmode & FMODE_WRITE)) {
     233           0 :                 error = -EISDIR;
     234           0 :                 goto out_dput;
     235             :         }
     236             : 
     237   183386572 :         fd = get_unused_fd_flags(0);
     238   183784465 :         if (fd < 0) {
     239           0 :                 error = fd;
     240           0 :                 goto out_dput;
     241             :         }
     242             : 
     243   183784465 :         path.mnt = parfilp->f_path.mnt;
     244   183784465 :         path.dentry = dentry;
     245   183784465 :         filp = dentry_open(&path, hreq->oflags, cred);
     246   182986605 :         dput(dentry);
     247   183381273 :         if (IS_ERR(filp)) {
     248           0 :                 put_unused_fd(fd);
     249           0 :                 return PTR_ERR(filp);
     250             :         }
     251             : 
     252   183381273 :         if (S_ISREG(inode->i_mode)) {
     253   116710532 :                 filp->f_flags |= O_NOATIME;
     254   116710532 :                 filp->f_mode |= FMODE_NOCMTIME;
     255             :         }
     256             : 
     257   183381273 :         fd_install(fd, filp);
     258   183381273 :         return fd;
     259             : 
     260         154 :  out_dput:
     261         154 :         dput(dentry);
     262         154 :         return error;
     263             : }
     264             : 
     265             : int
     266        1000 : xfs_readlink_by_handle(
     267             :         struct file             *parfilp,
     268             :         xfs_fsop_handlereq_t    *hreq)
     269             : {
     270        1000 :         struct dentry           *dentry;
     271        1000 :         __u32                   olen;
     272        1000 :         int                     error;
     273             : 
     274        1000 :         if (!capable(CAP_SYS_ADMIN))
     275             :                 return -EPERM;
     276             : 
     277        1000 :         dentry = xfs_handlereq_to_dentry(parfilp, hreq);
     278        1000 :         if (IS_ERR(dentry))
     279           0 :                 return PTR_ERR(dentry);
     280             : 
     281             :         /* Restrict this handle operation to symlinks only. */
     282        1000 :         if (!d_is_symlink(dentry)) {
     283          11 :                 error = -EINVAL;
     284          11 :                 goto out_dput;
     285             :         }
     286             : 
     287         989 :         if (copy_from_user(&olen, hreq->ohandlen, sizeof(__u32))) {
     288           0 :                 error = -EFAULT;
     289           0 :                 goto out_dput;
     290             :         }
     291             : 
     292         989 :         error = vfs_readlink(dentry, hreq->ohandle, olen);
     293             : 
     294        1000 :  out_dput:
     295        1000 :         dput(dentry);
     296        1000 :         return error;
     297             : }
     298             : 
     299             : /*
     300             :  * Format an attribute and copy it out to the user's buffer.
     301             :  * Take care to check values and protect against them changing later,
     302             :  * we may be reading them directly out of a user buffer.
     303             :  */
     304             : static void
     305    85601974 : xfs_ioc_attr_put_listent(
     306             :         struct xfs_attr_list_context *context,
     307             :         int                     flags,
     308             :         unsigned char           *name,
     309             :         int                     namelen,
     310             :         int                     valuelen)
     311             : {
     312    85601974 :         struct xfs_attrlist     *alist = context->buffer;
     313    85601974 :         struct xfs_attrlist_ent *aep;
     314    85601974 :         int                     arraytop;
     315             : 
     316    85601974 :         ASSERT(!context->seen_enough);
     317    85601974 :         ASSERT(context->count >= 0);
     318    85601974 :         ASSERT(context->count < (ATTR_MAX_VALUELEN/8));
     319    85601974 :         ASSERT(context->firstu >= sizeof(*alist));
     320    85601974 :         ASSERT(context->firstu <= context->bufsize);
     321             : 
     322             :         /*
     323             :          * Only list entries in the right namespace.
     324             :          */
     325    85601974 :         if (context->attr_filter != (flags & XFS_ATTR_NSP_ONDISK_MASK))
     326             :                 return;
     327             : 
     328    28977491 :         arraytop = sizeof(*alist) +
     329    28977491 :                         context->count * sizeof(alist->al_offset[0]);
     330             : 
     331             :         /* decrement by the actual bytes used by the attr */
     332    28977491 :         context->firstu -= round_up(offsetof(struct xfs_attrlist_ent, a_name) +
     333             :                         namelen + 1, sizeof(uint32_t));
     334    28977491 :         if (context->firstu < arraytop) {
     335        1036 :                 trace_xfs_attr_list_full(context);
     336        1036 :                 alist->al_more = 1;
     337        1036 :                 context->seen_enough = 1;
     338        1036 :                 return;
     339             :         }
     340             : 
     341    28976455 :         aep = context->buffer + context->firstu;
     342    28976455 :         aep->a_valuelen = valuelen;
     343    57952910 :         memcpy(aep->a_name, name, namelen);
     344    28976455 :         aep->a_name[namelen] = 0;
     345    28976455 :         alist->al_offset[context->count++] = context->firstu;
     346    28976455 :         alist->al_count = context->count;
     347    28976455 :         trace_xfs_attr_list_add(context);
     348             : }
     349             : 
     350             : static unsigned int
     351             : xfs_attr_filter(
     352             :         u32                     ioc_flags)
     353             : {
     354    43379555 :         if (ioc_flags & XFS_IOC_ATTR_ROOT)
     355             :                 return XFS_ATTR_ROOT;
     356    28920185 :         if (ioc_flags & XFS_IOC_ATTR_SECURE)
     357    14466396 :                 return XFS_ATTR_SECURE;
     358             :         return 0;
     359             : }
     360             : 
     361             : static unsigned int
     362             : xfs_attr_flags(
     363             :         u32                     ioc_flags)
     364             : {
     365         770 :         if (ioc_flags & XFS_IOC_ATTR_CREATE)
     366             :                 return XATTR_CREATE;
     367         770 :         if (ioc_flags & XFS_IOC_ATTR_REPLACE)
     368           0 :                 return XATTR_REPLACE;
     369             :         return 0;
     370             : }
     371             : 
     372             : int
     373    43383643 : xfs_ioc_attr_list(
     374             :         struct xfs_inode                *dp,
     375             :         void __user                     *ubuf,
     376             :         size_t                          bufsize,
     377             :         int                             flags,
     378             :         struct xfs_attrlist_cursor __user *ucursor)
     379             : {
     380    43383643 :         struct xfs_attr_list_context    context = { };
     381    43383643 :         struct xfs_attrlist             *alist;
     382    43383643 :         void                            *buffer;
     383    43383643 :         int                             error;
     384             : 
     385    43383643 :         if (bufsize < sizeof(struct xfs_attrlist) ||
     386             :             bufsize > XFS_XATTR_LIST_MAX)
     387             :                 return -EINVAL;
     388             : 
     389             :         /*
     390             :          * Reject flags, only allow namespaces.
     391             :          */
     392    43383643 :         if (flags & ~(XFS_IOC_ATTR_ROOT | XFS_IOC_ATTR_SECURE))
     393             :                 return -EINVAL;
     394    43383643 :         if (flags == (XFS_IOC_ATTR_ROOT | XFS_IOC_ATTR_SECURE))
     395             :                 return -EINVAL;
     396             : 
     397             :         /*
     398             :          * Validate the cursor.
     399             :          */
     400    43383643 :         if (copy_from_user(&context.cursor, ucursor, sizeof(context.cursor)))
     401             :                 return -EFAULT;
     402    43151643 :         if (context.cursor.pad1 || context.cursor.pad2)
     403             :                 return -EINVAL;
     404    43151643 :         if (!context.cursor.initted &&
     405    43150607 :             (context.cursor.hashval || context.cursor.blkno ||
     406    43150607 :              context.cursor.offset))
     407             :                 return -EINVAL;
     408             : 
     409    43151643 :         buffer = kvzalloc(bufsize, GFP_KERNEL);
     410    43378785 :         if (!buffer)
     411             :                 return -ENOMEM;
     412             : 
     413             :         /*
     414             :          * Initialize the output buffer.
     415             :          */
     416    43378785 :         context.dp = dp;
     417    43378785 :         context.resynch = 1;
     418    43378785 :         context.attr_filter = xfs_attr_filter(flags);
     419    43378785 :         context.buffer = buffer;
     420    43378785 :         context.bufsize = round_down(bufsize, sizeof(uint32_t));
     421    43378785 :         context.firstu = context.bufsize;
     422    43378785 :         context.put_listent = xfs_ioc_attr_put_listent;
     423             : 
     424    43378785 :         alist = context.buffer;
     425    43378785 :         alist->al_count = 0;
     426    43378785 :         alist->al_more = 0;
     427    43378785 :         alist->al_offset[0] = context.bufsize;
     428             : 
     429    43378785 :         error = xfs_attr_list(&context);
     430    43024178 :         if (error)
     431           0 :                 goto out_free;
     432             : 
     433   129360974 :         if (copy_to_user(ubuf, buffer, bufsize) ||
     434             :             copy_to_user(ucursor, &context.cursor, sizeof(context.cursor)))
     435             :                 error = -EFAULT;
     436    42990600 : out_free:
     437    42990600 :         kmem_free(buffer);
     438    42990600 :         return error;
     439             : }
     440             : 
     441             : STATIC int
     442    42776395 : xfs_attrlist_by_handle(
     443             :         struct file             *parfilp,
     444             :         struct xfs_fsop_attrlist_handlereq __user *p)
     445             : {
     446    42776395 :         struct xfs_fsop_attrlist_handlereq al_hreq;
     447    42776395 :         struct dentry           *dentry;
     448    42776395 :         int                     error = -ENOMEM;
     449             : 
     450    42776395 :         if (!capable(CAP_SYS_ADMIN))
     451             :                 return -EPERM;
     452    42862221 :         if (copy_from_user(&al_hreq, p, sizeof(al_hreq)))
     453             :                 return -EFAULT;
     454             : 
     455    43030856 :         dentry = xfs_handlereq_to_dentry(parfilp, &al_hreq.hreq);
     456    43234369 :         if (IS_ERR(dentry))
     457           1 :                 return PTR_ERR(dentry);
     458             : 
     459    43234368 :         error = xfs_ioc_attr_list(XFS_I(d_inode(dentry)), al_hreq.buffer,
     460    43234368 :                                   al_hreq.buflen, al_hreq.flags, &p->pos);
     461    43428497 :         dput(dentry);
     462    43428497 :         return error;
     463             : }
     464             : 
     465             : static int
     466         770 : xfs_attrmulti_attr_get(
     467             :         struct inode            *inode,
     468             :         unsigned char           *name,
     469             :         unsigned char           __user *ubuf,
     470             :         uint32_t                *len,
     471             :         uint32_t                flags)
     472             : {
     473        2310 :         struct xfs_da_args      args = {
     474             :                 .dp             = XFS_I(inode),
     475             :                 .attr_filter    = xfs_attr_filter(flags),
     476             :                 .attr_flags     = xfs_attr_flags(flags),
     477             :                 .name           = name,
     478             :                 .namelen        = strlen(name),
     479         770 :                 .valuelen       = *len,
     480             :         };
     481         770 :         int                     error;
     482             : 
     483         770 :         if (*len > XFS_XATTR_SIZE_MAX)
     484             :                 return -EINVAL;
     485             : 
     486         770 :         error = xfs_attr_get(&args);
     487         770 :         if (error)
     488           0 :                 goto out_kfree;
     489             : 
     490         770 :         *len = args.valuelen;
     491        1540 :         if (copy_to_user(ubuf, args.value, args.valuelen))
     492           0 :                 error = -EFAULT;
     493             : 
     494         770 : out_kfree:
     495         770 :         kmem_free(args.value);
     496         770 :         return error;
     497             : }
     498             : 
     499             : static int
     500           0 : xfs_attrmulti_attr_set(
     501             :         struct inode            *inode,
     502             :         unsigned char           *name,
     503             :         const unsigned char     __user *ubuf,
     504             :         uint32_t                len,
     505             :         uint32_t                flags)
     506             : {
     507           0 :         struct xfs_da_args      args = {
     508             :                 .dp             = XFS_I(inode),
     509             :                 .attr_filter    = xfs_attr_filter(flags),
     510             :                 .attr_flags     = xfs_attr_flags(flags),
     511             :                 .name           = name,
     512             :                 .namelen        = strlen(name),
     513             :         };
     514           0 :         int                     error;
     515             : 
     516           0 :         if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
     517             :                 return -EPERM;
     518             : 
     519           0 :         if (ubuf) {
     520           0 :                 if (len > XFS_XATTR_SIZE_MAX)
     521             :                         return -EINVAL;
     522           0 :                 args.value = memdup_user(ubuf, len);
     523           0 :                 if (IS_ERR(args.value))
     524           0 :                         return PTR_ERR(args.value);
     525           0 :                 args.valuelen = len;
     526             :         }
     527             : 
     528           0 :         error = xfs_attr_change(&args);
     529           0 :         if (!error && (flags & XFS_IOC_ATTR_ROOT))
     530           0 :                 xfs_forget_acl(inode, name);
     531           0 :         kfree(args.value);
     532           0 :         return error;
     533             : }
     534             : 
     535             : int
     536         770 : xfs_ioc_attrmulti_one(
     537             :         struct file             *parfilp,
     538             :         struct inode            *inode,
     539             :         uint32_t                opcode,
     540             :         void __user             *uname,
     541             :         void __user             *value,
     542             :         uint32_t                *len,
     543             :         uint32_t                flags)
     544             : {
     545         770 :         unsigned char           *name;
     546         770 :         int                     error;
     547             : 
     548         770 :         if ((flags & XFS_IOC_ATTR_ROOT) && (flags & XFS_IOC_ATTR_SECURE))
     549             :                 return -EINVAL;
     550             : 
     551         770 :         name = strndup_user(uname, MAXNAMELEN);
     552         770 :         if (IS_ERR(name))
     553           0 :                 return PTR_ERR(name);
     554             : 
     555         770 :         switch (opcode) {
     556         770 :         case ATTR_OP_GET:
     557         770 :                 error = xfs_attrmulti_attr_get(inode, name, value, len, flags);
     558         770 :                 break;
     559           0 :         case ATTR_OP_REMOVE:
     560           0 :                 value = NULL;
     561           0 :                 *len = 0;
     562           0 :                 fallthrough;
     563           0 :         case ATTR_OP_SET:
     564           0 :                 error = mnt_want_write_file(parfilp);
     565           0 :                 if (error)
     566             :                         break;
     567           0 :                 error = xfs_attrmulti_attr_set(inode, name, value, *len, flags);
     568           0 :                 mnt_drop_write_file(parfilp);
     569           0 :                 break;
     570             :         default:
     571             :                 error = -EINVAL;
     572             :                 break;
     573             :         }
     574             : 
     575         770 :         kfree(name);
     576         770 :         return error;
     577             : }
     578             : 
     579             : STATIC int
     580         733 : xfs_attrmulti_by_handle(
     581             :         struct file             *parfilp,
     582             :         void                    __user *arg)
     583             : {
     584         733 :         int                     error;
     585         733 :         xfs_attr_multiop_t      *ops;
     586         733 :         xfs_fsop_attrmulti_handlereq_t am_hreq;
     587         733 :         struct dentry           *dentry;
     588         733 :         unsigned int            i, size;
     589             : 
     590         733 :         if (!capable(CAP_SYS_ADMIN))
     591             :                 return -EPERM;
     592         733 :         if (copy_from_user(&am_hreq, arg, sizeof(xfs_fsop_attrmulti_handlereq_t)))
     593             :                 return -EFAULT;
     594             : 
     595             :         /* overflow check */
     596         733 :         if (am_hreq.opcount >= INT_MAX / sizeof(xfs_attr_multiop_t))
     597             :                 return -E2BIG;
     598             : 
     599         733 :         dentry = xfs_handlereq_to_dentry(parfilp, &am_hreq.hreq);
     600         733 :         if (IS_ERR(dentry))
     601           0 :                 return PTR_ERR(dentry);
     602             : 
     603         733 :         error = -E2BIG;
     604         733 :         size = am_hreq.opcount * sizeof(xfs_attr_multiop_t);
     605         733 :         if (!size || size > 16 * PAGE_SIZE)
     606           0 :                 goto out_dput;
     607             : 
     608         733 :         ops = memdup_user(am_hreq.ops, size);
     609         733 :         if (IS_ERR(ops)) {
     610           0 :                 error = PTR_ERR(ops);
     611           0 :                 goto out_dput;
     612             :         }
     613             : 
     614             :         error = 0;
     615        1503 :         for (i = 0; i < am_hreq.opcount; i++) {
     616         770 :                 ops[i].am_error = xfs_ioc_attrmulti_one(parfilp,
     617             :                                 d_inode(dentry), ops[i].am_opcode,
     618             :                                 ops[i].am_attrname, ops[i].am_attrvalue,
     619         770 :                                 &ops[i].am_length, ops[i].am_flags);
     620             :         }
     621             : 
     622        1466 :         if (copy_to_user(am_hreq.ops, ops, size))
     623           0 :                 error = -EFAULT;
     624             : 
     625         733 :         kfree(ops);
     626         733 :  out_dput:
     627         733 :         dput(dentry);
     628         733 :         return error;
     629             : }
     630             : 
     631             : /* Return 0 on success or positive error */
     632             : int
     633 52503131984 : xfs_fsbulkstat_one_fmt(
     634             :         struct xfs_ibulk                *breq,
     635             :         const struct xfs_bulkstat       *bstat)
     636             : {
     637 52503131984 :         struct xfs_bstat                bs1;
     638             : 
     639 52503131984 :         xfs_bulkstat_to_bstat(breq->mp, &bs1, bstat);
     640 52151979533 :         if (copy_to_user(breq->ubuffer, &bs1, sizeof(bs1)))
     641             :                 return -EFAULT;
     642 52602501016 :         return xfs_ibulk_advance(breq, sizeof(struct xfs_bstat));
     643             : }
     644             : 
     645             : int
     646       69469 : xfs_fsinumbers_fmt(
     647             :         struct xfs_ibulk                *breq,
     648             :         const struct xfs_inumbers       *igrp)
     649             : {
     650       69469 :         struct xfs_inogrp               ig1;
     651             : 
     652       69469 :         xfs_inumbers_to_inogrp(&ig1, igrp);
     653       69469 :         if (copy_to_user(breq->ubuffer, &ig1, sizeof(struct xfs_inogrp)))
     654             :                 return -EFAULT;
     655       69469 :         return xfs_ibulk_advance(breq, sizeof(struct xfs_inogrp));
     656             : }
     657             : 
     658             : STATIC int
     659   349189493 : xfs_ioc_fsbulkstat(
     660             :         struct file             *file,
     661             :         unsigned int            cmd,
     662             :         void                    __user *arg)
     663             : {
     664   349189493 :         struct xfs_mount        *mp = XFS_I(file_inode(file))->i_mount;
     665   349189493 :         struct xfs_fsop_bulkreq bulkreq;
     666   349189493 :         struct xfs_ibulk        breq = {
     667             :                 .mp             = mp,
     668             :                 .idmap          = file_mnt_idmap(file),
     669             :                 .ocount         = 0,
     670             :         };
     671   349221151 :         xfs_ino_t               lastino;
     672   349221151 :         int                     error;
     673             : 
     674             :         /* done = 1 if there are more stats to get and if bulkstat */
     675             :         /* should be called again (unused here, but used in dmapi) */
     676             : 
     677   349221151 :         if (!capable(CAP_SYS_ADMIN))
     678             :                 return -EPERM;
     679             : 
     680   698373014 :         if (xfs_is_shutdown(mp))
     681             :                 return -EIO;
     682             : 
     683   349175935 :         if (copy_from_user(&bulkreq, arg, sizeof(struct xfs_fsop_bulkreq)))
     684             :                 return -EFAULT;
     685             : 
     686   349233127 :         if (copy_from_user(&lastino, bulkreq.lastip, sizeof(__s64)))
     687             :                 return -EFAULT;
     688             : 
     689   349156835 :         if (bulkreq.icount <= 0)
     690             :                 return -EINVAL;
     691             : 
     692   349156835 :         if (bulkreq.ubuffer == NULL)
     693             :                 return -EINVAL;
     694             : 
     695   349156835 :         breq.ubuffer = bulkreq.ubuffer;
     696   349156835 :         breq.icount = bulkreq.icount;
     697             : 
     698             :         /*
     699             :          * FSBULKSTAT_SINGLE expects that *lastip contains the inode number
     700             :          * that we want to stat.  However, FSINUMBERS and FSBULKSTAT expect
     701             :          * that *lastip contains either zero or the number of the last inode to
     702             :          * be examined by the previous call and return results starting with
     703             :          * the next inode after that.  The new bulk request back end functions
     704             :          * take the inode to start with, so we have to compute the startino
     705             :          * parameter from lastino to maintain correct function.  lastino == 0
     706             :          * is a special case because it has traditionally meant "first inode
     707             :          * in filesystem".
     708             :          */
     709   349156835 :         if (cmd == XFS_IOC_FSINUMBERS) {
     710       16879 :                 breq.startino = lastino ? lastino + 1 : 0;
     711       16879 :                 error = xfs_inumbers(&breq, xfs_fsinumbers_fmt);
     712       16879 :                 lastino = breq.startino - 1;
     713   349139956 :         } else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE) {
     714     1485655 :                 breq.startino = lastino;
     715     1485655 :                 breq.icount = 1;
     716     1485655 :                 error = xfs_bulkstat_one(&breq, xfs_fsbulkstat_one_fmt);
     717             :         } else {        /* XFS_IOC_FSBULKSTAT */
     718   347654301 :                 breq.startino = lastino ? lastino + 1 : 0;
     719   347654301 :                 error = xfs_bulkstat(&breq, xfs_fsbulkstat_one_fmt);
     720   347778179 :                 lastino = breq.startino - 1;
     721             :         }
     722             : 
     723   349280796 :         if (error)
     724             :                 return error;
     725             : 
     726   697016293 :         if (bulkreq.lastip != NULL &&
     727             :             copy_to_user(bulkreq.lastip, &lastino, sizeof(xfs_ino_t)))
     728             :                 return -EFAULT;
     729             : 
     730   696327109 :         if (bulkreq.ocount != NULL &&
     731             :             copy_to_user(bulkreq.ocount, &breq.ocount, sizeof(__s32)))
     732           0 :                 return -EFAULT;
     733             : 
     734             :         return 0;
     735             : }
     736             : 
     737             : /* Return 0 on success or positive error */
     738             : static int
     739   581604202 : xfs_bulkstat_fmt(
     740             :         struct xfs_ibulk                *breq,
     741             :         const struct xfs_bulkstat       *bstat)
     742             : {
     743  1163873364 :         if (copy_to_user(breq->ubuffer, bstat, sizeof(struct xfs_bulkstat)))
     744           0 :                 return -EFAULT;
     745   582269162 :         return xfs_ibulk_advance(breq, sizeof(struct xfs_bulkstat));
     746             : }
     747             : 
     748             : /*
     749             :  * Check the incoming bulk request @hdr from userspace and initialize the
     750             :  * internal @breq bulk request appropriately.  Returns 0 if the bulk request
     751             :  * should proceed; -ECANCELED if there's nothing to do; or the usual
     752             :  * negative error code.
     753             :  */
     754             : static int
     755    33653609 : xfs_bulk_ireq_setup(
     756             :         struct xfs_mount        *mp,
     757             :         const struct xfs_bulk_ireq *hdr,
     758             :         struct xfs_ibulk        *breq,
     759             :         void __user             *ubuffer)
     760             : {
     761    33653609 :         if (hdr->icount == 0 ||
     762    67308547 :             (hdr->flags & ~XFS_BULK_IREQ_FLAGS_ALL) ||
     763    33653609 :             memchr_inv(hdr->reserved, 0, sizeof(hdr->reserved)))
     764           0 :                 return -EINVAL;
     765             : 
     766    33654938 :         breq->startino = hdr->ino;
     767    33654938 :         breq->ubuffer = ubuffer;
     768    33654938 :         breq->icount = hdr->icount;
     769    33654938 :         breq->ocount = 0;
     770    33654938 :         breq->flags = 0;
     771             : 
     772             :         /*
     773             :          * The @ino parameter is a special value, so we must look it up here.
     774             :          * We're not allowed to have IREQ_AGNO, and we only return one inode
     775             :          * worth of data.
     776             :          */
     777    33654938 :         if (hdr->flags & XFS_BULK_IREQ_SPECIAL) {
     778          21 :                 if (hdr->flags & XFS_BULK_IREQ_AGNO)
     779             :                         return -EINVAL;
     780             : 
     781          21 :                 switch (hdr->ino) {
     782          21 :                 case XFS_BULK_IREQ_SPECIAL_ROOT:
     783          21 :                         breq->startino = mp->m_sb.sb_rootino;
     784          21 :                         break;
     785             :                 default:
     786             :                         return -EINVAL;
     787             :                 }
     788          21 :                 breq->icount = 1;
     789             :         }
     790             : 
     791             :         /*
     792             :          * The IREQ_AGNO flag means that we only want results from a given AG.
     793             :          * If @hdr->ino is zero, we start iterating in that AG.  If @hdr->ino is
     794             :          * beyond the specified AG then we return no results.
     795             :          */
     796    33654938 :         if (hdr->flags & XFS_BULK_IREQ_AGNO) {
     797    12111479 :                 if (hdr->agno >= mp->m_sb.sb_agcount)
     798             :                         return -EINVAL;
     799             : 
     800    12111479 :                 if (breq->startino == 0)
     801     1799227 :                         breq->startino = XFS_AGINO_TO_INO(mp, hdr->agno, 0);
     802    10312252 :                 else if (XFS_INO_TO_AGNO(mp, breq->startino) < hdr->agno)
     803             :                         return -EINVAL;
     804             : 
     805    12111479 :                 breq->flags |= XFS_IBULK_SAME_AG;
     806             : 
     807             :                 /* Asking for an inode past the end of the AG?  We're done! */
     808    12111479 :                 if (XFS_INO_TO_AGNO(mp, breq->startino) > hdr->agno)
     809             :                         return -ECANCELED;
     810    21543459 :         } else if (hdr->agno)
     811             :                 return -EINVAL;
     812             : 
     813             :         /* Asking for an inode past the end of the FS?  We're done! */
     814    33654896 :         if (XFS_INO_TO_AGNO(mp, breq->startino) >= mp->m_sb.sb_agcount)
     815             :                 return -ECANCELED;
     816             : 
     817    33654840 :         if (hdr->flags & XFS_BULK_IREQ_NREXT64)
     818    21301698 :                 breq->flags |= XFS_IBULK_NREXT64;
     819             : 
     820             :         return 0;
     821             : }
     822             : 
     823             : /*
     824             :  * Update the userspace bulk request @hdr to reflect the end state of the
     825             :  * internal bulk request @breq.
     826             :  */
     827             : static void
     828             : xfs_bulk_ireq_teardown(
     829             :         struct xfs_bulk_ireq    *hdr,
     830             :         struct xfs_ibulk        *breq)
     831             : {
     832    33643296 :         hdr->ino = breq->startino;
     833    33643296 :         hdr->ocount = breq->ocount;
     834             : }
     835             : 
     836             : /* Handle the v5 bulkstat ioctl. */
     837             : STATIC int
     838    21631780 : xfs_ioc_bulkstat(
     839             :         struct file                     *file,
     840             :         unsigned int                    cmd,
     841             :         struct xfs_bulkstat_req __user  *arg)
     842             : {
     843    21631780 :         struct xfs_mount                *mp = XFS_I(file_inode(file))->i_mount;
     844    21631780 :         struct xfs_bulk_ireq            hdr;
     845    21631780 :         struct xfs_ibulk                breq = {
     846             :                 .mp                     = mp,
     847             :                 .idmap                  = file_mnt_idmap(file),
     848             :         };
     849    21631141 :         int                             error;
     850             : 
     851    21631141 :         if (!capable(CAP_SYS_ADMIN))
     852             :                 return -EPERM;
     853             : 
     854    43263714 :         if (xfs_is_shutdown(mp))
     855             :                 return -EIO;
     856             : 
     857    21631857 :         if (copy_from_user(&hdr, &arg->hdr, sizeof(hdr)))
     858             :                 return -EFAULT;
     859             : 
     860    21632820 :         error = xfs_bulk_ireq_setup(mp, &hdr, &breq, arg->bulkstat);
     861    21628719 :         if (error == -ECANCELED)
     862          56 :                 goto out_teardown;
     863    21628663 :         if (error < 0)
     864             :                 return error;
     865             : 
     866    21628663 :         error = xfs_bulkstat(&breq, xfs_bulkstat_fmt);
     867    21632491 :         if (error)
     868             :                 return error;
     869             : 
     870    21632480 : out_teardown:
     871    21632536 :         xfs_bulk_ireq_teardown(&hdr, &breq);
     872    21632536 :         if (copy_to_user(&arg->hdr, &hdr, sizeof(hdr)))
     873           0 :                 return -EFAULT;
     874             : 
     875             :         return 0;
     876             : }
     877             : 
     878             : STATIC int
     879    15464441 : xfs_inumbers_fmt(
     880             :         struct xfs_ibulk                *breq,
     881             :         const struct xfs_inumbers       *igrp)
     882             : {
     883    30945455 :         if (copy_to_user(breq->ubuffer, igrp, sizeof(struct xfs_inumbers)))
     884           0 :                 return -EFAULT;
     885    15481014 :         return xfs_ibulk_advance(breq, sizeof(struct xfs_inumbers));
     886             : }
     887             : 
     888             : /* Handle the v5 inumbers ioctl. */
     889             : STATIC int
     890    12021525 : xfs_ioc_inumbers(
     891             :         struct xfs_mount                *mp,
     892             :         unsigned int                    cmd,
     893             :         struct xfs_inumbers_req __user  *arg)
     894             : {
     895    12021525 :         struct xfs_bulk_ireq            hdr;
     896    12021525 :         struct xfs_ibulk                breq = {
     897             :                 .mp                     = mp,
     898             :         };
     899    12021525 :         int                             error;
     900             : 
     901    12021525 :         if (!capable(CAP_SYS_ADMIN))
     902             :                 return -EPERM;
     903             : 
     904    24041178 :         if (xfs_is_shutdown(mp))
     905             :                 return -EIO;
     906             : 
     907    12020589 :         if (copy_from_user(&hdr, &arg->hdr, sizeof(hdr)))
     908             :                 return -EFAULT;
     909             : 
     910    12023631 :         error = xfs_bulk_ireq_setup(mp, &hdr, &breq, arg->inumbers);
     911    12011990 :         if (error == -ECANCELED)
     912          42 :                 goto out_teardown;
     913    12011948 :         if (error < 0)
     914             :                 return error;
     915             : 
     916    12011948 :         error = xfs_inumbers(&breq, xfs_inumbers_fmt);
     917    12010718 :         if (error)
     918             :                 return error;
     919             : 
     920    12010718 : out_teardown:
     921    12010760 :         xfs_bulk_ireq_teardown(&hdr, &breq);
     922    12010760 :         if (copy_to_user(&arg->hdr, &hdr, sizeof(hdr)))
     923           0 :                 return -EFAULT;
     924             : 
     925             :         return 0;
     926             : }
     927             : 
     928             : STATIC int
     929     5564375 : xfs_ioc_fsgeometry(
     930             :         struct xfs_mount        *mp,
     931             :         void                    __user *arg,
     932             :         int                     struct_version)
     933             : {
     934     5564375 :         struct xfs_fsop_geom    fsgeo;
     935     5564375 :         size_t                  len;
     936             : 
     937     5564375 :         xfs_fs_geometry(mp, &fsgeo, struct_version);
     938             : 
     939     5545999 :         if (struct_version <= 3)
     940             :                 len = sizeof(struct xfs_fsop_geom_v1);
     941     5545428 :         else if (struct_version == 4)
     942             :                 len = sizeof(struct xfs_fsop_geom_v4);
     943             :         else {
     944     5545735 :                 xfs_fsop_geom_health(mp, &fsgeo);
     945     5545735 :                 len = sizeof(fsgeo);
     946             :         }
     947             : 
     948    11121908 :         if (copy_to_user(arg, &fsgeo, len))
     949           0 :                 return -EFAULT;
     950             :         return 0;
     951             : }
     952             : 
     953             : STATIC int
     954       67727 : xfs_ioc_ag_geometry(
     955             :         struct xfs_mount        *mp,
     956             :         void                    __user *arg)
     957             : {
     958       67727 :         struct xfs_perag        *pag;
     959       67727 :         struct xfs_ag_geometry  ageo;
     960       67727 :         int                     error;
     961             : 
     962       67727 :         if (copy_from_user(&ageo, arg, sizeof(ageo)))
     963             :                 return -EFAULT;
     964       67727 :         if (ageo.ag_flags)
     965             :                 return -EINVAL;
     966       67727 :         if (memchr_inv(&ageo.ag_reserved, 0, sizeof(ageo.ag_reserved)))
     967             :                 return -EINVAL;
     968             : 
     969       67727 :         pag = xfs_perag_get(mp, ageo.ag_number);
     970       67727 :         if (!pag)
     971             :                 return -EINVAL;
     972             : 
     973       67727 :         error = xfs_ag_get_geometry(pag, &ageo);
     974       67727 :         xfs_perag_put(pag);
     975       67727 :         if (error)
     976             :                 return error;
     977             : 
     978       67727 :         if (copy_to_user(arg, &ageo, sizeof(ageo)))
     979           0 :                 return -EFAULT;
     980             :         return 0;
     981             : }
     982             : 
     983             : /*
     984             :  * Linux extended inode flags interface.
     985             :  */
     986             : 
     987             : static void
     988     3040624 : xfs_fill_fsxattr(
     989             :         struct xfs_inode        *ip,
     990             :         int                     whichfork,
     991             :         struct fileattr         *fa)
     992             : {
     993     3040624 :         struct xfs_mount        *mp = ip->i_mount;
     994     3040624 :         struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
     995             : 
     996     3040576 :         fileattr_fill_xflags(fa, xfs_ip2xflags(ip));
     997             : 
     998     3040540 :         if (ip->i_diflags & XFS_DIFLAG_EXTSIZE) {
     999          87 :                 fa->fsx_extsize = XFS_FSB_TO_B(mp, ip->i_extsize);
    1000     3040453 :         } else if (ip->i_diflags & XFS_DIFLAG_EXTSZINHERIT) {
    1001             :                 /*
    1002             :                  * Don't let a misaligned extent size hint on a directory
    1003             :                  * escape to userspace if it won't pass the setattr checks
    1004             :                  * later.
    1005             :                  */
    1006          48 :                 if ((ip->i_diflags & XFS_DIFLAG_RTINHERIT) &&
    1007          24 :                     ip->i_extsize % mp->m_sb.sb_rextsize > 0) {
    1008           6 :                         fa->fsx_xflags &= ~(FS_XFLAG_EXTSIZE |
    1009             :                                             FS_XFLAG_EXTSZINHERIT);
    1010           6 :                         fa->fsx_extsize = 0;
    1011             :                 } else {
    1012          42 :                         fa->fsx_extsize = XFS_FSB_TO_B(mp, ip->i_extsize);
    1013             :                 }
    1014             :         }
    1015             : 
    1016     3040540 :         if (ip->i_diflags2 & XFS_DIFLAG2_COWEXTSIZE)
    1017         716 :                 fa->fsx_cowextsize = XFS_FSB_TO_B(mp, ip->i_cowextsize);
    1018     3040540 :         fa->fsx_projid = ip->i_projid;
    1019     6053941 :         if (ifp && !xfs_need_iread_extents(ifp))
    1020     3013234 :                 fa->fsx_nextents = xfs_iext_count(ifp);
    1021             :         else
    1022       27523 :                 fa->fsx_nextents = xfs_ifork_nextents(ifp);
    1023     3040576 : }
    1024             : 
    1025             : STATIC int
    1026       27222 : xfs_ioc_fsgetxattra(
    1027             :         xfs_inode_t             *ip,
    1028             :         void                    __user *arg)
    1029             : {
    1030       27222 :         struct fileattr         fa;
    1031             : 
    1032       27222 :         xfs_ilock(ip, XFS_ILOCK_SHARED);
    1033       27222 :         xfs_fill_fsxattr(ip, XFS_ATTR_FORK, &fa);
    1034       27222 :         xfs_iunlock(ip, XFS_ILOCK_SHARED);
    1035             : 
    1036       27222 :         return copy_fsxattr_to_user(&fa, arg);
    1037             : }
    1038             : 
    1039             : int
    1040     3013419 : xfs_fileattr_get(
    1041             :         struct dentry           *dentry,
    1042             :         struct fileattr         *fa)
    1043             : {
    1044     3013419 :         struct xfs_inode        *ip = XFS_I(d_inode(dentry));
    1045             : 
    1046     3013419 :         if (d_is_special(dentry))
    1047             :                 return -ENOTTY;
    1048             : 
    1049     3013419 :         xfs_ilock(ip, XFS_ILOCK_SHARED);
    1050     3013417 :         xfs_fill_fsxattr(ip, XFS_DATA_FORK, fa);
    1051     3013345 :         xfs_iunlock(ip, XFS_ILOCK_SHARED);
    1052             : 
    1053     3013345 :         return 0;
    1054             : }
    1055             : 
    1056             : STATIC uint16_t
    1057     2108123 : xfs_flags2diflags(
    1058             :         struct xfs_inode        *ip,
    1059             :         unsigned int            xflags)
    1060             : {
    1061             :         /* can't set PREALLOC this way, just preserve it */
    1062     2108123 :         uint16_t                di_flags =
    1063     2108123 :                 (ip->i_diflags & XFS_DIFLAG_PREALLOC);
    1064             : 
    1065     2108123 :         if (xflags & FS_XFLAG_IMMUTABLE)
    1066         343 :                 di_flags |= XFS_DIFLAG_IMMUTABLE;
    1067     2108123 :         if (xflags & FS_XFLAG_APPEND)
    1068         276 :                 di_flags |= XFS_DIFLAG_APPEND;
    1069     2108123 :         if (xflags & FS_XFLAG_SYNC)
    1070         134 :                 di_flags |= XFS_DIFLAG_SYNC;
    1071     2108123 :         if (xflags & FS_XFLAG_NOATIME)
    1072          56 :                 di_flags |= XFS_DIFLAG_NOATIME;
    1073     2108123 :         if (xflags & FS_XFLAG_NODUMP)
    1074          78 :                 di_flags |= XFS_DIFLAG_NODUMP;
    1075     2108123 :         if (xflags & FS_XFLAG_NODEFRAG)
    1076           1 :                 di_flags |= XFS_DIFLAG_NODEFRAG;
    1077     2108123 :         if (xflags & FS_XFLAG_FILESTREAM)
    1078        5105 :                 di_flags |= XFS_DIFLAG_FILESTREAM;
    1079     2108123 :         if (S_ISDIR(VFS_I(ip)->i_mode)) {
    1080       51092 :                 if (xflags & FS_XFLAG_RTINHERIT)
    1081       18798 :                         di_flags |= XFS_DIFLAG_RTINHERIT;
    1082       51092 :                 if (xflags & FS_XFLAG_NOSYMLINKS)
    1083          33 :                         di_flags |= XFS_DIFLAG_NOSYMLINKS;
    1084       51092 :                 if (xflags & FS_XFLAG_EXTSZINHERIT)
    1085         194 :                         di_flags |= XFS_DIFLAG_EXTSZINHERIT;
    1086       51092 :                 if (xflags & FS_XFLAG_PROJINHERIT)
    1087        3474 :                         di_flags |= XFS_DIFLAG_PROJINHERIT;
    1088     2057031 :         } else if (S_ISREG(VFS_I(ip)->i_mode)) {
    1089     2057031 :                 if (xflags & FS_XFLAG_REALTIME)
    1090      660124 :                         di_flags |= XFS_DIFLAG_REALTIME;
    1091     2057031 :                 if (xflags & FS_XFLAG_EXTSIZE)
    1092         180 :                         di_flags |= XFS_DIFLAG_EXTSIZE;
    1093             :         }
    1094             : 
    1095     2108123 :         return di_flags;
    1096             : }
    1097             : 
    1098             : STATIC uint64_t
    1099     1498265 : xfs_flags2diflags2(
    1100             :         struct xfs_inode        *ip,
    1101             :         unsigned int            xflags)
    1102             : {
    1103     1498265 :         uint64_t                di_flags2 =
    1104     1498265 :                 (ip->i_diflags2 & (XFS_DIFLAG2_REFLINK |
    1105             :                                    XFS_DIFLAG2_BIGTIME |
    1106             :                                    XFS_DIFLAG2_NREXT64));
    1107             : 
    1108     1498265 :         if (xflags & FS_XFLAG_DAX)
    1109         132 :                 di_flags2 |= XFS_DIFLAG2_DAX;
    1110     1498265 :         if (xflags & FS_XFLAG_COWEXTSIZE)
    1111         736 :                 di_flags2 |= XFS_DIFLAG2_COWEXTSIZE;
    1112             : 
    1113     1498265 :         return di_flags2;
    1114             : }
    1115             : 
    1116             : static int
    1117      888412 : xfs_ioctl_setattr_xflags(
    1118             :         struct xfs_trans        *tp,
    1119             :         struct xfs_inode        *ip,
    1120             :         struct fileattr         *fa)
    1121             : {
    1122      888412 :         struct xfs_mount        *mp = ip->i_mount;
    1123      888412 :         uint64_t                i_flags2;
    1124             : 
    1125             :         /* Can't change realtime flag if any extents are allocated. */
    1126      888412 :         if ((ip->i_df.if_nextents || ip->i_delayed_blks) &&
    1127      782070 :             XFS_IS_REALTIME_INODE(ip) != (fa->fsx_xflags & FS_XFLAG_REALTIME))
    1128             :                 return -EINVAL;
    1129             : 
    1130             :         /* If realtime flag is set then must have realtime device */
    1131      888412 :         if (fa->fsx_xflags & FS_XFLAG_REALTIME) {
    1132      288426 :                 if (mp->m_sb.sb_rblocks == 0 || mp->m_sb.sb_rextsize == 0 ||
    1133      288426 :                     (ip->i_extsize % mp->m_sb.sb_rextsize))
    1134             :                         return -EINVAL;
    1135             :         }
    1136             : 
    1137             :         /* Clear reflink if we are actually able to set the rt flag. */
    1138      888412 :         if ((fa->fsx_xflags & FS_XFLAG_REALTIME) && xfs_is_reflink_inode(ip))
    1139           0 :                 ip->i_diflags2 &= ~XFS_DIFLAG2_REFLINK;
    1140             : 
    1141             :         /* diflags2 only valid for v3 inodes. */
    1142      888412 :         i_flags2 = xfs_flags2diflags2(ip, fa->fsx_xflags);
    1143      888412 :         if (i_flags2 && !xfs_has_v3inodes(mp))
    1144             :                 return -EINVAL;
    1145             : 
    1146      888412 :         ip->i_diflags = xfs_flags2diflags(ip, fa->fsx_xflags);
    1147      888412 :         ip->i_diflags2 = i_flags2;
    1148             : 
    1149      888412 :         xfs_diflags_to_iflags(ip, false);
    1150      888406 :         xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG);
    1151      888407 :         xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
    1152      888415 :         XFS_STATS_INC(mp, xs_ig_attrchg);
    1153      888416 :         return 0;
    1154             : }
    1155             : 
    1156             : static void
    1157      888429 : xfs_ioctl_setattr_prepare_dax(
    1158             :         struct xfs_inode        *ip,
    1159             :         struct fileattr         *fa)
    1160             : {
    1161      888429 :         struct xfs_mount        *mp = ip->i_mount;
    1162      888429 :         struct inode            *inode = VFS_I(ip);
    1163             : 
    1164      888429 :         if (S_ISDIR(inode->i_mode))
    1165             :                 return;
    1166             : 
    1167      858074 :         if (xfs_has_dax_always(mp) || xfs_has_dax_never(mp))
    1168             :                 return;
    1169             : 
    1170      858074 :         if (((fa->fsx_xflags & FS_XFLAG_DAX) &&
    1171      858074 :             !(ip->i_diflags2 & XFS_DIFLAG2_DAX)) ||
    1172      858063 :             (!(fa->fsx_xflags & FS_XFLAG_DAX) &&
    1173      858063 :              (ip->i_diflags2 & XFS_DIFLAG2_DAX)))
    1174          22 :                 d_mark_dontcache(inode);
    1175             : }
    1176             : 
    1177             : /*
    1178             :  * Set up the transaction structure for the setattr operation, checking that we
    1179             :  * have permission to do so. On success, return a clean transaction and the
    1180             :  * inode locked exclusively ready for further operation specific checks. On
    1181             :  * failure, return an error without modifying or locking the inode.
    1182             :  */
    1183             : static struct xfs_trans *
    1184      888429 : xfs_ioctl_setattr_get_trans(
    1185             :         struct xfs_inode        *ip,
    1186             :         struct xfs_dquot        *pdqp)
    1187             : {
    1188      888429 :         struct xfs_mount        *mp = ip->i_mount;
    1189      888429 :         struct xfs_trans        *tp;
    1190      888429 :         int                     error = -EROFS;
    1191             : 
    1192     1776858 :         if (xfs_is_readonly(mp))
    1193           0 :                 goto out_error;
    1194      888429 :         error = -EIO;
    1195     1776858 :         if (xfs_is_shutdown(mp))
    1196           1 :                 goto out_error;
    1197             : 
    1198      888428 :         error = xfs_trans_alloc_ichange(ip, NULL, NULL, pdqp,
    1199      888428 :                         has_capability_noaudit(current, CAP_FOWNER), &tp);
    1200      888427 :         if (error)
    1201           0 :                 goto out_error;
    1202             : 
    1203      888427 :         if (xfs_has_wsync(mp))
    1204         456 :                 xfs_trans_set_sync(tp);
    1205             : 
    1206      888427 :         return tp;
    1207             : 
    1208           1 : out_error:
    1209           1 :         return ERR_PTR(error);
    1210             : }
    1211             : 
    1212             : /*
    1213             :  * Validate a proposed extent size hint.  For regular files, the hint can only
    1214             :  * be changed if no extents are allocated.
    1215             :  */
    1216             : static int
    1217      888427 : xfs_ioctl_setattr_check_extsize(
    1218             :         struct xfs_inode        *ip,
    1219             :         struct fileattr         *fa)
    1220             : {
    1221      888427 :         struct xfs_mount        *mp = ip->i_mount;
    1222      888427 :         xfs_failaddr_t          failaddr;
    1223      888427 :         uint16_t                new_diflags;
    1224             : 
    1225      888427 :         if (!fa->fsx_valid)
    1226             :                 return 0;
    1227             : 
    1228      609876 :         if (S_ISREG(VFS_I(ip)->i_mode) && ip->i_df.if_nextents &&
    1229      442171 :             XFS_FSB_TO_B(mp, ip->i_extsize) != fa->fsx_extsize)
    1230             :                 return -EINVAL;
    1231             : 
    1232      609870 :         if (fa->fsx_extsize & mp->m_blockmask)
    1233             :                 return -EINVAL;
    1234             : 
    1235      609865 :         new_diflags = xfs_flags2diflags(ip, fa->fsx_xflags);
    1236             : 
    1237             :         /*
    1238             :          * Inode verifiers do not check that the extent size hint is an integer
    1239             :          * multiple of the rt extent size on a directory with both rtinherit
    1240             :          * and extszinherit flags set.  Don't let sysadmins misconfigure
    1241             :          * directories.
    1242             :          */
    1243      609865 :         if ((new_diflags & XFS_DIFLAG_RTINHERIT) &&
    1244             :             (new_diflags & XFS_DIFLAG_EXTSZINHERIT)) {
    1245          28 :                 unsigned int    rtextsize_bytes;
    1246             : 
    1247          28 :                 rtextsize_bytes = XFS_FSB_TO_B(mp, mp->m_sb.sb_rextsize);
    1248          28 :                 if (fa->fsx_extsize % rtextsize_bytes)
    1249             :                         return -EINVAL;
    1250             :         }
    1251             : 
    1252     1219720 :         failaddr = xfs_inode_validate_extsize(ip->i_mount,
    1253      609860 :                         XFS_B_TO_FSB(mp, fa->fsx_extsize),
    1254      609860 :                         VFS_I(ip)->i_mode, new_diflags);
    1255      609854 :         return failaddr != NULL ? -EINVAL : 0;
    1256             : }
    1257             : 
    1258             : static int
    1259      888407 : xfs_ioctl_setattr_check_cowextsize(
    1260             :         struct xfs_inode        *ip,
    1261             :         struct fileattr         *fa)
    1262             : {
    1263      888407 :         struct xfs_mount        *mp = ip->i_mount;
    1264      888407 :         xfs_failaddr_t          failaddr;
    1265      888407 :         uint64_t                new_diflags2;
    1266      888407 :         uint16_t                new_diflags;
    1267             : 
    1268      888407 :         if (!fa->fsx_valid)
    1269             :                 return 0;
    1270             : 
    1271      609856 :         if (fa->fsx_cowextsize & mp->m_blockmask)
    1272             :                 return -EINVAL;
    1273             : 
    1274      609856 :         new_diflags = xfs_flags2diflags(ip, fa->fsx_xflags);
    1275      609856 :         new_diflags2 = xfs_flags2diflags2(ip, fa->fsx_xflags);
    1276             : 
    1277     1219712 :         failaddr = xfs_inode_validate_cowextsize(ip->i_mount,
    1278      609856 :                         XFS_B_TO_FSB(mp, fa->fsx_cowextsize),
    1279      609856 :                         VFS_I(ip)->i_mode, new_diflags, new_diflags2);
    1280      609856 :         return failaddr != NULL ? -EINVAL : 0;
    1281             : }
    1282             : 
    1283             : static int
    1284             : xfs_ioctl_setattr_check_projid(
    1285             :         struct xfs_inode        *ip,
    1286             :         struct fileattr         *fa)
    1287             : {
    1288      889925 :         if (!fa->fsx_valid)
    1289             :                 return 0;
    1290             : 
    1291             :         /* Disallow 32bit project ids if 32bit IDs are not enabled. */
    1292      611375 :         if (fa->fsx_projid > (uint16_t)-1 &&
    1293           0 :             !xfs_has_projid32(ip->i_mount))
    1294             :                 return -EINVAL;
    1295             :         return 0;
    1296             : }
    1297             : 
    1298             : int
    1299      910091 : xfs_fileattr_set(
    1300             :         struct mnt_idmap        *idmap,
    1301             :         struct dentry           *dentry,
    1302             :         struct fileattr         *fa)
    1303             : {
    1304      910091 :         struct xfs_inode        *ip = XFS_I(d_inode(dentry));
    1305      910091 :         struct xfs_mount        *mp = ip->i_mount;
    1306      910091 :         struct xfs_trans        *tp;
    1307      910091 :         struct xfs_dquot        *pdqp = NULL;
    1308      910091 :         struct xfs_dquot        *olddquot = NULL;
    1309      910091 :         int                     error;
    1310             : 
    1311      910091 :         trace_xfs_ioctl_setattr(ip);
    1312             : 
    1313      910082 :         if (d_is_special(dentry))
    1314             :                 return -ENOTTY;
    1315             : 
    1316      910082 :         if (!fa->fsx_valid) {
    1317      298708 :                 if (fa->flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL |
    1318             :                                   FS_NOATIME_FL | FS_NODUMP_FL |
    1319             :                                   FS_SYNC_FL | FS_DAX_FL | FS_PROJINHERIT_FL))
    1320             :                         return -EOPNOTSUPP;
    1321             :         }
    1322             : 
    1323      889925 :         error = xfs_ioctl_setattr_check_projid(ip, fa);
    1324             :         if (error)
    1325             :                 return error;
    1326             : 
    1327             :         /*
    1328             :          * If disk quotas is on, we make sure that the dquots do exist on disk,
    1329             :          * before we start any other transactions. Trying to do this later
    1330             :          * is messy. We don't care to take a readlock to look at the ids
    1331             :          * in inode here, because we can't hold it across the trans_reserve.
    1332             :          * If the IDs do change before we take the ilock, we're covered
    1333             :          * because the i_*dquot fields will get updated anyway.
    1334             :          */
    1335      889925 :         if (fa->fsx_valid && XFS_IS_QUOTA_ON(mp)) {
    1336      388712 :                 error = xfs_qm_vop_dqalloc(ip, VFS_I(ip)->i_uid,
    1337             :                                 VFS_I(ip)->i_gid, fa->fsx_projid,
    1338             :                                 XFS_QMOPT_PQUOTA, NULL, NULL, &pdqp);
    1339      388719 :                 if (error)
    1340             :                         return error;
    1341             :         }
    1342             : 
    1343      888429 :         xfs_ioctl_setattr_prepare_dax(ip, fa);
    1344             : 
    1345      888430 :         tp = xfs_ioctl_setattr_get_trans(ip, pdqp);
    1346      888427 :         if (IS_ERR(tp)) {
    1347           1 :                 error = PTR_ERR(tp);
    1348           1 :                 goto error_free_dquots;
    1349             :         }
    1350             : 
    1351      888426 :         error = xfs_ioctl_setattr_check_extsize(ip, fa);
    1352      888422 :         if (error)
    1353          16 :                 goto error_trans_cancel;
    1354             : 
    1355      888406 :         error = xfs_ioctl_setattr_check_cowextsize(ip, fa);
    1356      888404 :         if (error)
    1357           0 :                 goto error_trans_cancel;
    1358             : 
    1359      888404 :         error = xfs_ioctl_setattr_xflags(tp, ip, fa);
    1360      888415 :         if (error)
    1361           0 :                 goto error_trans_cancel;
    1362             : 
    1363      888415 :         if (!fa->fsx_valid)
    1364      278551 :                 goto skip_xattr;
    1365             :         /*
    1366             :          * Change file ownership.  Must be the owner or privileged.  CAP_FSETID
    1367             :          * overrides the following restrictions:
    1368             :          *
    1369             :          * The set-user-ID and set-group-ID bits of a file will be cleared upon
    1370             :          * successful return from chown()
    1371             :          */
    1372             : 
    1373      609908 :         if ((VFS_I(ip)->i_mode & (S_ISUID|S_ISGID)) &&
    1374          44 :             !capable_wrt_inode_uidgid(idmap, VFS_I(ip), CAP_FSETID))
    1375           0 :                 VFS_I(ip)->i_mode &= ~(S_ISUID|S_ISGID);
    1376             : 
    1377             :         /* Change the ownerships and register project quota modifications */
    1378      609864 :         if (ip->i_projid != fa->fsx_projid) {
    1379      501153 :                 if (XFS_IS_PQUOTA_ON(mp)) {
    1380      325283 :                         olddquot = xfs_qm_vop_chown(tp, ip,
    1381             :                                                 &ip->i_pdquot, pdqp);
    1382             :                 }
    1383      501156 :                 ip->i_projid = fa->fsx_projid;
    1384             :         }
    1385             : 
    1386             :         /*
    1387             :          * Only set the extent size hint if we've already determined that the
    1388             :          * extent size hint should be set on the inode. If no extent size flags
    1389             :          * are set on the inode then unconditionally clear the extent size hint.
    1390             :          */
    1391      609867 :         if (ip->i_diflags & (XFS_DIFLAG_EXTSIZE | XFS_DIFLAG_EXTSZINHERIT))
    1392         123 :                 ip->i_extsize = XFS_B_TO_FSB(mp, fa->fsx_extsize);
    1393             :         else
    1394      609744 :                 ip->i_extsize = 0;
    1395             : 
    1396      609867 :         if (xfs_has_v3inodes(mp)) {
    1397      609867 :                 if (ip->i_diflags2 & XFS_DIFLAG2_COWEXTSIZE)
    1398         368 :                         ip->i_cowextsize = XFS_B_TO_FSB(mp, fa->fsx_cowextsize);
    1399             :                 else
    1400      609499 :                         ip->i_cowextsize = 0;
    1401             :         }
    1402             : 
    1403           0 : skip_xattr:
    1404      888418 :         error = xfs_trans_commit(tp);
    1405             : 
    1406             :         /*
    1407             :          * Release any dquot(s) the inode had kept before chown.
    1408             :          */
    1409      888420 :         xfs_qm_dqrele(olddquot);
    1410      888417 :         xfs_qm_dqrele(pdqp);
    1411             : 
    1412      888417 :         return error;
    1413             : 
    1414          16 : error_trans_cancel:
    1415          16 :         xfs_trans_cancel(tp);
    1416          17 : error_free_dquots:
    1417          17 :         xfs_qm_dqrele(pdqp);
    1418          17 :         return error;
    1419             : }
    1420             : 
    1421             : static bool
    1422     2178708 : xfs_getbmap_format(
    1423             :         struct kgetbmap         *p,
    1424             :         struct getbmapx __user  *u,
    1425             :         size_t                  recsize)
    1426             : {
    1427     2178708 :         if (put_user(p->bmv_offset, &u->bmv_offset) ||
    1428     2178622 :             put_user(p->bmv_block, &u->bmv_block) ||
    1429     2178619 :             put_user(p->bmv_length, &u->bmv_length) ||
    1430     2178615 :             put_user(0, &u->bmv_count) ||
    1431     2178607 :             put_user(0, &u->bmv_entries))
    1432           0 :                 return false;
    1433     2178617 :         if (recsize < sizeof(struct getbmapx))
    1434             :                 return true;
    1435     1560586 :         if (put_user(0, &u->bmv_iflags) ||
    1436     1560584 :             put_user(p->bmv_oflags, &u->bmv_oflags) ||
    1437     1560619 :             put_user(0, &u->bmv_unused1) ||
    1438     1560583 :             put_user(0, &u->bmv_unused2))
    1439           0 :                 return false;
    1440             :         return true;
    1441             : }
    1442             : 
    1443             : STATIC int
    1444      436389 : xfs_ioc_getbmap(
    1445             :         struct file             *file,
    1446             :         unsigned int            cmd,
    1447             :         void                    __user *arg)
    1448             : {
    1449      436389 :         struct getbmapx         bmx = { 0 };
    1450      436389 :         struct kgetbmap         *buf;
    1451      436389 :         size_t                  recsize;
    1452      436389 :         int                     error, i;
    1453             : 
    1454      436389 :         switch (cmd) {
    1455           0 :         case XFS_IOC_GETBMAPA:
    1456           0 :                 bmx.bmv_iflags = BMV_IF_ATTRFORK;
    1457             :                 fallthrough;
    1458             :         case XFS_IOC_GETBMAP:
    1459             :                 /* struct getbmap is a strict subset of struct getbmapx. */
    1460             :                 recsize = sizeof(struct getbmap);
    1461             :                 break;
    1462             :         case XFS_IOC_GETBMAPX:
    1463             :                 recsize = sizeof(struct getbmapx);
    1464             :                 break;
    1465             :         default:
    1466             :                 return -EINVAL;
    1467             :         }
    1468             : 
    1469      872758 :         if (copy_from_user(&bmx, arg, recsize))
    1470             :                 return -EFAULT;
    1471             : 
    1472      436369 :         if (bmx.bmv_count < 2)
    1473             :                 return -EINVAL;
    1474      436369 :         if (bmx.bmv_count >= INT_MAX / recsize)
    1475             :                 return -ENOMEM;
    1476             : 
    1477      436369 :         buf = kvcalloc(bmx.bmv_count, sizeof(*buf), GFP_KERNEL);
    1478      436456 :         if (!buf)
    1479             :                 return -ENOMEM;
    1480             : 
    1481      436456 :         error = xfs_getbmap(XFS_I(file_inode(file)), &bmx, buf);
    1482      436418 :         if (error)
    1483           0 :                 goto out_free_buf;
    1484             : 
    1485      436418 :         error = -EFAULT;
    1486      872823 :         if (copy_to_user(arg, &bmx, recsize))
    1487           0 :                 goto out_free_buf;
    1488      436405 :         arg += recsize;
    1489             : 
    1490     2615048 :         for (i = 0; i < bmx.bmv_entries; i++) {
    1491     2178652 :                 if (!xfs_getbmap_format(buf + i, arg, recsize))
    1492           0 :                         goto out_free_buf;
    1493     2178643 :                 arg += recsize;
    1494             :         }
    1495             : 
    1496             :         error = 0;
    1497      436396 : out_free_buf:
    1498      436396 :         kmem_free(buf);
    1499      436396 :         return error;
    1500             : }
    1501             : 
    1502             : STATIC int
    1503      731517 : xfs_ioc_getfsmap(
    1504             :         struct xfs_inode        *ip,
    1505             :         struct fsmap_head       __user *arg)
    1506             : {
    1507      731517 :         struct xfs_fsmap_head   xhead = {0};
    1508      731517 :         struct fsmap_head       head;
    1509      731517 :         struct fsmap            *recs;
    1510      731517 :         unsigned int            count;
    1511      731517 :         __u32                   last_flags = 0;
    1512      731517 :         bool                    done = false;
    1513      731517 :         int                     error;
    1514             : 
    1515      731517 :         if (copy_from_user(&head, arg, sizeof(struct fsmap_head)))
    1516             :                 return -EFAULT;
    1517     1464706 :         if (memchr_inv(head.fmh_reserved, 0, sizeof(head.fmh_reserved)) ||
    1518             :             memchr_inv(head.fmh_keys[0].fmr_reserved, 0,
    1519      730370 :                        sizeof(head.fmh_keys[0].fmr_reserved)) ||
    1520             :             memchr_inv(head.fmh_keys[1].fmr_reserved, 0,
    1521             :                        sizeof(head.fmh_keys[1].fmr_reserved)))
    1522           0 :                 return -EINVAL;
    1523             : 
    1524             :         /*
    1525             :          * Use an internal memory buffer so that we don't have to copy fsmap
    1526             :          * data to userspace while holding locks.  Start by trying to allocate
    1527             :          * up to 128k for the buffer, but fall back to a single page if needed.
    1528             :          */
    1529      730370 :         count = min_t(unsigned int, head.fmh_count,
    1530             :                         131072 / sizeof(struct fsmap));
    1531      730370 :         recs = kvcalloc(count, sizeof(struct fsmap), GFP_KERNEL);
    1532      735903 :         if (!recs) {
    1533           0 :                 count = min_t(unsigned int, head.fmh_count,
    1534             :                                 PAGE_SIZE / sizeof(struct fsmap));
    1535           0 :                 recs = kvcalloc(count, sizeof(struct fsmap), GFP_KERNEL);
    1536           0 :                 if (!recs)
    1537             :                         return -ENOMEM;
    1538             :         }
    1539             : 
    1540      735903 :         xhead.fmh_iflags = head.fmh_iflags;
    1541      735903 :         xfs_fsmap_to_internal(&xhead.fmh_keys[0], &head.fmh_keys[0]);
    1542      727634 :         xfs_fsmap_to_internal(&xhead.fmh_keys[1], &head.fmh_keys[1]);
    1543             : 
    1544      730926 :         trace_xfs_getfsmap_low_key(ip->i_mount, &xhead.fmh_keys[0]);
    1545      730993 :         trace_xfs_getfsmap_high_key(ip->i_mount, &xhead.fmh_keys[1]);
    1546             : 
    1547      728543 :         head.fmh_entries = 0;
    1548      802316 :         do {
    1549      802316 :                 struct fsmap __user     *user_recs;
    1550      802316 :                 struct fsmap            *last_rec;
    1551             : 
    1552      802316 :                 user_recs = &arg->fmh_recs[head.fmh_entries];
    1553      802316 :                 xhead.fmh_entries = 0;
    1554      802316 :                 xhead.fmh_count = min_t(unsigned int, count,
    1555             :                                         head.fmh_count - head.fmh_entries);
    1556             : 
    1557             :                 /* Run query, record how many entries we got. */
    1558      802316 :                 error = xfs_getfsmap(ip->i_mount, &xhead, recs);
    1559      805611 :                 switch (error) {
    1560             :                 case 0:
    1561             :                         /*
    1562             :                          * There are no more records in the result set.  Copy
    1563             :                          * whatever we got to userspace and break out.
    1564             :                          */
    1565             :                         done = true;
    1566             :                         break;
    1567      117353 :                 case -ECANCELED:
    1568             :                         /*
    1569             :                          * The internal memory buffer is full.  Copy whatever
    1570             :                          * records we got to userspace and go again if we have
    1571             :                          * not yet filled the userspace buffer.
    1572             :                          */
    1573      117353 :                         error = 0;
    1574      117353 :                         break;
    1575           2 :                 default:
    1576           2 :                         goto out_free;
    1577             :                 }
    1578      805609 :                 head.fmh_entries += xhead.fmh_entries;
    1579      805609 :                 head.fmh_oflags = xhead.fmh_oflags;
    1580             : 
    1581             :                 /*
    1582             :                  * If the caller wanted a record count or there aren't any
    1583             :                  * new records to return, we're done.
    1584             :                  */
    1585      805609 :                 if (head.fmh_count == 0 || xhead.fmh_entries == 0)
    1586             :                         break;
    1587             : 
    1588             :                 /* Copy all the records we got out to userspace. */
    1589      809616 :                 if (copy_to_user(user_recs, recs,
    1590      805607 :                                  xhead.fmh_entries * sizeof(struct fsmap))) {
    1591           0 :                         error = -EFAULT;
    1592           0 :                         goto out_free;
    1593             :                 }
    1594             : 
    1595             :                 /* Remember the last record flags we copied to userspace. */
    1596      809616 :                 last_rec = &recs[xhead.fmh_entries - 1];
    1597      809616 :                 last_flags = last_rec->fmr_flags;
    1598             : 
    1599             :                 /* Set up the low key for the next iteration. */
    1600      809616 :                 xfs_fsmap_to_internal(&xhead.fmh_keys[0], last_rec);
    1601      806588 :                 trace_xfs_getfsmap_low_key(ip->i_mount, &xhead.fmh_keys[0]);
    1602      804583 :         } while (!done && head.fmh_entries < head.fmh_count);
    1603             : 
    1604             :         /*
    1605             :          * If there are no more records in the query result set and we're not
    1606             :          * in counting mode, mark the last record returned with the LAST flag.
    1607             :          */
    1608      730812 :         if (done && head.fmh_count > 0 && head.fmh_entries > 0) {
    1609      684490 :                 struct fsmap __user     *user_rec;
    1610             : 
    1611      684490 :                 last_flags |= FMR_OF_LAST;
    1612      684490 :                 user_rec = &arg->fmh_recs[head.fmh_entries - 1];
    1613             : 
    1614      684490 :                 if (copy_to_user(&user_rec->fmr_flags, &last_flags,
    1615             :                                         sizeof(last_flags))) {
    1616           0 :                         error = -EFAULT;
    1617           0 :                         goto out_free;
    1618             :                 }
    1619             :         }
    1620             : 
    1621             :         /* copy back header */
    1622      736470 :         if (copy_to_user(arg, &head, sizeof(struct fsmap_head))) {
    1623           0 :                 error = -EFAULT;
    1624           0 :                 goto out_free;
    1625             :         }
    1626             : 
    1627      732364 : out_free:
    1628      732366 :         kmem_free(recs);
    1629      732366 :         return error;
    1630             : }
    1631             : 
    1632             : STATIC int
    1633  2186467377 : xfs_ioc_scrub_metadata(
    1634             :         struct file                     *file,
    1635             :         void                            __user *arg)
    1636             : {
    1637  2186467377 :         struct xfs_scrub_metadata       scrub;
    1638  2186467377 :         int                             error;
    1639             : 
    1640  2186467377 :         if (!capable(CAP_SYS_ADMIN))
    1641             :                 return -EPERM;
    1642             : 
    1643  2187781561 :         if (copy_from_user(&scrub, arg, sizeof(scrub)))
    1644             :                 return -EFAULT;
    1645             : 
    1646  2191761387 :         error = xfs_scrub_metadata(file, &scrub);
    1647  2187851289 :         if (error)
    1648             :                 return error;
    1649             : 
    1650  1075289100 :         if (copy_to_user(arg, &scrub, sizeof(scrub)))
    1651           0 :                 return -EFAULT;
    1652             : 
    1653             :         return 0;
    1654             : }
    1655             : 
    1656             : int
    1657       28814 : xfs_ioc_swapext(
    1658             :         xfs_swapext_t   *sxp)
    1659             : {
    1660       28814 :         xfs_inode_t     *ip, *tip;
    1661       28814 :         struct fd       f, tmp;
    1662       28814 :         int             error = 0;
    1663             : 
    1664             :         /* Pull information for the target fd */
    1665       28814 :         f = fdget((int)sxp->sx_fdtarget);
    1666       28814 :         if (!f.file) {
    1667           0 :                 error = -EINVAL;
    1668           0 :                 goto out;
    1669             :         }
    1670             : 
    1671       28814 :         if (!(f.file->f_mode & FMODE_WRITE) ||
    1672       28814 :             !(f.file->f_mode & FMODE_READ) ||
    1673       28814 :             (f.file->f_flags & O_APPEND)) {
    1674           0 :                 error = -EBADF;
    1675           0 :                 goto out_put_file;
    1676             :         }
    1677             : 
    1678       28814 :         tmp = fdget((int)sxp->sx_fdtmp);
    1679       28814 :         if (!tmp.file) {
    1680           0 :                 error = -EINVAL;
    1681           0 :                 goto out_put_file;
    1682             :         }
    1683             : 
    1684       28814 :         if (!(tmp.file->f_mode & FMODE_WRITE) ||
    1685       28814 :             !(tmp.file->f_mode & FMODE_READ) ||
    1686       28814 :             (tmp.file->f_flags & O_APPEND)) {
    1687           0 :                 error = -EBADF;
    1688           0 :                 goto out_put_tmp_file;
    1689             :         }
    1690             : 
    1691       28814 :         if (IS_SWAPFILE(file_inode(f.file)) ||
    1692       28814 :             IS_SWAPFILE(file_inode(tmp.file))) {
    1693           0 :                 error = -EINVAL;
    1694           0 :                 goto out_put_tmp_file;
    1695             :         }
    1696             : 
    1697             :         /*
    1698             :          * We need to ensure that the fds passed in point to XFS inodes
    1699             :          * before we cast and access them as XFS structures as we have no
    1700             :          * control over what the user passes us here.
    1701             :          */
    1702       28814 :         if (f.file->f_op != &xfs_file_operations ||
    1703       28814 :             tmp.file->f_op != &xfs_file_operations) {
    1704           0 :                 error = -EINVAL;
    1705           0 :                 goto out_put_tmp_file;
    1706             :         }
    1707             : 
    1708       28814 :         ip = XFS_I(file_inode(f.file));
    1709       28814 :         tip = XFS_I(file_inode(tmp.file));
    1710             : 
    1711       28814 :         if (ip->i_mount != tip->i_mount) {
    1712           0 :                 error = -EINVAL;
    1713           0 :                 goto out_put_tmp_file;
    1714             :         }
    1715             : 
    1716       28814 :         if (ip->i_ino == tip->i_ino) {
    1717           0 :                 error = -EINVAL;
    1718           0 :                 goto out_put_tmp_file;
    1719             :         }
    1720             : 
    1721       57628 :         if (xfs_is_shutdown(ip->i_mount)) {
    1722           0 :                 error = -EIO;
    1723           0 :                 goto out_put_tmp_file;
    1724             :         }
    1725             : 
    1726       28814 :         error = xfs_swap_extents(ip, tip, sxp);
    1727             : 
    1728       28814 :  out_put_tmp_file:
    1729       28814 :         fdput(tmp);
    1730       28814 :  out_put_file:
    1731       28814 :         fdput(f);
    1732       28814 :  out:
    1733       28814 :         return error;
    1734             : }
    1735             : 
    1736             : static int
    1737      124650 : xfs_ioc_getlabel(
    1738             :         struct xfs_mount        *mp,
    1739             :         char                    __user *user_label)
    1740             : {
    1741      124650 :         struct xfs_sb           *sbp = &mp->m_sb;
    1742      124650 :         char                    label[XFSLABEL_MAX + 1];
    1743             : 
    1744             :         /* Paranoia */
    1745      124650 :         BUILD_BUG_ON(sizeof(sbp->sb_fname) > FSLABEL_MAX);
    1746             : 
    1747             :         /* 1 larger than sb_fname, so this ensures a trailing NUL char */
    1748      124650 :         memset(label, 0, sizeof(label));
    1749      124650 :         spin_lock(&mp->m_sb_lock);
    1750      124650 :         strncpy(label, sbp->sb_fname, XFSLABEL_MAX);
    1751      124650 :         spin_unlock(&mp->m_sb_lock);
    1752             : 
    1753      124650 :         if (copy_to_user(user_label, label, sizeof(label)))
    1754           0 :                 return -EFAULT;
    1755             :         return 0;
    1756             : }
    1757             : 
    1758             : static int
    1759         297 : xfs_ioc_setlabel(
    1760             :         struct file             *filp,
    1761             :         struct xfs_mount        *mp,
    1762             :         char                    __user *newlabel)
    1763             : {
    1764         297 :         struct xfs_sb           *sbp = &mp->m_sb;
    1765         297 :         char                    label[XFSLABEL_MAX + 1];
    1766         297 :         size_t                  len;
    1767         297 :         int                     error;
    1768             : 
    1769         297 :         if (!capable(CAP_SYS_ADMIN))
    1770             :                 return -EPERM;
    1771             :         /*
    1772             :          * The generic ioctl allows up to FSLABEL_MAX chars, but XFS is much
    1773             :          * smaller, at 12 bytes.  We copy one more to be sure we find the
    1774             :          * (required) NULL character to test the incoming label length.
    1775             :          * NB: The on disk label doesn't need to be null terminated.
    1776             :          */
    1777         297 :         if (copy_from_user(label, newlabel, XFSLABEL_MAX + 1))
    1778             :                 return -EFAULT;
    1779         297 :         len = strnlen(label, XFSLABEL_MAX + 1);
    1780         297 :         if (len > sizeof(sbp->sb_fname))
    1781             :                 return -EINVAL;
    1782             : 
    1783         286 :         error = mnt_want_write_file(filp);
    1784         286 :         if (error)
    1785             :                 return error;
    1786             : 
    1787         286 :         spin_lock(&mp->m_sb_lock);
    1788         286 :         memset(sbp->sb_fname, 0, sizeof(sbp->sb_fname));
    1789         572 :         memcpy(sbp->sb_fname, label, len);
    1790         286 :         spin_unlock(&mp->m_sb_lock);
    1791             : 
    1792             :         /*
    1793             :          * Now we do several things to satisfy userspace.
    1794             :          * In addition to normal logging of the primary superblock, we also
    1795             :          * immediately write these changes to sector zero for the primary, then
    1796             :          * update all backup supers (as xfs_db does for a label change), then
    1797             :          * invalidate the block device page cache.  This is so that any prior
    1798             :          * buffered reads from userspace (i.e. from blkid) are invalidated,
    1799             :          * and userspace will see the newly-written label.
    1800             :          */
    1801         286 :         error = xfs_sync_sb_buf(mp);
    1802         286 :         if (error)
    1803           0 :                 goto out;
    1804             :         /*
    1805             :          * growfs also updates backup supers so lock against that.
    1806             :          */
    1807         286 :         mutex_lock(&mp->m_growlock);
    1808         286 :         error = xfs_update_secondary_sbs(mp);
    1809         286 :         mutex_unlock(&mp->m_growlock);
    1810             : 
    1811         286 :         invalidate_bdev(mp->m_ddev_targp->bt_bdev);
    1812             : 
    1813         286 : out:
    1814         286 :         mnt_drop_write_file(filp);
    1815         286 :         return error;
    1816             : }
    1817             : 
    1818             : static inline int
    1819           0 : xfs_fs_eofblocks_from_user(
    1820             :         struct xfs_fs_eofblocks         *src,
    1821             :         struct xfs_icwalk               *dst)
    1822             : {
    1823           0 :         if (src->eof_version != XFS_EOFBLOCKS_VERSION)
    1824             :                 return -EINVAL;
    1825             : 
    1826           0 :         if (src->eof_flags & ~XFS_EOF_FLAGS_VALID)
    1827             :                 return -EINVAL;
    1828             : 
    1829           0 :         if (memchr_inv(&src->pad32, 0, sizeof(src->pad32)) ||
    1830           0 :             memchr_inv(src->pad64, 0, sizeof(src->pad64)))
    1831           0 :                 return -EINVAL;
    1832             : 
    1833           0 :         dst->icw_flags = 0;
    1834           0 :         if (src->eof_flags & XFS_EOF_FLAGS_SYNC)
    1835           0 :                 dst->icw_flags |= XFS_ICWALK_FLAG_SYNC;
    1836           0 :         if (src->eof_flags & XFS_EOF_FLAGS_UID)
    1837           0 :                 dst->icw_flags |= XFS_ICWALK_FLAG_UID;
    1838           0 :         if (src->eof_flags & XFS_EOF_FLAGS_GID)
    1839           0 :                 dst->icw_flags |= XFS_ICWALK_FLAG_GID;
    1840           0 :         if (src->eof_flags & XFS_EOF_FLAGS_PRID)
    1841           0 :                 dst->icw_flags |= XFS_ICWALK_FLAG_PRID;
    1842           0 :         if (src->eof_flags & XFS_EOF_FLAGS_MINFILESIZE)
    1843           0 :                 dst->icw_flags |= XFS_ICWALK_FLAG_MINFILESIZE;
    1844             : 
    1845           0 :         dst->icw_prid = src->eof_prid;
    1846           0 :         dst->icw_min_file_size = src->eof_min_file_size;
    1847             : 
    1848           0 :         dst->icw_uid = INVALID_UID;
    1849           0 :         if (src->eof_flags & XFS_EOF_FLAGS_UID) {
    1850           0 :                 dst->icw_uid = make_kuid(current_user_ns(), src->eof_uid);
    1851           0 :                 if (!uid_valid(dst->icw_uid))
    1852             :                         return -EINVAL;
    1853             :         }
    1854             : 
    1855           0 :         dst->icw_gid = INVALID_GID;
    1856           0 :         if (src->eof_flags & XFS_EOF_FLAGS_GID) {
    1857           0 :                 dst->icw_gid = make_kgid(current_user_ns(), src->eof_gid);
    1858           0 :                 if (!gid_valid(dst->icw_gid))
    1859           0 :                         return -EINVAL;
    1860             :         }
    1861             :         return 0;
    1862             : }
    1863             : 
    1864             : /*
    1865             :  * These long-unused ioctls were removed from the official ioctl API in 5.17,
    1866             :  * but retain these definitions so that we can log warnings about them.
    1867             :  */
    1868             : #define XFS_IOC_ALLOCSP         _IOW ('X', 10, struct xfs_flock64)
    1869             : #define XFS_IOC_FREESP          _IOW ('X', 11, struct xfs_flock64)
    1870             : #define XFS_IOC_ALLOCSP64       _IOW ('X', 36, struct xfs_flock64)
    1871             : #define XFS_IOC_FREESP64        _IOW ('X', 37, struct xfs_flock64)
    1872             : 
    1873             : /*
    1874             :  * Note: some of the ioctl's return positive numbers as a
    1875             :  * byte count indicating success, such as readlink_by_handle.
    1876             :  * So we don't "sign flip" like most other routines.  This means
    1877             :  * true errors need to be returned as a negative value.
    1878             :  */
    1879             : long
    1880  2818686826 : xfs_file_ioctl(
    1881             :         struct file             *filp,
    1882             :         unsigned int            cmd,
    1883             :         unsigned long           p)
    1884             : {
    1885  2818686826 :         struct inode            *inode = file_inode(filp);
    1886  2818686826 :         struct xfs_inode        *ip = XFS_I(inode);
    1887  2818686826 :         struct xfs_mount        *mp = ip->i_mount;
    1888  2818686826 :         void                    __user *arg = (void __user *)p;
    1889  2818686826 :         int                     error;
    1890             : 
    1891  2818686826 :         trace_xfs_file_ioctl(ip);
    1892             : 
    1893  2814744755 :         switch (cmd) {
    1894        6131 :         case FITRIM:
    1895        6131 :                 return xfs_ioc_trim(mp, arg);
    1896      124650 :         case FS_IOC_GETFSLABEL:
    1897      124650 :                 return xfs_ioc_getlabel(mp, arg);
    1898         297 :         case FS_IOC_SETFSLABEL:
    1899         297 :                 return xfs_ioc_setlabel(filp, mp, arg);
    1900             :         case XFS_IOC_ALLOCSP:
    1901             :         case XFS_IOC_FREESP:
    1902             :         case XFS_IOC_ALLOCSP64:
    1903             :         case XFS_IOC_FREESP64:
    1904          11 :                 xfs_warn_once(mp,
    1905             :         "%s should use fallocate; XFS_IOC_{ALLOC,FREE}SP ioctl unsupported",
    1906             :                                 current->comm);
    1907             :                 return -ENOTTY;
    1908    10854740 :         case XFS_IOC_DIOINFO: {
    1909    10854740 :                 struct xfs_buftarg      *target = xfs_inode_buftarg(ip);
    1910    10854740 :                 struct dioattr          da;
    1911             : 
    1912    10854740 :                 da.d_mem =  da.d_miniosz = target->bt_logical_sectorsize;
    1913    10854740 :                 da.d_maxiosz = INT_MAX & ~(da.d_miniosz - 1);
    1914             : 
    1915    10854740 :                 if (copy_to_user(arg, &da, sizeof(da)))
    1916           0 :                         return -EFAULT;
    1917             :                 return 0;
    1918             :         }
    1919             : 
    1920   349285821 :         case XFS_IOC_FSBULKSTAT_SINGLE:
    1921             :         case XFS_IOC_FSBULKSTAT:
    1922             :         case XFS_IOC_FSINUMBERS:
    1923   349285821 :                 return xfs_ioc_fsbulkstat(filp, cmd, arg);
    1924             : 
    1925    21631542 :         case XFS_IOC_BULKSTAT:
    1926    21631542 :                 return xfs_ioc_bulkstat(filp, cmd, arg);
    1927    12021918 :         case XFS_IOC_INUMBERS:
    1928    12021918 :                 return xfs_ioc_inumbers(mp, cmd, arg);
    1929             : 
    1930         772 :         case XFS_IOC_FSGEOMETRY_V1:
    1931         772 :                 return xfs_ioc_fsgeometry(mp, arg, 3);
    1932           0 :         case XFS_IOC_FSGEOMETRY_V4:
    1933           0 :                 return xfs_ioc_fsgeometry(mp, arg, 4);
    1934     5559166 :         case XFS_IOC_FSGEOMETRY:
    1935     5559166 :                 return xfs_ioc_fsgeometry(mp, arg, 5);
    1936             : 
    1937       67727 :         case XFS_IOC_AG_GEOMETRY:
    1938       67727 :                 return xfs_ioc_ag_geometry(mp, arg);
    1939             : 
    1940           0 :         case XFS_IOC_GETVERSION:
    1941           0 :                 return put_user(inode->i_generation, (int __user *)arg);
    1942             : 
    1943       27222 :         case XFS_IOC_FSGETXATTRA:
    1944       27222 :                 return xfs_ioc_fsgetxattra(ip, arg);
    1945             : 
    1946      436450 :         case XFS_IOC_GETBMAP:
    1947             :         case XFS_IOC_GETBMAPA:
    1948             :         case XFS_IOC_GETBMAPX:
    1949      436450 :                 return xfs_ioc_getbmap(filp, cmd, arg);
    1950             : 
    1951      732396 :         case FS_IOC_GETFSMAP:
    1952      732396 :                 return xfs_ioc_getfsmap(ip, arg);
    1953             : 
    1954  2186340039 :         case XFS_IOC_SCRUB_METADATA:
    1955  2186340039 :                 return xfs_ioc_scrub_metadata(filp, arg);
    1956             : 
    1957             :         case XFS_IOC_FD_TO_HANDLE:
    1958             :         case XFS_IOC_PATH_TO_HANDLE:
    1959             :         case XFS_IOC_PATH_TO_FSHANDLE: {
    1960      207627 :                 xfs_fsop_handlereq_t    hreq;
    1961             : 
    1962      207627 :                 if (copy_from_user(&hreq, arg, sizeof(hreq)))
    1963             :                         return -EFAULT;
    1964      207627 :                 return xfs_find_handle(cmd, &hreq);
    1965             :         }
    1966             :         case XFS_IOC_OPEN_BY_HANDLE: {
    1967   182317447 :                 xfs_fsop_handlereq_t    hreq;
    1968             : 
    1969   182317447 :                 if (copy_from_user(&hreq, arg, sizeof(xfs_fsop_handlereq_t)))
    1970             :                         return -EFAULT;
    1971   183582764 :                 return xfs_open_by_handle(filp, &hreq);
    1972             :         }
    1973             : 
    1974             :         case XFS_IOC_READLINK_BY_HANDLE: {
    1975        1000 :                 xfs_fsop_handlereq_t    hreq;
    1976             : 
    1977        1000 :                 if (copy_from_user(&hreq, arg, sizeof(xfs_fsop_handlereq_t)))
    1978             :                         return -EFAULT;
    1979        1000 :                 return xfs_readlink_by_handle(filp, &hreq);
    1980             :         }
    1981    42803573 :         case XFS_IOC_ATTRLIST_BY_HANDLE:
    1982    42803573 :                 return xfs_attrlist_by_handle(filp, arg);
    1983             : 
    1984         733 :         case XFS_IOC_ATTRMULTI_BY_HANDLE:
    1985         733 :                 return xfs_attrmulti_by_handle(filp, arg);
    1986             : 
    1987             :         case XFS_IOC_SWAPEXT: {
    1988       28814 :                 struct xfs_swapext      sxp;
    1989             : 
    1990       28814 :                 if (copy_from_user(&sxp, arg, sizeof(xfs_swapext_t)))
    1991             :                         return -EFAULT;
    1992       28814 :                 error = mnt_want_write_file(filp);
    1993       28814 :                 if (error)
    1994           0 :                         return error;
    1995       28814 :                 error = xfs_ioc_swapext(&sxp);
    1996       28814 :                 mnt_drop_write_file(filp);
    1997       28814 :                 return error;
    1998             :         }
    1999             : 
    2000      153780 :         case XFS_IOC_FSCOUNTS: {
    2001      153780 :                 xfs_fsop_counts_t out;
    2002             : 
    2003      153780 :                 xfs_fs_counts(mp, &out);
    2004             : 
    2005      153780 :                 if (copy_to_user(arg, &out, sizeof(out)))
    2006          11 :                         return -EFAULT;
    2007             :                 return 0;
    2008             :         }
    2009             : 
    2010         107 :         case XFS_IOC_SET_RESBLKS: {
    2011         107 :                 xfs_fsop_resblks_t inout;
    2012         107 :                 uint64_t           in;
    2013             : 
    2014         107 :                 if (!capable(CAP_SYS_ADMIN))
    2015             :                         return -EPERM;
    2016             : 
    2017         214 :                 if (xfs_is_readonly(mp))
    2018             :                         return -EROFS;
    2019             : 
    2020         107 :                 if (copy_from_user(&inout, arg, sizeof(inout)))
    2021             :                         return -EFAULT;
    2022             : 
    2023          96 :                 error = mnt_want_write_file(filp);
    2024          96 :                 if (error)
    2025           0 :                         return error;
    2026             : 
    2027             :                 /* input parameter is passed in resblks field of structure */
    2028          96 :                 in = inout.resblks;
    2029          96 :                 error = xfs_reserve_blocks(mp, &in, &inout);
    2030          96 :                 mnt_drop_write_file(filp);
    2031          96 :                 if (error)
    2032           0 :                         return error;
    2033             : 
    2034          96 :                 if (copy_to_user(arg, &inout, sizeof(inout)))
    2035           0 :                         return -EFAULT;
    2036             :                 return 0;
    2037             :         }
    2038             : 
    2039          33 :         case XFS_IOC_GET_RESBLKS: {
    2040          33 :                 xfs_fsop_resblks_t out;
    2041             : 
    2042          33 :                 if (!capable(CAP_SYS_ADMIN))
    2043             :                         return -EPERM;
    2044             : 
    2045          33 :                 error = xfs_reserve_blocks(mp, NULL, &out);
    2046          33 :                 if (error)
    2047           0 :                         return error;
    2048             : 
    2049          33 :                 if (copy_to_user(arg, &out, sizeof(out)))
    2050           0 :                         return -EFAULT;
    2051             : 
    2052             :                 return 0;
    2053             :         }
    2054             : 
    2055             :         case XFS_IOC_FSGROWFSDATA: {
    2056        1831 :                 struct xfs_growfs_data in;
    2057             : 
    2058        1831 :                 if (copy_from_user(&in, arg, sizeof(in)))
    2059             :                         return -EFAULT;
    2060             : 
    2061        1831 :                 error = mnt_want_write_file(filp);
    2062        1831 :                 if (error)
    2063           0 :                         return error;
    2064        1831 :                 error = xfs_growfs_data(mp, &in);
    2065        1831 :                 mnt_drop_write_file(filp);
    2066        1831 :                 return error;
    2067             :         }
    2068             : 
    2069             :         case XFS_IOC_FSGROWFSLOG: {
    2070           0 :                 struct xfs_growfs_log in;
    2071             : 
    2072           0 :                 if (copy_from_user(&in, arg, sizeof(in)))
    2073             :                         return -EFAULT;
    2074             : 
    2075           0 :                 error = mnt_want_write_file(filp);
    2076           0 :                 if (error)
    2077           0 :                         return error;
    2078           0 :                 error = xfs_growfs_log(mp, &in);
    2079           0 :                 mnt_drop_write_file(filp);
    2080           0 :                 return error;
    2081             :         }
    2082             : 
    2083             :         case XFS_IOC_FSGROWFSRT: {
    2084          47 :                 xfs_growfs_rt_t in;
    2085             : 
    2086          47 :                 if (copy_from_user(&in, arg, sizeof(in)))
    2087             :                         return -EFAULT;
    2088             : 
    2089          47 :                 error = mnt_want_write_file(filp);
    2090          47 :                 if (error)
    2091           0 :                         return error;
    2092          47 :                 error = xfs_growfs_rt(mp, &in);
    2093          47 :                 mnt_drop_write_file(filp);
    2094          47 :                 return error;
    2095             :         }
    2096             : 
    2097        5706 :         case XFS_IOC_GOINGDOWN: {
    2098        5706 :                 uint32_t in;
    2099             : 
    2100        5706 :                 if (!capable(CAP_SYS_ADMIN))
    2101             :                         return -EPERM;
    2102             : 
    2103        5706 :                 if (get_user(in, (uint32_t __user *)arg))
    2104             :                         return -EFAULT;
    2105             : 
    2106        5706 :                 return xfs_fs_goingdown(mp, in);
    2107             :         }
    2108             : 
    2109       68047 :         case XFS_IOC_ERROR_INJECTION: {
    2110       68047 :                 xfs_error_injection_t in;
    2111             : 
    2112       68047 :                 if (!capable(CAP_SYS_ADMIN))
    2113             :                         return -EPERM;
    2114             : 
    2115       68047 :                 if (copy_from_user(&in, arg, sizeof(in)))
    2116             :                         return -EFAULT;
    2117             : 
    2118       68047 :                 return xfs_errortag_add(mp, in.errtag);
    2119             :         }
    2120             : 
    2121        1304 :         case XFS_IOC_ERROR_CLEARALL:
    2122        1304 :                 if (!capable(CAP_SYS_ADMIN))
    2123             :                         return -EPERM;
    2124             : 
    2125        1304 :                 return xfs_errortag_clearall(mp);
    2126             : 
    2127           0 :         case XFS_IOC_FREE_EOFBLOCKS: {
    2128           0 :                 struct xfs_fs_eofblocks eofb;
    2129           0 :                 struct xfs_icwalk       icw;
    2130             : 
    2131           0 :                 if (!capable(CAP_SYS_ADMIN))
    2132             :                         return -EPERM;
    2133             : 
    2134           0 :                 if (xfs_is_readonly(mp))
    2135             :                         return -EROFS;
    2136             : 
    2137           0 :                 if (copy_from_user(&eofb, arg, sizeof(eofb)))
    2138             :                         return -EFAULT;
    2139             : 
    2140           0 :                 error = xfs_fs_eofblocks_from_user(&eofb, &icw);
    2141           0 :                 if (error)
    2142           0 :                         return error;
    2143             : 
    2144           0 :                 trace_xfs_ioc_free_eofblocks(mp, &icw, _RET_IP_);
    2145             : 
    2146           0 :                 sb_start_write(mp->m_super);
    2147           0 :                 error = xfs_blockgc_free_space(mp, &icw);
    2148           0 :                 sb_end_write(mp->m_super);
    2149           0 :                 return error;
    2150             :         }
    2151             : 
    2152             :         default:
    2153             :                 return -ENOTTY;
    2154             :         }
    2155             : }

Generated by: LCOV version 1.14