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