diff options
author | Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> | 2010-08-25 04:45:44 -0400 |
---|---|---|
committer | Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> | 2010-10-22 20:24:34 -0400 |
commit | 4d8d9293dce503eb0e083e17a02a328d397e7f00 (patch) | |
tree | ffa2dce7f100b1346131adc01cf93e280b225509 /fs/nilfs2 | |
parent | ba65ae4729bf81c58d9fc847f67d57eec525b042 (diff) |
nilfs2: set pointer to root object in inodes
This puts a pointer to nilfs_root object in the private part of
on-memory inode, and makes nilfs_iget function pick up the inode with
the same root object.
Non-root inodes inherit its nilfs_root object from parent inode. That
of the root inode is allocated through nilfs_attach_checkpoint()
function.
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Diffstat (limited to 'fs/nilfs2')
-rw-r--r-- | fs/nilfs2/inode.c | 27 | ||||
-rw-r--r-- | fs/nilfs2/namei.c | 5 | ||||
-rw-r--r-- | fs/nilfs2/nilfs.h | 7 | ||||
-rw-r--r-- | fs/nilfs2/recovery.c | 12 | ||||
-rw-r--r-- | fs/nilfs2/super.c | 37 |
5 files changed, 68 insertions, 20 deletions
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index 82cfdbc43e1c..7306fc7c4962 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c | |||
@@ -37,6 +37,7 @@ | |||
37 | struct nilfs_iget_args { | 37 | struct nilfs_iget_args { |
38 | u64 ino; | 38 | u64 ino; |
39 | __u64 cno; | 39 | __u64 cno; |
40 | struct nilfs_root *root; | ||
40 | int for_gc; | 41 | int for_gc; |
41 | }; | 42 | }; |
42 | 43 | ||
@@ -284,6 +285,7 @@ struct inode *nilfs_new_inode(struct inode *dir, int mode) | |||
284 | struct nilfs_sb_info *sbi = NILFS_SB(sb); | 285 | struct nilfs_sb_info *sbi = NILFS_SB(sb); |
285 | struct inode *inode; | 286 | struct inode *inode; |
286 | struct nilfs_inode_info *ii; | 287 | struct nilfs_inode_info *ii; |
288 | struct nilfs_root *root; | ||
287 | int err = -ENOMEM; | 289 | int err = -ENOMEM; |
288 | ino_t ino; | 290 | ino_t ino; |
289 | 291 | ||
@@ -294,8 +296,10 @@ struct inode *nilfs_new_inode(struct inode *dir, int mode) | |||
294 | mapping_set_gfp_mask(inode->i_mapping, | 296 | mapping_set_gfp_mask(inode->i_mapping, |
295 | mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS); | 297 | mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS); |
296 | 298 | ||
299 | root = NILFS_I(dir)->i_root; | ||
297 | ii = NILFS_I(inode); | 300 | ii = NILFS_I(inode); |
298 | ii->i_state = 1 << NILFS_I_NEW; | 301 | ii->i_state = 1 << NILFS_I_NEW; |
302 | ii->i_root = root; | ||
299 | 303 | ||
300 | err = nilfs_ifile_create_inode(sbi->s_ifile, &ino, &ii->i_bh); | 304 | err = nilfs_ifile_create_inode(sbi->s_ifile, &ino, &ii->i_bh); |
301 | if (unlikely(err)) | 305 | if (unlikely(err)) |
@@ -484,7 +488,7 @@ static int nilfs_iget_test(struct inode *inode, void *opaque) | |||
484 | struct nilfs_iget_args *args = opaque; | 488 | struct nilfs_iget_args *args = opaque; |
485 | struct nilfs_inode_info *ii; | 489 | struct nilfs_inode_info *ii; |
486 | 490 | ||
487 | if (args->ino != inode->i_ino) | 491 | if (args->ino != inode->i_ino || args->root != NILFS_I(inode)->i_root) |
488 | return 0; | 492 | return 0; |
489 | 493 | ||
490 | ii = NILFS_I(inode); | 494 | ii = NILFS_I(inode); |
@@ -502,13 +506,21 @@ static int nilfs_iget_set(struct inode *inode, void *opaque) | |||
502 | if (args->for_gc) { | 506 | if (args->for_gc) { |
503 | NILFS_I(inode)->i_state = 1 << NILFS_I_GCINODE; | 507 | NILFS_I(inode)->i_state = 1 << NILFS_I_GCINODE; |
504 | NILFS_I(inode)->i_cno = args->cno; | 508 | NILFS_I(inode)->i_cno = args->cno; |
509 | NILFS_I(inode)->i_root = NULL; | ||
510 | } else { | ||
511 | if (args->root && args->ino == NILFS_ROOT_INO) | ||
512 | nilfs_get_root(args->root); | ||
513 | NILFS_I(inode)->i_root = args->root; | ||
505 | } | 514 | } |
506 | return 0; | 515 | return 0; |
507 | } | 516 | } |
508 | 517 | ||
509 | struct inode *nilfs_iget(struct super_block *sb, unsigned long ino) | 518 | struct inode *nilfs_iget(struct super_block *sb, struct nilfs_root *root, |
519 | unsigned long ino) | ||
510 | { | 520 | { |
511 | struct nilfs_iget_args args = { .ino = ino, .cno = 0, .for_gc = 0 }; | 521 | struct nilfs_iget_args args = { |
522 | .ino = ino, .root = root, .cno = 0, .for_gc = 0 | ||
523 | }; | ||
512 | struct inode *inode; | 524 | struct inode *inode; |
513 | int err; | 525 | int err; |
514 | 526 | ||
@@ -530,7 +542,9 @@ struct inode *nilfs_iget(struct super_block *sb, unsigned long ino) | |||
530 | struct inode *nilfs_iget_for_gc(struct super_block *sb, unsigned long ino, | 542 | struct inode *nilfs_iget_for_gc(struct super_block *sb, unsigned long ino, |
531 | __u64 cno) | 543 | __u64 cno) |
532 | { | 544 | { |
533 | struct nilfs_iget_args args = { .ino = ino, .cno = cno, .for_gc = 1 }; | 545 | struct nilfs_iget_args args = { |
546 | .ino = ino, .root = NULL, .cno = cno, .for_gc = 1 | ||
547 | }; | ||
534 | struct inode *inode; | 548 | struct inode *inode; |
535 | int err; | 549 | int err; |
536 | 550 | ||
@@ -682,6 +696,9 @@ static void nilfs_clear_inode(struct inode *inode) | |||
682 | nilfs_bmap_clear(ii->i_bmap); | 696 | nilfs_bmap_clear(ii->i_bmap); |
683 | 697 | ||
684 | nilfs_btnode_cache_clear(&ii->i_btnode_cache); | 698 | nilfs_btnode_cache_clear(&ii->i_btnode_cache); |
699 | |||
700 | if (ii->i_root && inode->i_ino == NILFS_ROOT_INO) | ||
701 | nilfs_put_root(ii->i_root); | ||
685 | } | 702 | } |
686 | 703 | ||
687 | void nilfs_evict_inode(struct inode *inode) | 704 | void nilfs_evict_inode(struct inode *inode) |
@@ -690,7 +707,7 @@ void nilfs_evict_inode(struct inode *inode) | |||
690 | struct super_block *sb = inode->i_sb; | 707 | struct super_block *sb = inode->i_sb; |
691 | struct nilfs_inode_info *ii = NILFS_I(inode); | 708 | struct nilfs_inode_info *ii = NILFS_I(inode); |
692 | 709 | ||
693 | if (inode->i_nlink || unlikely(is_bad_inode(inode))) { | 710 | if (inode->i_nlink || !ii->i_root || unlikely(is_bad_inode(inode))) { |
694 | if (inode->i_data.nrpages) | 711 | if (inode->i_data.nrpages) |
695 | truncate_inode_pages(&inode->i_data, 0); | 712 | truncate_inode_pages(&inode->i_data, 0); |
696 | end_writeback(inode); | 713 | end_writeback(inode); |
diff --git a/fs/nilfs2/namei.c b/fs/nilfs2/namei.c index ad6ed2cf19b4..1110d56a23f5 100644 --- a/fs/nilfs2/namei.c +++ b/fs/nilfs2/namei.c | |||
@@ -70,7 +70,7 @@ nilfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | |||
70 | ino = nilfs_inode_by_name(dir, &dentry->d_name); | 70 | ino = nilfs_inode_by_name(dir, &dentry->d_name); |
71 | inode = NULL; | 71 | inode = NULL; |
72 | if (ino) { | 72 | if (ino) { |
73 | inode = nilfs_iget(dir->i_sb, ino); | 73 | inode = nilfs_iget(dir->i_sb, NILFS_I(dir)->i_root, ino); |
74 | if (IS_ERR(inode)) | 74 | if (IS_ERR(inode)) |
75 | return ERR_CAST(inode); | 75 | return ERR_CAST(inode); |
76 | } | 76 | } |
@@ -87,7 +87,8 @@ struct dentry *nilfs_get_parent(struct dentry *child) | |||
87 | if (!ino) | 87 | if (!ino) |
88 | return ERR_PTR(-ENOENT); | 88 | return ERR_PTR(-ENOENT); |
89 | 89 | ||
90 | inode = nilfs_iget(child->d_inode->i_sb, ino); | 90 | inode = nilfs_iget(child->d_inode->i_sb, |
91 | NILFS_I(child->d_inode)->i_root, ino); | ||
91 | if (IS_ERR(inode)) | 92 | if (IS_ERR(inode)) |
92 | return ERR_CAST(inode); | 93 | return ERR_CAST(inode); |
93 | return d_obtain_alias(inode); | 94 | return d_obtain_alias(inode); |
diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h index 797cd437970e..21d90c4b4e2d 100644 --- a/fs/nilfs2/nilfs.h +++ b/fs/nilfs2/nilfs.h | |||
@@ -59,6 +59,7 @@ struct nilfs_inode_info { | |||
59 | #endif | 59 | #endif |
60 | struct buffer_head *i_bh; /* i_bh contains a new or dirty | 60 | struct buffer_head *i_bh; /* i_bh contains a new or dirty |
61 | disk inode */ | 61 | disk inode */ |
62 | struct nilfs_root *i_root; | ||
62 | struct inode vfs_inode; | 63 | struct inode vfs_inode; |
63 | }; | 64 | }; |
64 | 65 | ||
@@ -247,7 +248,8 @@ extern int nilfs_get_block(struct inode *, sector_t, struct buffer_head *, int); | |||
247 | extern void nilfs_set_inode_flags(struct inode *); | 248 | extern void nilfs_set_inode_flags(struct inode *); |
248 | extern int nilfs_read_inode_common(struct inode *, struct nilfs_inode *); | 249 | extern int nilfs_read_inode_common(struct inode *, struct nilfs_inode *); |
249 | extern void nilfs_write_inode_common(struct inode *, struct nilfs_inode *, int); | 250 | extern void nilfs_write_inode_common(struct inode *, struct nilfs_inode *, int); |
250 | extern struct inode *nilfs_iget(struct super_block *, unsigned long); | 251 | struct inode *nilfs_iget(struct super_block *sb, struct nilfs_root *root, |
252 | unsigned long ino); | ||
251 | extern struct inode *nilfs_iget_for_gc(struct super_block *sb, | 253 | extern struct inode *nilfs_iget_for_gc(struct super_block *sb, |
252 | unsigned long ino, __u64 cno); | 254 | unsigned long ino, __u64 cno); |
253 | extern void nilfs_update_inode(struct inode *, struct buffer_head *); | 255 | extern void nilfs_update_inode(struct inode *, struct buffer_head *); |
@@ -285,7 +287,8 @@ extern struct nilfs_super_block **nilfs_prepare_super(struct nilfs_sb_info *, | |||
285 | int flip); | 287 | int flip); |
286 | extern int nilfs_commit_super(struct nilfs_sb_info *, int); | 288 | extern int nilfs_commit_super(struct nilfs_sb_info *, int); |
287 | extern int nilfs_cleanup_super(struct nilfs_sb_info *); | 289 | extern int nilfs_cleanup_super(struct nilfs_sb_info *); |
288 | extern int nilfs_attach_checkpoint(struct nilfs_sb_info *, __u64); | 290 | int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno, int curr_mnt, |
291 | struct nilfs_root **root); | ||
289 | extern void nilfs_detach_checkpoint(struct nilfs_sb_info *); | 292 | extern void nilfs_detach_checkpoint(struct nilfs_sb_info *); |
290 | 293 | ||
291 | /* gcinode.c */ | 294 | /* gcinode.c */ |
diff --git a/fs/nilfs2/recovery.c b/fs/nilfs2/recovery.c index d0c35ef39f6a..a9a5ba8f57d5 100644 --- a/fs/nilfs2/recovery.c +++ b/fs/nilfs2/recovery.c | |||
@@ -504,6 +504,7 @@ static int nilfs_recovery_copy_block(struct the_nilfs *nilfs, | |||
504 | 504 | ||
505 | static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs, | 505 | static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs, |
506 | struct nilfs_sb_info *sbi, | 506 | struct nilfs_sb_info *sbi, |
507 | struct nilfs_root *root, | ||
507 | struct list_head *head, | 508 | struct list_head *head, |
508 | unsigned long *nr_salvaged_blocks) | 509 | unsigned long *nr_salvaged_blocks) |
509 | { | 510 | { |
@@ -515,7 +516,7 @@ static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs, | |||
515 | int err = 0, err2 = 0; | 516 | int err = 0, err2 = 0; |
516 | 517 | ||
517 | list_for_each_entry_safe(rb, n, head, list) { | 518 | list_for_each_entry_safe(rb, n, head, list) { |
518 | inode = nilfs_iget(sbi->s_super, rb->ino); | 519 | inode = nilfs_iget(sbi->s_super, root, rb->ino); |
519 | if (IS_ERR(inode)) { | 520 | if (IS_ERR(inode)) { |
520 | err = PTR_ERR(inode); | 521 | err = PTR_ERR(inode); |
521 | inode = NULL; | 522 | inode = NULL; |
@@ -578,6 +579,7 @@ static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs, | |||
578 | */ | 579 | */ |
579 | static int nilfs_do_roll_forward(struct the_nilfs *nilfs, | 580 | static int nilfs_do_roll_forward(struct the_nilfs *nilfs, |
580 | struct nilfs_sb_info *sbi, | 581 | struct nilfs_sb_info *sbi, |
582 | struct nilfs_root *root, | ||
581 | struct nilfs_recovery_info *ri) | 583 | struct nilfs_recovery_info *ri) |
582 | { | 584 | { |
583 | struct buffer_head *bh_sum = NULL; | 585 | struct buffer_head *bh_sum = NULL; |
@@ -649,7 +651,7 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs, | |||
649 | goto failed; | 651 | goto failed; |
650 | if (flags & NILFS_SS_LOGEND) { | 652 | if (flags & NILFS_SS_LOGEND) { |
651 | err = nilfs_recover_dsync_blocks( | 653 | err = nilfs_recover_dsync_blocks( |
652 | nilfs, sbi, &dsync_blocks, | 654 | nilfs, sbi, root, &dsync_blocks, |
653 | &nsalvaged_blocks); | 655 | &nsalvaged_blocks); |
654 | if (unlikely(err)) | 656 | if (unlikely(err)) |
655 | goto failed; | 657 | goto failed; |
@@ -746,19 +748,20 @@ int nilfs_salvage_orphan_logs(struct the_nilfs *nilfs, | |||
746 | struct nilfs_sb_info *sbi, | 748 | struct nilfs_sb_info *sbi, |
747 | struct nilfs_recovery_info *ri) | 749 | struct nilfs_recovery_info *ri) |
748 | { | 750 | { |
751 | struct nilfs_root *root; | ||
749 | int err; | 752 | int err; |
750 | 753 | ||
751 | if (ri->ri_lsegs_start == 0 || ri->ri_lsegs_end == 0) | 754 | if (ri->ri_lsegs_start == 0 || ri->ri_lsegs_end == 0) |
752 | return 0; | 755 | return 0; |
753 | 756 | ||
754 | err = nilfs_attach_checkpoint(sbi, ri->ri_cno); | 757 | err = nilfs_attach_checkpoint(sbi, ri->ri_cno, true, &root); |
755 | if (unlikely(err)) { | 758 | if (unlikely(err)) { |
756 | printk(KERN_ERR | 759 | printk(KERN_ERR |
757 | "NILFS: error loading the latest checkpoint.\n"); | 760 | "NILFS: error loading the latest checkpoint.\n"); |
758 | return err; | 761 | return err; |
759 | } | 762 | } |
760 | 763 | ||
761 | err = nilfs_do_roll_forward(nilfs, sbi, ri); | 764 | err = nilfs_do_roll_forward(nilfs, sbi, root, ri); |
762 | if (unlikely(err)) | 765 | if (unlikely(err)) |
763 | goto failed; | 766 | goto failed; |
764 | 767 | ||
@@ -789,6 +792,7 @@ int nilfs_salvage_orphan_logs(struct the_nilfs *nilfs, | |||
789 | 792 | ||
790 | failed: | 793 | failed: |
791 | nilfs_detach_checkpoint(sbi); | 794 | nilfs_detach_checkpoint(sbi); |
795 | nilfs_put_root(root); | ||
792 | return err; | 796 | return err; |
793 | } | 797 | } |
794 | 798 | ||
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index f3a00a3b2a03..a1c0e38a7706 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c | |||
@@ -391,18 +391,24 @@ static int nilfs_sync_fs(struct super_block *sb, int wait) | |||
391 | return err; | 391 | return err; |
392 | } | 392 | } |
393 | 393 | ||
394 | int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno) | 394 | int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno, int curr_mnt, |
395 | struct nilfs_root **rootp) | ||
395 | { | 396 | { |
396 | struct the_nilfs *nilfs = sbi->s_nilfs; | 397 | struct the_nilfs *nilfs = sbi->s_nilfs; |
398 | struct nilfs_root *root; | ||
397 | struct nilfs_checkpoint *raw_cp; | 399 | struct nilfs_checkpoint *raw_cp; |
398 | struct buffer_head *bh_cp; | 400 | struct buffer_head *bh_cp; |
399 | int err; | 401 | int err = -ENOMEM; |
402 | |||
403 | root = nilfs_find_or_create_root( | ||
404 | nilfs, curr_mnt ? NILFS_CPTREE_CURRENT_CNO : cno); | ||
405 | if (!root) | ||
406 | return err; | ||
400 | 407 | ||
401 | down_write(&nilfs->ns_super_sem); | 408 | down_write(&nilfs->ns_super_sem); |
402 | list_add(&sbi->s_list, &nilfs->ns_supers); | 409 | list_add(&sbi->s_list, &nilfs->ns_supers); |
403 | up_write(&nilfs->ns_super_sem); | 410 | up_write(&nilfs->ns_super_sem); |
404 | 411 | ||
405 | err = -ENOMEM; | ||
406 | sbi->s_ifile = nilfs_ifile_new(sbi, nilfs->ns_inode_size); | 412 | sbi->s_ifile = nilfs_ifile_new(sbi, nilfs->ns_inode_size); |
407 | if (!sbi->s_ifile) | 413 | if (!sbi->s_ifile) |
408 | goto delist; | 414 | goto delist; |
@@ -428,6 +434,8 @@ int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno) | |||
428 | atomic_set(&sbi->s_blocks_count, le64_to_cpu(raw_cp->cp_blocks_count)); | 434 | atomic_set(&sbi->s_blocks_count, le64_to_cpu(raw_cp->cp_blocks_count)); |
429 | 435 | ||
430 | nilfs_cpfile_put_checkpoint(nilfs->ns_cpfile, cno, bh_cp); | 436 | nilfs_cpfile_put_checkpoint(nilfs->ns_cpfile, cno, bh_cp); |
437 | |||
438 | *rootp = root; | ||
431 | return 0; | 439 | return 0; |
432 | 440 | ||
433 | failed_bh: | 441 | failed_bh: |
@@ -440,6 +448,7 @@ int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno) | |||
440 | down_write(&nilfs->ns_super_sem); | 448 | down_write(&nilfs->ns_super_sem); |
441 | list_del_init(&sbi->s_list); | 449 | list_del_init(&sbi->s_list); |
442 | up_write(&nilfs->ns_super_sem); | 450 | up_write(&nilfs->ns_super_sem); |
451 | nilfs_put_root(root); | ||
443 | 452 | ||
444 | return err; | 453 | return err; |
445 | } | 454 | } |
@@ -551,12 +560,20 @@ static struct inode * | |||
551 | nilfs_nfs_get_inode(struct super_block *sb, u64 ino, u32 generation) | 560 | nilfs_nfs_get_inode(struct super_block *sb, u64 ino, u32 generation) |
552 | { | 561 | { |
553 | struct inode *inode; | 562 | struct inode *inode; |
563 | struct nilfs_root *root; | ||
554 | 564 | ||
555 | if (ino < NILFS_FIRST_INO(sb) && ino != NILFS_ROOT_INO && | 565 | if (ino < NILFS_FIRST_INO(sb) && ino != NILFS_ROOT_INO && |
556 | ino != NILFS_SKETCH_INO) | 566 | ino != NILFS_SKETCH_INO) |
557 | return ERR_PTR(-ESTALE); | 567 | return ERR_PTR(-ESTALE); |
558 | 568 | ||
559 | inode = nilfs_iget(sb, ino); | 569 | root = nilfs_lookup_root(NILFS_SB(sb)->s_nilfs, |
570 | NILFS_CPTREE_CURRENT_CNO); | ||
571 | if (!root) | ||
572 | return ERR_PTR(-ESTALE); | ||
573 | |||
574 | /* new file handle type is required to export snapshots */ | ||
575 | inode = nilfs_iget(sb, root, ino); | ||
576 | nilfs_put_root(root); | ||
560 | if (IS_ERR(inode)) | 577 | if (IS_ERR(inode)) |
561 | return ERR_CAST(inode); | 578 | return ERR_CAST(inode); |
562 | if (generation && inode->i_generation != generation) { | 579 | if (generation && inode->i_generation != generation) { |
@@ -815,9 +832,10 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent, | |||
815 | struct the_nilfs *nilfs) | 832 | struct the_nilfs *nilfs) |
816 | { | 833 | { |
817 | struct nilfs_sb_info *sbi; | 834 | struct nilfs_sb_info *sbi; |
835 | struct nilfs_root *fsroot; | ||
818 | struct inode *root; | 836 | struct inode *root; |
819 | __u64 cno; | 837 | __u64 cno; |
820 | int err; | 838 | int err, curr_mnt; |
821 | 839 | ||
822 | sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); | 840 | sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); |
823 | if (!sbi) | 841 | if (!sbi) |
@@ -859,6 +877,7 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent, | |||
859 | goto failed_sbi; | 877 | goto failed_sbi; |
860 | 878 | ||
861 | cno = nilfs_last_cno(nilfs); | 879 | cno = nilfs_last_cno(nilfs); |
880 | curr_mnt = true; | ||
862 | 881 | ||
863 | if (sb->s_flags & MS_RDONLY) { | 882 | if (sb->s_flags & MS_RDONLY) { |
864 | if (nilfs_test_opt(sbi, SNAPSHOT)) { | 883 | if (nilfs_test_opt(sbi, SNAPSHOT)) { |
@@ -881,10 +900,11 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent, | |||
881 | goto failed_sbi; | 900 | goto failed_sbi; |
882 | } | 901 | } |
883 | cno = sbi->s_snapshot_cno; | 902 | cno = sbi->s_snapshot_cno; |
903 | curr_mnt = false; | ||
884 | } | 904 | } |
885 | } | 905 | } |
886 | 906 | ||
887 | err = nilfs_attach_checkpoint(sbi, cno); | 907 | err = nilfs_attach_checkpoint(sbi, cno, curr_mnt, &fsroot); |
888 | if (err) { | 908 | if (err) { |
889 | printk(KERN_ERR "NILFS: error loading a checkpoint" | 909 | printk(KERN_ERR "NILFS: error loading a checkpoint" |
890 | " (checkpoint number=%llu).\n", (unsigned long long)cno); | 910 | " (checkpoint number=%llu).\n", (unsigned long long)cno); |
@@ -897,7 +917,7 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent, | |||
897 | goto failed_checkpoint; | 917 | goto failed_checkpoint; |
898 | } | 918 | } |
899 | 919 | ||
900 | root = nilfs_iget(sb, NILFS_ROOT_INO); | 920 | root = nilfs_iget(sb, fsroot, NILFS_ROOT_INO); |
901 | if (IS_ERR(root)) { | 921 | if (IS_ERR(root)) { |
902 | printk(KERN_ERR "NILFS: get root inode failed\n"); | 922 | printk(KERN_ERR "NILFS: get root inode failed\n"); |
903 | err = PTR_ERR(root); | 923 | err = PTR_ERR(root); |
@@ -917,6 +937,8 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent, | |||
917 | goto failed_segctor; | 937 | goto failed_segctor; |
918 | } | 938 | } |
919 | 939 | ||
940 | nilfs_put_root(fsroot); | ||
941 | |||
920 | if (!(sb->s_flags & MS_RDONLY)) { | 942 | if (!(sb->s_flags & MS_RDONLY)) { |
921 | down_write(&nilfs->ns_sem); | 943 | down_write(&nilfs->ns_sem); |
922 | nilfs_setup_super(sbi); | 944 | nilfs_setup_super(sbi); |
@@ -935,6 +957,7 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent, | |||
935 | 957 | ||
936 | failed_checkpoint: | 958 | failed_checkpoint: |
937 | nilfs_detach_checkpoint(sbi); | 959 | nilfs_detach_checkpoint(sbi); |
960 | nilfs_put_root(fsroot); | ||
938 | 961 | ||
939 | failed_sbi: | 962 | failed_sbi: |
940 | put_nilfs(nilfs); | 963 | put_nilfs(nilfs); |