diff options
Diffstat (limited to 'fs/nilfs2/the_nilfs.c')
| -rw-r--r-- | fs/nilfs2/the_nilfs.c | 155 |
1 files changed, 83 insertions, 72 deletions
diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c index ad391a8c3e7e..6241e1722efc 100644 --- a/fs/nilfs2/the_nilfs.c +++ b/fs/nilfs2/the_nilfs.c | |||
| @@ -146,13 +146,9 @@ void put_nilfs(struct the_nilfs *nilfs) | |||
| 146 | 146 | ||
| 147 | might_sleep(); | 147 | might_sleep(); |
| 148 | if (nilfs_loaded(nilfs)) { | 148 | if (nilfs_loaded(nilfs)) { |
| 149 | nilfs_mdt_clear(nilfs->ns_sufile); | ||
| 150 | nilfs_mdt_destroy(nilfs->ns_sufile); | 149 | nilfs_mdt_destroy(nilfs->ns_sufile); |
| 151 | nilfs_mdt_clear(nilfs->ns_cpfile); | ||
| 152 | nilfs_mdt_destroy(nilfs->ns_cpfile); | 150 | nilfs_mdt_destroy(nilfs->ns_cpfile); |
| 153 | nilfs_mdt_clear(nilfs->ns_dat); | ||
| 154 | nilfs_mdt_destroy(nilfs->ns_dat); | 151 | nilfs_mdt_destroy(nilfs->ns_dat); |
| 155 | /* XXX: how and when to clear nilfs->ns_gc_dat? */ | ||
| 156 | nilfs_mdt_destroy(nilfs->ns_gc_dat); | 152 | nilfs_mdt_destroy(nilfs->ns_gc_dat); |
| 157 | } | 153 | } |
| 158 | if (nilfs_init(nilfs)) { | 154 | if (nilfs_init(nilfs)) { |
| @@ -166,7 +162,6 @@ void put_nilfs(struct the_nilfs *nilfs) | |||
| 166 | static int nilfs_load_super_root(struct the_nilfs *nilfs, | 162 | static int nilfs_load_super_root(struct the_nilfs *nilfs, |
| 167 | struct nilfs_sb_info *sbi, sector_t sr_block) | 163 | struct nilfs_sb_info *sbi, sector_t sr_block) |
| 168 | { | 164 | { |
| 169 | static struct lock_class_key dat_lock_key; | ||
| 170 | struct buffer_head *bh_sr; | 165 | struct buffer_head *bh_sr; |
| 171 | struct nilfs_super_root *raw_sr; | 166 | struct nilfs_super_root *raw_sr; |
| 172 | struct nilfs_super_block **sbp = nilfs->ns_sbp; | 167 | struct nilfs_super_block **sbp = nilfs->ns_sbp; |
| @@ -187,51 +182,36 @@ static int nilfs_load_super_root(struct the_nilfs *nilfs, | |||
| 187 | inode_size = nilfs->ns_inode_size; | 182 | inode_size = nilfs->ns_inode_size; |
| 188 | 183 | ||
| 189 | err = -ENOMEM; | 184 | err = -ENOMEM; |
| 190 | nilfs->ns_dat = nilfs_mdt_new(nilfs, NULL, NILFS_DAT_INO); | 185 | nilfs->ns_dat = nilfs_dat_new(nilfs, dat_entry_size); |
| 191 | if (unlikely(!nilfs->ns_dat)) | 186 | if (unlikely(!nilfs->ns_dat)) |
| 192 | goto failed; | 187 | goto failed; |
| 193 | 188 | ||
| 194 | nilfs->ns_gc_dat = nilfs_mdt_new(nilfs, NULL, NILFS_DAT_INO); | 189 | nilfs->ns_gc_dat = nilfs_dat_new(nilfs, dat_entry_size); |
| 195 | if (unlikely(!nilfs->ns_gc_dat)) | 190 | if (unlikely(!nilfs->ns_gc_dat)) |
| 196 | goto failed_dat; | 191 | goto failed_dat; |
| 197 | 192 | ||
| 198 | nilfs->ns_cpfile = nilfs_mdt_new(nilfs, NULL, NILFS_CPFILE_INO); | 193 | nilfs->ns_cpfile = nilfs_cpfile_new(nilfs, checkpoint_size); |
| 199 | if (unlikely(!nilfs->ns_cpfile)) | 194 | if (unlikely(!nilfs->ns_cpfile)) |
| 200 | goto failed_gc_dat; | 195 | goto failed_gc_dat; |
| 201 | 196 | ||
| 202 | nilfs->ns_sufile = nilfs_mdt_new(nilfs, NULL, NILFS_SUFILE_INO); | 197 | nilfs->ns_sufile = nilfs_sufile_new(nilfs, segment_usage_size); |
| 203 | if (unlikely(!nilfs->ns_sufile)) | 198 | if (unlikely(!nilfs->ns_sufile)) |
| 204 | goto failed_cpfile; | 199 | goto failed_cpfile; |
| 205 | 200 | ||
| 206 | err = nilfs_palloc_init_blockgroup(nilfs->ns_dat, dat_entry_size); | ||
| 207 | if (unlikely(err)) | ||
| 208 | goto failed_sufile; | ||
| 209 | |||
| 210 | err = nilfs_palloc_init_blockgroup(nilfs->ns_gc_dat, dat_entry_size); | ||
| 211 | if (unlikely(err)) | ||
| 212 | goto failed_sufile; | ||
| 213 | |||
| 214 | lockdep_set_class(&NILFS_MDT(nilfs->ns_dat)->mi_sem, &dat_lock_key); | ||
| 215 | lockdep_set_class(&NILFS_MDT(nilfs->ns_gc_dat)->mi_sem, &dat_lock_key); | ||
| 216 | |||
| 217 | nilfs_mdt_set_shadow(nilfs->ns_dat, nilfs->ns_gc_dat); | 201 | nilfs_mdt_set_shadow(nilfs->ns_dat, nilfs->ns_gc_dat); |
| 218 | nilfs_mdt_set_entry_size(nilfs->ns_cpfile, checkpoint_size, | ||
| 219 | sizeof(struct nilfs_cpfile_header)); | ||
| 220 | nilfs_mdt_set_entry_size(nilfs->ns_sufile, segment_usage_size, | ||
| 221 | sizeof(struct nilfs_sufile_header)); | ||
| 222 | 202 | ||
| 223 | err = nilfs_mdt_read_inode_direct( | 203 | err = nilfs_dat_read(nilfs->ns_dat, (void *)bh_sr->b_data + |
| 224 | nilfs->ns_dat, bh_sr, NILFS_SR_DAT_OFFSET(inode_size)); | 204 | NILFS_SR_DAT_OFFSET(inode_size)); |
| 225 | if (unlikely(err)) | 205 | if (unlikely(err)) |
| 226 | goto failed_sufile; | 206 | goto failed_sufile; |
| 227 | 207 | ||
| 228 | err = nilfs_mdt_read_inode_direct( | 208 | err = nilfs_cpfile_read(nilfs->ns_cpfile, (void *)bh_sr->b_data + |
| 229 | nilfs->ns_cpfile, bh_sr, NILFS_SR_CPFILE_OFFSET(inode_size)); | 209 | NILFS_SR_CPFILE_OFFSET(inode_size)); |
| 230 | if (unlikely(err)) | 210 | if (unlikely(err)) |
| 231 | goto failed_sufile; | 211 | goto failed_sufile; |
| 232 | 212 | ||
| 233 | err = nilfs_mdt_read_inode_direct( | 213 | err = nilfs_sufile_read(nilfs->ns_sufile, (void *)bh_sr->b_data + |
| 234 | nilfs->ns_sufile, bh_sr, NILFS_SR_SUFILE_OFFSET(inode_size)); | 214 | NILFS_SR_SUFILE_OFFSET(inode_size)); |
| 235 | if (unlikely(err)) | 215 | if (unlikely(err)) |
| 236 | goto failed_sufile; | 216 | goto failed_sufile; |
| 237 | 217 | ||
| @@ -281,29 +261,30 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) | |||
| 281 | struct nilfs_recovery_info ri; | 261 | struct nilfs_recovery_info ri; |
| 282 | unsigned int s_flags = sbi->s_super->s_flags; | 262 | unsigned int s_flags = sbi->s_super->s_flags; |
| 283 | int really_read_only = bdev_read_only(nilfs->ns_bdev); | 263 | int really_read_only = bdev_read_only(nilfs->ns_bdev); |
| 284 | unsigned valid_fs; | 264 | int valid_fs = nilfs_valid_fs(nilfs); |
| 285 | int err = 0; | 265 | int err; |
| 286 | |||
| 287 | nilfs_init_recovery_info(&ri); | ||
| 288 | 266 | ||
| 289 | down_write(&nilfs->ns_sem); | 267 | if (nilfs_loaded(nilfs)) { |
| 290 | valid_fs = (nilfs->ns_mount_state & NILFS_VALID_FS); | 268 | if (valid_fs || |
| 291 | up_write(&nilfs->ns_sem); | 269 | ((s_flags & MS_RDONLY) && nilfs_test_opt(sbi, NORECOVERY))) |
| 270 | return 0; | ||
| 271 | printk(KERN_ERR "NILFS: the filesystem is in an incomplete " | ||
| 272 | "recovery state.\n"); | ||
| 273 | return -EINVAL; | ||
| 274 | } | ||
| 292 | 275 | ||
| 293 | if (!valid_fs && (s_flags & MS_RDONLY)) { | 276 | if (!valid_fs) { |
| 294 | printk(KERN_INFO "NILFS: INFO: recovery " | 277 | printk(KERN_WARNING "NILFS warning: mounting unchecked fs\n"); |
| 295 | "required for readonly filesystem.\n"); | 278 | if (s_flags & MS_RDONLY) { |
| 296 | if (really_read_only) { | 279 | printk(KERN_INFO "NILFS: INFO: recovery " |
| 297 | printk(KERN_ERR "NILFS: write access " | 280 | "required for readonly filesystem.\n"); |
| 298 | "unavailable, cannot proceed.\n"); | 281 | printk(KERN_INFO "NILFS: write access will " |
| 299 | err = -EROFS; | 282 | "be enabled during recovery.\n"); |
| 300 | goto failed; | ||
| 301 | } | 283 | } |
| 302 | printk(KERN_INFO "NILFS: write access will " | ||
| 303 | "be enabled during recovery.\n"); | ||
| 304 | sbi->s_super->s_flags &= ~MS_RDONLY; | ||
| 305 | } | 284 | } |
| 306 | 285 | ||
| 286 | nilfs_init_recovery_info(&ri); | ||
| 287 | |||
| 307 | err = nilfs_search_super_root(nilfs, sbi, &ri); | 288 | err = nilfs_search_super_root(nilfs, sbi, &ri); |
| 308 | if (unlikely(err)) { | 289 | if (unlikely(err)) { |
| 309 | printk(KERN_ERR "NILFS: error searching super root.\n"); | 290 | printk(KERN_ERR "NILFS: error searching super root.\n"); |
| @@ -316,19 +297,56 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) | |||
| 316 | goto failed; | 297 | goto failed; |
| 317 | } | 298 | } |
| 318 | 299 | ||
| 319 | if (!valid_fs) { | 300 | if (valid_fs) |
| 320 | err = nilfs_recover_logical_segments(nilfs, sbi, &ri); | 301 | goto skip_recovery; |
| 321 | if (unlikely(err)) { | 302 | |
| 322 | nilfs_mdt_destroy(nilfs->ns_cpfile); | 303 | if (s_flags & MS_RDONLY) { |
| 323 | nilfs_mdt_destroy(nilfs->ns_sufile); | 304 | if (nilfs_test_opt(sbi, NORECOVERY)) { |
| 324 | nilfs_mdt_destroy(nilfs->ns_dat); | 305 | printk(KERN_INFO "NILFS: norecovery option specified. " |
| 325 | goto failed; | 306 | "skipping roll-forward recovery\n"); |
| 307 | goto skip_recovery; | ||
| 326 | } | 308 | } |
| 327 | if (ri.ri_need_recovery == NILFS_RECOVERY_SR_UPDATED) | 309 | if (really_read_only) { |
| 328 | sbi->s_super->s_dirt = 1; | 310 | printk(KERN_ERR "NILFS: write access " |
| 311 | "unavailable, cannot proceed.\n"); | ||
| 312 | err = -EROFS; | ||
| 313 | goto failed_unload; | ||
| 314 | } | ||
| 315 | sbi->s_super->s_flags &= ~MS_RDONLY; | ||
| 316 | } else if (nilfs_test_opt(sbi, NORECOVERY)) { | ||
| 317 | printk(KERN_ERR "NILFS: recovery cancelled because norecovery " | ||
| 318 | "option was specified for a read/write mount\n"); | ||
| 319 | err = -EINVAL; | ||
| 320 | goto failed_unload; | ||
| 329 | } | 321 | } |
| 330 | 322 | ||
| 323 | err = nilfs_recover_logical_segments(nilfs, sbi, &ri); | ||
| 324 | if (err) | ||
| 325 | goto failed_unload; | ||
| 326 | |||
| 327 | down_write(&nilfs->ns_sem); | ||
| 328 | nilfs->ns_mount_state |= NILFS_VALID_FS; | ||
| 329 | nilfs->ns_sbp[0]->s_state = cpu_to_le16(nilfs->ns_mount_state); | ||
| 330 | err = nilfs_commit_super(sbi, 1); | ||
| 331 | up_write(&nilfs->ns_sem); | ||
| 332 | |||
| 333 | if (err) { | ||
| 334 | printk(KERN_ERR "NILFS: failed to update super block. " | ||
| 335 | "recovery unfinished.\n"); | ||
| 336 | goto failed_unload; | ||
| 337 | } | ||
| 338 | printk(KERN_INFO "NILFS: recovery complete.\n"); | ||
| 339 | |||
| 340 | skip_recovery: | ||
| 331 | set_nilfs_loaded(nilfs); | 341 | set_nilfs_loaded(nilfs); |
| 342 | nilfs_clear_recovery_info(&ri); | ||
| 343 | sbi->s_super->s_flags = s_flags; | ||
| 344 | return 0; | ||
| 345 | |||
| 346 | failed_unload: | ||
| 347 | nilfs_mdt_destroy(nilfs->ns_cpfile); | ||
| 348 | nilfs_mdt_destroy(nilfs->ns_sufile); | ||
| 349 | nilfs_mdt_destroy(nilfs->ns_dat); | ||
| 332 | 350 | ||
| 333 | failed: | 351 | failed: |
| 334 | nilfs_clear_recovery_info(&ri); | 352 | nilfs_clear_recovery_info(&ri); |
| @@ -632,30 +650,23 @@ int nilfs_count_free_blocks(struct the_nilfs *nilfs, sector_t *nblocks) | |||
| 632 | { | 650 | { |
| 633 | struct inode *dat = nilfs_dat_inode(nilfs); | 651 | struct inode *dat = nilfs_dat_inode(nilfs); |
| 634 | unsigned long ncleansegs; | 652 | unsigned long ncleansegs; |
| 635 | int err; | ||
| 636 | 653 | ||
| 637 | down_read(&NILFS_MDT(dat)->mi_sem); /* XXX */ | 654 | down_read(&NILFS_MDT(dat)->mi_sem); /* XXX */ |
| 638 | err = nilfs_sufile_get_ncleansegs(nilfs->ns_sufile, &ncleansegs); | 655 | ncleansegs = nilfs_sufile_get_ncleansegs(nilfs->ns_sufile); |
| 639 | up_read(&NILFS_MDT(dat)->mi_sem); /* XXX */ | 656 | up_read(&NILFS_MDT(dat)->mi_sem); /* XXX */ |
| 640 | if (likely(!err)) | 657 | *nblocks = (sector_t)ncleansegs * nilfs->ns_blocks_per_segment; |
| 641 | *nblocks = (sector_t)ncleansegs * nilfs->ns_blocks_per_segment; | 658 | return 0; |
| 642 | return err; | ||
| 643 | } | 659 | } |
| 644 | 660 | ||
| 645 | int nilfs_near_disk_full(struct the_nilfs *nilfs) | 661 | int nilfs_near_disk_full(struct the_nilfs *nilfs) |
| 646 | { | 662 | { |
| 647 | struct inode *sufile = nilfs->ns_sufile; | ||
| 648 | unsigned long ncleansegs, nincsegs; | 663 | unsigned long ncleansegs, nincsegs; |
| 649 | int ret; | ||
| 650 | 664 | ||
| 651 | ret = nilfs_sufile_get_ncleansegs(sufile, &ncleansegs); | 665 | ncleansegs = nilfs_sufile_get_ncleansegs(nilfs->ns_sufile); |
| 652 | if (likely(!ret)) { | 666 | nincsegs = atomic_read(&nilfs->ns_ndirtyblks) / |
| 653 | nincsegs = atomic_read(&nilfs->ns_ndirtyblks) / | 667 | nilfs->ns_blocks_per_segment + 1; |
| 654 | nilfs->ns_blocks_per_segment + 1; | 668 | |
| 655 | if (ncleansegs <= nilfs->ns_nrsvsegs + nincsegs) | 669 | return ncleansegs <= nilfs->ns_nrsvsegs + nincsegs; |
| 656 | ret++; | ||
| 657 | } | ||
| 658 | return ret; | ||
| 659 | } | 670 | } |
| 660 | 671 | ||
| 661 | /** | 672 | /** |
