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