Merge branch 'stable/xen-pcifront-fixes' of git://git.kernel.org/pub/scm/linux/kernel...
[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_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 = kzalloc(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         memset(&fa, 0, sizeof(struct fsxattr));
789
790         xfs_ilock(ip, XFS_ILOCK_SHARED);
791         fa.fsx_xflags = xfs_ip2xflags(ip);
792         fa.fsx_extsize = ip->i_d.di_extsize << ip->i_mount->m_sb.sb_blocklog;
793         fa.fsx_projid = xfs_get_projid(ip);
794
795         if (attr) {
796                 if (ip->i_afp) {
797                         if (ip->i_afp->if_flags & XFS_IFEXTENTS)
798                                 fa.fsx_nextents = ip->i_afp->if_bytes /
799                                                         sizeof(xfs_bmbt_rec_t);
800                         else
801                                 fa.fsx_nextents = ip->i_d.di_anextents;
802                 } else
803                         fa.fsx_nextents = 0;
804         } else {
805                 if (ip->i_df.if_flags & XFS_IFEXTENTS)
806                         fa.fsx_nextents = ip->i_df.if_bytes /
807                                                 sizeof(xfs_bmbt_rec_t);
808                 else
809                         fa.fsx_nextents = ip->i_d.di_nextents;
810         }
811         xfs_iunlock(ip, XFS_ILOCK_SHARED);
812
813         if (copy_to_user(arg, &fa, sizeof(fa)))
814                 return -EFAULT;
815         return 0;
816 }
817
818 STATIC void
819 xfs_set_diflags(
820         struct xfs_inode        *ip,
821         unsigned int            xflags)
822 {
823         unsigned int            di_flags;
824
825         /* can't set PREALLOC this way, just preserve it */
826         di_flags = (ip->i_d.di_flags & XFS_DIFLAG_PREALLOC);
827         if (xflags & XFS_XFLAG_IMMUTABLE)
828                 di_flags |= XFS_DIFLAG_IMMUTABLE;
829         if (xflags & XFS_XFLAG_APPEND)
830                 di_flags |= XFS_DIFLAG_APPEND;
831         if (xflags & XFS_XFLAG_SYNC)
832                 di_flags |= XFS_DIFLAG_SYNC;
833         if (xflags & XFS_XFLAG_NOATIME)
834                 di_flags |= XFS_DIFLAG_NOATIME;
835         if (xflags & XFS_XFLAG_NODUMP)
836                 di_flags |= XFS_DIFLAG_NODUMP;
837         if (xflags & XFS_XFLAG_PROJINHERIT)
838                 di_flags |= XFS_DIFLAG_PROJINHERIT;
839         if (xflags & XFS_XFLAG_NODEFRAG)
840                 di_flags |= XFS_DIFLAG_NODEFRAG;
841         if (xflags & XFS_XFLAG_FILESTREAM)
842                 di_flags |= XFS_DIFLAG_FILESTREAM;
843         if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) {
844                 if (xflags & XFS_XFLAG_RTINHERIT)
845                         di_flags |= XFS_DIFLAG_RTINHERIT;
846                 if (xflags & XFS_XFLAG_NOSYMLINKS)
847                         di_flags |= XFS_DIFLAG_NOSYMLINKS;
848                 if (xflags & XFS_XFLAG_EXTSZINHERIT)
849                         di_flags |= XFS_DIFLAG_EXTSZINHERIT;
850         } else if ((ip->i_d.di_mode & S_IFMT) == S_IFREG) {
851                 if (xflags & XFS_XFLAG_REALTIME)
852                         di_flags |= XFS_DIFLAG_REALTIME;
853                 if (xflags & XFS_XFLAG_EXTSIZE)
854                         di_flags |= XFS_DIFLAG_EXTSIZE;
855         }
856
857         ip->i_d.di_flags = di_flags;
858 }
859
860 STATIC void
861 xfs_diflags_to_linux(
862         struct xfs_inode        *ip)
863 {
864         struct inode            *inode = VFS_I(ip);
865         unsigned int            xflags = xfs_ip2xflags(ip);
866
867         if (xflags & XFS_XFLAG_IMMUTABLE)
868                 inode->i_flags |= S_IMMUTABLE;
869         else
870                 inode->i_flags &= ~S_IMMUTABLE;
871         if (xflags & XFS_XFLAG_APPEND)
872                 inode->i_flags |= S_APPEND;
873         else
874                 inode->i_flags &= ~S_APPEND;
875         if (xflags & XFS_XFLAG_SYNC)
876                 inode->i_flags |= S_SYNC;
877         else
878                 inode->i_flags &= ~S_SYNC;
879         if (xflags & XFS_XFLAG_NOATIME)
880                 inode->i_flags |= S_NOATIME;
881         else
882                 inode->i_flags &= ~S_NOATIME;
883 }
884
885 #define FSX_PROJID      1
886 #define FSX_EXTSIZE     2
887 #define FSX_XFLAGS      4
888 #define FSX_NONBLOCK    8
889
890 STATIC int
891 xfs_ioctl_setattr(
892         xfs_inode_t             *ip,
893         struct fsxattr          *fa,
894         int                     mask)
895 {
896         struct xfs_mount        *mp = ip->i_mount;
897         struct xfs_trans        *tp;
898         unsigned int            lock_flags = 0;
899         struct xfs_dquot        *udqp = NULL;
900         struct xfs_dquot        *gdqp = NULL;
901         struct xfs_dquot        *olddquot = NULL;
902         int                     code;
903
904         trace_xfs_ioctl_setattr(ip);
905
906         if (mp->m_flags & XFS_MOUNT_RDONLY)
907                 return XFS_ERROR(EROFS);
908         if (XFS_FORCED_SHUTDOWN(mp))
909                 return XFS_ERROR(EIO);
910
911         /*
912          * Disallow 32bit project ids when projid32bit feature is not enabled.
913          */
914         if ((mask & FSX_PROJID) && (fa->fsx_projid > (__uint16_t)-1) &&
915                         !xfs_sb_version_hasprojid32bit(&ip->i_mount->m_sb))
916                 return XFS_ERROR(EINVAL);
917
918         /*
919          * If disk quotas is on, we make sure that the dquots do exist on disk,
920          * before we start any other transactions. Trying to do this later
921          * is messy. We don't care to take a readlock to look at the ids
922          * in inode here, because we can't hold it across the trans_reserve.
923          * If the IDs do change before we take the ilock, we're covered
924          * because the i_*dquot fields will get updated anyway.
925          */
926         if (XFS_IS_QUOTA_ON(mp) && (mask & FSX_PROJID)) {
927                 code = xfs_qm_vop_dqalloc(ip, ip->i_d.di_uid,
928                                          ip->i_d.di_gid, fa->fsx_projid,
929                                          XFS_QMOPT_PQUOTA, &udqp, &gdqp);
930                 if (code)
931                         return code;
932         }
933
934         /*
935          * For the other attributes, we acquire the inode lock and
936          * first do an error checking pass.
937          */
938         tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_NOT_SIZE);
939         code = xfs_trans_reserve(tp, 0, XFS_ICHANGE_LOG_RES(mp), 0, 0, 0);
940         if (code)
941                 goto error_return;
942
943         lock_flags = XFS_ILOCK_EXCL;
944         xfs_ilock(ip, lock_flags);
945
946         /*
947          * CAP_FOWNER overrides the following restrictions:
948          *
949          * The user ID of the calling process must be equal
950          * to the file owner ID, except in cases where the
951          * CAP_FSETID capability is applicable.
952          */
953         if (current_fsuid() != ip->i_d.di_uid && !capable(CAP_FOWNER)) {
954                 code = XFS_ERROR(EPERM);
955                 goto error_return;
956         }
957
958         /*
959          * Do a quota reservation only if projid is actually going to change.
960          */
961         if (mask & FSX_PROJID) {
962                 if (XFS_IS_QUOTA_RUNNING(mp) &&
963                     XFS_IS_PQUOTA_ON(mp) &&
964                     xfs_get_projid(ip) != fa->fsx_projid) {
965                         ASSERT(tp);
966                         code = xfs_qm_vop_chown_reserve(tp, ip, udqp, gdqp,
967                                                 capable(CAP_FOWNER) ?
968                                                 XFS_QMOPT_FORCE_RES : 0);
969                         if (code)       /* out of quota */
970                                 goto error_return;
971                 }
972         }
973
974         if (mask & FSX_EXTSIZE) {
975                 /*
976                  * Can't change extent size if any extents are allocated.
977                  */
978                 if (ip->i_d.di_nextents &&
979                     ((ip->i_d.di_extsize << mp->m_sb.sb_blocklog) !=
980                      fa->fsx_extsize)) {
981                         code = XFS_ERROR(EINVAL);       /* EFBIG? */
982                         goto error_return;
983                 }
984
985                 /*
986                  * Extent size must be a multiple of the appropriate block
987                  * size, if set at all.
988                  */
989                 if (fa->fsx_extsize != 0) {
990                         xfs_extlen_t    size;
991
992                         if (XFS_IS_REALTIME_INODE(ip) ||
993                             ((mask & FSX_XFLAGS) &&
994                             (fa->fsx_xflags & XFS_XFLAG_REALTIME))) {
995                                 size = mp->m_sb.sb_rextsize <<
996                                        mp->m_sb.sb_blocklog;
997                         } else {
998                                 size = mp->m_sb.sb_blocksize;
999                         }
1000
1001                         if (fa->fsx_extsize % size) {
1002                                 code = XFS_ERROR(EINVAL);
1003                                 goto error_return;
1004                         }
1005                 }
1006         }
1007
1008
1009         if (mask & FSX_XFLAGS) {
1010                 /*
1011                  * Can't change realtime flag if any extents are allocated.
1012                  */
1013                 if ((ip->i_d.di_nextents || ip->i_delayed_blks) &&
1014                     (XFS_IS_REALTIME_INODE(ip)) !=
1015                     (fa->fsx_xflags & XFS_XFLAG_REALTIME)) {
1016                         code = XFS_ERROR(EINVAL);       /* EFBIG? */
1017                         goto error_return;
1018                 }
1019
1020                 /*
1021                  * If realtime flag is set then must have realtime data.
1022                  */
1023                 if ((fa->fsx_xflags & XFS_XFLAG_REALTIME)) {
1024                         if ((mp->m_sb.sb_rblocks == 0) ||
1025                             (mp->m_sb.sb_rextsize == 0) ||
1026                             (ip->i_d.di_extsize % mp->m_sb.sb_rextsize)) {
1027                                 code = XFS_ERROR(EINVAL);
1028                                 goto error_return;
1029                         }
1030                 }
1031
1032                 /*
1033                  * Can't modify an immutable/append-only file unless
1034                  * we have appropriate permission.
1035                  */
1036                 if ((ip->i_d.di_flags &
1037                                 (XFS_DIFLAG_IMMUTABLE|XFS_DIFLAG_APPEND) ||
1038                      (fa->fsx_xflags &
1039                                 (XFS_XFLAG_IMMUTABLE | XFS_XFLAG_APPEND))) &&
1040                     !capable(CAP_LINUX_IMMUTABLE)) {
1041                         code = XFS_ERROR(EPERM);
1042                         goto error_return;
1043                 }
1044         }
1045
1046         xfs_trans_ijoin(tp, ip);
1047
1048         /*
1049          * Change file ownership.  Must be the owner or privileged.
1050          */
1051         if (mask & FSX_PROJID) {
1052                 /*
1053                  * CAP_FSETID overrides the following restrictions:
1054                  *
1055                  * The set-user-ID and set-group-ID bits of a file will be
1056                  * cleared upon successful return from chown()
1057                  */
1058                 if ((ip->i_d.di_mode & (S_ISUID|S_ISGID)) &&
1059                     !capable(CAP_FSETID))
1060                         ip->i_d.di_mode &= ~(S_ISUID|S_ISGID);
1061
1062                 /*
1063                  * Change the ownerships and register quota modifications
1064                  * in the transaction.
1065                  */
1066                 if (xfs_get_projid(ip) != fa->fsx_projid) {
1067                         if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_PQUOTA_ON(mp)) {
1068                                 olddquot = xfs_qm_vop_chown(tp, ip,
1069                                                         &ip->i_gdquot, gdqp);
1070                         }
1071                         xfs_set_projid(ip, fa->fsx_projid);
1072
1073                         /*
1074                          * We may have to rev the inode as well as
1075                          * the superblock version number since projids didn't
1076                          * exist before DINODE_VERSION_2 and SB_VERSION_NLINK.
1077                          */
1078                         if (ip->i_d.di_version == 1)
1079                                 xfs_bump_ino_vers2(tp, ip);
1080                 }
1081
1082         }
1083
1084         if (mask & FSX_EXTSIZE)
1085                 ip->i_d.di_extsize = fa->fsx_extsize >> mp->m_sb.sb_blocklog;
1086         if (mask & FSX_XFLAGS) {
1087                 xfs_set_diflags(ip, fa->fsx_xflags);
1088                 xfs_diflags_to_linux(ip);
1089         }
1090
1091         xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG);
1092         xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
1093
1094         XFS_STATS_INC(xs_ig_attrchg);
1095
1096         /*
1097          * If this is a synchronous mount, make sure that the
1098          * transaction goes to disk before returning to the user.
1099          * This is slightly sub-optimal in that truncates require
1100          * two sync transactions instead of one for wsync filesystems.
1101          * One for the truncate and one for the timestamps since we
1102          * don't want to change the timestamps unless we're sure the
1103          * truncate worked.  Truncates are less than 1% of the laddis
1104          * mix so this probably isn't worth the trouble to optimize.
1105          */
1106         if (mp->m_flags & XFS_MOUNT_WSYNC)
1107                 xfs_trans_set_sync(tp);
1108         code = xfs_trans_commit(tp, 0);
1109         xfs_iunlock(ip, lock_flags);
1110
1111         /*
1112          * Release any dquot(s) the inode had kept before chown.
1113          */
1114         xfs_qm_dqrele(olddquot);
1115         xfs_qm_dqrele(udqp);
1116         xfs_qm_dqrele(gdqp);
1117
1118         return code;
1119
1120  error_return:
1121         xfs_qm_dqrele(udqp);
1122         xfs_qm_dqrele(gdqp);
1123         xfs_trans_cancel(tp, 0);
1124         if (lock_flags)
1125                 xfs_iunlock(ip, lock_flags);
1126         return code;
1127 }
1128
1129 STATIC int
1130 xfs_ioc_fssetxattr(
1131         xfs_inode_t             *ip,
1132         struct file             *filp,
1133         void                    __user *arg)
1134 {
1135         struct fsxattr          fa;
1136         unsigned int            mask;
1137
1138         if (copy_from_user(&fa, arg, sizeof(fa)))
1139                 return -EFAULT;
1140
1141         mask = FSX_XFLAGS | FSX_EXTSIZE | FSX_PROJID;
1142         if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
1143                 mask |= FSX_NONBLOCK;
1144
1145         return -xfs_ioctl_setattr(ip, &fa, mask);
1146 }
1147
1148 STATIC int
1149 xfs_ioc_getxflags(
1150         xfs_inode_t             *ip,
1151         void                    __user *arg)
1152 {
1153         unsigned int            flags;
1154
1155         flags = xfs_di2lxflags(ip->i_d.di_flags);
1156         if (copy_to_user(arg, &flags, sizeof(flags)))
1157                 return -EFAULT;
1158         return 0;
1159 }
1160
1161 STATIC int
1162 xfs_ioc_setxflags(
1163         xfs_inode_t             *ip,
1164         struct file             *filp,
1165         void                    __user *arg)
1166 {
1167         struct fsxattr          fa;
1168         unsigned int            flags;
1169         unsigned int            mask;
1170
1171         if (copy_from_user(&flags, arg, sizeof(flags)))
1172                 return -EFAULT;
1173
1174         if (flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL | \
1175                       FS_NOATIME_FL | FS_NODUMP_FL | \
1176                       FS_SYNC_FL))
1177                 return -EOPNOTSUPP;
1178
1179         mask = FSX_XFLAGS;
1180         if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
1181                 mask |= FSX_NONBLOCK;
1182         fa.fsx_xflags = xfs_merge_ioc_xflags(flags, xfs_ip2xflags(ip));
1183
1184         return -xfs_ioctl_setattr(ip, &fa, mask);
1185 }
1186
1187 STATIC int
1188 xfs_getbmap_format(void **ap, struct getbmapx *bmv, int *full)
1189 {
1190         struct getbmap __user   *base = *ap;
1191
1192         /* copy only getbmap portion (not getbmapx) */
1193         if (copy_to_user(base, bmv, sizeof(struct getbmap)))
1194                 return XFS_ERROR(EFAULT);
1195
1196         *ap += sizeof(struct getbmap);
1197         return 0;
1198 }
1199
1200 STATIC int
1201 xfs_ioc_getbmap(
1202         struct xfs_inode        *ip,
1203         int                     ioflags,
1204         unsigned int            cmd,
1205         void                    __user *arg)
1206 {
1207         struct getbmapx         bmx;
1208         int                     error;
1209
1210         if (copy_from_user(&bmx, arg, sizeof(struct getbmapx)))
1211                 return -XFS_ERROR(EFAULT);
1212
1213         if (bmx.bmv_count < 2)
1214                 return -XFS_ERROR(EINVAL);
1215
1216         bmx.bmv_iflags = (cmd == XFS_IOC_GETBMAPA ? BMV_IF_ATTRFORK : 0);
1217         if (ioflags & IO_INVIS)
1218                 bmx.bmv_iflags |= BMV_IF_NO_DMAPI_READ;
1219
1220         error = xfs_getbmap(ip, &bmx, xfs_getbmap_format,
1221                             (struct getbmap *)arg+1);
1222         if (error)
1223                 return -error;
1224
1225         /* copy back header - only size of getbmap */
1226         if (copy_to_user(arg, &bmx, sizeof(struct getbmap)))
1227                 return -XFS_ERROR(EFAULT);
1228         return 0;
1229 }
1230
1231 STATIC int
1232 xfs_getbmapx_format(void **ap, struct getbmapx *bmv, int *full)
1233 {
1234         struct getbmapx __user  *base = *ap;
1235
1236         if (copy_to_user(base, bmv, sizeof(struct getbmapx)))
1237                 return XFS_ERROR(EFAULT);
1238
1239         *ap += sizeof(struct getbmapx);
1240         return 0;
1241 }
1242
1243 STATIC int
1244 xfs_ioc_getbmapx(
1245         struct xfs_inode        *ip,
1246         void                    __user *arg)
1247 {
1248         struct getbmapx         bmx;
1249         int                     error;
1250
1251         if (copy_from_user(&bmx, arg, sizeof(bmx)))
1252                 return -XFS_ERROR(EFAULT);
1253
1254         if (bmx.bmv_count < 2)
1255                 return -XFS_ERROR(EINVAL);
1256
1257         if (bmx.bmv_iflags & (~BMV_IF_VALID))
1258                 return -XFS_ERROR(EINVAL);
1259
1260         error = xfs_getbmap(ip, &bmx, xfs_getbmapx_format,
1261                             (struct getbmapx *)arg+1);
1262         if (error)
1263                 return -error;
1264
1265         /* copy back header */
1266         if (copy_to_user(arg, &bmx, sizeof(struct getbmapx)))
1267                 return -XFS_ERROR(EFAULT);
1268
1269         return 0;
1270 }
1271
1272 /*
1273  * Note: some of the ioctl's return positive numbers as a
1274  * byte count indicating success, such as readlink_by_handle.
1275  * So we don't "sign flip" like most other routines.  This means
1276  * true errors need to be returned as a negative value.
1277  */
1278 long
1279 xfs_file_ioctl(
1280         struct file             *filp,
1281         unsigned int            cmd,
1282         unsigned long           p)
1283 {
1284         struct inode            *inode = filp->f_path.dentry->d_inode;
1285         struct xfs_inode        *ip = XFS_I(inode);
1286         struct xfs_mount        *mp = ip->i_mount;
1287         void                    __user *arg = (void __user *)p;
1288         int                     ioflags = 0;
1289         int                     error;
1290
1291         if (filp->f_mode & FMODE_NOCMTIME)
1292                 ioflags |= IO_INVIS;
1293
1294         trace_xfs_file_ioctl(ip);
1295
1296         switch (cmd) {
1297         case XFS_IOC_ALLOCSP:
1298         case XFS_IOC_FREESP:
1299         case XFS_IOC_RESVSP:
1300         case XFS_IOC_UNRESVSP:
1301         case XFS_IOC_ALLOCSP64:
1302         case XFS_IOC_FREESP64:
1303         case XFS_IOC_RESVSP64:
1304         case XFS_IOC_UNRESVSP64:
1305         case XFS_IOC_ZERO_RANGE: {
1306                 xfs_flock64_t           bf;
1307
1308                 if (copy_from_user(&bf, arg, sizeof(bf)))
1309                         return -XFS_ERROR(EFAULT);
1310                 return xfs_ioc_space(ip, inode, filp, ioflags, cmd, &bf);
1311         }
1312         case XFS_IOC_DIOINFO: {
1313                 struct dioattr  da;
1314                 xfs_buftarg_t   *target =
1315                         XFS_IS_REALTIME_INODE(ip) ?
1316                         mp->m_rtdev_targp : mp->m_ddev_targp;
1317
1318                 da.d_mem = da.d_miniosz = 1 << target->bt_sshift;
1319                 da.d_maxiosz = INT_MAX & ~(da.d_miniosz - 1);
1320
1321                 if (copy_to_user(arg, &da, sizeof(da)))
1322                         return -XFS_ERROR(EFAULT);
1323                 return 0;
1324         }
1325
1326         case XFS_IOC_FSBULKSTAT_SINGLE:
1327         case XFS_IOC_FSBULKSTAT:
1328         case XFS_IOC_FSINUMBERS:
1329                 return xfs_ioc_bulkstat(mp, cmd, arg);
1330
1331         case XFS_IOC_FSGEOMETRY_V1:
1332                 return xfs_ioc_fsgeometry_v1(mp, arg);
1333
1334         case XFS_IOC_FSGEOMETRY:
1335                 return xfs_ioc_fsgeometry(mp, arg);
1336
1337         case XFS_IOC_GETVERSION:
1338                 return put_user(inode->i_generation, (int __user *)arg);
1339
1340         case XFS_IOC_FSGETXATTR:
1341                 return xfs_ioc_fsgetxattr(ip, 0, arg);
1342         case XFS_IOC_FSGETXATTRA:
1343                 return xfs_ioc_fsgetxattr(ip, 1, arg);
1344         case XFS_IOC_FSSETXATTR:
1345                 return xfs_ioc_fssetxattr(ip, filp, arg);
1346         case XFS_IOC_GETXFLAGS:
1347                 return xfs_ioc_getxflags(ip, arg);
1348         case XFS_IOC_SETXFLAGS:
1349                 return xfs_ioc_setxflags(ip, filp, arg);
1350
1351         case XFS_IOC_FSSETDM: {
1352                 struct fsdmidata        dmi;
1353
1354                 if (copy_from_user(&dmi, arg, sizeof(dmi)))
1355                         return -XFS_ERROR(EFAULT);
1356
1357                 error = xfs_set_dmattrs(ip, dmi.fsd_dmevmask,
1358                                 dmi.fsd_dmstate);
1359                 return -error;
1360         }
1361
1362         case XFS_IOC_GETBMAP:
1363         case XFS_IOC_GETBMAPA:
1364                 return xfs_ioc_getbmap(ip, ioflags, cmd, arg);
1365
1366         case XFS_IOC_GETBMAPX:
1367                 return xfs_ioc_getbmapx(ip, arg);
1368
1369         case XFS_IOC_FD_TO_HANDLE:
1370         case XFS_IOC_PATH_TO_HANDLE:
1371         case XFS_IOC_PATH_TO_FSHANDLE: {
1372                 xfs_fsop_handlereq_t    hreq;
1373
1374                 if (copy_from_user(&hreq, arg, sizeof(hreq)))
1375                         return -XFS_ERROR(EFAULT);
1376                 return xfs_find_handle(cmd, &hreq);
1377         }
1378         case XFS_IOC_OPEN_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_open_by_handle(filp, &hreq);
1384         }
1385         case XFS_IOC_FSSETDM_BY_HANDLE:
1386                 return xfs_fssetdm_by_handle(filp, arg);
1387
1388         case XFS_IOC_READLINK_BY_HANDLE: {
1389                 xfs_fsop_handlereq_t    hreq;
1390
1391                 if (copy_from_user(&hreq, arg, sizeof(xfs_fsop_handlereq_t)))
1392                         return -XFS_ERROR(EFAULT);
1393                 return xfs_readlink_by_handle(filp, &hreq);
1394         }
1395         case XFS_IOC_ATTRLIST_BY_HANDLE:
1396                 return xfs_attrlist_by_handle(filp, arg);
1397
1398         case XFS_IOC_ATTRMULTI_BY_HANDLE:
1399                 return xfs_attrmulti_by_handle(filp, arg);
1400
1401         case XFS_IOC_SWAPEXT: {
1402                 struct xfs_swapext      sxp;
1403
1404                 if (copy_from_user(&sxp, arg, sizeof(xfs_swapext_t)))
1405                         return -XFS_ERROR(EFAULT);
1406                 error = xfs_swapext(&sxp);
1407                 return -error;
1408         }
1409
1410         case XFS_IOC_FSCOUNTS: {
1411                 xfs_fsop_counts_t out;
1412
1413                 error = xfs_fs_counts(mp, &out);
1414                 if (error)
1415                         return -error;
1416
1417                 if (copy_to_user(arg, &out, sizeof(out)))
1418                         return -XFS_ERROR(EFAULT);
1419                 return 0;
1420         }
1421
1422         case XFS_IOC_SET_RESBLKS: {
1423                 xfs_fsop_resblks_t inout;
1424                 __uint64_t         in;
1425
1426                 if (!capable(CAP_SYS_ADMIN))
1427                         return -EPERM;
1428
1429                 if (mp->m_flags & XFS_MOUNT_RDONLY)
1430                         return -XFS_ERROR(EROFS);
1431
1432                 if (copy_from_user(&inout, arg, sizeof(inout)))
1433                         return -XFS_ERROR(EFAULT);
1434
1435                 /* input parameter is passed in resblks field of structure */
1436                 in = inout.resblks;
1437                 error = xfs_reserve_blocks(mp, &in, &inout);
1438                 if (error)
1439                         return -error;
1440
1441                 if (copy_to_user(arg, &inout, sizeof(inout)))
1442                         return -XFS_ERROR(EFAULT);
1443                 return 0;
1444         }
1445
1446         case XFS_IOC_GET_RESBLKS: {
1447                 xfs_fsop_resblks_t out;
1448
1449                 if (!capable(CAP_SYS_ADMIN))
1450                         return -EPERM;
1451
1452                 error = xfs_reserve_blocks(mp, NULL, &out);
1453                 if (error)
1454                         return -error;
1455
1456                 if (copy_to_user(arg, &out, sizeof(out)))
1457                         return -XFS_ERROR(EFAULT);
1458
1459                 return 0;
1460         }
1461
1462         case XFS_IOC_FSGROWFSDATA: {
1463                 xfs_growfs_data_t in;
1464
1465                 if (copy_from_user(&in, arg, sizeof(in)))
1466                         return -XFS_ERROR(EFAULT);
1467
1468                 error = xfs_growfs_data(mp, &in);
1469                 return -error;
1470         }
1471
1472         case XFS_IOC_FSGROWFSLOG: {
1473                 xfs_growfs_log_t in;
1474
1475                 if (copy_from_user(&in, arg, sizeof(in)))
1476                         return -XFS_ERROR(EFAULT);
1477
1478                 error = xfs_growfs_log(mp, &in);
1479                 return -error;
1480         }
1481
1482         case XFS_IOC_FSGROWFSRT: {
1483                 xfs_growfs_rt_t in;
1484
1485                 if (copy_from_user(&in, arg, sizeof(in)))
1486                         return -XFS_ERROR(EFAULT);
1487
1488                 error = xfs_growfs_rt(mp, &in);
1489                 return -error;
1490         }
1491
1492         case XFS_IOC_GOINGDOWN: {
1493                 __uint32_t in;
1494
1495                 if (!capable(CAP_SYS_ADMIN))
1496                         return -EPERM;
1497
1498                 if (get_user(in, (__uint32_t __user *)arg))
1499                         return -XFS_ERROR(EFAULT);
1500
1501                 error = xfs_fs_goingdown(mp, in);
1502                 return -error;
1503         }
1504
1505         case XFS_IOC_ERROR_INJECTION: {
1506                 xfs_error_injection_t in;
1507
1508                 if (!capable(CAP_SYS_ADMIN))
1509                         return -EPERM;
1510
1511                 if (copy_from_user(&in, arg, sizeof(in)))
1512                         return -XFS_ERROR(EFAULT);
1513
1514                 error = xfs_errortag_add(in.errtag, mp);
1515                 return -error;
1516         }
1517
1518         case XFS_IOC_ERROR_CLEARALL:
1519                 if (!capable(CAP_SYS_ADMIN))
1520                         return -EPERM;
1521
1522                 error = xfs_errortag_clearall(mp, 1);
1523                 return -error;
1524
1525         default:
1526                 return -ENOTTY;
1527         }
1528 }