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