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