From 37e11f3397fab21604bff506cb31ffbf70fb255a Mon Sep 17 00:00:00 2001 From: Qinghuang Feng Date: Sun, 25 Apr 2010 20:17:25 +0800 Subject: nilfs2: update comment for struct nilfs_dat_entry The comment of struct nilfs_dat_entry is mismatched, fix it. Signed-off-by: Qinghuang Feng Signed-off-by: Ryusuke Konishi diff --git a/include/linux/nilfs2_fs.h b/include/linux/nilfs2_fs.h index 640702e..478ee34 100644 --- a/include/linux/nilfs2_fs.h +++ b/include/linux/nilfs2_fs.h @@ -437,10 +437,10 @@ struct nilfs_palloc_group_desc { /** * struct nilfs_dat_entry - disk address translation entry - * @dt_blocknr: block number - * @dt_start: start checkpoint number - * @dt_end: end checkpoint number - * @dt_rsv: reserved for future use + * @de_blocknr: block number + * @de_start: start checkpoint number + * @de_end: end checkpoint number + * @de_rsv: reserved for future use */ struct nilfs_dat_entry { __le64 de_blocknr; -- cgit v0.10.2 From 0d9cc2332df24d3e81060c782b2ecb87c28443f9 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Mon, 26 Apr 2010 01:17:48 +0900 Subject: nilfs2: fix style problems in nilfs2_fs.h This kills the following checkpatch warnings: WARNING: please, no space before tabs +^I__le32^Is_first_ino; ^I^I/* First non-reserved inode */$ WARNING: please, no space before tabs +^I__le16 s_inode_size; ^I^I/* Size of an inode */$ WARNING: please, no space before tabs +^Ichar^Is_volume_name[16]; ^I/* volume name */$ WARNING: please, no space before tabs +^Ichar^Is_last_mounted[64]; ^I/* directory where last mounted */$ Signed-off-by: Ryusuke Konishi diff --git a/include/linux/nilfs2_fs.h b/include/linux/nilfs2_fs.h index 478ee34..f960e1d 100644 --- a/include/linux/nilfs2_fs.h +++ b/include/linux/nilfs2_fs.h @@ -199,16 +199,16 @@ struct nilfs_super_block { __le32 s_creator_os; /* OS */ __le16 s_def_resuid; /* Default uid for reserved blocks */ __le16 s_def_resgid; /* Default gid for reserved blocks */ - __le32 s_first_ino; /* First non-reserved inode */ + __le32 s_first_ino; /* First non-reserved inode */ - __le16 s_inode_size; /* Size of an inode */ + __le16 s_inode_size; /* Size of an inode */ __le16 s_dat_entry_size; /* Size of a dat entry */ __le16 s_checkpoint_size; /* Size of a checkpoint */ __le16 s_segment_usage_size; /* Size of a segment usage */ __u8 s_uuid[16]; /* 128-bit uuid for volume */ - char s_volume_name[16]; /* volume name */ - char s_last_mounted[64]; /* directory where last mounted */ + char s_volume_name[16]; /* volume name */ + char s_last_mounted[64]; /* directory where last mounted */ __le32 s_c_interval; /* Commit interval of segment */ __le32 s_c_block_max; /* Threshold of data amount for -- cgit v0.10.2 From f905440f5edfa70a07e64bdbc973cbdd55dd001d Mon Sep 17 00:00:00 2001 From: Li Hong Date: Fri, 2 Apr 2010 17:36:34 +0800 Subject: nilfs2: Combine nilfs_btree_alloc_path() and nilfs_btree_init_path() nilfs_btree_alloc_path() and nilfs_btree_init_path() are bound into each other tightly. Make them into one procedure to clearify the logic and avoid some misusages. Signed-off-by: Li Hong Signed-off-by: Ryusuke Konishi diff --git a/fs/nilfs2/btree.c b/fs/nilfs2/btree.c index 76c38e3..f479849 100644 --- a/fs/nilfs2/btree.c +++ b/fs/nilfs2/btree.c @@ -71,23 +71,16 @@ void nilfs_btree_path_cache_destroy(void) kmem_cache_destroy(nilfs_btree_path_cache); } -static inline struct nilfs_btree_path *nilfs_btree_alloc_path(void) +static struct nilfs_btree_path *nilfs_btree_alloc_path(void) { - return kmem_cache_alloc(nilfs_btree_path_cache, GFP_NOFS); -} - -static inline void nilfs_btree_free_path(struct nilfs_btree_path *path) -{ - kmem_cache_free(nilfs_btree_path_cache, path); -} + struct nilfs_btree_path *path; + int level = NILFS_BTREE_LEVEL_DATA; -static void nilfs_btree_init_path(struct nilfs_btree_path *path) -{ - int level; + path = kmem_cache_alloc(nilfs_btree_path_cache, GFP_NOFS); + if (path == NULL) + goto out; - for (level = NILFS_BTREE_LEVEL_DATA; - level < NILFS_BTREE_LEVEL_MAX; - level++) { + for (; level < NILFS_BTREE_LEVEL_MAX; level++) { path[level].bp_bh = NULL; path[level].bp_sib_bh = NULL; path[level].bp_index = 0; @@ -95,6 +88,14 @@ static void nilfs_btree_init_path(struct nilfs_btree_path *path) path[level].bp_newreq.bpr_ptr = NILFS_BMAP_INVALID_PTR; path[level].bp_op = NULL; } + +out: + return path; +} + +static inline void nilfs_btree_free_path(struct nilfs_btree_path *path) +{ + kmem_cache_free(nilfs_btree_path_cache, path); } static void nilfs_btree_release_path(struct nilfs_btree_path *path) @@ -566,7 +567,6 @@ static int nilfs_btree_lookup(const struct nilfs_bmap *bmap, path = nilfs_btree_alloc_path(); if (path == NULL) return -ENOMEM; - nilfs_btree_init_path(path); ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level); @@ -594,7 +594,7 @@ static int nilfs_btree_lookup_contig(const struct nilfs_bmap *bmap, path = nilfs_btree_alloc_path(); if (path == NULL) return -ENOMEM; - nilfs_btree_init_path(path); + ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level); if (ret < 0) goto out; @@ -1123,7 +1123,6 @@ static int nilfs_btree_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr) path = nilfs_btree_alloc_path(); if (path == NULL) return -ENOMEM; - nilfs_btree_init_path(path); ret = nilfs_btree_do_lookup(btree, path, key, NULL, NILFS_BTREE_LEVEL_NODE_MIN); @@ -1456,7 +1455,7 @@ static int nilfs_btree_delete(struct nilfs_bmap *bmap, __u64 key) path = nilfs_btree_alloc_path(); if (path == NULL) return -ENOMEM; - nilfs_btree_init_path(path); + ret = nilfs_btree_do_lookup(btree, path, key, NULL, NILFS_BTREE_LEVEL_NODE_MIN); if (ret < 0) @@ -1488,7 +1487,6 @@ static int nilfs_btree_last_key(const struct nilfs_bmap *bmap, __u64 *keyp) path = nilfs_btree_alloc_path(); if (path == NULL) return -ENOMEM; - nilfs_btree_init_path(path); ret = nilfs_btree_do_lookup_last(btree, path, keyp, NULL); @@ -1923,7 +1921,6 @@ static int nilfs_btree_propagate(const struct nilfs_bmap *bmap, path = nilfs_btree_alloc_path(); if (path == NULL) return -ENOMEM; - nilfs_btree_init_path(path); if (buffer_nilfs_node(bh)) { node = (struct nilfs_btree_node *)bh->b_data; @@ -2108,7 +2105,6 @@ static int nilfs_btree_assign(struct nilfs_bmap *bmap, path = nilfs_btree_alloc_path(); if (path == NULL) return -ENOMEM; - nilfs_btree_init_path(path); if (buffer_nilfs_node(*bh)) { node = (struct nilfs_btree_node *)(*bh)->b_data; @@ -2175,7 +2171,6 @@ static int nilfs_btree_mark(struct nilfs_bmap *bmap, __u64 key, int level) path = nilfs_btree_alloc_path(); if (path == NULL) return -ENOMEM; - nilfs_btree_init_path(path); ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level + 1); if (ret < 0) { -- cgit v0.10.2 From 73bb48869b14fd5094b9ec173a2bf86bc0e464d4 Mon Sep 17 00:00:00 2001 From: Li Hong Date: Fri, 2 Apr 2010 18:35:00 +0800 Subject: nilfs2: Combine nilfs_btree_release_path() and nilfs_btree_free_path() nilfs_btree_release_path() and nilfs_btree_free_path() are bound into each other tightly. Make them into one procedure to clearify the logic and avoid some misusages. Signed-off-by: Li Hong Signed-off-by: Ryusuke Konishi diff --git a/fs/nilfs2/btree.c b/fs/nilfs2/btree.c index f479849..dcd4e1c 100644 --- a/fs/nilfs2/btree.c +++ b/fs/nilfs2/btree.c @@ -93,18 +93,14 @@ out: return path; } -static inline void nilfs_btree_free_path(struct nilfs_btree_path *path) +static void nilfs_btree_free_path(struct nilfs_btree_path *path) { - kmem_cache_free(nilfs_btree_path_cache, path); -} - -static void nilfs_btree_release_path(struct nilfs_btree_path *path) -{ - int level; + int level = NILFS_BTREE_LEVEL_DATA; - for (level = NILFS_BTREE_LEVEL_DATA; level < NILFS_BTREE_LEVEL_MAX; - level++) + for (; level < NILFS_BTREE_LEVEL_MAX; level++) brelse(path[level].bp_bh); + + kmem_cache_free(nilfs_btree_path_cache, path); } /* @@ -573,7 +569,6 @@ static int nilfs_btree_lookup(const struct nilfs_bmap *bmap, if (ptrp != NULL) *ptrp = ptr; - nilfs_btree_release_path(path); nilfs_btree_free_path(path); return ret; @@ -655,7 +650,6 @@ static int nilfs_btree_lookup_contig(const struct nilfs_bmap *bmap, *ptrp = ptr; ret = cnt; out: - nilfs_btree_release_path(path); nilfs_btree_free_path(path); return ret; } @@ -1139,7 +1133,6 @@ static int nilfs_btree_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr) nilfs_bmap_add_blocks(bmap, stats.bs_nblocks); out: - nilfs_btree_release_path(path); nilfs_btree_free_path(path); return ret; } @@ -1472,7 +1465,6 @@ static int nilfs_btree_delete(struct nilfs_bmap *bmap, __u64 key) nilfs_bmap_sub_blocks(bmap, stats.bs_nblocks); out: - nilfs_btree_release_path(path); nilfs_btree_free_path(path); return ret; } @@ -1490,7 +1482,6 @@ static int nilfs_btree_last_key(const struct nilfs_bmap *bmap, __u64 *keyp) ret = nilfs_btree_do_lookup_last(btree, path, keyp, NULL); - nilfs_btree_release_path(path); nilfs_btree_free_path(path); return ret; @@ -1944,7 +1935,6 @@ static int nilfs_btree_propagate(const struct nilfs_bmap *bmap, nilfs_btree_propagate_p(btree, path, level, bh); out: - nilfs_btree_release_path(path); nilfs_btree_free_path(path); return ret; @@ -2126,7 +2116,6 @@ static int nilfs_btree_assign(struct nilfs_bmap *bmap, nilfs_btree_assign_p(btree, path, level, bh, blocknr, binfo); out: - nilfs_btree_release_path(path); nilfs_btree_free_path(path); return ret; @@ -2190,7 +2179,6 @@ static int nilfs_btree_mark(struct nilfs_bmap *bmap, __u64 key, int level) nilfs_bmap_set_dirty(&btree->bt_bmap); out: - nilfs_btree_release_path(path); nilfs_btree_free_path(path); return ret; } -- cgit v0.10.2 From 277a6a34175dcb0ee98dceee619e0e3190347a25 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Fri, 2 Apr 2010 18:02:33 +0900 Subject: nilfs2: change default of 'errors' mount option to 'remount-ro' mode Like ext3, nilfs has 'errors' mount option to allow specifying desired behavior on severe errors. Currently, the default action is 'errors=continue' and has potential to advance filesystem corruption for severe errors. This will change the action to 'errors=remount-ro' to avoid the issue. Signed-off-by: Ryusuke Konishi diff --git a/Documentation/filesystems/nilfs2.txt b/Documentation/filesystems/nilfs2.txt index cf6d0d8..d3e7673 100644 --- a/Documentation/filesystems/nilfs2.txt +++ b/Documentation/filesystems/nilfs2.txt @@ -50,8 +50,8 @@ NILFS2 supports the following mount options: (*) == default nobarrier Disables barriers. -errors=continue(*) Keep going on a filesystem error. -errors=remount-ro Remount the filesystem read-only on an error. +errors=continue Keep going on a filesystem error. +errors=remount-ro(*) Remount the filesystem read-only on an error. errors=panic Panic and halt the machine if an error occurs. cp=n Specify the checkpoint-number of the snapshot to be mounted. Checkpoints and snapshots are listed by lscp diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 48145f5..0b1758b 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c @@ -470,10 +470,10 @@ static int nilfs_show_options(struct seq_file *seq, struct vfsmount *vfs) if (nilfs_test_opt(sbi, SNAPSHOT)) seq_printf(seq, ",cp=%llu", (unsigned long long int)sbi->s_snapshot_cno); - if (nilfs_test_opt(sbi, ERRORS_RO)) - seq_printf(seq, ",errors=remount-ro"); if (nilfs_test_opt(sbi, ERRORS_PANIC)) seq_printf(seq, ",errors=panic"); + if (nilfs_test_opt(sbi, ERRORS_CONT)) + seq_printf(seq, ",errors=continue"); if (nilfs_test_opt(sbi, STRICT_ORDER)) seq_printf(seq, ",order=strict"); if (nilfs_test_opt(sbi, NORECOVERY)) @@ -631,7 +631,7 @@ nilfs_set_default_options(struct nilfs_sb_info *sbi, struct nilfs_super_block *sbp) { sbi->s_mount_opt = - NILFS_MOUNT_ERRORS_CONT | NILFS_MOUNT_BARRIER; + NILFS_MOUNT_ERRORS_RO | NILFS_MOUNT_BARRIER; } static int nilfs_setup_super(struct nilfs_sb_info *sbi) -- cgit v0.10.2 From 1e2b68bf285dce604388fcb6f85b7e612156db17 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Tue, 23 Mar 2010 01:15:31 +0900 Subject: nilfs2: move pointer to super root block into logs This moves a pointer to buffer storing super root block to each log buffer from nilfs_sc_info struct for simplicity. Signed-off-by: Ryusuke Konishi diff --git a/fs/nilfs2/segbuf.c b/fs/nilfs2/segbuf.c index 17851f7..a24ca9c 100644 --- a/fs/nilfs2/segbuf.c +++ b/fs/nilfs2/segbuf.c @@ -81,6 +81,7 @@ struct nilfs_segment_buffer *nilfs_segbuf_new(struct super_block *sb) INIT_LIST_HEAD(&segbuf->sb_list); INIT_LIST_HEAD(&segbuf->sb_segsum_buffers); INIT_LIST_HEAD(&segbuf->sb_payload_buffers); + segbuf->sb_super_root = NULL; init_completion(&segbuf->sb_bio_event); atomic_set(&segbuf->sb_err, 0); @@ -282,6 +283,7 @@ static void nilfs_segbuf_clear(struct nilfs_segment_buffer *segbuf) { nilfs_release_buffers(&segbuf->sb_segsum_buffers); nilfs_release_buffers(&segbuf->sb_payload_buffers); + segbuf->sb_super_root = NULL; } /* diff --git a/fs/nilfs2/segbuf.h b/fs/nilfs2/segbuf.h index 94dfd35..a1a0af6 100644 --- a/fs/nilfs2/segbuf.h +++ b/fs/nilfs2/segbuf.h @@ -76,6 +76,7 @@ struct nilfs_segsum_info { * @sb_rest_blocks: Number of residual blocks in the current segment * @sb_segsum_buffers: List of buffers for segment summaries * @sb_payload_buffers: List of buffers for segment payload + * @sb_super_root: Pointer to buffer storing a super root block (if exists) * @sb_nbio: Number of flying bio requests * @sb_err: I/O error status * @sb_bio_event: Completion event of log writing @@ -95,6 +96,7 @@ struct nilfs_segment_buffer { /* Buffers */ struct list_head sb_segsum_buffers; struct list_head sb_payload_buffers; /* including super root */ + struct buffer_head *sb_super_root; /* io status */ int sb_nbio; diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index 6a7dbd8..7ab0270 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c @@ -435,7 +435,7 @@ static int nilfs_segctor_add_super_root(struct nilfs_sc_info *sci) return err; segbuf = sci->sc_curseg; } - err = nilfs_segbuf_extend_payload(segbuf, &sci->sc_super_root); + err = nilfs_segbuf_extend_payload(segbuf, &segbuf->sb_super_root); if (likely(!err)) segbuf->sb_sum.flags |= NILFS_SS_SR; return err; @@ -952,10 +952,10 @@ static void nilfs_segctor_fill_in_checksums(struct nilfs_sc_info *sci, { struct nilfs_segment_buffer *segbuf; - if (sci->sc_super_root) - nilfs_fill_in_super_root_crc(sci->sc_super_root, seed); - list_for_each_entry(segbuf, &sci->sc_segbufs, sb_list) { + if (segbuf->sb_super_root) + nilfs_fill_in_super_root_crc(segbuf->sb_super_root, + seed); nilfs_segbuf_fill_in_segsum_crc(segbuf, seed); nilfs_segbuf_fill_in_data_crc(segbuf, seed); } @@ -964,11 +964,13 @@ static void nilfs_segctor_fill_in_checksums(struct nilfs_sc_info *sci, static void nilfs_segctor_fill_in_super_root(struct nilfs_sc_info *sci, struct the_nilfs *nilfs) { - struct buffer_head *bh_sr = sci->sc_super_root; - struct nilfs_super_root *raw_sr = - (struct nilfs_super_root *)bh_sr->b_data; + struct buffer_head *bh_sr; + struct nilfs_super_root *raw_sr; unsigned isz = nilfs->ns_inode_size; + bh_sr = NILFS_LAST_SEGBUF(&sci->sc_segbufs)->sb_super_root; + raw_sr = (struct nilfs_super_root *)bh_sr->b_data; + raw_sr->sr_bytes = cpu_to_le16(NILFS_SR_BYTES); raw_sr->sr_nongc_ctime = cpu_to_le64(nilfs_doing_gc() ? @@ -1491,7 +1493,6 @@ static int nilfs_segctor_collect(struct nilfs_sc_info *sci, /* Collection retry loop */ for (;;) { - sci->sc_super_root = NULL; sci->sc_nblk_this_inc = 0; sci->sc_curseg = NILFS_FIRST_SEGBUF(&sci->sc_segbufs); @@ -1568,7 +1569,7 @@ nilfs_segctor_update_payload_blocknr(struct nilfs_sc_info *sci, ssp.offset = sizeof(struct nilfs_segment_summary); list_for_each_entry(bh, &segbuf->sb_payload_buffers, b_assoc_buffers) { - if (bh == sci->sc_super_root) + if (bh == segbuf->sb_super_root) break; if (!finfo) { finfo = nilfs_segctor_map_segsum_entry( @@ -1729,7 +1730,7 @@ static int nilfs_segctor_prepare_write(struct nilfs_sc_info *sci, list_for_each_entry(bh, &segbuf->sb_payload_buffers, b_assoc_buffers) { - if (bh == sci->sc_super_root) { + if (bh == segbuf->sb_super_root) { if (bh->b_page != bd_page) { lock_page(bd_page); clear_page_dirty_for_io(bd_page); @@ -1848,7 +1849,7 @@ static void nilfs_clear_copied_buffers(struct list_head *list, int err) } static void nilfs_abort_logs(struct list_head *logs, struct page *failed_page, - struct buffer_head *bh_sr, int err) + int err) { struct nilfs_segment_buffer *segbuf; struct page *bd_page = NULL, *fs_page = NULL; @@ -1869,7 +1870,7 @@ static void nilfs_abort_logs(struct list_head *logs, struct page *failed_page, list_for_each_entry(bh, &segbuf->sb_payload_buffers, b_assoc_buffers) { - if (bh == bh_sr) { + if (bh == segbuf->sb_super_root) { if (bh->b_page != bd_page) { end_page_writeback(bd_page); bd_page = bh->b_page; @@ -1898,7 +1899,7 @@ static void nilfs_segctor_abort_construction(struct nilfs_sc_info *sci, list_splice_tail_init(&sci->sc_write_logs, &logs); ret = nilfs_wait_on_logs(&logs); - nilfs_abort_logs(&logs, NULL, sci->sc_super_root, ret ? : err); + nilfs_abort_logs(&logs, NULL, ret ? : err); list_splice_tail_init(&sci->sc_segbufs, &logs); nilfs_cancel_segusage(&logs, nilfs->ns_sufile); @@ -1914,7 +1915,6 @@ static void nilfs_segctor_abort_construction(struct nilfs_sc_info *sci, } nilfs_destroy_logs(&logs); - sci->sc_super_root = NULL; } static void nilfs_set_next_segment(struct the_nilfs *nilfs, @@ -1933,7 +1933,7 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci) struct nilfs_segment_buffer *segbuf; struct page *bd_page = NULL, *fs_page = NULL; struct the_nilfs *nilfs = sci->sc_sbi->s_nilfs; - int update_sr = (sci->sc_super_root != NULL); + int update_sr = false; list_for_each_entry(segbuf, &sci->sc_write_logs, sb_list) { struct buffer_head *bh; @@ -1964,11 +1964,12 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci) set_buffer_uptodate(bh); clear_buffer_dirty(bh); clear_buffer_nilfs_volatile(bh); - if (bh == sci->sc_super_root) { + if (bh == segbuf->sb_super_root) { if (bh->b_page != bd_page) { end_page_writeback(bd_page); bd_page = bh->b_page; } + update_sr = true; break; } if (bh->b_page != fs_page) { @@ -2115,7 +2116,7 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode) struct nilfs_sb_info *sbi = sci->sc_sbi; struct the_nilfs *nilfs = sbi->s_nilfs; struct page *failed_page; - int err, has_sr = 0; + int err; sci->sc_stage.scnt = NILFS_ST_INIT; @@ -2143,8 +2144,6 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode) if (unlikely(err)) goto failed; - has_sr = (sci->sc_super_root != NULL); - /* Avoid empty segment */ if (sci->sc_stage.scnt == NILFS_ST_DONE && NILFS_SEG_EMPTY(&sci->sc_curseg->sb_sum)) { @@ -2159,7 +2158,8 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode) if (sci->sc_stage.flags & NILFS_CF_IFILE_STARTED) nilfs_segctor_fill_in_file_bmap(sci, sbi->s_ifile); - if (has_sr) { + if (mode == SC_LSEG_SR && + sci->sc_stage.scnt >= NILFS_ST_CPFILE) { err = nilfs_segctor_fill_in_checkpoint(sci); if (unlikely(err)) goto failed_to_write; @@ -2171,8 +2171,7 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode) /* Write partial segments */ err = nilfs_segctor_prepare_write(sci, &failed_page); if (err) { - nilfs_abort_logs(&sci->sc_segbufs, failed_page, - sci->sc_super_root, err); + nilfs_abort_logs(&sci->sc_segbufs, failed_page, err); goto failed_to_write; } nilfs_segctor_fill_in_checksums(sci, nilfs->ns_crc_seed); @@ -2196,8 +2195,6 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode) } } while (sci->sc_stage.scnt != NILFS_ST_DONE); - sci->sc_super_root = NULL; - out: nilfs_segctor_check_out_files(sci, sbi); return err; diff --git a/fs/nilfs2/segment.h b/fs/nilfs2/segment.h index 82dfd6a..e61fc79 100644 --- a/fs/nilfs2/segment.h +++ b/fs/nilfs2/segment.h @@ -100,7 +100,6 @@ struct nilfs_segsum_pointer { * @sc_write_logs: List of segment buffers to hold logs under writing * @sc_segbuf_nblocks: Number of available blocks in segment buffers. * @sc_curseg: Current segment buffer - * @sc_super_root: Pointer to the super root buffer * @sc_stage: Collection stage * @sc_finfo_ptr: pointer to the current finfo struct in the segment summary * @sc_binfo_ptr: pointer to the current binfo struct in the segment summary @@ -148,7 +147,6 @@ struct nilfs_sc_info { struct list_head sc_write_logs; unsigned long sc_segbuf_nblocks; struct nilfs_segment_buffer *sc_curseg; - struct buffer_head *sc_super_root; struct nilfs_cstage sc_stage; -- cgit v0.10.2 From aaed1d5bfac459ead9aaad324e7fe3326250f50a Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Tue, 23 Mar 2010 01:50:38 +0900 Subject: nilfs2: move out checksum routines to segment buffer code This moves out checksum routines in log writer to segbuf.c for cleanup. Signed-off-by: Ryusuke Konishi diff --git a/fs/nilfs2/segbuf.c b/fs/nilfs2/segbuf.c index a24ca9c..6bf3b1f 100644 --- a/fs/nilfs2/segbuf.c +++ b/fs/nilfs2/segbuf.c @@ -202,8 +202,8 @@ void nilfs_segbuf_fill_in_segsum(struct nilfs_segment_buffer *segbuf) /* * CRC calculation routines */ -void nilfs_segbuf_fill_in_segsum_crc(struct nilfs_segment_buffer *segbuf, - u32 seed) +static void +nilfs_segbuf_fill_in_segsum_crc(struct nilfs_segment_buffer *segbuf, u32 seed) { struct buffer_head *bh; struct nilfs_segment_summary *raw_sum; @@ -230,8 +230,8 @@ void nilfs_segbuf_fill_in_segsum_crc(struct nilfs_segment_buffer *segbuf, raw_sum->ss_sumsum = cpu_to_le32(crc); } -void nilfs_segbuf_fill_in_data_crc(struct nilfs_segment_buffer *segbuf, - u32 seed) +static void nilfs_segbuf_fill_in_data_crc(struct nilfs_segment_buffer *segbuf, + u32 seed) { struct buffer_head *bh; struct nilfs_segment_summary *raw_sum; @@ -257,6 +257,20 @@ void nilfs_segbuf_fill_in_data_crc(struct nilfs_segment_buffer *segbuf, raw_sum->ss_datasum = cpu_to_le32(crc); } +static void +nilfs_segbuf_fill_in_super_root_crc(struct nilfs_segment_buffer *segbuf, + u32 seed) +{ + struct nilfs_super_root *raw_sr; + u32 crc; + + raw_sr = (struct nilfs_super_root *)segbuf->sb_super_root->b_data; + crc = crc32_le(seed, + (unsigned char *)raw_sr + sizeof(raw_sr->sr_sum), + NILFS_SR_BYTES - sizeof(raw_sr->sr_sum)); + raw_sr->sr_sum = cpu_to_le32(crc); +} + static void nilfs_release_buffers(struct list_head *list) { struct buffer_head *bh, *n; @@ -336,6 +350,23 @@ int nilfs_wait_on_logs(struct list_head *logs) return ret; } +/** + * nilfs_add_checksums_on_logs - add checksums on the logs + * @logs: list of segment buffers storing target logs + * @seed: checksum seed value + */ +void nilfs_add_checksums_on_logs(struct list_head *logs, u32 seed) +{ + struct nilfs_segment_buffer *segbuf; + + list_for_each_entry(segbuf, logs, sb_list) { + if (segbuf->sb_super_root) + nilfs_segbuf_fill_in_super_root_crc(segbuf, seed); + nilfs_segbuf_fill_in_segsum_crc(segbuf, seed); + nilfs_segbuf_fill_in_data_crc(segbuf, seed); + } +} + /* * BIO operations */ diff --git a/fs/nilfs2/segbuf.h b/fs/nilfs2/segbuf.h index a1a0af6..ae12c2c 100644 --- a/fs/nilfs2/segbuf.h +++ b/fs/nilfs2/segbuf.h @@ -139,8 +139,6 @@ int nilfs_segbuf_extend_segsum(struct nilfs_segment_buffer *); int nilfs_segbuf_extend_payload(struct nilfs_segment_buffer *, struct buffer_head **); void nilfs_segbuf_fill_in_segsum(struct nilfs_segment_buffer *); -void nilfs_segbuf_fill_in_segsum_crc(struct nilfs_segment_buffer *, u32); -void nilfs_segbuf_fill_in_data_crc(struct nilfs_segment_buffer *, u32); static inline void nilfs_segbuf_add_segsum_buffer(struct nilfs_segment_buffer *segbuf, @@ -173,6 +171,7 @@ void nilfs_truncate_logs(struct list_head *logs, struct nilfs_segment_buffer *last); int nilfs_write_logs(struct list_head *logs, struct the_nilfs *nilfs); int nilfs_wait_on_logs(struct list_head *logs); +void nilfs_add_checksums_on_logs(struct list_head *logs, u32 seed); static inline void nilfs_destroy_logs(struct list_head *logs) { diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index 7ab0270..f649f01 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c @@ -932,35 +932,6 @@ static void nilfs_segctor_fill_in_file_bmap(struct nilfs_sc_info *sci, } } -/* - * CRC calculation routines - */ -static void nilfs_fill_in_super_root_crc(struct buffer_head *bh_sr, u32 seed) -{ - struct nilfs_super_root *raw_sr = - (struct nilfs_super_root *)bh_sr->b_data; - u32 crc; - - crc = crc32_le(seed, - (unsigned char *)raw_sr + sizeof(raw_sr->sr_sum), - NILFS_SR_BYTES - sizeof(raw_sr->sr_sum)); - raw_sr->sr_sum = cpu_to_le32(crc); -} - -static void nilfs_segctor_fill_in_checksums(struct nilfs_sc_info *sci, - u32 seed) -{ - struct nilfs_segment_buffer *segbuf; - - list_for_each_entry(segbuf, &sci->sc_segbufs, sb_list) { - if (segbuf->sb_super_root) - nilfs_fill_in_super_root_crc(segbuf->sb_super_root, - seed); - nilfs_segbuf_fill_in_segsum_crc(segbuf, seed); - nilfs_segbuf_fill_in_data_crc(segbuf, seed); - } -} - static void nilfs_segctor_fill_in_super_root(struct nilfs_sc_info *sci, struct the_nilfs *nilfs) { @@ -2174,7 +2145,9 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode) nilfs_abort_logs(&sci->sc_segbufs, failed_page, err); goto failed_to_write; } - nilfs_segctor_fill_in_checksums(sci, nilfs->ns_crc_seed); + + nilfs_add_checksums_on_logs(&sci->sc_segbufs, + nilfs->ns_crc_seed); err = nilfs_segctor_write(sci, nilfs); if (unlikely(err)) -- cgit v0.10.2 From 41c88bd74d372db5102996a4ea6167a725c24b5e Mon Sep 17 00:00:00 2001 From: Li Hong Date: Tue, 6 Apr 2010 00:54:11 +0800 Subject: nilfs2: cleanup multi kmem_cache_{create,destroy} code This cleanup patch gives several improvements: - Moving all kmem_cache_{create_destroy} calls into one place, which removes some small function calls, cleans up error check code and clarify the logic. - Mark all initial code in __init section. - Remove some very obvious comments. - Adjust some declarations. - Fix some space-tab issues. Signed-off-by: Li Hong Signed-off-by: Ryusuke Konishi diff --git a/fs/nilfs2/btree.c b/fs/nilfs2/btree.c index dcd4e1c..b27a342 100644 --- a/fs/nilfs2/btree.c +++ b/fs/nilfs2/btree.c @@ -31,46 +31,6 @@ #include "alloc.h" #include "dat.h" -/** - * struct nilfs_btree_path - A path on which B-tree operations are executed - * @bp_bh: buffer head of node block - * @bp_sib_bh: buffer head of sibling node block - * @bp_index: index of child node - * @bp_oldreq: ptr end request for old ptr - * @bp_newreq: ptr alloc request for new ptr - * @bp_op: rebalance operation - */ -struct nilfs_btree_path { - struct buffer_head *bp_bh; - struct buffer_head *bp_sib_bh; - int bp_index; - union nilfs_bmap_ptr_req bp_oldreq; - union nilfs_bmap_ptr_req bp_newreq; - struct nilfs_btnode_chkey_ctxt bp_ctxt; - void (*bp_op)(struct nilfs_btree *, struct nilfs_btree_path *, - int, __u64 *, __u64 *); -}; - -/* - * B-tree path operations - */ - -static struct kmem_cache *nilfs_btree_path_cache; - -int __init nilfs_btree_path_cache_init(void) -{ - nilfs_btree_path_cache = - kmem_cache_create("nilfs2_btree_path_cache", - sizeof(struct nilfs_btree_path) * - NILFS_BTREE_LEVEL_MAX, 0, 0, NULL); - return (nilfs_btree_path_cache != NULL) ? 0 : -ENOMEM; -} - -void nilfs_btree_path_cache_destroy(void) -{ - kmem_cache_destroy(nilfs_btree_path_cache); -} - static struct nilfs_btree_path *nilfs_btree_alloc_path(void) { struct nilfs_btree_path *path; diff --git a/fs/nilfs2/btree.h b/fs/nilfs2/btree.h index 4b82d84..af638d5 100644 --- a/fs/nilfs2/btree.h +++ b/fs/nilfs2/btree.h @@ -30,9 +30,6 @@ #include "btnode.h" #include "bmap.h" -struct nilfs_btree; -struct nilfs_btree_path; - /** * struct nilfs_btree - B-tree structure * @bt_bmap: bmap base structure @@ -41,6 +38,25 @@ struct nilfs_btree { struct nilfs_bmap bt_bmap; }; +/** + * struct nilfs_btree_path - A path on which B-tree operations are executed + * @bp_bh: buffer head of node block + * @bp_sib_bh: buffer head of sibling node block + * @bp_index: index of child node + * @bp_oldreq: ptr end request for old ptr + * @bp_newreq: ptr alloc request for new ptr + * @bp_op: rebalance operation + */ +struct nilfs_btree_path { + struct buffer_head *bp_bh; + struct buffer_head *bp_sib_bh; + int bp_index; + union nilfs_bmap_ptr_req bp_oldreq; + union nilfs_bmap_ptr_req bp_newreq; + struct nilfs_btnode_chkey_ctxt bp_ctxt; + void (*bp_op)(struct nilfs_btree *, struct nilfs_btree_path *, + int, __u64 *, __u64 *); +}; #define NILFS_BTREE_ROOT_SIZE NILFS_BMAP_SIZE #define NILFS_BTREE_ROOT_NCHILDREN_MAX \ @@ -57,6 +73,7 @@ struct nilfs_btree { #define NILFS_BTREE_KEY_MIN ((__u64)0) #define NILFS_BTREE_KEY_MAX (~(__u64)0) +extern struct kmem_cache *nilfs_btree_path_cache; int nilfs_btree_path_cache_init(void); void nilfs_btree_path_cache_destroy(void); diff --git a/fs/nilfs2/segbuf.c b/fs/nilfs2/segbuf.c index 6bf3b1f..9f83bc0 100644 --- a/fs/nilfs2/segbuf.c +++ b/fs/nilfs2/segbuf.c @@ -40,35 +40,10 @@ struct nilfs_write_info { sector_t blocknr; }; - static int nilfs_segbuf_write(struct nilfs_segment_buffer *segbuf, struct the_nilfs *nilfs); static int nilfs_segbuf_wait(struct nilfs_segment_buffer *segbuf); - -static struct kmem_cache *nilfs_segbuf_cachep; - -static void nilfs_segbuf_init_once(void *obj) -{ - memset(obj, 0, sizeof(struct nilfs_segment_buffer)); -} - -int __init nilfs_init_segbuf_cache(void) -{ - nilfs_segbuf_cachep = - kmem_cache_create("nilfs2_segbuf_cache", - sizeof(struct nilfs_segment_buffer), - 0, SLAB_RECLAIM_ACCOUNT, - nilfs_segbuf_init_once); - - return (nilfs_segbuf_cachep == NULL) ? -ENOMEM : 0; -} - -void nilfs_destroy_segbuf_cache(void) -{ - kmem_cache_destroy(nilfs_segbuf_cachep); -} - struct nilfs_segment_buffer *nilfs_segbuf_new(struct super_block *sb) { struct nilfs_segment_buffer *segbuf; diff --git a/fs/nilfs2/segbuf.h b/fs/nilfs2/segbuf.h index ae12c2c..e21497f 100644 --- a/fs/nilfs2/segbuf.h +++ b/fs/nilfs2/segbuf.h @@ -123,6 +123,7 @@ struct nilfs_segment_buffer { b_assoc_buffers)) #define NILFS_SEGBUF_BH_IS_LAST(bh, head) ((bh)->b_assoc_buffers.next == head) +extern struct kmem_cache *nilfs_segbuf_cachep; int __init nilfs_init_segbuf_cache(void); void nilfs_destroy_segbuf_cache(void); diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index f649f01..a17bfa1 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c @@ -116,42 +116,6 @@ static void nilfs_dispose_list(struct nilfs_sb_info *, struct list_head *, #define nilfs_cnt32_lt(a, b) nilfs_cnt32_gt(b, a) #define nilfs_cnt32_le(a, b) nilfs_cnt32_ge(b, a) -/* - * Transaction - */ -static struct kmem_cache *nilfs_transaction_cachep; - -/** - * nilfs_init_transaction_cache - create a cache for nilfs_transaction_info - * - * nilfs_init_transaction_cache() creates a slab cache for the struct - * nilfs_transaction_info. - * - * Return Value: On success, it returns 0. On error, one of the following - * negative error code is returned. - * - * %-ENOMEM - Insufficient memory available. - */ -int nilfs_init_transaction_cache(void) -{ - nilfs_transaction_cachep = - kmem_cache_create("nilfs2_transaction_cache", - sizeof(struct nilfs_transaction_info), - 0, SLAB_RECLAIM_ACCOUNT, NULL); - return (nilfs_transaction_cachep == NULL) ? -ENOMEM : 0; -} - -/** - * nilfs_destroy_transaction_cache - destroy the cache for transaction info - * - * nilfs_destroy_transaction_cache() frees the slab cache for the struct - * nilfs_transaction_info. - */ -void nilfs_destroy_transaction_cache(void) -{ - kmem_cache_destroy(nilfs_transaction_cachep); -} - static int nilfs_prepare_segment_lock(struct nilfs_transaction_info *ti) { struct nilfs_transaction_info *cur_ti = current->journal_info; diff --git a/fs/nilfs2/segment.h b/fs/nilfs2/segment.h index e61fc79..7aca765 100644 --- a/fs/nilfs2/segment.h +++ b/fs/nilfs2/segment.h @@ -217,6 +217,8 @@ enum { */ #define NILFS_SC_DEFAULT_WATERMARK 3600 +/* super.c */ +extern struct kmem_cache *nilfs_transaction_cachep; /* segment.c */ extern int nilfs_init_transaction_cache(void); diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 0b1758b..5a08c82 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c @@ -67,6 +67,11 @@ MODULE_DESCRIPTION("A New Implementation of the Log-structured Filesystem " "(NILFS)"); MODULE_LICENSE("GPL"); +struct kmem_cache *nilfs_inode_cachep; +struct kmem_cache *nilfs_transaction_cachep; +struct kmem_cache *nilfs_segbuf_cachep; +struct kmem_cache *nilfs_btree_path_cache; + static int nilfs_remount(struct super_block *sb, int *flags, char *data); /** @@ -129,7 +134,6 @@ void nilfs_warning(struct super_block *sb, const char *function, va_end(args); } -static struct kmem_cache *nilfs_inode_cachep; struct inode *nilfs_alloc_inode_common(struct the_nilfs *nilfs) { @@ -155,34 +159,6 @@ void nilfs_destroy_inode(struct inode *inode) kmem_cache_free(nilfs_inode_cachep, NILFS_I(inode)); } -static void init_once(void *obj) -{ - struct nilfs_inode_info *ii = obj; - - INIT_LIST_HEAD(&ii->i_dirty); -#ifdef CONFIG_NILFS_XATTR - init_rwsem(&ii->xattr_sem); -#endif - nilfs_btnode_cache_init_once(&ii->i_btnode_cache); - ii->i_bmap = (struct nilfs_bmap *)&ii->i_bmap_union; - inode_init_once(&ii->vfs_inode); -} - -static int nilfs_init_inode_cache(void) -{ - nilfs_inode_cachep = kmem_cache_create("nilfs2_inode_cache", - sizeof(struct nilfs_inode_info), - 0, SLAB_RECLAIM_ACCOUNT, - init_once); - - return (nilfs_inode_cachep == NULL) ? -ENOMEM : 0; -} - -static inline void nilfs_destroy_inode_cache(void) -{ - kmem_cache_destroy(nilfs_inode_cachep); -} - static void nilfs_clear_inode(struct inode *inode) { struct nilfs_inode_info *ii = NILFS_I(inode); @@ -1139,54 +1115,92 @@ struct file_system_type nilfs_fs_type = { .fs_flags = FS_REQUIRES_DEV, }; -static int __init init_nilfs_fs(void) +static void nilfs_inode_init_once(void *obj) { - int err; - - err = nilfs_init_inode_cache(); - if (err) - goto failed; + struct nilfs_inode_info *ii = obj; - err = nilfs_init_transaction_cache(); - if (err) - goto failed_inode_cache; + INIT_LIST_HEAD(&ii->i_dirty); +#ifdef CONFIG_NILFS_XATTR + init_rwsem(&ii->xattr_sem); +#endif + nilfs_btnode_cache_init_once(&ii->i_btnode_cache); + ii->i_bmap = (struct nilfs_bmap *)&ii->i_bmap_union; + inode_init_once(&ii->vfs_inode); +} - err = nilfs_init_segbuf_cache(); - if (err) - goto failed_transaction_cache; +static void nilfs_segbuf_init_once(void *obj) +{ + memset(obj, 0, sizeof(struct nilfs_segment_buffer)); +} - err = nilfs_btree_path_cache_init(); - if (err) - goto failed_segbuf_cache; +static void nilfs_destroy_cachep(void) +{ + if (nilfs_inode_cachep) + kmem_cache_destroy(nilfs_inode_cachep); + if (nilfs_transaction_cachep) + kmem_cache_destroy(nilfs_transaction_cachep); + if (nilfs_segbuf_cachep) + kmem_cache_destroy(nilfs_segbuf_cachep); + if (nilfs_btree_path_cache) + kmem_cache_destroy(nilfs_btree_path_cache); +} - err = register_filesystem(&nilfs_fs_type); - if (err) - goto failed_btree_path_cache; +static int __init nilfs_init_cachep(void) +{ + nilfs_inode_cachep = kmem_cache_create("nilfs2_inode_cache", + sizeof(struct nilfs_inode_info), 0, + SLAB_RECLAIM_ACCOUNT, nilfs_inode_init_once); + if (!nilfs_inode_cachep) + goto fail; + + nilfs_transaction_cachep = kmem_cache_create("nilfs2_transaction_cache", + sizeof(struct nilfs_transaction_info), 0, + SLAB_RECLAIM_ACCOUNT, NULL); + if (!nilfs_transaction_cachep) + goto fail; + + nilfs_segbuf_cachep = kmem_cache_create("nilfs2_segbuf_cache", + sizeof(struct nilfs_segment_buffer), 0, + SLAB_RECLAIM_ACCOUNT, nilfs_segbuf_init_once); + if (!nilfs_segbuf_cachep) + goto fail; + + nilfs_btree_path_cache = kmem_cache_create("nilfs2_btree_path_cache", + sizeof(struct nilfs_btree_path) * NILFS_BTREE_LEVEL_MAX, + 0, 0, NULL); + if (!nilfs_btree_path_cache) + goto fail; return 0; - failed_btree_path_cache: - nilfs_btree_path_cache_destroy(); +fail: + nilfs_destroy_cachep(); + return -ENOMEM; +} + +static int __init init_nilfs_fs(void) +{ + int err; - failed_segbuf_cache: - nilfs_destroy_segbuf_cache(); + err = nilfs_init_cachep(); + if (err) + goto fail; - failed_transaction_cache: - nilfs_destroy_transaction_cache(); + err = register_filesystem(&nilfs_fs_type); + if (err) + goto free_cachep; - failed_inode_cache: - nilfs_destroy_inode_cache(); + return 0; - failed: +free_cachep: + nilfs_destroy_cachep(); +fail: return err; } static void __exit exit_nilfs_fs(void) { - nilfs_destroy_segbuf_cache(); - nilfs_destroy_transaction_cache(); - nilfs_destroy_inode_cache(); - nilfs_btree_path_cache_destroy(); + nilfs_destroy_cachep(); unregister_filesystem(&nilfs_fs_type); } -- cgit v0.10.2 From 9f130263f30233a44a3175db3218dd89af143d64 Mon Sep 17 00:00:00 2001 From: Li Hong Date: Fri, 9 Apr 2010 23:09:53 +0800 Subject: nilfs2: add a print message after loading nilfs2 Printing a message after loading a file system is a practice. Add this to provide a better user-friendly experience. Signed-off-by: Li Hong Signed-off-by: Ryusuke Konishi diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 5a08c82..a512c3b 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c @@ -1190,6 +1190,7 @@ static int __init init_nilfs_fs(void) if (err) goto free_cachep; + printk(KERN_INFO "NILFS version 2 loaded\n"); return 0; free_cachep: -- cgit v0.10.2 From 50614bcf29d0cec6df5b84c0d8331e8b8c7d72a7 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Sat, 10 Apr 2010 17:59:15 +0900 Subject: nilfs2: insert checkpoint number in segment summary header This adds a field to record the latest checkpoint number in the nilfs_segment_summary structure. This will help to recover the latest checkpoint number from logs on disk. This field is intended for crucial cases in which super blocks have lost pointer to the latest log. Even though this will change the disk format, both backward and forward compatibility is preserved by a size field prepared in the segment summary header. Signed-off-by: Ryusuke Konishi diff --git a/fs/nilfs2/recovery.c b/fs/nilfs2/recovery.c index ba43146..bae2a51 100644 --- a/fs/nilfs2/recovery.c +++ b/fs/nilfs2/recovery.c @@ -105,6 +105,8 @@ static void store_segsum_info(struct nilfs_segsum_info *ssi, ssi->nsumblk = DIV_ROUND_UP(ssi->sumbytes, blocksize); ssi->nfileblk = ssi->nblocks - ssi->nsumblk - !!NILFS_SEG_HAS_SR(ssi); + + /* need to verify ->ss_bytes field if read ->ss_cno */ } /** diff --git a/fs/nilfs2/segbuf.c b/fs/nilfs2/segbuf.c index 9f83bc0..2e6a272 100644 --- a/fs/nilfs2/segbuf.c +++ b/fs/nilfs2/segbuf.c @@ -134,7 +134,7 @@ int nilfs_segbuf_extend_payload(struct nilfs_segment_buffer *segbuf, } int nilfs_segbuf_reset(struct nilfs_segment_buffer *segbuf, unsigned flags, - time_t ctime) + time_t ctime, __u64 cno) { int err; @@ -147,6 +147,7 @@ int nilfs_segbuf_reset(struct nilfs_segment_buffer *segbuf, unsigned flags, segbuf->sb_sum.sumbytes = sizeof(struct nilfs_segment_summary); segbuf->sb_sum.nfinfo = segbuf->sb_sum.nfileblk = 0; segbuf->sb_sum.ctime = ctime; + segbuf->sb_sum.cno = cno; return 0; } @@ -172,6 +173,7 @@ void nilfs_segbuf_fill_in_segsum(struct nilfs_segment_buffer *segbuf) raw_sum->ss_nfinfo = cpu_to_le32(segbuf->sb_sum.nfinfo); raw_sum->ss_sumbytes = cpu_to_le32(segbuf->sb_sum.sumbytes); raw_sum->ss_pad = 0; + raw_sum->ss_cno = cpu_to_le64(segbuf->sb_sum.cno); } /* diff --git a/fs/nilfs2/segbuf.h b/fs/nilfs2/segbuf.h index e21497f..fdf1c3b 100644 --- a/fs/nilfs2/segbuf.h +++ b/fs/nilfs2/segbuf.h @@ -37,6 +37,7 @@ * @sumbytes: Byte count of segment summary * @nfileblk: Total number of file blocks * @seg_seq: Segment sequence number + * @cno: Checkpoint number * @ctime: Creation time * @next: Block number of the next full segment */ @@ -48,6 +49,7 @@ struct nilfs_segsum_info { unsigned long sumbytes; unsigned long nfileblk; u64 seg_seq; + __u64 cno; time_t ctime; sector_t next; }; @@ -135,7 +137,7 @@ void nilfs_segbuf_map_cont(struct nilfs_segment_buffer *segbuf, struct nilfs_segment_buffer *prev); void nilfs_segbuf_set_next_segnum(struct nilfs_segment_buffer *, __u64, struct the_nilfs *); -int nilfs_segbuf_reset(struct nilfs_segment_buffer *, unsigned, time_t); +int nilfs_segbuf_reset(struct nilfs_segment_buffer *, unsigned, time_t, __u64); int nilfs_segbuf_extend_segsum(struct nilfs_segment_buffer *); int nilfs_segbuf_extend_payload(struct nilfs_segment_buffer *, struct buffer_head **); diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index a17bfa1..9f50fde 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c @@ -366,7 +366,8 @@ static int nilfs_segctor_reset_segment_buffer(struct nilfs_sc_info *sci) if (nilfs_doing_gc()) flags = NILFS_SS_GC; - err = nilfs_segbuf_reset(segbuf, flags, sci->sc_seg_ctime); + err = nilfs_segbuf_reset(segbuf, flags, sci->sc_seg_ctime, + sci->sc_sbi->s_nilfs->ns_cno); if (unlikely(err)) return err; diff --git a/include/linux/nilfs2_fs.h b/include/linux/nilfs2_fs.h index f960e1d..6505c00 100644 --- a/include/linux/nilfs2_fs.h +++ b/include/linux/nilfs2_fs.h @@ -377,6 +377,7 @@ union nilfs_binfo { * @ss_nfinfo: number of finfo structures * @ss_sumbytes: total size of segment summary in bytes * @ss_pad: padding + * @ss_cno: checkpoint number */ struct nilfs_segment_summary { __le32 ss_datasum; @@ -391,6 +392,7 @@ struct nilfs_segment_summary { __le32 ss_nfinfo; __le32 ss_sumbytes; __le32 ss_pad; + __le64 ss_cno; /* array of finfo structures */ }; -- cgit v0.10.2 From 154ac5a83014cd6ea72e4ac5018bf8c10ee9a79e Mon Sep 17 00:00:00 2001 From: Li Hong Date: Sat, 10 Apr 2010 21:57:11 +0800 Subject: nilfs2: remove nilfs_segctor_init() in segment.c There are only two lines of code in nilfs_segctor_init(). From a logic design view, the first line 'sci->sc_seq_done = sci->sc_seq_request;' should be put in nilfs_segctor_new(). Even in nilfs_segctor_new(), this initialization is needless because sci is kzalloc-ed. So nilfs_segctor_init() is only a wrap call to nilfs_segctor_start_thread(). Signed-off-by: Li Hong Signed-off-by: Ryusuke Konishi diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index 9f50fde..89a15f4 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c @@ -2685,13 +2685,6 @@ static void nilfs_segctor_kill_thread(struct nilfs_sc_info *sci) } } -static int nilfs_segctor_init(struct nilfs_sc_info *sci) -{ - sci->sc_seq_done = sci->sc_seq_request; - - return nilfs_segctor_start_thread(sci); -} - /* * Setup & clean-up functions */ @@ -2815,7 +2808,7 @@ int nilfs_attach_segment_constructor(struct nilfs_sb_info *sbi) return -ENOMEM; nilfs_attach_writer(nilfs, sbi); - err = nilfs_segctor_init(NILFS_SC(sbi)); + err = nilfs_segctor_start_thread(NILFS_SC(sbi)); if (err) { nilfs_detach_writer(nilfs, sbi); kfree(sbi->s_sc_info); -- cgit v0.10.2 From fdce895ea5dd4e24edf1f4d693827349a4e5b3b4 Mon Sep 17 00:00:00 2001 From: Li Hong Date: Sat, 10 Apr 2010 23:25:39 +0800 Subject: nilfs2: change sc_timer from a pointer to an embedded one in struct nilfs_sc_info In nilfs_segctor_thread(), timer is a local variable allocated on stack. Its address can't be set to sci->sc_timer and passed in several procedures. It works now by chance, just because other procedures are called by nilfs_segctor_thread() directly or indirectly and the stack hasn't been deallocated yet. Signed-off-by: Li Hong Signed-off-by: Ryusuke Konishi diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index 89a15f4..8b4e280 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c @@ -2159,9 +2159,9 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode) static void nilfs_segctor_start_timer(struct nilfs_sc_info *sci) { spin_lock(&sci->sc_state_lock); - if (sci->sc_timer && !(sci->sc_state & NILFS_SEGCTOR_COMMIT)) { - sci->sc_timer->expires = jiffies + sci->sc_interval; - add_timer(sci->sc_timer); + if (!(sci->sc_state & NILFS_SEGCTOR_COMMIT)) { + sci->sc_timer.expires = jiffies + sci->sc_interval; + add_timer(&sci->sc_timer); sci->sc_state |= NILFS_SEGCTOR_COMMIT; } spin_unlock(&sci->sc_state_lock); @@ -2366,9 +2366,7 @@ static void nilfs_segctor_accept(struct nilfs_sc_info *sci) spin_lock(&sci->sc_state_lock); sci->sc_seq_accepted = sci->sc_seq_request; spin_unlock(&sci->sc_state_lock); - - if (sci->sc_timer) - del_timer_sync(sci->sc_timer); + del_timer_sync(&sci->sc_timer); } /** @@ -2394,9 +2392,9 @@ static void nilfs_segctor_notify(struct nilfs_sc_info *sci, int mode, int err) sci->sc_flush_request &= ~FLUSH_DAT_BIT; /* re-enable timer if checkpoint creation was not done */ - if (sci->sc_timer && (sci->sc_state & NILFS_SEGCTOR_COMMIT) && - time_before(jiffies, sci->sc_timer->expires)) - add_timer(sci->sc_timer); + if ((sci->sc_state & NILFS_SEGCTOR_COMMIT) && + time_before(jiffies, sci->sc_timer.expires)) + add_timer(&sci->sc_timer); } spin_unlock(&sci->sc_state_lock); } @@ -2575,13 +2573,10 @@ static int nilfs_segctor_thread(void *arg) { struct nilfs_sc_info *sci = (struct nilfs_sc_info *)arg; struct the_nilfs *nilfs = sci->sc_sbi->s_nilfs; - struct timer_list timer; int timeout = 0; - init_timer(&timer); - timer.data = (unsigned long)current; - timer.function = nilfs_construction_timeout; - sci->sc_timer = &timer; + sci->sc_timer.data = (unsigned long)current; + sci->sc_timer.function = nilfs_construction_timeout; /* start sync. */ sci->sc_task = current; @@ -2630,7 +2625,7 @@ static int nilfs_segctor_thread(void *arg) should_sleep = 0; else if (sci->sc_state & NILFS_SEGCTOR_COMMIT) should_sleep = time_before(jiffies, - sci->sc_timer->expires); + sci->sc_timer.expires); if (should_sleep) { spin_unlock(&sci->sc_state_lock); @@ -2639,7 +2634,7 @@ static int nilfs_segctor_thread(void *arg) } finish_wait(&sci->sc_wait_daemon, &wait); timeout = ((sci->sc_state & NILFS_SEGCTOR_COMMIT) && - time_after_eq(jiffies, sci->sc_timer->expires)); + time_after_eq(jiffies, sci->sc_timer.expires)); if (nilfs_sb_dirty(nilfs) && nilfs_sb_need_update(nilfs)) set_nilfs_discontinued(nilfs); @@ -2648,8 +2643,6 @@ static int nilfs_segctor_thread(void *arg) end_thread: spin_unlock(&sci->sc_state_lock); - del_timer_sync(sci->sc_timer); - sci->sc_timer = NULL; /* end sync. */ sci->sc_task = NULL; @@ -2708,6 +2701,7 @@ static struct nilfs_sc_info *nilfs_segctor_new(struct nilfs_sb_info *sbi) INIT_LIST_HEAD(&sci->sc_write_logs); INIT_LIST_HEAD(&sci->sc_gc_inodes); INIT_LIST_HEAD(&sci->sc_copied_buffers); + init_timer(&sci->sc_timer); sci->sc_interval = HZ * NILFS_SC_DEFAULT_TIMEOUT; sci->sc_mjcp_freq = HZ * NILFS_SC_DEFAULT_SR_FREQ; @@ -2774,6 +2768,7 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci) down_write(&sbi->s_nilfs->ns_segctor_sem); + del_timer_sync(&sci->sc_timer); kfree(sci); } diff --git a/fs/nilfs2/segment.h b/fs/nilfs2/segment.h index 7aca765..dca1423 100644 --- a/fs/nilfs2/segment.h +++ b/fs/nilfs2/segment.h @@ -177,7 +177,7 @@ struct nilfs_sc_info { unsigned long sc_lseg_stime; /* in 1/HZ seconds */ unsigned long sc_watermark; - struct timer_list *sc_timer; + struct timer_list sc_timer; struct task_struct *sc_task; }; -- cgit v0.10.2 From db55d92252c07c0e5561966ecca95c6f332dd892 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Mon, 12 Apr 2010 01:46:02 +0900 Subject: nilfs2: add kernel doc comments to persistent object allocator functions The implementation of persistent object allocator (alloc.c) is poorly documented. This adds kernel doc style comments on that functions. Signed-off-by: Ryusuke Konishi diff --git a/fs/nilfs2/alloc.c b/fs/nilfs2/alloc.c index 7cfb87e..d7fd696 100644 --- a/fs/nilfs2/alloc.c +++ b/fs/nilfs2/alloc.c @@ -31,6 +31,11 @@ #include "alloc.h" +/** + * nilfs_palloc_groups_per_desc_block - get the number of groups that a group + * descriptor block can maintain + * @inode: inode of metadata file using this allocator + */ static inline unsigned long nilfs_palloc_groups_per_desc_block(const struct inode *inode) { @@ -38,12 +43,21 @@ nilfs_palloc_groups_per_desc_block(const struct inode *inode) sizeof(struct nilfs_palloc_group_desc); } +/** + * nilfs_palloc_groups_count - get maximum number of groups + * @inode: inode of metadata file using this allocator + */ static inline unsigned long nilfs_palloc_groups_count(const struct inode *inode) { return 1UL << (BITS_PER_LONG - (inode->i_blkbits + 3 /* log2(8) */)); } +/** + * nilfs_palloc_init_blockgroup - initialize private variables for allocator + * @inode: inode of metadata file using this allocator + * @entry_size: size of the persistent object + */ int nilfs_palloc_init_blockgroup(struct inode *inode, unsigned entry_size) { struct nilfs_mdt_info *mi = NILFS_MDT(inode); @@ -69,6 +83,12 @@ int nilfs_palloc_init_blockgroup(struct inode *inode, unsigned entry_size) return 0; } +/** + * nilfs_palloc_group - get group number and offset from an entry number + * @inode: inode of metadata file using this allocator + * @nr: serial number of the entry (e.g. inode number) + * @offset: pointer to store offset number in the group + */ static unsigned long nilfs_palloc_group(const struct inode *inode, __u64 nr, unsigned long *offset) { @@ -78,6 +98,14 @@ static unsigned long nilfs_palloc_group(const struct inode *inode, __u64 nr, return group; } +/** + * nilfs_palloc_desc_blkoff - get block offset of a group descriptor block + * @inode: inode of metadata file using this allocator + * @group: group number + * + * nilfs_palloc_desc_blkoff() returns block offset of the descriptor + * block which contains a descriptor of the specified group. + */ static unsigned long nilfs_palloc_desc_blkoff(const struct inode *inode, unsigned long group) { @@ -86,6 +114,14 @@ nilfs_palloc_desc_blkoff(const struct inode *inode, unsigned long group) return desc_block * NILFS_MDT(inode)->mi_blocks_per_desc_block; } +/** + * nilfs_palloc_bitmap_blkoff - get block offset of a bitmap block + * @inode: inode of metadata file using this allocator + * @group: group number + * + * nilfs_palloc_bitmap_blkoff() returns block offset of the bitmap + * block used to allocate/deallocate entries in the specified group. + */ static unsigned long nilfs_palloc_bitmap_blkoff(const struct inode *inode, unsigned long group) { @@ -95,6 +131,12 @@ nilfs_palloc_bitmap_blkoff(const struct inode *inode, unsigned long group) desc_offset * NILFS_MDT(inode)->mi_blocks_per_group; } +/** + * nilfs_palloc_group_desc_nfrees - get the number of free entries in a group + * @inode: inode of metadata file using this allocator + * @group: group number + * @desc: pointer to descriptor structure for the group + */ static unsigned long nilfs_palloc_group_desc_nfrees(struct inode *inode, unsigned long group, const struct nilfs_palloc_group_desc *desc) @@ -107,6 +149,13 @@ nilfs_palloc_group_desc_nfrees(struct inode *inode, unsigned long group, return nfree; } +/** + * nilfs_palloc_group_desc_add_entries - adjust count of free entries + * @inode: inode of metadata file using this allocator + * @group: group number + * @desc: pointer to descriptor structure for the group + * @n: delta to be added + */ static void nilfs_palloc_group_desc_add_entries(struct inode *inode, unsigned long group, @@ -118,6 +167,11 @@ nilfs_palloc_group_desc_add_entries(struct inode *inode, spin_unlock(nilfs_mdt_bgl_lock(inode, group)); } +/** + * nilfs_palloc_entry_blkoff - get block offset of an entry block + * @inode: inode of metadata file using this allocator + * @nr: serial number of the entry (e.g. inode number) + */ static unsigned long nilfs_palloc_entry_blkoff(const struct inode *inode, __u64 nr) { @@ -129,6 +183,12 @@ nilfs_palloc_entry_blkoff(const struct inode *inode, __u64 nr) group_offset / NILFS_MDT(inode)->mi_entries_per_block; } +/** + * nilfs_palloc_desc_block_init - initialize buffer of a group descriptor block + * @inode: inode of metadata file + * @bh: buffer head of the buffer to be initialized + * @kaddr: kernel address mapped for the page including the buffer + */ static void nilfs_palloc_desc_block_init(struct inode *inode, struct buffer_head *bh, void *kaddr) { @@ -179,6 +239,13 @@ static int nilfs_palloc_get_block(struct inode *inode, unsigned long blkoff, return ret; } +/** + * nilfs_palloc_get_desc_block - get buffer head of a group descriptor block + * @inode: inode of metadata file using this allocator + * @group: group number + * @create: create flag + * @bhp: pointer to store the resultant buffer head + */ static int nilfs_palloc_get_desc_block(struct inode *inode, unsigned long group, int create, struct buffer_head **bhp) @@ -191,6 +258,13 @@ static int nilfs_palloc_get_desc_block(struct inode *inode, bhp, &cache->prev_desc, &cache->lock); } +/** + * nilfs_palloc_get_bitmap_block - get buffer head of a bitmap block + * @inode: inode of metadata file using this allocator + * @group: group number + * @create: create flag + * @bhp: pointer to store the resultant buffer head + */ static int nilfs_palloc_get_bitmap_block(struct inode *inode, unsigned long group, int create, struct buffer_head **bhp) @@ -203,6 +277,13 @@ static int nilfs_palloc_get_bitmap_block(struct inode *inode, &cache->prev_bitmap, &cache->lock); } +/** + * nilfs_palloc_get_entry_block - get buffer head of an entry block + * @inode: inode of metadata file using this allocator + * @nr: serial number of the entry (e.g. inode number) + * @create: create flag + * @bhp: pointer to store the resultant buffer head + */ int nilfs_palloc_get_entry_block(struct inode *inode, __u64 nr, int create, struct buffer_head **bhp) { @@ -214,6 +295,13 @@ int nilfs_palloc_get_entry_block(struct inode *inode, __u64 nr, &cache->prev_entry, &cache->lock); } +/** + * nilfs_palloc_block_get_group_desc - get kernel address of a group descriptor + * @inode: inode of metadata file using this allocator + * @group: group number + * @bh: buffer head of the buffer storing the group descriptor block + * @kaddr: kernel address mapped for the page including the buffer + */ static struct nilfs_palloc_group_desc * nilfs_palloc_block_get_group_desc(const struct inode *inode, unsigned long group, @@ -223,6 +311,13 @@ nilfs_palloc_block_get_group_desc(const struct inode *inode, group % nilfs_palloc_groups_per_desc_block(inode); } +/** + * nilfs_palloc_block_get_entry - get kernel address of an entry + * @inode: inode of metadata file using this allocator + * @nr: serial number of the entry (e.g. inode number) + * @bh: buffer head of the buffer storing the entry block + * @kaddr: kernel address mapped for the page including the buffer + */ void *nilfs_palloc_block_get_entry(const struct inode *inode, __u64 nr, const struct buffer_head *bh, void *kaddr) { @@ -235,11 +330,19 @@ void *nilfs_palloc_block_get_entry(const struct inode *inode, __u64 nr, entry_offset * NILFS_MDT(inode)->mi_entry_size; } +/** + * nilfs_palloc_find_available_slot - find available slot in a group + * @inode: inode of metadata file using this allocator + * @group: group number + * @target: offset number of an entry in the group (start point) + * @bitmap: bitmap of the group + * @bsize: size in bits + */ static int nilfs_palloc_find_available_slot(struct inode *inode, unsigned long group, unsigned long target, unsigned char *bitmap, - int bsize) /* size in bits */ + int bsize) { int curr, pos, end, i; @@ -277,6 +380,13 @@ static int nilfs_palloc_find_available_slot(struct inode *inode, return -ENOSPC; } +/** + * nilfs_palloc_rest_groups_in_desc_block - get the remaining number of groups + * in a group descriptor block + * @inode: inode of metadata file using this allocator + * @curr: current group number + * @max: maximum number of groups + */ static unsigned long nilfs_palloc_rest_groups_in_desc_block(const struct inode *inode, unsigned long curr, unsigned long max) @@ -287,6 +397,11 @@ nilfs_palloc_rest_groups_in_desc_block(const struct inode *inode, max - curr + 1); } +/** + * nilfs_palloc_prepare_alloc_entry - prepare to allocate a persistent object + * @inode: inode of metadata file using this allocator + * @req: nilfs_palloc_req structure exchanged for the allocation + */ int nilfs_palloc_prepare_alloc_entry(struct inode *inode, struct nilfs_palloc_req *req) { @@ -366,6 +481,11 @@ int nilfs_palloc_prepare_alloc_entry(struct inode *inode, return ret; } +/** + * nilfs_palloc_commit_alloc_entry - finish allocation of a persistent object + * @inode: inode of metadata file using this allocator + * @req: nilfs_palloc_req structure exchanged for the allocation + */ void nilfs_palloc_commit_alloc_entry(struct inode *inode, struct nilfs_palloc_req *req) { @@ -377,6 +497,11 @@ void nilfs_palloc_commit_alloc_entry(struct inode *inode, brelse(req->pr_desc_bh); } +/** + * nilfs_palloc_commit_free_entry - finish deallocating a persistent object + * @inode: inode of metadata file using this allocator + * @req: nilfs_palloc_req structure exchanged for the removal + */ void nilfs_palloc_commit_free_entry(struct inode *inode, struct nilfs_palloc_req *req) { @@ -410,6 +535,11 @@ void nilfs_palloc_commit_free_entry(struct inode *inode, brelse(req->pr_desc_bh); } +/** + * nilfs_palloc_abort_alloc_entry - cancel allocation of a persistent object + * @inode: inode of metadata file using this allocator + * @req: nilfs_palloc_req structure exchanged for the allocation + */ void nilfs_palloc_abort_alloc_entry(struct inode *inode, struct nilfs_palloc_req *req) { @@ -442,6 +572,11 @@ void nilfs_palloc_abort_alloc_entry(struct inode *inode, req->pr_desc_bh = NULL; } +/** + * nilfs_palloc_prepare_free_entry - prepare to deallocate a persistent object + * @inode: inode of metadata file using this allocator + * @req: nilfs_palloc_req structure exchanged for the removal + */ int nilfs_palloc_prepare_free_entry(struct inode *inode, struct nilfs_palloc_req *req) { @@ -464,6 +599,11 @@ int nilfs_palloc_prepare_free_entry(struct inode *inode, return 0; } +/** + * nilfs_palloc_abort_free_entry - cancel deallocating a persistent object + * @inode: inode of metadata file using this allocator + * @req: nilfs_palloc_req structure exchanged for the removal + */ void nilfs_palloc_abort_free_entry(struct inode *inode, struct nilfs_palloc_req *req) { @@ -475,6 +615,12 @@ void nilfs_palloc_abort_free_entry(struct inode *inode, req->pr_desc_bh = NULL; } +/** + * nilfs_palloc_group_is_in - judge if an entry is in a group + * @inode: inode of metadata file using this allocator + * @group: group number + * @nr: serial number of the entry (e.g. inode number) + */ static int nilfs_palloc_group_is_in(struct inode *inode, unsigned long group, __u64 nr) { @@ -485,6 +631,12 @@ nilfs_palloc_group_is_in(struct inode *inode, unsigned long group, __u64 nr) return (nr >= first) && (nr <= last); } +/** + * nilfs_palloc_freev - deallocate a set of persistent objects + * @inode: inode of metadata file using this allocator + * @entry_nrs: array of entry numbers to be deallocated + * @nitems: number of entries stored in @entry_nrs + */ int nilfs_palloc_freev(struct inode *inode, __u64 *entry_nrs, size_t nitems) { struct buffer_head *desc_bh, *bitmap_bh; diff --git a/fs/nilfs2/alloc.h b/fs/nilfs2/alloc.h index 5cccf87..9af34a7 100644 --- a/fs/nilfs2/alloc.h +++ b/fs/nilfs2/alloc.h @@ -29,6 +29,13 @@ #include #include +/** + * nilfs_palloc_entries_per_group - get the number of entries per group + * @inode: inode of metadata file using this allocator + * + * The number of entries per group is defined by the number of bits + * that a bitmap block can maintain. + */ static inline unsigned long nilfs_palloc_entries_per_group(const struct inode *inode) { -- cgit v0.10.2 From 4e819509cba664e7cbfba5c4d1517df4dfda86f5 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Fri, 23 Apr 2010 17:35:23 +0900 Subject: nilfs2: make nilfs_sc_*_ops static This kills the following sparse warnings: fs/nilfs2/segment.c:567:28: warning: symbol 'nilfs_sc_file_ops' was not declared. Should it be static? fs/nilfs2/segment.c:617:28: warning: symbol 'nilfs_sc_dat_ops' was not declared. Should it be static? fs/nilfs2/segment.c:625:28: warning: symbol 'nilfs_sc_dsync_ops' was not declared. Should it be static? Signed-off-by: Ryusuke Konishi diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index 8b4e280..c920164 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c @@ -564,7 +564,7 @@ static void nilfs_write_file_node_binfo(struct nilfs_sc_info *sci, *vblocknr = binfo->bi_v.bi_vblocknr; } -struct nilfs_sc_operations nilfs_sc_file_ops = { +static struct nilfs_sc_operations nilfs_sc_file_ops = { .collect_data = nilfs_collect_file_data, .collect_node = nilfs_collect_file_node, .collect_bmap = nilfs_collect_file_bmap, @@ -614,7 +614,7 @@ static void nilfs_write_dat_node_binfo(struct nilfs_sc_info *sci, *binfo_dat = binfo->bi_dat; } -struct nilfs_sc_operations nilfs_sc_dat_ops = { +static struct nilfs_sc_operations nilfs_sc_dat_ops = { .collect_data = nilfs_collect_dat_data, .collect_node = nilfs_collect_file_node, .collect_bmap = nilfs_collect_dat_bmap, @@ -622,7 +622,7 @@ struct nilfs_sc_operations nilfs_sc_dat_ops = { .write_node_binfo = nilfs_write_dat_node_binfo, }; -struct nilfs_sc_operations nilfs_sc_dsync_ops = { +static struct nilfs_sc_operations nilfs_sc_dsync_ops = { .collect_data = nilfs_collect_file_data, .collect_node = NULL, .collect_bmap = NULL, -- cgit v0.10.2 From 34cb9b5c973ac06449b96884be932da9a9b99819 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Sat, 1 May 2010 10:07:07 +0900 Subject: nilfs2: add missing endian conversion on super block magic number This adds missing endian conversions in comparision of the magic number of super blocks. It was coincidence that prior versions didn't incur problems; the upper byte of the magic number happened to be equal to the lower byte. But, semantically it's wrong to depend on this. This won't change anything else nor suffer any compatibility issues. Signed-off-by: Ryusuke Konishi diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index a512c3b..430a508 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c @@ -242,8 +242,8 @@ int nilfs_commit_super(struct nilfs_sb_info *sbi, int dupsb) int err; /* nilfs->sem must be locked by the caller. */ - if (sbp[0]->s_magic != NILFS_SUPER_MAGIC) { - if (sbp[1] && sbp[1]->s_magic == NILFS_SUPER_MAGIC) + if (sbp[0]->s_magic != cpu_to_le16(NILFS_SUPER_MAGIC)) { + if (sbp[1] && sbp[1]->s_magic == cpu_to_le16(NILFS_SUPER_MAGIC)) nilfs_swap_super_block(nilfs); else { printk(KERN_CRIT "NILFS: superblock broke on dev %s\n", -- cgit v0.10.2 From 25294d8c376296b1420694317e9856eaaea710ca Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Sat, 1 May 2010 11:54:21 +0900 Subject: nilfs2: use checkpoint number instead of timestamp to select super block Nilfs maintains two super blocks, and selects the new one on mount time if they both have valid checksums and their timestamps differ. However, this has potential for mis-selection since the system clock may be rewinded and the resolution of the timestamps is not high. Usually this doesn't become an issue because both super blocks are updated at the same time when the file system is unmounted. Even if the file system wasn't unmounted cleanly, the roll-forward recovery will find the proper log which stores the latest super root. Thus, the issue can appear only if update of one super block fails and the clock happens to be rewinded. This fixes the issue by using checkpoint numbers instead of timestamps to pick the super block storing the location of the latest log. Signed-off-by: Ryusuke Konishi diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c index 33871f7..a756168 100644 --- a/fs/nilfs2/the_nilfs.c +++ b/fs/nilfs2/the_nilfs.c @@ -486,11 +486,15 @@ static int nilfs_load_super_block(struct the_nilfs *nilfs, printk(KERN_WARNING "NILFS warning: unable to read secondary superblock\n"); + /* + * Compare two super blocks and set 1 in swp if the secondary + * super block is valid and newer. Otherwise, set 0 in swp. + */ valid[0] = nilfs_valid_sb(sbp[0]); valid[1] = nilfs_valid_sb(sbp[1]); - swp = valid[1] && - (!valid[0] || - le64_to_cpu(sbp[1]->s_wtime) > le64_to_cpu(sbp[0]->s_wtime)); + swp = valid[1] && (!valid[0] || + le64_to_cpu(sbp[1]->s_last_cno) > + le64_to_cpu(sbp[0]->s_last_cno)); if (valid[swp] && nilfs_sb2_bad_offset(sbp[swp], sb2off)) { brelse(sbh[1]); -- cgit v0.10.2 From 400ade845cb9930552e791bbd658a0953f68499d Mon Sep 17 00:00:00 2001 From: Jiro SEKIBA Date: Sun, 2 May 2010 23:29:04 +0900 Subject: nilfs2: enlarge s_volume_name member in nilfs_super_block Current s_volume_name has 16 bytes, which is too small as modern filesystem. s_last_mounted resides just after s_volume_name and has 64 bytes. s_last_mounted is historically came from ext2, but not used in nilfs2 at all. Deleting s_last_mounted member and merging that space with s_volume_name enlarge s_volume_name upto 80 bytes for volume label. When user land tools see the old header for new disk, it will just ignore additional bytes stored in s_last_mounted. While, old disk format has only 16 bytes label, it doesn't affects in case seeing the new header for old disk. Signed-off-by: Jiro SEKIBA Signed-off-by: Ryusuke Konishi diff --git a/include/linux/nilfs2_fs.h b/include/linux/nilfs2_fs.h index 6505c00..8c2c611 100644 --- a/include/linux/nilfs2_fs.h +++ b/include/linux/nilfs2_fs.h @@ -207,8 +207,7 @@ struct nilfs_super_block { __le16 s_segment_usage_size; /* Size of a segment usage */ __u8 s_uuid[16]; /* 128-bit uuid for volume */ - char s_volume_name[16]; /* volume name */ - char s_last_mounted[64]; /* directory where last mounted */ + char s_volume_name[80]; /* volume name */ __le32 s_c_interval; /* Commit interval of segment */ __le32 s_c_block_max; /* Threshold of data amount for -- cgit v0.10.2 From 13e905592b3daacb6ec27a5a4169afe725c3b668 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Sun, 9 May 2010 02:57:57 +0900 Subject: nilfs2: fix misuse of open_bdev_exclusive/close_bdev_exclusive The second argument of open_bdev_exclusive/close_bdev_exclusive takes fmode_t flags instead of mount flags. This fixes the misuse. Signed-off-by: Ryusuke Konishi diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 430a508..3ff2118 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c @@ -998,10 +998,14 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags, { struct nilfs_super_data sd; struct super_block *s; + fmode_t mode = FMODE_READ; struct the_nilfs *nilfs; int err, need_to_close = 1; - sd.bdev = open_bdev_exclusive(dev_name, flags, fs_type); + if (!(flags & MS_RDONLY)) + mode |= FMODE_WRITE; + + sd.bdev = open_bdev_exclusive(dev_name, mode, fs_type); if (IS_ERR(sd.bdev)) return PTR_ERR(sd.bdev); @@ -1082,7 +1086,7 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags, mutex_unlock(&nilfs->ns_mount_mutex); put_nilfs(nilfs); if (need_to_close) - close_bdev_exclusive(sd.bdev, flags); + close_bdev_exclusive(sd.bdev, mode); simple_set_mnt(mnt, s); return 0; @@ -1090,7 +1094,7 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags, mutex_unlock(&nilfs->ns_mount_mutex); put_nilfs(nilfs); failed: - close_bdev_exclusive(sd.bdev, flags); + close_bdev_exclusive(sd.bdev, mode); return err; -- cgit v0.10.2 From 4571b82cdcd076a3b8ecaddcf9846cb52f9979e5 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Sun, 9 May 2010 03:01:32 +0900 Subject: nilfs2: add missing initialization of s_mode An fmode_t argument is passed to kill_block_super() through s_mode member of the super_block structure. This is used to release the block device with the same mode, however, nilfs does not set s_mode anywhere. This modifies nilfs_get_sb function to properly initialize the s_mode member. Signed-off-by: Ryusuke Konishi diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 3ff2118..16939b3 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c @@ -1072,6 +1072,7 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags, /* New superblock instance created */ s->s_flags = flags; + s->s_mode = mode; strlcpy(s->s_id, bdevname(sd.bdev, b), sizeof(s->s_id)); sb_set_blocksize(s, block_size(sd.bdev)); -- cgit v0.10.2 From e2d1591a13118b2bccb41af06830a2904478a514 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Sun, 9 May 2010 09:48:31 +0900 Subject: nilfs2: replace MS_VERBOSE with MS_SILENT MS_VERBOSE is deprecated. This replaces it with MS_SILENT in reference to get_sb_bdev function. Signed-off-by: Ryusuke Konishi diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 16939b3..6b05771 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c @@ -1076,7 +1076,8 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags, strlcpy(s->s_id, bdevname(sd.bdev, b), sizeof(s->s_id)); sb_set_blocksize(s, block_size(sd.bdev)); - err = nilfs_fill_super(s, data, flags & MS_VERBOSE, nilfs); + err = nilfs_fill_super(s, data, flags & MS_SILENT ? 1 : 0, + nilfs); if (err) goto cancel_new; -- cgit v0.10.2 From b87ca91948843472c05ae49e4c5e1714001d24c9 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Sun, 9 May 2010 10:05:21 +0900 Subject: nilfs2: update comment on deactivate_super at nilfs_get_sb deactivate_super was replaced with deactivate_locked_super, but the comment of nilfs_get_sb remain unchanged. This renews the comment. Signed-off-by: Ryusuke Konishi diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 6b05771..c88e664 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c @@ -1106,7 +1106,7 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags, put_nilfs(nilfs); deactivate_locked_super(s); /* - * deactivate_super() invokes close_bdev_exclusive(). + * deactivate_locked_super() invokes close_bdev_exclusive(). * We must finish all post-cleaning before this call; * put_nilfs() needs the block device. */ -- cgit v0.10.2 From cdce214e39814fd46d47e0e660ca3ddf3fdce8a6 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Sun, 9 May 2010 15:31:22 +0900 Subject: nilfs2: use huge_encode_dev/huge_decode_dev This replaces uses of new_encode_dev/new_decode_dev with their 64-bit counterparts, huge_encode_dev/huge_decode_dev respectively. This is just for clarification and has no impact on the disk format. Signed-off-by: Ryusuke Konishi diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index 0957b58..5e226d4 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c @@ -451,7 +451,7 @@ static int __nilfs_read_inode(struct super_block *sb, unsigned long ino, inode->i_op = &nilfs_special_inode_operations; init_special_inode( inode, inode->i_mode, - new_decode_dev(le64_to_cpu(raw_inode->i_device_code))); + huge_decode_dev(le64_to_cpu(raw_inode->i_device_code))); } nilfs_ifile_unmap_inode(sbi->s_ifile, ino, bh); brelse(bh); @@ -511,7 +511,7 @@ void nilfs_write_inode_common(struct inode *inode, nilfs_bmap_write(ii->i_bmap, raw_inode); else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) raw_inode->i_device_code = - cpu_to_le64(new_encode_dev(inode->i_rdev)); + cpu_to_le64(huge_encode_dev(inode->i_rdev)); /* When extending inode, nilfs->ns_inode_size should be checked for substitutions of appended fields */ } -- cgit v0.10.2 From d240e06713007bba309b074a386b7072b73c31a6 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Sun, 9 May 2010 21:51:53 +0900 Subject: nilfs2: disallow remount of snapshot from/to a regular mount Snapshots and regular ro/rw mounts are essentially-different within the meaning whether the checkpoint is static or not and is marked with a snapshot flag or not. The current implemenation, however, allows to remount a snapshot to a regular rw-mount if the checkpoint number equals the latest one. This transition is actually impossible since changing a checkpoint to a snapshot makes another checkpoint, thus the condition is never satisfied. This fixes the weird state of affairs, and specifically separates snapshots and regular rw/ro-mounts. Signed-off-by: Ryusuke Konishi diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index c88e664..03b34b7 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c @@ -754,9 +754,7 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent, goto failed_sbi; } cno = sbi->s_snapshot_cno; - } else - /* Read-only mount */ - sbi->s_snapshot_cno = cno; + } } err = nilfs_attach_checkpoint(sbi, cno); @@ -825,7 +823,7 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) struct the_nilfs *nilfs = sbi->s_nilfs; unsigned long old_sb_flags; struct nilfs_mount_options old_opts; - int err; + int was_snapshot, err; lock_kernel(); @@ -833,6 +831,7 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) old_sb_flags = sb->s_flags; old_opts.mount_opt = sbi->s_mount_opt; old_opts.snapshot_cno = sbi->s_snapshot_cno; + was_snapshot = nilfs_test_opt(sbi, SNAPSHOT); if (!parse_options(data, sb)) { err = -EINVAL; @@ -840,20 +839,32 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) } sb->s_flags = (sb->s_flags & ~MS_POSIXACL); - if ((*flags & MS_RDONLY) && - sbi->s_snapshot_cno != old_opts.snapshot_cno) { - printk(KERN_WARNING "NILFS (device %s): couldn't " - "remount to a different snapshot.\n", - sb->s_id); - err = -EINVAL; - goto restore_opts; + err = -EINVAL; + if (was_snapshot) { + if (!(*flags & MS_RDONLY)) { + printk(KERN_ERR "NILFS (device %s): cannot remount " + "snapshot read/write.\n", + sb->s_id); + goto restore_opts; + } else if (sbi->s_snapshot_cno != old_opts.snapshot_cno) { + printk(KERN_ERR "NILFS (device %s): cannot " + "remount to a different snapshot.\n", + sb->s_id); + goto restore_opts; + } + } else { + if (nilfs_test_opt(sbi, SNAPSHOT)) { + printk(KERN_ERR "NILFS (device %s): cannot change " + "a regular mount to a snapshot.\n", + sb->s_id); + goto restore_opts; + } } if (!nilfs_valid_fs(nilfs)) { printk(KERN_WARNING "NILFS (device %s): couldn't " "remount because the filesystem is in an " "incomplete recovery state.\n", sb->s_id); - err = -EINVAL; goto restore_opts; } @@ -864,9 +875,6 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) nilfs_detach_segment_constructor(sbi); sb->s_flags |= MS_RDONLY; - sbi->s_snapshot_cno = nilfs_last_cno(nilfs); - /* nilfs_set_opt(sbi, SNAPSHOT); */ - /* * Remounting a valid RW partition RDONLY, so set * the RDONLY flag and then mark the partition as valid again. @@ -885,24 +893,7 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) * store the current valid flag. (It may have been changed * by fsck since we originally mounted the partition.) */ - if (nilfs->ns_current && nilfs->ns_current != sbi) { - printk(KERN_WARNING "NILFS (device %s): couldn't " - "remount because an RW-mount exists.\n", - sb->s_id); - err = -EBUSY; - goto restore_opts; - } - if (sbi->s_snapshot_cno != nilfs_last_cno(nilfs)) { - printk(KERN_WARNING "NILFS (device %s): couldn't " - "remount because the current RO-mount is not " - "the latest one.\n", - sb->s_id); - err = -EINVAL; - goto restore_opts; - } sb->s_flags &= ~MS_RDONLY; - nilfs_clear_opt(sbi, SNAPSHOT); - sbi->s_snapshot_cno = 0; err = nilfs_attach_segment_constructor(sbi); if (err) @@ -911,8 +902,6 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) down_write(&nilfs->ns_sem); nilfs_setup_super(sbi); up_write(&nilfs->ns_sem); - - nilfs->ns_current = sbi; } out: up_write(&nilfs->ns_super_sem); -- cgit v0.10.2