diff options
Diffstat (limited to 'fs/xfs/linux-2.6/xfs_ioctl32.c')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_ioctl32.c | 849 |
1 files changed, 553 insertions, 296 deletions
diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.c b/fs/xfs/linux-2.6/xfs_ioctl32.c index a4b254eb43b2..0504cece9f66 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl32.c +++ b/fs/xfs/linux-2.6/xfs_ioctl32.c | |||
@@ -16,11 +16,7 @@ | |||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
17 | */ | 17 | */ |
18 | #include <linux/compat.h> | 18 | #include <linux/compat.h> |
19 | #include <linux/init.h> | ||
20 | #include <linux/ioctl.h> | 19 | #include <linux/ioctl.h> |
21 | #include <linux/syscalls.h> | ||
22 | #include <linux/types.h> | ||
23 | #include <linux/fs.h> | ||
24 | #include <asm/uaccess.h> | 20 | #include <asm/uaccess.h> |
25 | #include "xfs.h" | 21 | #include "xfs.h" |
26 | #include "xfs_fs.h" | 22 | #include "xfs_fs.h" |
@@ -36,7 +32,6 @@ | |||
36 | #include "xfs_bmap_btree.h" | 32 | #include "xfs_bmap_btree.h" |
37 | #include "xfs_attr_sf.h" | 33 | #include "xfs_attr_sf.h" |
38 | #include "xfs_dir2_sf.h" | 34 | #include "xfs_dir2_sf.h" |
39 | #include "xfs_vfs.h" | ||
40 | #include "xfs_vnode.h" | 35 | #include "xfs_vnode.h" |
41 | #include "xfs_dinode.h" | 36 | #include "xfs_dinode.h" |
42 | #include "xfs_inode.h" | 37 | #include "xfs_inode.h" |
@@ -44,221 +39,219 @@ | |||
44 | #include "xfs_error.h" | 39 | #include "xfs_error.h" |
45 | #include "xfs_dfrag.h" | 40 | #include "xfs_dfrag.h" |
46 | #include "xfs_vnodeops.h" | 41 | #include "xfs_vnodeops.h" |
42 | #include "xfs_fsops.h" | ||
43 | #include "xfs_alloc.h" | ||
44 | #include "xfs_rtalloc.h" | ||
45 | #include "xfs_attr.h" | ||
46 | #include "xfs_ioctl.h" | ||
47 | #include "xfs_ioctl32.h" | 47 | #include "xfs_ioctl32.h" |
48 | 48 | ||
49 | #define _NATIVE_IOC(cmd, type) \ | 49 | #define _NATIVE_IOC(cmd, type) \ |
50 | _IOC(_IOC_DIR(cmd), _IOC_TYPE(cmd), _IOC_NR(cmd), sizeof(type)) | 50 | _IOC(_IOC_DIR(cmd), _IOC_TYPE(cmd), _IOC_NR(cmd), sizeof(type)) |
51 | 51 | ||
52 | #if defined(CONFIG_IA64) || defined(CONFIG_X86_64) | 52 | #ifdef BROKEN_X86_ALIGNMENT |
53 | #define BROKEN_X86_ALIGNMENT | 53 | STATIC int |
54 | #define _PACKED __attribute__((packed)) | 54 | xfs_compat_flock64_copyin( |
55 | /* on ia32 l_start is on a 32-bit boundary */ | 55 | xfs_flock64_t *bf, |
56 | typedef struct xfs_flock64_32 { | 56 | compat_xfs_flock64_t __user *arg32) |
57 | __s16 l_type; | ||
58 | __s16 l_whence; | ||
59 | __s64 l_start __attribute__((packed)); | ||
60 | /* len == 0 means until end of file */ | ||
61 | __s64 l_len __attribute__((packed)); | ||
62 | __s32 l_sysid; | ||
63 | __u32 l_pid; | ||
64 | __s32 l_pad[4]; /* reserve area */ | ||
65 | } xfs_flock64_32_t; | ||
66 | |||
67 | #define XFS_IOC_ALLOCSP_32 _IOW ('X', 10, struct xfs_flock64_32) | ||
68 | #define XFS_IOC_FREESP_32 _IOW ('X', 11, struct xfs_flock64_32) | ||
69 | #define XFS_IOC_ALLOCSP64_32 _IOW ('X', 36, struct xfs_flock64_32) | ||
70 | #define XFS_IOC_FREESP64_32 _IOW ('X', 37, struct xfs_flock64_32) | ||
71 | #define XFS_IOC_RESVSP_32 _IOW ('X', 40, struct xfs_flock64_32) | ||
72 | #define XFS_IOC_UNRESVSP_32 _IOW ('X', 41, struct xfs_flock64_32) | ||
73 | #define XFS_IOC_RESVSP64_32 _IOW ('X', 42, struct xfs_flock64_32) | ||
74 | #define XFS_IOC_UNRESVSP64_32 _IOW ('X', 43, struct xfs_flock64_32) | ||
75 | |||
76 | /* just account for different alignment */ | ||
77 | STATIC unsigned long | ||
78 | xfs_ioctl32_flock( | ||
79 | unsigned long arg) | ||
80 | { | 57 | { |
81 | xfs_flock64_32_t __user *p32 = (void __user *)arg; | 58 | if (get_user(bf->l_type, &arg32->l_type) || |
82 | xfs_flock64_t __user *p = compat_alloc_user_space(sizeof(*p)); | 59 | get_user(bf->l_whence, &arg32->l_whence) || |
83 | 60 | get_user(bf->l_start, &arg32->l_start) || | |
84 | if (copy_in_user(&p->l_type, &p32->l_type, sizeof(s16)) || | 61 | get_user(bf->l_len, &arg32->l_len) || |
85 | copy_in_user(&p->l_whence, &p32->l_whence, sizeof(s16)) || | 62 | get_user(bf->l_sysid, &arg32->l_sysid) || |
86 | copy_in_user(&p->l_start, &p32->l_start, sizeof(s64)) || | 63 | get_user(bf->l_pid, &arg32->l_pid) || |
87 | copy_in_user(&p->l_len, &p32->l_len, sizeof(s64)) || | 64 | copy_from_user(bf->l_pad, &arg32->l_pad, 4*sizeof(u32))) |
88 | copy_in_user(&p->l_sysid, &p32->l_sysid, sizeof(s32)) || | 65 | return -XFS_ERROR(EFAULT); |
89 | copy_in_user(&p->l_pid, &p32->l_pid, sizeof(u32)) || | 66 | return 0; |
90 | copy_in_user(&p->l_pad, &p32->l_pad, 4*sizeof(u32))) | ||
91 | return -EFAULT; | ||
92 | |||
93 | return (unsigned long)p; | ||
94 | } | 67 | } |
95 | 68 | ||
96 | typedef struct compat_xfs_fsop_geom_v1 { | 69 | STATIC int |
97 | __u32 blocksize; /* filesystem (data) block size */ | 70 | xfs_compat_ioc_fsgeometry_v1( |
98 | __u32 rtextsize; /* realtime extent size */ | 71 | struct xfs_mount *mp, |
99 | __u32 agblocks; /* fsblocks in an AG */ | 72 | compat_xfs_fsop_geom_v1_t __user *arg32) |
100 | __u32 agcount; /* number of allocation groups */ | ||
101 | __u32 logblocks; /* fsblocks in the log */ | ||
102 | __u32 sectsize; /* (data) sector size, bytes */ | ||
103 | __u32 inodesize; /* inode size in bytes */ | ||
104 | __u32 imaxpct; /* max allowed inode space(%) */ | ||
105 | __u64 datablocks; /* fsblocks in data subvolume */ | ||
106 | __u64 rtblocks; /* fsblocks in realtime subvol */ | ||
107 | __u64 rtextents; /* rt extents in realtime subvol*/ | ||
108 | __u64 logstart; /* starting fsblock of the log */ | ||
109 | unsigned char uuid[16]; /* unique id of the filesystem */ | ||
110 | __u32 sunit; /* stripe unit, fsblocks */ | ||
111 | __u32 swidth; /* stripe width, fsblocks */ | ||
112 | __s32 version; /* structure version */ | ||
113 | __u32 flags; /* superblock version flags */ | ||
114 | __u32 logsectsize; /* log sector size, bytes */ | ||
115 | __u32 rtsectsize; /* realtime sector size, bytes */ | ||
116 | __u32 dirblocksize; /* directory block size, bytes */ | ||
117 | } __attribute__((packed)) compat_xfs_fsop_geom_v1_t; | ||
118 | |||
119 | #define XFS_IOC_FSGEOMETRY_V1_32 \ | ||
120 | _IOR ('X', 100, struct compat_xfs_fsop_geom_v1) | ||
121 | |||
122 | STATIC unsigned long xfs_ioctl32_geom_v1(unsigned long arg) | ||
123 | { | 73 | { |
124 | compat_xfs_fsop_geom_v1_t __user *p32 = (void __user *)arg; | 74 | xfs_fsop_geom_t fsgeo; |
125 | xfs_fsop_geom_v1_t __user *p = compat_alloc_user_space(sizeof(*p)); | 75 | int error; |
126 | 76 | ||
127 | if (copy_in_user(p, p32, sizeof(*p32))) | 77 | error = xfs_fs_geometry(mp, &fsgeo, 3); |
128 | return -EFAULT; | 78 | if (error) |
129 | return (unsigned long)p; | 79 | return -error; |
80 | /* The 32-bit variant simply has some padding at the end */ | ||
81 | if (copy_to_user(arg32, &fsgeo, sizeof(struct compat_xfs_fsop_geom_v1))) | ||
82 | return -XFS_ERROR(EFAULT); | ||
83 | return 0; | ||
130 | } | 84 | } |
131 | 85 | ||
132 | typedef struct compat_xfs_inogrp { | 86 | STATIC int |
133 | __u64 xi_startino; /* starting inode number */ | 87 | xfs_compat_growfs_data_copyin( |
134 | __s32 xi_alloccount; /* # bits set in allocmask */ | 88 | struct xfs_growfs_data *in, |
135 | __u64 xi_allocmask; /* mask of allocated inodes */ | 89 | compat_xfs_growfs_data_t __user *arg32) |
136 | } __attribute__((packed)) compat_xfs_inogrp_t; | ||
137 | |||
138 | STATIC int xfs_inumbers_fmt_compat( | ||
139 | void __user *ubuffer, | ||
140 | const xfs_inogrp_t *buffer, | ||
141 | long count, | ||
142 | long *written) | ||
143 | { | 90 | { |
144 | compat_xfs_inogrp_t __user *p32 = ubuffer; | 91 | if (get_user(in->newblocks, &arg32->newblocks) || |
145 | long i; | 92 | get_user(in->imaxpct, &arg32->imaxpct)) |
93 | return -XFS_ERROR(EFAULT); | ||
94 | return 0; | ||
95 | } | ||
96 | |||
97 | STATIC int | ||
98 | xfs_compat_growfs_rt_copyin( | ||
99 | struct xfs_growfs_rt *in, | ||
100 | compat_xfs_growfs_rt_t __user *arg32) | ||
101 | { | ||
102 | if (get_user(in->newblocks, &arg32->newblocks) || | ||
103 | get_user(in->extsize, &arg32->extsize)) | ||
104 | return -XFS_ERROR(EFAULT); | ||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | STATIC int | ||
109 | xfs_inumbers_fmt_compat( | ||
110 | void __user *ubuffer, | ||
111 | const xfs_inogrp_t *buffer, | ||
112 | long count, | ||
113 | long *written) | ||
114 | { | ||
115 | compat_xfs_inogrp_t __user *p32 = ubuffer; | ||
116 | long i; | ||
146 | 117 | ||
147 | for (i = 0; i < count; i++) { | 118 | for (i = 0; i < count; i++) { |
148 | if (put_user(buffer[i].xi_startino, &p32[i].xi_startino) || | 119 | if (put_user(buffer[i].xi_startino, &p32[i].xi_startino) || |
149 | put_user(buffer[i].xi_alloccount, &p32[i].xi_alloccount) || | 120 | put_user(buffer[i].xi_alloccount, &p32[i].xi_alloccount) || |
150 | put_user(buffer[i].xi_allocmask, &p32[i].xi_allocmask)) | 121 | put_user(buffer[i].xi_allocmask, &p32[i].xi_allocmask)) |
151 | return -EFAULT; | 122 | return -XFS_ERROR(EFAULT); |
152 | } | 123 | } |
153 | *written = count * sizeof(*p32); | 124 | *written = count * sizeof(*p32); |
154 | return 0; | 125 | return 0; |
155 | } | 126 | } |
156 | 127 | ||
157 | #else | 128 | #else |
158 | |||
159 | #define xfs_inumbers_fmt_compat xfs_inumbers_fmt | 129 | #define xfs_inumbers_fmt_compat xfs_inumbers_fmt |
160 | #define _PACKED | 130 | #endif /* BROKEN_X86_ALIGNMENT */ |
161 | 131 | ||
162 | #endif | 132 | STATIC int |
133 | xfs_ioctl32_bstime_copyin( | ||
134 | xfs_bstime_t *bstime, | ||
135 | compat_xfs_bstime_t __user *bstime32) | ||
136 | { | ||
137 | compat_time_t sec32; /* tv_sec differs on 64 vs. 32 */ | ||
163 | 138 | ||
164 | /* XFS_IOC_FSBULKSTAT and friends */ | 139 | if (get_user(sec32, &bstime32->tv_sec) || |
140 | get_user(bstime->tv_nsec, &bstime32->tv_nsec)) | ||
141 | return -XFS_ERROR(EFAULT); | ||
142 | bstime->tv_sec = sec32; | ||
143 | return 0; | ||
144 | } | ||
145 | |||
146 | /* xfs_bstat_t has differing alignment on intel, & bstime_t sizes everywhere */ | ||
147 | STATIC int | ||
148 | xfs_ioctl32_bstat_copyin( | ||
149 | xfs_bstat_t *bstat, | ||
150 | compat_xfs_bstat_t __user *bstat32) | ||
151 | { | ||
152 | if (get_user(bstat->bs_ino, &bstat32->bs_ino) || | ||
153 | get_user(bstat->bs_mode, &bstat32->bs_mode) || | ||
154 | get_user(bstat->bs_nlink, &bstat32->bs_nlink) || | ||
155 | get_user(bstat->bs_uid, &bstat32->bs_uid) || | ||
156 | get_user(bstat->bs_gid, &bstat32->bs_gid) || | ||
157 | get_user(bstat->bs_rdev, &bstat32->bs_rdev) || | ||
158 | get_user(bstat->bs_blksize, &bstat32->bs_blksize) || | ||
159 | get_user(bstat->bs_size, &bstat32->bs_size) || | ||
160 | xfs_ioctl32_bstime_copyin(&bstat->bs_atime, &bstat32->bs_atime) || | ||
161 | xfs_ioctl32_bstime_copyin(&bstat->bs_mtime, &bstat32->bs_mtime) || | ||
162 | xfs_ioctl32_bstime_copyin(&bstat->bs_ctime, &bstat32->bs_ctime) || | ||
163 | get_user(bstat->bs_blocks, &bstat32->bs_size) || | ||
164 | get_user(bstat->bs_xflags, &bstat32->bs_size) || | ||
165 | get_user(bstat->bs_extsize, &bstat32->bs_extsize) || | ||
166 | get_user(bstat->bs_extents, &bstat32->bs_extents) || | ||
167 | get_user(bstat->bs_gen, &bstat32->bs_gen) || | ||
168 | get_user(bstat->bs_projid, &bstat32->bs_projid) || | ||
169 | get_user(bstat->bs_dmevmask, &bstat32->bs_dmevmask) || | ||
170 | get_user(bstat->bs_dmstate, &bstat32->bs_dmstate) || | ||
171 | get_user(bstat->bs_aextents, &bstat32->bs_aextents)) | ||
172 | return -XFS_ERROR(EFAULT); | ||
173 | return 0; | ||
174 | } | ||
165 | 175 | ||
166 | typedef struct compat_xfs_bstime { | 176 | /* XFS_IOC_FSBULKSTAT and friends */ |
167 | __s32 tv_sec; /* seconds */ | ||
168 | __s32 tv_nsec; /* and nanoseconds */ | ||
169 | } compat_xfs_bstime_t; | ||
170 | 177 | ||
171 | STATIC int xfs_bstime_store_compat( | 178 | STATIC int |
172 | compat_xfs_bstime_t __user *p32, | 179 | xfs_bstime_store_compat( |
173 | const xfs_bstime_t *p) | 180 | compat_xfs_bstime_t __user *p32, |
181 | const xfs_bstime_t *p) | ||
174 | { | 182 | { |
175 | __s32 sec32; | 183 | __s32 sec32; |
176 | 184 | ||
177 | sec32 = p->tv_sec; | 185 | sec32 = p->tv_sec; |
178 | if (put_user(sec32, &p32->tv_sec) || | 186 | if (put_user(sec32, &p32->tv_sec) || |
179 | put_user(p->tv_nsec, &p32->tv_nsec)) | 187 | put_user(p->tv_nsec, &p32->tv_nsec)) |
180 | return -EFAULT; | 188 | return -XFS_ERROR(EFAULT); |
181 | return 0; | 189 | return 0; |
182 | } | 190 | } |
183 | 191 | ||
184 | typedef struct compat_xfs_bstat { | 192 | /* Return 0 on success or positive error (to xfs_bulkstat()) */ |
185 | __u64 bs_ino; /* inode number */ | 193 | STATIC int |
186 | __u16 bs_mode; /* type and mode */ | 194 | xfs_bulkstat_one_fmt_compat( |
187 | __u16 bs_nlink; /* number of links */ | ||
188 | __u32 bs_uid; /* user id */ | ||
189 | __u32 bs_gid; /* group id */ | ||
190 | __u32 bs_rdev; /* device value */ | ||
191 | __s32 bs_blksize; /* block size */ | ||
192 | __s64 bs_size; /* file size */ | ||
193 | compat_xfs_bstime_t bs_atime; /* access time */ | ||
194 | compat_xfs_bstime_t bs_mtime; /* modify time */ | ||
195 | compat_xfs_bstime_t bs_ctime; /* inode change time */ | ||
196 | int64_t bs_blocks; /* number of blocks */ | ||
197 | __u32 bs_xflags; /* extended flags */ | ||
198 | __s32 bs_extsize; /* extent size */ | ||
199 | __s32 bs_extents; /* number of extents */ | ||
200 | __u32 bs_gen; /* generation count */ | ||
201 | __u16 bs_projid; /* project id */ | ||
202 | unsigned char bs_pad[14]; /* pad space, unused */ | ||
203 | __u32 bs_dmevmask; /* DMIG event mask */ | ||
204 | __u16 bs_dmstate; /* DMIG state info */ | ||
205 | __u16 bs_aextents; /* attribute number of extents */ | ||
206 | } _PACKED compat_xfs_bstat_t; | ||
207 | |||
208 | STATIC int xfs_bulkstat_one_fmt_compat( | ||
209 | void __user *ubuffer, | 195 | void __user *ubuffer, |
196 | int ubsize, | ||
197 | int *ubused, | ||
210 | const xfs_bstat_t *buffer) | 198 | const xfs_bstat_t *buffer) |
211 | { | 199 | { |
212 | compat_xfs_bstat_t __user *p32 = ubuffer; | 200 | compat_xfs_bstat_t __user *p32 = ubuffer; |
213 | 201 | ||
214 | if (put_user(buffer->bs_ino, &p32->bs_ino) || | 202 | if (ubsize < sizeof(*p32)) |
215 | put_user(buffer->bs_mode, &p32->bs_mode) || | 203 | return XFS_ERROR(ENOMEM); |
216 | put_user(buffer->bs_nlink, &p32->bs_nlink) || | 204 | |
217 | put_user(buffer->bs_uid, &p32->bs_uid) || | 205 | if (put_user(buffer->bs_ino, &p32->bs_ino) || |
218 | put_user(buffer->bs_gid, &p32->bs_gid) || | 206 | put_user(buffer->bs_mode, &p32->bs_mode) || |
219 | put_user(buffer->bs_rdev, &p32->bs_rdev) || | 207 | put_user(buffer->bs_nlink, &p32->bs_nlink) || |
220 | put_user(buffer->bs_blksize, &p32->bs_blksize) || | 208 | put_user(buffer->bs_uid, &p32->bs_uid) || |
221 | put_user(buffer->bs_size, &p32->bs_size) || | 209 | put_user(buffer->bs_gid, &p32->bs_gid) || |
210 | put_user(buffer->bs_rdev, &p32->bs_rdev) || | ||
211 | put_user(buffer->bs_blksize, &p32->bs_blksize) || | ||
212 | put_user(buffer->bs_size, &p32->bs_size) || | ||
222 | xfs_bstime_store_compat(&p32->bs_atime, &buffer->bs_atime) || | 213 | xfs_bstime_store_compat(&p32->bs_atime, &buffer->bs_atime) || |
223 | xfs_bstime_store_compat(&p32->bs_mtime, &buffer->bs_mtime) || | 214 | xfs_bstime_store_compat(&p32->bs_mtime, &buffer->bs_mtime) || |
224 | xfs_bstime_store_compat(&p32->bs_ctime, &buffer->bs_ctime) || | 215 | xfs_bstime_store_compat(&p32->bs_ctime, &buffer->bs_ctime) || |
225 | put_user(buffer->bs_blocks, &p32->bs_blocks) || | 216 | put_user(buffer->bs_blocks, &p32->bs_blocks) || |
226 | put_user(buffer->bs_xflags, &p32->bs_xflags) || | 217 | put_user(buffer->bs_xflags, &p32->bs_xflags) || |
227 | put_user(buffer->bs_extsize, &p32->bs_extsize) || | 218 | put_user(buffer->bs_extsize, &p32->bs_extsize) || |
228 | put_user(buffer->bs_extents, &p32->bs_extents) || | 219 | put_user(buffer->bs_extents, &p32->bs_extents) || |
229 | put_user(buffer->bs_gen, &p32->bs_gen) || | 220 | put_user(buffer->bs_gen, &p32->bs_gen) || |
230 | put_user(buffer->bs_projid, &p32->bs_projid) || | 221 | put_user(buffer->bs_projid, &p32->bs_projid) || |
231 | put_user(buffer->bs_dmevmask, &p32->bs_dmevmask) || | 222 | put_user(buffer->bs_dmevmask, &p32->bs_dmevmask) || |
232 | put_user(buffer->bs_dmstate, &p32->bs_dmstate) || | 223 | put_user(buffer->bs_dmstate, &p32->bs_dmstate) || |
233 | put_user(buffer->bs_aextents, &p32->bs_aextents)) | 224 | put_user(buffer->bs_aextents, &p32->bs_aextents)) |
234 | return -EFAULT; | 225 | return XFS_ERROR(EFAULT); |
235 | return sizeof(*p32); | 226 | if (ubused) |
227 | *ubused = sizeof(*p32); | ||
228 | return 0; | ||
236 | } | 229 | } |
237 | 230 | ||
238 | 231 | STATIC int | |
239 | 232 | xfs_bulkstat_one_compat( | |
240 | typedef struct compat_xfs_fsop_bulkreq { | 233 | xfs_mount_t *mp, /* mount point for filesystem */ |
241 | compat_uptr_t lastip; /* last inode # pointer */ | 234 | xfs_ino_t ino, /* inode number to get data for */ |
242 | __s32 icount; /* count of entries in buffer */ | 235 | void __user *buffer, /* buffer to place output in */ |
243 | compat_uptr_t ubuffer; /* user buffer for inode desc. */ | 236 | int ubsize, /* size of buffer */ |
244 | compat_uptr_t ocount; /* output count pointer */ | 237 | void *private_data, /* my private data */ |
245 | } compat_xfs_fsop_bulkreq_t; | 238 | xfs_daddr_t bno, /* starting bno of inode cluster */ |
246 | 239 | int *ubused, /* bytes used by me */ | |
247 | #define XFS_IOC_FSBULKSTAT_32 \ | 240 | void *dibuff, /* on-disk inode buffer */ |
248 | _IOWR('X', 101, struct compat_xfs_fsop_bulkreq) | 241 | int *stat) /* BULKSTAT_RV_... */ |
249 | #define XFS_IOC_FSBULKSTAT_SINGLE_32 \ | 242 | { |
250 | _IOWR('X', 102, struct compat_xfs_fsop_bulkreq) | 243 | return xfs_bulkstat_one_int(mp, ino, buffer, ubsize, |
251 | #define XFS_IOC_FSINUMBERS_32 \ | 244 | xfs_bulkstat_one_fmt_compat, bno, |
252 | _IOWR('X', 103, struct compat_xfs_fsop_bulkreq) | 245 | ubused, dibuff, stat); |
246 | } | ||
253 | 247 | ||
254 | /* copied from xfs_ioctl.c */ | 248 | /* copied from xfs_ioctl.c */ |
255 | STATIC int | 249 | STATIC int |
256 | xfs_ioc_bulkstat_compat( | 250 | xfs_compat_ioc_bulkstat( |
257 | xfs_mount_t *mp, | 251 | xfs_mount_t *mp, |
258 | unsigned int cmd, | 252 | unsigned int cmd, |
259 | void __user *arg) | 253 | compat_xfs_fsop_bulkreq_t __user *p32) |
260 | { | 254 | { |
261 | compat_xfs_fsop_bulkreq_t __user *p32 = (void __user *)arg; | ||
262 | u32 addr; | 255 | u32 addr; |
263 | xfs_fsop_bulkreq_t bulkreq; | 256 | xfs_fsop_bulkreq_t bulkreq; |
264 | int count; /* # of records returned */ | 257 | int count; /* # of records returned */ |
@@ -270,20 +263,20 @@ xfs_ioc_bulkstat_compat( | |||
270 | /* should be called again (unused here, but used in dmapi) */ | 263 | /* should be called again (unused here, but used in dmapi) */ |
271 | 264 | ||
272 | if (!capable(CAP_SYS_ADMIN)) | 265 | if (!capable(CAP_SYS_ADMIN)) |
273 | return -EPERM; | 266 | return -XFS_ERROR(EPERM); |
274 | 267 | ||
275 | if (XFS_FORCED_SHUTDOWN(mp)) | 268 | if (XFS_FORCED_SHUTDOWN(mp)) |
276 | return -XFS_ERROR(EIO); | 269 | return -XFS_ERROR(EIO); |
277 | 270 | ||
278 | if (get_user(addr, &p32->lastip)) | 271 | if (get_user(addr, &p32->lastip)) |
279 | return -EFAULT; | 272 | return -XFS_ERROR(EFAULT); |
280 | bulkreq.lastip = compat_ptr(addr); | 273 | bulkreq.lastip = compat_ptr(addr); |
281 | if (get_user(bulkreq.icount, &p32->icount) || | 274 | if (get_user(bulkreq.icount, &p32->icount) || |
282 | get_user(addr, &p32->ubuffer)) | 275 | get_user(addr, &p32->ubuffer)) |
283 | return -EFAULT; | 276 | return -XFS_ERROR(EFAULT); |
284 | bulkreq.ubuffer = compat_ptr(addr); | 277 | bulkreq.ubuffer = compat_ptr(addr); |
285 | if (get_user(addr, &p32->ocount)) | 278 | if (get_user(addr, &p32->ocount)) |
286 | return -EFAULT; | 279 | return -XFS_ERROR(EFAULT); |
287 | bulkreq.ocount = compat_ptr(addr); | 280 | bulkreq.ocount = compat_ptr(addr); |
288 | 281 | ||
289 | if (copy_from_user(&inlast, bulkreq.lastip, sizeof(__s64))) | 282 | if (copy_from_user(&inlast, bulkreq.lastip, sizeof(__s64))) |
@@ -295,17 +288,22 @@ xfs_ioc_bulkstat_compat( | |||
295 | if (bulkreq.ubuffer == NULL) | 288 | if (bulkreq.ubuffer == NULL) |
296 | return -XFS_ERROR(EINVAL); | 289 | return -XFS_ERROR(EINVAL); |
297 | 290 | ||
298 | if (cmd == XFS_IOC_FSINUMBERS) | 291 | if (cmd == XFS_IOC_FSINUMBERS_32) { |
299 | error = xfs_inumbers(mp, &inlast, &count, | 292 | error = xfs_inumbers(mp, &inlast, &count, |
300 | bulkreq.ubuffer, xfs_inumbers_fmt_compat); | 293 | bulkreq.ubuffer, xfs_inumbers_fmt_compat); |
301 | else { | 294 | } else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE_32) { |
302 | /* declare a var to get a warning in case the type changes */ | 295 | int res; |
303 | bulkstat_one_fmt_pf formatter = xfs_bulkstat_one_fmt_compat; | 296 | |
297 | error = xfs_bulkstat_one_compat(mp, inlast, bulkreq.ubuffer, | ||
298 | sizeof(compat_xfs_bstat_t), | ||
299 | NULL, 0, NULL, NULL, &res); | ||
300 | } else if (cmd == XFS_IOC_FSBULKSTAT_32) { | ||
304 | error = xfs_bulkstat(mp, &inlast, &count, | 301 | error = xfs_bulkstat(mp, &inlast, &count, |
305 | xfs_bulkstat_one, formatter, | 302 | xfs_bulkstat_one_compat, NULL, |
306 | sizeof(compat_xfs_bstat_t), bulkreq.ubuffer, | 303 | sizeof(compat_xfs_bstat_t), bulkreq.ubuffer, |
307 | BULKSTAT_FG_QUICK, &done); | 304 | BULKSTAT_FG_QUICK, &done); |
308 | } | 305 | } else |
306 | error = XFS_ERROR(EINVAL); | ||
309 | if (error) | 307 | if (error) |
310 | return -error; | 308 | return -error; |
311 | 309 | ||
@@ -321,63 +319,306 @@ xfs_ioc_bulkstat_compat( | |||
321 | return 0; | 319 | return 0; |
322 | } | 320 | } |
323 | 321 | ||
322 | STATIC int | ||
323 | xfs_compat_handlereq_copyin( | ||
324 | xfs_fsop_handlereq_t *hreq, | ||
325 | compat_xfs_fsop_handlereq_t __user *arg32) | ||
326 | { | ||
327 | compat_xfs_fsop_handlereq_t hreq32; | ||
328 | |||
329 | if (copy_from_user(&hreq32, arg32, sizeof(compat_xfs_fsop_handlereq_t))) | ||
330 | return -XFS_ERROR(EFAULT); | ||
331 | |||
332 | hreq->fd = hreq32.fd; | ||
333 | hreq->path = compat_ptr(hreq32.path); | ||
334 | hreq->oflags = hreq32.oflags; | ||
335 | hreq->ihandle = compat_ptr(hreq32.ihandle); | ||
336 | hreq->ihandlen = hreq32.ihandlen; | ||
337 | hreq->ohandle = compat_ptr(hreq32.ohandle); | ||
338 | hreq->ohandlen = compat_ptr(hreq32.ohandlen); | ||
324 | 339 | ||
340 | return 0; | ||
341 | } | ||
325 | 342 | ||
326 | typedef struct compat_xfs_fsop_handlereq { | 343 | /* |
327 | __u32 fd; /* fd for FD_TO_HANDLE */ | 344 | * Convert userspace handle data into inode. |
328 | compat_uptr_t path; /* user pathname */ | 345 | * |
329 | __u32 oflags; /* open flags */ | 346 | * We use the fact that all the fsop_handlereq ioctl calls have a data |
330 | compat_uptr_t ihandle; /* user supplied handle */ | 347 | * structure argument whose first component is always a xfs_fsop_handlereq_t, |
331 | __u32 ihandlen; /* user supplied length */ | 348 | * so we can pass that sub structure into this handy, shared routine. |
332 | compat_uptr_t ohandle; /* user buffer for handle */ | 349 | * |
333 | compat_uptr_t ohandlen; /* user buffer length */ | 350 | * If no error, caller must always iput the returned inode. |
334 | } compat_xfs_fsop_handlereq_t; | 351 | */ |
335 | 352 | STATIC int | |
336 | #define XFS_IOC_PATH_TO_FSHANDLE_32 \ | 353 | xfs_vget_fsop_handlereq_compat( |
337 | _IOWR('X', 104, struct compat_xfs_fsop_handlereq) | 354 | xfs_mount_t *mp, |
338 | #define XFS_IOC_PATH_TO_HANDLE_32 \ | 355 | struct inode *parinode, /* parent inode pointer */ |
339 | _IOWR('X', 105, struct compat_xfs_fsop_handlereq) | 356 | compat_xfs_fsop_handlereq_t *hreq, |
340 | #define XFS_IOC_FD_TO_HANDLE_32 \ | 357 | struct inode **inode) |
341 | _IOWR('X', 106, struct compat_xfs_fsop_handlereq) | ||
342 | #define XFS_IOC_OPEN_BY_HANDLE_32 \ | ||
343 | _IOWR('X', 107, struct compat_xfs_fsop_handlereq) | ||
344 | #define XFS_IOC_READLINK_BY_HANDLE_32 \ | ||
345 | _IOWR('X', 108, struct compat_xfs_fsop_handlereq) | ||
346 | |||
347 | STATIC unsigned long xfs_ioctl32_fshandle(unsigned long arg) | ||
348 | { | 358 | { |
349 | compat_xfs_fsop_handlereq_t __user *p32 = (void __user *)arg; | 359 | void __user *hanp; |
350 | xfs_fsop_handlereq_t __user *p = compat_alloc_user_space(sizeof(*p)); | 360 | size_t hlen; |
351 | u32 addr; | 361 | xfs_fid_t *xfid; |
352 | 362 | xfs_handle_t *handlep; | |
353 | if (copy_in_user(&p->fd, &p32->fd, sizeof(__u32)) || | 363 | xfs_handle_t handle; |
354 | get_user(addr, &p32->path) || | 364 | xfs_inode_t *ip; |
355 | put_user(compat_ptr(addr), &p->path) || | 365 | xfs_ino_t ino; |
356 | copy_in_user(&p->oflags, &p32->oflags, sizeof(__u32)) || | 366 | __u32 igen; |
357 | get_user(addr, &p32->ihandle) || | 367 | int error; |
358 | put_user(compat_ptr(addr), &p->ihandle) || | 368 | |
359 | copy_in_user(&p->ihandlen, &p32->ihandlen, sizeof(__u32)) || | 369 | /* |
360 | get_user(addr, &p32->ohandle) || | 370 | * Only allow handle opens under a directory. |
361 | put_user(compat_ptr(addr), &p->ohandle) || | 371 | */ |
362 | get_user(addr, &p32->ohandlen) || | 372 | if (!S_ISDIR(parinode->i_mode)) |
363 | put_user(compat_ptr(addr), &p->ohandlen)) | 373 | return XFS_ERROR(ENOTDIR); |
364 | return -EFAULT; | 374 | |
365 | 375 | hanp = compat_ptr(hreq->ihandle); | |
366 | return (unsigned long)p; | 376 | hlen = hreq->ihandlen; |
377 | handlep = &handle; | ||
378 | |||
379 | if (hlen < sizeof(handlep->ha_fsid) || hlen > sizeof(*handlep)) | ||
380 | return XFS_ERROR(EINVAL); | ||
381 | if (copy_from_user(handlep, hanp, hlen)) | ||
382 | return XFS_ERROR(EFAULT); | ||
383 | if (hlen < sizeof(*handlep)) | ||
384 | memset(((char *)handlep) + hlen, 0, sizeof(*handlep) - hlen); | ||
385 | if (hlen > sizeof(handlep->ha_fsid)) { | ||
386 | if (handlep->ha_fid.fid_len != | ||
387 | (hlen - sizeof(handlep->ha_fsid) - | ||
388 | sizeof(handlep->ha_fid.fid_len)) || | ||
389 | handlep->ha_fid.fid_pad) | ||
390 | return XFS_ERROR(EINVAL); | ||
391 | } | ||
392 | |||
393 | /* | ||
394 | * Crack the handle, obtain the inode # & generation # | ||
395 | */ | ||
396 | xfid = (struct xfs_fid *)&handlep->ha_fid; | ||
397 | if (xfid->fid_len == sizeof(*xfid) - sizeof(xfid->fid_len)) { | ||
398 | ino = xfid->fid_ino; | ||
399 | igen = xfid->fid_gen; | ||
400 | } else { | ||
401 | return XFS_ERROR(EINVAL); | ||
402 | } | ||
403 | |||
404 | /* | ||
405 | * Get the XFS inode, building a Linux inode to go with it. | ||
406 | */ | ||
407 | error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_SHARED, &ip, 0); | ||
408 | if (error) | ||
409 | return error; | ||
410 | if (ip == NULL) | ||
411 | return XFS_ERROR(EIO); | ||
412 | if (ip->i_d.di_gen != igen) { | ||
413 | xfs_iput_new(ip, XFS_ILOCK_SHARED); | ||
414 | return XFS_ERROR(ENOENT); | ||
415 | } | ||
416 | |||
417 | xfs_iunlock(ip, XFS_ILOCK_SHARED); | ||
418 | |||
419 | *inode = VFS_I(ip); | ||
420 | return 0; | ||
367 | } | 421 | } |
368 | 422 | ||
423 | STATIC int | ||
424 | xfs_compat_attrlist_by_handle( | ||
425 | xfs_mount_t *mp, | ||
426 | void __user *arg, | ||
427 | struct inode *parinode) | ||
428 | { | ||
429 | int error; | ||
430 | attrlist_cursor_kern_t *cursor; | ||
431 | compat_xfs_fsop_attrlist_handlereq_t al_hreq; | ||
432 | struct inode *inode; | ||
433 | char *kbuf; | ||
434 | |||
435 | if (!capable(CAP_SYS_ADMIN)) | ||
436 | return -XFS_ERROR(EPERM); | ||
437 | if (copy_from_user(&al_hreq, arg, | ||
438 | sizeof(compat_xfs_fsop_attrlist_handlereq_t))) | ||
439 | return -XFS_ERROR(EFAULT); | ||
440 | if (al_hreq.buflen > XATTR_LIST_MAX) | ||
441 | return -XFS_ERROR(EINVAL); | ||
442 | |||
443 | /* | ||
444 | * Reject flags, only allow namespaces. | ||
445 | */ | ||
446 | if (al_hreq.flags & ~(ATTR_ROOT | ATTR_SECURE)) | ||
447 | return -XFS_ERROR(EINVAL); | ||
448 | |||
449 | error = xfs_vget_fsop_handlereq_compat(mp, parinode, &al_hreq.hreq, | ||
450 | &inode); | ||
451 | if (error) | ||
452 | goto out; | ||
453 | |||
454 | kbuf = kmalloc(al_hreq.buflen, GFP_KERNEL); | ||
455 | if (!kbuf) | ||
456 | goto out_vn_rele; | ||
457 | |||
458 | cursor = (attrlist_cursor_kern_t *)&al_hreq.pos; | ||
459 | error = xfs_attr_list(XFS_I(inode), kbuf, al_hreq.buflen, | ||
460 | al_hreq.flags, cursor); | ||
461 | if (error) | ||
462 | goto out_kfree; | ||
463 | |||
464 | if (copy_to_user(compat_ptr(al_hreq.buffer), kbuf, al_hreq.buflen)) | ||
465 | error = -EFAULT; | ||
466 | |||
467 | out_kfree: | ||
468 | kfree(kbuf); | ||
469 | out_vn_rele: | ||
470 | iput(inode); | ||
471 | out: | ||
472 | return -error; | ||
473 | } | ||
369 | 474 | ||
370 | STATIC long | 475 | STATIC int |
371 | xfs_compat_ioctl( | 476 | xfs_compat_attrmulti_by_handle( |
372 | int mode, | 477 | xfs_mount_t *mp, |
373 | struct file *file, | 478 | void __user *arg, |
374 | unsigned cmd, | 479 | struct inode *parinode) |
375 | unsigned long arg) | 480 | { |
481 | int error; | ||
482 | compat_xfs_attr_multiop_t *ops; | ||
483 | compat_xfs_fsop_attrmulti_handlereq_t am_hreq; | ||
484 | struct inode *inode; | ||
485 | unsigned int i, size; | ||
486 | char *attr_name; | ||
487 | |||
488 | if (!capable(CAP_SYS_ADMIN)) | ||
489 | return -XFS_ERROR(EPERM); | ||
490 | if (copy_from_user(&am_hreq, arg, | ||
491 | sizeof(compat_xfs_fsop_attrmulti_handlereq_t))) | ||
492 | return -XFS_ERROR(EFAULT); | ||
493 | |||
494 | error = xfs_vget_fsop_handlereq_compat(mp, parinode, &am_hreq.hreq, | ||
495 | &inode); | ||
496 | if (error) | ||
497 | goto out; | ||
498 | |||
499 | error = E2BIG; | ||
500 | size = am_hreq.opcount * sizeof(compat_xfs_attr_multiop_t); | ||
501 | if (!size || size > 16 * PAGE_SIZE) | ||
502 | goto out_vn_rele; | ||
503 | |||
504 | error = ENOMEM; | ||
505 | ops = kmalloc(size, GFP_KERNEL); | ||
506 | if (!ops) | ||
507 | goto out_vn_rele; | ||
508 | |||
509 | error = EFAULT; | ||
510 | if (copy_from_user(ops, compat_ptr(am_hreq.ops), size)) | ||
511 | goto out_kfree_ops; | ||
512 | |||
513 | attr_name = kmalloc(MAXNAMELEN, GFP_KERNEL); | ||
514 | if (!attr_name) | ||
515 | goto out_kfree_ops; | ||
516 | |||
517 | |||
518 | error = 0; | ||
519 | for (i = 0; i < am_hreq.opcount; i++) { | ||
520 | ops[i].am_error = strncpy_from_user(attr_name, | ||
521 | compat_ptr(ops[i].am_attrname), | ||
522 | MAXNAMELEN); | ||
523 | if (ops[i].am_error == 0 || ops[i].am_error == MAXNAMELEN) | ||
524 | error = -ERANGE; | ||
525 | if (ops[i].am_error < 0) | ||
526 | break; | ||
527 | |||
528 | switch (ops[i].am_opcode) { | ||
529 | case ATTR_OP_GET: | ||
530 | ops[i].am_error = xfs_attrmulti_attr_get(inode, | ||
531 | attr_name, | ||
532 | compat_ptr(ops[i].am_attrvalue), | ||
533 | &ops[i].am_length, ops[i].am_flags); | ||
534 | break; | ||
535 | case ATTR_OP_SET: | ||
536 | ops[i].am_error = xfs_attrmulti_attr_set(inode, | ||
537 | attr_name, | ||
538 | compat_ptr(ops[i].am_attrvalue), | ||
539 | ops[i].am_length, ops[i].am_flags); | ||
540 | break; | ||
541 | case ATTR_OP_REMOVE: | ||
542 | ops[i].am_error = xfs_attrmulti_attr_remove(inode, | ||
543 | attr_name, ops[i].am_flags); | ||
544 | break; | ||
545 | default: | ||
546 | ops[i].am_error = EINVAL; | ||
547 | } | ||
548 | } | ||
549 | |||
550 | if (copy_to_user(compat_ptr(am_hreq.ops), ops, size)) | ||
551 | error = XFS_ERROR(EFAULT); | ||
552 | |||
553 | kfree(attr_name); | ||
554 | out_kfree_ops: | ||
555 | kfree(ops); | ||
556 | out_vn_rele: | ||
557 | iput(inode); | ||
558 | out: | ||
559 | return -error; | ||
560 | } | ||
561 | |||
562 | STATIC int | ||
563 | xfs_compat_fssetdm_by_handle( | ||
564 | xfs_mount_t *mp, | ||
565 | void __user *arg, | ||
566 | struct inode *parinode) | ||
567 | { | ||
568 | int error; | ||
569 | struct fsdmidata fsd; | ||
570 | compat_xfs_fsop_setdm_handlereq_t dmhreq; | ||
571 | struct inode *inode; | ||
572 | |||
573 | if (!capable(CAP_MKNOD)) | ||
574 | return -XFS_ERROR(EPERM); | ||
575 | if (copy_from_user(&dmhreq, arg, | ||
576 | sizeof(compat_xfs_fsop_setdm_handlereq_t))) | ||
577 | return -XFS_ERROR(EFAULT); | ||
578 | |||
579 | error = xfs_vget_fsop_handlereq_compat(mp, parinode, &dmhreq.hreq, | ||
580 | &inode); | ||
581 | if (error) | ||
582 | return -error; | ||
583 | |||
584 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) { | ||
585 | error = -XFS_ERROR(EPERM); | ||
586 | goto out; | ||
587 | } | ||
588 | |||
589 | if (copy_from_user(&fsd, compat_ptr(dmhreq.data), sizeof(fsd))) { | ||
590 | error = -XFS_ERROR(EFAULT); | ||
591 | goto out; | ||
592 | } | ||
593 | |||
594 | error = -xfs_set_dmattrs(XFS_I(inode), fsd.fsd_dmevmask, | ||
595 | fsd.fsd_dmstate); | ||
596 | |||
597 | out: | ||
598 | iput(inode); | ||
599 | return error; | ||
600 | } | ||
601 | |||
602 | long | ||
603 | xfs_file_compat_ioctl( | ||
604 | struct file *filp, | ||
605 | unsigned cmd, | ||
606 | unsigned long p) | ||
376 | { | 607 | { |
377 | struct inode *inode = file->f_path.dentry->d_inode; | 608 | struct inode *inode = filp->f_path.dentry->d_inode; |
378 | int error; | 609 | struct xfs_inode *ip = XFS_I(inode); |
610 | struct xfs_mount *mp = ip->i_mount; | ||
611 | void __user *arg = (void __user *)p; | ||
612 | int ioflags = 0; | ||
613 | int error; | ||
614 | |||
615 | if (filp->f_mode & FMODE_NOCMTIME) | ||
616 | ioflags |= IO_INVIS; | ||
617 | |||
618 | xfs_itrace_entry(ip); | ||
379 | 619 | ||
380 | switch (cmd) { | 620 | switch (cmd) { |
621 | /* No size or alignment issues on any arch */ | ||
381 | case XFS_IOC_DIOINFO: | 622 | case XFS_IOC_DIOINFO: |
382 | case XFS_IOC_FSGEOMETRY: | 623 | case XFS_IOC_FSGEOMETRY: |
383 | case XFS_IOC_FSGETXATTR: | 624 | case XFS_IOC_FSGETXATTR: |
@@ -387,48 +628,18 @@ xfs_compat_ioctl( | |||
387 | case XFS_IOC_GETBMAP: | 628 | case XFS_IOC_GETBMAP: |
388 | case XFS_IOC_GETBMAPA: | 629 | case XFS_IOC_GETBMAPA: |
389 | case XFS_IOC_GETBMAPX: | 630 | case XFS_IOC_GETBMAPX: |
390 | /* not handled | ||
391 | case XFS_IOC_FSSETDM_BY_HANDLE: | ||
392 | case XFS_IOC_ATTRLIST_BY_HANDLE: | ||
393 | case XFS_IOC_ATTRMULTI_BY_HANDLE: | ||
394 | */ | ||
395 | case XFS_IOC_FSCOUNTS: | 631 | case XFS_IOC_FSCOUNTS: |
396 | case XFS_IOC_SET_RESBLKS: | 632 | case XFS_IOC_SET_RESBLKS: |
397 | case XFS_IOC_GET_RESBLKS: | 633 | case XFS_IOC_GET_RESBLKS: |
398 | case XFS_IOC_FSGROWFSDATA: | ||
399 | case XFS_IOC_FSGROWFSLOG: | 634 | case XFS_IOC_FSGROWFSLOG: |
400 | case XFS_IOC_FSGROWFSRT: | ||
401 | case XFS_IOC_FREEZE: | 635 | case XFS_IOC_FREEZE: |
402 | case XFS_IOC_THAW: | 636 | case XFS_IOC_THAW: |
403 | case XFS_IOC_GOINGDOWN: | 637 | case XFS_IOC_GOINGDOWN: |
404 | case XFS_IOC_ERROR_INJECTION: | 638 | case XFS_IOC_ERROR_INJECTION: |
405 | case XFS_IOC_ERROR_CLEARALL: | 639 | case XFS_IOC_ERROR_CLEARALL: |
406 | break; | 640 | return xfs_file_ioctl(filp, cmd, p); |
407 | 641 | #ifndef BROKEN_X86_ALIGNMENT | |
408 | case XFS_IOC32_GETXFLAGS: | 642 | /* These are handled fine if no alignment issues */ |
409 | case XFS_IOC32_SETXFLAGS: | ||
410 | case XFS_IOC32_GETVERSION: | ||
411 | cmd = _NATIVE_IOC(cmd, long); | ||
412 | break; | ||
413 | #ifdef BROKEN_X86_ALIGNMENT | ||
414 | /* xfs_flock_t has wrong u32 vs u64 alignment */ | ||
415 | case XFS_IOC_ALLOCSP_32: | ||
416 | case XFS_IOC_FREESP_32: | ||
417 | case XFS_IOC_ALLOCSP64_32: | ||
418 | case XFS_IOC_FREESP64_32: | ||
419 | case XFS_IOC_RESVSP_32: | ||
420 | case XFS_IOC_UNRESVSP_32: | ||
421 | case XFS_IOC_RESVSP64_32: | ||
422 | case XFS_IOC_UNRESVSP64_32: | ||
423 | arg = xfs_ioctl32_flock(arg); | ||
424 | cmd = _NATIVE_IOC(cmd, struct xfs_flock64); | ||
425 | break; | ||
426 | case XFS_IOC_FSGEOMETRY_V1_32: | ||
427 | arg = xfs_ioctl32_geom_v1(arg); | ||
428 | cmd = _NATIVE_IOC(cmd, struct xfs_fsop_geom_v1); | ||
429 | break; | ||
430 | |||
431 | #else /* These are handled fine if no alignment issues */ | ||
432 | case XFS_IOC_ALLOCSP: | 643 | case XFS_IOC_ALLOCSP: |
433 | case XFS_IOC_FREESP: | 644 | case XFS_IOC_FREESP: |
434 | case XFS_IOC_RESVSP: | 645 | case XFS_IOC_RESVSP: |
@@ -438,51 +649,97 @@ xfs_compat_ioctl( | |||
438 | case XFS_IOC_RESVSP64: | 649 | case XFS_IOC_RESVSP64: |
439 | case XFS_IOC_UNRESVSP64: | 650 | case XFS_IOC_UNRESVSP64: |
440 | case XFS_IOC_FSGEOMETRY_V1: | 651 | case XFS_IOC_FSGEOMETRY_V1: |
441 | break; | 652 | case XFS_IOC_FSGROWFSDATA: |
653 | case XFS_IOC_FSGROWFSRT: | ||
654 | return xfs_file_ioctl(filp, cmd, p); | ||
655 | #else | ||
656 | case XFS_IOC_ALLOCSP_32: | ||
657 | case XFS_IOC_FREESP_32: | ||
658 | case XFS_IOC_ALLOCSP64_32: | ||
659 | case XFS_IOC_FREESP64_32: | ||
660 | case XFS_IOC_RESVSP_32: | ||
661 | case XFS_IOC_UNRESVSP_32: | ||
662 | case XFS_IOC_RESVSP64_32: | ||
663 | case XFS_IOC_UNRESVSP64_32: { | ||
664 | struct xfs_flock64 bf; | ||
442 | 665 | ||
443 | /* xfs_bstat_t still has wrong u32 vs u64 alignment */ | 666 | if (xfs_compat_flock64_copyin(&bf, arg)) |
444 | case XFS_IOC_SWAPEXT: | 667 | return -XFS_ERROR(EFAULT); |
445 | break; | 668 | cmd = _NATIVE_IOC(cmd, struct xfs_flock64); |
669 | return xfs_ioc_space(ip, inode, filp, ioflags, cmd, &bf); | ||
670 | } | ||
671 | case XFS_IOC_FSGEOMETRY_V1_32: | ||
672 | return xfs_compat_ioc_fsgeometry_v1(mp, arg); | ||
673 | case XFS_IOC_FSGROWFSDATA_32: { | ||
674 | struct xfs_growfs_data in; | ||
675 | |||
676 | if (xfs_compat_growfs_data_copyin(&in, arg)) | ||
677 | return -XFS_ERROR(EFAULT); | ||
678 | error = xfs_growfs_data(mp, &in); | ||
679 | return -error; | ||
680 | } | ||
681 | case XFS_IOC_FSGROWFSRT_32: { | ||
682 | struct xfs_growfs_rt in; | ||
446 | 683 | ||
684 | if (xfs_compat_growfs_rt_copyin(&in, arg)) | ||
685 | return -XFS_ERROR(EFAULT); | ||
686 | error = xfs_growfs_rt(mp, &in); | ||
687 | return -error; | ||
688 | } | ||
447 | #endif | 689 | #endif |
690 | /* long changes size, but xfs only copiese out 32 bits */ | ||
691 | case XFS_IOC_GETXFLAGS_32: | ||
692 | case XFS_IOC_SETXFLAGS_32: | ||
693 | case XFS_IOC_GETVERSION_32: | ||
694 | cmd = _NATIVE_IOC(cmd, long); | ||
695 | return xfs_file_ioctl(filp, cmd, p); | ||
696 | case XFS_IOC_SWAPEXT: { | ||
697 | struct xfs_swapext sxp; | ||
698 | struct compat_xfs_swapext __user *sxu = arg; | ||
699 | |||
700 | /* Bulk copy in up to the sx_stat field, then copy bstat */ | ||
701 | if (copy_from_user(&sxp, sxu, | ||
702 | offsetof(struct xfs_swapext, sx_stat)) || | ||
703 | xfs_ioctl32_bstat_copyin(&sxp.sx_stat, &sxu->sx_stat)) | ||
704 | return -XFS_ERROR(EFAULT); | ||
705 | error = xfs_swapext(&sxp); | ||
706 | return -error; | ||
707 | } | ||
448 | case XFS_IOC_FSBULKSTAT_32: | 708 | case XFS_IOC_FSBULKSTAT_32: |
449 | case XFS_IOC_FSBULKSTAT_SINGLE_32: | 709 | case XFS_IOC_FSBULKSTAT_SINGLE_32: |
450 | case XFS_IOC_FSINUMBERS_32: | 710 | case XFS_IOC_FSINUMBERS_32: |
451 | cmd = _NATIVE_IOC(cmd, struct xfs_fsop_bulkreq); | 711 | return xfs_compat_ioc_bulkstat(mp, cmd, arg); |
452 | return xfs_ioc_bulkstat_compat(XFS_I(inode)->i_mount, | ||
453 | cmd, (void __user*)arg); | ||
454 | case XFS_IOC_FD_TO_HANDLE_32: | 712 | case XFS_IOC_FD_TO_HANDLE_32: |
455 | case XFS_IOC_PATH_TO_HANDLE_32: | 713 | case XFS_IOC_PATH_TO_HANDLE_32: |
456 | case XFS_IOC_PATH_TO_FSHANDLE_32: | 714 | case XFS_IOC_PATH_TO_FSHANDLE_32: { |
457 | case XFS_IOC_OPEN_BY_HANDLE_32: | 715 | struct xfs_fsop_handlereq hreq; |
458 | case XFS_IOC_READLINK_BY_HANDLE_32: | 716 | |
459 | arg = xfs_ioctl32_fshandle(arg); | 717 | if (xfs_compat_handlereq_copyin(&hreq, arg)) |
718 | return -XFS_ERROR(EFAULT); | ||
460 | cmd = _NATIVE_IOC(cmd, struct xfs_fsop_handlereq); | 719 | cmd = _NATIVE_IOC(cmd, struct xfs_fsop_handlereq); |
461 | break; | 720 | return xfs_find_handle(cmd, &hreq); |
462 | default: | ||
463 | return -ENOIOCTLCMD; | ||
464 | } | 721 | } |
722 | case XFS_IOC_OPEN_BY_HANDLE_32: { | ||
723 | struct xfs_fsop_handlereq hreq; | ||
465 | 724 | ||
466 | error = xfs_ioctl(XFS_I(inode), file, mode, cmd, (void __user *)arg); | 725 | if (xfs_compat_handlereq_copyin(&hreq, arg)) |
467 | xfs_iflags_set(XFS_I(inode), XFS_IMODIFIED); | 726 | return -XFS_ERROR(EFAULT); |
468 | 727 | return xfs_open_by_handle(mp, &hreq, filp, inode); | |
469 | return error; | 728 | } |
470 | } | 729 | case XFS_IOC_READLINK_BY_HANDLE_32: { |
471 | 730 | struct xfs_fsop_handlereq hreq; | |
472 | long | ||
473 | xfs_file_compat_ioctl( | ||
474 | struct file *file, | ||
475 | unsigned cmd, | ||
476 | unsigned long arg) | ||
477 | { | ||
478 | return xfs_compat_ioctl(0, file, cmd, arg); | ||
479 | } | ||
480 | 731 | ||
481 | long | 732 | if (xfs_compat_handlereq_copyin(&hreq, arg)) |
482 | xfs_file_compat_invis_ioctl( | 733 | return -XFS_ERROR(EFAULT); |
483 | struct file *file, | 734 | return xfs_readlink_by_handle(mp, &hreq, inode); |
484 | unsigned cmd, | 735 | } |
485 | unsigned long arg) | 736 | case XFS_IOC_ATTRLIST_BY_HANDLE_32: |
486 | { | 737 | return xfs_compat_attrlist_by_handle(mp, arg, inode); |
487 | return xfs_compat_ioctl(IO_INVIS, file, cmd, arg); | 738 | case XFS_IOC_ATTRMULTI_BY_HANDLE_32: |
739 | return xfs_compat_attrmulti_by_handle(mp, arg, inode); | ||
740 | case XFS_IOC_FSSETDM_BY_HANDLE_32: | ||
741 | return xfs_compat_fssetdm_by_handle(mp, arg, inode); | ||
742 | default: | ||
743 | return -XFS_ERROR(ENOIOCTLCMD); | ||
744 | } | ||
488 | } | 745 | } |