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