diff options
Diffstat (limited to 'fs/nilfs2')
-rw-r--r-- | fs/nilfs2/cpfile.c | 30 |
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; |