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