vserver 1.9.3
[linux-2.6.git] / fs / xfs / linux-2.6 / xfs_ioctl.c
1 /*
2  * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of version 2 of the GNU General Public License as
6  * published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it would be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11  *
12  * Further, this software is distributed without any warranty that it is
13  * free of the rightful claim of any third person regarding infringement
14  * or the like.  Any license provided herein, whether implied or
15  * otherwise, applies only to this software file.  Patent licenses, if
16  * any, provided herein do not apply to combinations of this program with
17  * other software, or any other product whatsoever.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write the Free Software Foundation, Inc., 59
21  * Temple Place - Suite 330, Boston MA 02111-1307, USA.
22  *
23  * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24  * Mountain View, CA  94043, or:
25  *
26  * http://www.sgi.com
27  *
28  * For further information regarding this notice, see:
29  *
30  * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
31  */
32
33 #include "xfs.h"
34
35 #include "xfs_fs.h"
36 #include "xfs_inum.h"
37 #include "xfs_log.h"
38 #include "xfs_trans.h"
39 #include "xfs_sb.h"
40 #include "xfs_dir.h"
41 #include "xfs_dir2.h"
42 #include "xfs_alloc.h"
43 #include "xfs_dmapi.h"
44 #include "xfs_mount.h"
45 #include "xfs_alloc_btree.h"
46 #include "xfs_bmap_btree.h"
47 #include "xfs_ialloc_btree.h"
48 #include "xfs_btree.h"
49 #include "xfs_ialloc.h"
50 #include "xfs_attr_sf.h"
51 #include "xfs_dir_sf.h"
52 #include "xfs_dir2_sf.h"
53 #include "xfs_dinode.h"
54 #include "xfs_inode.h"
55 #include "xfs_bmap.h"
56 #include "xfs_bit.h"
57 #include "xfs_rtalloc.h"
58 #include "xfs_error.h"
59 #include "xfs_itable.h"
60 #include "xfs_rw.h"
61 #include "xfs_acl.h"
62 #include "xfs_cap.h"
63 #include "xfs_mac.h"
64 #include "xfs_attr.h"
65 #include "xfs_buf_item.h"
66 #include "xfs_utils.h"
67 #include "xfs_dfrag.h"
68 #include "xfs_fsops.h"
69
70 #include <linux/dcache.h>
71 #include <linux/mount.h>
72 #include <linux/namei.h>
73 #include <linux/pagemap.h>
74
75 /*
76  * xfs_find_handle maps from userspace xfs_fsop_handlereq structure to
77  * a file or fs handle.
78  *
79  * XFS_IOC_PATH_TO_FSHANDLE
80  *    returns fs handle for a mount point or path within that mount point
81  * XFS_IOC_FD_TO_HANDLE
82  *    returns full handle for a FD opened in user space
83  * XFS_IOC_PATH_TO_HANDLE
84  *    returns full handle for a path
85  */
86 STATIC int
87 xfs_find_handle(
88         unsigned int            cmd,
89         void                    __user *arg)
90 {
91         int                     hsize;
92         xfs_handle_t            handle;
93         xfs_fsop_handlereq_t    hreq;
94         struct inode            *inode;
95         struct vnode            *vp;
96
97         if (copy_from_user(&hreq, arg, sizeof(hreq)))
98                 return -XFS_ERROR(EFAULT);
99
100         memset((char *)&handle, 0, sizeof(handle));
101
102         switch (cmd) {
103         case XFS_IOC_PATH_TO_FSHANDLE:
104         case XFS_IOC_PATH_TO_HANDLE: {
105                 struct nameidata        nd;
106                 int                     error;
107
108                 error = user_path_walk_link((const char __user *)hreq.path, &nd);
109                 if (error)
110                         return error;
111
112                 ASSERT(nd.dentry);
113                 ASSERT(nd.dentry->d_inode);
114                 inode = igrab(nd.dentry->d_inode);
115                 path_release(&nd);
116                 break;
117         }
118
119         case XFS_IOC_FD_TO_HANDLE: {
120                 struct file     *file;
121
122                 file = fget(hreq.fd);
123                 if (!file)
124                     return -EBADF;
125
126                 ASSERT(file->f_dentry);
127                 ASSERT(file->f_dentry->d_inode);
128                 inode = igrab(file->f_dentry->d_inode);
129                 fput(file);
130                 break;
131         }
132
133         default:
134                 ASSERT(0);
135                 return -XFS_ERROR(EINVAL);
136         }
137
138         if (inode->i_sb->s_magic != XFS_SB_MAGIC) {
139                 /* we're not in XFS anymore, Toto */
140                 iput(inode);
141                 return -XFS_ERROR(EINVAL);
142         }
143
144         /* we need the vnode */
145         vp = LINVFS_GET_VP(inode);
146         if (vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK) {
147                 iput(inode);
148                 return -XFS_ERROR(EBADF);
149         }
150
151         /* now we can grab the fsid */
152         memcpy(&handle.ha_fsid, vp->v_vfsp->vfs_altfsid, sizeof(xfs_fsid_t));
153         hsize = sizeof(xfs_fsid_t);
154
155         if (cmd != XFS_IOC_PATH_TO_FSHANDLE) {
156                 xfs_inode_t     *ip;
157                 bhv_desc_t      *bhv;
158                 int             lock_mode;
159
160                 /* need to get access to the xfs_inode to read the generation */
161                 bhv = vn_bhv_lookup_unlocked(VN_BHV_HEAD(vp), &xfs_vnodeops);
162                 ASSERT(bhv);
163                 ip = XFS_BHVTOI(bhv);
164                 ASSERT(ip);
165                 lock_mode = xfs_ilock_map_shared(ip);
166
167                 /* fill in fid section of handle from inode */
168                 handle.ha_fid.xfs_fid_len = sizeof(xfs_fid_t) -
169                                             sizeof(handle.ha_fid.xfs_fid_len);
170                 handle.ha_fid.xfs_fid_pad = 0;
171                 handle.ha_fid.xfs_fid_gen = ip->i_d.di_gen;
172                 handle.ha_fid.xfs_fid_ino = ip->i_ino;
173
174                 xfs_iunlock_map_shared(ip, lock_mode);
175
176                 hsize = XFS_HSIZE(handle);
177         }
178
179         /* now copy our handle into the user buffer & write out the size */
180         if (copy_to_user(hreq.ohandle, &handle, hsize) ||
181             copy_to_user(hreq.ohandlen, &hsize, sizeof(__s32))) {
182                 iput(inode);
183                 return -XFS_ERROR(EFAULT);
184         }
185
186         iput(inode);
187         return 0;
188 }
189
190
191 /*
192  * Convert userspace handle data into vnode (and inode).
193  * We [ab]use the fact that all the fsop_handlereq ioctl calls
194  * have a data structure argument whose first component is always
195  * a xfs_fsop_handlereq_t, so we can cast to and from this type.
196  * This allows us to optimise the copy_from_user calls and gives
197  * a handy, shared routine.
198  *
199  * If no error, caller must always VN_RELE the returned vp.
200  */
201 STATIC int
202 xfs_vget_fsop_handlereq(
203         xfs_mount_t             *mp,
204         struct inode            *parinode,      /* parent inode pointer    */
205         int                     cap,            /* capability level for op */
206         void                    __user *arg,    /* userspace data pointer  */
207         unsigned long           size,           /* size of expected struct */
208         /* output arguments */
209         xfs_fsop_handlereq_t    *hreq,
210         vnode_t                 **vp,
211         struct inode            **inode)
212 {
213         void                    __user *hanp;
214         size_t                  hlen;
215         xfs_fid_t               *xfid;
216         xfs_handle_t            *handlep;
217         xfs_handle_t            handle;
218         xfs_inode_t             *ip;
219         struct inode            *inodep;
220         vnode_t                 *vpp;
221         xfs_ino_t               ino;
222         __u32                   igen;
223         int                     error;
224
225         if (!capable(cap))
226                 return XFS_ERROR(EPERM);
227
228         /*
229          * Only allow handle opens under a directory.
230          */
231         if (!S_ISDIR(parinode->i_mode))
232                 return XFS_ERROR(ENOTDIR);
233
234         /*
235          * Copy the handle down from the user and validate
236          * that it looks to be in the correct format.
237          */
238         if (copy_from_user(hreq, arg, size))
239                 return XFS_ERROR(EFAULT);
240
241         hanp = hreq->ihandle;
242         hlen = hreq->ihandlen;
243         handlep = &handle;
244
245         if (hlen < sizeof(handlep->ha_fsid) || hlen > sizeof(*handlep))
246                 return XFS_ERROR(EINVAL);
247         if (copy_from_user(handlep, hanp, hlen))
248                 return XFS_ERROR(EFAULT);
249         if (hlen < sizeof(*handlep))
250                 memset(((char *)handlep) + hlen, 0, sizeof(*handlep) - hlen);
251         if (hlen > sizeof(handlep->ha_fsid)) {
252                 if (handlep->ha_fid.xfs_fid_len !=
253                                 (hlen - sizeof(handlep->ha_fsid)
254                                         - sizeof(handlep->ha_fid.xfs_fid_len))
255                     || handlep->ha_fid.xfs_fid_pad)
256                         return XFS_ERROR(EINVAL);
257         }
258
259         /*
260          * Crack the handle, obtain the inode # & generation #
261          */
262         xfid = (struct xfs_fid *)&handlep->ha_fid;
263         if (xfid->xfs_fid_len == sizeof(*xfid) - sizeof(xfid->xfs_fid_len)) {
264                 ino  = xfid->xfs_fid_ino;
265                 igen = xfid->xfs_fid_gen;
266         } else {
267                 return XFS_ERROR(EINVAL);
268         }
269
270         /*
271          * Get the XFS inode, building a vnode to go with it.
272          */
273         error = xfs_iget(mp, NULL, ino, XFS_ILOCK_SHARED, &ip, 0);
274         if (error)
275                 return error;
276         if (ip == NULL)
277                 return XFS_ERROR(EIO);
278         if (ip->i_d.di_mode == 0 || ip->i_d.di_gen != igen) {
279                 xfs_iput_new(ip, XFS_ILOCK_SHARED);
280                 return XFS_ERROR(ENOENT);
281         }
282
283         vpp = XFS_ITOV(ip);
284         inodep = LINVFS_GET_IP(vpp);
285         xfs_iunlock(ip, XFS_ILOCK_SHARED);
286
287         *vp = vpp;
288         *inode = inodep;
289         return 0;
290 }
291
292 STATIC int
293 xfs_open_by_handle(
294         xfs_mount_t             *mp,
295         void                    __user *arg,
296         struct file             *parfilp,
297         struct inode            *parinode)
298 {
299         int                     error;
300         int                     new_fd;
301         int                     permflag;
302         struct file             *filp;
303         struct inode            *inode;
304         struct dentry           *dentry;
305         vnode_t                 *vp;
306         xfs_fsop_handlereq_t    hreq;
307
308         error = xfs_vget_fsop_handlereq(mp, parinode, CAP_SYS_ADMIN, arg,
309                                         sizeof(xfs_fsop_handlereq_t),
310                                         &hreq, &vp, &inode);
311         if (error)
312                 return -error;
313
314         /* Restrict xfs_open_by_handle to directories & regular files. */
315         if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) {
316                 iput(inode);
317                 return -XFS_ERROR(EINVAL);
318         }
319
320 #if BITS_PER_LONG != 32
321         hreq.oflags |= O_LARGEFILE;
322 #endif
323         /* Put open permission in namei format. */
324         permflag = hreq.oflags;
325         if ((permflag+1) & O_ACCMODE)
326                 permflag++;
327         if (permflag & O_TRUNC)
328                 permflag |= 2;
329
330         if ((!(permflag & O_APPEND) || (permflag & O_TRUNC)) &&
331             (permflag & FMODE_WRITE) && IS_APPEND(inode)) {
332                 iput(inode);
333                 return -XFS_ERROR(EPERM);
334         }
335
336         if ((permflag & FMODE_WRITE) && IS_IMMUTABLE(inode)) {
337                 iput(inode);
338                 return -XFS_ERROR(EACCES);
339         }
340
341         /* Can't write directories. */
342         if ( S_ISDIR(inode->i_mode) && (permflag & FMODE_WRITE)) {
343                 iput(inode);
344                 return -XFS_ERROR(EISDIR);
345         }
346
347         if ((new_fd = get_unused_fd()) < 0) {
348                 iput(inode);
349                 return new_fd;
350         }
351
352         dentry = d_alloc_anon(inode);
353         if (dentry == NULL) {
354                 iput(inode);
355                 put_unused_fd(new_fd);
356                 return -XFS_ERROR(ENOMEM);
357         }
358
359         /* Ensure umount returns EBUSY on umounts while this file is open. */
360         mntget(parfilp->f_vfsmnt);
361
362         /* Create file pointer. */
363         filp = dentry_open(dentry, parfilp->f_vfsmnt, hreq.oflags);
364         if (IS_ERR(filp)) {
365                 put_unused_fd(new_fd);
366                 return -XFS_ERROR(-PTR_ERR(filp));
367         }
368         if (inode->i_mode & S_IFREG)
369                 filp->f_op = &linvfs_invis_file_operations;
370
371         fd_install(new_fd, filp);
372         return new_fd;
373 }
374
375 STATIC int
376 xfs_readlink_by_handle(
377         xfs_mount_t             *mp,
378         void                    __user *arg,
379         struct file             *parfilp,
380         struct inode            *parinode)
381 {
382         int                     error;
383         struct iovec            aiov;
384         struct uio              auio;
385         struct inode            *inode;
386         xfs_fsop_handlereq_t    hreq;
387         vnode_t                 *vp;
388         __u32                   olen;
389
390         error = xfs_vget_fsop_handlereq(mp, parinode, CAP_SYS_ADMIN, arg,
391                                         sizeof(xfs_fsop_handlereq_t),
392                                         &hreq, &vp, &inode);
393         if (error)
394                 return -error;
395
396         /* Restrict this handle operation to symlinks only. */
397         if (vp->v_type != VLNK) {
398                 VN_RELE(vp);
399                 return -XFS_ERROR(EINVAL);
400         }
401
402         if (copy_from_user(&olen, hreq.ohandlen, sizeof(__u32))) {
403                 VN_RELE(vp);
404                 return -XFS_ERROR(EFAULT);
405         }
406         aiov.iov_len    = olen;
407         aiov.iov_base   = hreq.ohandle;
408
409         auio.uio_iov    = &aiov;
410         auio.uio_iovcnt = 1;
411         auio.uio_offset = 0;
412         auio.uio_segflg = UIO_USERSPACE;
413         auio.uio_resid  = olen;
414
415         VOP_READLINK(vp, &auio, IO_INVIS, NULL, error);
416
417         VN_RELE(vp);
418         return (olen - auio.uio_resid);
419 }
420
421 STATIC int
422 xfs_fssetdm_by_handle(
423         xfs_mount_t             *mp,
424         void                    __user *arg,
425         struct file             *parfilp,
426         struct inode            *parinode)
427 {
428         int                     error;
429         struct fsdmidata        fsd;
430         xfs_fsop_setdm_handlereq_t dmhreq;
431         struct inode            *inode;
432         bhv_desc_t              *bdp;
433         vnode_t                 *vp;
434
435         error = xfs_vget_fsop_handlereq(mp, parinode, CAP_MKNOD, arg,
436                                         sizeof(xfs_fsop_setdm_handlereq_t),
437                                         (xfs_fsop_handlereq_t *)&dmhreq,
438                                         &vp, &inode);
439         if (error)
440                 return -error;
441
442         if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) {
443                 VN_RELE(vp);
444                 return -XFS_ERROR(EPERM);
445         }
446
447         if (copy_from_user(&fsd, dmhreq.data, sizeof(fsd))) {
448                 VN_RELE(vp);
449                 return -XFS_ERROR(EFAULT);
450         }
451
452         bdp = bhv_base_unlocked(VN_BHV_HEAD(vp));
453         error = xfs_set_dmattrs(bdp, fsd.fsd_dmevmask, fsd.fsd_dmstate, NULL);
454
455         VN_RELE(vp);
456         if (error)
457                 return -error;
458         return 0;
459 }
460
461 STATIC int
462 xfs_attrlist_by_handle(
463         xfs_mount_t             *mp,
464         void                    __user *arg,
465         struct file             *parfilp,
466         struct inode            *parinode)
467 {
468         int                     error;
469         attrlist_cursor_kern_t  *cursor;
470         xfs_fsop_attrlist_handlereq_t al_hreq;
471         struct inode            *inode;
472         vnode_t                 *vp;
473
474         error = xfs_vget_fsop_handlereq(mp, parinode, CAP_SYS_ADMIN, arg,
475                                         sizeof(xfs_fsop_attrlist_handlereq_t),
476                                         (xfs_fsop_handlereq_t *)&al_hreq,
477                                         &vp, &inode);
478         if (error)
479                 return -error;
480
481         cursor = (attrlist_cursor_kern_t *)&al_hreq.pos;
482         VOP_ATTR_LIST(vp, al_hreq.buffer, al_hreq.buflen, al_hreq.flags,
483                         cursor, NULL, error);
484         VN_RELE(vp);
485         if (error)
486                 return -error;
487         return 0;
488 }
489
490 STATIC int
491 xfs_attrmulti_by_handle(
492         xfs_mount_t             *mp,
493         void                    __user *arg,
494         struct file             *parfilp,
495         struct inode            *parinode)
496 {
497         int                     error;
498         xfs_attr_multiop_t      *ops;
499         xfs_fsop_attrmulti_handlereq_t am_hreq;
500         struct inode            *inode;
501         vnode_t                 *vp;
502         int                     i, size;
503
504         error = xfs_vget_fsop_handlereq(mp, parinode, CAP_SYS_ADMIN, arg,
505                                         sizeof(xfs_fsop_attrmulti_handlereq_t),
506                                         (xfs_fsop_handlereq_t *)&am_hreq,
507                                         &vp, &inode);
508         if (error)
509                 return -error;
510
511         size = am_hreq.opcount * sizeof(attr_multiop_t);
512         ops = (xfs_attr_multiop_t *)kmalloc(size, GFP_KERNEL);
513         if (!ops) {
514                 VN_RELE(vp);
515                 return -XFS_ERROR(ENOMEM);
516         }
517
518         if (copy_from_user(ops, am_hreq.ops, size)) {
519                 kfree(ops);
520                 VN_RELE(vp);
521                 return -XFS_ERROR(EFAULT);
522         }
523
524         for (i = 0; i < am_hreq.opcount; i++) {
525                 switch(ops[i].am_opcode) {
526                 case ATTR_OP_GET:
527                         VOP_ATTR_GET(vp,ops[i].am_attrname, ops[i].am_attrvalue,
528                                         &ops[i].am_length, ops[i].am_flags,
529                                         NULL, ops[i].am_error);
530                         break;
531                 case ATTR_OP_SET:
532                         if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) {
533                                 ops[i].am_error = EPERM;
534                                 break;
535                         }
536                         VOP_ATTR_SET(vp,ops[i].am_attrname, ops[i].am_attrvalue,
537                                         ops[i].am_length, ops[i].am_flags,
538                                         NULL, ops[i].am_error);
539                         break;
540                 case ATTR_OP_REMOVE:
541                         if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) {
542                                 ops[i].am_error = EPERM;
543                                 break;
544                         }
545                         VOP_ATTR_REMOVE(vp, ops[i].am_attrname, ops[i].am_flags,
546                                         NULL, ops[i].am_error);
547                         break;
548                 default:
549                         ops[i].am_error = EINVAL;
550                 }
551         }
552
553         if (copy_to_user(am_hreq.ops, ops, size))
554                 error = -XFS_ERROR(EFAULT);
555
556         kfree(ops);
557         VN_RELE(vp);
558         return error;
559 }
560
561 /* prototypes for a few of the stack-hungry cases that have
562  * their own functions.  Functions are defined after their use
563  * so gcc doesn't get fancy and inline them with -03 */
564
565 STATIC int
566 xfs_ioc_space(
567         bhv_desc_t              *bdp,
568         vnode_t                 *vp,
569         struct file             *filp,
570         int                     flags,
571         unsigned int            cmd,
572         void                    __user *arg);
573
574 STATIC int
575 xfs_ioc_bulkstat(
576         xfs_mount_t             *mp,
577         unsigned int            cmd,
578         void                    __user *arg);
579
580 STATIC int
581 xfs_ioc_fsgeometry_v1(
582         xfs_mount_t             *mp,
583         void                    __user *arg);
584
585 STATIC int
586 xfs_ioc_fsgeometry(
587         xfs_mount_t             *mp,
588         void                    __user *arg);
589
590 STATIC int
591 xfs_ioc_xattr(
592         vnode_t                 *vp,
593         xfs_inode_t             *ip,
594         struct file             *filp,
595         unsigned int            cmd,
596         void                    __user *arg);
597
598 STATIC int
599 xfs_ioc_getbmap(
600         bhv_desc_t              *bdp,
601         struct file             *filp,
602         int                     flags,
603         unsigned int            cmd,
604         void                    __user *arg);
605
606 STATIC int
607 xfs_ioc_getbmapx(
608         bhv_desc_t              *bdp,
609         void                    __user *arg);
610
611 int
612 xfs_ioctl(
613         bhv_desc_t              *bdp,
614         struct inode            *inode,
615         struct file             *filp,
616         int                     ioflags,
617         unsigned int            cmd,
618         void                    __user *arg)
619 {
620         int                     error;
621         vnode_t                 *vp;
622         xfs_inode_t             *ip;
623         xfs_mount_t             *mp;
624
625         vp = LINVFS_GET_VP(inode);
626
627         vn_trace_entry(vp, "xfs_ioctl", (inst_t *)__return_address);
628
629         ip = XFS_BHVTOI(bdp);
630         mp = ip->i_mount;
631
632         switch (cmd) {
633
634         case XFS_IOC_ALLOCSP:
635         case XFS_IOC_FREESP:
636         case XFS_IOC_RESVSP:
637         case XFS_IOC_UNRESVSP:
638         case XFS_IOC_ALLOCSP64:
639         case XFS_IOC_FREESP64:
640         case XFS_IOC_RESVSP64:
641         case XFS_IOC_UNRESVSP64:
642                 /*
643                  * Only allow the sys admin to reserve space unless
644                  * unwritten extents are enabled.
645                  */
646                 if (!XFS_SB_VERSION_HASEXTFLGBIT(&mp->m_sb) &&
647                     !capable(CAP_SYS_ADMIN))
648                         return -EPERM;
649
650                 return xfs_ioc_space(bdp, vp, filp, ioflags, cmd, arg);
651
652         case XFS_IOC_DIOINFO: {
653                 struct dioattr  da;
654                 xfs_buftarg_t   *target =
655                         (ip->i_d.di_flags & XFS_DIFLAG_REALTIME) ?
656                         mp->m_rtdev_targp : mp->m_ddev_targp;
657
658                 da.d_mem = da.d_miniosz = 1 << target->pbr_sshift;
659                 /* The size dio will do in one go */
660                 da.d_maxiosz = 64 * PAGE_CACHE_SIZE;
661
662                 if (copy_to_user(arg, &da, sizeof(da)))
663                         return -XFS_ERROR(EFAULT);
664                 return 0;
665         }
666
667         case XFS_IOC_FSBULKSTAT_SINGLE:
668         case XFS_IOC_FSBULKSTAT:
669         case XFS_IOC_FSINUMBERS:
670                 return xfs_ioc_bulkstat(mp, cmd, arg);
671
672         case XFS_IOC_FSGEOMETRY_V1:
673                 return xfs_ioc_fsgeometry_v1(mp, arg);
674
675         case XFS_IOC_FSGEOMETRY:
676                 return xfs_ioc_fsgeometry(mp, arg);
677
678         case XFS_IOC_GETVERSION:
679         case XFS_IOC_GETXFLAGS:
680         case XFS_IOC_SETXFLAGS:
681         case XFS_IOC_FSGETXATTR:
682         case XFS_IOC_FSSETXATTR:
683         case XFS_IOC_FSGETXATTRA:
684                 return xfs_ioc_xattr(vp, ip, filp, cmd, arg);
685
686         case XFS_IOC_FSSETDM: {
687                 struct fsdmidata        dmi;
688
689                 if (copy_from_user(&dmi, arg, sizeof(dmi)))
690                         return -XFS_ERROR(EFAULT);
691
692                 error = xfs_set_dmattrs(bdp, dmi.fsd_dmevmask, dmi.fsd_dmstate,
693                                                         NULL);
694                 return -error;
695         }
696
697         case XFS_IOC_GETBMAP:
698         case XFS_IOC_GETBMAPA:
699                 return xfs_ioc_getbmap(bdp, filp, ioflags, cmd, arg);
700
701         case XFS_IOC_GETBMAPX:
702                 return xfs_ioc_getbmapx(bdp, arg);
703
704         case XFS_IOC_FD_TO_HANDLE:
705         case XFS_IOC_PATH_TO_HANDLE:
706         case XFS_IOC_PATH_TO_FSHANDLE:
707                 return xfs_find_handle(cmd, arg);
708
709         case XFS_IOC_OPEN_BY_HANDLE:
710                 return xfs_open_by_handle(mp, arg, filp, inode);
711
712         case XFS_IOC_FSSETDM_BY_HANDLE:
713                 return xfs_fssetdm_by_handle(mp, arg, filp, inode);
714
715         case XFS_IOC_READLINK_BY_HANDLE:
716                 return xfs_readlink_by_handle(mp, arg, filp, inode);
717
718         case XFS_IOC_ATTRLIST_BY_HANDLE:
719                 return xfs_attrlist_by_handle(mp, arg, filp, inode);
720
721         case XFS_IOC_ATTRMULTI_BY_HANDLE:
722                 return xfs_attrmulti_by_handle(mp, arg, filp, inode);
723
724         case XFS_IOC_SWAPEXT: {
725                 error = xfs_swapext((struct xfs_swapext __user *)arg);
726                 return -error;
727         }
728
729         case XFS_IOC_FSCOUNTS: {
730                 xfs_fsop_counts_t out;
731
732                 error = xfs_fs_counts(mp, &out);
733                 if (error)
734                         return -error;
735
736                 if (copy_to_user(arg, &out, sizeof(out)))
737                         return -XFS_ERROR(EFAULT);
738                 return 0;
739         }
740
741         case XFS_IOC_SET_RESBLKS: {
742                 xfs_fsop_resblks_t inout;
743                 __uint64_t         in;
744
745                 if (!capable(CAP_SYS_ADMIN))
746                         return -EPERM;
747
748                 if (copy_from_user(&inout, arg, sizeof(inout)))
749                         return -XFS_ERROR(EFAULT);
750
751                 /* input parameter is passed in resblks field of structure */
752                 in = inout.resblks;
753                 error = xfs_reserve_blocks(mp, &in, &inout);
754                 if (error)
755                         return -error;
756
757                 if (copy_to_user(arg, &inout, sizeof(inout)))
758                         return -XFS_ERROR(EFAULT);
759                 return 0;
760         }
761
762         case XFS_IOC_GET_RESBLKS: {
763                 xfs_fsop_resblks_t out;
764
765                 if (!capable(CAP_SYS_ADMIN))
766                         return -EPERM;
767
768                 error = xfs_reserve_blocks(mp, NULL, &out);
769                 if (error)
770                         return -error;
771
772                 if (copy_to_user(arg, &out, sizeof(out)))
773                         return -XFS_ERROR(EFAULT);
774
775                 return 0;
776         }
777
778         case XFS_IOC_FSGROWFSDATA: {
779                 xfs_growfs_data_t in;
780
781                 if (!capable(CAP_SYS_ADMIN))
782                         return -EPERM;
783
784                 if (copy_from_user(&in, arg, sizeof(in)))
785                         return -XFS_ERROR(EFAULT);
786
787                 error = xfs_growfs_data(mp, &in);
788                 return -error;
789         }
790
791         case XFS_IOC_FSGROWFSLOG: {
792                 xfs_growfs_log_t in;
793
794                 if (!capable(CAP_SYS_ADMIN))
795                         return -EPERM;
796
797                 if (copy_from_user(&in, arg, sizeof(in)))
798                         return -XFS_ERROR(EFAULT);
799
800                 error = xfs_growfs_log(mp, &in);
801                 return -error;
802         }
803
804         case XFS_IOC_FSGROWFSRT: {
805                 xfs_growfs_rt_t in;
806
807                 if (!capable(CAP_SYS_ADMIN))
808                         return -EPERM;
809
810                 if (copy_from_user(&in, arg, sizeof(in)))
811                         return -XFS_ERROR(EFAULT);
812
813                 error = xfs_growfs_rt(mp, &in);
814                 return -error;
815         }
816
817         case XFS_IOC_FREEZE:
818                 if (!capable(CAP_SYS_ADMIN))
819                         return -EPERM;
820
821                 if (inode->i_sb->s_frozen == SB_UNFROZEN)
822                         freeze_bdev(inode->i_sb->s_bdev);
823                 return 0;
824
825         case XFS_IOC_THAW:
826                 if (!capable(CAP_SYS_ADMIN))
827                         return -EPERM;
828                 if (inode->i_sb->s_frozen != SB_UNFROZEN)
829                         thaw_bdev(inode->i_sb->s_bdev, inode->i_sb);
830                 return 0;
831
832         case XFS_IOC_GOINGDOWN: {
833                 __uint32_t in;
834
835                 if (!capable(CAP_SYS_ADMIN))
836                         return -EPERM;
837
838                 if (get_user(in, (__uint32_t __user *)arg))
839                         return -XFS_ERROR(EFAULT);
840
841                 error = xfs_fs_goingdown(mp, in);
842                 return -error;
843         }
844
845         case XFS_IOC_ERROR_INJECTION: {
846                 xfs_error_injection_t in;
847
848                 if (!capable(CAP_SYS_ADMIN))
849                         return -EPERM;
850
851                 if (copy_from_user(&in, arg, sizeof(in)))
852                         return -XFS_ERROR(EFAULT);
853
854                 error = xfs_errortag_add(in.errtag, mp);
855                 return -error;
856         }
857
858         case XFS_IOC_ERROR_CLEARALL:
859                 if (!capable(CAP_SYS_ADMIN))
860                         return -EPERM;
861
862                 error = xfs_errortag_clearall(mp);
863                 return -error;
864
865         default:
866                 return -ENOTTY;
867         }
868 }
869
870 STATIC int
871 xfs_ioc_space(
872         bhv_desc_t              *bdp,
873         vnode_t                 *vp,
874         struct file             *filp,
875         int                     ioflags,
876         unsigned int            cmd,
877         void                    __user *arg)
878 {
879         xfs_flock64_t           bf;
880         int                     attr_flags = 0;
881         int                     error;
882
883         if (vp->v_inode.i_flags & (S_IMMUTABLE|S_APPEND))
884                 return -XFS_ERROR(EPERM);
885
886         if (!(filp->f_flags & FMODE_WRITE))
887                 return -XFS_ERROR(EBADF);
888
889         if (vp->v_type != VREG)
890                 return -XFS_ERROR(EINVAL);
891
892         if (copy_from_user(&bf, arg, sizeof(bf)))
893                 return -XFS_ERROR(EFAULT);
894
895         if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
896                 attr_flags |= ATTR_NONBLOCK;
897         if (ioflags & IO_INVIS)
898                 attr_flags |= ATTR_DMI;
899
900         error = xfs_change_file_space(bdp, cmd, &bf, filp->f_pos,
901                                               NULL, attr_flags);
902         return -error;
903 }
904
905 STATIC int
906 xfs_ioc_bulkstat(
907         xfs_mount_t             *mp,
908         unsigned int            cmd,
909         void                    __user *arg)
910 {
911         xfs_fsop_bulkreq_t      bulkreq;
912         int                     count;  /* # of records returned */
913         xfs_ino_t               inlast; /* last inode number */
914         int                     done;
915         int                     error;
916
917         /* done = 1 if there are more stats to get and if bulkstat */
918         /* should be called again (unused here, but used in dmapi) */
919
920         if (!capable(CAP_SYS_ADMIN))
921                 return -EPERM;
922
923         if (XFS_FORCED_SHUTDOWN(mp))
924                 return -XFS_ERROR(EIO);
925
926         if (copy_from_user(&bulkreq, arg, sizeof(xfs_fsop_bulkreq_t)))
927                 return -XFS_ERROR(EFAULT);
928
929         if (copy_from_user(&inlast, bulkreq.lastip, sizeof(__s64)))
930                 return -XFS_ERROR(EFAULT);
931
932         if ((count = bulkreq.icount) <= 0)
933                 return -XFS_ERROR(EINVAL);
934
935         if (cmd == XFS_IOC_FSINUMBERS)
936                 error = xfs_inumbers(mp, &inlast, &count,
937                                                 bulkreq.ubuffer);
938         else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE)
939                 error = xfs_bulkstat_single(mp, &inlast,
940                                                 bulkreq.ubuffer, &done);
941         else {  /* XFS_IOC_FSBULKSTAT */
942                 if (count == 1 && inlast != 0) {
943                         inlast++;
944                         error = xfs_bulkstat_single(mp, &inlast,
945                                         bulkreq.ubuffer, &done);
946                 } else {
947                         error = xfs_bulkstat(mp, &inlast, &count,
948                                 (bulkstat_one_pf)xfs_bulkstat_one, NULL,
949                                 sizeof(xfs_bstat_t), bulkreq.ubuffer,
950                                 BULKSTAT_FG_QUICK, &done);
951                 }
952         }
953
954         if (error)
955                 return -error;
956
957         if (bulkreq.ocount != NULL) {
958                 if (copy_to_user(bulkreq.lastip, &inlast,
959                                                 sizeof(xfs_ino_t)))
960                         return -XFS_ERROR(EFAULT);
961
962                 if (copy_to_user(bulkreq.ocount, &count, sizeof(count)))
963                         return -XFS_ERROR(EFAULT);
964         }
965
966         return 0;
967 }
968
969 STATIC int
970 xfs_ioc_fsgeometry_v1(
971         xfs_mount_t             *mp,
972         void                    __user *arg)
973 {
974         xfs_fsop_geom_v1_t      fsgeo;
975         int                     error;
976
977         error = xfs_fs_geometry(mp, (xfs_fsop_geom_t *)&fsgeo, 3);
978         if (error)
979                 return -error;
980
981         if (copy_to_user(arg, &fsgeo, sizeof(fsgeo)))
982                 return -XFS_ERROR(EFAULT);
983         return 0;
984 }
985
986 STATIC int
987 xfs_ioc_fsgeometry(
988         xfs_mount_t             *mp,
989         void                    __user *arg)
990 {
991         xfs_fsop_geom_t         fsgeo;
992         int                     error;
993
994         error = xfs_fs_geometry(mp, &fsgeo, 4);
995         if (error)
996                 return -error;
997
998         if (copy_to_user(arg, &fsgeo, sizeof(fsgeo)))
999                 return -XFS_ERROR(EFAULT);
1000         return 0;
1001 }
1002
1003 /*
1004  * Linux extended inode flags interface.
1005  */
1006 #define LINUX_XFLAG_SYNC        0x00000008 /* Synchronous updates */
1007 #define LINUX_XFLAG_IMMUTABLE   0x00000010 /* Immutable file */
1008 #define LINUX_XFLAG_APPEND      0x00000020 /* writes to file may only append */
1009 #define LINUX_XFLAG_NODUMP      0x00000040 /* do not dump file */
1010 #define LINUX_XFLAG_NOATIME     0x00000080 /* do not update atime */
1011 #define LINUX_XFLAG_BARRIER     0x00004000 /* chroot() barrier */
1012 #define LINUX_XFLAG_IUNLINK     0x00008000 /* Immutable unlink */
1013
1014 STATIC unsigned int
1015 xfs_merge_ioc_xflags(
1016         unsigned int    flags,
1017         unsigned int    start)
1018 {
1019         unsigned int    xflags = start;
1020
1021         if (flags & LINUX_XFLAG_IMMUTABLE)
1022                 xflags |= XFS_XFLAG_IMMUTABLE;
1023         else
1024                 xflags &= ~XFS_XFLAG_IMMUTABLE;
1025         if (flags & LINUX_XFLAG_APPEND)
1026                 xflags |= XFS_XFLAG_APPEND;
1027         else
1028                 xflags &= ~XFS_XFLAG_APPEND;
1029         if (flags & LINUX_XFLAG_SYNC)
1030                 xflags |= XFS_XFLAG_SYNC;
1031         else
1032                 xflags &= ~XFS_XFLAG_SYNC;
1033         if (flags & LINUX_XFLAG_NOATIME)
1034                 xflags |= XFS_XFLAG_NOATIME;
1035         else
1036                 xflags &= ~XFS_XFLAG_NOATIME;
1037         if (flags & LINUX_XFLAG_NODUMP)
1038                 xflags |= XFS_XFLAG_NODUMP;
1039         else
1040                 xflags &= ~XFS_XFLAG_NODUMP;
1041
1042         return xflags;
1043 }
1044
1045 STATIC unsigned int
1046 xfs_di2lxflags(
1047         __uint16_t      di_flags)
1048 {
1049         unsigned int    flags = 0;
1050
1051         if (di_flags & XFS_DIFLAG_IMMUTABLE)
1052                 flags |= LINUX_XFLAG_IMMUTABLE;
1053         if (di_flags & XFS_DIFLAG_IUNLINK)
1054                 flags |= LINUX_XFLAG_IUNLINK;
1055         if (di_flags & XFS_DIFLAG_BARRIER)
1056                 flags |= LINUX_XFLAG_BARRIER;
1057         if (di_flags & XFS_DIFLAG_APPEND)
1058                 flags |= LINUX_XFLAG_APPEND;
1059         if (di_flags & XFS_DIFLAG_SYNC)
1060                 flags |= LINUX_XFLAG_SYNC;
1061         if (di_flags & XFS_DIFLAG_NOATIME)
1062                 flags |= LINUX_XFLAG_NOATIME;
1063         if (di_flags & XFS_DIFLAG_NODUMP)
1064                 flags |= LINUX_XFLAG_NODUMP;
1065         return flags;
1066 }
1067
1068 STATIC int
1069 xfs_ioc_xattr(
1070         vnode_t                 *vp,
1071         xfs_inode_t             *ip,
1072         struct file             *filp,
1073         unsigned int            cmd,
1074         void                    __user *arg)
1075 {
1076         struct fsxattr          fa;
1077         vattr_t                 va;
1078         int                     error;
1079         int                     attr_flags;
1080         unsigned int            flags;
1081
1082         switch (cmd) {
1083         case XFS_IOC_FSGETXATTR: {
1084                 va.va_mask = XFS_AT_XFLAGS|XFS_AT_EXTSIZE|XFS_AT_NEXTENTS;
1085                 VOP_GETATTR(vp, &va, 0, NULL, error);
1086                 if (error)
1087                         return -error;
1088
1089                 fa.fsx_xflags   = va.va_xflags;
1090                 fa.fsx_extsize  = va.va_extsize;
1091                 fa.fsx_nextents = va.va_nextents;
1092
1093                 if (copy_to_user(arg, &fa, sizeof(fa)))
1094                         return -XFS_ERROR(EFAULT);
1095                 return 0;
1096         }
1097
1098         case XFS_IOC_FSSETXATTR: {
1099                 if (copy_from_user(&fa, arg, sizeof(fa)))
1100                         return -XFS_ERROR(EFAULT);
1101
1102                 attr_flags = 0;
1103                 if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
1104                         attr_flags |= ATTR_NONBLOCK;
1105
1106                 va.va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE;
1107                 va.va_xflags  = fa.fsx_xflags;
1108                 va.va_extsize = fa.fsx_extsize;
1109
1110                 VOP_SETATTR(vp, &va, attr_flags, NULL, error);
1111                 if (!error)
1112                         vn_revalidate(vp);      /* update Linux inode flags */
1113                 return -error;
1114         }
1115
1116         case XFS_IOC_FSGETXATTRA: {
1117                 va.va_mask = XFS_AT_XFLAGS|XFS_AT_EXTSIZE|XFS_AT_ANEXTENTS;
1118                 VOP_GETATTR(vp, &va, 0, NULL, error);
1119                 if (error)
1120                         return -error;
1121
1122                 fa.fsx_xflags   = va.va_xflags;
1123                 fa.fsx_extsize  = va.va_extsize;
1124                 fa.fsx_nextents = va.va_anextents;
1125
1126                 if (copy_to_user(arg, &fa, sizeof(fa)))
1127                         return -XFS_ERROR(EFAULT);
1128                 return 0;
1129         }
1130
1131         case XFS_IOC_GETXFLAGS: {
1132                 flags = xfs_di2lxflags(ip->i_d.di_flags);
1133                 if (copy_to_user(arg, &flags, sizeof(flags)))
1134                         return -XFS_ERROR(EFAULT);
1135                 return 0;
1136         }
1137
1138         case XFS_IOC_SETXFLAGS: {
1139                 if (copy_from_user(&flags, arg, sizeof(flags)))
1140                         return -XFS_ERROR(EFAULT);
1141
1142                 if (flags & ~(LINUX_XFLAG_IMMUTABLE | LINUX_XFLAG_APPEND | \
1143                               LINUX_XFLAG_NOATIME | LINUX_XFLAG_NODUMP | \
1144                               LINUX_XFLAG_SYNC))
1145                         return -XFS_ERROR(EOPNOTSUPP);
1146
1147                 attr_flags = 0;
1148                 if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
1149                         attr_flags |= ATTR_NONBLOCK;
1150
1151                 va.va_mask = XFS_AT_XFLAGS;
1152                 va.va_xflags = xfs_merge_ioc_xflags(flags,
1153                                 xfs_dic2xflags(&ip->i_d, ARCH_NOCONVERT));
1154
1155                 VOP_SETATTR(vp, &va, attr_flags, NULL, error);
1156                 if (!error)
1157                         vn_revalidate(vp);      /* update Linux inode flags */
1158                 return -error;
1159         }
1160
1161         case XFS_IOC_GETVERSION: {
1162                 flags = LINVFS_GET_IP(vp)->i_generation;
1163                 if (copy_to_user(arg, &flags, sizeof(flags)))
1164                         return -XFS_ERROR(EFAULT);
1165                 return 0;
1166         }
1167
1168         default:
1169                 return -ENOTTY;
1170         }
1171 }
1172
1173 STATIC int
1174 xfs_ioc_getbmap(
1175         bhv_desc_t              *bdp,
1176         struct file             *filp,
1177         int                     ioflags,
1178         unsigned int            cmd,
1179         void                    __user *arg)
1180 {
1181         struct getbmap          bm;
1182         int                     iflags;
1183         int                     error;
1184
1185         if (copy_from_user(&bm, arg, sizeof(bm)))
1186                 return -XFS_ERROR(EFAULT);
1187
1188         if (bm.bmv_count < 2)
1189                 return -XFS_ERROR(EINVAL);
1190
1191         iflags = (cmd == XFS_IOC_GETBMAPA ? BMV_IF_ATTRFORK : 0);
1192         if (ioflags & IO_INVIS)
1193                 iflags |= BMV_IF_NO_DMAPI_READ;
1194
1195         error = xfs_getbmap(bdp, &bm, (struct getbmap __user *)arg+1, iflags);
1196         if (error)
1197                 return -error;
1198
1199         if (copy_to_user(arg, &bm, sizeof(bm)))
1200                 return -XFS_ERROR(EFAULT);
1201         return 0;
1202 }
1203
1204 STATIC int
1205 xfs_ioc_getbmapx(
1206         bhv_desc_t              *bdp,
1207         void                    __user *arg)
1208 {
1209         struct getbmapx         bmx;
1210         struct getbmap          bm;
1211         int                     iflags;
1212         int                     error;
1213
1214         if (copy_from_user(&bmx, arg, sizeof(bmx)))
1215                 return -XFS_ERROR(EFAULT);
1216
1217         if (bmx.bmv_count < 2)
1218                 return -XFS_ERROR(EINVAL);
1219
1220         /*
1221          * Map input getbmapx structure to a getbmap
1222          * structure for xfs_getbmap.
1223          */
1224         GETBMAP_CONVERT(bmx, bm);
1225
1226         iflags = bmx.bmv_iflags;
1227
1228         if (iflags & (~BMV_IF_VALID))
1229                 return -XFS_ERROR(EINVAL);
1230
1231         iflags |= BMV_IF_EXTENDED;
1232
1233         error = xfs_getbmap(bdp, &bm, (struct getbmapx __user *)arg+1, iflags);
1234         if (error)
1235                 return -error;
1236
1237         GETBMAP_CONVERT(bm, bmx);
1238
1239         if (copy_to_user(arg, &bmx, sizeof(bmx)))
1240                 return -XFS_ERROR(EFAULT);
1241
1242         return 0;
1243 }