aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nilfs2/super.c
diff options
context:
space:
mode:
authorRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>2011-05-04 12:23:57 -0400
committerRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>2011-05-10 09:21:45 -0400
commitcfb0a4bfd8736418cbe5cbc115cabc84b527111e (patch)
tree9faf66ad535fea01e19bc3f7bf59fe8fd75d8082 /fs/nilfs2/super.c
parent619205da5b567504310daf829dede1187fa29bbc (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.c57
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 */
355static 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 }
403out:
404 return ret;
405}
406
350static void nilfs_put_super(struct super_block *sb) 407static 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;