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.u...@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

-- 
sheepdog mailing list
sheepdog@lists.wpkg.org
http://lists.wpkg.org/mailman/listinfo/sheepdog

Reply via email to