]> git.proxmox.com Git - mirror_ubuntu-kernels.git/blob - fs/xfs/linux-2.6/xfs_ioctl.c
[XFS] call common xfs vnode-level helpers directly and remove vnode operations
[mirror_ubuntu-kernels.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 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 }