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