diff options
Diffstat (limited to 'fs/nilfs2')
-rw-r--r-- | fs/nilfs2/nilfs.h | 7 | ||||
-rw-r--r-- | fs/nilfs2/recovery.c | 1 | ||||
-rw-r--r-- | fs/nilfs2/segment.c | 8 | ||||
-rw-r--r-- | fs/nilfs2/segment.h | 2 | ||||
-rw-r--r-- | fs/nilfs2/super.c | 229 | ||||
-rw-r--r-- | fs/nilfs2/the_nilfs.c | 180 | ||||
-rw-r--r-- | fs/nilfs2/the_nilfs.h | 18 |
7 files changed, 270 insertions, 175 deletions
diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h index a7f5bc724e33..19af5ab86275 100644 --- a/fs/nilfs2/nilfs.h +++ b/fs/nilfs2/nilfs.h | |||
@@ -275,13 +275,10 @@ extern void nilfs_error(struct super_block *, const char *, const char *, ...) | |||
275 | extern void nilfs_warning(struct super_block *, const char *, const char *, ...) | 275 | extern void nilfs_warning(struct super_block *, const char *, const char *, ...) |
276 | __attribute__ ((format (printf, 3, 4))); | 276 | __attribute__ ((format (printf, 3, 4))); |
277 | extern struct nilfs_super_block * | 277 | extern struct nilfs_super_block * |
278 | nilfs_load_super_block(struct super_block *, struct buffer_head **); | 278 | nilfs_read_super_block(struct super_block *, u64, int, struct buffer_head **); |
279 | extern struct nilfs_super_block * | ||
280 | nilfs_reload_super_block(struct super_block *, struct buffer_head **, int); | ||
281 | extern int nilfs_store_magic_and_option(struct super_block *, | 279 | extern int nilfs_store_magic_and_option(struct super_block *, |
282 | struct nilfs_super_block *, char *); | 280 | struct nilfs_super_block *, char *); |
283 | extern void nilfs_update_last_segment(struct nilfs_sb_info *, int); | 281 | extern int nilfs_commit_super(struct nilfs_sb_info *, int); |
284 | extern int nilfs_commit_super(struct nilfs_sb_info *); | ||
285 | extern int nilfs_attach_checkpoint(struct nilfs_sb_info *, __u64); | 282 | extern int nilfs_attach_checkpoint(struct nilfs_sb_info *, __u64); |
286 | extern void nilfs_detach_checkpoint(struct nilfs_sb_info *); | 283 | extern void nilfs_detach_checkpoint(struct nilfs_sb_info *); |
287 | 284 | ||
diff --git a/fs/nilfs2/recovery.c b/fs/nilfs2/recovery.c index 6ab4c8fc5e9f..6ade0963fc1d 100644 --- a/fs/nilfs2/recovery.c +++ b/fs/nilfs2/recovery.c | |||
@@ -870,7 +870,6 @@ int nilfs_search_super_root(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, | |||
870 | if (scan_newer) | 870 | if (scan_newer) |
871 | ri->ri_need_recovery = NILFS_RECOVERY_SR_UPDATED; | 871 | ri->ri_need_recovery = NILFS_RECOVERY_SR_UPDATED; |
872 | else { | 872 | else { |
873 | nilfs->ns_prot_seq = ssi.seg_seq; | ||
874 | if (nilfs->ns_mount_state & NILFS_VALID_FS) | 873 | if (nilfs->ns_mount_state & NILFS_VALID_FS) |
875 | goto super_root_found; | 874 | goto super_root_found; |
876 | scan_newer = 1; | 875 | scan_newer = 1; |
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index e43558d50e78..fb70ec3be20e 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c | |||
@@ -2068,7 +2068,8 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci) | |||
2068 | 2068 | ||
2069 | if (update_sr) { | 2069 | if (update_sr) { |
2070 | nilfs_set_last_segment(nilfs, segbuf->sb_pseg_start, | 2070 | nilfs_set_last_segment(nilfs, segbuf->sb_pseg_start, |
2071 | segbuf->sb_sum.seg_seq, nilfs->ns_cno); | 2071 | segbuf->sb_sum.seg_seq, nilfs->ns_cno++); |
2072 | sbi->s_super->s_dirt = 1; | ||
2072 | 2073 | ||
2073 | clear_bit(NILFS_SC_HAVE_DELTA, &sci->sc_flags); | 2074 | clear_bit(NILFS_SC_HAVE_DELTA, &sci->sc_flags); |
2074 | clear_bit(NILFS_SC_DIRTY, &sci->sc_flags); | 2075 | clear_bit(NILFS_SC_DIRTY, &sci->sc_flags); |
@@ -2224,9 +2225,6 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode) | |||
2224 | 2225 | ||
2225 | /* Commit segments */ | 2226 | /* Commit segments */ |
2226 | if (has_sr) { | 2227 | if (has_sr) { |
2227 | down_write(&nilfs->ns_sem); | ||
2228 | nilfs_update_last_segment(sbi, 1); | ||
2229 | up_write(&nilfs->ns_sem); | ||
2230 | nilfs_segctor_commit_free_segments(sci); | 2228 | nilfs_segctor_commit_free_segments(sci); |
2231 | nilfs_segctor_clear_metadata_dirty(sci); | 2229 | nilfs_segctor_clear_metadata_dirty(sci); |
2232 | } | 2230 | } |
@@ -2564,7 +2562,7 @@ static int nilfs_segctor_construct(struct nilfs_sc_info *sci, | |||
2564 | if (test_bit(NILFS_SC_SUPER_ROOT, &sci->sc_flags) && | 2562 | if (test_bit(NILFS_SC_SUPER_ROOT, &sci->sc_flags) && |
2565 | nilfs_discontinued(nilfs)) { | 2563 | nilfs_discontinued(nilfs)) { |
2566 | down_write(&nilfs->ns_sem); | 2564 | down_write(&nilfs->ns_sem); |
2567 | req->sb_err = nilfs_commit_super(sbi); | 2565 | req->sb_err = nilfs_commit_super(sbi, 0); |
2568 | up_write(&nilfs->ns_sem); | 2566 | up_write(&nilfs->ns_sem); |
2569 | } | 2567 | } |
2570 | } | 2568 | } |
diff --git a/fs/nilfs2/segment.h b/fs/nilfs2/segment.h index 4a64eb82f1f5..a98fc1ed0bbb 100644 --- a/fs/nilfs2/segment.h +++ b/fs/nilfs2/segment.h | |||
@@ -206,8 +206,6 @@ enum { | |||
206 | logical segment with a super root */ | 206 | logical segment with a super root */ |
207 | #define NILFS_SC_DEFAULT_SR_FREQ 30 /* Maximum frequency of super root | 207 | #define NILFS_SC_DEFAULT_SR_FREQ 30 /* Maximum frequency of super root |
208 | creation */ | 208 | creation */ |
209 | #define NILFS_SC_DEFAULT_SB_FREQ 30 /* Minimum interval of periodical | ||
210 | update of superblock (reserved) */ | ||
211 | 209 | ||
212 | /* | 210 | /* |
213 | * The default threshold amount of data, in block counts. | 211 | * The default threshold amount of data, in block counts. |
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index ef31e9a51c84..e2ced824c624 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c | |||
@@ -103,8 +103,9 @@ void nilfs_error(struct super_block *sb, const char *function, | |||
103 | down_write(&nilfs->ns_sem); | 103 | down_write(&nilfs->ns_sem); |
104 | if (!(nilfs->ns_mount_state & NILFS_ERROR_FS)) { | 104 | if (!(nilfs->ns_mount_state & NILFS_ERROR_FS)) { |
105 | nilfs->ns_mount_state |= NILFS_ERROR_FS; | 105 | nilfs->ns_mount_state |= NILFS_ERROR_FS; |
106 | nilfs->ns_sbp->s_state |= cpu_to_le16(NILFS_ERROR_FS); | 106 | nilfs->ns_sbp[0]->s_state |= |
107 | nilfs_commit_super(sbi); | 107 | cpu_to_le16(NILFS_ERROR_FS); |
108 | nilfs_commit_super(sbi, 1); | ||
108 | } | 109 | } |
109 | up_write(&nilfs->ns_sem); | 110 | up_write(&nilfs->ns_sem); |
110 | 111 | ||
@@ -208,90 +209,106 @@ static void nilfs_clear_inode(struct inode *inode) | |||
208 | nilfs_btnode_cache_clear(&ii->i_btnode_cache); | 209 | nilfs_btnode_cache_clear(&ii->i_btnode_cache); |
209 | } | 210 | } |
210 | 211 | ||
211 | /** | 212 | static int nilfs_sync_super(struct nilfs_sb_info *sbi, int dupsb) |
212 | * nilfs_update_last_segment - change pointer to the latest segment | ||
213 | * @sbi: nilfs_sb_info | ||
214 | * @update_cno: flag whether to update checkpoint number. | ||
215 | * | ||
216 | * nilfs_update_last_segment() changes information in the super block | ||
217 | * after a partial segment is written out successfully. The super | ||
218 | * block is marked dirty. It will be written out at the next VFS sync | ||
219 | * operations such as sync_supers() and generic_shutdown_super(). | ||
220 | */ | ||
221 | void nilfs_update_last_segment(struct nilfs_sb_info *sbi, int update_cno) | ||
222 | { | ||
223 | struct the_nilfs *nilfs = sbi->s_nilfs; | ||
224 | struct nilfs_super_block *sbp = nilfs->ns_sbp; | ||
225 | |||
226 | /* nilfs->sem must be locked by the caller. */ | ||
227 | spin_lock(&nilfs->ns_last_segment_lock); | ||
228 | if (update_cno) | ||
229 | nilfs->ns_last_cno = nilfs->ns_cno++; | ||
230 | sbp->s_last_seq = cpu_to_le64(nilfs->ns_last_seq); | ||
231 | sbp->s_last_pseg = cpu_to_le64(nilfs->ns_last_pseg); | ||
232 | sbp->s_last_cno = cpu_to_le64(nilfs->ns_last_cno); | ||
233 | spin_unlock(&nilfs->ns_last_segment_lock); | ||
234 | |||
235 | sbi->s_super->s_dirt = 1; /* must be set if delaying the call of | ||
236 | nilfs_commit_super() */ | ||
237 | } | ||
238 | |||
239 | static int nilfs_sync_super(struct nilfs_sb_info *sbi) | ||
240 | { | 213 | { |
241 | struct the_nilfs *nilfs = sbi->s_nilfs; | 214 | struct the_nilfs *nilfs = sbi->s_nilfs; |
242 | int err; | 215 | int err; |
243 | int barrier_done = 0; | 216 | int barrier_done = 0; |
244 | 217 | ||
245 | if (nilfs_test_opt(sbi, BARRIER)) { | 218 | if (nilfs_test_opt(sbi, BARRIER)) { |
246 | set_buffer_ordered(nilfs->ns_sbh); | 219 | set_buffer_ordered(nilfs->ns_sbh[0]); |
247 | barrier_done = 1; | 220 | barrier_done = 1; |
248 | } | 221 | } |
249 | retry: | 222 | retry: |
250 | set_buffer_dirty(nilfs->ns_sbh); | 223 | set_buffer_dirty(nilfs->ns_sbh[0]); |
251 | err = sync_dirty_buffer(nilfs->ns_sbh); | 224 | err = sync_dirty_buffer(nilfs->ns_sbh[0]); |
252 | if (err == -EOPNOTSUPP && barrier_done) { | 225 | if (err == -EOPNOTSUPP && barrier_done) { |
253 | nilfs_warning(sbi->s_super, __func__, | 226 | nilfs_warning(sbi->s_super, __func__, |
254 | "barrier-based sync failed. " | 227 | "barrier-based sync failed. " |
255 | "disabling barriers\n"); | 228 | "disabling barriers\n"); |
256 | nilfs_clear_opt(sbi, BARRIER); | 229 | nilfs_clear_opt(sbi, BARRIER); |
257 | barrier_done = 0; | 230 | barrier_done = 0; |
258 | clear_buffer_ordered(nilfs->ns_sbh); | 231 | clear_buffer_ordered(nilfs->ns_sbh[0]); |
259 | goto retry; | 232 | goto retry; |
260 | } | 233 | } |
261 | if (unlikely(err)) | 234 | if (unlikely(err)) { |
262 | printk(KERN_ERR | 235 | printk(KERN_ERR |
263 | "NILFS: unable to write superblock (err=%d)\n", err); | 236 | "NILFS: unable to write superblock (err=%d)\n", err); |
264 | else { | 237 | if (err == -EIO && nilfs->ns_sbh[1]) { |
238 | nilfs_fall_back_super_block(nilfs); | ||
239 | goto retry; | ||
240 | } | ||
241 | } else { | ||
242 | struct nilfs_super_block *sbp = nilfs->ns_sbp[0]; | ||
243 | |||
244 | /* | ||
245 | * The latest segment becomes trailable from the position | ||
246 | * written in superblock. | ||
247 | */ | ||
265 | clear_nilfs_discontinued(nilfs); | 248 | clear_nilfs_discontinued(nilfs); |
266 | spin_lock(&nilfs->ns_last_segment_lock); | 249 | |
267 | nilfs->ns_prot_seq = le64_to_cpu(nilfs->ns_sbp->s_last_seq); | 250 | /* update GC protection for recent segments */ |
268 | spin_unlock(&nilfs->ns_last_segment_lock); | 251 | if (nilfs->ns_sbh[1]) { |
252 | sbp = NULL; | ||
253 | if (dupsb) { | ||
254 | set_buffer_dirty(nilfs->ns_sbh[1]); | ||
255 | if (!sync_dirty_buffer(nilfs->ns_sbh[1])) | ||
256 | sbp = nilfs->ns_sbp[1]; | ||
257 | } | ||
258 | } | ||
259 | if (sbp) { | ||
260 | spin_lock(&nilfs->ns_last_segment_lock); | ||
261 | nilfs->ns_prot_seq = le64_to_cpu(sbp->s_last_seq); | ||
262 | spin_unlock(&nilfs->ns_last_segment_lock); | ||
263 | } | ||
269 | } | 264 | } |
270 | 265 | ||
271 | return err; | 266 | return err; |
272 | } | 267 | } |
273 | 268 | ||
274 | int nilfs_commit_super(struct nilfs_sb_info *sbi) | 269 | int nilfs_commit_super(struct nilfs_sb_info *sbi, int dupsb) |
275 | { | 270 | { |
276 | struct the_nilfs *nilfs = sbi->s_nilfs; | 271 | struct the_nilfs *nilfs = sbi->s_nilfs; |
277 | struct nilfs_super_block *sbp = nilfs->ns_sbp; | 272 | struct nilfs_super_block **sbp = nilfs->ns_sbp; |
278 | sector_t nfreeblocks; | 273 | sector_t nfreeblocks; |
274 | time_t t; | ||
279 | int err; | 275 | int err; |
280 | 276 | ||
281 | /* nilfs->sem must be locked by the caller. */ | 277 | /* nilfs->sem must be locked by the caller. */ |
278 | if (sbp[0]->s_magic != NILFS_SUPER_MAGIC) { | ||
279 | if (sbp[1] && sbp[1]->s_magic == NILFS_SUPER_MAGIC) | ||
280 | nilfs_swap_super_block(nilfs); | ||
281 | else { | ||
282 | printk(KERN_CRIT "NILFS: superblock broke on dev %s\n", | ||
283 | sbi->s_super->s_id); | ||
284 | return -EIO; | ||
285 | } | ||
286 | } | ||
282 | err = nilfs_count_free_blocks(nilfs, &nfreeblocks); | 287 | err = nilfs_count_free_blocks(nilfs, &nfreeblocks); |
283 | if (unlikely(err)) { | 288 | if (unlikely(err)) { |
284 | printk(KERN_ERR "NILFS: failed to count free blocks\n"); | 289 | printk(KERN_ERR "NILFS: failed to count free blocks\n"); |
285 | return err; | 290 | return err; |
286 | } | 291 | } |
287 | sbp->s_free_blocks_count = cpu_to_le64(nfreeblocks); | 292 | spin_lock(&nilfs->ns_last_segment_lock); |
288 | sbp->s_wtime = cpu_to_le64(get_seconds()); | 293 | sbp[0]->s_last_seq = cpu_to_le64(nilfs->ns_last_seq); |
289 | sbp->s_sum = 0; | 294 | sbp[0]->s_last_pseg = cpu_to_le64(nilfs->ns_last_pseg); |
290 | sbp->s_sum = cpu_to_le32(crc32_le(nilfs->ns_crc_seed, | 295 | sbp[0]->s_last_cno = cpu_to_le64(nilfs->ns_last_cno); |
291 | (unsigned char *)sbp, | 296 | spin_unlock(&nilfs->ns_last_segment_lock); |
292 | le16_to_cpu(sbp->s_bytes))); | 297 | |
298 | t = get_seconds(); | ||
299 | nilfs->ns_sbwtime[0] = t; | ||
300 | sbp[0]->s_free_blocks_count = cpu_to_le64(nfreeblocks); | ||
301 | sbp[0]->s_wtime = cpu_to_le64(t); | ||
302 | sbp[0]->s_sum = 0; | ||
303 | sbp[0]->s_sum = cpu_to_le32(crc32_le(nilfs->ns_crc_seed, | ||
304 | (unsigned char *)sbp[0], | ||
305 | nilfs->ns_sbsize)); | ||
306 | if (dupsb && sbp[1]) { | ||
307 | memcpy(sbp[1], sbp[0], nilfs->ns_sbsize); | ||
308 | nilfs->ns_sbwtime[1] = t; | ||
309 | } | ||
293 | sbi->s_super->s_dirt = 0; | 310 | sbi->s_super->s_dirt = 0; |
294 | return nilfs_sync_super(sbi); | 311 | return nilfs_sync_super(sbi, dupsb); |
295 | } | 312 | } |
296 | 313 | ||
297 | static void nilfs_put_super(struct super_block *sb) | 314 | static void nilfs_put_super(struct super_block *sb) |
@@ -303,8 +320,8 @@ static void nilfs_put_super(struct super_block *sb) | |||
303 | 320 | ||
304 | if (!(sb->s_flags & MS_RDONLY)) { | 321 | if (!(sb->s_flags & MS_RDONLY)) { |
305 | down_write(&nilfs->ns_sem); | 322 | down_write(&nilfs->ns_sem); |
306 | nilfs->ns_sbp->s_state = cpu_to_le16(nilfs->ns_mount_state); | 323 | nilfs->ns_sbp[0]->s_state = cpu_to_le16(nilfs->ns_mount_state); |
307 | nilfs_commit_super(sbi); | 324 | nilfs_commit_super(sbi, 1); |
308 | up_write(&nilfs->ns_sem); | 325 | up_write(&nilfs->ns_sem); |
309 | } | 326 | } |
310 | 327 | ||
@@ -330,7 +347,7 @@ static void nilfs_put_super(struct super_block *sb) | |||
330 | * 2. down_write(&nilfs->ns_sem) | 347 | * 2. down_write(&nilfs->ns_sem) |
331 | * | 348 | * |
332 | * Inside NILFS, locking ns_sem is enough to protect s_dirt and the buffer | 349 | * Inside NILFS, locking ns_sem is enough to protect s_dirt and the buffer |
333 | * of the super block (nilfs->ns_sbp). | 350 | * of the super block (nilfs->ns_sbp[]). |
334 | * | 351 | * |
335 | * In most cases, VFS functions call lock_super() before calling these | 352 | * In most cases, VFS functions call lock_super() before calling these |
336 | * methods. So we must be careful not to bring on deadlocks when using | 353 | * methods. So we must be careful not to bring on deadlocks when using |
@@ -346,8 +363,19 @@ static void nilfs_write_super(struct super_block *sb) | |||
346 | struct the_nilfs *nilfs = sbi->s_nilfs; | 363 | struct the_nilfs *nilfs = sbi->s_nilfs; |
347 | 364 | ||
348 | down_write(&nilfs->ns_sem); | 365 | down_write(&nilfs->ns_sem); |
349 | if (!(sb->s_flags & MS_RDONLY)) | 366 | if (!(sb->s_flags & MS_RDONLY)) { |
350 | nilfs_commit_super(sbi); | 367 | struct nilfs_super_block **sbp = nilfs->ns_sbp; |
368 | u64 t = get_seconds(); | ||
369 | int dupsb; | ||
370 | |||
371 | if (!nilfs_discontinued(nilfs) && t >= nilfs->ns_sbwtime[0] && | ||
372 | t < nilfs->ns_sbwtime[0] + NILFS_SB_FREQ) { | ||
373 | up_write(&nilfs->ns_sem); | ||
374 | return; | ||
375 | } | ||
376 | dupsb = sbp[1] && t > nilfs->ns_sbwtime[1] + NILFS_ALTSB_FREQ; | ||
377 | nilfs_commit_super(sbi, dupsb); | ||
378 | } | ||
351 | sb->s_dirt = 0; | 379 | sb->s_dirt = 0; |
352 | up_write(&nilfs->ns_sem); | 380 | up_write(&nilfs->ns_sem); |
353 | } | 381 | } |
@@ -436,7 +464,7 @@ static int nilfs_mark_recovery_complete(struct nilfs_sb_info *sbi) | |||
436 | down_write(&nilfs->ns_sem); | 464 | down_write(&nilfs->ns_sem); |
437 | if (!(nilfs->ns_mount_state & NILFS_VALID_FS)) { | 465 | if (!(nilfs->ns_mount_state & NILFS_VALID_FS)) { |
438 | nilfs->ns_mount_state |= NILFS_VALID_FS; | 466 | nilfs->ns_mount_state |= NILFS_VALID_FS; |
439 | err = nilfs_commit_super(sbi); | 467 | err = nilfs_commit_super(sbi, 1); |
440 | if (likely(!err)) | 468 | if (likely(!err)) |
441 | printk(KERN_INFO "NILFS: recovery complete.\n"); | 469 | printk(KERN_INFO "NILFS: recovery complete.\n"); |
442 | } | 470 | } |
@@ -652,7 +680,7 @@ nilfs_set_default_options(struct nilfs_sb_info *sbi, | |||
652 | static int nilfs_setup_super(struct nilfs_sb_info *sbi) | 680 | static int nilfs_setup_super(struct nilfs_sb_info *sbi) |
653 | { | 681 | { |
654 | struct the_nilfs *nilfs = sbi->s_nilfs; | 682 | struct the_nilfs *nilfs = sbi->s_nilfs; |
655 | struct nilfs_super_block *sbp = nilfs->ns_sbp; | 683 | struct nilfs_super_block *sbp = nilfs->ns_sbp[0]; |
656 | int max_mnt_count = le16_to_cpu(sbp->s_max_mnt_count); | 684 | int max_mnt_count = le16_to_cpu(sbp->s_max_mnt_count); |
657 | int mnt_count = le16_to_cpu(sbp->s_mnt_count); | 685 | int mnt_count = le16_to_cpu(sbp->s_mnt_count); |
658 | 686 | ||
@@ -674,88 +702,29 @@ static int nilfs_setup_super(struct nilfs_sb_info *sbi) | |||
674 | sbp->s_mnt_count = cpu_to_le16(mnt_count + 1); | 702 | sbp->s_mnt_count = cpu_to_le16(mnt_count + 1); |
675 | sbp->s_state = cpu_to_le16(le16_to_cpu(sbp->s_state) & ~NILFS_VALID_FS); | 703 | sbp->s_state = cpu_to_le16(le16_to_cpu(sbp->s_state) & ~NILFS_VALID_FS); |
676 | sbp->s_mtime = cpu_to_le64(get_seconds()); | 704 | sbp->s_mtime = cpu_to_le64(get_seconds()); |
677 | return nilfs_commit_super(sbi); | 705 | return nilfs_commit_super(sbi, 1); |
678 | } | 706 | } |
679 | 707 | ||
680 | struct nilfs_super_block * | 708 | struct nilfs_super_block *nilfs_read_super_block(struct super_block *sb, |
681 | nilfs_load_super_block(struct super_block *sb, struct buffer_head **pbh) | 709 | u64 pos, int blocksize, |
710 | struct buffer_head **pbh) | ||
682 | { | 711 | { |
683 | int blocksize; | 712 | unsigned long long sb_index = pos; |
684 | unsigned long offset, sb_index; | 713 | unsigned long offset; |
685 | |||
686 | /* | ||
687 | * Adjusting block size | ||
688 | * Blocksize will be enlarged when it is smaller than hardware | ||
689 | * sector size. | ||
690 | * Disk format of superblock does not change. | ||
691 | */ | ||
692 | blocksize = sb_min_blocksize(sb, BLOCK_SIZE); | ||
693 | if (!blocksize) { | ||
694 | printk(KERN_ERR | ||
695 | "NILFS: unable to set blocksize of superblock\n"); | ||
696 | return NULL; | ||
697 | } | ||
698 | sb_index = NILFS_SB_OFFSET_BYTES / blocksize; | ||
699 | offset = NILFS_SB_OFFSET_BYTES % blocksize; | ||
700 | 714 | ||
715 | offset = do_div(sb_index, blocksize); | ||
701 | *pbh = sb_bread(sb, sb_index); | 716 | *pbh = sb_bread(sb, sb_index); |
702 | if (!*pbh) { | 717 | if (!*pbh) |
703 | printk(KERN_ERR "NILFS: unable to read superblock\n"); | ||
704 | return NULL; | 718 | return NULL; |
705 | } | ||
706 | return (struct nilfs_super_block *)((char *)(*pbh)->b_data + offset); | 719 | return (struct nilfs_super_block *)((char *)(*pbh)->b_data + offset); |
707 | } | 720 | } |
708 | 721 | ||
709 | struct nilfs_super_block * | ||
710 | nilfs_reload_super_block(struct super_block *sb, struct buffer_head **pbh, | ||
711 | int blocksize) | ||
712 | { | ||
713 | struct nilfs_super_block *sbp; | ||
714 | unsigned long offset, sb_index; | ||
715 | int hw_blocksize = bdev_hardsect_size(sb->s_bdev); | ||
716 | |||
717 | if (blocksize < hw_blocksize) { | ||
718 | printk(KERN_ERR | ||
719 | "NILFS: blocksize %d too small for device " | ||
720 | "(sector-size = %d).\n", | ||
721 | blocksize, hw_blocksize); | ||
722 | goto failed_sbh; | ||
723 | } | ||
724 | brelse(*pbh); | ||
725 | sb_set_blocksize(sb, blocksize); | ||
726 | |||
727 | sb_index = NILFS_SB_OFFSET_BYTES / blocksize; | ||
728 | offset = NILFS_SB_OFFSET_BYTES % blocksize; | ||
729 | |||
730 | *pbh = sb_bread(sb, sb_index); | ||
731 | if (!*pbh) { | ||
732 | printk(KERN_ERR | ||
733 | "NILFS: cannot read superblock on 2nd try.\n"); | ||
734 | goto failed; | ||
735 | } | ||
736 | |||
737 | sbp = (struct nilfs_super_block *)((char *)(*pbh)->b_data + offset); | ||
738 | if (sbp->s_magic != cpu_to_le16(NILFS_SUPER_MAGIC)) { | ||
739 | printk(KERN_ERR | ||
740 | "NILFS: !? Magic mismatch on 2nd try.\n"); | ||
741 | goto failed_sbh; | ||
742 | } | ||
743 | return sbp; | ||
744 | |||
745 | failed_sbh: | ||
746 | brelse(*pbh); | ||
747 | |||
748 | failed: | ||
749 | return NULL; | ||
750 | } | ||
751 | |||
752 | int nilfs_store_magic_and_option(struct super_block *sb, | 722 | int nilfs_store_magic_and_option(struct super_block *sb, |
753 | struct nilfs_super_block *sbp, | 723 | struct nilfs_super_block *sbp, |
754 | char *data) | 724 | char *data) |
755 | { | 725 | { |
756 | struct nilfs_sb_info *sbi = NILFS_SB(sb); | 726 | struct nilfs_sb_info *sbi = NILFS_SB(sb); |
757 | 727 | ||
758 | /* trying to fill super (1st stage) */ | ||
759 | sb->s_magic = le16_to_cpu(sbp->s_magic); | 728 | sb->s_magic = le16_to_cpu(sbp->s_magic); |
760 | 729 | ||
761 | /* FS independent flags */ | 730 | /* FS independent flags */ |
@@ -763,11 +732,6 @@ int nilfs_store_magic_and_option(struct super_block *sb, | |||
763 | sb->s_flags |= MS_NOATIME; | 732 | sb->s_flags |= MS_NOATIME; |
764 | #endif | 733 | #endif |
765 | 734 | ||
766 | if (sb->s_magic != NILFS_SUPER_MAGIC) { | ||
767 | printk("NILFS: Can't find nilfs on dev %s.\n", sb->s_id); | ||
768 | return -EINVAL; | ||
769 | } | ||
770 | |||
771 | nilfs_set_default_options(sbi, sbp); | 735 | nilfs_set_default_options(sbi, sbp); |
772 | 736 | ||
773 | sbi->s_resuid = le16_to_cpu(sbp->s_def_resuid); | 737 | sbi->s_resuid = le16_to_cpu(sbp->s_def_resuid); |
@@ -775,10 +739,7 @@ int nilfs_store_magic_and_option(struct super_block *sb, | |||
775 | sbi->s_interval = le32_to_cpu(sbp->s_c_interval); | 739 | sbi->s_interval = le32_to_cpu(sbp->s_c_interval); |
776 | sbi->s_watermark = le32_to_cpu(sbp->s_c_block_max); | 740 | sbi->s_watermark = le32_to_cpu(sbp->s_c_block_max); |
777 | 741 | ||
778 | if (!parse_options(data, sb)) | 742 | return !parse_options(data, sb) ? -EINVAL : 0 ; |
779 | return -EINVAL; | ||
780 | |||
781 | return 0; | ||
782 | } | 743 | } |
783 | 744 | ||
784 | /** | 745 | /** |
@@ -967,12 +928,12 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) | |||
967 | * the RDONLY flag and then mark the partition as valid again. | 928 | * the RDONLY flag and then mark the partition as valid again. |
968 | */ | 929 | */ |
969 | down_write(&nilfs->ns_sem); | 930 | down_write(&nilfs->ns_sem); |
970 | sbp = nilfs->ns_sbp; | 931 | sbp = nilfs->ns_sbp[0]; |
971 | if (!(sbp->s_state & le16_to_cpu(NILFS_VALID_FS)) && | 932 | if (!(sbp->s_state & le16_to_cpu(NILFS_VALID_FS)) && |
972 | (nilfs->ns_mount_state & NILFS_VALID_FS)) | 933 | (nilfs->ns_mount_state & NILFS_VALID_FS)) |
973 | sbp->s_state = cpu_to_le16(nilfs->ns_mount_state); | 934 | sbp->s_state = cpu_to_le16(nilfs->ns_mount_state); |
974 | sbp->s_mtime = cpu_to_le64(get_seconds()); | 935 | sbp->s_mtime = cpu_to_le64(get_seconds()); |
975 | nilfs_commit_super(sbi); | 936 | nilfs_commit_super(sbi, 1); |
976 | up_write(&nilfs->ns_sem); | 937 | up_write(&nilfs->ns_sem); |
977 | } else { | 938 | } else { |
978 | /* | 939 | /* |
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 | ||
299 | static int | 299 | static int nilfs_store_disk_layout(struct the_nilfs *nilfs, |
300 | nilfs_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 | ||
336 | static 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 | |||
356 | static 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 | |||
363 | static 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 | |||
376 | void 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 | |||
385 | void 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 | |||
396 | static 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, | |||
352 | int init_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, char *data) | 471 | int 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 | ||
diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h index d750e48257c9..30fe58778d05 100644 --- a/fs/nilfs2/the_nilfs.h +++ b/fs/nilfs2/the_nilfs.h | |||
@@ -49,8 +49,10 @@ enum { | |||
49 | * @ns_sem: semaphore for shared states | 49 | * @ns_sem: semaphore for shared states |
50 | * @ns_writer_mutex: mutex protecting ns_writer attach/detach | 50 | * @ns_writer_mutex: mutex protecting ns_writer attach/detach |
51 | * @ns_writer_refcount: number of referrers on ns_writer | 51 | * @ns_writer_refcount: number of referrers on ns_writer |
52 | * @ns_sbh: buffer head of the on-disk super block | 52 | * @ns_sbh: buffer heads of on-disk super blocks |
53 | * @ns_sbp: pointer to the super block data | 53 | * @ns_sbp: pointers to super block data |
54 | * @ns_sbwtime: previous write time of super blocks | ||
55 | * @ns_sbsize: size of valid data in super block | ||
54 | * @ns_supers: list of nilfs super block structs | 56 | * @ns_supers: list of nilfs super block structs |
55 | * @ns_seg_seq: segment sequence counter | 57 | * @ns_seg_seq: segment sequence counter |
56 | * @ns_segnum: index number of the latest full segment. | 58 | * @ns_segnum: index number of the latest full segment. |
@@ -101,8 +103,10 @@ struct the_nilfs { | |||
101 | * - protecting s_dirt in the super_block struct | 103 | * - protecting s_dirt in the super_block struct |
102 | * (see nilfs_write_super) and the following fields. | 104 | * (see nilfs_write_super) and the following fields. |
103 | */ | 105 | */ |
104 | struct buffer_head *ns_sbh; | 106 | struct buffer_head *ns_sbh[2]; |
105 | struct nilfs_super_block *ns_sbp; | 107 | struct nilfs_super_block *ns_sbp[2]; |
108 | time_t ns_sbwtime[2]; | ||
109 | unsigned ns_sbsize; | ||
106 | unsigned ns_mount_state; | 110 | unsigned ns_mount_state; |
107 | struct list_head ns_supers; | 111 | struct list_head ns_supers; |
108 | 112 | ||
@@ -182,6 +186,10 @@ THE_NILFS_FNS(INIT, init) | |||
182 | THE_NILFS_FNS(LOADED, loaded) | 186 | THE_NILFS_FNS(LOADED, loaded) |
183 | THE_NILFS_FNS(DISCONTINUED, discontinued) | 187 | THE_NILFS_FNS(DISCONTINUED, discontinued) |
184 | 188 | ||
189 | /* Minimum interval of periodical update of superblocks (in seconds) */ | ||
190 | #define NILFS_SB_FREQ 10 | ||
191 | #define NILFS_ALTSB_FREQ 60 /* spare superblock */ | ||
192 | |||
185 | void nilfs_set_last_segment(struct the_nilfs *, sector_t, u64, __u64); | 193 | void nilfs_set_last_segment(struct the_nilfs *, sector_t, u64, __u64); |
186 | struct the_nilfs *alloc_nilfs(struct block_device *); | 194 | struct the_nilfs *alloc_nilfs(struct block_device *); |
187 | void put_nilfs(struct the_nilfs *); | 195 | void put_nilfs(struct the_nilfs *); |
@@ -190,6 +198,8 @@ int load_nilfs(struct the_nilfs *, struct nilfs_sb_info *); | |||
190 | int nilfs_count_free_blocks(struct the_nilfs *, sector_t *); | 198 | int nilfs_count_free_blocks(struct the_nilfs *, sector_t *); |
191 | int nilfs_checkpoint_is_mounted(struct the_nilfs *, __u64, int); | 199 | int nilfs_checkpoint_is_mounted(struct the_nilfs *, __u64, int); |
192 | int nilfs_near_disk_full(struct the_nilfs *); | 200 | int nilfs_near_disk_full(struct the_nilfs *); |
201 | void nilfs_fall_back_super_block(struct the_nilfs *); | ||
202 | void nilfs_swap_super_block(struct the_nilfs *); | ||
193 | 203 | ||
194 | 204 | ||
195 | static inline void get_nilfs(struct the_nilfs *nilfs) | 205 | static inline void get_nilfs(struct the_nilfs *nilfs) |