[sheepdog] [PATCH v2 10/12] sheep/nfs: add mkdir support
Liu Yuan
namei.unix at gmail.com
Wed Jan 29 08:35:56 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