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