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