aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nilfs2/recovery.c32
-rw-r--r--fs/nilfs2/segment.c39
-rw-r--r--fs/nilfs2/sufile.c8
-rw-r--r--fs/nilfs2/super.c4
-rw-r--r--fs/nilfs2/the_nilfs.c18
-rw-r--r--fs/nilfs2/the_nilfs.h5
-rw-r--r--include/linux/nilfs2_fs.h10
7 files changed, 41 insertions, 75 deletions
diff --git a/fs/nilfs2/recovery.c b/fs/nilfs2/recovery.c
index 877dc1ba23f3..a4253f34e138 100644
--- a/fs/nilfs2/recovery.c
+++ b/fs/nilfs2/recovery.c
@@ -416,6 +416,7 @@ static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs,
416 struct nilfs_segment_entry *ent, *n; 416 struct nilfs_segment_entry *ent, *n;
417 struct inode *sufile = nilfs->ns_sufile; 417 struct inode *sufile = nilfs->ns_sufile;
418 __u64 segnum[4]; 418 __u64 segnum[4];
419 time_t mtime;
419 int err; 420 int err;
420 int i; 421 int i;
421 422
@@ -442,9 +443,9 @@ static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs,
442 443
443 /* 444 /*
444 * Collecting segments written after the latest super root. 445 * Collecting segments written after the latest super root.
445 * These are marked volatile active, and won't be reallocated in 446 * These are marked dirty to avoid being reallocated in the next write.
446 * the next construction.
447 */ 447 */
448 mtime = get_seconds();
448 list_for_each_entry_safe(ent, n, head, list) { 449 list_for_each_entry_safe(ent, n, head, list) {
449 if (ent->segnum == segnum[0]) { 450 if (ent->segnum == segnum[0]) {
450 list_del(&ent->list); 451 list_del(&ent->list);
@@ -454,17 +455,16 @@ static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs,
454 err = nilfs_open_segment_entry(ent, sufile); 455 err = nilfs_open_segment_entry(ent, sufile);
455 if (unlikely(err)) 456 if (unlikely(err))
456 goto failed; 457 goto failed;
457 if (nilfs_segment_usage_clean(ent->raw_su)) { 458 if (!nilfs_segment_usage_dirty(ent->raw_su)) {
458 nilfs_segment_usage_set_volatile_active(ent->raw_su); 459 /* make the segment garbage */
459 /* Keep it open */ 460 ent->raw_su->su_nblocks = cpu_to_le32(0);
460 } else { 461 ent->raw_su->su_lastmod = cpu_to_le32(mtime);
461 /* Removing duplicated entries */ 462 nilfs_segment_usage_set_dirty(ent->raw_su);
462 list_del(&ent->list);
463 nilfs_close_segment_entry(ent, sufile);
464 nilfs_free_segment_entry(ent);
465 } 463 }
464 list_del(&ent->list);
465 nilfs_close_segment_entry(ent, sufile);
466 nilfs_free_segment_entry(ent);
466 } 467 }
467 list_splice_init(head, nilfs->ns_used_segments.prev);
468 468
469 /* 469 /*
470 * The segment having the latest super root is active, and 470 * The segment having the latest super root is active, and
@@ -882,10 +882,12 @@ int nilfs_search_super_root(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi,
882 882
883 if (scan_newer) 883 if (scan_newer)
884 ri->ri_need_recovery = NILFS_RECOVERY_SR_UPDATED; 884 ri->ri_need_recovery = NILFS_RECOVERY_SR_UPDATED;
885 else if (nilfs->ns_mount_state & NILFS_VALID_FS) 885 else {
886 goto super_root_found; 886 nilfs->ns_prot_seq = ssi.seg_seq;
887 887 if (nilfs->ns_mount_state & NILFS_VALID_FS)
888 scan_newer = 1; 888 goto super_root_found;
889 scan_newer = 1;
890 }
889 891
890 /* reset region for roll-forward */ 892 /* reset region for roll-forward */
891 pseg_start += ssi.nblocks; 893 pseg_start += ssi.nblocks;
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c
index 5db12d774a03..24d0fbd4271c 100644
--- a/fs/nilfs2/segment.c
+++ b/fs/nilfs2/segment.c
@@ -2229,13 +2229,6 @@ static void nilfs_segctor_reactivate_segments(struct nilfs_sc_info *sci,
2229 nilfs_segment_usage_set_active(ent->raw_su); 2229 nilfs_segment_usage_set_active(ent->raw_su);
2230 nilfs_close_segment_entry(ent, sufile); 2230 nilfs_close_segment_entry(ent, sufile);
2231 } 2231 }
2232
2233 down_write(&nilfs->ns_sem);
2234 head = &nilfs->ns_used_segments;
2235 list_for_each_entry(ent, head, list) {
2236 nilfs_segment_usage_set_volatile_active(ent->raw_su);
2237 }
2238 up_write(&nilfs->ns_sem);
2239} 2232}
2240 2233
2241static int nilfs_segctor_deactivate_segments(struct nilfs_sc_info *sci, 2234static int nilfs_segctor_deactivate_segments(struct nilfs_sc_info *sci,
@@ -2244,7 +2237,6 @@ static int nilfs_segctor_deactivate_segments(struct nilfs_sc_info *sci,
2244 struct nilfs_segment_buffer *segbuf, *last; 2237 struct nilfs_segment_buffer *segbuf, *last;
2245 struct nilfs_segment_entry *ent; 2238 struct nilfs_segment_entry *ent;
2246 struct inode *sufile = nilfs->ns_sufile; 2239 struct inode *sufile = nilfs->ns_sufile;
2247 struct list_head *head;
2248 int err; 2240 int err;
2249 2241
2250 last = NILFS_LAST_SEGBUF(&sci->sc_segbufs); 2242 last = NILFS_LAST_SEGBUF(&sci->sc_segbufs);
@@ -2265,22 +2257,13 @@ static int nilfs_segctor_deactivate_segments(struct nilfs_sc_info *sci,
2265 BUG_ON(!buffer_dirty(ent->bh_su)); 2257 BUG_ON(!buffer_dirty(ent->bh_su));
2266 } 2258 }
2267 2259
2268 head = &sci->sc_active_segments; 2260 list_for_each_entry(ent, &sci->sc_active_segments, list) {
2269 list_for_each_entry(ent, head, list) {
2270 err = nilfs_open_segment_entry(ent, sufile); 2261 err = nilfs_open_segment_entry(ent, sufile);
2271 if (unlikely(err)) 2262 if (unlikely(err))
2272 goto failed; 2263 goto failed;
2273 nilfs_segment_usage_clear_active(ent->raw_su); 2264 nilfs_segment_usage_clear_active(ent->raw_su);
2274 BUG_ON(!buffer_dirty(ent->bh_su)); 2265 BUG_ON(!buffer_dirty(ent->bh_su));
2275 } 2266 }
2276
2277 down_write(&nilfs->ns_sem);
2278 head = &nilfs->ns_used_segments;
2279 list_for_each_entry(ent, head, list) {
2280 /* clear volatile active for segments of older generations */
2281 nilfs_segment_usage_clear_volatile_active(ent->raw_su);
2282 }
2283 up_write(&nilfs->ns_sem);
2284 return 0; 2267 return 0;
2285 2268
2286 failed: 2269 failed:
@@ -2304,19 +2287,15 @@ static void nilfs_segctor_bead_completed_segments(struct nilfs_sc_info *sci)
2304 } 2287 }
2305} 2288}
2306 2289
2307static void 2290static void nilfs_segctor_commit_deactivate_segments(struct nilfs_sc_info *sci,
2308__nilfs_segctor_commit_deactivate_segments(struct nilfs_sc_info *sci, 2291 struct the_nilfs *nilfs)
2309 struct the_nilfs *nilfs)
2310
2311{ 2292{
2312 struct nilfs_segment_entry *ent; 2293 struct nilfs_segment_entry *ent, *n;
2313
2314 list_splice_init(&sci->sc_active_segments,
2315 nilfs->ns_used_segments.prev);
2316 2294
2317 list_for_each_entry(ent, &nilfs->ns_used_segments, list) { 2295 list_for_each_entry_safe(ent, n, &sci->sc_active_segments, list) {
2318 nilfs_segment_usage_set_volatile_active(ent->raw_su); 2296 list_del(&ent->list);
2319 /* These segments are kept open */ 2297 nilfs_close_segment_entry(ent, nilfs->ns_sufile);
2298 nilfs_free_segment_entry(ent);
2320 } 2299 }
2321} 2300}
2322 2301
@@ -2405,8 +2384,8 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode)
2405 if (has_sr) { 2384 if (has_sr) {
2406 down_write(&nilfs->ns_sem); 2385 down_write(&nilfs->ns_sem);
2407 nilfs_update_last_segment(sbi, 1); 2386 nilfs_update_last_segment(sbi, 1);
2408 __nilfs_segctor_commit_deactivate_segments(sci, nilfs);
2409 up_write(&nilfs->ns_sem); 2387 up_write(&nilfs->ns_sem);
2388 nilfs_segctor_commit_deactivate_segments(sci, nilfs);
2410 nilfs_segctor_commit_free_segments(sci); 2389 nilfs_segctor_commit_free_segments(sci);
2411 nilfs_segctor_clear_metadata_dirty(sci); 2390 nilfs_segctor_clear_metadata_dirty(sci);
2412 } 2391 }
diff --git a/fs/nilfs2/sufile.c b/fs/nilfs2/sufile.c
index b3674a8162a1..cc714c72b138 100644
--- a/fs/nilfs2/sufile.c
+++ b/fs/nilfs2/sufile.c
@@ -446,6 +446,7 @@ int nilfs_sufile_get_stat(struct inode *sufile, struct nilfs_sustat *sustat)
446{ 446{
447 struct buffer_head *header_bh; 447 struct buffer_head *header_bh;
448 struct nilfs_sufile_header *header; 448 struct nilfs_sufile_header *header;
449 struct the_nilfs *nilfs = NILFS_MDT(sufile)->mi_nilfs;
449 void *kaddr; 450 void *kaddr;
450 int ret; 451 int ret;
451 452
@@ -460,8 +461,11 @@ int nilfs_sufile_get_stat(struct inode *sufile, struct nilfs_sustat *sustat)
460 sustat->ss_nsegs = nilfs_sufile_get_nsegments(sufile); 461 sustat->ss_nsegs = nilfs_sufile_get_nsegments(sufile);
461 sustat->ss_ncleansegs = le64_to_cpu(header->sh_ncleansegs); 462 sustat->ss_ncleansegs = le64_to_cpu(header->sh_ncleansegs);
462 sustat->ss_ndirtysegs = le64_to_cpu(header->sh_ndirtysegs); 463 sustat->ss_ndirtysegs = le64_to_cpu(header->sh_ndirtysegs);
463 sustat->ss_ctime = NILFS_MDT(sufile)->mi_nilfs->ns_ctime; 464 sustat->ss_ctime = nilfs->ns_ctime;
464 sustat->ss_nongc_ctime = NILFS_MDT(sufile)->mi_nilfs->ns_nongc_ctime; 465 sustat->ss_nongc_ctime = nilfs->ns_nongc_ctime;
466 spin_lock(&nilfs->ns_last_segment_lock);
467 sustat->ss_prot_seq = nilfs->ns_prot_seq;
468 spin_unlock(&nilfs->ns_last_segment_lock);
465 kunmap_atomic(kaddr, KM_USER0); 469 kunmap_atomic(kaddr, KM_USER0);
466 brelse(header_bh); 470 brelse(header_bh);
467 471
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c
index 268b563d215a..2f0e9f7bf152 100644
--- a/fs/nilfs2/super.c
+++ b/fs/nilfs2/super.c
@@ -262,8 +262,10 @@ static int nilfs_sync_super(struct nilfs_sb_info *sbi)
262 printk(KERN_ERR 262 printk(KERN_ERR
263 "NILFS: unable to write superblock (err=%d)\n", err); 263 "NILFS: unable to write superblock (err=%d)\n", err);
264 else { 264 else {
265 nilfs_dispose_used_segments(nilfs);
266 clear_nilfs_discontinued(nilfs); 265 clear_nilfs_discontinued(nilfs);
266 spin_lock(&nilfs->ns_last_segment_lock);
267 nilfs->ns_prot_seq = le64_to_cpu(nilfs->ns_sbp->s_last_seq);
268 spin_unlock(&nilfs->ns_last_segment_lock);
267 } 269 }
268 270
269 return err; 271 return err;
diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c
index 69b625586226..661ab762d765 100644
--- a/fs/nilfs2/the_nilfs.c
+++ b/fs/nilfs2/the_nilfs.c
@@ -71,7 +71,6 @@ struct the_nilfs *alloc_nilfs(struct block_device *bdev)
71 INIT_LIST_HEAD(&nilfs->ns_supers); 71 INIT_LIST_HEAD(&nilfs->ns_supers);
72 spin_lock_init(&nilfs->ns_last_segment_lock); 72 spin_lock_init(&nilfs->ns_last_segment_lock);
73 nilfs->ns_gc_inodes_h = NULL; 73 nilfs->ns_gc_inodes_h = NULL;
74 INIT_LIST_HEAD(&nilfs->ns_used_segments);
75 init_rwsem(&nilfs->ns_segctor_sem); 74 init_rwsem(&nilfs->ns_segctor_sem);
76 75
77 return nilfs; 76 return nilfs;
@@ -95,7 +94,6 @@ void put_nilfs(struct the_nilfs *nilfs)
95 */ 94 */
96 might_sleep(); 95 might_sleep();
97 if (nilfs_loaded(nilfs)) { 96 if (nilfs_loaded(nilfs)) {
98 nilfs_dispose_used_segments(nilfs);
99 nilfs_mdt_clear(nilfs->ns_sufile); 97 nilfs_mdt_clear(nilfs->ns_sufile);
100 nilfs_mdt_destroy(nilfs->ns_sufile); 98 nilfs_mdt_destroy(nilfs->ns_sufile);
101 nilfs_mdt_clear(nilfs->ns_cpfile); 99 nilfs_mdt_clear(nilfs->ns_cpfile);
@@ -463,22 +461,6 @@ int nilfs_count_free_blocks(struct the_nilfs *nilfs, sector_t *nblocks)
463 return err; 461 return err;
464} 462}
465 463
466void nilfs_dispose_used_segments(struct the_nilfs *nilfs)
467{
468 struct nilfs_segment_entry *ent, *n;
469
470 /* nilfs->sem must be locked by the caller. */
471 if (!nilfs_loaded(nilfs))
472 return;
473
474 list_for_each_entry_safe(ent, n, &nilfs->ns_used_segments, list) {
475 list_del_init(&ent->list);
476 nilfs_segment_usage_clear_volatile_active(ent->raw_su);
477 nilfs_close_segment_entry(ent, nilfs->ns_sufile);
478 nilfs_free_segment_entry(ent);
479 }
480}
481
482int nilfs_near_disk_full(struct the_nilfs *nilfs) 464int nilfs_near_disk_full(struct the_nilfs *nilfs)
483{ 465{
484 struct inode *sufile = nilfs->ns_sufile; 466 struct inode *sufile = nilfs->ns_sufile;
diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h
index 75da37306964..af566e78f7af 100644
--- a/fs/nilfs2/the_nilfs.h
+++ b/fs/nilfs2/the_nilfs.h
@@ -51,7 +51,6 @@ enum {
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 head of the on-disk super block
53 * @ns_sbp: pointer to the super block data 53 * @ns_sbp: pointer to the super block data
54 * @ns_used_segments: list of full segments in volatile active state
55 * @ns_supers: list of nilfs super block structs 54 * @ns_supers: list of nilfs super block structs
56 * @ns_seg_seq: segment sequence counter 55 * @ns_seg_seq: segment sequence counter
57 * @ns_segnum: index number of the latest full segment. 56 * @ns_segnum: index number of the latest full segment.
@@ -65,6 +64,7 @@ enum {
65 * @ns_last_pseg: start block number of the latest segment 64 * @ns_last_pseg: start block number of the latest segment
66 * @ns_last_seq: sequence value of the latest segment 65 * @ns_last_seq: sequence value of the latest segment
67 * @ns_last_cno: checkpoint number of the latest segment 66 * @ns_last_cno: checkpoint number of the latest segment
67 * @ns_prot_seq: least sequence number of segments which must not be reclaimed
68 * @ns_free_segments_count: counter of free segments 68 * @ns_free_segments_count: counter of free segments
69 * @ns_segctor_sem: segment constructor semaphore 69 * @ns_segctor_sem: segment constructor semaphore
70 * @ns_dat: DAT file inode 70 * @ns_dat: DAT file inode
@@ -103,7 +103,6 @@ struct the_nilfs {
103 */ 103 */
104 struct buffer_head *ns_sbh; 104 struct buffer_head *ns_sbh;
105 struct nilfs_super_block *ns_sbp; 105 struct nilfs_super_block *ns_sbp;
106 struct list_head ns_used_segments;
107 unsigned ns_mount_state; 106 unsigned ns_mount_state;
108 struct list_head ns_supers; 107 struct list_head ns_supers;
109 108
@@ -132,6 +131,7 @@ struct the_nilfs {
132 sector_t ns_last_pseg; 131 sector_t ns_last_pseg;
133 u64 ns_last_seq; 132 u64 ns_last_seq;
134 __u64 ns_last_cno; 133 __u64 ns_last_cno;
134 u64 ns_prot_seq;
135 unsigned long ns_free_segments_count; 135 unsigned long ns_free_segments_count;
136 136
137 struct rw_semaphore ns_segctor_sem; 137 struct rw_semaphore ns_segctor_sem;
@@ -188,7 +188,6 @@ void put_nilfs(struct the_nilfs *);
188int init_nilfs(struct the_nilfs *, struct nilfs_sb_info *, char *); 188int init_nilfs(struct the_nilfs *, struct nilfs_sb_info *, char *);
189int load_nilfs(struct the_nilfs *, struct nilfs_sb_info *); 189int load_nilfs(struct the_nilfs *, struct nilfs_sb_info *);
190int nilfs_count_free_blocks(struct the_nilfs *, sector_t *); 190int nilfs_count_free_blocks(struct the_nilfs *, sector_t *);
191void nilfs_dispose_used_segments(struct the_nilfs *);
192int nilfs_checkpoint_is_mounted(struct the_nilfs *, __u64, int); 191int nilfs_checkpoint_is_mounted(struct the_nilfs *, __u64, int);
193int nilfs_near_disk_full(struct the_nilfs *); 192int nilfs_near_disk_full(struct the_nilfs *);
194 193
diff --git a/include/linux/nilfs2_fs.h b/include/linux/nilfs2_fs.h
index 306c446e694e..aa93f0ee29d4 100644
--- a/include/linux/nilfs2_fs.h
+++ b/include/linux/nilfs2_fs.h
@@ -565,8 +565,6 @@ enum {
565 NILFS_SEGMENT_USAGE_DIRTY, 565 NILFS_SEGMENT_USAGE_DIRTY,
566 NILFS_SEGMENT_USAGE_ERROR, 566 NILFS_SEGMENT_USAGE_ERROR,
567 567
568 /* on-memory only */
569 NILFS_SEGMENT_USAGE_VOLATILE_ACTIVE,
570 /* ... */ 568 /* ... */
571}; 569};
572 570
@@ -594,7 +592,6 @@ nilfs_segment_usage_##name(const struct nilfs_segment_usage *su) \
594NILFS_SEGMENT_USAGE_FNS(ACTIVE, active) 592NILFS_SEGMENT_USAGE_FNS(ACTIVE, active)
595NILFS_SEGMENT_USAGE_FNS(DIRTY, dirty) 593NILFS_SEGMENT_USAGE_FNS(DIRTY, dirty)
596NILFS_SEGMENT_USAGE_FNS(ERROR, error) 594NILFS_SEGMENT_USAGE_FNS(ERROR, error)
597NILFS_SEGMENT_USAGE_FNS(VOLATILE_ACTIVE, volatile_active)
598 595
599static inline void 596static inline void
600nilfs_segment_usage_set_clean(struct nilfs_segment_usage *su) 597nilfs_segment_usage_set_clean(struct nilfs_segment_usage *su)
@@ -650,7 +647,6 @@ nilfs_suinfo_##name(const struct nilfs_suinfo *si) \
650NILFS_SUINFO_FNS(ACTIVE, active) 647NILFS_SUINFO_FNS(ACTIVE, active)
651NILFS_SUINFO_FNS(DIRTY, dirty) 648NILFS_SUINFO_FNS(DIRTY, dirty)
652NILFS_SUINFO_FNS(ERROR, error) 649NILFS_SUINFO_FNS(ERROR, error)
653NILFS_SUINFO_FNS(VOLATILE_ACTIVE, volatile_active)
654 650
655static inline int nilfs_suinfo_clean(const struct nilfs_suinfo *si) 651static inline int nilfs_suinfo_clean(const struct nilfs_suinfo *si)
656{ 652{
@@ -717,8 +713,9 @@ struct nilfs_cpstat {
717 * @ss_nsegs: number of segments 713 * @ss_nsegs: number of segments
718 * @ss_ncleansegs: number of clean segments 714 * @ss_ncleansegs: number of clean segments
719 * @ss_ndirtysegs: number of dirty segments 715 * @ss_ndirtysegs: number of dirty segments
720 * @ss_ctime: 716 * @ss_ctime: creation time of the last segment
721 * @ss_nongc_ctime: 717 * @ss_nongc_ctime: creation time of the last segment not for GC
718 * @ss_prot_seq: least sequence number of segments which must not be reclaimed
722 */ 719 */
723struct nilfs_sustat { 720struct nilfs_sustat {
724 __u64 ss_nsegs; 721 __u64 ss_nsegs;
@@ -726,6 +723,7 @@ struct nilfs_sustat {
726 __u64 ss_ndirtysegs; 723 __u64 ss_ndirtysegs;
727 __u64 ss_ctime; 724 __u64 ss_ctime;
728 __u64 ss_nongc_ctime; 725 __u64 ss_nongc_ctime;
726 __u64 ss_prot_seq;
729}; 727};
730 728
731/** 729/**