aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nilfs2
diff options
context:
space:
mode:
authorRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>2009-04-06 22:01:54 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-04-07 11:31:19 -0400
commit2c2e52fc4fca251e68f90821c9ff5cb18be4df58 (patch)
treefb0b86203bb5f4dda4d5907e29bd2b1b6cc0be90 /fs/nilfs2
parent7a9461939a46345860622ea36ff267ee4446f00f (diff)
nilfs2: extend nilfs_sustat ioctl struct
This adds a new argument to the nilfs_sustat structure. The extended field allows to delete volatile active state of segments, which was needed to protect freshly-created segments from garbage collection but has confused code dealing with segments. This extension alleviates the mess and gives room for further simplifications. The volatile active flag is not persistent, so it's eliminable on this occasion without affecting compatibility other than the ioctl change. Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/nilfs2')
-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
6 files changed, 37 insertions, 69 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