aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nilfs2/the_nilfs.c
diff options
context:
space:
mode:
authorRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>2009-04-06 22:01:59 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-04-07 11:31:20 -0400
commite339ad31f59925b48a92ee3947692fdf9758b8c7 (patch)
tree6bb85c43bfd100b0a220c788c654f2f74ca553e4 /fs/nilfs2/the_nilfs.c
parentcece552074c591970353ad48308d65f110aeaf28 (diff)
nilfs2: introduce secondary super block
The former versions didn't have extra super blocks. This improves the weak point by introducing another super block at unused region in tail of the partition. This doesn't break disk format compatibility; older versions just ingore the secondary super block, and new versions just recover it if it doesn't exist. The partition created by an old mkfs may not have unused region, but in that case, the secondary super block will not be added. This doesn't make more redundant copies of the super block; it is a future work. Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/nilfs2/the_nilfs.c')
-rw-r--r--fs/nilfs2/the_nilfs.c180
1 files changed, 156 insertions, 24 deletions
diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c
index 661ab762d765..33400cf0bbe2 100644
--- a/fs/nilfs2/the_nilfs.c
+++ b/fs/nilfs2/the_nilfs.c
@@ -25,6 +25,7 @@
25#include <linux/slab.h> 25#include <linux/slab.h>
26#include <linux/blkdev.h> 26#include <linux/blkdev.h>
27#include <linux/backing-dev.h> 27#include <linux/backing-dev.h>
28#include <linux/crc32.h>
28#include "nilfs.h" 29#include "nilfs.h"
29#include "segment.h" 30#include "segment.h"
30#include "alloc.h" 31#include "alloc.h"
@@ -105,7 +106,8 @@ void put_nilfs(struct the_nilfs *nilfs)
105 } 106 }
106 if (nilfs_init(nilfs)) { 107 if (nilfs_init(nilfs)) {
107 nilfs_destroy_gccache(nilfs); 108 nilfs_destroy_gccache(nilfs);
108 brelse(nilfs->ns_sbh); 109 brelse(nilfs->ns_sbh[0]);
110 brelse(nilfs->ns_sbh[1]);
109 } 111 }
110 kfree(nilfs); 112 kfree(nilfs);
111} 113}
@@ -115,6 +117,7 @@ static int nilfs_load_super_root(struct the_nilfs *nilfs,
115{ 117{
116 struct buffer_head *bh_sr; 118 struct buffer_head *bh_sr;
117 struct nilfs_super_root *raw_sr; 119 struct nilfs_super_root *raw_sr;
120 struct nilfs_super_block **sbp = nilfs->ns_sbp;
118 unsigned dat_entry_size, segment_usage_size, checkpoint_size; 121 unsigned dat_entry_size, segment_usage_size, checkpoint_size;
119 unsigned inode_size; 122 unsigned inode_size;
120 int err; 123 int err;
@@ -124,9 +127,9 @@ static int nilfs_load_super_root(struct the_nilfs *nilfs,
124 return err; 127 return err;
125 128
126 down_read(&nilfs->ns_sem); 129 down_read(&nilfs->ns_sem);
127 dat_entry_size = le16_to_cpu(nilfs->ns_sbp->s_dat_entry_size); 130 dat_entry_size = le16_to_cpu(sbp[0]->s_dat_entry_size);
128 checkpoint_size = le16_to_cpu(nilfs->ns_sbp->s_checkpoint_size); 131 checkpoint_size = le16_to_cpu(sbp[0]->s_checkpoint_size);
129 segment_usage_size = le16_to_cpu(nilfs->ns_sbp->s_segment_usage_size); 132 segment_usage_size = le16_to_cpu(sbp[0]->s_segment_usage_size);
130 up_read(&nilfs->ns_sem); 133 up_read(&nilfs->ns_sem);
131 134
132 inode_size = nilfs->ns_inode_size; 135 inode_size = nilfs->ns_inode_size;
@@ -270,11 +273,8 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
270 nilfs_mdt_destroy(nilfs->ns_dat); 273 nilfs_mdt_destroy(nilfs->ns_dat);
271 goto failed; 274 goto failed;
272 } 275 }
273 if (ri.ri_need_recovery == NILFS_RECOVERY_SR_UPDATED) { 276 if (ri.ri_need_recovery == NILFS_RECOVERY_SR_UPDATED)
274 down_write(&nilfs->ns_sem); 277 sbi->s_super->s_dirt = 1;
275 nilfs_update_last_segment(sbi, 0);
276 up_write(&nilfs->ns_sem);
277 }
278 } 278 }
279 279
280 set_nilfs_loaded(nilfs); 280 set_nilfs_loaded(nilfs);
@@ -296,9 +296,8 @@ static unsigned long long nilfs_max_size(unsigned int blkbits)
296 return res; 296 return res;
297} 297}
298 298
299static int 299static int nilfs_store_disk_layout(struct the_nilfs *nilfs,
300nilfs_store_disk_layout(struct the_nilfs *nilfs, struct super_block *sb, 300 struct nilfs_super_block *sbp)
301 struct nilfs_super_block *sbp)
302{ 301{
303 if (le32_to_cpu(sbp->s_rev_level) != NILFS_CURRENT_REV) { 302 if (le32_to_cpu(sbp->s_rev_level) != NILFS_CURRENT_REV) {
304 printk(KERN_ERR "NILFS: revision mismatch " 303 printk(KERN_ERR "NILFS: revision mismatch "
@@ -309,6 +308,10 @@ nilfs_store_disk_layout(struct the_nilfs *nilfs, struct super_block *sb,
309 NILFS_CURRENT_REV, NILFS_MINOR_REV); 308 NILFS_CURRENT_REV, NILFS_MINOR_REV);
310 return -EINVAL; 309 return -EINVAL;
311 } 310 }
311 nilfs->ns_sbsize = le16_to_cpu(sbp->s_bytes);
312 if (nilfs->ns_sbsize > BLOCK_SIZE)
313 return -EINVAL;
314
312 nilfs->ns_inode_size = le16_to_cpu(sbp->s_inode_size); 315 nilfs->ns_inode_size = le16_to_cpu(sbp->s_inode_size);
313 nilfs->ns_first_ino = le32_to_cpu(sbp->s_first_ino); 316 nilfs->ns_first_ino = le32_to_cpu(sbp->s_first_ino);
314 317
@@ -330,6 +333,122 @@ nilfs_store_disk_layout(struct the_nilfs *nilfs, struct super_block *sb,
330 return 0; 333 return 0;
331} 334}
332 335
336static int nilfs_valid_sb(struct nilfs_super_block *sbp)
337{
338 static unsigned char sum[4];
339 const int sumoff = offsetof(struct nilfs_super_block, s_sum);
340 size_t bytes;
341 u32 crc;
342
343 if (!sbp || le16_to_cpu(sbp->s_magic) != NILFS_SUPER_MAGIC)
344 return 0;
345 bytes = le16_to_cpu(sbp->s_bytes);
346 if (bytes > BLOCK_SIZE)
347 return 0;
348 crc = crc32_le(le32_to_cpu(sbp->s_crc_seed), (unsigned char *)sbp,
349 sumoff);
350 crc = crc32_le(crc, sum, 4);
351 crc = crc32_le(crc, (unsigned char *)sbp + sumoff + 4,
352 bytes - sumoff - 4);
353 return crc == le32_to_cpu(sbp->s_sum);
354}
355
356static int nilfs_sb2_bad_offset(struct nilfs_super_block *sbp, u64 offset)
357{
358 return offset < ((le64_to_cpu(sbp->s_nsegments) *
359 le32_to_cpu(sbp->s_blocks_per_segment)) <<
360 (le32_to_cpu(sbp->s_log_block_size) + 10));
361}
362
363static void nilfs_release_super_block(struct the_nilfs *nilfs)
364{
365 int i;
366
367 for (i = 0; i < 2; i++) {
368 if (nilfs->ns_sbp[i]) {
369 brelse(nilfs->ns_sbh[i]);
370 nilfs->ns_sbh[i] = NULL;
371 nilfs->ns_sbp[i] = NULL;
372 }
373 }
374}
375
376void nilfs_fall_back_super_block(struct the_nilfs *nilfs)
377{
378 brelse(nilfs->ns_sbh[0]);
379 nilfs->ns_sbh[0] = nilfs->ns_sbh[1];
380 nilfs->ns_sbp[0] = nilfs->ns_sbp[1];
381 nilfs->ns_sbh[1] = NULL;
382 nilfs->ns_sbp[1] = NULL;
383}
384
385void nilfs_swap_super_block(struct the_nilfs *nilfs)
386{
387 struct buffer_head *tsbh = nilfs->ns_sbh[0];
388 struct nilfs_super_block *tsbp = nilfs->ns_sbp[0];
389
390 nilfs->ns_sbh[0] = nilfs->ns_sbh[1];
391 nilfs->ns_sbp[0] = nilfs->ns_sbp[1];
392 nilfs->ns_sbh[1] = tsbh;
393 nilfs->ns_sbp[1] = tsbp;
394}
395
396static int nilfs_load_super_block(struct the_nilfs *nilfs,
397 struct super_block *sb, int blocksize,
398 struct nilfs_super_block **sbpp)
399{
400 struct nilfs_super_block **sbp = nilfs->ns_sbp;
401 struct buffer_head **sbh = nilfs->ns_sbh;
402 u64 sb2off = NILFS_SB2_OFFSET_BYTES(nilfs->ns_bdev->bd_inode->i_size);
403 int valid[2], swp = 0;
404
405 sbp[0] = nilfs_read_super_block(sb, NILFS_SB_OFFSET_BYTES, blocksize,
406 &sbh[0]);
407 sbp[1] = nilfs_read_super_block(sb, sb2off, blocksize, &sbh[1]);
408
409 if (!sbp[0]) {
410 if (!sbp[1]) {
411 printk(KERN_ERR "NILFS: unable to read superblock\n");
412 return -EIO;
413 }
414 printk(KERN_WARNING
415 "NILFS warning: unable to read primary superblock\n");
416 } else if (!sbp[1])
417 printk(KERN_WARNING
418 "NILFS warning: unable to read secondary superblock\n");
419
420 valid[0] = nilfs_valid_sb(sbp[0]);
421 valid[1] = nilfs_valid_sb(sbp[1]);
422 swp = valid[1] &&
423 (!valid[0] ||
424 le64_to_cpu(sbp[1]->s_wtime) > le64_to_cpu(sbp[0]->s_wtime));
425
426 if (valid[swp] && nilfs_sb2_bad_offset(sbp[swp], sb2off)) {
427 brelse(sbh[1]);
428 sbh[1] = NULL;
429 sbp[1] = NULL;
430 swp = 0;
431 }
432 if (!valid[swp]) {
433 nilfs_release_super_block(nilfs);
434 printk(KERN_ERR "NILFS: Can't find nilfs on dev %s.\n",
435 sb->s_id);
436 return -EINVAL;
437 }
438
439 if (swp) {
440 printk(KERN_WARNING "NILFS warning: broken superblock. "
441 "using spare superblock.\n");
442 nilfs_swap_super_block(nilfs);
443 }
444
445 nilfs->ns_sbwtime[0] = le64_to_cpu(sbp[0]->s_wtime);
446 nilfs->ns_sbwtime[1] = valid[!swp] ? le64_to_cpu(sbp[1]->s_wtime) : 0;
447 nilfs->ns_prot_seq = le64_to_cpu(sbp[valid[1] & !swp]->s_last_seq);
448 *sbpp = sbp[0];
449 return 0;
450}
451
333/** 452/**
334 * init_nilfs - initialize a NILFS instance. 453 * init_nilfs - initialize a NILFS instance.
335 * @nilfs: the_nilfs structure 454 * @nilfs: the_nilfs structure
@@ -352,16 +471,15 @@ nilfs_store_disk_layout(struct the_nilfs *nilfs, struct super_block *sb,
352int init_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, char *data) 471int init_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, char *data)
353{ 472{
354 struct super_block *sb = sbi->s_super; 473 struct super_block *sb = sbi->s_super;
355 struct buffer_head *sbh;
356 struct nilfs_super_block *sbp; 474 struct nilfs_super_block *sbp;
357 struct backing_dev_info *bdi; 475 struct backing_dev_info *bdi;
358 int blocksize; 476 int blocksize;
359 int err = 0; 477 int err;
360 478
361 down_write(&nilfs->ns_sem); 479 down_write(&nilfs->ns_sem);
362 if (nilfs_init(nilfs)) { 480 if (nilfs_init(nilfs)) {
363 /* Load values from existing the_nilfs */ 481 /* Load values from existing the_nilfs */
364 sbp = nilfs->ns_sbp; 482 sbp = nilfs->ns_sbp[0];
365 err = nilfs_store_magic_and_option(sb, sbp, data); 483 err = nilfs_store_magic_and_option(sb, sbp, data);
366 if (err) 484 if (err)
367 goto out; 485 goto out;
@@ -377,36 +495,50 @@ int init_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, char *data)
377 goto out; 495 goto out;
378 } 496 }
379 497
380 sbp = nilfs_load_super_block(sb, &sbh); 498 blocksize = sb_min_blocksize(sb, BLOCK_SIZE);
381 if (!sbp) { 499 if (!blocksize) {
500 printk(KERN_ERR "NILFS: unable to set blocksize\n");
382 err = -EINVAL; 501 err = -EINVAL;
383 goto out; 502 goto out;
384 } 503 }
504 err = nilfs_load_super_block(nilfs, sb, blocksize, &sbp);
505 if (err)
506 goto out;
507
385 err = nilfs_store_magic_and_option(sb, sbp, data); 508 err = nilfs_store_magic_and_option(sb, sbp, data);
386 if (err) 509 if (err)
387 goto failed_sbh; 510 goto failed_sbh;
388 511
389 blocksize = BLOCK_SIZE << le32_to_cpu(sbp->s_log_block_size); 512 blocksize = BLOCK_SIZE << le32_to_cpu(sbp->s_log_block_size);
390 if (sb->s_blocksize != blocksize) { 513 if (sb->s_blocksize != blocksize) {
391 sbp = nilfs_reload_super_block(sb, &sbh, blocksize); 514 int hw_blocksize = bdev_hardsect_size(sb->s_bdev);
392 if (!sbp) { 515
516 if (blocksize < hw_blocksize) {
517 printk(KERN_ERR
518 "NILFS: blocksize %d too small for device "
519 "(sector-size = %d).\n",
520 blocksize, hw_blocksize);
393 err = -EINVAL; 521 err = -EINVAL;
522 goto failed_sbh;
523 }
524 nilfs_release_super_block(nilfs);
525 sb_set_blocksize(sb, blocksize);
526
527 err = nilfs_load_super_block(nilfs, sb, blocksize, &sbp);
528 if (err)
394 goto out; 529 goto out;
395 /* not failed_sbh; sbh is released automatically 530 /* not failed_sbh; sbh is released automatically
396 when reloading fails. */ 531 when reloading fails. */
397 }
398 } 532 }
399 nilfs->ns_blocksize_bits = sb->s_blocksize_bits; 533 nilfs->ns_blocksize_bits = sb->s_blocksize_bits;
400 534
401 err = nilfs_store_disk_layout(nilfs, sb, sbp); 535 err = nilfs_store_disk_layout(nilfs, sbp);
402 if (err) 536 if (err)
403 goto failed_sbh; 537 goto failed_sbh;
404 538
405 sb->s_maxbytes = nilfs_max_size(sb->s_blocksize_bits); 539 sb->s_maxbytes = nilfs_max_size(sb->s_blocksize_bits);
406 540
407 nilfs->ns_mount_state = le16_to_cpu(sbp->s_state); 541 nilfs->ns_mount_state = le16_to_cpu(sbp->s_state);
408 nilfs->ns_sbh = sbh;
409 nilfs->ns_sbp = sbp;
410 542
411 bdi = nilfs->ns_bdev->bd_inode_backing_dev_info; 543 bdi = nilfs->ns_bdev->bd_inode_backing_dev_info;
412 if (!bdi) 544 if (!bdi)
@@ -443,7 +575,7 @@ int init_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, char *data)
443 return err; 575 return err;
444 576
445 failed_sbh: 577 failed_sbh:
446 brelse(sbh); 578 nilfs_release_super_block(nilfs);
447 goto out; 579 goto out;
448} 580}
449 581