NFSv3 mkdir.
authorMichael Vrable <mvrable@cs.ucsd.edu>
Fri, 11 Sep 2009 21:36:50 +0000 (14:36 -0700)
committerMichael Vrable <mvrable@turin.ucsd.edu>
Fri, 11 Sep 2009 21:36:50 +0000 (14:36 -0700)
nfs3/nfs3.c

index 7fdd521..1b83181 100644 (file)
@@ -49,6 +49,55 @@ int64_t decode_nfstime3(nfstime3 *time)
     return result;
 }
 
+void set_attributes(BlueSkyInode *inode, sattr3 *attributes)
+{
+    int64_t now = bluesky_get_current_time();
+
+    if (attributes->mode.set) {
+        inode->mode = attributes->mode.set_uint32_u.val;
+    }
+
+    if (attributes->uid.set) {
+        inode->uid = attributes->uid.set_uint32_u.val;
+    }
+
+    if (attributes->gid.set) {
+        inode->gid = attributes->gid.set_uint32_u.val;
+    }
+
+    if (attributes->size.set) {
+        if (inode->type == BLUESKY_REGULAR) {
+            bluesky_file_truncate(inode, attributes->size.set_uint64_u.val);
+            inode->mtime = now;
+        }
+    }
+
+    switch (attributes->atime.set) {
+    case DONT_CHANGE:
+        break;
+    case SET_TO_SERVER_TIME:
+        inode->atime = now;
+        break;
+    case SET_TO_CLIENT_TIME:
+        inode->atime = decode_nfstime3(&attributes->atime.set_time_u.time);
+        break;
+    }
+
+    switch (attributes->mtime.set) {
+    case DONT_CHANGE:
+        break;
+    case SET_TO_SERVER_TIME:
+        inode->mtime = now;
+        break;
+    case SET_TO_CLIENT_TIME:
+        inode->mtime = decode_nfstime3(&attributes->mtime.set_time_u.time);
+        break;
+    }
+
+    inode->ctime = now;
+    inode->change_count++;
+}
+
 /* Copy inode attributes into NFS response.  The BlueSkyInode should be locked
  * by the caller. */
 void encode_fattr3(struct fattr3 *result, BlueSkyInode *inode)
@@ -126,50 +175,7 @@ nfsproc3_setattr_3_svc(setattr3args *argp, struct svc_req *rqstp)
         }
     }
 
-    if (argp->new_attributes.mode.set) {
-        inode->mode = argp->new_attributes.mode.set_uint32_u.val;
-    }
-
-    if (argp->new_attributes.uid.set) {
-        inode->uid = argp->new_attributes.uid.set_uint32_u.val;
-    }
-
-    if (argp->new_attributes.gid.set) {
-        inode->gid = argp->new_attributes.gid.set_uint32_u.val;
-    }
-
-    int64_t now = bluesky_get_current_time();
-
-    if (argp->new_attributes.size.set) {
-        bluesky_file_truncate(inode,
-                              argp->new_attributes.size.set_uint64_u.val);
-        inode->mtime = now;
-    }
-
-    switch (argp->new_attributes.atime.set) {
-    case DONT_CHANGE:
-        break;
-    case SET_TO_SERVER_TIME:
-        inode->atime = now;
-        break;
-    case SET_TO_CLIENT_TIME:
-        inode->atime = decode_nfstime3(&argp->new_attributes.atime.set_time_u.time);
-        break;
-    }
-
-    switch (argp->new_attributes.mtime.set) {
-    case DONT_CHANGE:
-        break;
-    case SET_TO_SERVER_TIME:
-        inode->mtime = now;
-        break;
-    case SET_TO_CLIENT_TIME:
-        inode->mtime = decode_nfstime3(&argp->new_attributes.mtime.set_time_u.time);
-        break;
-    }
-
-    inode->ctime = now;
-    inode->change_count++;
+    set_attributes(inode, &argp->new_attributes);
 
     result.wccstat3_u.wcc.after.present = TRUE;
     encode_fattr3(&result.wccstat3_u.wcc.after.post_op_attr_u.attributes,
@@ -378,6 +384,9 @@ nfsproc3_create_3_svc(create3args *argp, struct svc_req *rqstp)
     bluesky_insert_inode(fs, file);
     bluesky_directory_insert(dir, argp->where.name, file->inum);
 
+    dir->mtime = dir->ctime = bluesky_get_current_time();
+    dir->change_count++;
+
     wcc.after.present = TRUE;
     encode_fattr3(&wcc.after.post_op_attr_u.attributes, dir);
     result.diropres3_u.resok.obj_attributes.present = TRUE;
@@ -397,8 +406,59 @@ diropres3 *
 nfsproc3_mkdir_3_svc(mkdir3args *argp, struct svc_req *rqstp)
 {
     static diropres3 result;
+    struct wcc_data wcc;
+    memset(&wcc, 0, sizeof(wcc));
 
-    result.status = NFS3ERR_NOTSUPP;
+    BlueSkyInode *dir = lookup_fh(&argp->where.dir);
+    if (dir == NULL) {
+        result.status = NFS3ERR_STALE;
+        result.diropres3_u.resfail = wcc;
+        return &result;
+    }
+
+    encode_pre_wcc(&wcc, dir);
+    if (dir->type != BLUESKY_DIRECTORY) {
+        result.status = NFS3ERR_NOTDIR;
+        result.diropres3_u.resfail = wcc;
+        return &result;
+    }
+
+    if (!validate_filename(argp->where.name)
+        || strcmp(argp->where.name, ".") == 0
+        || strcmp(argp->where.name, "..") == 0)
+    {
+        result.status = NFS3ERR_EXIST;
+        result.diropres3_u.resfail = wcc;
+        return &result;
+    }
+
+    BlueSkyInode *file;
+    file = bluesky_new_inode(bluesky_fs_alloc_inode(fs), fs, BLUESKY_DIRECTORY);
+    file->nlink = 1;
+    file->mode = 0755;
+    int64_t time = bluesky_get_current_time();
+    file->mtime = time;
+    file->ctime = time;
+    file->atime = time;
+    file->ntime = time;
+    bluesky_insert_inode(fs, file);
+    bluesky_directory_insert(dir, argp->where.name, file->inum);
+    set_attributes(file, &argp->attributes);
+
+    dir->mtime = dir->ctime = bluesky_get_current_time();
+    dir->change_count++;
+
+    wcc.after.present = TRUE;
+    encode_fattr3(&wcc.after.post_op_attr_u.attributes, dir);
+    result.diropres3_u.resok.obj_attributes.present = TRUE;
+    encode_fattr3(&result.diropres3_u.resok.obj_attributes.post_op_attr_u.attributes, file);
+    result.diropres3_u.resok.dir_wcc = wcc;
+
+    static uint64_t fh_bytes;
+    fh_bytes = GUINT64_TO_BE(file->inum);
+    result.diropres3_u.resok.obj.present = TRUE;
+    result.diropres3_u.resok.obj.post_op_fh3_u.handle.data.data_len = 8;
+    result.diropres3_u.resok.obj.post_op_fh3_u.handle.data.data_val = (char *)&fh_bytes;
 
     return &result;
 }