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