aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nilfs2/super.c
diff options
context:
space:
mode:
authorJiro SEKIBA <jir@unicus.jp>2010-06-28 04:49:32 -0400
committerRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>2010-07-22 21:02:10 -0400
commitd26493b6f017c0b0063a15bf893411ddae85eee4 (patch)
tree994de3e7c0383f0e30e5e9c88c0c5d0261a834bc /fs/nilfs2/super.c
parent60f46b7efc1d6b980511c2644cb89903062f6e98 (diff)
nilfs2: introduce nilfs_prepare_super
This function checks validity of super block pointers. If first super block is invalid, it will swap the super blocks. The function should be called before any super block information updates. Caller must obtain nilfs->ns_sem. Signed-off-by: Jiro SEKIBA <jir@unicus.jp> Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Diffstat (limited to 'fs/nilfs2/super.c')
-rw-r--r--fs/nilfs2/super.c73
1 files changed, 51 insertions, 22 deletions
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c
index c5328c8ba1d2..eb7de40828c7 100644
--- a/fs/nilfs2/super.c
+++ b/fs/nilfs2/super.c
@@ -77,12 +77,16 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data);
77static void nilfs_set_error(struct nilfs_sb_info *sbi) 77static void nilfs_set_error(struct nilfs_sb_info *sbi)
78{ 78{
79 struct the_nilfs *nilfs = sbi->s_nilfs; 79 struct the_nilfs *nilfs = sbi->s_nilfs;
80 struct nilfs_super_block **sbp;
80 81
81 down_write(&nilfs->ns_sem); 82 down_write(&nilfs->ns_sem);
82 if (!(nilfs->ns_mount_state & NILFS_ERROR_FS)) { 83 if (!(nilfs->ns_mount_state & NILFS_ERROR_FS)) {
83 nilfs->ns_mount_state |= NILFS_ERROR_FS; 84 nilfs->ns_mount_state |= NILFS_ERROR_FS;
84 nilfs->ns_sbp[0]->s_state |= cpu_to_le16(NILFS_ERROR_FS); 85 sbp = nilfs_prepare_super(sbi);
85 nilfs_commit_super(sbi, 1); 86 if (likely(sbp)) {
87 sbp[0]->s_state |= cpu_to_le16(NILFS_ERROR_FS);
88 nilfs_commit_super(sbi, 1);
89 }
86 } 90 }
87 up_write(&nilfs->ns_sem); 91 up_write(&nilfs->ns_sem);
88} 92}
@@ -253,22 +257,32 @@ void nilfs_set_log_cursor(struct nilfs_super_block *sbp,
253 spin_unlock(&nilfs->ns_last_segment_lock); 257 spin_unlock(&nilfs->ns_last_segment_lock);
254} 258}
255 259
256int nilfs_commit_super(struct nilfs_sb_info *sbi, int dupsb) 260struct nilfs_super_block **nilfs_prepare_super(struct nilfs_sb_info *sbi)
257{ 261{
258 struct the_nilfs *nilfs = sbi->s_nilfs; 262 struct the_nilfs *nilfs = sbi->s_nilfs;
259 struct nilfs_super_block **sbp = nilfs->ns_sbp; 263 struct nilfs_super_block **sbp = nilfs->ns_sbp;
260 time_t t;
261 264
262 /* nilfs->sem must be locked by the caller. */ 265 /* nilfs->ns_sem must be locked by the caller. */
263 if (sbp[0]->s_magic != cpu_to_le16(NILFS_SUPER_MAGIC)) { 266 if (sbp[0]->s_magic != cpu_to_le16(NILFS_SUPER_MAGIC)) {
264 if (sbp[1] && sbp[1]->s_magic == cpu_to_le16(NILFS_SUPER_MAGIC)) 267 if (sbp[1] &&
268 sbp[1]->s_magic == cpu_to_le16(NILFS_SUPER_MAGIC)) {
265 nilfs_swap_super_block(nilfs); 269 nilfs_swap_super_block(nilfs);
266 else { 270 } else {
267 printk(KERN_CRIT "NILFS: superblock broke on dev %s\n", 271 printk(KERN_CRIT "NILFS: superblock broke on dev %s\n",
268 sbi->s_super->s_id); 272 sbi->s_super->s_id);
269 return -EIO; 273 return NULL;
270 } 274 }
271 } 275 }
276 return sbp;
277}
278
279int nilfs_commit_super(struct nilfs_sb_info *sbi, int dupsb)
280{
281 struct the_nilfs *nilfs = sbi->s_nilfs;
282 struct nilfs_super_block **sbp = nilfs->ns_sbp;
283 time_t t;
284
285 /* nilfs->ns_sem must be locked by the caller. */
272 nilfs_set_log_cursor(sbp[0], nilfs); 286 nilfs_set_log_cursor(sbp[0], nilfs);
273 287
274 t = get_seconds(); 288 t = get_seconds();
@@ -296,11 +310,14 @@ int nilfs_commit_super(struct nilfs_sb_info *sbi, int dupsb)
296 */ 310 */
297int nilfs_cleanup_super(struct nilfs_sb_info *sbi) 311int nilfs_cleanup_super(struct nilfs_sb_info *sbi)
298{ 312{
299 struct nilfs_super_block **sbp = sbi->s_nilfs->ns_sbp; 313 struct nilfs_super_block **sbp;
300 int ret; 314 int ret = -EIO;
301 315
302 sbp[0]->s_state = cpu_to_le16(sbi->s_nilfs->ns_mount_state); 316 sbp = nilfs_prepare_super(sbi);
303 ret = nilfs_commit_super(sbi, 1); 317 if (sbp) {
318 sbp[0]->s_state = cpu_to_le16(sbi->s_nilfs->ns_mount_state);
319 ret = nilfs_commit_super(sbi, 1);
320 }
304 return ret; 321 return ret;
305} 322}
306 323
@@ -336,6 +353,7 @@ static int nilfs_sync_fs(struct super_block *sb, int wait)
336{ 353{
337 struct nilfs_sb_info *sbi = NILFS_SB(sb); 354 struct nilfs_sb_info *sbi = NILFS_SB(sb);
338 struct the_nilfs *nilfs = sbi->s_nilfs; 355 struct the_nilfs *nilfs = sbi->s_nilfs;
356 struct nilfs_super_block **sbp;
339 int err = 0; 357 int err = 0;
340 358
341 /* This function is called when super block should be written back */ 359 /* This function is called when super block should be written back */
@@ -343,8 +361,11 @@ static int nilfs_sync_fs(struct super_block *sb, int wait)
343 err = nilfs_construct_segment(sb); 361 err = nilfs_construct_segment(sb);
344 362
345 down_write(&nilfs->ns_sem); 363 down_write(&nilfs->ns_sem);
346 if (nilfs_sb_dirty(nilfs)) 364 if (nilfs_sb_dirty(nilfs)) {
347 nilfs_commit_super(sbi, 1); 365 sbp = nilfs_prepare_super(sbi);
366 if (likely(sbp))
367 nilfs_commit_super(sbi, 1);
368 }
348 up_write(&nilfs->ns_sem); 369 up_write(&nilfs->ns_sem);
349 370
350 return err; 371 return err;
@@ -638,11 +659,18 @@ nilfs_set_default_options(struct nilfs_sb_info *sbi,
638static int nilfs_setup_super(struct nilfs_sb_info *sbi) 659static int nilfs_setup_super(struct nilfs_sb_info *sbi)
639{ 660{
640 struct the_nilfs *nilfs = sbi->s_nilfs; 661 struct the_nilfs *nilfs = sbi->s_nilfs;
641 struct nilfs_super_block *sbp = nilfs->ns_sbp[0]; 662 struct nilfs_super_block **sbp;
642 int max_mnt_count = le16_to_cpu(sbp->s_max_mnt_count); 663 int max_mnt_count;
643 int mnt_count = le16_to_cpu(sbp->s_mnt_count); 664 int mnt_count;
665
666 /* nilfs->ns_sem must be locked by the caller. */
667 sbp = nilfs_prepare_super(sbi);
668 if (!sbp)
669 return -EIO;
670
671 max_mnt_count = le16_to_cpu(sbp[0]->s_max_mnt_count);
672 mnt_count = le16_to_cpu(sbp[0]->s_mnt_count);
644 673
645 /* nilfs->sem must be locked by the caller. */
646 if (nilfs->ns_mount_state & NILFS_ERROR_FS) { 674 if (nilfs->ns_mount_state & NILFS_ERROR_FS) {
647 printk(KERN_WARNING 675 printk(KERN_WARNING
648 "NILFS warning: mounting fs with errors\n"); 676 "NILFS warning: mounting fs with errors\n");
@@ -653,11 +681,12 @@ static int nilfs_setup_super(struct nilfs_sb_info *sbi)
653#endif 681#endif
654 } 682 }
655 if (!max_mnt_count) 683 if (!max_mnt_count)
656 sbp->s_max_mnt_count = cpu_to_le16(NILFS_DFL_MAX_MNT_COUNT); 684 sbp[0]->s_max_mnt_count = cpu_to_le16(NILFS_DFL_MAX_MNT_COUNT);
657 685
658 sbp->s_mnt_count = cpu_to_le16(mnt_count + 1); 686 sbp[0]->s_mnt_count = cpu_to_le16(mnt_count + 1);
659 sbp->s_state = cpu_to_le16(le16_to_cpu(sbp->s_state) & ~NILFS_VALID_FS); 687 sbp[0]->s_state =
660 sbp->s_mtime = cpu_to_le64(get_seconds()); 688 cpu_to_le16(le16_to_cpu(sbp[0]->s_state) & ~NILFS_VALID_FS);
689 sbp[0]->s_mtime = cpu_to_le64(get_seconds());
661 return nilfs_commit_super(sbi, 1); 690 return nilfs_commit_super(sbi, 1);
662} 691}
663 692