diff options
author | Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> | 2009-04-05 05:30:58 -0400 |
---|---|---|
committer | Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> | 2009-04-12 20:53:52 -0400 |
commit | c85399c2da8b86de8f6877980294fa1a4a88a5a4 (patch) | |
tree | 0319b8ab4d8b7da4d614e46949755b8a9ba4eab0 /fs/nilfs2/sufile.c | |
parent | a703018f7bbec8109419318f5d51f235fdce5155 (diff) |
nilfs2: fix possible mismatch of sufile counters on recovery
On-disk counters ndirtysegs and ncleansegs of sufile, can go wrong
after roll-forward recovery because
nilfs_prepare_segment_for_recovery() function marks segments dirty
without adjusting value of these counters.
This fixes the problem by adding a function to sufile which does the
operation adjusting the counters, and by letting the recovery function
use it.
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Diffstat (limited to 'fs/nilfs2/sufile.c')
-rw-r--r-- | fs/nilfs2/sufile.c | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/fs/nilfs2/sufile.c b/fs/nilfs2/sufile.c index 07013f58dfe9..98e68677f045 100644 --- a/fs/nilfs2/sufile.c +++ b/fs/nilfs2/sufile.c | |||
@@ -258,6 +258,35 @@ void nilfs_sufile_do_cancel_free(struct inode *sufile, __u64 segnum, | |||
258 | nilfs_mdt_mark_dirty(sufile); | 258 | nilfs_mdt_mark_dirty(sufile); |
259 | } | 259 | } |
260 | 260 | ||
261 | void nilfs_sufile_do_scrap(struct inode *sufile, __u64 segnum, | ||
262 | struct buffer_head *header_bh, | ||
263 | struct buffer_head *su_bh) | ||
264 | { | ||
265 | struct nilfs_segment_usage *su; | ||
266 | void *kaddr; | ||
267 | int clean, dirty; | ||
268 | |||
269 | kaddr = kmap_atomic(su_bh->b_page, KM_USER0); | ||
270 | su = nilfs_sufile_block_get_segment_usage(sufile, segnum, su_bh, kaddr); | ||
271 | if (su->su_flags == cpu_to_le32(1UL << NILFS_SEGMENT_USAGE_DIRTY) && | ||
272 | su->su_nblocks == cpu_to_le32(0)) { | ||
273 | kunmap_atomic(kaddr, KM_USER0); | ||
274 | return; | ||
275 | } | ||
276 | clean = nilfs_segment_usage_clean(su); | ||
277 | dirty = nilfs_segment_usage_dirty(su); | ||
278 | |||
279 | /* make the segment garbage */ | ||
280 | su->su_lastmod = cpu_to_le64(0); | ||
281 | su->su_nblocks = cpu_to_le32(0); | ||
282 | su->su_flags = cpu_to_le32(1UL << NILFS_SEGMENT_USAGE_DIRTY); | ||
283 | kunmap_atomic(kaddr, KM_USER0); | ||
284 | |||
285 | nilfs_sufile_mod_counter(header_bh, clean ? (u64)-1 : 0, dirty ? 0 : 1); | ||
286 | nilfs_mdt_mark_buffer_dirty(su_bh); | ||
287 | nilfs_mdt_mark_dirty(sufile); | ||
288 | } | ||
289 | |||
261 | void nilfs_sufile_do_free(struct inode *sufile, __u64 segnum, | 290 | void nilfs_sufile_do_free(struct inode *sufile, __u64 segnum, |
262 | struct buffer_head *header_bh, | 291 | struct buffer_head *header_bh, |
263 | struct buffer_head *su_bh) | 292 | struct buffer_head *su_bh) |