[RFC][STEP 1][PATCH v2 08/17] nilfs2: implement prepare-(commit|abort) pair of xanode change functionality

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Vyacheslav Dubeyko <slava@xxxxxxxxxxx>
Subject: [RFC][STEP 1][PATCH v2 08/17] 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 03641df..73904c1 100644
--- a/fs/nilfs2/xafile.c
+++ b/fs/nilfs2/xafile.c
@@ -1029,3 +1029,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-nilfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Filesystem Development]     [Linux BTRFS]     [Linux CIFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux SCSI]

  Powered by Linux