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