diff options
| author | Michal Marek <mmarek@suse.cz> | 2007-07-10 21:10:19 -0400 |
|---|---|---|
| committer | Tim Shimmin <tes@chook.melbourne.sgi.com> | 2007-07-14 01:42:50 -0400 |
| commit | faa63e9584df41020440756b8b90b7b63f95e4f6 (patch) | |
| tree | 9b0369a028d682e36ab91396bcebb1ecfb298e29 | |
| parent | 1fa503df66f7bffc0ff62662626897eec79446c2 (diff) | |
[XFS] Fix XFS_IOC_FSBULKSTAT{,_SINGLE} & XFS_IOC_FSINUMBERS in compat mode
* 32bit struct xfs_fsop_bulkreq has different size and layout of
members, no matter the alignment. Move the code out of the #else
branch (why was it there in the first place?). Define _32 variants of
the ioctl constants.
* 32bit struct xfs_bstat is different because of time_t and on
i386 because of different padding. Make xfs_bulkstat_one() accept a
custom "output formatter" in the private_data argument which takes care
of the xfs_bulkstat_one_compat() that takes care of the different
layout in the compat case.
* i386 struct xfs_inogrp has different padding.
Add a similar "output formatter" mecanism to xfs_inumbers().
SGI-PV: 967354
SGI-Modid: xfs-linux-melb:xfs-kern:29102a
Signed-off-by: Michal Marek <mmarek@suse.cz>
Signed-off-by: David Chinner <dgc@sgi.com>
Signed-off-by: Tim Shimmin <tes@sgi.com>
| -rw-r--r-- | fs/xfs/linux-2.6/xfs_ioctl.c | 2 | ||||
| -rw-r--r-- | fs/xfs/linux-2.6/xfs_ioctl32.c | 224 | ||||
| -rw-r--r-- | fs/xfs/xfs_itable.c | 42 | ||||
| -rw-r--r-- | fs/xfs/xfs_itable.h | 20 |
4 files changed, 255 insertions, 33 deletions
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c index ff5c41ff8d40..5917808abbd6 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl.c +++ b/fs/xfs/linux-2.6/xfs_ioctl.c | |||
| @@ -1019,7 +1019,7 @@ xfs_ioc_bulkstat( | |||
| 1019 | 1019 | ||
| 1020 | if (cmd == XFS_IOC_FSINUMBERS) | 1020 | if (cmd == XFS_IOC_FSINUMBERS) |
| 1021 | error = xfs_inumbers(mp, &inlast, &count, | 1021 | error = xfs_inumbers(mp, &inlast, &count, |
| 1022 | bulkreq.ubuffer); | 1022 | bulkreq.ubuffer, xfs_inumbers_fmt); |
| 1023 | else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE) | 1023 | else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE) |
| 1024 | error = xfs_bulkstat_single(mp, &inlast, | 1024 | error = xfs_bulkstat_single(mp, &inlast, |
| 1025 | bulkreq.ubuffer, &done); | 1025 | bulkreq.ubuffer, &done); |
diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.c b/fs/xfs/linux-2.6/xfs_ioctl32.c index 87163fb9746b..141cf15067c2 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl32.c +++ b/fs/xfs/linux-2.6/xfs_ioctl32.c | |||
| @@ -23,10 +23,25 @@ | |||
| 23 | #include <linux/fs.h> | 23 | #include <linux/fs.h> |
| 24 | #include <asm/uaccess.h> | 24 | #include <asm/uaccess.h> |
| 25 | #include "xfs.h" | 25 | #include "xfs.h" |
| 26 | #include "xfs_types.h" | ||
| 27 | #include "xfs_fs.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" | ||
| 28 | #include "xfs_vfs.h" | 39 | #include "xfs_vfs.h" |
| 29 | #include "xfs_vnode.h" | 40 | #include "xfs_vnode.h" |
| 41 | #include "xfs_dinode.h" | ||
| 42 | #include "xfs_inode.h" | ||
| 43 | #include "xfs_itable.h" | ||
| 44 | #include "xfs_error.h" | ||
| 30 | #include "xfs_dfrag.h" | 45 | #include "xfs_dfrag.h" |
| 31 | 46 | ||
| 32 | #define _NATIVE_IOC(cmd, type) \ | 47 | #define _NATIVE_IOC(cmd, type) \ |
| @@ -34,6 +49,7 @@ | |||
| 34 | 49 | ||
| 35 | #if defined(CONFIG_IA64) || defined(CONFIG_X86_64) | 50 | #if defined(CONFIG_IA64) || defined(CONFIG_X86_64) |
| 36 | #define BROKEN_X86_ALIGNMENT | 51 | #define BROKEN_X86_ALIGNMENT |
| 52 | #define _PACKED __attribute__((packed)) | ||
| 37 | /* on ia32 l_start is on a 32-bit boundary */ | 53 | /* on ia32 l_start is on a 32-bit boundary */ |
| 38 | typedef struct xfs_flock64_32 { | 54 | typedef struct xfs_flock64_32 { |
| 39 | __s16 l_type; | 55 | __s16 l_type; |
| @@ -111,35 +127,196 @@ STATIC unsigned long xfs_ioctl32_geom_v1(unsigned long arg) | |||
| 111 | return (unsigned long)p; | 127 | return (unsigned long)p; |
| 112 | } | 128 | } |
| 113 | 129 | ||
| 130 | typedef struct compat_xfs_inogrp { | ||
| 131 | __u64 xi_startino; /* starting inode number */ | ||
| 132 | __s32 xi_alloccount; /* # bits set in allocmask */ | ||
| 133 | __u64 xi_allocmask; /* mask of allocated inodes */ | ||
| 134 | } __attribute__((packed)) compat_xfs_inogrp_t; | ||
| 135 | |||
| 136 | STATIC int xfs_inumbers_fmt_compat( | ||
| 137 | void __user *ubuffer, | ||
| 138 | const xfs_inogrp_t *buffer, | ||
| 139 | long count, | ||
| 140 | long *written) | ||
| 141 | { | ||
| 142 | compat_xfs_inogrp_t *p32 = ubuffer; | ||
| 143 | long i; | ||
| 144 | |||
| 145 | for (i = 0; i < count; i++) { | ||
| 146 | if (put_user(buffer[i].xi_startino, &p32[i].xi_startino) || | ||
| 147 | put_user(buffer[i].xi_alloccount, &p32[i].xi_alloccount) || | ||
| 148 | put_user(buffer[i].xi_allocmask, &p32[i].xi_allocmask)) | ||
| 149 | return -EFAULT; | ||
| 150 | } | ||
| 151 | *written = count * sizeof(*p32); | ||
| 152 | return 0; | ||
| 153 | } | ||
| 154 | |||
| 114 | #else | 155 | #else |
| 115 | 156 | ||
| 116 | typedef struct xfs_fsop_bulkreq32 { | 157 | #define xfs_inumbers_fmt_compat xfs_inumbers_fmt |
| 158 | #define _PACKED | ||
| 159 | |||
| 160 | #endif | ||
| 161 | |||
| 162 | /* XFS_IOC_FSBULKSTAT and friends */ | ||
| 163 | |||
| 164 | typedef struct compat_xfs_bstime { | ||
| 165 | __s32 tv_sec; /* seconds */ | ||
| 166 | __s32 tv_nsec; /* and nanoseconds */ | ||
| 167 | } compat_xfs_bstime_t; | ||
| 168 | |||
| 169 | STATIC int xfs_bstime_store_compat( | ||
| 170 | compat_xfs_bstime_t __user *p32, | ||
| 171 | const xfs_bstime_t *p) | ||
| 172 | { | ||
| 173 | __s32 sec32; | ||
| 174 | |||
| 175 | sec32 = p->tv_sec; | ||
| 176 | if (put_user(sec32, &p32->tv_sec) || | ||
| 177 | put_user(p->tv_nsec, &p32->tv_nsec)) | ||
| 178 | return -EFAULT; | ||
| 179 | return 0; | ||
| 180 | } | ||
| 181 | |||
| 182 | typedef struct compat_xfs_bstat { | ||
| 183 | __u64 bs_ino; /* inode number */ | ||
| 184 | __u16 bs_mode; /* type and mode */ | ||
| 185 | __u16 bs_nlink; /* number of links */ | ||
| 186 | __u32 bs_uid; /* user id */ | ||
| 187 | __u32 bs_gid; /* group id */ | ||
| 188 | __u32 bs_rdev; /* device value */ | ||
| 189 | __s32 bs_blksize; /* block size */ | ||
| 190 | __s64 bs_size; /* file size */ | ||
| 191 | compat_xfs_bstime_t bs_atime; /* access time */ | ||
| 192 | compat_xfs_bstime_t bs_mtime; /* modify time */ | ||
| 193 | compat_xfs_bstime_t bs_ctime; /* inode change time */ | ||
| 194 | int64_t bs_blocks; /* number of blocks */ | ||
| 195 | __u32 bs_xflags; /* extended flags */ | ||
| 196 | __s32 bs_extsize; /* extent size */ | ||
| 197 | __s32 bs_extents; /* number of extents */ | ||
| 198 | __u32 bs_gen; /* generation count */ | ||
| 199 | __u16 bs_projid; /* project id */ | ||
| 200 | unsigned char bs_pad[14]; /* pad space, unused */ | ||
| 201 | __u32 bs_dmevmask; /* DMIG event mask */ | ||
| 202 | __u16 bs_dmstate; /* DMIG state info */ | ||
| 203 | __u16 bs_aextents; /* attribute number of extents */ | ||
| 204 | } _PACKED compat_xfs_bstat_t; | ||
| 205 | |||
| 206 | STATIC int xfs_bulkstat_one_fmt_compat( | ||
| 207 | void __user *ubuffer, | ||
| 208 | const xfs_bstat_t *buffer) | ||
| 209 | { | ||
| 210 | compat_xfs_bstat_t __user *p32 = ubuffer; | ||
| 211 | |||
| 212 | if (put_user(buffer->bs_ino, &p32->bs_ino) || | ||
| 213 | put_user(buffer->bs_mode, &p32->bs_mode) || | ||
| 214 | put_user(buffer->bs_nlink, &p32->bs_nlink) || | ||
| 215 | put_user(buffer->bs_uid, &p32->bs_uid) || | ||
| 216 | put_user(buffer->bs_gid, &p32->bs_gid) || | ||
| 217 | put_user(buffer->bs_rdev, &p32->bs_rdev) || | ||
| 218 | put_user(buffer->bs_blksize, &p32->bs_blksize) || | ||
| 219 | put_user(buffer->bs_size, &p32->bs_size) || | ||
| 220 | xfs_bstime_store_compat(&p32->bs_atime, &buffer->bs_atime) || | ||
| 221 | xfs_bstime_store_compat(&p32->bs_mtime, &buffer->bs_mtime) || | ||
| 222 | xfs_bstime_store_compat(&p32->bs_ctime, &buffer->bs_ctime) || | ||
| 223 | put_user(buffer->bs_blocks, &p32->bs_blocks) || | ||
| 224 | put_user(buffer->bs_xflags, &p32->bs_xflags) || | ||
| 225 | put_user(buffer->bs_extsize, &p32->bs_extsize) || | ||
| 226 | put_user(buffer->bs_extents, &p32->bs_extents) || | ||
| 227 | put_user(buffer->bs_gen, &p32->bs_gen) || | ||
| 228 | put_user(buffer->bs_projid, &p32->bs_projid) || | ||
| 229 | put_user(buffer->bs_dmevmask, &p32->bs_dmevmask) || | ||
| 230 | put_user(buffer->bs_dmstate, &p32->bs_dmstate) || | ||
| 231 | put_user(buffer->bs_aextents, &p32->bs_aextents)) | ||
| 232 | return -EFAULT; | ||
| 233 | return sizeof(*p32); | ||
| 234 | } | ||
| 235 | |||
| 236 | |||
| 237 | |||
| 238 | typedef struct compat_xfs_fsop_bulkreq { | ||
| 117 | compat_uptr_t lastip; /* last inode # pointer */ | 239 | compat_uptr_t lastip; /* last inode # pointer */ |
| 118 | __s32 icount; /* count of entries in buffer */ | 240 | __s32 icount; /* count of entries in buffer */ |
| 119 | compat_uptr_t ubuffer; /* user buffer for inode desc. */ | 241 | compat_uptr_t ubuffer; /* user buffer for inode desc. */ |
| 120 | __s32 ocount; /* output count pointer */ | 242 | compat_uptr_t ocount; /* output count pointer */ |
| 121 | } xfs_fsop_bulkreq32_t; | 243 | } compat_xfs_fsop_bulkreq_t; |
| 122 | 244 | ||
| 123 | STATIC unsigned long | 245 | #define XFS_IOC_FSBULKSTAT_32 \ |
| 124 | xfs_ioctl32_bulkstat( | 246 | _IOWR('X', 101, struct compat_xfs_fsop_bulkreq) |
| 125 | unsigned long arg) | 247 | #define XFS_IOC_FSBULKSTAT_SINGLE_32 \ |
| 248 | _IOWR('X', 102, struct compat_xfs_fsop_bulkreq) | ||
| 249 | #define XFS_IOC_FSINUMBERS_32 \ | ||
| 250 | _IOWR('X', 103, struct compat_xfs_fsop_bulkreq) | ||
| 251 | |||
| 252 | /* copied from xfs_ioctl.c */ | ||
| 253 | STATIC int | ||
| 254 | xfs_ioc_bulkstat_compat( | ||
| 255 | xfs_mount_t *mp, | ||
| 256 | unsigned int cmd, | ||
| 257 | void __user *arg) | ||
| 126 | { | 258 | { |
| 127 | xfs_fsop_bulkreq32_t __user *p32 = (void __user *)arg; | 259 | compat_xfs_fsop_bulkreq_t __user *p32 = (void __user *)arg; |
| 128 | xfs_fsop_bulkreq_t __user *p = compat_alloc_user_space(sizeof(*p)); | ||
| 129 | u32 addr; | 260 | u32 addr; |
| 261 | xfs_fsop_bulkreq_t bulkreq; | ||
| 262 | int count; /* # of records returned */ | ||
| 263 | xfs_ino_t inlast; /* last inode number */ | ||
| 264 | int done; | ||
| 265 | int error; | ||
| 266 | |||
| 267 | /* done = 1 if there are more stats to get and if bulkstat */ | ||
| 268 | /* should be called again (unused here, but used in dmapi) */ | ||
| 130 | 269 | ||
| 131 | if (get_user(addr, &p32->lastip) || | 270 | if (!capable(CAP_SYS_ADMIN)) |
| 132 | put_user(compat_ptr(addr), &p->lastip) || | 271 | return -EPERM; |
| 133 | copy_in_user(&p->icount, &p32->icount, sizeof(s32)) || | 272 | |
| 134 | get_user(addr, &p32->ubuffer) || | 273 | if (XFS_FORCED_SHUTDOWN(mp)) |
| 135 | put_user(compat_ptr(addr), &p->ubuffer) || | 274 | return -XFS_ERROR(EIO); |
| 136 | get_user(addr, &p32->ocount) || | 275 | |
| 137 | put_user(compat_ptr(addr), &p->ocount)) | 276 | if (get_user(addr, &p32->lastip)) |
| 277 | return -EFAULT; | ||
| 278 | bulkreq.lastip = compat_ptr(addr); | ||
| 279 | if (get_user(bulkreq.icount, &p32->icount) || | ||
| 280 | get_user(addr, &p32->ubuffer)) | ||
| 138 | return -EFAULT; | 281 | return -EFAULT; |
| 282 | bulkreq.ubuffer = compat_ptr(addr); | ||
| 283 | if (get_user(addr, &p32->ocount)) | ||
| 284 | return -EFAULT; | ||
| 285 | bulkreq.ocount = compat_ptr(addr); | ||
| 139 | 286 | ||
| 140 | return (unsigned long)p; | 287 | if (copy_from_user(&inlast, bulkreq.lastip, sizeof(__s64))) |
| 288 | return -XFS_ERROR(EFAULT); | ||
| 289 | |||
| 290 | if ((count = bulkreq.icount) <= 0) | ||
| 291 | return -XFS_ERROR(EINVAL); | ||
| 292 | |||
| 293 | if (cmd == XFS_IOC_FSINUMBERS) | ||
| 294 | error = xfs_inumbers(mp, &inlast, &count, | ||
| 295 | bulkreq.ubuffer, xfs_inumbers_fmt_compat); | ||
| 296 | else { | ||
| 297 | /* declare a var to get a warning in case the type changes */ | ||
| 298 | bulkstat_one_fmt_pf formatter = xfs_bulkstat_one_fmt_compat; | ||
| 299 | error = xfs_bulkstat(mp, &inlast, &count, | ||
| 300 | xfs_bulkstat_one, formatter, | ||
| 301 | sizeof(compat_xfs_bstat_t), bulkreq.ubuffer, | ||
| 302 | BULKSTAT_FG_QUICK, &done); | ||
| 303 | } | ||
| 304 | if (error) | ||
| 305 | return -error; | ||
| 306 | |||
| 307 | if (bulkreq.ocount != NULL) { | ||
| 308 | if (copy_to_user(bulkreq.lastip, &inlast, | ||
| 309 | sizeof(xfs_ino_t))) | ||
| 310 | return -XFS_ERROR(EFAULT); | ||
| 311 | |||
| 312 | if (copy_to_user(bulkreq.ocount, &count, sizeof(count))) | ||
| 313 | return -XFS_ERROR(EFAULT); | ||
| 314 | } | ||
| 315 | |||
| 316 | return 0; | ||
| 141 | } | 317 | } |
| 142 | #endif | 318 | |
| 319 | |||
| 143 | 320 | ||
| 144 | typedef struct compat_xfs_fsop_handlereq { | 321 | typedef struct compat_xfs_fsop_handlereq { |
| 145 | __u32 fd; /* fd for FD_TO_HANDLE */ | 322 | __u32 fd; /* fd for FD_TO_HANDLE */ |
| @@ -261,12 +438,13 @@ xfs_compat_ioctl( | |||
| 261 | case XFS_IOC_SWAPEXT: | 438 | case XFS_IOC_SWAPEXT: |
| 262 | break; | 439 | break; |
| 263 | 440 | ||
| 264 | case XFS_IOC_FSBULKSTAT_SINGLE: | ||
| 265 | case XFS_IOC_FSBULKSTAT: | ||
| 266 | case XFS_IOC_FSINUMBERS: | ||
| 267 | arg = xfs_ioctl32_bulkstat(arg); | ||
| 268 | break; | ||
| 269 | #endif | 441 | #endif |
| 442 | case XFS_IOC_FSBULKSTAT_32: | ||
| 443 | case XFS_IOC_FSBULKSTAT_SINGLE_32: | ||
| 444 | case XFS_IOC_FSINUMBERS_32: | ||
| 445 | cmd = _NATIVE_IOC(cmd, struct xfs_fsop_bulkreq); | ||
| 446 | return xfs_ioc_bulkstat_compat(XFS_BHVTOI(VNHEAD(vp))->i_mount, | ||
| 447 | cmd, (void*)arg); | ||
| 270 | case XFS_IOC_FD_TO_HANDLE_32: | 448 | case XFS_IOC_FD_TO_HANDLE_32: |
| 271 | case XFS_IOC_PATH_TO_HANDLE_32: | 449 | case XFS_IOC_PATH_TO_HANDLE_32: |
| 272 | case XFS_IOC_PATH_TO_FSHANDLE_32: | 450 | case XFS_IOC_PATH_TO_FSHANDLE_32: |
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c index e725ddd3de5f..4c2454bcc714 100644 --- a/fs/xfs/xfs_itable.c +++ b/fs/xfs/xfs_itable.c | |||
| @@ -202,6 +202,16 @@ xfs_bulkstat_one_dinode( | |||
| 202 | return 0; | 202 | return 0; |
| 203 | } | 203 | } |
| 204 | 204 | ||
| 205 | STATIC int | ||
| 206 | xfs_bulkstat_one_fmt( | ||
| 207 | void __user *ubuffer, | ||
| 208 | const xfs_bstat_t *buffer) | ||
| 209 | { | ||
| 210 | if (copy_to_user(ubuffer, buffer, sizeof(*buffer))) | ||
| 211 | return -EFAULT; | ||
| 212 | return sizeof(*buffer); | ||
| 213 | } | ||
| 214 | |||
| 205 | /* | 215 | /* |
| 206 | * Return stat information for one inode. | 216 | * Return stat information for one inode. |
| 207 | * Return 0 if ok, else errno. | 217 | * Return 0 if ok, else errno. |
| @@ -221,6 +231,7 @@ xfs_bulkstat_one( | |||
| 221 | xfs_bstat_t *buf; /* return buffer */ | 231 | xfs_bstat_t *buf; /* return buffer */ |
| 222 | int error = 0; /* error value */ | 232 | int error = 0; /* error value */ |
| 223 | xfs_dinode_t *dip; /* dinode inode pointer */ | 233 | xfs_dinode_t *dip; /* dinode inode pointer */ |
| 234 | bulkstat_one_fmt_pf formatter = private_data ? : xfs_bulkstat_one_fmt; | ||
| 224 | 235 | ||
| 225 | dip = (xfs_dinode_t *)dibuff; | 236 | dip = (xfs_dinode_t *)dibuff; |
| 226 | *stat = BULKSTAT_RV_NOTHING; | 237 | *stat = BULKSTAT_RV_NOTHING; |
| @@ -243,14 +254,15 @@ xfs_bulkstat_one( | |||
| 243 | xfs_bulkstat_one_dinode(mp, ino, dip, buf); | 254 | xfs_bulkstat_one_dinode(mp, ino, dip, buf); |
| 244 | } | 255 | } |
| 245 | 256 | ||
| 246 | if (copy_to_user(buffer, buf, sizeof(*buf))) { | 257 | error = formatter(buffer, buf); |
| 258 | if (error < 0) { | ||
| 247 | error = EFAULT; | 259 | error = EFAULT; |
| 248 | goto out_free; | 260 | goto out_free; |
| 249 | } | 261 | } |
| 250 | 262 | ||
| 251 | *stat = BULKSTAT_RV_DIDONE; | 263 | *stat = BULKSTAT_RV_DIDONE; |
| 252 | if (ubused) | 264 | if (ubused) |
| 253 | *ubused = sizeof(*buf); | 265 | *ubused = error; |
| 254 | 266 | ||
| 255 | out_free: | 267 | out_free: |
| 256 | kmem_free(buf, sizeof(*buf)); | 268 | kmem_free(buf, sizeof(*buf)); |
| @@ -748,6 +760,19 @@ xfs_bulkstat_single( | |||
| 748 | return 0; | 760 | return 0; |
| 749 | } | 761 | } |
| 750 | 762 | ||
| 763 | int | ||
| 764 | xfs_inumbers_fmt( | ||
| 765 | void __user *ubuffer, /* buffer to write to */ | ||
| 766 | const xfs_inogrp_t *buffer, /* buffer to read from */ | ||
| 767 | long count, /* # of elements to read */ | ||
| 768 | long *written) /* # of bytes written */ | ||
| 769 | { | ||
| 770 | if (copy_to_user(ubuffer, buffer, count * sizeof(*buffer))) | ||
| 771 | return -EFAULT; | ||
| 772 | *written = count * sizeof(*buffer); | ||
| 773 | return 0; | ||
| 774 | } | ||
| 775 | |||
| 751 | /* | 776 | /* |
| 752 | * Return inode number table for the filesystem. | 777 | * Return inode number table for the filesystem. |
| 753 | */ | 778 | */ |
| @@ -756,7 +781,8 @@ xfs_inumbers( | |||
| 756 | xfs_mount_t *mp, /* mount point for filesystem */ | 781 | xfs_mount_t *mp, /* mount point for filesystem */ |
| 757 | xfs_ino_t *lastino, /* last inode returned */ | 782 | xfs_ino_t *lastino, /* last inode returned */ |
| 758 | int *count, /* size of buffer/count returned */ | 783 | int *count, /* size of buffer/count returned */ |
| 759 | xfs_inogrp_t __user *ubuffer)/* buffer with inode descriptions */ | 784 | void __user *ubuffer,/* buffer with inode descriptions */ |
| 785 | inumbers_fmt_pf formatter) | ||
| 760 | { | 786 | { |
| 761 | xfs_buf_t *agbp; | 787 | xfs_buf_t *agbp; |
| 762 | xfs_agino_t agino; | 788 | xfs_agino_t agino; |
| @@ -835,12 +861,12 @@ xfs_inumbers( | |||
| 835 | bufidx++; | 861 | bufidx++; |
| 836 | left--; | 862 | left--; |
| 837 | if (bufidx == bcount) { | 863 | if (bufidx == bcount) { |
| 838 | if (copy_to_user(ubuffer, buffer, | 864 | long written; |
| 839 | bufidx * sizeof(*buffer))) { | 865 | if (formatter(ubuffer, buffer, bufidx, &written)) { |
| 840 | error = XFS_ERROR(EFAULT); | 866 | error = XFS_ERROR(EFAULT); |
| 841 | break; | 867 | break; |
| 842 | } | 868 | } |
| 843 | ubuffer += bufidx; | 869 | ubuffer += written; |
| 844 | *count += bufidx; | 870 | *count += bufidx; |
| 845 | bufidx = 0; | 871 | bufidx = 0; |
| 846 | } | 872 | } |
| @@ -862,8 +888,8 @@ xfs_inumbers( | |||
| 862 | } | 888 | } |
| 863 | if (!error) { | 889 | if (!error) { |
| 864 | if (bufidx) { | 890 | if (bufidx) { |
| 865 | if (copy_to_user(ubuffer, buffer, | 891 | long written; |
| 866 | bufidx * sizeof(*buffer))) | 892 | if (formatter(ubuffer, buffer, bufidx, &written)) |
| 867 | error = XFS_ERROR(EFAULT); | 893 | error = XFS_ERROR(EFAULT); |
| 868 | else | 894 | else |
| 869 | *count += bufidx; | 895 | *count += bufidx; |
diff --git a/fs/xfs/xfs_itable.h b/fs/xfs/xfs_itable.h index f25a28862a17..a1f18fce9b70 100644 --- a/fs/xfs/xfs_itable.h +++ b/fs/xfs/xfs_itable.h | |||
| @@ -69,6 +69,10 @@ xfs_bulkstat_single( | |||
| 69 | char __user *buffer, | 69 | char __user *buffer, |
| 70 | int *done); | 70 | int *done); |
| 71 | 71 | ||
| 72 | typedef int (*bulkstat_one_fmt_pf)( /* used size in bytes or negative error */ | ||
| 73 | void __user *ubuffer, /* buffer to write to */ | ||
| 74 | const xfs_bstat_t *buffer); /* buffer to read from */ | ||
| 75 | |||
| 72 | int | 76 | int |
| 73 | xfs_bulkstat_one( | 77 | xfs_bulkstat_one( |
| 74 | xfs_mount_t *mp, | 78 | xfs_mount_t *mp, |
| @@ -86,11 +90,25 @@ xfs_internal_inum( | |||
| 86 | xfs_mount_t *mp, | 90 | xfs_mount_t *mp, |
| 87 | xfs_ino_t ino); | 91 | xfs_ino_t ino); |
| 88 | 92 | ||
| 93 | typedef int (*inumbers_fmt_pf)( | ||
| 94 | void __user *ubuffer, /* buffer to write to */ | ||
| 95 | const xfs_inogrp_t *buffer, /* buffer to read from */ | ||
| 96 | long count, /* # of elements to read */ | ||
| 97 | long *written); /* # of bytes written */ | ||
| 98 | |||
| 99 | int | ||
| 100 | xfs_inumbers_fmt( | ||
| 101 | void __user *ubuffer, /* buffer to write to */ | ||
| 102 | const xfs_inogrp_t *buffer, /* buffer to read from */ | ||
| 103 | long count, /* # of elements to read */ | ||
| 104 | long *written); /* # of bytes written */ | ||
| 105 | |||
| 89 | int /* error status */ | 106 | int /* error status */ |
| 90 | xfs_inumbers( | 107 | xfs_inumbers( |
| 91 | xfs_mount_t *mp, /* mount point for filesystem */ | 108 | xfs_mount_t *mp, /* mount point for filesystem */ |
| 92 | xfs_ino_t *last, /* last inode returned */ | 109 | xfs_ino_t *last, /* last inode returned */ |
| 93 | int *count, /* size of buffer/count returned */ | 110 | int *count, /* size of buffer/count returned */ |
| 94 | xfs_inogrp_t __user *buffer);/* buffer with inode info */ | 111 | void __user *buffer, /* buffer with inode info */ |
| 112 | inumbers_fmt_pf formatter); | ||
| 95 | 113 | ||
| 96 | #endif /* __XFS_ITABLE_H__ */ | 114 | #endif /* __XFS_ITABLE_H__ */ |
