aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nilfs2
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
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')
-rw-r--r--fs/nilfs2/nilfs.h1
-rw-r--r--fs/nilfs2/segment.c8
-rw-r--r--fs/nilfs2/super.c73
3 files changed, 58 insertions, 24 deletions
diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h
index 6718616183b7..462651061b03 100644
--- a/fs/nilfs2/nilfs.h
+++ b/fs/nilfs2/nilfs.h
@@ -272,6 +272,7 @@ extern int nilfs_store_magic_and_option(struct super_block *,
272 struct nilfs_super_block *, char *); 272 struct nilfs_super_block *, char *);
273extern void nilfs_set_log_cursor(struct nilfs_super_block *, 273extern void nilfs_set_log_cursor(struct nilfs_super_block *,
274 struct the_nilfs *); 274 struct the_nilfs *);
275extern struct nilfs_super_block **nilfs_prepare_super(struct nilfs_sb_info *);
275extern int nilfs_commit_super(struct nilfs_sb_info *, int); 276extern int nilfs_commit_super(struct nilfs_sb_info *, int);
276extern int nilfs_cleanup_super(struct nilfs_sb_info *); 277extern int nilfs_cleanup_super(struct nilfs_sb_info *);
277extern int nilfs_attach_checkpoint(struct nilfs_sb_info *, __u64); 278extern int nilfs_attach_checkpoint(struct nilfs_sb_info *, __u64);
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c
index 1f7881ca01c4..9e680a93b13a 100644
--- a/fs/nilfs2/segment.c
+++ b/fs/nilfs2/segment.c
@@ -2408,6 +2408,7 @@ static int nilfs_segctor_construct(struct nilfs_sc_info *sci, int mode)
2408{ 2408{
2409 struct nilfs_sb_info *sbi = sci->sc_sbi; 2409 struct nilfs_sb_info *sbi = sci->sc_sbi;
2410 struct the_nilfs *nilfs = sbi->s_nilfs; 2410 struct the_nilfs *nilfs = sbi->s_nilfs;
2411 struct nilfs_super_block **sbp;
2411 int err = 0; 2412 int err = 0;
2412 2413
2413 nilfs_segctor_accept(sci); 2414 nilfs_segctor_accept(sci);
@@ -2423,8 +2424,11 @@ static int nilfs_segctor_construct(struct nilfs_sc_info *sci, int mode)
2423 if (test_bit(NILFS_SC_SUPER_ROOT, &sci->sc_flags) && 2424 if (test_bit(NILFS_SC_SUPER_ROOT, &sci->sc_flags) &&
2424 nilfs_discontinued(nilfs)) { 2425 nilfs_discontinued(nilfs)) {
2425 down_write(&nilfs->ns_sem); 2426 down_write(&nilfs->ns_sem);
2426 err = nilfs_commit_super( 2427 err = -EIO;
2427 sbi, nilfs_altsb_need_update(nilfs)); 2428 sbp = nilfs_prepare_super(sbi);
2429 if (likely(sbp))
2430 err = nilfs_commit_super(
2431 sbi, nilfs_altsb_need_update(nilfs));
2428 up_write(&nilfs->ns_sem); 2432 up_write(&nilfs->ns_sem);
2429 } 2433 }
2430 } 2434 }
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