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