]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - fs/xfs/linux-2.6/xfs_ioctl32.c
[XFS] Hook up compat XFS_IOC_ATTRLIST_BY_HANDLE ioctl handler
[linux-2.6-omap-h63xx.git] / fs / xfs / linux-2.6 / xfs_ioctl32.c
1 /*
2  * Copyright (c) 2004-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 <linux/compat.h>
19 #include <linux/init.h>
20 #include <linux/ioctl.h>
21 #include <linux/syscalls.h>
22 #include <linux/types.h>
23 #include <linux/fs.h>
24 #include <asm/uaccess.h>
25 #include "xfs.h"
26 #include "xfs_fs.h"
27 #include "xfs_bit.h"
28 #include "xfs_log.h"
29 #include "xfs_inum.h"
30 #include "xfs_trans.h"
31 #include "xfs_sb.h"
32 #include "xfs_ag.h"
33 #include "xfs_dir2.h"
34 #include "xfs_dmapi.h"
35 #include "xfs_mount.h"
36 #include "xfs_bmap_btree.h"
37 #include "xfs_attr_sf.h"
38 #include "xfs_dir2_sf.h"
39 #include "xfs_vnode.h"
40 #include "xfs_dinode.h"
41 #include "xfs_inode.h"
42 #include "xfs_itable.h"
43 #include "xfs_error.h"
44 #include "xfs_dfrag.h"
45 #include "xfs_vnodeops.h"
46 #include "xfs_fsops.h"
47 #include "xfs_alloc.h"
48 #include "xfs_rtalloc.h"
49 #include "xfs_attr.h"
50 #include "xfs_ioctl.h"
51 #include "xfs_ioctl32.h"
52
53 #define  _NATIVE_IOC(cmd, type) \
54           _IOC(_IOC_DIR(cmd), _IOC_TYPE(cmd), _IOC_NR(cmd), sizeof(type))
55
56 #ifdef BROKEN_X86_ALIGNMENT
57 STATIC int
58 xfs_compat_flock64_copyin(
59         xfs_flock64_t           *bf,
60         compat_xfs_flock64_t    __user *arg32)
61 {
62         if (get_user(bf->l_type,        &arg32->l_type) ||
63             get_user(bf->l_whence,      &arg32->l_whence) ||
64             get_user(bf->l_start,       &arg32->l_start) ||
65             get_user(bf->l_len,         &arg32->l_len) ||
66             get_user(bf->l_sysid,       &arg32->l_sysid) ||
67             get_user(bf->l_pid,         &arg32->l_pid) ||
68             copy_from_user(bf->l_pad,   &arg32->l_pad,  4*sizeof(u32)))
69                 return -XFS_ERROR(EFAULT);
70         return 0;
71 }
72
73 STATIC int
74 xfs_compat_ioc_fsgeometry_v1(
75         struct xfs_mount          *mp,
76         compat_xfs_fsop_geom_v1_t __user *arg32)
77 {
78         xfs_fsop_geom_t           fsgeo;
79         int                       error;
80
81         error = xfs_fs_geometry(mp, &fsgeo, 3);
82         if (error)
83                 return -error;
84         /* The 32-bit variant simply has some padding at the end */
85         if (copy_to_user(arg32, &fsgeo, sizeof(struct compat_xfs_fsop_geom_v1)))
86                 return -XFS_ERROR(EFAULT);
87         return 0;
88 }
89
90 STATIC int
91 xfs_compat_growfs_data_copyin(
92         struct xfs_growfs_data   *in,
93         compat_xfs_growfs_data_t __user *arg32)
94 {
95         if (get_user(in->newblocks, &arg32->newblocks) ||
96             get_user(in->imaxpct,   &arg32->imaxpct))
97                 return -XFS_ERROR(EFAULT);
98         return 0;
99 }
100
101 STATIC int
102 xfs_compat_growfs_rt_copyin(
103         struct xfs_growfs_rt     *in,
104         compat_xfs_growfs_rt_t  __user *arg32)
105 {
106         if (get_user(in->newblocks, &arg32->newblocks) ||
107             get_user(in->extsize,   &arg32->extsize))
108                 return -XFS_ERROR(EFAULT);
109         return 0;
110 }
111
112 STATIC int
113 xfs_inumbers_fmt_compat(
114         void                    __user *ubuffer,
115         const xfs_inogrp_t      *buffer,
116         long                    count,
117         long                    *written)
118 {
119         compat_xfs_inogrp_t     __user *p32 = ubuffer;
120         long                    i;
121
122         for (i = 0; i < count; i++) {
123                 if (put_user(buffer[i].xi_startino,   &p32[i].xi_startino) ||
124                     put_user(buffer[i].xi_alloccount, &p32[i].xi_alloccount) ||
125                     put_user(buffer[i].xi_allocmask,  &p32[i].xi_allocmask))
126                         return -XFS_ERROR(EFAULT);
127         }
128         *written = count * sizeof(*p32);
129         return 0;
130 }
131
132 #else
133 #define xfs_inumbers_fmt_compat xfs_inumbers_fmt
134 #endif
135
136 STATIC int
137 xfs_ioctl32_bstime_copyin(
138         xfs_bstime_t            *bstime,
139         compat_xfs_bstime_t     __user *bstime32)
140 {
141         compat_time_t           sec32;  /* tv_sec differs on 64 vs. 32 */
142
143         if (get_user(sec32,             &bstime32->tv_sec)      ||
144             get_user(bstime->tv_nsec,   &bstime32->tv_nsec))
145                 return -XFS_ERROR(EFAULT);
146         bstime->tv_sec = sec32;
147         return 0;
148 }
149
150 /* xfs_bstat_t has differing alignment on intel, & bstime_t sizes everywhere */
151 STATIC int
152 xfs_ioctl32_bstat_copyin(
153         xfs_bstat_t             *bstat,
154         compat_xfs_bstat_t      __user *bstat32)
155 {
156         if (get_user(bstat->bs_ino,     &bstat32->bs_ino)       ||
157             get_user(bstat->bs_mode,    &bstat32->bs_mode)      ||
158             get_user(bstat->bs_nlink,   &bstat32->bs_nlink)     ||
159             get_user(bstat->bs_uid,     &bstat32->bs_uid)       ||
160             get_user(bstat->bs_gid,     &bstat32->bs_gid)       ||
161             get_user(bstat->bs_rdev,    &bstat32->bs_rdev)      ||
162             get_user(bstat->bs_blksize, &bstat32->bs_blksize)   ||
163             get_user(bstat->bs_size,    &bstat32->bs_size)      ||
164             xfs_ioctl32_bstime_copyin(&bstat->bs_atime, &bstat32->bs_atime) ||
165             xfs_ioctl32_bstime_copyin(&bstat->bs_mtime, &bstat32->bs_mtime) ||
166             xfs_ioctl32_bstime_copyin(&bstat->bs_ctime, &bstat32->bs_ctime) ||
167             get_user(bstat->bs_blocks,  &bstat32->bs_size)      ||
168             get_user(bstat->bs_xflags,  &bstat32->bs_size)      ||
169             get_user(bstat->bs_extsize, &bstat32->bs_extsize)   ||
170             get_user(bstat->bs_extents, &bstat32->bs_extents)   ||
171             get_user(bstat->bs_gen,     &bstat32->bs_gen)       ||
172             get_user(bstat->bs_projid,  &bstat32->bs_projid)    ||
173             get_user(bstat->bs_dmevmask, &bstat32->bs_dmevmask) ||
174             get_user(bstat->bs_dmstate, &bstat32->bs_dmstate)   ||
175             get_user(bstat->bs_aextents, &bstat32->bs_aextents))
176                 return -XFS_ERROR(EFAULT);
177         return 0;
178 }
179
180 /* XFS_IOC_FSBULKSTAT and friends */
181
182 STATIC int
183 xfs_bstime_store_compat(
184         compat_xfs_bstime_t     __user *p32,
185         const xfs_bstime_t      *p)
186 {
187         __s32                   sec32;
188
189         sec32 = p->tv_sec;
190         if (put_user(sec32, &p32->tv_sec) ||
191             put_user(p->tv_nsec, &p32->tv_nsec))
192                 return -XFS_ERROR(EFAULT);
193         return 0;
194 }
195
196 /* Return 0 on success or positive error (to xfs_bulkstat()) */
197 STATIC int
198 xfs_bulkstat_one_fmt_compat(
199         void                    __user *ubuffer,
200         int                     ubsize,
201         int                     *ubused,
202         const xfs_bstat_t       *buffer)
203 {
204         compat_xfs_bstat_t      __user *p32 = ubuffer;
205
206         if (ubsize < sizeof(*p32))
207                 return XFS_ERROR(ENOMEM);
208
209         if (put_user(buffer->bs_ino,      &p32->bs_ino)         ||
210             put_user(buffer->bs_mode,     &p32->bs_mode)        ||
211             put_user(buffer->bs_nlink,    &p32->bs_nlink)       ||
212             put_user(buffer->bs_uid,      &p32->bs_uid)         ||
213             put_user(buffer->bs_gid,      &p32->bs_gid)         ||
214             put_user(buffer->bs_rdev,     &p32->bs_rdev)        ||
215             put_user(buffer->bs_blksize,  &p32->bs_blksize)     ||
216             put_user(buffer->bs_size,     &p32->bs_size)        ||
217             xfs_bstime_store_compat(&p32->bs_atime, &buffer->bs_atime) ||
218             xfs_bstime_store_compat(&p32->bs_mtime, &buffer->bs_mtime) ||
219             xfs_bstime_store_compat(&p32->bs_ctime, &buffer->bs_ctime) ||
220             put_user(buffer->bs_blocks,   &p32->bs_blocks)      ||
221             put_user(buffer->bs_xflags,   &p32->bs_xflags)      ||
222             put_user(buffer->bs_extsize,  &p32->bs_extsize)     ||
223             put_user(buffer->bs_extents,  &p32->bs_extents)     ||
224             put_user(buffer->bs_gen,      &p32->bs_gen)         ||
225             put_user(buffer->bs_projid,   &p32->bs_projid)      ||
226             put_user(buffer->bs_dmevmask, &p32->bs_dmevmask)    ||
227             put_user(buffer->bs_dmstate,  &p32->bs_dmstate)     ||
228             put_user(buffer->bs_aextents, &p32->bs_aextents))
229                 return XFS_ERROR(EFAULT);
230         if (ubused)
231                 *ubused = sizeof(*p32);
232         return 0;
233 }
234
235 STATIC int
236 xfs_bulkstat_one_compat(
237         xfs_mount_t     *mp,            /* mount point for filesystem */
238         xfs_ino_t       ino,            /* inode number to get data for */
239         void            __user *buffer, /* buffer to place output in */
240         int             ubsize,         /* size of buffer */
241         void            *private_data,  /* my private data */
242         xfs_daddr_t     bno,            /* starting bno of inode cluster */
243         int             *ubused,        /* bytes used by me */
244         void            *dibuff,        /* on-disk inode buffer */
245         int             *stat)          /* BULKSTAT_RV_... */
246 {
247         return xfs_bulkstat_one_int(mp, ino, buffer, ubsize,
248                                     xfs_bulkstat_one_fmt_compat, bno,
249                                     ubused, dibuff, stat);
250 }
251
252 /* copied from xfs_ioctl.c */
253 STATIC int
254 xfs_compat_ioc_bulkstat(
255         xfs_mount_t               *mp,
256         unsigned int              cmd,
257         compat_xfs_fsop_bulkreq_t __user *p32)
258 {
259         u32                     addr;
260         xfs_fsop_bulkreq_t      bulkreq;
261         int                     count;  /* # of records returned */
262         xfs_ino_t               inlast; /* last inode number */
263         int                     done;
264         int                     error;
265
266         /* done = 1 if there are more stats to get and if bulkstat */
267         /* should be called again (unused here, but used in dmapi) */
268
269         if (!capable(CAP_SYS_ADMIN))
270                 return -XFS_ERROR(EPERM);
271
272         if (XFS_FORCED_SHUTDOWN(mp))
273                 return -XFS_ERROR(EIO);
274
275         if (get_user(addr, &p32->lastip))
276                 return -XFS_ERROR(EFAULT);
277         bulkreq.lastip = compat_ptr(addr);
278         if (get_user(bulkreq.icount, &p32->icount) ||
279             get_user(addr, &p32->ubuffer))
280                 return -XFS_ERROR(EFAULT);
281         bulkreq.ubuffer = compat_ptr(addr);
282         if (get_user(addr, &p32->ocount))
283                 return -XFS_ERROR(EFAULT);
284         bulkreq.ocount = compat_ptr(addr);
285
286         if (copy_from_user(&inlast, bulkreq.lastip, sizeof(__s64)))
287                 return -XFS_ERROR(EFAULT);
288
289         if ((count = bulkreq.icount) <= 0)
290                 return -XFS_ERROR(EINVAL);
291
292         if (bulkreq.ubuffer == NULL)
293                 return -XFS_ERROR(EINVAL);
294
295         if (cmd == XFS_IOC_FSINUMBERS_32) {
296                 error = xfs_inumbers(mp, &inlast, &count,
297                                 bulkreq.ubuffer, xfs_inumbers_fmt_compat);
298         } else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE_32) {
299                 int res;
300
301                 error = xfs_bulkstat_one_compat(mp, inlast, bulkreq.ubuffer,
302                                 sizeof(compat_xfs_bstat_t),
303                                 NULL, 0, NULL, NULL, &res);
304         } else if (cmd == XFS_IOC_FSBULKSTAT_32) {
305                 error = xfs_bulkstat(mp, &inlast, &count,
306                         xfs_bulkstat_one_compat, NULL,
307                         sizeof(compat_xfs_bstat_t), bulkreq.ubuffer,
308                         BULKSTAT_FG_QUICK, &done);
309         } else
310                 error = XFS_ERROR(EINVAL);
311         if (error)
312                 return -error;
313
314         if (bulkreq.ocount != NULL) {
315                 if (copy_to_user(bulkreq.lastip, &inlast,
316                                                 sizeof(xfs_ino_t)))
317                         return -XFS_ERROR(EFAULT);
318
319                 if (copy_to_user(bulkreq.ocount, &count, sizeof(count)))
320                         return -XFS_ERROR(EFAULT);
321         }
322
323         return 0;
324 }
325
326 STATIC int
327 xfs_compat_handlereq_copyin(
328         xfs_fsop_handlereq_t            *hreq,
329         compat_xfs_fsop_handlereq_t     __user *arg32)
330 {
331         compat_xfs_fsop_handlereq_t     hreq32;
332
333         if (copy_from_user(&hreq32, arg32, sizeof(compat_xfs_fsop_handlereq_t)))
334                 return -XFS_ERROR(EFAULT);
335
336         hreq->fd = hreq32.fd;
337         hreq->path = compat_ptr(hreq32.path);
338         hreq->oflags = hreq32.oflags;
339         hreq->ihandle = compat_ptr(hreq32.ihandle);
340         hreq->ihandlen = hreq32.ihandlen;
341         hreq->ohandle = compat_ptr(hreq32.ohandle);
342         hreq->ohandlen = compat_ptr(hreq32.ohandlen);
343
344         return 0;
345 }
346
347 /*
348  * Convert userspace handle data into inode.
349  *
350  * We use the fact that all the fsop_handlereq ioctl calls have a data
351  * structure argument whose first component is always a xfs_fsop_handlereq_t,
352  * so we can pass that sub structure into this handy, shared routine.
353  *
354  * If no error, caller must always iput the returned inode.
355  */
356 STATIC int
357 xfs_vget_fsop_handlereq_compat(
358         xfs_mount_t             *mp,
359         struct inode            *parinode,      /* parent inode pointer    */
360         compat_xfs_fsop_handlereq_t     *hreq,
361         struct inode            **inode)
362 {
363         void                    __user *hanp;
364         size_t                  hlen;
365         xfs_fid_t               *xfid;
366         xfs_handle_t            *handlep;
367         xfs_handle_t            handle;
368         xfs_inode_t             *ip;
369         xfs_ino_t               ino;
370         __u32                   igen;
371         int                     error;
372
373         /*
374          * Only allow handle opens under a directory.
375          */
376         if (!S_ISDIR(parinode->i_mode))
377                 return XFS_ERROR(ENOTDIR);
378
379         hanp = compat_ptr(hreq->ihandle);
380         hlen = hreq->ihandlen;
381         handlep = &handle;
382
383         if (hlen < sizeof(handlep->ha_fsid) || hlen > sizeof(*handlep))
384                 return XFS_ERROR(EINVAL);
385         if (copy_from_user(handlep, hanp, hlen))
386                 return XFS_ERROR(EFAULT);
387         if (hlen < sizeof(*handlep))
388                 memset(((char *)handlep) + hlen, 0, sizeof(*handlep) - hlen);
389         if (hlen > sizeof(handlep->ha_fsid)) {
390                 if (handlep->ha_fid.fid_len !=
391                     (hlen - sizeof(handlep->ha_fsid) -
392                             sizeof(handlep->ha_fid.fid_len)) ||
393                     handlep->ha_fid.fid_pad)
394                         return XFS_ERROR(EINVAL);
395         }
396
397         /*
398          * Crack the handle, obtain the inode # & generation #
399          */
400         xfid = (struct xfs_fid *)&handlep->ha_fid;
401         if (xfid->fid_len == sizeof(*xfid) - sizeof(xfid->fid_len)) {
402                 ino  = xfid->fid_ino;
403                 igen = xfid->fid_gen;
404         } else {
405                 return XFS_ERROR(EINVAL);
406         }
407
408         /*
409          * Get the XFS inode, building a Linux inode to go with it.
410          */
411         error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_SHARED, &ip, 0);
412         if (error)
413                 return error;
414         if (ip == NULL)
415                 return XFS_ERROR(EIO);
416         if (ip->i_d.di_gen != igen) {
417                 xfs_iput_new(ip, XFS_ILOCK_SHARED);
418                 return XFS_ERROR(ENOENT);
419         }
420
421         xfs_iunlock(ip, XFS_ILOCK_SHARED);
422
423         *inode = VFS_I(ip);
424         return 0;
425 }
426
427 STATIC int
428 xfs_compat_attrlist_by_handle(
429         xfs_mount_t             *mp,
430         void                    __user *arg,
431         struct inode            *parinode)
432 {
433         int                     error;
434         attrlist_cursor_kern_t  *cursor;
435         compat_xfs_fsop_attrlist_handlereq_t al_hreq;
436         struct inode            *inode;
437         char                    *kbuf;
438
439         if (!capable(CAP_SYS_ADMIN))
440                 return -XFS_ERROR(EPERM);
441         if (copy_from_user(&al_hreq, arg,
442                            sizeof(compat_xfs_fsop_attrlist_handlereq_t)))
443                 return -XFS_ERROR(EFAULT);
444         if (al_hreq.buflen > XATTR_LIST_MAX)
445                 return -XFS_ERROR(EINVAL);
446
447         /*
448          * Reject flags, only allow namespaces.
449          */
450         if (al_hreq.flags & ~(ATTR_ROOT | ATTR_SECURE))
451                 return -XFS_ERROR(EINVAL);
452
453         error = xfs_vget_fsop_handlereq_compat(mp, parinode, &al_hreq.hreq,
454                                                &inode);
455         if (error)
456                 goto out;
457
458         kbuf = kmalloc(al_hreq.buflen, GFP_KERNEL);
459         if (!kbuf)
460                 goto out_vn_rele;
461
462         cursor = (attrlist_cursor_kern_t *)&al_hreq.pos;
463         error = xfs_attr_list(XFS_I(inode), kbuf, al_hreq.buflen,
464                                         al_hreq.flags, cursor);
465         if (error)
466                 goto out_kfree;
467
468         if (copy_to_user(compat_ptr(al_hreq.buffer), kbuf, al_hreq.buflen))
469                 error = -EFAULT;
470
471  out_kfree:
472         kfree(kbuf);
473  out_vn_rele:
474         iput(inode);
475  out:
476         return -error;
477 }
478
479 STATIC long
480 xfs_compat_ioctl(
481         xfs_inode_t     *ip,
482         struct file     *filp,
483         int             ioflags,
484         unsigned        cmd,
485         void            __user *arg)
486 {
487         struct inode    *inode = filp->f_path.dentry->d_inode;
488         xfs_mount_t     *mp = ip->i_mount;
489         int             error;
490
491         xfs_itrace_entry(XFS_I(inode));
492         switch (cmd) {
493         case XFS_IOC_DIOINFO:
494         case XFS_IOC_FSGEOMETRY:
495         case XFS_IOC_FSGETXATTR:
496         case XFS_IOC_FSSETXATTR:
497         case XFS_IOC_FSGETXATTRA:
498         case XFS_IOC_FSSETDM:
499         case XFS_IOC_GETBMAP:
500         case XFS_IOC_GETBMAPA:
501         case XFS_IOC_GETBMAPX:
502 /* not handled
503         case XFS_IOC_FSSETDM_BY_HANDLE:
504         case XFS_IOC_ATTRMULTI_BY_HANDLE:
505 */
506         case XFS_IOC_FSCOUNTS:
507         case XFS_IOC_SET_RESBLKS:
508         case XFS_IOC_GET_RESBLKS:
509         case XFS_IOC_FSGROWFSDATA:
510         case XFS_IOC_FSGROWFSLOG:
511         case XFS_IOC_FSGROWFSRT:
512         case XFS_IOC_FREEZE:
513         case XFS_IOC_THAW:
514         case XFS_IOC_GOINGDOWN:
515         case XFS_IOC_ERROR_INJECTION:
516         case XFS_IOC_ERROR_CLEARALL:
517                 break;
518
519         case XFS_IOC_GETXFLAGS_32:
520         case XFS_IOC_SETXFLAGS_32:
521         case XFS_IOC_GETVERSION_32:
522                 cmd = _NATIVE_IOC(cmd, long);
523                 break;
524         case XFS_IOC_SWAPEXT: {
525                 struct xfs_swapext        sxp;
526                 struct compat_xfs_swapext __user *sxu = arg;
527
528                 /* Bulk copy in up to the sx_stat field, then grab bstat */
529                 if (copy_from_user(&sxp, sxu,
530                                    offsetof(xfs_swapext_t, sx_stat)) ||
531                     xfs_ioctl32_bstat_copyin(&sxp.sx_stat, &sxu->sx_stat))
532                         return -XFS_ERROR(EFAULT);
533                 error = xfs_swapext(&sxp);
534                 return -error;
535         }
536 #ifdef BROKEN_X86_ALIGNMENT
537         /* xfs_flock_t has wrong u32 vs u64 alignment */
538         case XFS_IOC_ALLOCSP_32:
539         case XFS_IOC_FREESP_32:
540         case XFS_IOC_ALLOCSP64_32:
541         case XFS_IOC_FREESP64_32:
542         case XFS_IOC_RESVSP_32:
543         case XFS_IOC_UNRESVSP_32:
544         case XFS_IOC_RESVSP64_32:
545         case XFS_IOC_UNRESVSP64_32: {
546                 struct xfs_flock64      bf;
547
548                 if (xfs_compat_flock64_copyin(&bf, arg))
549                         return -XFS_ERROR(EFAULT);
550                 cmd = _NATIVE_IOC(cmd, struct xfs_flock64);
551                 return xfs_ioc_space(ip, inode, filp, ioflags, cmd, &bf);
552         }
553         case XFS_IOC_FSGEOMETRY_V1_32:
554                 return xfs_compat_ioc_fsgeometry_v1(mp, arg);
555         case XFS_IOC_FSGROWFSDATA_32: {
556                 struct xfs_growfs_data  in;
557
558                 if (xfs_compat_growfs_data_copyin(&in, arg))
559                         return -XFS_ERROR(EFAULT);
560                 error = xfs_growfs_data(mp, &in);
561                 return -error;
562         }
563         case XFS_IOC_FSGROWFSRT_32: {
564                 struct xfs_growfs_rt    in;
565
566                 if (xfs_compat_growfs_rt_copyin(&in, arg))
567                         return -XFS_ERROR(EFAULT);
568                 error = xfs_growfs_rt(mp, &in);
569                 return -error;
570         }
571 #else /* These are handled fine if no alignment issues */
572         case XFS_IOC_ALLOCSP:
573         case XFS_IOC_FREESP:
574         case XFS_IOC_RESVSP:
575         case XFS_IOC_UNRESVSP:
576         case XFS_IOC_ALLOCSP64:
577         case XFS_IOC_FREESP64:
578         case XFS_IOC_RESVSP64:
579         case XFS_IOC_UNRESVSP64:
580         case XFS_IOC_FSGEOMETRY_V1:
581                 break;
582 #endif
583         case XFS_IOC_FSBULKSTAT_32:
584         case XFS_IOC_FSBULKSTAT_SINGLE_32:
585         case XFS_IOC_FSINUMBERS_32:
586                 return xfs_compat_ioc_bulkstat(mp, cmd, arg);
587         case XFS_IOC_FD_TO_HANDLE_32:
588         case XFS_IOC_PATH_TO_HANDLE_32:
589         case XFS_IOC_PATH_TO_FSHANDLE_32: {
590                 struct xfs_fsop_handlereq       hreq;
591
592                 if (xfs_compat_handlereq_copyin(&hreq, arg))
593                         return -XFS_ERROR(EFAULT);
594                 cmd = _NATIVE_IOC(cmd, struct xfs_fsop_handlereq);
595                 return xfs_find_handle(cmd, &hreq);
596         }
597         case XFS_IOC_OPEN_BY_HANDLE_32: {
598                 struct xfs_fsop_handlereq       hreq;
599
600                 if (xfs_compat_handlereq_copyin(&hreq, arg))
601                         return -XFS_ERROR(EFAULT);
602                 return xfs_open_by_handle(mp, &hreq, filp, inode);
603         }
604         case XFS_IOC_READLINK_BY_HANDLE_32: {
605                 struct xfs_fsop_handlereq       hreq;
606
607                 if (xfs_compat_handlereq_copyin(&hreq, arg))
608                         return -XFS_ERROR(EFAULT);
609                 return xfs_readlink_by_handle(mp, &hreq, inode);
610         }
611         case XFS_IOC_ATTRLIST_BY_HANDLE_32:
612                 return xfs_compat_attrlist_by_handle(mp, arg, inode);
613         default:
614                 return -XFS_ERROR(ENOIOCTLCMD);
615         }
616
617         error = xfs_ioctl(ip, filp, ioflags, cmd, arg);
618         return error;
619 }
620
621 long
622 xfs_file_compat_ioctl(
623         struct file             *filp,
624         unsigned int            cmd,
625         unsigned long           p)
626 {
627         struct inode    *inode = filp->f_path.dentry->d_inode;
628
629         return xfs_compat_ioctl(XFS_I(inode), filp, 0, cmd, (void __user *)p);
630 }
631
632 long
633 xfs_file_compat_invis_ioctl(
634         struct file             *filp,
635         unsigned int            cmd,
636         unsigned long           p)
637 {
638         struct inode    *inode = filp->f_path.dentry->d_inode;
639
640         return xfs_compat_ioctl(XFS_I(inode), filp, IO_INVIS, cmd,
641                                 (void __user *)p);
642 }