diff options
author | sandeen@sandeen.net <sandeen@sandeen.net> | 2008-11-25 22:20:12 -0500 |
---|---|---|
committer | Lachlan McIlroy <lachlan@redback.melbourne.sgi.com> | 2008-12-02 01:16:03 -0500 |
commit | 65fbaf2489c667bf79ae1f20403f30c66568d445 (patch) | |
tree | 9694dd8017f997730755dec5e58a2324361cf577 /fs/xfs/xfs_itable.c | |
parent | 2ee4fa5cb716eba104a4ef8efe159e1007a2aef6 (diff) |
[XFS] Fix xfs_bulkstat_one size checks & error handling
The 32-bit xfs_blkstat_one handler was failing because
a size check checked whether the remaining (32-bit)
user buffer was less than the (64-bit) bulkstat buffer,
and failed with ENOMEM if so. Move this check
into the respective handlers so that they check the
correct sizes.
Also, the formatters were returning negative errors
or positive bytes copied; this was odd in the positive
error value world of xfs, and handled wrong by at least
some of the callers, which treated the bytes returned
as an error value. Move the bytes-used assignment
into the formatters.
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Lachlan McIlroy <lachlan@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_itable.c')
-rw-r--r-- | fs/xfs/xfs_itable.c | 21 |
1 files changed, 11 insertions, 10 deletions
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c index 7bd49b87160c..e19d0a8d5618 100644 --- a/fs/xfs/xfs_itable.c +++ b/fs/xfs/xfs_itable.c | |||
@@ -188,14 +188,21 @@ xfs_bulkstat_one_dinode( | |||
188 | } | 188 | } |
189 | } | 189 | } |
190 | 190 | ||
191 | /* Return 0 on success or positive error */ | ||
191 | STATIC int | 192 | STATIC int |
192 | xfs_bulkstat_one_fmt( | 193 | xfs_bulkstat_one_fmt( |
193 | void __user *ubuffer, | 194 | void __user *ubuffer, |
195 | int ubsize, | ||
196 | int *ubused, | ||
194 | const xfs_bstat_t *buffer) | 197 | const xfs_bstat_t *buffer) |
195 | { | 198 | { |
199 | if (ubsize < sizeof(*buffer)) | ||
200 | return XFS_ERROR(ENOMEM); | ||
196 | if (copy_to_user(ubuffer, buffer, sizeof(*buffer))) | 201 | if (copy_to_user(ubuffer, buffer, sizeof(*buffer))) |
197 | return -EFAULT; | 202 | return XFS_ERROR(EFAULT); |
198 | return sizeof(*buffer); | 203 | if (ubused) |
204 | *ubused = sizeof(*buffer); | ||
205 | return 0; | ||
199 | } | 206 | } |
200 | 207 | ||
201 | /* | 208 | /* |
@@ -223,8 +230,6 @@ xfs_bulkstat_one_int( | |||
223 | 230 | ||
224 | if (!buffer || xfs_internal_inum(mp, ino)) | 231 | if (!buffer || xfs_internal_inum(mp, ino)) |
225 | return XFS_ERROR(EINVAL); | 232 | return XFS_ERROR(EINVAL); |
226 | if (ubsize < sizeof(*buf)) | ||
227 | return XFS_ERROR(ENOMEM); | ||
228 | 233 | ||
229 | buf = kmem_alloc(sizeof(*buf), KM_SLEEP); | 234 | buf = kmem_alloc(sizeof(*buf), KM_SLEEP); |
230 | 235 | ||
@@ -239,15 +244,11 @@ xfs_bulkstat_one_int( | |||
239 | xfs_bulkstat_one_dinode(mp, ino, dip, buf); | 244 | xfs_bulkstat_one_dinode(mp, ino, dip, buf); |
240 | } | 245 | } |
241 | 246 | ||
242 | error = formatter(buffer, buf); | 247 | error = formatter(buffer, ubsize, ubused, buf); |
243 | if (error < 0) { | 248 | if (error) |
244 | error = EFAULT; | ||
245 | goto out_free; | 249 | goto out_free; |
246 | } | ||
247 | 250 | ||
248 | *stat = BULKSTAT_RV_DIDONE; | 251 | *stat = BULKSTAT_RV_DIDONE; |
249 | if (ubused) | ||
250 | *ubused = error; | ||
251 | 252 | ||
252 | out_free: | 253 | out_free: |
253 | kmem_free(buf); | 254 | kmem_free(buf); |