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