aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nilfs2
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nilfs2')
-rw-r--r--fs/nilfs2/the_nilfs.c52
1 files changed, 50 insertions, 2 deletions
diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c
index 0d2a46cb75f8..88c8976c55a9 100644
--- a/fs/nilfs2/the_nilfs.c
+++ b/fs/nilfs2/the_nilfs.c
@@ -38,6 +38,8 @@
38static LIST_HEAD(nilfs_objects); 38static LIST_HEAD(nilfs_objects);
39static DEFINE_SPINLOCK(nilfs_lock); 39static DEFINE_SPINLOCK(nilfs_lock);
40 40
41static int nilfs_valid_sb(struct nilfs_super_block *sbp);
42
41void nilfs_set_last_segment(struct the_nilfs *nilfs, 43void nilfs_set_last_segment(struct the_nilfs *nilfs,
42 sector_t start_blocknr, u64 seq, __u64 cno) 44 sector_t start_blocknr, u64 seq, __u64 cno)
43{ 45{
@@ -316,8 +318,50 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
316 318
317 err = nilfs_search_super_root(nilfs, &ri); 319 err = nilfs_search_super_root(nilfs, &ri);
318 if (unlikely(err)) { 320 if (unlikely(err)) {
319 printk(KERN_ERR "NILFS: error searching super root.\n"); 321 struct nilfs_super_block **sbp = nilfs->ns_sbp;
320 goto failed; 322 int blocksize;
323
324 if (err != -EINVAL)
325 goto scan_error;
326
327 if (!nilfs_valid_sb(sbp[1])) {
328 printk(KERN_WARNING
329 "NILFS warning: unable to fall back to spare"
330 "super block\n");
331 goto scan_error;
332 }
333 printk(KERN_INFO
334 "NILFS: try rollback from an earlier position\n");
335
336 /*
337 * restore super block with its spare and reconfigure
338 * relevant states of the nilfs object.
339 */
340 memcpy(sbp[0], sbp[1], nilfs->ns_sbsize);
341 nilfs->ns_crc_seed = le32_to_cpu(sbp[0]->s_crc_seed);
342 nilfs->ns_sbwtime = le64_to_cpu(sbp[0]->s_wtime);
343
344 /* verify consistency between two super blocks */
345 blocksize = BLOCK_SIZE << le32_to_cpu(sbp[0]->s_log_block_size);
346 if (blocksize != nilfs->ns_blocksize) {
347 printk(KERN_WARNING
348 "NILFS warning: blocksize differs between "
349 "two super blocks (%d != %d)\n",
350 blocksize, nilfs->ns_blocksize);
351 goto scan_error;
352 }
353
354 err = nilfs_store_log_cursor(nilfs, sbp[0]);
355 if (err)
356 goto scan_error;
357
358 /* drop clean flag to allow roll-forward and recovery */
359 nilfs->ns_mount_state &= ~NILFS_VALID_FS;
360 valid_fs = 0;
361
362 err = nilfs_search_super_root(nilfs, &ri);
363 if (err)
364 goto scan_error;
321 } 365 }
322 366
323 err = nilfs_load_super_root(nilfs, ri.ri_super_root); 367 err = nilfs_load_super_root(nilfs, ri.ri_super_root);
@@ -371,6 +415,10 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
371 sbi->s_super->s_flags = s_flags; 415 sbi->s_super->s_flags = s_flags;
372 return 0; 416 return 0;
373 417
418 scan_error:
419 printk(KERN_ERR "NILFS: error searching super root.\n");
420 goto failed;
421
374 failed_unload: 422 failed_unload:
375 nilfs_mdt_destroy(nilfs->ns_cpfile); 423 nilfs_mdt_destroy(nilfs->ns_cpfile);
376 nilfs_mdt_destroy(nilfs->ns_sufile); 424 nilfs_mdt_destroy(nilfs->ns_sufile);