[sheepdog] [PATCH v3 08/12] sheep/nfs: support lookup/create/setattr nfs operation

Liu Yuan namei.unix at gmail.com
Wed Jan 29 09:26:22 CET 2014


Now we support 'touch' command.

Signed-off-by: Liu Yuan <namei.unix at gmail.com>
---
 sheep/nfs/fs.c  |  51 +++++++++++++++++++++
 sheep/nfs/fs.h  |   2 +
 sheep/nfs/nfs.c | 140 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 sheep/nfs/nfs.h |  26 +++--------
 sheep/nfs/xdr.c |  12 ++---
 5 files changed, 202 insertions(+), 29 deletions(-)

diff --git a/sheep/nfs/fs.c b/sheep/nfs/fs.c
index 23632dd..acf58f1 100644
--- a/sheep/nfs/fs.c
+++ b/sheep/nfs/fs.c
@@ -286,3 +286,54 @@ int fs_read_dir(struct inode *inode, uint64_t offset,
 	}
 	return ret;
 }
+
+static int dentry_compare(struct dentry *a, struct dentry *b)
+{
+	return strcmp(a->name, b->name);
+}
+
+struct dentry *fs_lookup_dir(struct inode *inode, const char *name)
+{
+	struct dentry *tmp, *base = (struct dentry *)inode->data;
+	struct dentry *key = xmalloc(sizeof(*key));
+	uint64_t dentry_count = inode->size / sizeof(struct dentry);
+
+	sd_debug("%"PRIx64", %s", inode->ino, name);
+
+	pstrcpy(key->name, NFS_MAXNAMLEN, name);
+
+	tmp = xlfind(key, base, dentry_count, dentry_compare);
+	if (tmp)
+		*key = *tmp;
+	else {
+		free(key);
+		key = (struct dentry *)-SD_RES_NOT_FOUND;
+	}
+
+	return key;
+}
+
+int fs_create_file(uint64_t pino, struct inode *new, const char *name)
+{
+	uint32_t vid = oid_to_vid(pino);
+	struct inode *inode;
+	struct dentry *dentry;
+	int ret;
+
+	ret = inode_create(new, vid, name);
+	if (ret != SD_RES_SUCCESS)
+		return ret;
+
+	inode = fs_read_inode_full(pino);
+	if (IS_ERR(inode))
+		return PTR_ERR(inode);
+
+	dentry = (struct dentry *)(inode->data + inode->size);
+	pstrcpy(dentry->name, NFS_MAXNAMLEN, name);
+	dentry->ino = new->ino;
+	inode->size += sizeof(*dentry);
+
+	ret = fs_write_inode_full(inode);
+	free(inode);
+	return ret;
+}
diff --git a/sheep/nfs/fs.h b/sheep/nfs/fs.h
index 50c7052..5d6b308 100644
--- a/sheep/nfs/fs.h
+++ b/sheep/nfs/fs.h
@@ -64,5 +64,7 @@ int fs_write_inode_full(struct inode *inode);
 int fs_read_dir(struct inode *inode, uint64_t offset,
 		int (*dentry_reader)(struct inode *, struct dentry *, void *),
 		void *data);
+struct dentry *fs_lookup_dir(struct inode *inode, const char *name);
+int fs_create_file(uint64_t pino, struct inode *new, const char *name);
 
 #endif
diff --git a/sheep/nfs/nfs.c b/sheep/nfs/nfs.c
index f992434..16dcfe8 100644
--- a/sheep/nfs/nfs.c
+++ b/sheep/nfs/nfs.c
@@ -41,7 +41,7 @@
 #define RPCSVC_MAXPAYLOAD_TCP	RPCSVC_MAXPAYLOAD
 #define RPCSVC_MAXPAYLOAD_UDP	(32*1024u)
 
-static struct svc_fh *get_svc_fh(struct nfs_arg *argp)
+static inline struct svc_fh *get_svc_fh(struct nfs_arg *argp)
 {
 	struct nfs_fh3 *nfh = (struct nfs_fh3 *)argp;
 
@@ -51,6 +51,12 @@ static struct svc_fh *get_svc_fh(struct nfs_arg *argp)
 	return (struct svc_fh *)(nfh->data.data_val);
 }
 
+static inline void set_svc_fh(struct nfs_fh3 *nfh, struct svc_fh *sfh)
+{
+	nfh->data.data_len = sizeof(struct svc_fh);
+	nfh->data.data_val = (char *)sfh;
+}
+
 static void update_post_attr(struct inode *inode, fattr3 *post)
 {
 	post->type = S_ISDIR(inode->mode) ? NF3DIR : NF3REG;
@@ -101,14 +107,102 @@ out:
 	return &result;
 }
 
+/* FIXME: Add nanotime support */
 void *nfs3_setattr(struct svc_req *req, struct nfs_arg *argp)
 {
-	return NULL;
+	static SETATTR3res result;
+	SETATTR3args *arg = &argp->setattr;
+	struct svc_fh *fh = get_svc_fh(argp);
+	struct sattr3 *sattr = &arg->new_attributes;
+	struct post_op_attr *poa = &result.SETATTR3res_u.resok.obj_wcc.after;
+	struct fattr3 *post = &poa->post_op_attr_u.attributes;
+	struct inode *inode;
+	int ret;
+
+	sd_debug("%"PRIx64, fh->ino);
+
+	inode = fs_read_inode_hdr(fh->ino);
+	if (IS_ERR(inode)) {
+		switch (PTR_ERR(inode)) {
+		case SD_RES_NO_OBJ:
+			result.status = NFS3ERR_NOENT;
+			goto out;
+		default:
+			result.status = NFS3ERR_IO;
+			goto out;
+		}
+	}
+
+	if (sattr->mode.set_it)
+		inode->mode = sattr->mode.mode;
+	if (sattr->uid.set_it)
+		inode->uid = sattr->uid.uid;
+	if (sattr->gid.set_it)
+		inode->gid = sattr->gid.gid;
+	if (sattr->size.set_it)
+		inode->size = sattr->size.size;
+
+	ret = fs_write_inode_hdr(inode);
+	if (ret != SD_RES_SUCCESS)
+		result.status = NFS3ERR_IO;
+	else
+		result.status = NFS3_OK;
+
+	poa->attributes_follow = true;
+	update_post_attr(inode, post);
+	free(inode);
+out:
+	return &result;
 }
 
 void *nfs3_lookup(struct svc_req *req, struct nfs_arg *argp)
 {
-	return NULL;
+	static LOOKUP3res result;
+	static struct svc_fh den_fh;
+	LOOKUP3args *arg = &argp->lookup;
+	struct svc_fh *fh = get_svc_fh(argp);
+	struct inode *inode;
+	struct dentry *dentry;
+	char *name = arg->what.name;
+
+	sd_debug("%"PRIx64" %s", fh->ino, name);
+
+	inode = fs_read_inode_full(fh->ino);
+	if (IS_ERR(inode)) {
+		switch (PTR_ERR(inode)) {
+		case SD_RES_NO_OBJ:
+			result.status = NFS3ERR_NOENT;
+			goto out;
+		default:
+			result.status = NFS3ERR_IO;
+			goto out;
+		}
+	}
+
+	if (!S_ISDIR(inode->mode)) {
+		result.status = NFS3ERR_NOTDIR;
+		goto out_free;
+	}
+
+	dentry = fs_lookup_dir(inode, name);
+	if (IS_ERR(dentry)) {
+		switch (PTR_ERR(dentry)) {
+		case SD_RES_NOT_FOUND:
+			result.status = NFS3ERR_NOENT;
+			goto out_free;
+		default:
+			result.status = NFS3ERR_IO;
+			goto out_free;
+		}
+	}
+
+	result.status = NFS3_OK;
+	den_fh.ino = dentry->ino;
+	set_svc_fh(&result.LOOKUP3res_u.resok.object, &den_fh);
+out_free:
+	free(inode);
+out:
+	return &result;
 }
 
 /* FIXME: implement UNIX ACL */
@@ -166,9 +260,47 @@ void *nfs3_write(struct svc_req *req, struct nfs_arg *argp)
 	return NULL;
 }
 
+/* FIXME: support GUARDED and EXCLUSIVE */
 void *nfs3_create(struct svc_req *req, struct nfs_arg *argp)
 {
-	return NULL;
+	static CREATE3res result;
+	static struct svc_fh file_fh;
+	CREATE3args *arg = &argp->create;
+	struct svc_fh *fh = get_svc_fh(argp);
+	struct sattr3 *sattr = &arg->how.createhow3_u.obj_attributes;
+	struct post_op_attr *poa =
+		&result.CREATE3res_u.resok.obj_attributes;
+	struct fattr3 *post = &poa->post_op_attr_u.attributes;
+	struct inode *new = xzalloc(sizeof(*new));
+	char *name = arg->where.name;
+	int mode = arg->how.mode, ret;
+
+	sd_debug("%"PRIx64" %s, mode %d, size %"PRIu64, fh->ino, name, mode,
+		 sattr->size.size);
+
+	new->mode = S_IFREG | sd_def_fmode;
+	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_file(fh->ino, new, name);
+	if (ret != SD_RES_SUCCESS) {
+		result.status = NFS3ERR_IO;
+		goto out;
+	}
+
+	file_fh.ino = new->ino;
+
+	result.status = NFS3_OK;
+	result.CREATE3res_u.resok.obj.handle_follows = true;
+	set_svc_fh(&result.CREATE3res_u.resok.obj.post_op_fh3_u.handle,
+		   &file_fh);
+	poa->attributes_follow = true;
+	update_post_attr(new, post);
+out:
+	return &result;
 }
 
 void *nfs3_mkdir(struct svc_req *req, struct nfs_arg *argp)
diff --git a/sheep/nfs/nfs.h b/sheep/nfs/nfs.h
index 5d6a67d..f3f8288 100644
--- a/sheep/nfs/nfs.h
+++ b/sheep/nfs/nfs.h
@@ -18,7 +18,7 @@
 #define NFS_PORT 2049
 #define NFS_MAXDATA 8192
 #define NFS_MAXPATHLEN 1024
-#define NFS_MAXNAMLEN 255
+#define NFS_MAXNAMLEN 63
 #define NFS_FHSIZE 32
 #define NFS_COOKIESIZE 4
 #define NFS_FIFO_DEV -1
@@ -197,49 +197,37 @@ typedef enum time_how time_how;
 
 struct set_mode3 {
 	bool_t set_it;
-	union {
-		mode3 mode;
-	} set_mode3_u;
+	mode3 mode;
 };
 typedef struct set_mode3 set_mode3;
 
 struct set_uid3 {
 	bool_t set_it;
-	union {
-		uid3 uid;
-	} set_uid3_u;
+	uid3 uid;
 };
 typedef struct set_uid3 set_uid3;
 
 struct set_gid3 {
 	bool_t set_it;
-	union {
-		gid3 gid;
-	} set_gid3_u;
+	gid3 gid;
 };
 typedef struct set_gid3 set_gid3;
 
 struct set_size3 {
 	bool_t set_it;
-	union {
-		size3 size;
-	} set_size3_u;
+	size3 size;
 };
 typedef struct set_size3 set_size3;
 
 struct set_atime {
 	time_how set_it;
-	union {
-		nfstime3 atime;
-	} set_atime_u;
+	nfstime3 atime;
 };
 typedef struct set_atime set_atime;
 
 struct set_mtime {
 	time_how set_it;
-	union {
-		nfstime3 mtime;
-	} set_mtime_u;
+	nfstime3 mtime;
 };
 typedef struct set_mtime set_mtime;
 
diff --git a/sheep/nfs/xdr.c b/sheep/nfs/xdr.c
index 8a47daa..1391f2f 100644
--- a/sheep/nfs/xdr.c
+++ b/sheep/nfs/xdr.c
@@ -316,7 +316,7 @@ xdr_set_mode3(XDR *xdrs, set_mode3 *objp)
 		return FALSE;
 	switch (objp->set_it) {
 	case TRUE:
-		if (!xdr_mode3(xdrs, &objp->set_mode3_u.mode))
+		if (!xdr_mode3(xdrs, &objp->mode))
 			return FALSE;
 		break;
 	default:
@@ -332,7 +332,7 @@ xdr_set_uid3(XDR *xdrs, set_uid3 *objp)
 		return FALSE;
 	switch (objp->set_it) {
 	case TRUE:
-		if (!xdr_uid3(xdrs, &objp->set_uid3_u.uid))
+		if (!xdr_uid3(xdrs, &objp->uid))
 			return FALSE;
 		break;
 	default:
@@ -348,7 +348,7 @@ xdr_set_gid3(XDR *xdrs, set_gid3 *objp)
 		return FALSE;
 	switch (objp->set_it) {
 	case TRUE:
-		if (!xdr_gid3(xdrs, &objp->set_gid3_u.gid))
+		if (!xdr_gid3(xdrs, &objp->gid))
 			return FALSE;
 		break;
 	default:
@@ -364,7 +364,7 @@ xdr_set_size3(XDR *xdrs, set_size3 *objp)
 		return FALSE;
 	switch (objp->set_it) {
 	case TRUE:
-		if (!xdr_size3(xdrs, &objp->set_size3_u.size))
+		if (!xdr_size3(xdrs, &objp->size))
 			return FALSE;
 		break;
 	default:
@@ -380,7 +380,7 @@ xdr_set_atime(XDR *xdrs, set_atime *objp)
 		return FALSE;
 	switch (objp->set_it) {
 	case SET_TO_CLIENT_TIME:
-		if (!xdr_nfstime3(xdrs, &objp->set_atime_u.atime))
+		if (!xdr_nfstime3(xdrs, &objp->atime))
 			return FALSE;
 		break;
 	default:
@@ -396,7 +396,7 @@ xdr_set_mtime(XDR *xdrs, set_mtime *objp)
 		return FALSE;
 	switch (objp->set_it) {
 	case SET_TO_CLIENT_TIME:
-		if (!xdr_nfstime3(xdrs, &objp->set_mtime_u.mtime))
+		if (!xdr_nfstime3(xdrs, &objp->mtime))
 			return FALSE;
 		break;
 	default:
-- 
1.8.1.2




More information about the sheepdog mailing list