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