On Tue, 24 Feb 2015 20:01:39 +0100, Andreas Rohner wrote: > This patch adds a function to modify the su_nlive_blks field of the > nilfs_segment_usage structure in the SUFILE. By using positive or > negative integers, it is possible to add and substract any value from > the su_nlive_blks field. > > The use of a modification cache is optional and by passing a NULL > pointer the value will be added or subtracted directly. Otherwise it is > necessary to call nilfs_sufile_flush_nlive_blks() at some point to make > the modifications persistent. > > The modification cache is useful, because it allows for small values, > like simple increments and decrements, to be added up before writing > them to the SUFILE. > > Signed-off-by: Andreas Rohner <andreas.rohner@xxxxxxx> > --- > fs/nilfs2/sufile.c | 138 +++++++++++++++++++++++++++++++++++++++++++++++++++++ > fs/nilfs2/sufile.h | 5 ++ > 2 files changed, 143 insertions(+) > > diff --git a/fs/nilfs2/sufile.c b/fs/nilfs2/sufile.c > index ae08050..574a77e 100644 > --- a/fs/nilfs2/sufile.c > +++ b/fs/nilfs2/sufile.c > @@ -1380,6 +1380,144 @@ static inline int nilfs_sufile_mc_update(struct inode *sufile, > } > > /** > + * nilfs_sufile_do_flush_nlive_blks - apply modification to su_nlive_blks > + * @sufile: inode of segment usage file > + * @mod: modification structure > + * @header_bh: sufile header block > + * @su_bh: block containing segment usage of m_segnum in @mod > + * > + * Description: nilfs_sufile_do_flush_nlive_blks() is a callback function > + * used with nilfs_sufile_updatev(), that adds m_value in @mod to > + * the su_nlive_blks field of the segment usage entry belonging to m_segnum. > + */ > +static void nilfs_sufile_do_flush_nlive_blks(struct inode *sufile, > + struct nilfs_sufile_mod *mod, > + struct buffer_head *header_bh, > + struct buffer_head *su_bh) > +{ > + struct the_nilfs *nilfs = sufile->i_sb->s_fs_info; > + struct nilfs_segment_usage *su; > + void *kaddr; > + __u32 nblocks, nlive_blocks; > + __u64 segnum = mod->m_segnum; > + __s64 value = mod->m_value; > + > + if (!value) > + return; > + > + kaddr = kmap_atomic(su_bh->b_page); > + > + su = nilfs_sufile_block_get_segment_usage(sufile, segnum, su_bh, kaddr); > + WARN_ON(nilfs_segment_usage_error(su)); > + > + nblocks = le32_to_cpu(su->su_nblocks); > + nlive_blocks = le32_to_cpu(su->su_nlive_blks); > + > + value += nlive_blocks; > + if (value < 0) > + value = 0; > + else if (value > nblocks) > + value = nblocks; > + > + /* do nothing if the value didn't change */ > + if (value != nlive_blocks) { > + su->su_nlive_blks = cpu_to_le32(value); > + su->su_nlive_lastmod = cpu_to_le64(nilfs->ns_ctime); ns_ctime should not be used because it is updated after writing segment. get_seconds() should be used. > + } > + > + kunmap_atomic(kaddr); > + > + if (value != nlive_blocks) { > + mark_buffer_dirty(su_bh); > + nilfs_mdt_mark_dirty(sufile); > + } > +} > + > +/** > + * nilfs_sufile_flush_nlive_blks - flush mod cache to su_nlive_blks > + * @sufile: inode of segment usage file > + * @mc: modification cache > + * > + * Description: nilfs_sufile_flush_nlive_blks() flushes the cached > + * modifications in @mc, by applying them to the su_nlive_blks field of > + * the corresponding segment usage entries. @mc can be NULL or empty. If > + * the sufile extension needed to support su_nlive_blks is not supported the > + * function will abort without error. > + * > + * Return Value: On success, zero is returned. On error, one of the > + * following negative error codes is returned. > + * > + * %-EIO - I/O error. > + * > + * %-ENOMEM - Insufficient amount of memory available. > + * > + * %-ENOENT - Given segment usage is in hole block > + * > + * %-EINVAL - Invalid segment usage number > + */ > +int nilfs_sufile_flush_nlive_blks(struct inode *sufile, > + struct nilfs_sufile_mod_cache *mc) > +{ > + int ret; > + > + if (!mc || !mc->mc_size || !nilfs_sufile_ext_supported(sufile)) > + return 0; > + > + ret = nilfs_sufile_mc_flush(sufile, mc, > + nilfs_sufile_do_flush_nlive_blks); > + > + nilfs_sufile_mc_clear(mc); > + > + return ret; > +} > + > +/** > + * nilfs_sufile_mod_nlive_blks - modifiy su_nlive_blks using mod cache > + * @sufile: inode of segment usage file > + * @mc: modification cache > + * @segnum: segment number > + * @value: signed value (can be positive and negative) > + * > + * Description: nilfs_sufile_mod_nlive_blks() adds @value to the su_nlive_blks > + * field of the segment usage entry for @segnum. If @mc is not NULL it first > + * accumulates all modifications in the cache and flushes it if it is full. > + * Otherwise the change is applied directly. > + * > + * Return Value: On success, zero is returned. On error, one of the > + * following negative error codes is returned. > + * > + * %-EIO - I/O error. > + * > + * %-ENOMEM - Insufficient amount of memory available. > + * > + * %-ENOENT - Given segment usage is in hole block > + * > + * %-EINVAL - Invalid segment usage number > + */ > +int nilfs_sufile_mod_nlive_blks(struct inode *sufile, > + struct nilfs_sufile_mod_cache *mc, > + __u64 segnum, __s64 value) > +{ > + int ret; > + > + if (!value || !nilfs_sufile_ext_supported(sufile)) > + return 0; > + > + if (!mc) > + return nilfs_sufile_mc_update(sufile, segnum, value, > + nilfs_sufile_do_flush_nlive_blks); > + > + if (!nilfs_sufile_mc_add(mc, segnum, value)) > + return 0; > + > + ret = nilfs_sufile_flush_nlive_blks(sufile, mc); > + > + nilfs_sufile_mc_reset(mc, segnum, value); > + > + return ret; > +} > + > +/** > * nilfs_sufile_read - read or get sufile inode > * @sb: super block instance > * @susize: size of a segment usage entry > diff --git a/fs/nilfs2/sufile.h b/fs/nilfs2/sufile.h > index d56498b..ae3c52a 100644 > --- a/fs/nilfs2/sufile.h > +++ b/fs/nilfs2/sufile.h > @@ -195,4 +195,9 @@ static inline void nilfs_sufile_mc_destroy(struct nilfs_sufile_mod_cache *mc) > } > } > > +int nilfs_sufile_flush_nlive_blks(struct inode *, > + struct nilfs_sufile_mod_cache *); > +int nilfs_sufile_mod_nlive_blks(struct inode *, struct nilfs_sufile_mod_cache *, > + __u64, __s64); > + Please add variable names to arguments of new declarations. (You don't have to add variable names to unrelated declarations) Regards, Ryusuke Konishi > #endif /* _NILFS_SUFILE_H */ > -- > 2.3.0 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-nilfs" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-nilfs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html