[sheepdog] [PATCH v3 08/15] sheepfs: implement 'sync' operation for volumes
Liu Yuan
namei.unix at gmail.com
Mon May 21 17:25:52 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 67a95c9..6e2570c 100644
--- a/sheepfs/core.c
+++ b/sheepfs/core.c
@@ -45,12 +45,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)
@@ -169,12 +171,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 0bacb42..060a0f3 100644
--- a/sheepfs/volume.c
+++ b/sheepfs/volume.c
@@ -227,6 +227,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.10.2
More information about the sheepdog
mailing list