From 407fee0f026faf3296f08231e862799fbc2740c5 Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Thu, 26 May 2011 14:41:15 +0530 Subject: hw/9pfs: Update the fidp path before opendir We need to update the fidp path before opendir. Since we don't use the fid returned by mkdir, earlier code should not have much issue. We do a double v9fs_string_copy here. The later patch cleanup the entire function. Signed-off-by: Aneesh Kumar K.V --- hw/9pfs/virtio-9p.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c index 94b7090..71bc51b 100644 --- a/hw/9pfs/virtio-9p.c +++ b/hw/9pfs/virtio-9p.c @@ -2106,6 +2106,7 @@ static void v9fs_create(void *opaque) if (err < 0) { goto out; } + v9fs_string_copy(&fidp->path, &fullname); err = v9fs_co_opendir(pdu->s, fidp); if (err < 0) { goto out; -- cgit v1.1 From 25427ec1437b63e335a30293b58d47b601373223 Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Tue, 2 Aug 2011 11:36:24 +0530 Subject: hw/9pfs: Initialize rest of qid field to zero. Since qid is allocated out of stack we need to intialize the field to zero. Otherwise we will send wrong qid value to client. Signed-off-by: Aneesh Kumar K.V --- hw/9pfs/virtio-9p.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c index 71bc51b..91e0957 100644 --- a/hw/9pfs/virtio-9p.c +++ b/hw/9pfs/virtio-9p.c @@ -543,6 +543,7 @@ static void stat_to_qid(const struct stat *stbuf, V9fsQID *qidp) { size_t size; + memset(&qidp->path, 0, sizeof(qidp->path)); size = MIN(sizeof(stbuf->st_ino), sizeof(qidp->path)); memcpy(&qidp->path, &stbuf->st_ino, size); qidp->version = stbuf->st_mtime ^ (stbuf->st_size << 8); -- cgit v1.1 From 10e72295bd33af848e96c2ceaad86299ef244da4 Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Mon, 8 Aug 2011 12:19:51 +0530 Subject: hw/9pfs: Fix memleaks in some 9p operation Signed-off-by: Aneesh Kumar K.V --- hw/9pfs/virtio-9p.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c index 91e0957..1f186a2 100644 --- a/hw/9pfs/virtio-9p.c +++ b/hw/9pfs/virtio-9p.c @@ -2696,6 +2696,7 @@ out_nofid: err = offset; err += pdu_marshal(pdu, offset, "b", status); complete_pdu(s, pdu, err); + v9fs_string_free(&flock->client_id); g_free(flock); } @@ -2736,6 +2737,7 @@ out: put_fid(s, fidp); out_nofid: complete_pdu(s, pdu, err); + v9fs_string_free(&glock->client_id); g_free(glock); } -- cgit v1.1 From 89bf65938aa9f70e1c903160af509b693bd58c7b Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Mon, 23 May 2011 23:24:41 +0530 Subject: hw/9pfs: add 9P2000.L renameat operation rename - change name of file or directory size[4] Trenameat tag[2] olddirfid[4] oldname[s] newdirfid[4] newname[s] size[4] Rrenameat tag[2] older Trename have the below request format size[4] Trename tag[2] fid[4] newdirfid[4] name[s] The rename message is used to change the name of a file, possibly moving it to a new directory. The rename opreation is actually a directory opertation and should ideally have olddirfid, if not we cannot represent the fid on server with anything other than name. We will have to derive the old directory name from fid in the Trename request. Signed-off-by: Aneesh Kumar K.V --- hw/9pfs/virtio-9p.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++ hw/9pfs/virtio-9p.h | 2 ++ 2 files changed, 84 insertions(+) diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c index 1f186a2..0293fe4 100644 --- a/hw/9pfs/virtio-9p.c +++ b/hw/9pfs/virtio-9p.c @@ -2440,6 +2440,87 @@ out_nofid: v9fs_string_free(&name); } +static int v9fs_complete_renameat(V9fsState *s, int32_t olddirfid, + V9fsString *old_name, int32_t newdirfid, + V9fsString *new_name) +{ + int err = 0; + V9fsString old_full_name, new_full_name; + V9fsFidState *newdirfidp = NULL, *olddirfidp = NULL; + + olddirfidp = get_fid(s, olddirfid); + if (olddirfidp == NULL) { + err = -ENOENT; + goto out; + } + v9fs_string_init(&old_full_name); + v9fs_string_init(&new_full_name); + + v9fs_string_sprintf(&old_full_name, "%s/%s", + olddirfidp->path.data, old_name->data); + if (newdirfid != -1) { + newdirfidp = get_fid(s, newdirfid); + if (newdirfidp == NULL) { + err = -ENOENT; + goto out; + } + v9fs_string_sprintf(&new_full_name, "%s/%s", + newdirfidp->path.data, new_name->data); + } else { + v9fs_string_sprintf(&new_full_name, "%s/%s", + olddirfidp->path.data, new_name->data); + } + + if (strcmp(old_full_name.data, new_full_name.data) != 0) { + V9fsFidState *tfidp; + err = v9fs_co_rename(s, &old_full_name, &new_full_name); + if (err < 0) { + goto out; + } + /* + * Fixup fid's pointing to the old name to + * start pointing to the new name + */ + for (tfidp = s->fid_list; tfidp; tfidp = tfidp->next) { + if (v9fs_path_is_ancestor(&old_full_name, &tfidp->path)) { + /* replace the name */ + v9fs_fix_path(&tfidp->path, &new_full_name, old_full_name.size); + } + } + } +out: + if (olddirfidp) { + put_fid(s, olddirfidp); + } + if (newdirfidp) { + put_fid(s, newdirfidp); + } + v9fs_string_free(&old_full_name); + v9fs_string_free(&new_full_name); + return err; +} + +static void v9fs_renameat(void *opaque) +{ + ssize_t err = 0; + size_t offset = 7; + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; + int32_t olddirfid, newdirfid; + V9fsString old_name, new_name; + + pdu_unmarshal(pdu, offset, "dsds", &olddirfid, + &old_name, &newdirfid, &new_name); + + err = v9fs_complete_renameat(s, olddirfid, &old_name, newdirfid, &new_name); + if (!err) { + err = offset; + } + complete_pdu(s, pdu, err); + v9fs_string_free(&old_name); + v9fs_string_free(&new_name); +} + static void v9fs_wstat(void *opaque) { int32_t fid; @@ -2957,6 +3038,7 @@ static CoroutineEntry *pdu_co_handlers[] = { [P9_TRENAME] = v9fs_rename, [P9_TLOCK] = v9fs_lock, [P9_TGETLOCK] = v9fs_getlock, + [P9_TRENAMEAT] = v9fs_renameat, [P9_TREADLINK] = v9fs_readlink, [P9_TMKDIR] = v9fs_mkdir, [P9_TVERSION] = v9fs_version, diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h index 9d1b508..4950782 100644 --- a/hw/9pfs/virtio-9p.h +++ b/hw/9pfs/virtio-9p.h @@ -50,6 +50,8 @@ enum { P9_RLINK, P9_TMKDIR = 72, P9_RMKDIR, + P9_TRENAMEAT = 74, + P9_RRENAMEAT, P9_TVERSION = 100, P9_RVERSION, P9_TAUTH = 102, -- cgit v1.1 From 7834cf77be7e3e301177c6ab98a3d7f1bf73f28f Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Fri, 9 Sep 2011 15:07:01 +0530 Subject: hw/9pfs: add 9P2000.L unlinkat operation unlinkat - Remove a directory entry size[4] Tunlinkat tag[2] dirfid[4] name[s] flag[4] size[4] Runlinkat tag[2] older Tremove have the below request format size[4] Tremove tag[2] fid[4] The remove message is used to remove a directory entry either file or directory The remove opreation is actually a directory opertation and should ideally have dirfid, if not we cannot represent the fid on server with anything other than name. We will have to derive the directory name from fid in the Tremove request. NOTE: The operation doesn't clunk the unlink fid. Signed-off-by: Aneesh Kumar K.V --- hw/9pfs/virtio-9p.c | 40 ++++++++++++++++++++++++++++++++++++++++ hw/9pfs/virtio-9p.h | 2 ++ 2 files changed, 42 insertions(+) diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c index 0293fe4..d28edb7 100644 --- a/hw/9pfs/virtio-9p.c +++ b/hw/9pfs/virtio-9p.c @@ -2338,6 +2338,45 @@ out_nofid: complete_pdu(pdu->s, pdu, err); } +static void v9fs_unlinkat(void *opaque) +{ + int err = 0; + V9fsString name; + int32_t dfid, flags; + size_t offset = 7; + V9fsFidState *dfidp; + V9fsPDU *pdu = opaque; + V9fsString full_name; + + pdu_unmarshal(pdu, offset, "dsd", &dfid, &name, &flags); + + dfidp = get_fid(pdu->s, dfid); + if (dfidp == NULL) { + err = -EINVAL; + goto out_nofid; + } + v9fs_string_init(&full_name); + v9fs_string_sprintf(&full_name, "%s/%s", dfidp->path.data, name.data); + /* + * IF the file is unlinked, we cannot reopen + * the file later. So don't reclaim fd + */ + err = v9fs_mark_fids_unreclaim(pdu->s, &full_name); + if (err < 0) { + goto out_err; + } + err = v9fs_co_remove(pdu->s, &full_name); + if (!err) { + err = offset; + } +out_err: + put_fid(pdu->s, dfidp); + v9fs_string_free(&full_name); +out_nofid: + complete_pdu(pdu->s, pdu, err); + v9fs_string_free(&name); +} + static int v9fs_complete_rename(V9fsState *s, V9fsFidState *fidp, int32_t newdirfid, V9fsString *name) { @@ -3040,6 +3079,7 @@ static CoroutineEntry *pdu_co_handlers[] = { [P9_TGETLOCK] = v9fs_getlock, [P9_TRENAMEAT] = v9fs_renameat, [P9_TREADLINK] = v9fs_readlink, + [P9_TUNLINKAT] = v9fs_unlinkat, [P9_TMKDIR] = v9fs_mkdir, [P9_TVERSION] = v9fs_version, [P9_TLOPEN] = v9fs_open, diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h index 4950782..17d44b4 100644 --- a/hw/9pfs/virtio-9p.h +++ b/hw/9pfs/virtio-9p.h @@ -52,6 +52,8 @@ enum { P9_RMKDIR, P9_TRENAMEAT = 74, P9_RRENAMEAT, + P9_TUNLINKAT = 76, + P9_RUNLINKAT, P9_TVERSION = 100, P9_RVERSION, P9_TAUTH = 102, -- cgit v1.1