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