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 /fs/xfs/xfs_itable.c | |
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>
Diffstat (limited to 'fs/xfs/xfs_itable.c')
-rw-r--r-- | fs/xfs/xfs_itable.c | 42 |
1 files changed, 34 insertions, 8 deletions
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; |