[Sheepdog] [PATCH v2 08/15] sheepfs: implement 'sync' operation for volumes

Liu Yuan namei.unix at gmail.com
Mon May 14 11:47:33 CEST 2012


From: Liu Yuan <tailai.ly at taobao.com>

When we use page cache to cache vdi in sheepdog storage, we need sync operation
to flush dirty bits back into sheep storage. This is wired up to the 'writeback'
of the kernel's page cache.

Signed-off-by: Liu Yuan <tailai.ly at taobao.com>
---
 sheepfs/core.c    |   19 +++++++++++++++++--
 sheepfs/sheepfs.h |    1 +
 sheepfs/volume.c  |   34 ++++++++++++++++++++++++++++++++++
 3 files changed, 52 insertions(+), 2 deletions(-)

diff --git a/sheepfs/core.c b/sheepfs/core.c
index 0f4f451..bda043f 100644
--- a/sheepfs/core.c
+++ b/sheepfs/core.c
@@ -46,12 +46,14 @@ static struct sheepfs_file_operation {
 	int (*read)(const char *path, char *buf, size_t size, off_t);
 	int (*write)(const char *path, const char *buf, size_t size, off_t);
 	size_t (*get_size)(const char *path);
+	int (*sync)(const char *path);
 } sheepfs_file_ops[] = {
-	[OP_NULL        ] = { NULL, NULL, NULL },
+	[OP_NULL]         = { NULL, NULL, NULL },
 	[OP_CLUSTER_INFO] = { cluster_info_read, NULL, cluster_info_get_size },
 	[OP_VDI_LIST]     = { vdi_list_read, NULL, vdi_list_get_size },
 	[OP_VDI_MOUNT]    = { NULL, vdi_mount_write, NULL },
-	[OP_VOLUME]       = { volume_read, volume_write, volume_get_size },
+	[OP_VOLUME]       = { volume_read, volume_write, volume_get_size,
+			      volume_sync },
 };
 
 int sheepfs_set_op(const char *path, unsigned opcode)
@@ -170,12 +172,25 @@ static int sheepfs_truncate(const char *path, off_t size)
 	return ret;
 }
 
+static int sheepfs_fsync(const char *path, int datasync,
+			 struct fuse_file_info *fi)
+{
+	int ret = 0;
+	unsigned op = sheepfs_get_op(path);
+
+	if (sheepfs_file_ops[op].sync)
+		ret = sheepfs_file_ops[op].sync(path);
+
+	return ret;
+}
+
 struct fuse_operations sheepfs_ops =  {
 	.getattr  = sheepfs_getattr,
 	.readdir  = sheepfs_readdir,
 	.truncate = sheepfs_truncate,
 	.read     = sheepfs_read,
 	.write    = sheepfs_write,
+	.fsync    = sheepfs_fsync,
 };
 
 static int sheepfs_main_loop(char *mountpoint)
diff --git a/sheepfs/sheepfs.h b/sheepfs/sheepfs.h
index cfb1402..563d3c3 100644
--- a/sheepfs/sheepfs.h
+++ b/sheepfs/sheepfs.h
@@ -32,6 +32,7 @@ extern int volume_read(const char *path, char *buf, size_t size, off_t offset);
 extern int volume_write(const char *, const char *buf, size_t size, off_t);
 extern size_t volume_get_size(const char *);
 extern int volume_create_entry(const char *entry);
+extern int volume_sync(const char *path);
 
 /* cluster.c */
 extern int cluster_info_read(const char *path, char *buf, size_t size, off_t);
diff --git a/sheepfs/volume.c b/sheepfs/volume.c
index 438e9a2..c84b0a6 100644
--- a/sheepfs/volume.c
+++ b/sheepfs/volume.c
@@ -222,6 +222,40 @@ size_t volume_get_size(const char *path)
 	return size;
 }
 
+static int volume_do_sync(uint32_t vid)
+{
+	struct sd_obj_req hdr = { 0 };
+	struct sd_obj_rsp *rsp = (struct sd_obj_rsp *)&hdr;
+	int ret;
+	unsigned wlen = 0, rlen = 0;
+
+	hdr.opcode = SD_OP_FLUSH_VDI;
+	hdr.oid = vid_to_vdi_oid(vid);
+
+	ret = exec_req(sheep_fd, (struct sd_req *)&hdr, NULL, &wlen, &rlen);
+
+	if (ret || rsp->result != SD_RES_SUCCESS) {
+		syslog(LOG_ERR, "[%s] failed to flush vdi %"PRIx32"\n",
+			__func__, vid);
+		return -1;
+	}
+
+	return 0;
+}
+
+int volume_sync(const char *path)
+{
+	uint32_t vid;
+
+	if (shadow_file_getxattr(path, SH_VID_NAME, &vid, SH_VID_SIZE) < 0)
+		return -EIO;
+
+	if (volume_do_sync(vid) < 0)
+		return -EIO;
+
+	return 0;
+}
+
 static int init_vdi_info(const char *entry, uint32_t *vid, size_t *size)
 {
 	struct strbuf *buf;
-- 
1.7.8.2




More information about the sheepdog mailing list