[sheepdog] [PATCH v2 08/12] sheep/nfs: support lookup/create/setattr nfs operation
Liu Yuan
namei.unix at gmail.com
Wed Jan 29 08:35:54 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