[sheepdog] [PATCH 10/12] sheep/nfs: add mkdir support

Liu Yuan namei.unix at gmail.com
Tue Jan 28 21:19:10 CET 2014


Now we support 'mkdir' command and gain hierarchical structure support.

TODO:
 - make dentry operation operate on top of 'file' operation
 - add hash or btree based dentries management

Signed-off-by: Liu Yuan <namei.unix at gmail.com>
---
 sheep/nfs/fs.c  | 41 ++++++++++++++---------------
 sheep/nfs/fs.h  |  1 +
 sheep/nfs/nfs.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++----
 3 files changed, 98 insertions(+), 26 deletions(-)

diff --git a/sheep/nfs/fs.c b/sheep/nfs/fs.c
index a0a6691..cb1624d 100644
--- a/sheep/nfs/fs.c
+++ b/sheep/nfs/fs.c
@@ -140,27 +140,21 @@ static inline int inode_create(struct inode *inode, uint32_t vid,
 	return ret;
 }
 
-static int nlink_inc(uint64_t ino)
+static void dentry_add(struct inode *parent, struct dentry *dentry)
 {
-	struct inode *inode = fs_read_inode_hdr(ino);
-	int ret;
-
-	if (IS_ERR(inode))
-		return PTR_ERR(inode);
-
-	inode->nlink++;
+	uint8_t *tail = parent->data + parent->size;
 
-	ret = fs_write_inode_hdr(inode);
-	free(inode);
-	return ret;
+	parent->nlink++;
+	memcpy(tail, dentry, sizeof(*dentry));
+	parent->size += sizeof(*dentry);
 }
 
-static int dir_create(struct inode *inode, uint32_t vid, const char *name,
-		      uint64_t pino)
+int fs_create_dir(struct inode *inode, const char *name, struct inode *parent)
 {
+	uint64_t myino, pino = parent->ino;
+	uint32_t vid = oid_to_vid(pino);
 	struct inode_data *id = prepare_inode_data(inode, vid, name);
 	struct dentry *entry;
-	uint64_t myino;
 	int ret;
 
 	sys->cdrv->lock(vid);
@@ -185,17 +179,21 @@ static int dir_create(struct inode *inode, uint32_t vid, const char *name,
 	entry->name[0] = '.';
 	entry->name[1] = '.';
 
-	if (unlikely(myino == pino))
+	if (unlikely(inode == parent))
 		inode->nlink++; /* I'm root */
 	else {
-		ret = nlink_inc(pino);
-		if (ret != SD_RES_SUCCESS) {
-			sd_err("failed to inc nlink %"PRIx64, pino);
-			goto out;
-		}
+		struct dentry new = {
+			.ino = myino,
+			.nlen = strlen(name),
+		};
+		pstrcpy(new.name, NFS_MAXNAMLEN, name);
+		dentry_add(parent, &new);
 	}
 
 	ret = inode_do_create(id);
+	if (ret != SD_RES_SUCCESS)
+		goto out;
+	ret = fs_write_inode_full(parent);
 out:
 	sys->cdrv->unlock(vid);
 	finish_inode_data(id);
@@ -211,8 +209,9 @@ int fs_make_root(uint32_t vid)
 	root->uid = 0;
 	root->gid = 0;
 	root->atime = root->mtime = root->ctime = time(NULL);
+	root->ino = fs_root_ino(vid);
 
-	ret = dir_create(root, vid, "/", fs_root_ino(vid));
+	ret = fs_create_dir(root, "/", root);
 	free(root);
 	return ret;
 }
diff --git a/sheep/nfs/fs.h b/sheep/nfs/fs.h
index eaecb7c..0664d84 100644
--- a/sheep/nfs/fs.h
+++ b/sheep/nfs/fs.h
@@ -68,5 +68,6 @@ struct dentry *fs_lookup_dir(struct inode *inode, const char *name);
 int fs_create_file(uint64_t pino, struct inode *new, const char *name);
 int64_t fs_read(struct inode *inode, void *buffer, uint64_t count, uint64_t);
 int64_t fs_write(struct inode *inode, void *buffer, uint64_t count, uint64_t);
+int fs_create_dir(struct inode *inode, const char *name, struct inode *parent);
 
 #endif
diff --git a/sheep/nfs/nfs.c b/sheep/nfs/nfs.c
index b9b55f6..8d0e11f 100644
--- a/sheep/nfs/nfs.c
+++ b/sheep/nfs/nfs.c
@@ -388,7 +388,62 @@ out:
 
 void *nfs3_mkdir(struct svc_req *req, struct nfs_arg *argp)
 {
-	return NULL;
+	static MKDIR3res result;
+	static struct svc_fh file_fh;
+	MKDIR3args *arg = &argp->mkdir;
+	struct svc_fh *fh = get_svc_fh(argp);
+	struct post_op_attr *poa =
+		&result.MKDIR3res_u.resok.obj_attributes;
+	struct fattr3 *post = &poa->post_op_attr_u.attributes;
+	struct inode *new = xzalloc(sizeof(*new)), *parent;
+	char *name = arg->where.name;
+	int ret;
+
+	sd_debug("%"PRIx64" %s", fh->ino, name);
+
+	parent = fs_read_inode_full(fh->ino);
+	if (IS_ERR(parent)) {
+		switch (PTR_ERR(parent)) {
+		case SD_RES_NO_OBJ:
+			result.status = NFS3ERR_NOENT;
+			goto out;
+		default:
+			result.status = NFS3ERR_IO;
+			goto out;
+		}
+	}
+
+	if (!S_ISDIR(parent->mode)) {
+		result.status = NFS3ERR_NOTDIR;
+		goto out_free_parent;
+	}
+
+	new->mode = S_IFDIR | sd_def_dmode;
+	new->uid = 0;
+	new->gid = 0;
+	new->size = 0;
+	new->used = INODE_DATA_SIZE;
+	new->ctime = new->atime = new->mtime = time(NULL);
+
+	ret = fs_create_dir(new, name, parent);
+	if (ret != SD_RES_SUCCESS) {
+		result.status = NFS3ERR_IO;
+		goto out_free_parent;
+	}
+
+	file_fh.ino = new->ino;
+	result.status = NFS3_OK;
+	result.MKDIR3res_u.resok.obj.handle_follows = true;
+	set_svc_fh(&result.MKDIR3res_u.resok.obj.post_op_fh3_u.handle,
+		   &file_fh);
+	poa->attributes_follow = true;
+	update_post_attr(new, post);
+
+out_free_parent:
+	free(parent);
+out:
+	free(new);
+	return &result;
 }
 
 void *nfs3_symlink(struct svc_req *req, struct nfs_arg *argp)
@@ -398,17 +453,30 @@ void *nfs3_symlink(struct svc_req *req, struct nfs_arg *argp)
 
 void *nfs3_mknod(struct svc_req *req, struct nfs_arg *argp)
 {
-	return NULL;
+	static MKNOD3res result;
+
+	result.status = NFS3ERR_NOTSUPP;
+
+	return &result;
 }
 
+/* TODO: implement btree or hash based kv store to manage dentries */
 void *nfs3_remove(struct svc_req *req, struct nfs_arg *argp)
 {
-	return NULL;
+	static REMOVE3res result;
+
+	result.status = NFS3ERR_NOTSUPP;
+
+	return &result;
 }
 
 void *nfs3_rmdir(struct svc_req *req, struct nfs_arg *argp)
 {
-	return NULL;
+	static RMDIR3res result;
+
+	result.status = NFS3ERR_NOTSUPP;
+
+	return &result;
 }
 
 void *nfs3_rename(struct svc_req *req, struct nfs_arg *argp)
@@ -612,5 +680,9 @@ void *nfs3_pathconf(struct svc_req *req, struct nfs_arg *argp)
 
 void *nfs3_commit(struct svc_req *req, struct nfs_arg *argp)
 {
-	return NULL;
+	static COMMIT3res result;
+
+	result.status = NFS3ERR_NOTSUPP;
+
+	return &result;
 }
-- 
1.8.1.2




More information about the sheepdog mailing list