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