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