diff options
Diffstat (limited to 'fs/nilfs2/super.c')
-rw-r--r-- | fs/nilfs2/super.c | 42 |
1 files changed, 17 insertions, 25 deletions
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 5a8c5e4731b3..1d1b6e125159 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c | |||
@@ -336,7 +336,7 @@ static void nilfs_put_super(struct super_block *sb) | |||
336 | put_nilfs(sbi->s_nilfs); | 336 | put_nilfs(sbi->s_nilfs); |
337 | sbi->s_super = NULL; | 337 | sbi->s_super = NULL; |
338 | sb->s_fs_info = NULL; | 338 | sb->s_fs_info = NULL; |
339 | kfree(sbi); | 339 | nilfs_put_sbinfo(sbi); |
340 | 340 | ||
341 | unlock_kernel(); | 341 | unlock_kernel(); |
342 | } | 342 | } |
@@ -785,6 +785,7 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent, | |||
785 | get_nilfs(nilfs); | 785 | get_nilfs(nilfs); |
786 | sbi->s_nilfs = nilfs; | 786 | sbi->s_nilfs = nilfs; |
787 | sbi->s_super = sb; | 787 | sbi->s_super = sb; |
788 | atomic_set(&sbi->s_count, 1); | ||
788 | 789 | ||
789 | err = init_nilfs(nilfs, sbi, (char *)data); | 790 | err = init_nilfs(nilfs, sbi, (char *)data); |
790 | if (err) | 791 | if (err) |
@@ -902,7 +903,7 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent, | |||
902 | failed_sbi: | 903 | failed_sbi: |
903 | put_nilfs(nilfs); | 904 | put_nilfs(nilfs); |
904 | sb->s_fs_info = NULL; | 905 | sb->s_fs_info = NULL; |
905 | kfree(sbi); | 906 | nilfs_put_sbinfo(sbi); |
906 | return err; | 907 | return err; |
907 | } | 908 | } |
908 | 909 | ||
@@ -1014,6 +1015,7 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) | |||
1014 | 1015 | ||
1015 | struct nilfs_super_data { | 1016 | struct nilfs_super_data { |
1016 | struct block_device *bdev; | 1017 | struct block_device *bdev; |
1018 | struct nilfs_sb_info *sbi; | ||
1017 | __u64 cno; | 1019 | __u64 cno; |
1018 | int flags; | 1020 | int flags; |
1019 | }; | 1021 | }; |
@@ -1071,27 +1073,8 @@ static int nilfs_set_bdev_super(struct super_block *s, void *data) | |||
1071 | static int nilfs_test_bdev_super(struct super_block *s, void *data) | 1073 | static int nilfs_test_bdev_super(struct super_block *s, void *data) |
1072 | { | 1074 | { |
1073 | struct nilfs_super_data *sd = data; | 1075 | struct nilfs_super_data *sd = data; |
1074 | int ret; | 1076 | |
1075 | 1077 | return sd->sbi && s->s_fs_info == (void *)sd->sbi; | |
1076 | if (s->s_bdev != sd->bdev) | ||
1077 | return 0; | ||
1078 | |||
1079 | if (!((s->s_flags | sd->flags) & MS_RDONLY)) | ||
1080 | return 1; /* Reuse an old R/W-mode super_block */ | ||
1081 | |||
1082 | if (s->s_flags & sd->flags & MS_RDONLY) { | ||
1083 | if (down_read_trylock(&s->s_umount)) { | ||
1084 | ret = s->s_root && | ||
1085 | (sd->cno == NILFS_SB(s)->s_snapshot_cno); | ||
1086 | up_read(&s->s_umount); | ||
1087 | /* | ||
1088 | * This path is locked with sb_lock by sget(). | ||
1089 | * So, drop_super() causes deadlock. | ||
1090 | */ | ||
1091 | return ret; | ||
1092 | } | ||
1093 | } | ||
1094 | return 0; | ||
1095 | } | 1078 | } |
1096 | 1079 | ||
1097 | static int | 1080 | static int |
@@ -1112,7 +1095,6 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags, | |||
1112 | * much more information than normal filesystems to identify mount | 1095 | * much more information than normal filesystems to identify mount |
1113 | * instance. For snapshot mounts, not only a mount type (ro-mount | 1096 | * instance. For snapshot mounts, not only a mount type (ro-mount |
1114 | * or rw-mount) but also a checkpoint number is required. | 1097 | * or rw-mount) but also a checkpoint number is required. |
1115 | * The results are passed in sget() using nilfs_super_data. | ||
1116 | */ | 1098 | */ |
1117 | sd.cno = 0; | 1099 | sd.cno = 0; |
1118 | sd.flags = flags; | 1100 | sd.flags = flags; |
@@ -1148,13 +1130,23 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags, | |||
1148 | } | 1130 | } |
1149 | 1131 | ||
1150 | /* | 1132 | /* |
1151 | * Search specified snapshot or R/W mode super_block | 1133 | * Find existing nilfs_sb_info struct |
1152 | */ | 1134 | */ |
1135 | sd.sbi = nilfs_find_sbinfo(nilfs, !(flags & MS_RDONLY), sd.cno); | ||
1136 | |||
1153 | if (!sd.cno) | 1137 | if (!sd.cno) |
1154 | /* trying to get the latest checkpoint. */ | 1138 | /* trying to get the latest checkpoint. */ |
1155 | sd.cno = nilfs_last_cno(nilfs); | 1139 | sd.cno = nilfs_last_cno(nilfs); |
1156 | 1140 | ||
1141 | /* | ||
1142 | * Get super block instance holding the nilfs_sb_info struct. | ||
1143 | * A new instance is allocated if no existing mount is present or | ||
1144 | * existing instance has been unmounted. | ||
1145 | */ | ||
1157 | s = sget(fs_type, nilfs_test_bdev_super, nilfs_set_bdev_super, &sd); | 1146 | s = sget(fs_type, nilfs_test_bdev_super, nilfs_set_bdev_super, &sd); |
1147 | if (sd.sbi) | ||
1148 | nilfs_put_sbinfo(sd.sbi); | ||
1149 | |||
1158 | if (IS_ERR(s)) { | 1150 | if (IS_ERR(s)) { |
1159 | err = PTR_ERR(s); | 1151 | err = PTR_ERR(s); |
1160 | goto failed_unlock; | 1152 | goto failed_unlock; |