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