From: Vyacheslav Dubeyko <slava@xxxxxxxxxxx> Subject: [RFC][PATCH 08/15] nilfs2: implement prepare-(commit|abort) pair of xanode change functionality This patch adds functionality of new xanode initialization, preparation for modification and commit/abort at the end of modification operation. Signed-off-by: Vyacheslav Dubeyko <slava@xxxxxxxxxxx> CC: Ryusuke Konishi <konishi.ryusuke@xxxxxxxxxxxxx> --- fs/nilfs2/xafile.c | 269 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 269 insertions(+) diff --git a/fs/nilfs2/xafile.c b/fs/nilfs2/xafile.c index 1c95fb2..6511da7 100644 --- a/fs/nilfs2/xafile.c +++ b/fs/nilfs2/xafile.c @@ -1031,3 +1031,272 @@ start_entry_search: failed_find_node: return err; } + +/* + * __nilfs_xafile_node_init - initialize newly created xanode in memory + * @inode: inode pointer + * @node_type: xanode type + * @buf: xanode's buffer in memory + * @buf_size: buffer size + */ +static +void __nilfs_xafile_node_init(struct inode *inode, + int node_type, + void *buf, size_t buf_size) +{ + union nilfs_xanode_header *hdr = NILFS_XANODE_HDR(buf); + +#ifdef CONFIG_NILFS2_FS_DEBUG + BUG_ON(node_type > NILFS_XATTR_TREE_XANODE_TYPE); +#endif + + switch(node_type) { + case NILFS_XATTR_TREE_XANODE_TYPE: + hdr->tree_hdr.magic = cpu_to_le16(NILFS_XANODE_MAGIC); + hdr->tree_hdr.flags = NILFS_XANODE_SET_TYPE(node_type, hdr); + hdr->tree_hdr.flags = + NILFS_XANODE_SET_FLAGS(NILFS_XANODE_CRC32_FLAG, hdr); + hdr->tree_hdr.height = 0; + hdr->tree_hdr.log_index_keys = + ilog2(NILFS_XANODE_MIN_INDEX_KEYS); + hdr->tree_hdr.entries = 0; + hdr->tree_hdr.checksum = 0; + hdr->tree_hdr.index_keys = 0; + hdr->tree_hdr.parent_node = cpu_to_le64(NILFS_INVALID_XANODE); + break; + + default: + BUG(); + }; +} + +/* + * nilfs_xafile_node_init - initialize new xanode and mark buffer dirty + * @inode: inode pointer + * @node: xanode number (index in xafile) + * @node_type: xanode type + * @bh: xanode buffer + */ +/*static +void nilfs_xafile_node_init(struct inode *inode, __u64 node, + int node_type, struct buffer_head *bh) +{ + __nilfs_xafile_node_init(inode, node_type, BH_DATA(bh), BH_SIZE(bh)); + + switch(node_type) { + case NILFS_XATTR_TREE_XANODE_TYPE: + NILFS_XANODE_HDR(BH_DATA(bh))->tree_hdr.checksum = + nilfs_xafile_node_crc32(inode, BH_DATA(bh), + BH_SIZE(bh), node); + break; + + default: + BUG(); + }; + + mark_buffer_dirty(bh); +}*/ + +/* + * nilfs_xafile_prepare_new_node - prepare new xanode for shadow modifications + * @inode: inode pointer + * @new_node: prepared internal xattr search structure [out] + */ +static +int nilfs_xafile_prepare_new_node(struct inode *inode, + struct nilfs_xattr_search *new_node) +{ + int err; + struct the_nilfs *nilfs = inode->i_sb->s_fs_info; + struct inode *xafile = nilfs->ns_xafile; + union nilfs_xanode_header *hdr; + char *buf; + +#ifdef CONFIG_NILFS2_FS_DEBUG + BUG_ON(!IS_SEARCH_RESULT_EMPTY(new_node)); +#endif + + err = nilfs_xafile_prepare_node_creation(xafile, &new_node->node.req); + if (unlikely(err)) { + printk(KERN_ERR "NILFS: can't prepare new xafile node\n"); + return err; + } + + buf = kzalloc(BH_SIZE(NODE_BH(&new_node->node)), GFP_NOFS); + if (!buf) { + nilfs_xafile_abort_node_creation(xafile, &new_node->node.req); + return -ENOMEM; + } + + /* TODO: [REWORK] it is used tree type temporary */ + __nilfs_xafile_node_init(inode, NILFS_XATTR_TREE_XANODE_TYPE, + buf, BH_SIZE(NODE_BH(&new_node->node))); + + hdr = NILFS_XANODE_HDR(buf); + new_node->result.hdr = hdr; + new_node->result.key = NILFS_XANODE_FIRST_NOT_INDEX_KEY(hdr); + new_node->result.entry = NULL; + new_node->result.found = false; + + new_node->node.flags = NILFS_DIRTY_SHADOW_XANODE; + new_node->node.shadow_copy = buf; + + set_buffer_nilfs_volatile(NODE_BH(&new_node->node)); + + return 0; +} + +/* + * nilfs_xafile_prepare_node_for_change - prepare xanode for shadow changes + * @inode: inode pointer + * @data: internal xattr search structure + */ +static +int nilfs_xafile_prepare_node_for_change(struct inode *inode, + struct nilfs_xattr_search *data) +{ + int err; + char *buf; + size_t node_size; + union nilfs_xanode_header *hdr; + +#ifdef CONFIG_NILFS2_FS_DEBUG + BUG_ON(data->node.shadow_copy); +#endif + + node_size = BH_SIZE(NODE_BH(&data->node)); + + buf = kmalloc(node_size, GFP_NOFS); + if (!buf) { + err = -ENOMEM; + goto cleanup_after_failure; + } + + memcpy(buf, BH_DATA(NODE_BH(&data->node)), node_size); + data->node.flags = NILFS_SHADOW_XANODE; + data->node.shadow_copy = buf; + + hdr = NILFS_XANODE_HDR(buf); + + if (IS_SEARCH_KEY_EMPTY(data)) { + data->result.hdr = hdr; + data->result.key = NILFS_XANODE_FIRST_NOT_INDEX_KEY(hdr); + data->result.entry = NULL; + data->result.found = false; + } else if (IS_SEARCH_RESULT_EMPTY(data)) { + err = nilfs_xafile_find_entry(inode, data); + if (unlikely(err && err != -ENODATA)) + goto cleanup_after_failure; + } + + set_buffer_nilfs_volatile(NODE_BH(&data->node)); + + return 0; + +cleanup_after_failure: + nilfs_xattr_search_release(data); + return err; +} + +/* + * nilfs_xafile_commit_changed_node - commit xanode's shadow changes + * @inode: inode pointer + * @data: internal xattr search structure + */ +static +void nilfs_xafile_commit_changed_node(struct inode *inode, + struct nilfs_xattr_search *data) +{ + int err; + union nilfs_xanode_header *hdr; + struct buffer_head *bh; + size_t node_size; + __u64 node; + +#ifdef CONFIG_NILFS2_FS_DEBUG + BUG_ON(IS_SEARCH_RESULT_EMPTY(data)); + BUG_ON(!data->node.shadow_copy); + BUG_ON(!buffer_nilfs_volatile(NODE_BH(&data->node))); +#endif + + hdr = data->result.hdr; + bh = NODE_BH(&data->node); + clear_buffer_nilfs_checked(bh); + node_size = BH_SIZE(NODE_BH(&data->node)); + node = NODE_ID(&data->node); + + /* TODO: [REWORK] temporary only tree xanode is used */ + hdr->tree_hdr.checksum = nilfs_xafile_node_crc32(inode, (char *)hdr, + node_size, node); + + lock_buffer(bh); + memcpy(BH_DATA(bh), hdr, node_size); + unlock_buffer(bh); + + err = nilfs_xafile_check_node(inode, node, bh); + if (unlikely(err)) + printk(KERN_WARNING "NILFS: xanode is corrupted\n"); +#ifdef CONFIG_NILFS2_FS_DEBUG + BUG_ON(unlikely(err)); +#endif + + mark_buffer_dirty(bh); + clear_buffer_nilfs_volatile(bh); + nilfs_mark_inode_dirty(inode); + + kfree(data->node.shadow_copy); + data->node.shadow_copy = NULL; + data->node.flags = NILFS_RO_XANODE; +} + +/* + * nilfs_xafile_commit_new_node - commit new xanode's shadow changes + * @inode: inode pointer + * @data: internal xattr search structure + */ +static +void nilfs_xafile_commit_new_node(struct inode *inode, + struct nilfs_xattr_search *data) +{ + struct the_nilfs *nilfs = inode->i_sb->s_fs_info; + struct inode *xafile = nilfs->ns_xafile; + struct buffer_head *bh; + +#ifdef CONFIG_NILFS2_FS_DEBUG + BUG_ON(!data->node.shadow_copy); +#endif + + bh = NODE_BH(&data->node); + + nilfs_xafile_commit_changed_node(inode, data); + nilfs_xafile_commit_node_creation(xafile, &data->node.req); +} + +/* + * nilfs_xafile_abort_node_change - abort xanode's shadow changes + * @data: internal xattr search structure + */ +static inline +void nilfs_xafile_abort_node_change(struct nilfs_xattr_search *data) +{ + if (data && NODE_BH(&data->node)) + clear_buffer_nilfs_volatile(NODE_BH(&data->node)); + if (data) + nilfs_xattr_search_release(data); +} + +/* + * nilfs_xafile_abort_new_node - complete abort xanode creation + * @inode: inode pointer + * @data: internal xattr search structure + */ +static inline +void nilfs_xafile_abort_new_node(struct inode *inode, + struct nilfs_xattr_search *data) +{ + struct the_nilfs *nilfs = inode->i_sb->s_fs_info; + struct inode *xafile = nilfs->ns_xafile; + + nilfs_xafile_abort_node_creation(xafile, &data->node.req); + nilfs_xafile_abort_node_change(data); +} -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html