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