diff options
author | Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> | 2011-05-04 12:23:57 -0400 |
---|---|---|
committer | Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> | 2011-05-10 09:21:45 -0400 |
commit | cfb0a4bfd8736418cbe5cbc115cabc84b527111e (patch) | |
tree | 9faf66ad535fea01e19bc3f7bf59fe8fd75d8082 /fs/nilfs2/super.c | |
parent | 619205da5b567504310daf829dede1187fa29bbc (diff) |
nilfs2: add routine to move secondary super block
After resizing the filesystem, the secondary super block must be moved
to a new location. This adds a helper function for this.
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Diffstat (limited to 'fs/nilfs2/super.c')
-rw-r--r-- | fs/nilfs2/super.c | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 062cca065195..eba5b53b1080 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c | |||
@@ -347,6 +347,63 @@ int nilfs_cleanup_super(struct super_block *sb) | |||
347 | return ret; | 347 | return ret; |
348 | } | 348 | } |
349 | 349 | ||
350 | /** | ||
351 | * nilfs_move_2nd_super - relocate secondary super block | ||
352 | * @sb: super block instance | ||
353 | * @sb2off: new offset of the secondary super block (in bytes) | ||
354 | */ | ||
355 | static int nilfs_move_2nd_super(struct super_block *sb, loff_t sb2off) | ||
356 | { | ||
357 | struct the_nilfs *nilfs = sb->s_fs_info; | ||
358 | struct buffer_head *nsbh; | ||
359 | struct nilfs_super_block *nsbp; | ||
360 | sector_t blocknr, newblocknr; | ||
361 | unsigned long offset; | ||
362 | int sb2i = -1; /* array index of the secondary superblock */ | ||
363 | int ret = 0; | ||
364 | |||
365 | /* nilfs->ns_sem must be locked by the caller. */ | ||
366 | if (nilfs->ns_sbh[1] && | ||
367 | nilfs->ns_sbh[1]->b_blocknr > nilfs->ns_first_data_block) { | ||
368 | sb2i = 1; | ||
369 | blocknr = nilfs->ns_sbh[1]->b_blocknr; | ||
370 | } else if (nilfs->ns_sbh[0]->b_blocknr > nilfs->ns_first_data_block) { | ||
371 | sb2i = 0; | ||
372 | blocknr = nilfs->ns_sbh[0]->b_blocknr; | ||
373 | } | ||
374 | if (sb2i >= 0 && (u64)blocknr << nilfs->ns_blocksize_bits == sb2off) | ||
375 | goto out; /* super block location is unchanged */ | ||
376 | |||
377 | /* Get new super block buffer */ | ||
378 | newblocknr = sb2off >> nilfs->ns_blocksize_bits; | ||
379 | offset = sb2off & (nilfs->ns_blocksize - 1); | ||
380 | nsbh = sb_getblk(sb, newblocknr); | ||
381 | if (!nsbh) { | ||
382 | printk(KERN_WARNING | ||
383 | "NILFS warning: unable to move secondary superblock " | ||
384 | "to block %llu\n", (unsigned long long)newblocknr); | ||
385 | ret = -EIO; | ||
386 | goto out; | ||
387 | } | ||
388 | nsbp = (void *)nsbh->b_data + offset; | ||
389 | memset(nsbp, 0, nilfs->ns_blocksize); | ||
390 | |||
391 | if (sb2i >= 0) { | ||
392 | memcpy(nsbp, nilfs->ns_sbp[sb2i], nilfs->ns_sbsize); | ||
393 | brelse(nilfs->ns_sbh[sb2i]); | ||
394 | nilfs->ns_sbh[sb2i] = nsbh; | ||
395 | nilfs->ns_sbp[sb2i] = nsbp; | ||
396 | } else if (nilfs->ns_sbh[0]->b_blocknr < nilfs->ns_first_data_block) { | ||
397 | /* secondary super block will be restored to index 1 */ | ||
398 | nilfs->ns_sbh[1] = nsbh; | ||
399 | nilfs->ns_sbp[1] = nsbp; | ||
400 | } else { | ||
401 | brelse(nsbh); | ||
402 | } | ||
403 | out: | ||
404 | return ret; | ||
405 | } | ||
406 | |||
350 | static void nilfs_put_super(struct super_block *sb) | 407 | static void nilfs_put_super(struct super_block *sb) |
351 | { | 408 | { |
352 | struct the_nilfs *nilfs = sb->s_fs_info; | 409 | struct the_nilfs *nilfs = sb->s_fs_info; |