[virtio-9p] This patch implements TLCREATE for 9p2000.L protocol.
authorVenkateswararao Jujjuri (JV) <jvrao@linux.vnet.ibm.com>
Fri, 18 Jun 2010 01:27:24 +0000 (18:27 -0700)
committerAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Wed, 8 Sep 2010 17:26:40 +0000 (22:56 +0530)
SYNOPSIS

    size[4] Tlcreate tag[2] fid[4] name[s] flags[4] mode[4] gid[4]

    size[4] Rlcreate tag[2] qid[13] iounit[4]

DESCRIPTION

The Tlreate request asks the file server to create a new regular file with the
name supplied, in the directory (dir) represented by fid.
The mode argument specifies the permissions to use. New file is created with
the uid if the fid and with supplied gid.

The flags argument represent Linux access mode flags with which the caller
is requesting to open the file with. Protocol allows all the Linux access
modes but it is upto the server to allow/disallow any of these acess modes.
If the server doesn't support any of the access mode, it is expected to
return error.

To start with we will not restricit/limit any Linux flags on this server.
If needed, We can start restricting as we move forward with various use cases.

Signed-off-by: Venkateswararao Jujjuri <jvrao@linux.vnet.ibm.com>
hw/virtio-9p-debug.c
hw/virtio-9p.c
hw/virtio-9p.h

index 54179aa0900793b74fe87074318b8972da3f0e2c..a8abdd2d8243941fbe9dac820315f6c884ade989 100644 (file)
@@ -475,6 +475,19 @@ void pprint_pdu(V9fsPDU *pdu)
         fprintf(llogfile, "RSYMLINK: (");
         pprint_qid(pdu, 1, &offset, "qid");
         break;
+    case P9_TLCREATE:
+        fprintf(llogfile, "TLCREATE: (");
+        pprint_int32(pdu, 0, &offset, "dfid");
+        pprint_str(pdu, 0, &offset, ", name");
+        pprint_int32(pdu, 0, &offset, ", flags");
+        pprint_int32(pdu, 0, &offset, ", mode");
+        pprint_int32(pdu, 0, &offset, ", gid");
+        break;
+    case P9_RLCREATE:
+        fprintf(llogfile, "RLCREATE: (");
+        pprint_qid(pdu, 1, &offset, "qid");
+        pprint_int32(pdu, 1, &offset, ", iounit");
+        break;
     case P9_TREAD:
         fprintf(llogfile, "TREAD: (");
         pprint_int32(pdu, 0, &offset, "fid");
index 1036b49ee7801c73691e5a2337e3e42fb05c9e89..39f7071798794710c51671bb48474fc4b76ed8a5 100644 (file)
@@ -187,17 +187,18 @@ static int v9fs_do_fstat(V9fsState *s, int fd, struct stat *stbuf)
     return s->ops->fstat(&s->ctx, fd, stbuf);
 }
 
-static int v9fs_do_open2(V9fsState *s, V9fsCreateState *vs)
+static int v9fs_do_open2(V9fsState *s, char *fullname, uid_t uid, gid_t gid,
+        int flags, int mode)
 {
     FsCred cred;
-    int flags;
 
     cred_init(&cred);
-    cred.fc_uid = vs->fidp->uid;
-    cred.fc_mode = vs->perm & 0777;
-    flags = omode_to_uflags(vs->mode) | O_CREAT;
+    cred.fc_uid = uid;
+    cred.fc_gid = gid;
+    cred.fc_mode = mode & 07777;
+    flags = flags;
 
-    return s->ops->open2(&s->ctx, vs->fullname.data, flags, &cred);
+    return s->ops->open2(&s->ctx, fullname, flags, &cred);
 }
 
 static int v9fs_do_symlink(V9fsState *s, V9fsFidState *fidp,
@@ -1671,6 +1672,88 @@ out:
     qemu_free(vs);
 }
 
+static void v9fs_post_lcreate(V9fsState *s, V9fsLcreateState *vs, int err)
+{
+    if (err == 0) {
+        v9fs_string_copy(&vs->fidp->path, &vs->fullname);
+        stat_to_qid(&vs->stbuf, &vs->qid);
+        vs->offset += pdu_marshal(vs->pdu, vs->offset, "Qd", &vs->qid,
+                &vs->iounit);
+        err = vs->offset;
+    } else {
+        err = -errno;
+    }
+
+    complete_pdu(s, vs->pdu, err);
+    v9fs_string_free(&vs->name);
+    v9fs_string_free(&vs->fullname);
+    qemu_free(vs);
+}
+
+static void v9fs_lcreate_post_get_iounit(V9fsState *s, V9fsLcreateState *vs,
+        int err)
+{
+    if (err) {
+        err = -errno;
+        goto out;
+    }
+    err = v9fs_do_lstat(s, &vs->fullname, &vs->stbuf);
+
+out:
+    v9fs_post_lcreate(s, vs, err);
+}
+
+static void v9fs_lcreate_post_do_open2(V9fsState *s, V9fsLcreateState *vs,
+        int err)
+{
+    if (vs->fidp->fd == -1) {
+        err = -errno;
+        goto out;
+    }
+    vs->iounit =  get_iounit(s, &vs->fullname);
+    v9fs_lcreate_post_get_iounit(s, vs, err);
+    return;
+
+out:
+    v9fs_post_lcreate(s, vs, err);
+}
+
+static void v9fs_lcreate(V9fsState *s, V9fsPDU *pdu)
+{
+    int32_t dfid, flags, mode;
+    gid_t gid;
+    V9fsLcreateState *vs;
+    ssize_t err = 0;
+
+    vs = qemu_malloc(sizeof(*vs));
+    vs->pdu = pdu;
+    vs->offset = 7;
+
+    v9fs_string_init(&vs->fullname);
+
+    pdu_unmarshal(vs->pdu, vs->offset, "dsddd", &dfid, &vs->name, &flags,
+            &mode, &gid);
+
+    vs->fidp = lookup_fid(s, dfid);
+    if (vs->fidp == NULL) {
+        err = -ENOENT;
+        goto out;
+    }
+
+    v9fs_string_sprintf(&vs->fullname, "%s/%s", vs->fidp->path.data,
+             vs->name.data);
+
+    vs->fidp->fd = v9fs_do_open2(s, vs->fullname.data, vs->fidp->uid,
+            gid, flags, mode);
+    v9fs_lcreate_post_do_open2(s, vs, err);
+    return;
+
+out:
+    complete_pdu(s, vs->pdu, err);
+    v9fs_string_free(&vs->name);
+    qemu_free(vs);
+}
+
 static void v9fs_clunk(V9fsState *s, V9fsPDU *pdu)
 {
     int32_t fid;
@@ -2258,7 +2341,9 @@ static void v9fs_create_post_lstat(V9fsState *s, V9fsCreateState *vs, int err)
         err = v9fs_do_mknod(s, vs, S_IFSOCK | (vs->perm & 0777), 0);
         v9fs_post_create(s, vs, err);
     } else {
-        vs->fidp->fd = v9fs_do_open2(s, vs);
+        vs->fidp->fd = v9fs_do_open2(s, vs->fullname.data, vs->fidp->uid,
+                -1, omode_to_uflags(vs->mode)|O_CREAT, vs->perm);
+
         v9fs_create_post_open2(s, vs, err);
     }
 
@@ -2785,6 +2870,7 @@ static pdu_handler_t *pdu_handlers[] = {
     [P9_TLINK] = v9fs_link,
     [P9_TSYMLINK] = v9fs_symlink,
     [P9_TCREATE] = v9fs_create,
+    [P9_TLCREATE] = v9fs_lcreate,
     [P9_TWRITE] = v9fs_write,
     [P9_TWSTAT] = v9fs_wstat,
     [P9_TREMOVE] = v9fs_remove,
index 367186358df34bd49a55b7135ff962a8dc2d9df9..ad4d2162b1b042fdbff2cad6419b47f4c01fc146 100644 (file)
@@ -15,6 +15,8 @@
 enum {
     P9_TSTATFS = 8,
     P9_RSTATFS,
+    P9_TLCREATE = 14,
+    P9_RLCREATE,
     P9_TSYMLINK = 16,
     P9_RSYMLINK,
     P9_TGETATTR = 24,
@@ -185,6 +187,17 @@ typedef struct V9fsCreateState {
     int iounit;
 } V9fsCreateState;
 
+typedef struct V9fsLcreateState {
+    V9fsPDU *pdu;
+    size_t offset;
+    V9fsFidState *fidp;
+    V9fsQID qid;
+    int32_t iounit;
+    struct stat stbuf;
+    V9fsString name;
+    V9fsString fullname;
+} V9fsLcreateState;
+
 typedef struct V9fsStatState {
     V9fsPDU *pdu;
     size_t offset;