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