[Sheepdog] [PATCH RFC 02/10] sheepfs: core infrastructure

Liu Yuan namei.unix at gmail.com
Sat May 5 13:29:14 CEST 2012


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


Signed-off-by: Liu Yuan <tailai.ly at taobao.com>
---
 sheep/sheep.c           |    5 +
 sheep/sheepfs/core.c    |  228 +++++++++++++++++++++++++++++++++++++++++++++++
 sheep/sheepfs/sheepfs.h |   14 +++
 3 files changed, 247 insertions(+), 0 deletions(-)
 create mode 100644 sheep/sheepfs/core.c
 create mode 100644 sheep/sheepfs/sheepfs.h

diff --git a/sheep/sheep.c b/sheep/sheep.c
index 6645e8d..3f7ef3d 100644
--- a/sheep/sheep.c
+++ b/sheep/sheep.c
@@ -22,6 +22,7 @@
 
 #include "sheep_priv.h"
 #include "trace/trace.h"
+#include "sheepfs/sheepfs.h"
 
 #define EPOLL_SIZE 4096
 #define DEFAULT_OBJECT_DIR "/tmp"
@@ -232,6 +233,10 @@ int main(int argc, char **argv)
 	if (ret)
 		exit(1);
 
+	ret = sheepfs_init(dir);
+	if (ret)
+		exit(1);
+
 	ret = init_event(EPOLL_SIZE);
 	if (ret)
 		exit(1);
diff --git a/sheep/sheepfs/core.c b/sheep/sheepfs/core.c
new file mode 100644
index 0000000..880078c
--- /dev/null
+++ b/sheep/sheepfs/core.c
@@ -0,0 +1,228 @@
+#include <fuse.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <attr/xattr.h>
+#include <dirent.h>
+#include <pthread.h>
+
+#include "strbuf.h"
+#include "logger.h"
+#include "sheepfs.h"
+
+#define SH_OP_NAME   "user.sheepfs.opcode"
+#define SH_OP_SIZE   sizeof(uint32_t)
+
+char sheepfs_shadow[PATH_MAX];
+
+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);
+} sheepfs_file_ops[] = {
+	[OP_NULL] = { NULL, NULL, NULL },
+};
+
+int sheepfs_set_op(const char *path, unsigned opcode)
+{
+	if (shadow_file_setxattr(path, SH_OP_NAME, &opcode, SH_OP_SIZE) < 0) {
+		shadow_file_delete(path);
+		return -1;
+	}
+	return 0;
+}
+
+static unsigned sheepfs_get_op(const char *path)
+{
+	unsigned opcode = 0;
+
+	/* If fail, we simply return 0 to run NULL operation */
+	shadow_file_getxattr(path, SH_OP_NAME, &opcode, SH_OP_SIZE);
+
+	return opcode;
+}
+
+static size_t sheepfs_get_size(const char *path)
+{
+	unsigned op = sheepfs_get_op(path);
+
+	if (sheepfs_file_ops[op].get_size)
+		return sheepfs_file_ops[op].get_size(path);
+
+	return 0;
+}
+
+static int sheepfs_getattr(const char *path, struct stat *st)
+{
+	struct strbuf p = STRBUF_INIT;
+	int ret;
+
+	strbuf_addf(&p, "%s%s", sheepfs_shadow, path);
+	ret = stat(p.buf, st);
+	if (ret < 0) {
+		ret = -errno;
+		goto out;
+	}
+	if (S_ISREG(st->st_mode))
+		st->st_size = sheepfs_get_size(path);
+out:
+	strbuf_release(&p);
+	return ret;
+}
+
+static int sheepfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
+			   off_t offset, struct fuse_file_info *fi)
+{
+	DIR *dir;
+	struct dirent *dentry;
+	struct strbuf p = STRBUF_INIT;
+	int ret = 0;
+
+	strbuf_addf(&p, "%s%s", sheepfs_shadow, path);
+	dir = opendir(p.buf);
+	if (!dir) {
+		ret = -errno;
+		dprintf("%m\n");
+		goto out;
+	}
+
+	while ((dentry = readdir(dir))) {
+		if (filler(buf, dentry->d_name, NULL, 0) != 0) {
+			dprintf("out of memory\n");
+			ret = -ENOMEM;
+			goto out;
+		}
+	}
+
+out:
+	strbuf_release(&p);
+	return ret;
+}
+
+static int sheepfs_read(const char *path, char *buf, size_t size,
+			off_t offset, struct fuse_file_info *fi)
+{
+	int ret = 0;
+	unsigned op = sheepfs_get_op(path);
+
+	if (sheepfs_file_ops[op].read)
+		ret = sheepfs_file_ops[op].read(path, buf, size, offset);
+
+	return ret;
+}
+
+static int sheepfs_write(const char *path, const char *buf, size_t size,
+			 off_t offset, struct fuse_file_info *fi)
+{
+	int ret = 0;
+	unsigned op = sheepfs_get_op(path);
+
+	if (sheepfs_file_ops[op].write)
+		ret = sheepfs_file_ops[op].write(path, buf, size, offset);
+
+	return ret;
+}
+
+static int sheepfs_truncate(const char *path, off_t size)
+{
+	struct strbuf p = STRBUF_INIT;
+	int ret = 0, fd;
+
+	strbuf_addf(&p, "%s%s", sheepfs_shadow, path);
+	fd = open(p.buf, O_RDWR);
+	if (fd < 0)
+		ret = -ENOENT;
+	else
+		close(fd);
+
+	strbuf_release(&p);
+	return ret;
+}
+
+struct fuse_operations sheepfs_ops =  {
+	.getattr  = sheepfs_getattr,
+	.readdir  = sheepfs_readdir,
+	.truncate = sheepfs_truncate,
+	.read     = sheepfs_read,
+	.write    = sheepfs_write,
+};
+
+static void sheepfs_main_loop(char *root)
+{
+	struct fuse_args args = FUSE_ARGS_INIT(0, NULL);
+	int ret = -1;
+
+	dprintf("%s\n", root);
+	if (mkdir(root, 0755) < 0) {
+		if (errno != EEXIST) {
+			eprintf("%m\n");
+			return;
+		}
+	}
+
+	fuse_opt_add_arg(&args, "sheepfs"); /* placeholder for argv[0] */
+	fuse_opt_add_arg(&args, "-ofsname=sheepfs");
+	fuse_opt_add_arg(&args, root);
+	ret = fuse_main(args.argc, args.argv, &sheepfs_ops, NULL);
+	dprintf("sheepfs daemon exited %d\n", ret);
+	return;
+}
+
+static int create_sheepfs_layout(char *path)
+{
+	return 0;
+}
+
+int sheepfs_init(const char *dir)
+{
+	struct strbuf path = STRBUF_INIT;
+	pid_t pid;
+
+	strbuf_addf(&path, "%s/%s", dir, ".sheepfs");
+	memcpy(sheepfs_shadow, path.buf, path.len);
+	if (mkdir(sheepfs_shadow, 0755) < 0) {
+		if (errno != EEXIST) {
+			eprintf("%m\n");
+			return -1;
+		}
+	}
+
+	create_sheepfs_layout();
+	strbuf_reset(&path);
+	strbuf_addf(&path, "%s/%s", dir, "sheepfs");
+
+	pid = fork();
+	if (pid < 0) {
+		eprintf("failed to fork sheepfs daemon: %m");
+		return -1;
+	} else if (pid) {
+		strbuf_release(&path);
+		return 0;
+	} else /* child */ {
+		sheepfs_main_loop(path.buf);
+		exit(0);
+	}
+}
+
+struct strbuf *sheepfs_run_cmd(const char *command)
+{
+	struct strbuf *buf = xmalloc(sizeof(*buf));
+	FILE *f = popen(command, "re");
+
+	if (!f) {
+		dprintf("popen failed\n");
+		goto err;
+	}
+
+	strbuf_init(buf, 4096);
+
+	while (!feof(f))
+		strbuf_fread(buf, 4096, f);
+
+	pclose(f);
+	return buf;
+err:
+	strbuf_release(buf);
+	pclose(f);
+	free(buf);
+	return NULL;
+}
diff --git a/sheep/sheepfs/sheepfs.h b/sheep/sheepfs/sheepfs.h
new file mode 100644
index 0000000..8b27a51
--- /dev/null
+++ b/sheep/sheepfs/sheepfs.h
@@ -0,0 +1,14 @@
+#ifndef SHEEPFS_H
+#define SHEEPFS_H
+
+enum sheepfs_opcode {
+	OP_NULL = 0,
+};
+
+extern char sheepfs_shadow[];
+
+extern struct strbuf *sheepfs_run_cmd(const char *command);
+extern int sheepfs_init(const char *dir);
+extern int sheepfs_set_op(const char *path, unsigned opcode);
+
+#endif
-- 
1.7.8.2




More information about the sheepdog mailing list