diff options
author | Jie Liu <jeff.liu@oracle.com> | 2014-08-03 21:22:31 -0400 |
---|---|---|
committer | Dave Chinner <david@fromorbit.com> | 2014-08-03 21:22:31 -0400 |
commit | 1e773c4989d2dfe08332b4c18f7e1d7ad633015c (patch) | |
tree | 1bbc729141d2aa5be746e34a701668bc272285e7 /fs/xfs | |
parent | f3d1e587437b784635459dcfccaedd17149282cc (diff) |
xfs: introduce xfs_bulkstat_ag_ichunk
Introduce xfs_bulkstat_ag_ichunk() to process inodes in chunk with a
pointer to a formatter function that will iget the inode and fill in
the appropriate structure.
Refactor xfs_bulkstat() with it.
Signed-off-by: Jie Liu <jeff.liu@oracle.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r-- | fs/xfs/xfs_itable.c | 141 | ||||
-rw-r--r-- | fs/xfs/xfs_itable.h | 16 |
2 files changed, 103 insertions, 54 deletions
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c index 32cf52ee33bc..f71be9c68017 100644 --- a/fs/xfs/xfs_itable.c +++ b/fs/xfs/xfs_itable.c | |||
@@ -263,6 +263,79 @@ xfs_bulkstat_grab_ichunk( | |||
263 | #define XFS_BULKSTAT_UBLEFT(ubleft) ((ubleft) >= statstruct_size) | 263 | #define XFS_BULKSTAT_UBLEFT(ubleft) ((ubleft) >= statstruct_size) |
264 | 264 | ||
265 | /* | 265 | /* |
266 | * Process inodes in chunk with a pointer to a formatter function | ||
267 | * that will iget the inode and fill in the appropriate structure. | ||
268 | */ | ||
269 | int | ||
270 | xfs_bulkstat_ag_ichunk( | ||
271 | struct xfs_mount *mp, | ||
272 | xfs_agnumber_t agno, | ||
273 | struct xfs_inobt_rec_incore *irbp, | ||
274 | bulkstat_one_pf formatter, | ||
275 | size_t statstruct_size, | ||
276 | struct xfs_bulkstat_agichunk *acp) | ||
277 | { | ||
278 | xfs_ino_t lastino = acp->ac_lastino; | ||
279 | char __user **ubufp = acp->ac_ubuffer; | ||
280 | int ubleft = acp->ac_ubleft; | ||
281 | int ubelem = acp->ac_ubelem; | ||
282 | int chunkidx, clustidx; | ||
283 | int error = 0; | ||
284 | xfs_agino_t agino; | ||
285 | |||
286 | for (agino = irbp->ir_startino, chunkidx = clustidx = 0; | ||
287 | XFS_BULKSTAT_UBLEFT(ubleft) && | ||
288 | irbp->ir_freecount < XFS_INODES_PER_CHUNK; | ||
289 | chunkidx++, clustidx++, agino++) { | ||
290 | int fmterror; /* bulkstat formatter result */ | ||
291 | int ubused; | ||
292 | xfs_ino_t ino = XFS_AGINO_TO_INO(mp, agno, agino); | ||
293 | |||
294 | ASSERT(chunkidx < XFS_INODES_PER_CHUNK); | ||
295 | |||
296 | /* Skip if this inode is free */ | ||
297 | if (XFS_INOBT_MASK(chunkidx) & irbp->ir_free) { | ||
298 | lastino = ino; | ||
299 | continue; | ||
300 | } | ||
301 | |||
302 | /* | ||
303 | * Count used inodes as free so we can tell when the | ||
304 | * chunk is used up. | ||
305 | */ | ||
306 | irbp->ir_freecount++; | ||
307 | |||
308 | /* Get the inode and fill in a single buffer */ | ||
309 | ubused = statstruct_size; | ||
310 | error = formatter(mp, ino, *ubufp, ubleft, &ubused, &fmterror); | ||
311 | if (fmterror == BULKSTAT_RV_NOTHING) { | ||
312 | if (error && error != -ENOENT && error != -EINVAL) { | ||
313 | ubleft = 0; | ||
314 | break; | ||
315 | } | ||
316 | lastino = ino; | ||
317 | continue; | ||
318 | } | ||
319 | if (fmterror == BULKSTAT_RV_GIVEUP) { | ||
320 | ubleft = 0; | ||
321 | ASSERT(error); | ||
322 | break; | ||
323 | } | ||
324 | if (*ubufp) | ||
325 | *ubufp += ubused; | ||
326 | ubleft -= ubused; | ||
327 | ubelem++; | ||
328 | lastino = ino; | ||
329 | } | ||
330 | |||
331 | acp->ac_lastino = lastino; | ||
332 | acp->ac_ubleft = ubleft; | ||
333 | acp->ac_ubelem = ubelem; | ||
334 | |||
335 | return error; | ||
336 | } | ||
337 | |||
338 | /* | ||
266 | * Return stat information in bulk (by-inode) for the filesystem. | 339 | * Return stat information in bulk (by-inode) for the filesystem. |
267 | */ | 340 | */ |
268 | int /* error status */ | 341 | int /* error status */ |
@@ -279,8 +352,6 @@ xfs_bulkstat( | |||
279 | xfs_agi_t *agi; /* agi header data */ | 352 | xfs_agi_t *agi; /* agi header data */ |
280 | xfs_agino_t agino; /* inode # in allocation group */ | 353 | xfs_agino_t agino; /* inode # in allocation group */ |
281 | xfs_agnumber_t agno; /* allocation group number */ | 354 | xfs_agnumber_t agno; /* allocation group number */ |
282 | int chunkidx; /* current index into inode chunk */ | ||
283 | int clustidx; /* current index into inode cluster */ | ||
284 | xfs_btree_cur_t *cur; /* btree cursor for ialloc btree */ | 355 | xfs_btree_cur_t *cur; /* btree cursor for ialloc btree */ |
285 | int end_of_ag; /* set if we've seen the ag end */ | 356 | int end_of_ag; /* set if we've seen the ag end */ |
286 | int error; /* error code */ | 357 | int error; /* error code */ |
@@ -300,7 +371,6 @@ xfs_bulkstat( | |||
300 | int ubleft; /* bytes left in user's buffer */ | 371 | int ubleft; /* bytes left in user's buffer */ |
301 | char __user *ubufp; /* pointer into user's buffer */ | 372 | char __user *ubufp; /* pointer into user's buffer */ |
302 | int ubelem; /* spaces used in user's buffer */ | 373 | int ubelem; /* spaces used in user's buffer */ |
303 | int ubused; /* bytes used by formatter */ | ||
304 | 374 | ||
305 | /* | 375 | /* |
306 | * Get the last inode value, see if there's nothing to do. | 376 | * Get the last inode value, see if there's nothing to do. |
@@ -419,57 +489,20 @@ xfs_bulkstat( | |||
419 | irbufend = irbp; | 489 | irbufend = irbp; |
420 | for (irbp = irbuf; | 490 | for (irbp = irbuf; |
421 | irbp < irbufend && XFS_BULKSTAT_UBLEFT(ubleft); irbp++) { | 491 | irbp < irbufend && XFS_BULKSTAT_UBLEFT(ubleft); irbp++) { |
422 | /* | 492 | struct xfs_bulkstat_agichunk ac; |
423 | * Now process this chunk of inodes. | 493 | |
424 | */ | 494 | ac.ac_lastino = lastino; |
425 | for (agino = irbp->ir_startino, chunkidx = clustidx = 0; | 495 | ac.ac_ubuffer = &ubuffer; |
426 | XFS_BULKSTAT_UBLEFT(ubleft) && | 496 | ac.ac_ubleft = ubleft; |
427 | irbp->ir_freecount < XFS_INODES_PER_CHUNK; | 497 | ac.ac_ubelem = ubelem; |
428 | chunkidx++, clustidx++, agino++) { | 498 | error = xfs_bulkstat_ag_ichunk(mp, agno, irbp, |
429 | ASSERT(chunkidx < XFS_INODES_PER_CHUNK); | 499 | formatter, statstruct_size, &ac); |
430 | 500 | if (error) | |
431 | ino = XFS_AGINO_TO_INO(mp, agno, agino); | 501 | rval = error; |
432 | /* | 502 | |
433 | * Skip if this inode is free. | 503 | lastino = ac.ac_lastino; |
434 | */ | 504 | ubleft = ac.ac_ubleft; |
435 | if (XFS_INOBT_MASK(chunkidx) & irbp->ir_free) { | 505 | ubelem = ac.ac_ubelem; |
436 | lastino = ino; | ||
437 | continue; | ||
438 | } | ||
439 | /* | ||
440 | * Count used inodes as free so we can tell | ||
441 | * when the chunk is used up. | ||
442 | */ | ||
443 | irbp->ir_freecount++; | ||
444 | |||
445 | /* | ||
446 | * Get the inode and fill in a single buffer. | ||
447 | */ | ||
448 | ubused = statstruct_size; | ||
449 | error = formatter(mp, ino, ubufp, ubleft, | ||
450 | &ubused, &fmterror); | ||
451 | if (fmterror == BULKSTAT_RV_NOTHING) { | ||
452 | if (error && error != -ENOENT && | ||
453 | error != -EINVAL) { | ||
454 | ubleft = 0; | ||
455 | rval = error; | ||
456 | break; | ||
457 | } | ||
458 | lastino = ino; | ||
459 | continue; | ||
460 | } | ||
461 | if (fmterror == BULKSTAT_RV_GIVEUP) { | ||
462 | ubleft = 0; | ||
463 | ASSERT(error); | ||
464 | rval = error; | ||
465 | break; | ||
466 | } | ||
467 | if (ubufp) | ||
468 | ubufp += ubused; | ||
469 | ubleft -= ubused; | ||
470 | ubelem++; | ||
471 | lastino = ino; | ||
472 | } | ||
473 | 506 | ||
474 | cond_resched(); | 507 | cond_resched(); |
475 | } | 508 | } |
diff --git a/fs/xfs/xfs_itable.h b/fs/xfs/xfs_itable.h index 6ea8b3912fa4..aaed08022eb9 100644 --- a/fs/xfs/xfs_itable.h +++ b/fs/xfs/xfs_itable.h | |||
@@ -30,6 +30,22 @@ typedef int (*bulkstat_one_pf)(struct xfs_mount *mp, | |||
30 | int *ubused, | 30 | int *ubused, |
31 | int *stat); | 31 | int *stat); |
32 | 32 | ||
33 | struct xfs_bulkstat_agichunk { | ||
34 | xfs_ino_t ac_lastino; /* last inode returned */ | ||
35 | char __user **ac_ubuffer;/* pointer into user's buffer */ | ||
36 | int ac_ubleft; /* bytes left in user's buffer */ | ||
37 | int ac_ubelem; /* spaces used in user's buffer */ | ||
38 | }; | ||
39 | |||
40 | int | ||
41 | xfs_bulkstat_ag_ichunk( | ||
42 | struct xfs_mount *mp, | ||
43 | xfs_agnumber_t agno, | ||
44 | struct xfs_inobt_rec_incore *irbp, | ||
45 | bulkstat_one_pf formatter, | ||
46 | size_t statstruct_size, | ||
47 | struct xfs_bulkstat_agichunk *acp); | ||
48 | |||
33 | /* | 49 | /* |
34 | * Values for stat return value. | 50 | * Values for stat return value. |
35 | */ | 51 | */ |