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