aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>2009-04-06 22:01:48 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-04-07 11:31:17 -0400
commit7fa10d20012296300dfe645cb3e628a4e9a0d5ef (patch)
treed3678ad2cbfb41624af0058b7de1ee2d48b7334c
parentb028fcfc4cd198a6aa1ffcfb872073ccc1db3459 (diff)
nilfs2: fix improper return values of nilfs_get_cpinfo ioctl
A few tool developers gave me requests for fixing inconvenient return value of nilfs_get_cpinfo() ioctl; if the requested mode is NILFS_SNAPSHOT and the specified start entry is not a snapshot, the ioctl unnaturally returns one as the number of acquired snapshot item. In addition, the ioctl function returns an ENOENT error for checkpoints within blocks deleted by garbage collection. These behaviors require corrections for programs which enumerate snapshots. This resolves the inconvenience by changing the return values to zero for the above cases. Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--fs/nilfs2/cpfile.c30
1 files changed, 18 insertions, 12 deletions
diff --git a/fs/nilfs2/cpfile.c b/fs/nilfs2/cpfile.c
index a4c9550fd774..50dff147744f 100644
--- a/fs/nilfs2/cpfile.c
+++ b/fs/nilfs2/cpfile.c
@@ -431,7 +431,7 @@ static ssize_t nilfs_cpfile_do_get_ssinfo(struct inode *cpfile, __u64 *cnop,
431 __u64 curr = *cnop, next; 431 __u64 curr = *cnop, next;
432 unsigned long curr_blkoff, next_blkoff; 432 unsigned long curr_blkoff, next_blkoff;
433 void *kaddr; 433 void *kaddr;
434 int n, ret; 434 int n = 0, ret;
435 435
436 down_read(&NILFS_MDT(cpfile)->mi_sem); 436 down_read(&NILFS_MDT(cpfile)->mi_sem);
437 437
@@ -455,27 +455,33 @@ static ssize_t nilfs_cpfile_do_get_ssinfo(struct inode *cpfile, __u64 *cnop,
455 455
456 curr_blkoff = nilfs_cpfile_get_blkoff(cpfile, curr); 456 curr_blkoff = nilfs_cpfile_get_blkoff(cpfile, curr);
457 ret = nilfs_cpfile_get_checkpoint_block(cpfile, curr, 0, &bh); 457 ret = nilfs_cpfile_get_checkpoint_block(cpfile, curr, 0, &bh);
458 if (ret < 0) 458 if (unlikely(ret < 0)) {
459 if (ret == -ENOENT)
460 ret = 0; /* No snapshots (started from a hole block) */
459 goto out; 461 goto out;
462 }
460 kaddr = kmap_atomic(bh->b_page, KM_USER0); 463 kaddr = kmap_atomic(bh->b_page, KM_USER0);
461 for (n = 0; n < nci; n++) { 464 while (n < nci) {
462 cp = nilfs_cpfile_block_get_checkpoint( 465 cp = nilfs_cpfile_block_get_checkpoint(cpfile, curr, bh, kaddr);
463 cpfile, curr, bh, kaddr); 466 curr = ~(__u64)0; /* Terminator */
464 nilfs_cpfile_checkpoint_to_cpinfo(cpfile, cp, &ci[n]); 467 if (unlikely(nilfs_checkpoint_invalid(cp) ||
465 next = le64_to_cpu(cp->cp_snapshot_list.ssl_next); 468 !nilfs_checkpoint_snapshot(cp)))
466 if (next == 0) {
467 curr = ~(__u64)0; /* Terminator */
468 n++;
469 break; 469 break;
470 } 470 nilfs_cpfile_checkpoint_to_cpinfo(cpfile, cp, &ci[n++]);
471 next = le64_to_cpu(cp->cp_snapshot_list.ssl_next);
472 if (next == 0)
473 break; /* reach end of the snapshot list */
474
471 next_blkoff = nilfs_cpfile_get_blkoff(cpfile, next); 475 next_blkoff = nilfs_cpfile_get_blkoff(cpfile, next);
472 if (curr_blkoff != next_blkoff) { 476 if (curr_blkoff != next_blkoff) {
473 kunmap_atomic(kaddr, KM_USER0); 477 kunmap_atomic(kaddr, KM_USER0);
474 brelse(bh); 478 brelse(bh);
475 ret = nilfs_cpfile_get_checkpoint_block(cpfile, next, 479 ret = nilfs_cpfile_get_checkpoint_block(cpfile, next,
476 0, &bh); 480 0, &bh);
477 if (ret < 0) 481 if (unlikely(ret < 0)) {
482 WARN_ON(ret == -ENOENT);
478 goto out; 483 goto out;
484 }
479 kaddr = kmap_atomic(bh->b_page, KM_USER0); 485 kaddr = kmap_atomic(bh->b_page, KM_USER0);
480 } 486 }
481 curr = next; 487 curr = next;