[XFS] kill the vfs_fsid and vfs_altfsid members in struct bhv_vfs
[linux-2.6] / 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_getbmap(
713         struct xfs_inode        *ip,
714         int                     flags,
715         unsigned int            cmd,
716         void                    __user *arg);
717
718 STATIC int
719 xfs_ioc_getbmapx(
720         struct xfs_inode        *ip,
721         void                    __user *arg);
722
723 int
724 xfs_ioctl(
725         xfs_inode_t             *ip,
726         struct file             *filp,
727         int                     ioflags,
728         unsigned int            cmd,
729         void                    __user *arg)
730 {
731         struct inode            *inode = filp->f_path.dentry->d_inode;
732         bhv_vnode_t             *vp = vn_from_inode(inode);
733         xfs_mount_t             *mp = ip->i_mount;
734         int                     error;
735
736         vn_trace_entry(XFS_I(inode), "xfs_ioctl", (inst_t *)__return_address);
737
738         switch (cmd) {
739
740         case XFS_IOC_ALLOCSP:
741         case XFS_IOC_FREESP:
742         case XFS_IOC_RESVSP:
743         case XFS_IOC_UNRESVSP:
744         case XFS_IOC_ALLOCSP64:
745         case XFS_IOC_FREESP64:
746         case XFS_IOC_RESVSP64:
747         case XFS_IOC_UNRESVSP64:
748                 /*
749                  * Only allow the sys admin to reserve space unless
750                  * unwritten extents are enabled.
751                  */
752                 if (!XFS_SB_VERSION_HASEXTFLGBIT(&mp->m_sb) &&
753                     !capable(CAP_SYS_ADMIN))
754                         return -EPERM;
755
756                 return xfs_ioc_space(ip, inode, filp, ioflags, cmd, arg);
757
758         case XFS_IOC_DIOINFO: {
759                 struct dioattr  da;
760                 xfs_buftarg_t   *target =
761                         (ip->i_d.di_flags & XFS_DIFLAG_REALTIME) ?
762                         mp->m_rtdev_targp : mp->m_ddev_targp;
763
764                 da.d_mem = da.d_miniosz = 1 << target->bt_sshift;
765                 da.d_maxiosz = INT_MAX & ~(da.d_miniosz - 1);
766
767                 if (copy_to_user(arg, &da, sizeof(da)))
768                         return -XFS_ERROR(EFAULT);
769                 return 0;
770         }
771
772         case XFS_IOC_FSBULKSTAT_SINGLE:
773         case XFS_IOC_FSBULKSTAT:
774         case XFS_IOC_FSINUMBERS:
775                 return xfs_ioc_bulkstat(mp, cmd, arg);
776
777         case XFS_IOC_FSGEOMETRY_V1:
778                 return xfs_ioc_fsgeometry_v1(mp, arg);
779
780         case XFS_IOC_FSGEOMETRY:
781                 return xfs_ioc_fsgeometry(mp, arg);
782
783         case XFS_IOC_GETVERSION:
784                 return put_user(inode->i_generation, (int __user *)arg);
785
786         case XFS_IOC_GETXFLAGS:
787         case XFS_IOC_SETXFLAGS:
788         case XFS_IOC_FSGETXATTR:
789         case XFS_IOC_FSSETXATTR:
790         case XFS_IOC_FSGETXATTRA:
791                 return xfs_ioc_xattr(vp, ip, filp, cmd, arg);
792
793         case XFS_IOC_FSSETDM: {
794                 struct fsdmidata        dmi;
795
796                 if (copy_from_user(&dmi, arg, sizeof(dmi)))
797                         return -XFS_ERROR(EFAULT);
798
799                 error = xfs_set_dmattrs(ip, dmi.fsd_dmevmask,
800                                 dmi.fsd_dmstate);
801                 return -error;
802         }
803
804         case XFS_IOC_GETBMAP:
805         case XFS_IOC_GETBMAPA:
806                 return xfs_ioc_getbmap(ip, ioflags, cmd, arg);
807
808         case XFS_IOC_GETBMAPX:
809                 return xfs_ioc_getbmapx(ip, arg);
810
811         case XFS_IOC_FD_TO_HANDLE:
812         case XFS_IOC_PATH_TO_HANDLE:
813         case XFS_IOC_PATH_TO_FSHANDLE:
814                 return xfs_find_handle(cmd, arg);
815
816         case XFS_IOC_OPEN_BY_HANDLE:
817                 return xfs_open_by_handle(mp, arg, filp, inode);
818
819         case XFS_IOC_FSSETDM_BY_HANDLE:
820                 return xfs_fssetdm_by_handle(mp, arg, inode);
821
822         case XFS_IOC_READLINK_BY_HANDLE:
823                 return xfs_readlink_by_handle(mp, arg, inode);
824
825         case XFS_IOC_ATTRLIST_BY_HANDLE:
826                 return xfs_attrlist_by_handle(mp, arg, inode);
827
828         case XFS_IOC_ATTRMULTI_BY_HANDLE:
829                 return xfs_attrmulti_by_handle(mp, arg, inode);
830
831         case XFS_IOC_SWAPEXT: {
832                 error = xfs_swapext((struct xfs_swapext __user *)arg);
833                 return -error;
834         }
835
836         case XFS_IOC_FSCOUNTS: {
837                 xfs_fsop_counts_t out;
838
839                 error = xfs_fs_counts(mp, &out);
840                 if (error)
841                         return -error;
842
843                 if (copy_to_user(arg, &out, sizeof(out)))
844                         return -XFS_ERROR(EFAULT);
845                 return 0;
846         }
847
848         case XFS_IOC_SET_RESBLKS: {
849                 xfs_fsop_resblks_t inout;
850                 __uint64_t         in;
851
852                 if (!capable(CAP_SYS_ADMIN))
853                         return -EPERM;
854
855                 if (copy_from_user(&inout, arg, sizeof(inout)))
856                         return -XFS_ERROR(EFAULT);
857
858                 /* input parameter is passed in resblks field of structure */
859                 in = inout.resblks;
860                 error = xfs_reserve_blocks(mp, &in, &inout);
861                 if (error)
862                         return -error;
863
864                 if (copy_to_user(arg, &inout, sizeof(inout)))
865                         return -XFS_ERROR(EFAULT);
866                 return 0;
867         }
868
869         case XFS_IOC_GET_RESBLKS: {
870                 xfs_fsop_resblks_t out;
871
872                 if (!capable(CAP_SYS_ADMIN))
873                         return -EPERM;
874
875                 error = xfs_reserve_blocks(mp, NULL, &out);
876                 if (error)
877                         return -error;
878
879                 if (copy_to_user(arg, &out, sizeof(out)))
880                         return -XFS_ERROR(EFAULT);
881
882                 return 0;
883         }
884
885         case XFS_IOC_FSGROWFSDATA: {
886                 xfs_growfs_data_t in;
887
888                 if (!capable(CAP_SYS_ADMIN))
889                         return -EPERM;
890
891                 if (copy_from_user(&in, arg, sizeof(in)))
892                         return -XFS_ERROR(EFAULT);
893
894                 error = xfs_growfs_data(mp, &in);
895                 return -error;
896         }
897
898         case XFS_IOC_FSGROWFSLOG: {
899                 xfs_growfs_log_t in;
900
901                 if (!capable(CAP_SYS_ADMIN))
902                         return -EPERM;
903
904                 if (copy_from_user(&in, arg, sizeof(in)))
905                         return -XFS_ERROR(EFAULT);
906
907                 error = xfs_growfs_log(mp, &in);
908                 return -error;
909         }
910
911         case XFS_IOC_FSGROWFSRT: {
912                 xfs_growfs_rt_t in;
913
914                 if (!capable(CAP_SYS_ADMIN))
915                         return -EPERM;
916
917                 if (copy_from_user(&in, arg, sizeof(in)))
918                         return -XFS_ERROR(EFAULT);
919
920                 error = xfs_growfs_rt(mp, &in);
921                 return -error;
922         }
923
924         case XFS_IOC_FREEZE:
925                 if (!capable(CAP_SYS_ADMIN))
926                         return -EPERM;
927
928                 if (inode->i_sb->s_frozen == SB_UNFROZEN)
929                         freeze_bdev(inode->i_sb->s_bdev);
930                 return 0;
931
932         case XFS_IOC_THAW:
933                 if (!capable(CAP_SYS_ADMIN))
934                         return -EPERM;
935                 if (inode->i_sb->s_frozen != SB_UNFROZEN)
936                         thaw_bdev(inode->i_sb->s_bdev, inode->i_sb);
937                 return 0;
938
939         case XFS_IOC_GOINGDOWN: {
940                 __uint32_t in;
941
942                 if (!capable(CAP_SYS_ADMIN))
943                         return -EPERM;
944
945                 if (get_user(in, (__uint32_t __user *)arg))
946                         return -XFS_ERROR(EFAULT);
947
948                 error = xfs_fs_goingdown(mp, in);
949                 return -error;
950         }
951
952         case XFS_IOC_ERROR_INJECTION: {
953                 xfs_error_injection_t in;
954
955                 if (!capable(CAP_SYS_ADMIN))
956                         return -EPERM;
957
958                 if (copy_from_user(&in, arg, sizeof(in)))
959                         return -XFS_ERROR(EFAULT);
960
961                 error = xfs_errortag_add(in.errtag, mp);
962                 return -error;
963         }
964
965         case XFS_IOC_ERROR_CLEARALL:
966                 if (!capable(CAP_SYS_ADMIN))
967                         return -EPERM;
968
969                 error = xfs_errortag_clearall(mp, 1);
970                 return -error;
971
972         default:
973                 return -ENOTTY;
974         }
975 }
976
977 STATIC int
978 xfs_ioc_space(
979         struct xfs_inode        *ip,
980         struct inode            *inode,
981         struct file             *filp,
982         int                     ioflags,
983         unsigned int            cmd,
984         void                    __user *arg)
985 {
986         xfs_flock64_t           bf;
987         int                     attr_flags = 0;
988         int                     error;
989
990         if (inode->i_flags & (S_IMMUTABLE|S_APPEND))
991                 return -XFS_ERROR(EPERM);
992
993         if (!(filp->f_mode & FMODE_WRITE))
994                 return -XFS_ERROR(EBADF);
995
996         if (!S_ISREG(inode->i_mode))
997                 return -XFS_ERROR(EINVAL);
998
999         if (copy_from_user(&bf, arg, sizeof(bf)))
1000                 return -XFS_ERROR(EFAULT);
1001
1002         if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
1003                 attr_flags |= ATTR_NONBLOCK;
1004         if (ioflags & IO_INVIS)
1005                 attr_flags |= ATTR_DMI;
1006
1007         error = xfs_change_file_space(ip, cmd, &bf, filp->f_pos,
1008                                               NULL, attr_flags);
1009         return -error;
1010 }
1011
1012 STATIC int
1013 xfs_ioc_bulkstat(
1014         xfs_mount_t             *mp,
1015         unsigned int            cmd,
1016         void                    __user *arg)
1017 {
1018         xfs_fsop_bulkreq_t      bulkreq;
1019         int                     count;  /* # of records returned */
1020         xfs_ino_t               inlast; /* last inode number */
1021         int                     done;
1022         int                     error;
1023
1024         /* done = 1 if there are more stats to get and if bulkstat */
1025         /* should be called again (unused here, but used in dmapi) */
1026
1027         if (!capable(CAP_SYS_ADMIN))
1028                 return -EPERM;
1029
1030         if (XFS_FORCED_SHUTDOWN(mp))
1031                 return -XFS_ERROR(EIO);
1032
1033         if (copy_from_user(&bulkreq, arg, sizeof(xfs_fsop_bulkreq_t)))
1034                 return -XFS_ERROR(EFAULT);
1035
1036         if (copy_from_user(&inlast, bulkreq.lastip, sizeof(__s64)))
1037                 return -XFS_ERROR(EFAULT);
1038
1039         if ((count = bulkreq.icount) <= 0)
1040                 return -XFS_ERROR(EINVAL);
1041
1042         if (cmd == XFS_IOC_FSINUMBERS)
1043                 error = xfs_inumbers(mp, &inlast, &count,
1044                                         bulkreq.ubuffer, xfs_inumbers_fmt);
1045         else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE)
1046                 error = xfs_bulkstat_single(mp, &inlast,
1047                                                 bulkreq.ubuffer, &done);
1048         else {  /* XFS_IOC_FSBULKSTAT */
1049                 if (count == 1 && inlast != 0) {
1050                         inlast++;
1051                         error = xfs_bulkstat_single(mp, &inlast,
1052                                         bulkreq.ubuffer, &done);
1053                 } else {
1054                         error = xfs_bulkstat(mp, &inlast, &count,
1055                                 (bulkstat_one_pf)xfs_bulkstat_one, NULL,
1056                                 sizeof(xfs_bstat_t), bulkreq.ubuffer,
1057                                 BULKSTAT_FG_QUICK, &done);
1058                 }
1059         }
1060
1061         if (error)
1062                 return -error;
1063
1064         if (bulkreq.ocount != NULL) {
1065                 if (copy_to_user(bulkreq.lastip, &inlast,
1066                                                 sizeof(xfs_ino_t)))
1067                         return -XFS_ERROR(EFAULT);
1068
1069                 if (copy_to_user(bulkreq.ocount, &count, sizeof(count)))
1070                         return -XFS_ERROR(EFAULT);
1071         }
1072
1073         return 0;
1074 }
1075
1076 STATIC int
1077 xfs_ioc_fsgeometry_v1(
1078         xfs_mount_t             *mp,
1079         void                    __user *arg)
1080 {
1081         xfs_fsop_geom_v1_t      fsgeo;
1082         int                     error;
1083
1084         error = xfs_fs_geometry(mp, (xfs_fsop_geom_t *)&fsgeo, 3);
1085         if (error)
1086                 return -error;
1087
1088         if (copy_to_user(arg, &fsgeo, sizeof(fsgeo)))
1089                 return -XFS_ERROR(EFAULT);
1090         return 0;
1091 }
1092
1093 STATIC int
1094 xfs_ioc_fsgeometry(
1095         xfs_mount_t             *mp,
1096         void                    __user *arg)
1097 {
1098         xfs_fsop_geom_t         fsgeo;
1099         int                     error;
1100
1101         error = xfs_fs_geometry(mp, &fsgeo, 4);
1102         if (error)
1103                 return -error;
1104
1105         if (copy_to_user(arg, &fsgeo, sizeof(fsgeo)))
1106                 return -XFS_ERROR(EFAULT);
1107         return 0;
1108 }
1109
1110 /*
1111  * Linux extended inode flags interface.
1112  */
1113
1114 STATIC unsigned int
1115 xfs_merge_ioc_xflags(
1116         unsigned int    flags,
1117         unsigned int    start)
1118 {
1119         unsigned int    xflags = start;
1120
1121         if (flags & FS_IMMUTABLE_FL)
1122                 xflags |= XFS_XFLAG_IMMUTABLE;
1123         else
1124                 xflags &= ~XFS_XFLAG_IMMUTABLE;
1125         if (flags & FS_APPEND_FL)
1126                 xflags |= XFS_XFLAG_APPEND;
1127         else
1128                 xflags &= ~XFS_XFLAG_APPEND;
1129         if (flags & FS_SYNC_FL)
1130                 xflags |= XFS_XFLAG_SYNC;
1131         else
1132                 xflags &= ~XFS_XFLAG_SYNC;
1133         if (flags & FS_NOATIME_FL)
1134                 xflags |= XFS_XFLAG_NOATIME;
1135         else
1136                 xflags &= ~XFS_XFLAG_NOATIME;
1137         if (flags & FS_NODUMP_FL)
1138                 xflags |= XFS_XFLAG_NODUMP;
1139         else
1140                 xflags &= ~XFS_XFLAG_NODUMP;
1141
1142         return xflags;
1143 }
1144
1145 STATIC unsigned int
1146 xfs_di2lxflags(
1147         __uint16_t      di_flags)
1148 {
1149         unsigned int    flags = 0;
1150
1151         if (di_flags & XFS_DIFLAG_IMMUTABLE)
1152                 flags |= FS_IMMUTABLE_FL;
1153         if (di_flags & XFS_DIFLAG_APPEND)
1154                 flags |= FS_APPEND_FL;
1155         if (di_flags & XFS_DIFLAG_SYNC)
1156                 flags |= FS_SYNC_FL;
1157         if (di_flags & XFS_DIFLAG_NOATIME)
1158                 flags |= FS_NOATIME_FL;
1159         if (di_flags & XFS_DIFLAG_NODUMP)
1160                 flags |= FS_NODUMP_FL;
1161         return flags;
1162 }
1163
1164 STATIC int
1165 xfs_ioc_xattr(
1166         bhv_vnode_t             *vp,
1167         xfs_inode_t             *ip,
1168         struct file             *filp,
1169         unsigned int            cmd,
1170         void                    __user *arg)
1171 {
1172         struct fsxattr          fa;
1173         struct bhv_vattr        *vattr;
1174         int                     error = 0;
1175         int                     attr_flags;
1176         unsigned int            flags;
1177
1178         vattr = kmalloc(sizeof(*vattr), GFP_KERNEL);
1179         if (unlikely(!vattr))
1180                 return -ENOMEM;
1181
1182         switch (cmd) {
1183         case XFS_IOC_FSGETXATTR: {
1184                 vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | \
1185                                  XFS_AT_NEXTENTS | XFS_AT_PROJID;
1186                 error = xfs_getattr(ip, vattr, 0);
1187                 if (unlikely(error)) {
1188                         error = -error;
1189                         break;
1190                 }
1191
1192                 fa.fsx_xflags   = vattr->va_xflags;
1193                 fa.fsx_extsize  = vattr->va_extsize;
1194                 fa.fsx_nextents = vattr->va_nextents;
1195                 fa.fsx_projid   = vattr->va_projid;
1196
1197                 if (copy_to_user(arg, &fa, sizeof(fa))) {
1198                         error = -EFAULT;
1199                         break;
1200                 }
1201                 break;
1202         }
1203
1204         case XFS_IOC_FSSETXATTR: {
1205                 if (copy_from_user(&fa, arg, sizeof(fa))) {
1206                         error = -EFAULT;
1207                         break;
1208                 }
1209
1210                 attr_flags = 0;
1211                 if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
1212                         attr_flags |= ATTR_NONBLOCK;
1213
1214                 vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | XFS_AT_PROJID;
1215                 vattr->va_xflags  = fa.fsx_xflags;
1216                 vattr->va_extsize = fa.fsx_extsize;
1217                 vattr->va_projid  = fa.fsx_projid;
1218
1219                 error = xfs_setattr(ip, vattr, attr_flags, NULL);
1220                 if (likely(!error))
1221                         __vn_revalidate(vp, vattr);     /* update flags */
1222                 error = -error;
1223                 break;
1224         }
1225
1226         case XFS_IOC_FSGETXATTRA: {
1227                 vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | \
1228                                  XFS_AT_ANEXTENTS | XFS_AT_PROJID;
1229                 error = xfs_getattr(ip, vattr, 0);
1230                 if (unlikely(error)) {
1231                         error = -error;
1232                         break;
1233                 }
1234
1235                 fa.fsx_xflags   = vattr->va_xflags;
1236                 fa.fsx_extsize  = vattr->va_extsize;
1237                 fa.fsx_nextents = vattr->va_anextents;
1238                 fa.fsx_projid   = vattr->va_projid;
1239
1240                 if (copy_to_user(arg, &fa, sizeof(fa))) {
1241                         error = -EFAULT;
1242                         break;
1243                 }
1244                 break;
1245         }
1246
1247         case XFS_IOC_GETXFLAGS: {
1248                 flags = xfs_di2lxflags(ip->i_d.di_flags);
1249                 if (copy_to_user(arg, &flags, sizeof(flags)))
1250                         error = -EFAULT;
1251                 break;
1252         }
1253
1254         case XFS_IOC_SETXFLAGS: {
1255                 if (copy_from_user(&flags, arg, sizeof(flags))) {
1256                         error = -EFAULT;
1257                         break;
1258                 }
1259
1260                 if (flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL | \
1261                               FS_NOATIME_FL | FS_NODUMP_FL | \
1262                               FS_SYNC_FL)) {
1263                         error = -EOPNOTSUPP;
1264                         break;
1265                 }
1266
1267                 attr_flags = 0;
1268                 if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
1269                         attr_flags |= ATTR_NONBLOCK;
1270
1271                 vattr->va_mask = XFS_AT_XFLAGS;
1272                 vattr->va_xflags = xfs_merge_ioc_xflags(flags,
1273                                                         xfs_ip2xflags(ip));
1274
1275                 error = xfs_setattr(ip, vattr, attr_flags, NULL);
1276                 if (likely(!error))
1277                         __vn_revalidate(vp, vattr);     /* update flags */
1278                 error = -error;
1279                 break;
1280         }
1281
1282         default:
1283                 error = -ENOTTY;
1284                 break;
1285         }
1286
1287         kfree(vattr);
1288         return error;
1289 }
1290
1291 STATIC int
1292 xfs_ioc_getbmap(
1293         struct xfs_inode        *ip,
1294         int                     ioflags,
1295         unsigned int            cmd,
1296         void                    __user *arg)
1297 {
1298         struct getbmap          bm;
1299         int                     iflags;
1300         int                     error;
1301
1302         if (copy_from_user(&bm, arg, sizeof(bm)))
1303                 return -XFS_ERROR(EFAULT);
1304
1305         if (bm.bmv_count < 2)
1306                 return -XFS_ERROR(EINVAL);
1307
1308         iflags = (cmd == XFS_IOC_GETBMAPA ? BMV_IF_ATTRFORK : 0);
1309         if (ioflags & IO_INVIS)
1310                 iflags |= BMV_IF_NO_DMAPI_READ;
1311
1312         error = xfs_getbmap(ip, &bm, (struct getbmap __user *)arg+1, iflags);
1313         if (error)
1314                 return -error;
1315
1316         if (copy_to_user(arg, &bm, sizeof(bm)))
1317                 return -XFS_ERROR(EFAULT);
1318         return 0;
1319 }
1320
1321 STATIC int
1322 xfs_ioc_getbmapx(
1323         struct xfs_inode        *ip,
1324         void                    __user *arg)
1325 {
1326         struct getbmapx         bmx;
1327         struct getbmap          bm;
1328         int                     iflags;
1329         int                     error;
1330
1331         if (copy_from_user(&bmx, arg, sizeof(bmx)))
1332                 return -XFS_ERROR(EFAULT);
1333
1334         if (bmx.bmv_count < 2)
1335                 return -XFS_ERROR(EINVAL);
1336
1337         /*
1338          * Map input getbmapx structure to a getbmap
1339          * structure for xfs_getbmap.
1340          */
1341         GETBMAP_CONVERT(bmx, bm);
1342
1343         iflags = bmx.bmv_iflags;
1344
1345         if (iflags & (~BMV_IF_VALID))
1346                 return -XFS_ERROR(EINVAL);
1347
1348         iflags |= BMV_IF_EXTENDED;
1349
1350         error = xfs_getbmap(ip, &bm, (struct getbmapx __user *)arg+1, iflags);
1351         if (error)
1352                 return -error;
1353
1354         GETBMAP_CONVERT(bm, bmx);
1355
1356         if (copy_to_user(arg, &bmx, sizeof(bmx)))
1357                 return -XFS_ERROR(EFAULT);
1358
1359         return 0;
1360 }