qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 1/6] hw/9pfs: Add reference counting for fid
@ 2011-06-06 17:16 Aneesh Kumar K.V
  2011-06-06 17:16 ` [Qemu-devel] [PATCH 2/6] hw/9pfs: Don't free fid in clunk Aneesh Kumar K.V
                   ` (5 more replies)
  0 siblings, 6 replies; 14+ messages in thread
From: Aneesh Kumar K.V @ 2011-06-06 17:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, Aneesh Kumar K.V

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 hw/9pfs/virtio-9p.c |  205 +++++++++++++++++++++++++++++++++++----------------
 hw/9pfs/virtio-9p.h |    7 ++
 2 files changed, 147 insertions(+), 65 deletions(-)

diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
index e2aa863..03d8664 100644
--- a/hw/9pfs/virtio-9p.c
+++ b/hw/9pfs/virtio-9p.c
@@ -232,12 +232,13 @@ static size_t v9fs_string_size(V9fsString *str)
     return str->size;
 }
 
-static V9fsFidState *lookup_fid(V9fsState *s, int32_t fid)
+static V9fsFidState *get_fid(V9fsState *s, int32_t fid)
 {
     V9fsFidState *f;
 
     for (f = s->fid_list; f; f = f->next) {
         if (f->fid == fid) {
+            f->ref++;
             return f;
         }
     }
@@ -249,16 +250,16 @@ static V9fsFidState *alloc_fid(V9fsState *s, int32_t fid)
 {
     V9fsFidState *f;
 
-    f = lookup_fid(s, fid);
+    f = get_fid(s, fid);
     if (f) {
+        f->ref--;
         return NULL;
     }
 
     f = qemu_mallocz(sizeof(V9fsFidState));
-
     f->fid = fid;
     f->fid_type = P9_FID_NONE;
-
+    f->ref = 1;
     f->next = s->fid_list;
     s->fid_list = f;
 
@@ -1014,19 +1015,22 @@ static void v9fs_attach(void *opaque)
     fidp = alloc_fid(s, fid);
     if (fidp == NULL) {
         err = -EINVAL;
-        goto out;
+        goto out_nofid;
     }
     fidp->uid = n_uname;
     v9fs_string_sprintf(&fidp->path, "%s", "/");
     err = fid_to_qid(s, fidp, &qid);
     if (err < 0) {
         err = -EINVAL;
+        put_fid(fidp);
         free_fid(s, fid);
-        goto out;
+        goto out_nofid;
     }
     offset += pdu_marshal(pdu, offset, "Q", &qid);
     err = offset;
-out:
+    put_fid(fidp);
+
+out_nofid:
     complete_pdu(s, pdu, err);
     v9fs_string_free(&uname);
     v9fs_string_free(&aname);
@@ -1045,10 +1049,10 @@ static void v9fs_stat(void *opaque)
 
     pdu_unmarshal(pdu, offset, "d", &fid);
 
-    fidp = lookup_fid(s, fid);
+    fidp = get_fid(s, fid);
     if (fidp == NULL) {
         err = -ENOENT;
-        goto out;
+        goto out_nofid;
     }
     err = v9fs_co_lstat(s, &fidp->path, &stbuf);
     if (err < 0) {
@@ -1062,6 +1066,8 @@ static void v9fs_stat(void *opaque)
     err = offset;
     v9fs_stat_free(&v9stat);
 out:
+    put_fid(fidp);
+out_nofid:
     complete_pdu(s, pdu, err);
 }
 
@@ -1079,10 +1085,10 @@ static void v9fs_getattr(void *opaque)
 
     pdu_unmarshal(pdu, offset, "dq", &fid, &request_mask);
 
-    fidp = lookup_fid(s, fid);
+    fidp = get_fid(s, fid);
     if (fidp == NULL) {
         retval = -ENOENT;
-        goto out;
+        goto out_nofid;
     }
     /*
      * Currently we only support BASIC fields in stat, so there is no
@@ -1096,6 +1102,8 @@ static void v9fs_getattr(void *opaque)
     retval = offset;
     retval += pdu_marshal(pdu, offset, "A", &v9stat_dotl);
 out:
+    put_fid(fidp);
+out_nofid:
     complete_pdu(s, pdu, retval);
 }
 
@@ -1123,10 +1131,10 @@ static void v9fs_setattr(void *opaque)
 
     pdu_unmarshal(pdu, offset, "dI", &fid, &v9iattr);
 
-    fidp = lookup_fid(s, fid);
+    fidp = get_fid(s, fid);
     if (fidp == NULL) {
         err = -EINVAL;
-        goto out;
+        goto out_nofid;
     }
     if (v9iattr.valid & ATTR_MODE) {
         err = v9fs_co_chmod(s, &fidp->path, v9iattr.mode);
@@ -1188,6 +1196,8 @@ static void v9fs_setattr(void *opaque)
     }
     err = offset;
 out:
+    put_fid(fidp);
+out_nofid:
     complete_pdu(s, pdu, err);
 }
 
@@ -1214,7 +1224,7 @@ static void v9fs_walk(void *opaque)
     int32_t fid, newfid;
     V9fsString *wnames = NULL;
     V9fsFidState *fidp;
-    V9fsFidState *newfidp;
+    V9fsFidState *newfidp = NULL;;
     V9fsPDU *pdu = opaque;
     V9fsState *s = pdu->s;
 
@@ -1231,12 +1241,12 @@ static void v9fs_walk(void *opaque)
 
     } else if (nwnames > P9_MAXWELEM) {
         err = -EINVAL;
-        goto out;
+        goto out_nofid;
     }
-    fidp = lookup_fid(s, fid);
+    fidp = get_fid(s, fid);
     if (fidp == NULL) {
         err = -ENOENT;
-        goto out;
+        goto out_nofid;
     }
     if (fid == newfid) {
         BUG_ON(fidp->fid_type != P9_FID_NONE);
@@ -1269,7 +1279,9 @@ static void v9fs_walk(void *opaque)
             v9fs_string_copy(&newfidp->path, &path);
             err = v9fs_co_lstat(s, &newfidp->path, &stbuf);
             if (err < 0) {
+                put_fid(newfidp);
                 free_fid(s, newfidp->fid);
+                newfidp = NULL;
                 v9fs_string_free(&path);
                 goto out;
             }
@@ -1279,6 +1291,11 @@ static void v9fs_walk(void *opaque)
     }
     err = v9fs_walk_marshal(pdu, nwnames, qids);
 out:
+    put_fid(fidp);
+    if (newfidp) {
+        put_fid(newfidp);
+    }
+out_nofid:
     complete_pdu(s, pdu, err);
     if (nwnames && nwnames <= P9_MAXWELEM) {
         for (name_idx = 0; name_idx < nwnames; name_idx++) {
@@ -1327,10 +1344,10 @@ static void v9fs_open(void *opaque)
     } else {
         pdu_unmarshal(pdu, offset, "db", &fid, &mode);
     }
-    fidp = lookup_fid(s, fid);
+    fidp = get_fid(s, fid);
     if (fidp == NULL) {
         err = -ENOENT;
-        goto out;
+        goto out_nofid;
     }
     BUG_ON(fidp->fid_type != P9_FID_NONE);
 
@@ -1366,6 +1383,8 @@ static void v9fs_open(void *opaque)
         err = offset;
     }
 out:
+    put_fid(fidp);
+out_nofid:
     complete_pdu(s, pdu, err);
 }
 
@@ -1388,10 +1407,10 @@ static void v9fs_lcreate(void *opaque)
     pdu_unmarshal(pdu, offset, "dsddd", &dfid, &name, &flags,
                   &mode, &gid);
 
-    fidp = lookup_fid(pdu->s, dfid);
+    fidp = get_fid(pdu->s, dfid);
     if (fidp == NULL) {
         err = -ENOENT;
-        goto out;
+        goto out_nofid;
     }
     v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data);
 
@@ -1418,6 +1437,8 @@ static void v9fs_lcreate(void *opaque)
     offset += pdu_marshal(pdu, offset, "Qd", &qid, iounit);
     err = offset;
 out:
+    put_fid(fidp);
+out_nofid:
     complete_pdu(pdu->s, pdu, err);
     v9fs_string_free(&name);
     v9fs_string_free(&fullname);
@@ -1434,7 +1455,7 @@ static void v9fs_fsync(void *opaque)
     V9fsState *s = pdu->s;
 
     pdu_unmarshal(pdu, offset, "dd", &fid, &datasync);
-    fidp = lookup_fid(s, fid);
+    fidp = get_fid(s, fid);
     if (fidp == NULL) {
         err = -ENOENT;
         goto out;
@@ -1444,6 +1465,7 @@ static void v9fs_fsync(void *opaque)
         err = offset;
     }
 out:
+    put_fid(fidp);
     complete_pdu(s, pdu, err);
 }
 
@@ -1561,10 +1583,10 @@ static void v9fs_read(void *opaque)
 
     pdu_unmarshal(pdu, offset, "dqd", &fid, &off, &max_count);
 
-    fidp = lookup_fid(s, fid);
+    fidp = get_fid(s, fid);
     if (fidp == NULL) {
         err = -EINVAL;
-        goto out;
+        goto out_nofid;
     }
     if (fidp->fid_type == P9_FID_DIR) {
 
@@ -1616,6 +1638,8 @@ static void v9fs_read(void *opaque)
         err = -EINVAL;
     }
 out:
+    put_fid(fidp);
+out_nofid:
     complete_pdu(s, pdu, err);
 }
 
@@ -1700,8 +1724,12 @@ static void v9fs_readdir(void *opaque)
 
     pdu_unmarshal(pdu, offset, "dqd", &fid, &initial_offset, &max_count);
 
-    fidp = lookup_fid(s, fid);
-    if (fidp == NULL || !fidp->fs.dir) {
+    fidp = get_fid(s, fid);
+    if (fidp == NULL) {
+        retval = -EINVAL;
+        goto out_nofid;
+    }
+    if (!fidp->fs.dir) {
         retval = -EINVAL;
         goto out;
     }
@@ -1719,6 +1747,8 @@ static void v9fs_readdir(void *opaque)
     retval += pdu_marshal(pdu, offset, "d", count);
     retval += count;
 out:
+    put_fid(fidp);
+out_nofid:
     complete_pdu(s, pdu, retval);
 }
 
@@ -1784,10 +1814,10 @@ static void v9fs_write(void *opaque)
 
     pdu_unmarshal(pdu, offset, "dqdv", &fid, &off, &count, sg, &cnt);
 
-    fidp = lookup_fid(s, fid);
+    fidp = get_fid(s, fid);
     if (fidp == NULL) {
         err = -EINVAL;
-        goto out;
+        goto out_nofid;
     }
     if (fidp->fid_type == P9_FID_FILE) {
         if (fidp->fs.fd == -1) {
@@ -1827,6 +1857,8 @@ static void v9fs_write(void *opaque)
     offset += pdu_marshal(pdu, offset, "d", total);
     err = offset;
 out:
+    put_fid(fidp);
+out_nofid:
     complete_pdu(s, pdu, err);
 }
 
@@ -1851,10 +1883,10 @@ static void v9fs_create(void *opaque)
     pdu_unmarshal(pdu, offset, "dsdbs", &fid, &name,
                   &perm, &mode, &extension);
 
-    fidp = lookup_fid(pdu->s, fid);
+    fidp = get_fid(pdu->s, fid);
     if (fidp == NULL) {
         err = -EINVAL;
-        goto out;
+        goto out_nofid;
     }
 
     v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data);
@@ -1884,15 +1916,17 @@ static void v9fs_create(void *opaque)
         }
     } else if (perm & P9_STAT_MODE_LINK) {
         int32_t nfid = atoi(extension.data);
-        V9fsFidState *nfidp = lookup_fid(pdu->s, nfid);
+        V9fsFidState *nfidp = get_fid(pdu->s, nfid);
         if (nfidp == NULL) {
             err = -EINVAL;
             goto out;
         }
         err = v9fs_co_link(pdu->s, &nfidp->path, &fullname);
         if (err < 0) {
+            put_fid(nfidp);
             goto out;
         }
+        put_fid(nfidp);
     } else if (perm & P9_STAT_MODE_DEVICE) {
         char ctype;
         uint32_t major, minor;
@@ -1956,6 +1990,8 @@ static void v9fs_create(void *opaque)
     err = offset;
 
 out:
+    put_fid(fidp);
+out_nofid:
    complete_pdu(pdu->s, pdu, err);
    v9fs_string_free(&name);
    v9fs_string_free(&extension);
@@ -1980,10 +2016,10 @@ static void v9fs_symlink(void *opaque)
 
     pdu_unmarshal(pdu, offset, "dssd", &dfid, &name, &symname, &gid);
 
-    dfidp = lookup_fid(pdu->s, dfid);
+    dfidp = get_fid(pdu->s, dfid);
     if (dfidp == NULL) {
         err = -EINVAL;
-        goto out;
+        goto out_nofid;
     }
 
     v9fs_string_sprintf(&fullname, "%s/%s", dfidp->path.data, name.data);
@@ -1999,6 +2035,8 @@ static void v9fs_symlink(void *opaque)
     offset += pdu_marshal(pdu, offset, "Q", &qid);
     err = offset;
 out:
+    put_fid(dfidp);
+out_nofid:
     complete_pdu(pdu->s, pdu, err);
     v9fs_string_free(&name);
     v9fs_string_free(&symname);
@@ -2028,13 +2066,13 @@ static void v9fs_link(void *opaque)
 
     pdu_unmarshal(pdu, offset, "dds", &dfid, &oldfid, &name);
 
-    dfidp = lookup_fid(s, dfid);
+    dfidp = get_fid(s, dfid);
     if (dfidp == NULL) {
         err = -ENOENT;
-        goto out;
+        goto out_nofid;
     }
 
-    oldfidp = lookup_fid(s, oldfid);
+    oldfidp = get_fid(s, oldfid);
     if (oldfidp == NULL) {
         err = -ENOENT;
         goto out;
@@ -2048,6 +2086,8 @@ static void v9fs_link(void *opaque)
     v9fs_string_free(&fullname);
 
 out:
+    put_fid(dfidp);
+out_nofid:
     v9fs_string_free(&name);
     complete_pdu(s, pdu, err);
 }
@@ -2062,10 +2102,10 @@ static void v9fs_remove(void *opaque)
 
     pdu_unmarshal(pdu, offset, "d", &fid);
 
-    fidp = lookup_fid(pdu->s, fid);
+    fidp = get_fid(pdu->s, fid);
     if (fidp == NULL) {
         err = -EINVAL;
-        goto out;
+        goto out_nofid;
     }
     err = v9fs_co_remove(pdu->s, &fidp->path);
     if (!err) {
@@ -2073,8 +2113,9 @@ static void v9fs_remove(void *opaque)
     }
 
     /* For TREMOVE we need to clunk the fid even on failed remove */
+    put_fid(fidp);
     free_fid(pdu->s, fidp->fid);
-out:
+out_nofid:
     complete_pdu(pdu->s, pdu, err);
 }
 
@@ -2083,14 +2124,14 @@ static int v9fs_complete_rename(V9fsState *s, V9fsFidState *fidp,
 {
     char *end;
     int err = 0;
+    V9fsFidState *dirfidp = NULL;
     char *old_name, *new_name;
 
     if (newdirfid != -1) {
-        V9fsFidState *dirfidp;
-        dirfidp = lookup_fid(s, newdirfid);
+        dirfidp = get_fid(s, newdirfid);
         if (dirfidp == NULL) {
             err = -ENOENT;
-            goto out;
+            goto out_nofid;
         }
         BUG_ON(dirfidp->fid_type != P9_FID_NONE);
 
@@ -2143,6 +2184,10 @@ static int v9fs_complete_rename(V9fsState *s, V9fsFidState *fidp,
         v9fs_string_copy(&fidp->path, name);
     }
 out:
+    if (dirfidp) {
+        put_fid(dirfidp);
+    }
+out_nofid:
     return err;
 }
 
@@ -2159,10 +2204,10 @@ static void v9fs_rename(void *opaque)
 
     pdu_unmarshal(pdu, offset, "dds", &fid, &newdirfid, &name);
 
-    fidp = lookup_fid(s, fid);
+    fidp = get_fid(s, fid);
     if (fidp == NULL) {
         err = -ENOENT;
-        goto out;
+        goto out_nofid;
     }
     BUG_ON(fidp->fid_type != P9_FID_NONE);
 
@@ -2171,6 +2216,8 @@ static void v9fs_rename(void *opaque)
         err = offset;
     }
 out:
+    put_fid(fidp);
+out_nofid:
     complete_pdu(s, pdu, err);
     v9fs_string_free(&name);
 }
@@ -2189,10 +2236,10 @@ static void v9fs_wstat(void *opaque)
 
     pdu_unmarshal(pdu, offset, "dwS", &fid, &unused, &v9stat);
 
-    fidp = lookup_fid(s, fid);
+    fidp = get_fid(s, fid);
     if (fidp == NULL) {
         err = -EINVAL;
-        goto out;
+        goto out_nofid;
     }
     /* do we need to sync the file? */
     if (donttouch_stat(&v9stat)) {
@@ -2258,6 +2305,8 @@ static void v9fs_wstat(void *opaque)
     }
     err = offset;
 out:
+    put_fid(fidp);
+out_nofid:
     v9fs_stat_free(&v9stat);
     complete_pdu(s, pdu, err);
 }
@@ -2318,10 +2367,10 @@ static void v9fs_statfs(void *opaque)
     V9fsState *s = pdu->s;
 
     pdu_unmarshal(pdu, offset, "d", &fid);
-    fidp = lookup_fid(s, fid);
+    fidp = get_fid(s, fid);
     if (fidp == NULL) {
         retval = -ENOENT;
-        goto out;
+        goto out_nofid;
     }
     retval = v9fs_co_statfs(s, &fidp->path, &stbuf);
     if (retval < 0) {
@@ -2330,6 +2379,8 @@ static void v9fs_statfs(void *opaque)
     retval = offset;
     retval += v9fs_fill_statfs(s, pdu, &stbuf);
 out:
+    put_fid(fidp);
+out_nofid:
     complete_pdu(s, pdu, retval);
     return;
 }
@@ -2355,10 +2406,10 @@ static void v9fs_mknod(void *opaque)
     pdu_unmarshal(pdu, offset, "dsdddd", &fid, &name, &mode,
                   &major, &minor, &gid);
 
-    fidp = lookup_fid(s, fid);
+    fidp = get_fid(s, fid);
     if (fidp == NULL) {
         err = -ENOENT;
-        goto out;
+        goto out_nofid;
     }
     v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data);
     err = v9fs_co_mknod(s, &fullname, fidp->uid, gid,
@@ -2374,6 +2425,8 @@ static void v9fs_mknod(void *opaque)
     err = offset;
     err += pdu_marshal(pdu, offset, "Q", &qid);
 out:
+    put_fid(fidp);
+out_nofid:
     complete_pdu(s, pdu, err);
     v9fs_string_free(&fullname);
     v9fs_string_free(&name);
@@ -2407,12 +2460,12 @@ static void v9fs_lock(void *opaque)
     /* We support only block flag now (that too ignored currently) */
     if (flock->flags & ~P9_LOCK_FLAGS_BLOCK) {
         err = -EINVAL;
-        goto out;
+        goto out_nofid;
     }
-    fidp = lookup_fid(s, fid);
+    fidp = get_fid(s, fid);
     if (fidp == NULL) {
         err = -ENOENT;
-        goto out;
+        goto out_nofid;
     }
     err = v9fs_co_fstat(s, fidp->fs.fd, &stbuf);
     if (err < 0) {
@@ -2420,6 +2473,8 @@ static void v9fs_lock(void *opaque)
     }
     status = P9_LOCK_SUCCESS;
 out:
+    put_fid(fidp);
+out_nofid:
     err = offset;
     err += pdu_marshal(pdu, offset, "b", status);
     complete_pdu(s, pdu, err);
@@ -2445,10 +2500,10 @@ static void v9fs_getlock(void *opaque)
                   &glock->start, &glock->length, &glock->proc_id,
                   &glock->client_id);
 
-    fidp = lookup_fid(s, fid);
+    fidp = get_fid(s, fid);
     if (fidp == NULL) {
         err = -ENOENT;
-        goto out;
+        goto out_nofid;
     }
     err = v9fs_co_fstat(s, fidp->fs.fd, &stbuf);
     if (err < 0) {
@@ -2460,6 +2515,8 @@ static void v9fs_getlock(void *opaque)
                           &glock->client_id);
     err = offset;
 out:
+    put_fid(fidp);
+out_nofid:
     complete_pdu(s, pdu, err);
     qemu_free(glock);
 }
@@ -2480,10 +2537,10 @@ static void v9fs_mkdir(void *opaque)
     v9fs_string_init(&fullname);
     pdu_unmarshal(pdu, offset, "dsdd", &fid, &name, &mode, &gid);
 
-    fidp = lookup_fid(pdu->s, fid);
+    fidp = get_fid(pdu->s, fid);
     if (fidp == NULL) {
         err = -ENOENT;
-        goto out;
+        goto out_nofid;
     }
     v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data);
     err = v9fs_co_mkdir(pdu->s, fullname.data, mode, fidp->uid, gid);
@@ -2498,6 +2555,8 @@ static void v9fs_mkdir(void *opaque)
     offset += pdu_marshal(pdu, offset, "Q", &qid);
     err = offset;
 out:
+    put_fid(fidp);
+out_nofid:
     complete_pdu(pdu->s, pdu, err);
     v9fs_string_free(&fullname);
     v9fs_string_free(&name);
@@ -2511,15 +2570,15 @@ static void v9fs_xattrwalk(void *opaque)
     size_t offset = 7;
     int32_t fid, newfid;
     V9fsFidState *file_fidp;
-    V9fsFidState *xattr_fidp;
+    V9fsFidState *xattr_fidp = NULL;
     V9fsPDU *pdu = opaque;
     V9fsState *s = pdu->s;
 
     pdu_unmarshal(pdu, offset, "dds", &fid, &newfid, &name);
-    file_fidp = lookup_fid(s, fid);
+    file_fidp = get_fid(s, fid);
     if (file_fidp == NULL) {
         err = -ENOENT;
-        goto out;
+        goto out_nofid;
     }
     xattr_fidp = alloc_fid(s, newfid);
     if (xattr_fidp == NULL) {
@@ -2534,7 +2593,9 @@ static void v9fs_xattrwalk(void *opaque)
         size = v9fs_co_llistxattr(s, &xattr_fidp->path, NULL, 0);
         if (size < 0) {
             err = size;
+            put_fid(xattr_fidp);
             free_fid(s, xattr_fidp->fid);
+            xattr_fidp = NULL;
             goto out;
         }
         /*
@@ -2549,7 +2610,9 @@ static void v9fs_xattrwalk(void *opaque)
                                      xattr_fidp->fs.xattr.value,
                                      xattr_fidp->fs.xattr.len);
             if (err < 0) {
+                put_fid(xattr_fidp);
                 free_fid(s, xattr_fidp->fid);
+                xattr_fidp = NULL;
                 goto out;
             }
         }
@@ -2564,7 +2627,9 @@ static void v9fs_xattrwalk(void *opaque)
                                  &name, NULL, 0);
         if (size < 0) {
             err = size;
+            put_fid(xattr_fidp);
             free_fid(s, xattr_fidp->fid);
+            xattr_fidp = NULL;
             goto out;
         }
         /*
@@ -2579,7 +2644,9 @@ static void v9fs_xattrwalk(void *opaque)
                                     &name, xattr_fidp->fs.xattr.value,
                                     xattr_fidp->fs.xattr.len);
             if (err < 0) {
+                put_fid(xattr_fidp);
                 free_fid(s, xattr_fidp->fid);
+                xattr_fidp = NULL;
                 goto out;
             }
         }
@@ -2587,6 +2654,11 @@ static void v9fs_xattrwalk(void *opaque)
         err = offset;
     }
 out:
+    put_fid(file_fidp);
+    if (xattr_fidp) {
+        put_fid(xattr_fidp);
+    }
+out_nofid:
     complete_pdu(s, pdu, err);
     v9fs_string_free(&name);
 }
@@ -2607,10 +2679,10 @@ static void v9fs_xattrcreate(void *opaque)
     pdu_unmarshal(pdu, offset, "dsqd",
                   &fid, &name, &size, &flags);
 
-    file_fidp = lookup_fid(s, fid);
+    file_fidp = get_fid(s, fid);
     if (file_fidp == NULL) {
         err = -EINVAL;
-        goto out;
+        goto out_nofid;
     }
     /* Make the file fid point to xattr */
     xattr_fidp = file_fidp;
@@ -2626,7 +2698,8 @@ static void v9fs_xattrcreate(void *opaque)
         xattr_fidp->fs.xattr.value = NULL;
     }
     err = offset;
-out:
+    put_fid(file_fidp);
+out_nofid:
     complete_pdu(s, pdu, err);
     v9fs_string_free(&name);
 }
@@ -2641,10 +2714,10 @@ static void v9fs_readlink(void *opaque)
     V9fsFidState *fidp;
 
     pdu_unmarshal(pdu, offset, "d", &fid);
-    fidp = lookup_fid(pdu->s, fid);
+    fidp = get_fid(pdu->s, fid);
     if (fidp == NULL) {
         err = -ENOENT;
-        goto out;
+        goto out_nofid;
     }
 
     v9fs_string_init(&target);
@@ -2656,6 +2729,8 @@ static void v9fs_readlink(void *opaque)
     err = offset;
     v9fs_string_free(&target);
 out:
+    put_fid(fidp);
+out_nofid:
     complete_pdu(pdu->s, pdu, err);
 }
 
diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h
index 1d8c1b1..ce93c20 100644
--- a/hw/9pfs/virtio-9p.h
+++ b/hw/9pfs/virtio-9p.h
@@ -203,6 +203,7 @@ struct V9fsFidState
 	V9fsXattr xattr;
     } fs;
     uid_t uid;
+    int ref;
     V9fsFidState *next;
 };
 
@@ -361,5 +362,11 @@ static inline size_t do_pdu_unpack(void *dst, struct iovec *sg, int sg_count,
     return pdu_packunpack(dst, sg, sg_count, offset, size, 0);
 }
 
+static inline void put_fid(V9fsFidState *fidp)
+{
+    BUG_ON(!fidp->ref);
+    fidp->ref--;
+}
+
 extern void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq);
 #endif
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Qemu-devel] [PATCH 2/6] hw/9pfs: Don't free fid in clunk
  2011-06-06 17:16 [Qemu-devel] [PATCH 1/6] hw/9pfs: Add reference counting for fid Aneesh Kumar K.V
@ 2011-06-06 17:16 ` Aneesh Kumar K.V
  2011-06-10  0:27   ` Venkateswararao Jujjuri
  2011-06-06 17:16 ` [Qemu-devel] [PATCH 3/6] hw/9pfs: Add file descriptor reclaim support Aneesh Kumar K.V
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 14+ messages in thread
From: Aneesh Kumar K.V @ 2011-06-06 17:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, Aneesh Kumar K.V

On interrupted syscall on client we can end up having fid
being acted upon by glib pool but still get a clunk request on that

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 hw/9pfs/virtio-9p.c |  139 +++++++++++++++++++++++++++-----------------------
 hw/9pfs/virtio-9p.h |    7 +--
 2 files changed, 76 insertions(+), 70 deletions(-)

diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
index 03d8664..f3127a5 100644
--- a/hw/9pfs/virtio-9p.c
+++ b/hw/9pfs/virtio-9p.c
@@ -237,12 +237,11 @@ static V9fsFidState *get_fid(V9fsState *s, int32_t fid)
     V9fsFidState *f;
 
     for (f = s->fid_list; f; f = f->next) {
-        if (f->fid == fid) {
+        if (f->fid == fid && !f->clunked) {
             f->ref++;
             return f;
         }
     }
-
     return NULL;
 }
 
@@ -250,12 +249,12 @@ static V9fsFidState *alloc_fid(V9fsState *s, int32_t fid)
 {
     V9fsFidState *f;
 
-    f = get_fid(s, fid);
-    if (f) {
-        f->ref--;
-        return NULL;
+    for (f = s->fid_list; f; f = f->next) {
+        /* If fid is already there return NULL */
+        if (f->fid == fid && !f->clunked) {
+            return NULL;
+        }
     }
-
     f = qemu_mallocz(sizeof(V9fsFidState));
     f->fid = fid;
     f->fid_type = P9_FID_NONE;
@@ -300,9 +299,33 @@ free_value:
     return retval;
 }
 
-static int free_fid(V9fsState *s, int32_t fid)
+static int release_fid(V9fsState *s, V9fsFidState *fidp)
 {
     int retval = 0;
+
+    if (fidp->fid_type == P9_FID_FILE) {
+        retval = v9fs_co_close(s, fidp);
+    } else if (fidp->fid_type == P9_FID_DIR) {
+        retval = v9fs_co_closedir(s, fidp);
+    } else if (fidp->fid_type == P9_FID_XATTR) {
+        retval = v9fs_xattr_fid_clunk(s, fidp);
+    }
+    v9fs_string_free(&fidp->path);
+    qemu_free(fidp);
+    return retval;
+}
+
+static void put_fid(V9fsState *s, V9fsFidState *fidp)
+{
+    BUG_ON(!fidp->ref);
+    fidp->ref--;
+    if (!fidp->ref && fidp->clunked) {
+        release_fid(s, fidp);
+    }
+}
+
+static int free_fid(V9fsState *s, int32_t fid)
+{
     V9fsFidState **fidpp, *fidp;
 
     for (fidpp = &s->fid_list; *fidpp; fidpp = &(*fidpp)->next) {
@@ -314,20 +337,10 @@ static int free_fid(V9fsState *s, int32_t fid)
     if (*fidpp == NULL) {
         return -ENOENT;
     }
-
     fidp = *fidpp;
     *fidpp = fidp->next;
-
-    if (fidp->fid_type == P9_FID_FILE) {
-        retval = v9fs_co_close(s, fidp);
-    } else if (fidp->fid_type == P9_FID_DIR) {
-        retval = v9fs_co_closedir(s, fidp);
-    } else if (fidp->fid_type == P9_FID_XATTR) {
-        retval = v9fs_xattr_fid_clunk(s, fidp);
-    }
-    v9fs_string_free(&fidp->path);
-    qemu_free(fidp);
-    return retval;
+    fidp->clunked = 1;
+    return 0;
 }
 
 #define P9_QID_TYPE_DIR         0x80
@@ -1022,14 +1035,13 @@ static void v9fs_attach(void *opaque)
     err = fid_to_qid(s, fidp, &qid);
     if (err < 0) {
         err = -EINVAL;
-        put_fid(fidp);
         free_fid(s, fid);
-        goto out_nofid;
+        goto out;
     }
     offset += pdu_marshal(pdu, offset, "Q", &qid);
     err = offset;
-    put_fid(fidp);
-
+out:
+    put_fid(s, fidp);
 out_nofid:
     complete_pdu(s, pdu, err);
     v9fs_string_free(&uname);
@@ -1066,7 +1078,7 @@ static void v9fs_stat(void *opaque)
     err = offset;
     v9fs_stat_free(&v9stat);
 out:
-    put_fid(fidp);
+    put_fid(s, fidp);
 out_nofid:
     complete_pdu(s, pdu, err);
 }
@@ -1102,7 +1114,7 @@ static void v9fs_getattr(void *opaque)
     retval = offset;
     retval += pdu_marshal(pdu, offset, "A", &v9stat_dotl);
 out:
-    put_fid(fidp);
+    put_fid(s, fidp);
 out_nofid:
     complete_pdu(s, pdu, retval);
 }
@@ -1196,7 +1208,7 @@ static void v9fs_setattr(void *opaque)
     }
     err = offset;
 out:
-    put_fid(fidp);
+    put_fid(s, fidp);
 out_nofid:
     complete_pdu(s, pdu, err);
 }
@@ -1279,9 +1291,7 @@ static void v9fs_walk(void *opaque)
             v9fs_string_copy(&newfidp->path, &path);
             err = v9fs_co_lstat(s, &newfidp->path, &stbuf);
             if (err < 0) {
-                put_fid(newfidp);
                 free_fid(s, newfidp->fid);
-                newfidp = NULL;
                 v9fs_string_free(&path);
                 goto out;
             }
@@ -1291,9 +1301,9 @@ static void v9fs_walk(void *opaque)
     }
     err = v9fs_walk_marshal(pdu, nwnames, qids);
 out:
-    put_fid(fidp);
+    put_fid(s, fidp);
     if (newfidp) {
-        put_fid(newfidp);
+        put_fid(s, newfidp);
     }
 out_nofid:
     complete_pdu(s, pdu, err);
@@ -1383,7 +1393,7 @@ static void v9fs_open(void *opaque)
         err = offset;
     }
 out:
-    put_fid(fidp);
+    put_fid(s, fidp);
 out_nofid:
     complete_pdu(s, pdu, err);
 }
@@ -1437,7 +1447,7 @@ static void v9fs_lcreate(void *opaque)
     offset += pdu_marshal(pdu, offset, "Qd", &qid, iounit);
     err = offset;
 out:
-    put_fid(fidp);
+    put_fid(pdu->s, fidp);
 out_nofid:
     complete_pdu(pdu->s, pdu, err);
     v9fs_string_free(&name);
@@ -1465,7 +1475,7 @@ static void v9fs_fsync(void *opaque)
         err = offset;
     }
 out:
-    put_fid(fidp);
+    put_fid(s, fidp);
     complete_pdu(s, pdu, err);
 }
 
@@ -1474,16 +1484,25 @@ static void v9fs_clunk(void *opaque)
     int err;
     int32_t fid;
     size_t offset = 7;
+    V9fsFidState *fidp;
     V9fsPDU *pdu = opaque;
     V9fsState *s = pdu->s;
 
     pdu_unmarshal(pdu, offset, "d", &fid);
-    err = free_fid(s, fid);
+
+    fidp = get_fid(s, fid);
+    if (fidp == NULL) {
+        err = -ENOENT;
+        goto out_nofid;
+    }
+    err = free_fid(s, fidp->fid);
     if (err < 0) {
         goto out;
     }
     err = offset;
 out:
+    put_fid(s, fidp);
+out_nofid:
     complete_pdu(s, pdu, err);
 }
 
@@ -1638,7 +1657,7 @@ static void v9fs_read(void *opaque)
         err = -EINVAL;
     }
 out:
-    put_fid(fidp);
+    put_fid(s, fidp);
 out_nofid:
     complete_pdu(s, pdu, err);
 }
@@ -1747,7 +1766,7 @@ static void v9fs_readdir(void *opaque)
     retval += pdu_marshal(pdu, offset, "d", count);
     retval += count;
 out:
-    put_fid(fidp);
+    put_fid(s, fidp);
 out_nofid:
     complete_pdu(s, pdu, retval);
 }
@@ -1857,7 +1876,7 @@ static void v9fs_write(void *opaque)
     offset += pdu_marshal(pdu, offset, "d", total);
     err = offset;
 out:
-    put_fid(fidp);
+    put_fid(s, fidp);
 out_nofid:
     complete_pdu(s, pdu, err);
 }
@@ -1923,10 +1942,10 @@ static void v9fs_create(void *opaque)
         }
         err = v9fs_co_link(pdu->s, &nfidp->path, &fullname);
         if (err < 0) {
-            put_fid(nfidp);
+            put_fid(pdu->s, nfidp);
             goto out;
         }
-        put_fid(nfidp);
+        put_fid(pdu->s, nfidp);
     } else if (perm & P9_STAT_MODE_DEVICE) {
         char ctype;
         uint32_t major, minor;
@@ -1990,7 +2009,7 @@ static void v9fs_create(void *opaque)
     err = offset;
 
 out:
-    put_fid(fidp);
+    put_fid(pdu->s, fidp);
 out_nofid:
    complete_pdu(pdu->s, pdu, err);
    v9fs_string_free(&name);
@@ -2035,7 +2054,7 @@ static void v9fs_symlink(void *opaque)
     offset += pdu_marshal(pdu, offset, "Q", &qid);
     err = offset;
 out:
-    put_fid(dfidp);
+    put_fid(pdu->s, dfidp);
 out_nofid:
     complete_pdu(pdu->s, pdu, err);
     v9fs_string_free(&name);
@@ -2086,7 +2105,7 @@ static void v9fs_link(void *opaque)
     v9fs_string_free(&fullname);
 
 out:
-    put_fid(dfidp);
+    put_fid(s, dfidp);
 out_nofid:
     v9fs_string_free(&name);
     complete_pdu(s, pdu, err);
@@ -2113,8 +2132,8 @@ static void v9fs_remove(void *opaque)
     }
 
     /* For TREMOVE we need to clunk the fid even on failed remove */
-    put_fid(fidp);
     free_fid(pdu->s, fidp->fid);
+    put_fid(pdu->s, fidp);
 out_nofid:
     complete_pdu(pdu->s, pdu, err);
 }
@@ -2185,7 +2204,7 @@ static int v9fs_complete_rename(V9fsState *s, V9fsFidState *fidp,
     }
 out:
     if (dirfidp) {
-        put_fid(dirfidp);
+        put_fid(s, dirfidp);
     }
 out_nofid:
     return err;
@@ -2216,7 +2235,7 @@ static void v9fs_rename(void *opaque)
         err = offset;
     }
 out:
-    put_fid(fidp);
+    put_fid(s, fidp);
 out_nofid:
     complete_pdu(s, pdu, err);
     v9fs_string_free(&name);
@@ -2305,7 +2324,7 @@ static void v9fs_wstat(void *opaque)
     }
     err = offset;
 out:
-    put_fid(fidp);
+    put_fid(s, fidp);
 out_nofid:
     v9fs_stat_free(&v9stat);
     complete_pdu(s, pdu, err);
@@ -2379,7 +2398,7 @@ static void v9fs_statfs(void *opaque)
     retval = offset;
     retval += v9fs_fill_statfs(s, pdu, &stbuf);
 out:
-    put_fid(fidp);
+    put_fid(s, fidp);
 out_nofid:
     complete_pdu(s, pdu, retval);
     return;
@@ -2425,7 +2444,7 @@ static void v9fs_mknod(void *opaque)
     err = offset;
     err += pdu_marshal(pdu, offset, "Q", &qid);
 out:
-    put_fid(fidp);
+    put_fid(s, fidp);
 out_nofid:
     complete_pdu(s, pdu, err);
     v9fs_string_free(&fullname);
@@ -2473,7 +2492,7 @@ static void v9fs_lock(void *opaque)
     }
     status = P9_LOCK_SUCCESS;
 out:
-    put_fid(fidp);
+    put_fid(s, fidp);
 out_nofid:
     err = offset;
     err += pdu_marshal(pdu, offset, "b", status);
@@ -2515,7 +2534,7 @@ static void v9fs_getlock(void *opaque)
                           &glock->client_id);
     err = offset;
 out:
-    put_fid(fidp);
+    put_fid(s, fidp);
 out_nofid:
     complete_pdu(s, pdu, err);
     qemu_free(glock);
@@ -2555,7 +2574,7 @@ static void v9fs_mkdir(void *opaque)
     offset += pdu_marshal(pdu, offset, "Q", &qid);
     err = offset;
 out:
-    put_fid(fidp);
+    put_fid(pdu->s, fidp);
 out_nofid:
     complete_pdu(pdu->s, pdu, err);
     v9fs_string_free(&fullname);
@@ -2593,9 +2612,7 @@ static void v9fs_xattrwalk(void *opaque)
         size = v9fs_co_llistxattr(s, &xattr_fidp->path, NULL, 0);
         if (size < 0) {
             err = size;
-            put_fid(xattr_fidp);
             free_fid(s, xattr_fidp->fid);
-            xattr_fidp = NULL;
             goto out;
         }
         /*
@@ -2610,9 +2627,7 @@ static void v9fs_xattrwalk(void *opaque)
                                      xattr_fidp->fs.xattr.value,
                                      xattr_fidp->fs.xattr.len);
             if (err < 0) {
-                put_fid(xattr_fidp);
                 free_fid(s, xattr_fidp->fid);
-                xattr_fidp = NULL;
                 goto out;
             }
         }
@@ -2627,9 +2642,7 @@ static void v9fs_xattrwalk(void *opaque)
                                  &name, NULL, 0);
         if (size < 0) {
             err = size;
-            put_fid(xattr_fidp);
             free_fid(s, xattr_fidp->fid);
-            xattr_fidp = NULL;
             goto out;
         }
         /*
@@ -2644,9 +2657,7 @@ static void v9fs_xattrwalk(void *opaque)
                                     &name, xattr_fidp->fs.xattr.value,
                                     xattr_fidp->fs.xattr.len);
             if (err < 0) {
-                put_fid(xattr_fidp);
                 free_fid(s, xattr_fidp->fid);
-                xattr_fidp = NULL;
                 goto out;
             }
         }
@@ -2654,9 +2665,9 @@ static void v9fs_xattrwalk(void *opaque)
         err = offset;
     }
 out:
-    put_fid(file_fidp);
+    put_fid(s, file_fidp);
     if (xattr_fidp) {
-        put_fid(xattr_fidp);
+        put_fid(s, xattr_fidp);
     }
 out_nofid:
     complete_pdu(s, pdu, err);
@@ -2698,7 +2709,7 @@ static void v9fs_xattrcreate(void *opaque)
         xattr_fidp->fs.xattr.value = NULL;
     }
     err = offset;
-    put_fid(file_fidp);
+    put_fid(s, file_fidp);
 out_nofid:
     complete_pdu(s, pdu, err);
     v9fs_string_free(&name);
@@ -2729,7 +2740,7 @@ static void v9fs_readlink(void *opaque)
     err = offset;
     v9fs_string_free(&target);
 out:
-    put_fid(fidp);
+    put_fid(pdu->s, fidp);
 out_nofid:
     complete_pdu(pdu->s, pdu, err);
 }
diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h
index ce93c20..e16e5f4 100644
--- a/hw/9pfs/virtio-9p.h
+++ b/hw/9pfs/virtio-9p.h
@@ -204,6 +204,7 @@ struct V9fsFidState
     } fs;
     uid_t uid;
     int ref;
+    int clunked;
     V9fsFidState *next;
 };
 
@@ -362,11 +363,5 @@ static inline size_t do_pdu_unpack(void *dst, struct iovec *sg, int sg_count,
     return pdu_packunpack(dst, sg, sg_count, offset, size, 0);
 }
 
-static inline void put_fid(V9fsFidState *fidp)
-{
-    BUG_ON(!fidp->ref);
-    fidp->ref--;
-}
-
 extern void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq);
 #endif
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Qemu-devel] [PATCH 3/6] hw/9pfs: Add file descriptor reclaim support
  2011-06-06 17:16 [Qemu-devel] [PATCH 1/6] hw/9pfs: Add reference counting for fid Aneesh Kumar K.V
  2011-06-06 17:16 ` [Qemu-devel] [PATCH 2/6] hw/9pfs: Don't free fid in clunk Aneesh Kumar K.V
@ 2011-06-06 17:16 ` Aneesh Kumar K.V
  2011-06-10  1:27   ` Venkateswararao Jujjuri
  2011-06-06 17:16 ` [Qemu-devel] [PATCH 4/6] hw/9pfs: init fid list properly Aneesh Kumar K.V
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 14+ messages in thread
From: Aneesh Kumar K.V @ 2011-06-06 17:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, Aneesh Kumar K.V

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 hw/9pfs/codir.c            |    4 +-
 hw/9pfs/cofile.c           |   19 ++++-
 hw/9pfs/virtio-9p-coth.h   |    4 +-
 hw/9pfs/virtio-9p-device.c |    1 +
 hw/9pfs/virtio-9p.c        |  193 +++++++++++++++++++++++++++++++++++++++++++-
 hw/9pfs/virtio-9p.h        |   23 +++++-
 6 files changed, 229 insertions(+), 15 deletions(-)

diff --git a/hw/9pfs/codir.c b/hw/9pfs/codir.c
index 783d279..3347038 100644
--- a/hw/9pfs/codir.c
+++ b/hw/9pfs/codir.c
@@ -101,12 +101,10 @@ int v9fs_co_opendir(V9fsState *s, V9fsFidState *fidp)
     return err;
 }
 
-int v9fs_co_closedir(V9fsState *s, V9fsFidState *fidp)
+int v9fs_co_closedir(V9fsState *s, DIR *dir)
 {
     int err;
-    DIR *dir;
 
-    dir = fidp->fs.dir;
     v9fs_co_run_in_worker(
         {
             err = s->ops->closedir(&s->ctx, dir);
diff --git a/hw/9pfs/cofile.c b/hw/9pfs/cofile.c
index e388146..0caf1e3 100644
--- a/hw/9pfs/cofile.c
+++ b/hw/9pfs/cofile.c
@@ -58,6 +58,12 @@ int v9fs_co_open(V9fsState *s, V9fsFidState *fidp, int flags)
                 err = 0;
             }
         });
+    if (!err) {
+        total_open_fd++;
+        if (total_open_fd > open_fd_hw) {
+            v9fs_reclaim_fd(s);
+        }
+    }
     return err;
 }
 
@@ -79,15 +85,19 @@ int v9fs_co_open2(V9fsState *s, V9fsFidState *fidp, char *fullname, gid_t gid,
                 err = -errno;
             }
         });
+    if (!err) {
+        total_open_fd++;
+        if (total_open_fd > open_fd_hw) {
+            v9fs_reclaim_fd(s);
+        }
+    }
     return err;
 }
 
-int v9fs_co_close(V9fsState *s, V9fsFidState *fidp)
+int v9fs_co_close(V9fsState *s, int fd)
 {
-    int fd;
     int err;
 
-    fd = fidp->fs.fd;
     v9fs_co_run_in_worker(
         {
             err = s->ops->close(&s->ctx, fd);
@@ -95,6 +105,9 @@ int v9fs_co_close(V9fsState *s, V9fsFidState *fidp)
                 err = -errno;
             }
         });
+    if (!err) {
+        total_open_fd--;
+    }
     return err;
 }
 
diff --git a/hw/9pfs/virtio-9p-coth.h b/hw/9pfs/virtio-9p-coth.h
index 48defb7..b7be9b5 100644
--- a/hw/9pfs/virtio-9p-coth.h
+++ b/hw/9pfs/virtio-9p-coth.h
@@ -83,8 +83,8 @@ extern int v9fs_co_open2(V9fsState *, V9fsFidState *, char *, gid_t, int, int);
 extern int v9fs_co_lsetxattr(V9fsState *, V9fsString *, V9fsString *,
                              void *, size_t, int);
 extern int v9fs_co_lremovexattr(V9fsState *, V9fsString *, V9fsString *);
-extern int v9fs_co_closedir(V9fsState *, V9fsFidState *);
-extern int v9fs_co_close(V9fsState *, V9fsFidState *);
+extern int v9fs_co_closedir(V9fsState *, DIR *);
+extern int v9fs_co_close(V9fsState *, int);
 extern int v9fs_co_fsync(V9fsState *, V9fsFidState *, int);
 extern int v9fs_co_symlink(V9fsState *, V9fsFidState *, const char *,
                            const char *, gid_t);
diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c
index 7811103..70629b2 100644
--- a/hw/9pfs/virtio-9p-device.c
+++ b/hw/9pfs/virtio-9p-device.c
@@ -171,6 +171,7 @@ static PCIDeviceInfo virtio_9p_info = {
 static void virtio_9p_register_devices(void)
 {
     pci_qdev_register(&virtio_9p_info);
+    virtio_9p_set_fd_limit();
 }
 
 device_init(virtio_9p_register_devices)
diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
index f3127a5..21e07fb 100644
--- a/hw/9pfs/virtio-9p.c
+++ b/hw/9pfs/virtio-9p.c
@@ -22,6 +22,9 @@
 #include "virtio-9p-coth.h"
 
 int debug_9p_pdu;
+int open_fd_hw;
+int total_open_fd;
+static int open_fd_rc;
 
 enum {
     Oread   = 0x00,
@@ -234,11 +237,40 @@ static size_t v9fs_string_size(V9fsString *str)
 
 static V9fsFidState *get_fid(V9fsState *s, int32_t fid)
 {
+    int err;
     V9fsFidState *f;
 
     for (f = s->fid_list; f; f = f->next) {
         if (f->fid == fid && !f->clunked) {
+            /*
+             * Update the fid ref upfront so that
+             * we don't get reclaimed when we yield
+             * in open later.
+             */
             f->ref++;
+
+            /*
+             * check whether we need to reopen the
+             * file. We might have closed the fd
+             * while trying to free up some file
+             * descriptors.
+             */
+            if (f->fid_type == P9_FID_FILE) {
+                if (f->fs.fd == -1) {
+                    do {
+                        err = v9fs_co_open(s, f, f->open_flags);
+                    } while (err == -EINTR);
+                    if (err < 0) {
+                        f->ref--;
+                        return NULL;
+                    }
+                }
+            }
+            /*
+             * Mark the fid as referenced so that the LRU
+             * reclaim won't close the file descriptor
+             */
+            f->flags |= FID_REFERENCED;
             return f;
         }
     }
@@ -259,6 +291,11 @@ static V9fsFidState *alloc_fid(V9fsState *s, int32_t fid)
     f->fid = fid;
     f->fid_type = P9_FID_NONE;
     f->ref = 1;
+    /*
+     * Mark the fid as referenced so that the LRU
+     * reclaim won't close the file descriptor
+     */
+    f->flags |= FID_REFERENCED;
     f->next = s->fid_list;
     s->fid_list = f;
 
@@ -304,9 +341,12 @@ static int release_fid(V9fsState *s, V9fsFidState *fidp)
     int retval = 0;
 
     if (fidp->fid_type == P9_FID_FILE) {
-        retval = v9fs_co_close(s, fidp);
+        /* If we reclaimed the fd no need to close */
+        if (fidp->fs.fd != -1) {
+            retval = v9fs_co_close(s, fidp->fs.fd);
+        }
     } else if (fidp->fid_type == P9_FID_DIR) {
-        retval = v9fs_co_closedir(s, fidp);
+        retval = v9fs_co_closedir(s, fidp->fs.dir);
     } else if (fidp->fid_type == P9_FID_XATTR) {
         retval = v9fs_xattr_fid_clunk(s, fidp);
     }
@@ -319,7 +359,10 @@ static void put_fid(V9fsState *s, V9fsFidState *fidp)
 {
     BUG_ON(!fidp->ref);
     fidp->ref--;
-    if (!fidp->ref && fidp->clunked) {
+    /*
+     * Don't free the fid if it is in reclaim list
+     */
+    if (!fidp->ref && fidp->clunked && !fidp->rclm_lst) {
         release_fid(s, fidp);
     }
 }
@@ -343,6 +386,105 @@ static int free_fid(V9fsState *s, int32_t fid)
     return 0;
 }
 
+void v9fs_reclaim_fd(V9fsState *s)
+{
+    int reclaim_count = 0;
+    V9fsFidState *f, head_fid, *reclaim_list = NULL;
+
+    /*
+     * We don't want multiple coroutine to do reclaim
+     */
+    if (s->reclaim_in_prgs) {
+        return;
+    }
+    s->reclaim_in_prgs = 1;
+
+    head_fid.next = s->fid_list;
+    for (f = s->fid_list; f; f = f->next) {
+        /*
+         * Unlink fids cannot be reclaimed. Check
+         * for them and skip them. Also skip fids
+         * currently being operated on.
+         */
+        if (f->ref || f->flags & FID_NON_RECLAIMABLE) {
+            continue;
+        }
+        /*
+         * if it is a recently referenced fid
+         * we leave the fid untouched and clear the
+         * reference bit. We come back to it later
+         * in the next iteration. (a simple LRU without
+         * moving list elements around)
+         */
+        if (f->flags & FID_REFERENCED) {
+            f->flags &= ~FID_REFERENCED;
+            continue;
+        }
+        /*
+         * Add fids to reclaim list.
+         */
+        if (f->fid_type == P9_FID_FILE) {
+            if (f->fs.fd != -1) {
+                f->rclm_lst = reclaim_list;
+                reclaim_list = f;
+                f->fs_reclaim.fd = f->fs.fd;
+                f->fs.fd = -1;
+                reclaim_count++;
+            }
+        }
+        if (reclaim_count >= open_fd_rc) {
+            break;
+        }
+    }
+    /*
+     * Now close the fid in reclaim list. Free them if they
+     * are already clunked.
+     */
+    while (reclaim_list) {
+        f = reclaim_list;
+        reclaim_list = f->rclm_lst;
+        if (f->clunked) {
+            release_fid(s, f);
+        } else {
+            if (f->fid_type == P9_FID_FILE) {
+                v9fs_co_close(s, f->fs_reclaim.fd);
+            }
+            f->rclm_lst = NULL;
+        }
+    }
+    s->reclaim_in_prgs = 0;
+}
+
+static int v9fs_mark_fids_unreclaim(V9fsState *s, V9fsString *str)
+{
+    int err;
+    V9fsFidState *fidp, head_fid;
+
+    head_fid.next = s->fid_list;
+    for (fidp = s->fid_list; fidp; fidp = fidp->next) {
+        if (!strcmp(fidp->path.data, str->data)) {
+            /* Mark the fid non reclaimable. */
+            fidp->flags |= FID_NON_RECLAIMABLE;
+            /* reopen the file if already closed */
+            if (fidp->fs.fd == -1) {
+                do {
+                    err = v9fs_co_open(s, fidp, fidp->open_flags);
+                } while (err == -EINTR);
+                if (err < 0) {
+                    return -1;
+                }
+                /*
+                 * Go back to head of fid list because
+                 * the list could have got updated when
+                 * switched to the worker thread
+                 */
+                fidp = &head_fid;
+            }
+        }
+    }
+    return 0;
+}
+
 #define P9_QID_TYPE_DIR         0x80
 #define P9_QID_TYPE_SYMLINK     0x02
 
@@ -1388,6 +1530,14 @@ static void v9fs_open(void *opaque)
             goto out;
         }
         fidp->fid_type = P9_FID_FILE;
+        fidp->open_flags = flags;
+        if (flags & O_EXCL) {
+            /*
+             * We let the host file system do O_EXCL check
+             * We should not reclaim such fd
+             */
+            fidp->flags |= FID_NON_RECLAIMABLE;
+        }
         iounit = get_iounit(s, &fidp->path);
         offset += pdu_marshal(pdu, offset, "Qd", &qid, iounit);
         err = offset;
@@ -1432,6 +1582,14 @@ static void v9fs_lcreate(void *opaque)
         goto out;
     }
     fidp->fid_type = P9_FID_FILE;
+    fidp->open_flags = flags;
+    if (flags & O_EXCL) {
+        /*
+         * We let the host file system do O_EXCL check
+         * We should not reclaim such fd
+         */
+        fidp->flags |= FID_NON_RECLAIMABLE;
+    }
     iounit =  get_iounit(pdu->s, &fullname);
 
     err = v9fs_co_lstat(pdu->s, &fullname, &stbuf);
@@ -1993,6 +2151,14 @@ static void v9fs_create(void *opaque)
             goto out;
         }
         fidp->fid_type = P9_FID_FILE;
+        fidp->open_flags = omode_to_uflags(mode);
+        if (fidp->open_flags & O_EXCL) {
+            /*
+             * We let the host file system do O_EXCL check
+             * We should not reclaim such fd
+             */
+            fidp->flags |= FID_NON_RECLAIMABLE;
+        }
     }
     err = v9fs_co_lstat(pdu->s, &fullname, &stbuf);
     if (err < 0) {
@@ -2126,11 +2292,19 @@ static void v9fs_remove(void *opaque)
         err = -EINVAL;
         goto out_nofid;
     }
+    /*
+     * IF the file is unlinked, we cannot reopen
+     * the file later. So don't reclaim fd
+     */
+    err = v9fs_mark_fids_unreclaim(pdu->s, &fidp->path);
+    if (err < 0) {
+        goto out_err;
+    }
     err = v9fs_co_remove(pdu->s, &fidp->path);
     if (!err) {
         err = offset;
     }
-
+out_err:
     /* For TREMOVE we need to clunk the fid even on failed remove */
     free_fid(pdu->s, fidp->fid);
     put_fid(pdu->s, fidp);
@@ -2826,3 +3000,14 @@ void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq)
     }
     free_pdu(s, pdu);
 }
+
+void virtio_9p_set_fd_limit(void)
+{
+    struct rlimit rlim;
+    if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) {
+        fprintf(stderr, "Failed to get the resource limit\n");
+        exit(1);
+    }
+    open_fd_hw = rlim.rlim_cur - MIN(400, rlim.rlim_cur/3);
+    open_fd_rc = rlim.rlim_cur/2;
+}
diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h
index e16e5f4..36aa4a5 100644
--- a/hw/9pfs/virtio-9p.h
+++ b/hw/9pfs/virtio-9p.h
@@ -5,6 +5,7 @@
 #include <dirent.h>
 #include <sys/time.h>
 #include <utime.h>
+#include <sys/resource.h>
 #include "hw/virtio.h"
 #include "fsdev/file-op-9p.h"
 
@@ -101,6 +102,9 @@ enum p9_proto_version {
 #define P9_NOTAG    (u16)(~0)
 #define P9_NOFID    (u32)(~0)
 #define P9_MAXWELEM 16
+
+#define FID_REFERENCED          0x1
+#define FID_NON_RECLAIMABLE     0x2
 static inline const char *rpath(FsContext *ctx, const char *path, char *buffer)
 {
     snprintf(buffer, PATH_MAX, "%s/%s", ctx->fs_root, path);
@@ -198,14 +202,21 @@ struct V9fsFidState
     int32_t fid;
     V9fsString path;
     union {
-	int fd;
-	DIR *dir;
-	V9fsXattr xattr;
+        int fd;
+        DIR *dir;
+        V9fsXattr xattr;
     } fs;
+    union {
+        int fd;
+        DIR *dir;
+    } fs_reclaim;
+    int flags;
+    int open_flags;
     uid_t uid;
     int ref;
     int clunked;
     V9fsFidState *next;
+    V9fsFidState *rclm_lst;
 };
 
 typedef struct V9fsState
@@ -222,6 +233,7 @@ typedef struct V9fsState
     size_t config_size;
     enum p9_proto_version proto_version;
     int32_t msize;
+    int reclaim_in_prgs;
 } V9fsState;
 
 typedef struct V9fsStatState {
@@ -354,6 +366,9 @@ typedef struct V9fsGetlock
     V9fsString client_id;
 } V9fsGetlock;
 
+extern int open_fd_hw;
+extern int total_open_fd;
+
 size_t pdu_packunpack(void *addr, struct iovec *sg, int sg_count,
                       size_t offset, size_t size, int pack);
 
@@ -364,4 +379,6 @@ static inline size_t do_pdu_unpack(void *dst, struct iovec *sg, int sg_count,
 }
 
 extern void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq);
+extern void virtio_9p_set_fd_limit(void);
+extern void v9fs_reclaim_fd(V9fsState *s);
 #endif
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Qemu-devel] [PATCH 4/6] hw/9pfs: init fid list properly
  2011-06-06 17:16 [Qemu-devel] [PATCH 1/6] hw/9pfs: Add reference counting for fid Aneesh Kumar K.V
  2011-06-06 17:16 ` [Qemu-devel] [PATCH 2/6] hw/9pfs: Don't free fid in clunk Aneesh Kumar K.V
  2011-06-06 17:16 ` [Qemu-devel] [PATCH 3/6] hw/9pfs: Add file descriptor reclaim support Aneesh Kumar K.V
@ 2011-06-06 17:16 ` Aneesh Kumar K.V
  2011-06-06 17:16 ` [Qemu-devel] [PATCH 5/6] hw/9pfs: Use v9fs_do_close instead of close Aneesh Kumar K.V
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 14+ messages in thread
From: Aneesh Kumar K.V @ 2011-06-06 17:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, Aneesh Kumar K.V

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 hw/9pfs/virtio-9p-device.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c
index 70629b2..4bec8bf 100644
--- a/hw/9pfs/virtio-9p-device.c
+++ b/hw/9pfs/virtio-9p-device.c
@@ -130,6 +130,7 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf)
     s->config_size = sizeof(struct virtio_9p_config) +
                         s->tag_len;
     s->vdev.get_config = virtio_9p_get_config;
+    s->fid_list = NULL;
 
     if (v9fs_init_worker_threads() < 0) {
         fprintf(stderr, "worker thread initialization failed\n");
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Qemu-devel] [PATCH 5/6] hw/9pfs: Use v9fs_do_close instead of close
  2011-06-06 17:16 [Qemu-devel] [PATCH 1/6] hw/9pfs: Add reference counting for fid Aneesh Kumar K.V
                   ` (2 preceding siblings ...)
  2011-06-06 17:16 ` [Qemu-devel] [PATCH 4/6] hw/9pfs: init fid list properly Aneesh Kumar K.V
@ 2011-06-06 17:16 ` Aneesh Kumar K.V
  2011-06-10  1:32   ` Venkateswararao Jujjuri
  2011-06-06 17:16 ` [Qemu-devel] [PATCH 6/6] hw/9pfs: Add directory reclaim support Aneesh Kumar K.V
  2011-06-09 23:10 ` [Qemu-devel] [PATCH 1/6] hw/9pfs: Add reference counting for fid Venkateswararao Jujjuri
  5 siblings, 1 reply; 14+ messages in thread
From: Aneesh Kumar K.V @ 2011-06-06 17:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, Aneesh Kumar K.V

we should use the local abstraction instead of
directly calling close.

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 hw/9pfs/virtio-9p.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
index 21e07fb..d322814 100644
--- a/hw/9pfs/virtio-9p.c
+++ b/hw/9pfs/virtio-9p.c
@@ -1596,7 +1596,7 @@ static void v9fs_lcreate(void *opaque)
     if (err < 0) {
         fidp->fid_type = P9_FID_NONE;
         if (fidp->fs.fd > 0) {
-            close(fidp->fs.fd);
+            v9fs_co_close(pdu->s, fidp->fs.fd);
         }
         goto out;
     }
@@ -2164,7 +2164,7 @@ static void v9fs_create(void *opaque)
     if (err < 0) {
         fidp->fid_type = P9_FID_NONE;
         if (fidp->fs.fd) {
-            close(fidp->fs.fd);
+            v9fs_co_close(pdu->s, fidp->fs.fd);
         }
         goto out;
     }
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Qemu-devel] [PATCH 6/6] hw/9pfs: Add directory reclaim support
  2011-06-06 17:16 [Qemu-devel] [PATCH 1/6] hw/9pfs: Add reference counting for fid Aneesh Kumar K.V
                   ` (3 preceding siblings ...)
  2011-06-06 17:16 ` [Qemu-devel] [PATCH 5/6] hw/9pfs: Use v9fs_do_close instead of close Aneesh Kumar K.V
@ 2011-06-06 17:16 ` Aneesh Kumar K.V
  2011-06-10  1:36   ` Venkateswararao Jujjuri
  2011-06-09 23:10 ` [Qemu-devel] [PATCH 1/6] hw/9pfs: Add reference counting for fid Venkateswararao Jujjuri
  5 siblings, 1 reply; 14+ messages in thread
From: Aneesh Kumar K.V @ 2011-06-06 17:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, Aneesh Kumar K.V

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 hw/9pfs/codir.c     |    9 +++++++++
 hw/9pfs/virtio-9p.c |   26 ++++++++++++++++++++++++--
 2 files changed, 33 insertions(+), 2 deletions(-)

diff --git a/hw/9pfs/codir.c b/hw/9pfs/codir.c
index 3347038..2c26f72 100644
--- a/hw/9pfs/codir.c
+++ b/hw/9pfs/codir.c
@@ -98,6 +98,12 @@ int v9fs_co_opendir(V9fsState *s, V9fsFidState *fidp)
                 err = 0;
             }
         });
+    if (!err) {
+        total_open_fd++;
+        if (total_open_fd > open_fd_hw) {
+            v9fs_reclaim_fd(s);
+        }
+    }
     return err;
 }
 
@@ -112,5 +118,8 @@ int v9fs_co_closedir(V9fsState *s, DIR *dir)
                 err = -errno;
             }
         });
+    if (!err) {
+        total_open_fd--;
+    }
     return err;
 }
diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
index d322814..55aca93 100644
--- a/hw/9pfs/virtio-9p.c
+++ b/hw/9pfs/virtio-9p.c
@@ -265,7 +265,17 @@ static V9fsFidState *get_fid(V9fsState *s, int32_t fid)
                         return NULL;
                     }
                 }
-            }
+            } else if (f->fid_type == P9_FID_DIR) {
+                if (f->fs.dir == NULL) {
+                    do {
+                        err = v9fs_co_opendir(s, f);
+                    } while (err == -EINTR);
+                    if (err < 0) {
+                        f->ref--;
+                        return NULL;
+                    }
+                }
+             }
             /*
              * Mark the fid as referenced so that the LRU
              * reclaim won't close the file descriptor
@@ -346,7 +356,9 @@ static int release_fid(V9fsState *s, V9fsFidState *fidp)
             retval = v9fs_co_close(s, fidp->fs.fd);
         }
     } else if (fidp->fid_type == P9_FID_DIR) {
-        retval = v9fs_co_closedir(s, fidp->fs.dir);
+        if (fidp->fs.dir != NULL) {
+            retval = v9fs_co_closedir(s, fidp->fs.dir);
+        }
     } else if (fidp->fid_type == P9_FID_XATTR) {
         retval = v9fs_xattr_fid_clunk(s, fidp);
     }
@@ -431,6 +443,14 @@ void v9fs_reclaim_fd(V9fsState *s)
                 f->fs.fd = -1;
                 reclaim_count++;
             }
+        } else if (f->fid_type == P9_FID_DIR) {
+            if (f->fs.dir != NULL) {
+                f->rclm_lst = reclaim_list;
+                reclaim_list = f;
+                f->fs_reclaim.dir = f->fs.dir;
+                f->fs.dir = NULL;
+                reclaim_count++;
+            }
         }
         if (reclaim_count >= open_fd_rc) {
             break;
@@ -448,6 +468,8 @@ void v9fs_reclaim_fd(V9fsState *s)
         } else {
             if (f->fid_type == P9_FID_FILE) {
                 v9fs_co_close(s, f->fs_reclaim.fd);
+            } else if (f->fid_type == P9_FID_DIR) {
+                v9fs_co_closedir(s, f->fs_reclaim.dir);
             }
             f->rclm_lst = NULL;
         }
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [PATCH 1/6] hw/9pfs: Add reference counting for fid
  2011-06-06 17:16 [Qemu-devel] [PATCH 1/6] hw/9pfs: Add reference counting for fid Aneesh Kumar K.V
                   ` (4 preceding siblings ...)
  2011-06-06 17:16 ` [Qemu-devel] [PATCH 6/6] hw/9pfs: Add directory reclaim support Aneesh Kumar K.V
@ 2011-06-09 23:10 ` Venkateswararao Jujjuri
  2011-06-10  6:27   ` Aneesh Kumar K.V
  5 siblings, 1 reply; 14+ messages in thread
From: Venkateswararao Jujjuri @ 2011-06-09 23:10 UTC (permalink / raw)
  To: qemu-devel

On 06/06/2011 10:16 AM, Aneesh Kumar K.V wrote:
> Signed-off-by: Aneesh Kumar K.V<aneesh.kumar@linux.vnet.ibm.com>

Just one minor issue below; otherwise

Reviewed-by: Venkateswararao Jujjuri "<jvrao@linux.vnet.ibm.com>

> ---
>   hw/9pfs/virtio-9p.c |  205 +++++++++++++++++++++++++++++++++++----------------
>   hw/9pfs/virtio-9p.h |    7 ++
>   2 files changed, 147 insertions(+), 65 deletions(-)
>
> diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
> index e2aa863..03d8664 100644
> --- a/hw/9pfs/virtio-9p.c
> +++ b/hw/9pfs/virtio-9p.c
> @@ -232,12 +232,13 @@ static size_t v9fs_string_size(V9fsString *str)
>       return str->size;
>   }
>
> -static V9fsFidState *lookup_fid(V9fsState *s, int32_t fid)
> +static V9fsFidState *get_fid(V9fsState *s, int32_t fid)
>   {
>       V9fsFidState *f;
>
>       for (f = s->fid_list; f; f = f->next) {
>           if (f->fid == fid) {
> +            f->ref++;
>               return f;
>           }
>       }
> @@ -249,16 +250,16 @@ static V9fsFidState *alloc_fid(V9fsState *s, int32_t fid)
>   {
>       V9fsFidState *f;
>
> -    f = lookup_fid(s, fid);
> +    f = get_fid(s, fid);
>       if (f) {
> +        f->ref--;
>           return NULL;
>       }
>
>       f = qemu_mallocz(sizeof(V9fsFidState));
> -
>       f->fid = fid;
>       f->fid_type = P9_FID_NONE;
> -
> +    f->ref = 1;
>       f->next = s->fid_list;
>       s->fid_list = f;
>
> @@ -1014,19 +1015,22 @@ static void v9fs_attach(void *opaque)
>       fidp = alloc_fid(s, fid);
>       if (fidp == NULL) {
>           err = -EINVAL;
> -        goto out;
> +        goto out_nofid;
>       }
>       fidp->uid = n_uname;
>       v9fs_string_sprintf(&fidp->path, "%s", "/");
>       err = fid_to_qid(s, fidp,&qid);
>       if (err<  0) {
>           err = -EINVAL;
> +        put_fid(fidp);
>           free_fid(s, fid);
> -        goto out;
> +        goto out_nofid;
>       }
>       offset += pdu_marshal(pdu, offset, "Q",&qid);
>       err = offset;
> -out:
> +    put_fid(fidp);
> +
> +out_nofid:
>       complete_pdu(s, pdu, err);
>       v9fs_string_free(&uname);
>       v9fs_string_free(&aname);
> @@ -1045,10 +1049,10 @@ static void v9fs_stat(void *opaque)
>
>       pdu_unmarshal(pdu, offset, "d",&fid);
>
> -    fidp = lookup_fid(s, fid);
> +    fidp = get_fid(s, fid);
>       if (fidp == NULL) {
>           err = -ENOENT;
> -        goto out;
> +        goto out_nofid;
>       }
>       err = v9fs_co_lstat(s,&fidp->path,&stbuf);
>       if (err<  0) {
> @@ -1062,6 +1066,8 @@ static void v9fs_stat(void *opaque)
>       err = offset;
>       v9fs_stat_free(&v9stat);
>   out:
> +    put_fid(fidp);
> +out_nofid:
>       complete_pdu(s, pdu, err);
>   }
>
> @@ -1079,10 +1085,10 @@ static void v9fs_getattr(void *opaque)
>
>       pdu_unmarshal(pdu, offset, "dq",&fid,&request_mask);
>
> -    fidp = lookup_fid(s, fid);
> +    fidp = get_fid(s, fid);
>       if (fidp == NULL) {
>           retval = -ENOENT;
> -        goto out;
> +        goto out_nofid;
>       }
>       /*
>        * Currently we only support BASIC fields in stat, so there is no
> @@ -1096,6 +1102,8 @@ static void v9fs_getattr(void *opaque)
>       retval = offset;
>       retval += pdu_marshal(pdu, offset, "A",&v9stat_dotl);
>   out:
> +    put_fid(fidp);
> +out_nofid:
>       complete_pdu(s, pdu, retval);
>   }
>
> @@ -1123,10 +1131,10 @@ static void v9fs_setattr(void *opaque)
>
>       pdu_unmarshal(pdu, offset, "dI",&fid,&v9iattr);
>
> -    fidp = lookup_fid(s, fid);
> +    fidp = get_fid(s, fid);
>       if (fidp == NULL) {
>           err = -EINVAL;
> -        goto out;
> +        goto out_nofid;
>       }
>       if (v9iattr.valid&  ATTR_MODE) {
>           err = v9fs_co_chmod(s,&fidp->path, v9iattr.mode);
> @@ -1188,6 +1196,8 @@ static void v9fs_setattr(void *opaque)
>       }
>       err = offset;
>   out:
> +    put_fid(fidp);
> +out_nofid:
>       complete_pdu(s, pdu, err);
>   }
>
> @@ -1214,7 +1224,7 @@ static void v9fs_walk(void *opaque)
>       int32_t fid, newfid;
>       V9fsString *wnames = NULL;
>       V9fsFidState *fidp;
> -    V9fsFidState *newfidp;
> +    V9fsFidState *newfidp = NULL;;
>       V9fsPDU *pdu = opaque;
>       V9fsState *s = pdu->s;
>
> @@ -1231,12 +1241,12 @@ static void v9fs_walk(void *opaque)
>
>       } else if (nwnames>  P9_MAXWELEM) {
>           err = -EINVAL;
> -        goto out;
> +        goto out_nofid;
>       }
> -    fidp = lookup_fid(s, fid);
> +    fidp = get_fid(s, fid);
>       if (fidp == NULL) {
>           err = -ENOENT;
> -        goto out;
> +        goto out_nofid;
>       }
>       if (fid == newfid) {
>           BUG_ON(fidp->fid_type != P9_FID_NONE);
> @@ -1269,7 +1279,9 @@ static void v9fs_walk(void *opaque)
>               v9fs_string_copy(&newfidp->path,&path);
>               err = v9fs_co_lstat(s,&newfidp->path,&stbuf);
>               if (err<  0) {
> +                put_fid(newfidp);
>                   free_fid(s, newfidp->fid);
> +                newfidp = NULL;
>                   v9fs_string_free(&path);
>                   goto out;
>               }
> @@ -1279,6 +1291,11 @@ static void v9fs_walk(void *opaque)
>       }
>       err = v9fs_walk_marshal(pdu, nwnames, qids);
>   out:
> +    put_fid(fidp);
> +    if (newfidp) {
> +        put_fid(newfidp);
> +    }
> +out_nofid:
>       complete_pdu(s, pdu, err);
>       if (nwnames&&  nwnames<= P9_MAXWELEM) {
>           for (name_idx = 0; name_idx<  nwnames; name_idx++) {
> @@ -1327,10 +1344,10 @@ static void v9fs_open(void *opaque)
>       } else {
>           pdu_unmarshal(pdu, offset, "db",&fid,&mode);
>       }
> -    fidp = lookup_fid(s, fid);
> +    fidp = get_fid(s, fid);
>       if (fidp == NULL) {
>           err = -ENOENT;
> -        goto out;
> +        goto out_nofid;
>       }
>       BUG_ON(fidp->fid_type != P9_FID_NONE);
>
> @@ -1366,6 +1383,8 @@ static void v9fs_open(void *opaque)
>           err = offset;
>       }
>   out:
> +    put_fid(fidp);
> +out_nofid:
>       complete_pdu(s, pdu, err);
>   }
>
> @@ -1388,10 +1407,10 @@ static void v9fs_lcreate(void *opaque)
>       pdu_unmarshal(pdu, offset, "dsddd",&dfid,&name,&flags,
>                     &mode,&gid);
>
> -    fidp = lookup_fid(pdu->s, dfid);
> +    fidp = get_fid(pdu->s, dfid);
>       if (fidp == NULL) {
>           err = -ENOENT;
> -        goto out;
> +        goto out_nofid;
>       }
>       v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data);
>
> @@ -1418,6 +1437,8 @@ static void v9fs_lcreate(void *opaque)
>       offset += pdu_marshal(pdu, offset, "Qd",&qid, iounit);
>       err = offset;
>   out:
> +    put_fid(fidp);
> +out_nofid:
>       complete_pdu(pdu->s, pdu, err);
>       v9fs_string_free(&name);
>       v9fs_string_free(&fullname);
> @@ -1434,7 +1455,7 @@ static void v9fs_fsync(void *opaque)
>       V9fsState *s = pdu->s;
>
>       pdu_unmarshal(pdu, offset, "dd",&fid,&datasync);
> -    fidp = lookup_fid(s, fid);
> +    fidp = get_fid(s, fid);
>       if (fidp == NULL) {
>           err = -ENOENT;
>           goto out;
> @@ -1444,6 +1465,7 @@ static void v9fs_fsync(void *opaque)
>           err = offset;
>       }
>   out:
> +    put_fid(fidp);
It should be

put_fid(fidp);

out_nofid:

>       complete_pdu(s, pdu, err);
>   }
>
> @@ -1561,10 +1583,10 @@ static void v9fs_read(void *opaque)
>
>       pdu_unmarshal(pdu, offset, "dqd",&fid,&off,&max_count);
>
> -    fidp = lookup_fid(s, fid);
> +    fidp = get_fid(s, fid);
>       if (fidp == NULL) {
>           err = -EINVAL;
> -        goto out;
> +        goto out_nofid;
>       }
>       if (fidp->fid_type == P9_FID_DIR) {
>
> @@ -1616,6 +1638,8 @@ static void v9fs_read(void *opaque)
>           err = -EINVAL;
>       }
>   out:
> +    put_fid(fidp);
> +out_nofid:
>       complete_pdu(s, pdu, err);
>   }
>
> @@ -1700,8 +1724,12 @@ static void v9fs_readdir(void *opaque)
>
>       pdu_unmarshal(pdu, offset, "dqd",&fid,&initial_offset,&max_count);
>
> -    fidp = lookup_fid(s, fid);
> -    if (fidp == NULL || !fidp->fs.dir) {
> +    fidp = get_fid(s, fid);
> +    if (fidp == NULL) {
> +        retval = -EINVAL;
> +        goto out_nofid;
> +    }
> +    if (!fidp->fs.dir) {
>           retval = -EINVAL;
>           goto out;
>       }
> @@ -1719,6 +1747,8 @@ static void v9fs_readdir(void *opaque)
>       retval += pdu_marshal(pdu, offset, "d", count);
>       retval += count;
>   out:
> +    put_fid(fidp);
> +out_nofid:
>       complete_pdu(s, pdu, retval);
>   }
>
> @@ -1784,10 +1814,10 @@ static void v9fs_write(void *opaque)
>
>       pdu_unmarshal(pdu, offset, "dqdv",&fid,&off,&count, sg,&cnt);
>
> -    fidp = lookup_fid(s, fid);
> +    fidp = get_fid(s, fid);
>       if (fidp == NULL) {
>           err = -EINVAL;
> -        goto out;
> +        goto out_nofid;
>       }
>       if (fidp->fid_type == P9_FID_FILE) {
>           if (fidp->fs.fd == -1) {
> @@ -1827,6 +1857,8 @@ static void v9fs_write(void *opaque)
>       offset += pdu_marshal(pdu, offset, "d", total);
>       err = offset;
>   out:
> +    put_fid(fidp);
> +out_nofid:
>       complete_pdu(s, pdu, err);
>   }
>
> @@ -1851,10 +1883,10 @@ static void v9fs_create(void *opaque)
>       pdu_unmarshal(pdu, offset, "dsdbs",&fid,&name,
>                     &perm,&mode,&extension);
>
> -    fidp = lookup_fid(pdu->s, fid);
> +    fidp = get_fid(pdu->s, fid);
>       if (fidp == NULL) {
>           err = -EINVAL;
> -        goto out;
> +        goto out_nofid;
>       }
>
>       v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data);
> @@ -1884,15 +1916,17 @@ static void v9fs_create(void *opaque)
>           }
>       } else if (perm&  P9_STAT_MODE_LINK) {
>           int32_t nfid = atoi(extension.data);
> -        V9fsFidState *nfidp = lookup_fid(pdu->s, nfid);
> +        V9fsFidState *nfidp = get_fid(pdu->s, nfid);
>           if (nfidp == NULL) {
>               err = -EINVAL;
>               goto out;
>           }
>           err = v9fs_co_link(pdu->s,&nfidp->path,&fullname);
>           if (err<  0) {
> +            put_fid(nfidp);
>               goto out;
>           }
> +        put_fid(nfidp);
>       } else if (perm&  P9_STAT_MODE_DEVICE) {
>           char ctype;
>           uint32_t major, minor;
> @@ -1956,6 +1990,8 @@ static void v9fs_create(void *opaque)
>       err = offset;
>
>   out:
> +    put_fid(fidp);
> +out_nofid:
>      complete_pdu(pdu->s, pdu, err);
>      v9fs_string_free(&name);
>      v9fs_string_free(&extension);
> @@ -1980,10 +2016,10 @@ static void v9fs_symlink(void *opaque)
>
>       pdu_unmarshal(pdu, offset, "dssd",&dfid,&name,&symname,&gid);
>
> -    dfidp = lookup_fid(pdu->s, dfid);
> +    dfidp = get_fid(pdu->s, dfid);
>       if (dfidp == NULL) {
>           err = -EINVAL;
> -        goto out;
> +        goto out_nofid;
>       }
>
>       v9fs_string_sprintf(&fullname, "%s/%s", dfidp->path.data, name.data);
> @@ -1999,6 +2035,8 @@ static void v9fs_symlink(void *opaque)
>       offset += pdu_marshal(pdu, offset, "Q",&qid);
>       err = offset;
>   out:
> +    put_fid(dfidp);
> +out_nofid:
>       complete_pdu(pdu->s, pdu, err);
>       v9fs_string_free(&name);
>       v9fs_string_free(&symname);
> @@ -2028,13 +2066,13 @@ static void v9fs_link(void *opaque)
>
>       pdu_unmarshal(pdu, offset, "dds",&dfid,&oldfid,&name);
>
> -    dfidp = lookup_fid(s, dfid);
> +    dfidp = get_fid(s, dfid);
>       if (dfidp == NULL) {
>           err = -ENOENT;
> -        goto out;
> +        goto out_nofid;
>       }
>
> -    oldfidp = lookup_fid(s, oldfid);
> +    oldfidp = get_fid(s, oldfid);
>       if (oldfidp == NULL) {
>           err = -ENOENT;
>           goto out;
> @@ -2048,6 +2086,8 @@ static void v9fs_link(void *opaque)
>       v9fs_string_free(&fullname);
>
>   out:
> +    put_fid(dfidp);
> +out_nofid:
>       v9fs_string_free(&name);
>       complete_pdu(s, pdu, err);
>   }
> @@ -2062,10 +2102,10 @@ static void v9fs_remove(void *opaque)
>
>       pdu_unmarshal(pdu, offset, "d",&fid);
>
> -    fidp = lookup_fid(pdu->s, fid);
> +    fidp = get_fid(pdu->s, fid);
>       if (fidp == NULL) {
>           err = -EINVAL;
> -        goto out;
> +        goto out_nofid;
>       }
>       err = v9fs_co_remove(pdu->s,&fidp->path);
>       if (!err) {
> @@ -2073,8 +2113,9 @@ static void v9fs_remove(void *opaque)
>       }
>
>       /* For TREMOVE we need to clunk the fid even on failed remove */
> +    put_fid(fidp);
>       free_fid(pdu->s, fidp->fid);
> -out:
> +out_nofid:
>       complete_pdu(pdu->s, pdu, err);
>   }
>
> @@ -2083,14 +2124,14 @@ static int v9fs_complete_rename(V9fsState *s, V9fsFidState *fidp,
>   {
>       char *end;
>       int err = 0;
> +    V9fsFidState *dirfidp = NULL;
>       char *old_name, *new_name;
>
>       if (newdirfid != -1) {
> -        V9fsFidState *dirfidp;
> -        dirfidp = lookup_fid(s, newdirfid);
> +        dirfidp = get_fid(s, newdirfid);
>           if (dirfidp == NULL) {
>               err = -ENOENT;
> -            goto out;
> +            goto out_nofid;
>           }
>           BUG_ON(dirfidp->fid_type != P9_FID_NONE);
>
> @@ -2143,6 +2184,10 @@ static int v9fs_complete_rename(V9fsState *s, V9fsFidState *fidp,
>           v9fs_string_copy(&fidp->path, name);
>       }
>   out:
> +    if (dirfidp) {
> +        put_fid(dirfidp);
> +    }
> +out_nofid:
>       return err;
>   }
>
> @@ -2159,10 +2204,10 @@ static void v9fs_rename(void *opaque)
>
>       pdu_unmarshal(pdu, offset, "dds",&fid,&newdirfid,&name);
>
> -    fidp = lookup_fid(s, fid);
> +    fidp = get_fid(s, fid);
>       if (fidp == NULL) {
>           err = -ENOENT;
> -        goto out;
> +        goto out_nofid;
>       }
>       BUG_ON(fidp->fid_type != P9_FID_NONE);
>
> @@ -2171,6 +2216,8 @@ static void v9fs_rename(void *opaque)
>           err = offset;
>       }
>   out:
> +    put_fid(fidp);
> +out_nofid:
>       complete_pdu(s, pdu, err);
>       v9fs_string_free(&name);
>   }
> @@ -2189,10 +2236,10 @@ static void v9fs_wstat(void *opaque)
>
>       pdu_unmarshal(pdu, offset, "dwS",&fid,&unused,&v9stat);
>
> -    fidp = lookup_fid(s, fid);
> +    fidp = get_fid(s, fid);
>       if (fidp == NULL) {
>           err = -EINVAL;
> -        goto out;
> +        goto out_nofid;
>       }
>       /* do we need to sync the file? */
>       if (donttouch_stat(&v9stat)) {
> @@ -2258,6 +2305,8 @@ static void v9fs_wstat(void *opaque)
>       }
>       err = offset;
>   out:
> +    put_fid(fidp);
> +out_nofid:
>       v9fs_stat_free(&v9stat);
>       complete_pdu(s, pdu, err);
>   }
> @@ -2318,10 +2367,10 @@ static void v9fs_statfs(void *opaque)
>       V9fsState *s = pdu->s;
>
>       pdu_unmarshal(pdu, offset, "d",&fid);
> -    fidp = lookup_fid(s, fid);
> +    fidp = get_fid(s, fid);
>       if (fidp == NULL) {
>           retval = -ENOENT;
> -        goto out;
> +        goto out_nofid;
>       }
>       retval = v9fs_co_statfs(s,&fidp->path,&stbuf);
>       if (retval<  0) {
> @@ -2330,6 +2379,8 @@ static void v9fs_statfs(void *opaque)
>       retval = offset;
>       retval += v9fs_fill_statfs(s, pdu,&stbuf);
>   out:
> +    put_fid(fidp);
> +out_nofid:
>       complete_pdu(s, pdu, retval);
>       return;
>   }
> @@ -2355,10 +2406,10 @@ static void v9fs_mknod(void *opaque)
>       pdu_unmarshal(pdu, offset, "dsdddd",&fid,&name,&mode,
>                     &major,&minor,&gid);
>
> -    fidp = lookup_fid(s, fid);
> +    fidp = get_fid(s, fid);
>       if (fidp == NULL) {
>           err = -ENOENT;
> -        goto out;
> +        goto out_nofid;
>       }
>       v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data);
>       err = v9fs_co_mknod(s,&fullname, fidp->uid, gid,
> @@ -2374,6 +2425,8 @@ static void v9fs_mknod(void *opaque)
>       err = offset;
>       err += pdu_marshal(pdu, offset, "Q",&qid);
>   out:
> +    put_fid(fidp);
> +out_nofid:
>       complete_pdu(s, pdu, err);
>       v9fs_string_free(&fullname);
>       v9fs_string_free(&name);
> @@ -2407,12 +2460,12 @@ static void v9fs_lock(void *opaque)
>       /* We support only block flag now (that too ignored currently) */
>       if (flock->flags&  ~P9_LOCK_FLAGS_BLOCK) {
>           err = -EINVAL;
> -        goto out;
> +        goto out_nofid;
>       }
> -    fidp = lookup_fid(s, fid);
> +    fidp = get_fid(s, fid);
>       if (fidp == NULL) {
>           err = -ENOENT;
> -        goto out;
> +        goto out_nofid;
>       }
>       err = v9fs_co_fstat(s, fidp->fs.fd,&stbuf);
>       if (err<  0) {
> @@ -2420,6 +2473,8 @@ static void v9fs_lock(void *opaque)
>       }
>       status = P9_LOCK_SUCCESS;
>   out:
> +    put_fid(fidp);
> +out_nofid:
>       err = offset;
>       err += pdu_marshal(pdu, offset, "b", status);
>       complete_pdu(s, pdu, err);
> @@ -2445,10 +2500,10 @@ static void v9fs_getlock(void *opaque)
>                     &glock->start,&glock->length,&glock->proc_id,
>                     &glock->client_id);
>
> -    fidp = lookup_fid(s, fid);
> +    fidp = get_fid(s, fid);
>       if (fidp == NULL) {
>           err = -ENOENT;
> -        goto out;
> +        goto out_nofid;
>       }
>       err = v9fs_co_fstat(s, fidp->fs.fd,&stbuf);
>       if (err<  0) {
> @@ -2460,6 +2515,8 @@ static void v9fs_getlock(void *opaque)
>                             &glock->client_id);
>       err = offset;
>   out:
> +    put_fid(fidp);
> +out_nofid:
>       complete_pdu(s, pdu, err);
>       qemu_free(glock);
>   }
> @@ -2480,10 +2537,10 @@ static void v9fs_mkdir(void *opaque)
>       v9fs_string_init(&fullname);
>       pdu_unmarshal(pdu, offset, "dsdd",&fid,&name,&mode,&gid);
>
> -    fidp = lookup_fid(pdu->s, fid);
> +    fidp = get_fid(pdu->s, fid);
>       if (fidp == NULL) {
>           err = -ENOENT;
> -        goto out;
> +        goto out_nofid;
>       }
>       v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data);
>       err = v9fs_co_mkdir(pdu->s, fullname.data, mode, fidp->uid, gid);
> @@ -2498,6 +2555,8 @@ static void v9fs_mkdir(void *opaque)
>       offset += pdu_marshal(pdu, offset, "Q",&qid);
>       err = offset;
>   out:
> +    put_fid(fidp);
> +out_nofid:
>       complete_pdu(pdu->s, pdu, err);
>       v9fs_string_free(&fullname);
>       v9fs_string_free(&name);
> @@ -2511,15 +2570,15 @@ static void v9fs_xattrwalk(void *opaque)
>       size_t offset = 7;
>       int32_t fid, newfid;
>       V9fsFidState *file_fidp;
> -    V9fsFidState *xattr_fidp;
> +    V9fsFidState *xattr_fidp = NULL;
>       V9fsPDU *pdu = opaque;
>       V9fsState *s = pdu->s;
>
>       pdu_unmarshal(pdu, offset, "dds",&fid,&newfid,&name);
> -    file_fidp = lookup_fid(s, fid);
> +    file_fidp = get_fid(s, fid);
>       if (file_fidp == NULL) {
>           err = -ENOENT;
> -        goto out;
> +        goto out_nofid;
>       }
>       xattr_fidp = alloc_fid(s, newfid);
>       if (xattr_fidp == NULL) {
> @@ -2534,7 +2593,9 @@ static void v9fs_xattrwalk(void *opaque)
>           size = v9fs_co_llistxattr(s,&xattr_fidp->path, NULL, 0);
>           if (size<  0) {
>               err = size;
> +            put_fid(xattr_fidp);
>               free_fid(s, xattr_fidp->fid);
> +            xattr_fidp = NULL;
>               goto out;
>           }
>           /*
> @@ -2549,7 +2610,9 @@ static void v9fs_xattrwalk(void *opaque)
>                                        xattr_fidp->fs.xattr.value,
>                                        xattr_fidp->fs.xattr.len);
>               if (err<  0) {
> +                put_fid(xattr_fidp);
>                   free_fid(s, xattr_fidp->fid);
> +                xattr_fidp = NULL;
>                   goto out;
>               }
>           }
> @@ -2564,7 +2627,9 @@ static void v9fs_xattrwalk(void *opaque)
>                                    &name, NULL, 0);
>           if (size<  0) {
>               err = size;
> +            put_fid(xattr_fidp);
>               free_fid(s, xattr_fidp->fid);
> +            xattr_fidp = NULL;
>               goto out;
>           }
>           /*
> @@ -2579,7 +2644,9 @@ static void v9fs_xattrwalk(void *opaque)
>                                       &name, xattr_fidp->fs.xattr.value,
>                                       xattr_fidp->fs.xattr.len);
>               if (err<  0) {
> +                put_fid(xattr_fidp);
>                   free_fid(s, xattr_fidp->fid);
> +                xattr_fidp = NULL;
>                   goto out;
>               }
>           }
> @@ -2587,6 +2654,11 @@ static void v9fs_xattrwalk(void *opaque)
>           err = offset;
>       }
>   out:
> +    put_fid(file_fidp);
> +    if (xattr_fidp) {
> +        put_fid(xattr_fidp);
> +    }
> +out_nofid:
>       complete_pdu(s, pdu, err);
>       v9fs_string_free(&name);
>   }
> @@ -2607,10 +2679,10 @@ static void v9fs_xattrcreate(void *opaque)
>       pdu_unmarshal(pdu, offset, "dsqd",
>                     &fid,&name,&size,&flags);
>
> -    file_fidp = lookup_fid(s, fid);
> +    file_fidp = get_fid(s, fid);
>       if (file_fidp == NULL) {
>           err = -EINVAL;
> -        goto out;
> +        goto out_nofid;
>       }
>       /* Make the file fid point to xattr */
>       xattr_fidp = file_fidp;
> @@ -2626,7 +2698,8 @@ static void v9fs_xattrcreate(void *opaque)
>           xattr_fidp->fs.xattr.value = NULL;
>       }
>       err = offset;
> -out:
> +    put_fid(file_fidp);
> +out_nofid:
>       complete_pdu(s, pdu, err);
>       v9fs_string_free(&name);
>   }
> @@ -2641,10 +2714,10 @@ static void v9fs_readlink(void *opaque)
>       V9fsFidState *fidp;
>
>       pdu_unmarshal(pdu, offset, "d",&fid);
> -    fidp = lookup_fid(pdu->s, fid);
> +    fidp = get_fid(pdu->s, fid);
>       if (fidp == NULL) {
>           err = -ENOENT;
> -        goto out;
> +        goto out_nofid;
>       }
>
>       v9fs_string_init(&target);
> @@ -2656,6 +2729,8 @@ static void v9fs_readlink(void *opaque)
>       err = offset;
>       v9fs_string_free(&target);
>   out:
> +    put_fid(fidp);
> +out_nofid:
>       complete_pdu(pdu->s, pdu, err);
>   }
>
> diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h
> index 1d8c1b1..ce93c20 100644
> --- a/hw/9pfs/virtio-9p.h
> +++ b/hw/9pfs/virtio-9p.h
> @@ -203,6 +203,7 @@ struct V9fsFidState
>   	V9fsXattr xattr;
>       } fs;
>       uid_t uid;
> +    int ref;
>       V9fsFidState *next;
>   };
>
> @@ -361,5 +362,11 @@ static inline size_t do_pdu_unpack(void *dst, struct iovec *sg, int sg_count,
>       return pdu_packunpack(dst, sg, sg_count, offset, size, 0);
>   }
>
> +static inline void put_fid(V9fsFidState *fidp)
> +{
> +    BUG_ON(!fidp->ref);
> +    fidp->ref--;
> +}
> +
>   extern void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq);
>   #endif

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [PATCH 2/6] hw/9pfs: Don't free fid in clunk
  2011-06-06 17:16 ` [Qemu-devel] [PATCH 2/6] hw/9pfs: Don't free fid in clunk Aneesh Kumar K.V
@ 2011-06-10  0:27   ` Venkateswararao Jujjuri
  2011-06-10  6:19     ` Aneesh Kumar K.V
  0 siblings, 1 reply; 14+ messages in thread
From: Venkateswararao Jujjuri @ 2011-06-10  0:27 UTC (permalink / raw)
  To: Aneesh Kumar K.V; +Cc: aliguori, qemu-devel

On 06/06/2011 10:16 AM, Aneesh Kumar K.V wrote:
> On interrupted syscall on client we can end up having fid
> being acted upon by glib pool but still get a clunk request on that

Couple of comments below.

- JV

> Signed-off-by: Aneesh Kumar K.V<aneesh.kumar@linux.vnet.ibm.com>
> ---
>   hw/9pfs/virtio-9p.c |  139 +++++++++++++++++++++++++++-----------------------
>   hw/9pfs/virtio-9p.h |    7 +--
>   2 files changed, 76 insertions(+), 70 deletions(-)
>
> diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
> index 03d8664..f3127a5 100644
> --- a/hw/9pfs/virtio-9p.c
> +++ b/hw/9pfs/virtio-9p.c
> @@ -237,12 +237,11 @@ static V9fsFidState *get_fid(V9fsState *s, int32_t fid)
>       V9fsFidState *f;
>
>       for (f = s->fid_list; f; f = f->next) {
> -        if (f->fid == fid) {
> +        if (f->fid == fid&&  !f->clunked) {
>               f->ref++;
>               return f;
>           }
>       }
> -
>       return NULL;
>   }
>
> @@ -250,12 +249,12 @@ static V9fsFidState *alloc_fid(V9fsState *s, int32_t fid)
>   {
>       V9fsFidState *f;
>
> -    f = get_fid(s, fid);
> -    if (f) {
> -        f->ref--;
> -        return NULL;
> +    for (f = s->fid_list; f; f = f->next) {
> +        /* If fid is already there return NULL */
> +        if (f->fid == fid&&  !f->clunked) {
> +            return NULL;
> +        }
>       }
> -
>       f = qemu_mallocz(sizeof(V9fsFidState));
Memory leak if we find a cluncked fid here?
More than that how do you handle this?
>       f->fid = fid;
>       f->fid_type = P9_FID_NONE;
> @@ -300,9 +299,33 @@ free_value:
>       return retval;
>   }
>
> -static int free_fid(V9fsState *s, int32_t fid)
> +static int release_fid(V9fsState *s, V9fsFidState *fidp)
>   {
>       int retval = 0;
> +
> +    if (fidp->fid_type == P9_FID_FILE) {
> +        retval = v9fs_co_close(s, fidp);
> +    } else if (fidp->fid_type == P9_FID_DIR) {
> +        retval = v9fs_co_closedir(s, fidp);
> +    } else if (fidp->fid_type == P9_FID_XATTR) {
> +        retval = v9fs_xattr_fid_clunk(s, fidp);
> +    }
> +    v9fs_string_free(&fidp->path);
> +    qemu_free(fidp);
> +    return retval;
> +}
> +
> +static void put_fid(V9fsState *s, V9fsFidState *fidp)
> +{
> +    BUG_ON(!fidp->ref);
> +    fidp->ref--;
> +    if (!fidp->ref&&  fidp->clunked) {
> +        release_fid(s, fidp);
> +    }
> +}
> +
> +static int free_fid(V9fsState *s, int32_t fid)
With the changed semantics; I would suggest you to swap the names of
release_fid() and free_fid()

Or even better
free_fid() -> clunk_fid()
release_fid() -> free_fid()
> +{
>       V9fsFidState **fidpp, *fidp;
>
>       for (fidpp =&s->fid_list; *fidpp; fidpp =&(*fidpp)->next) {
> @@ -314,20 +337,10 @@ static int free_fid(V9fsState *s, int32_t fid)
>       if (*fidpp == NULL) {
>           return -ENOENT;
>       }
> -
>       fidp = *fidpp;
>       *fidpp = fidp->next;
> -
> -    if (fidp->fid_type == P9_FID_FILE) {
> -        retval = v9fs_co_close(s, fidp);
> -    } else if (fidp->fid_type == P9_FID_DIR) {
> -        retval = v9fs_co_closedir(s, fidp);
> -    } else if (fidp->fid_type == P9_FID_XATTR) {
> -        retval = v9fs_xattr_fid_clunk(s, fidp);
> -    }
> -    v9fs_string_free(&fidp->path);
> -    qemu_free(fidp);
> -    return retval;
> +    fidp->clunked = 1;
> +    return 0;
>   }
>
>   #define P9_QID_TYPE_DIR         0x80
> @@ -1022,14 +1035,13 @@ static void v9fs_attach(void *opaque)
>       err = fid_to_qid(s, fidp,&qid);
>       if (err<  0) {
>           err = -EINVAL;
> -        put_fid(fidp);
>           free_fid(s, fid);
> -        goto out_nofid;
> +        goto out;
>       }
>       offset += pdu_marshal(pdu, offset, "Q",&qid);
>       err = offset;
> -    put_fid(fidp);
> -
> +out:
> +    put_fid(s, fidp);
>   out_nofid:
>       complete_pdu(s, pdu, err);
>       v9fs_string_free(&uname);
> @@ -1066,7 +1078,7 @@ static void v9fs_stat(void *opaque)
>       err = offset;
>       v9fs_stat_free(&v9stat);
>   out:
> -    put_fid(fidp);
> +    put_fid(s, fidp);
>   out_nofid:
>       complete_pdu(s, pdu, err);
>   }
> @@ -1102,7 +1114,7 @@ static void v9fs_getattr(void *opaque)
>       retval = offset;
>       retval += pdu_marshal(pdu, offset, "A",&v9stat_dotl);
>   out:
> -    put_fid(fidp);
> +    put_fid(s, fidp);
>   out_nofid:
>       complete_pdu(s, pdu, retval);
>   }
> @@ -1196,7 +1208,7 @@ static void v9fs_setattr(void *opaque)
>       }
>       err = offset;
>   out:
> -    put_fid(fidp);
> +    put_fid(s, fidp);
>   out_nofid:
>       complete_pdu(s, pdu, err);
>   }
> @@ -1279,9 +1291,7 @@ static void v9fs_walk(void *opaque)
>               v9fs_string_copy(&newfidp->path,&path);
>               err = v9fs_co_lstat(s,&newfidp->path,&stbuf);
>               if (err<  0) {
> -                put_fid(newfidp);
>                   free_fid(s, newfidp->fid);
> -                newfidp = NULL;
>                   v9fs_string_free(&path);
>                   goto out;
>               }
> @@ -1291,9 +1301,9 @@ static void v9fs_walk(void *opaque)
>       }
>       err = v9fs_walk_marshal(pdu, nwnames, qids);
>   out:
> -    put_fid(fidp);
> +    put_fid(s, fidp);
>       if (newfidp) {
> -        put_fid(newfidp);
> +        put_fid(s, newfidp);
>       }
>   out_nofid:
>       complete_pdu(s, pdu, err);
> @@ -1383,7 +1393,7 @@ static void v9fs_open(void *opaque)
>           err = offset;
>       }
>   out:
> -    put_fid(fidp);
> +    put_fid(s, fidp);
>   out_nofid:
>       complete_pdu(s, pdu, err);
>   }
> @@ -1437,7 +1447,7 @@ static void v9fs_lcreate(void *opaque)
>       offset += pdu_marshal(pdu, offset, "Qd",&qid, iounit);
>       err = offset;
>   out:
> -    put_fid(fidp);
> +    put_fid(pdu->s, fidp);
>   out_nofid:
>       complete_pdu(pdu->s, pdu, err);
>       v9fs_string_free(&name);
> @@ -1465,7 +1475,7 @@ static void v9fs_fsync(void *opaque)
>           err = offset;
>       }
>   out:
> -    put_fid(fidp);
> +    put_fid(s, fidp);
>       complete_pdu(s, pdu, err);
>   }
>
> @@ -1474,16 +1484,25 @@ static void v9fs_clunk(void *opaque)
>       int err;
>       int32_t fid;
>       size_t offset = 7;
> +    V9fsFidState *fidp;
>       V9fsPDU *pdu = opaque;
>       V9fsState *s = pdu->s;
>
>       pdu_unmarshal(pdu, offset, "d",&fid);
> -    err = free_fid(s, fid);
> +
> +    fidp = get_fid(s, fid);
> +    if (fidp == NULL) {
> +        err = -ENOENT;
> +        goto out_nofid;
> +    }
> +    err = free_fid(s, fidp->fid);
>       if (err<  0) {
>           goto out;
>       }
>       err = offset;
>   out:
> +    put_fid(s, fidp);
> +out_nofid:
>       complete_pdu(s, pdu, err);
>   }
>
> @@ -1638,7 +1657,7 @@ static void v9fs_read(void *opaque)
>           err = -EINVAL;
>       }
>   out:
> -    put_fid(fidp);
> +    put_fid(s, fidp);
>   out_nofid:
>       complete_pdu(s, pdu, err);
>   }
> @@ -1747,7 +1766,7 @@ static void v9fs_readdir(void *opaque)
>       retval += pdu_marshal(pdu, offset, "d", count);
>       retval += count;
>   out:
> -    put_fid(fidp);
> +    put_fid(s, fidp);
>   out_nofid:
>       complete_pdu(s, pdu, retval);
>   }
> @@ -1857,7 +1876,7 @@ static void v9fs_write(void *opaque)
>       offset += pdu_marshal(pdu, offset, "d", total);
>       err = offset;
>   out:
> -    put_fid(fidp);
> +    put_fid(s, fidp);
>   out_nofid:
>       complete_pdu(s, pdu, err);
>   }
> @@ -1923,10 +1942,10 @@ static void v9fs_create(void *opaque)
>           }
>           err = v9fs_co_link(pdu->s,&nfidp->path,&fullname);
>           if (err<  0) {
> -            put_fid(nfidp);
> +            put_fid(pdu->s, nfidp);
>               goto out;
>           }
> -        put_fid(nfidp);
> +        put_fid(pdu->s, nfidp);
>       } else if (perm&  P9_STAT_MODE_DEVICE) {
>           char ctype;
>           uint32_t major, minor;
> @@ -1990,7 +2009,7 @@ static void v9fs_create(void *opaque)
>       err = offset;
>
>   out:
> -    put_fid(fidp);
> +    put_fid(pdu->s, fidp);
>   out_nofid:
>      complete_pdu(pdu->s, pdu, err);
>      v9fs_string_free(&name);
> @@ -2035,7 +2054,7 @@ static void v9fs_symlink(void *opaque)
>       offset += pdu_marshal(pdu, offset, "Q",&qid);
>       err = offset;
>   out:
> -    put_fid(dfidp);
> +    put_fid(pdu->s, dfidp);
>   out_nofid:
>       complete_pdu(pdu->s, pdu, err);
>       v9fs_string_free(&name);
> @@ -2086,7 +2105,7 @@ static void v9fs_link(void *opaque)
>       v9fs_string_free(&fullname);
>
>   out:
> -    put_fid(dfidp);
> +    put_fid(s, dfidp);
>   out_nofid:
>       v9fs_string_free(&name);
>       complete_pdu(s, pdu, err);
> @@ -2113,8 +2132,8 @@ static void v9fs_remove(void *opaque)
>       }
>
>       /* For TREMOVE we need to clunk the fid even on failed remove */
> -    put_fid(fidp);
>       free_fid(pdu->s, fidp->fid);
> +    put_fid(pdu->s, fidp);
>   out_nofid:
>       complete_pdu(pdu->s, pdu, err);
>   }
> @@ -2185,7 +2204,7 @@ static int v9fs_complete_rename(V9fsState *s, V9fsFidState *fidp,
>       }
>   out:
>       if (dirfidp) {
> -        put_fid(dirfidp);
> +        put_fid(s, dirfidp);
>       }
>   out_nofid:
>       return err;
> @@ -2216,7 +2235,7 @@ static void v9fs_rename(void *opaque)
>           err = offset;
>       }
>   out:
> -    put_fid(fidp);
> +    put_fid(s, fidp);
>   out_nofid:
>       complete_pdu(s, pdu, err);
>       v9fs_string_free(&name);
> @@ -2305,7 +2324,7 @@ static void v9fs_wstat(void *opaque)
>       }
>       err = offset;
>   out:
> -    put_fid(fidp);
> +    put_fid(s, fidp);
>   out_nofid:
>       v9fs_stat_free(&v9stat);
>       complete_pdu(s, pdu, err);
> @@ -2379,7 +2398,7 @@ static void v9fs_statfs(void *opaque)
>       retval = offset;
>       retval += v9fs_fill_statfs(s, pdu,&stbuf);
>   out:
> -    put_fid(fidp);
> +    put_fid(s, fidp);
>   out_nofid:
>       complete_pdu(s, pdu, retval);
>       return;
> @@ -2425,7 +2444,7 @@ static void v9fs_mknod(void *opaque)
>       err = offset;
>       err += pdu_marshal(pdu, offset, "Q",&qid);
>   out:
> -    put_fid(fidp);
> +    put_fid(s, fidp);
>   out_nofid:
>       complete_pdu(s, pdu, err);
>       v9fs_string_free(&fullname);
> @@ -2473,7 +2492,7 @@ static void v9fs_lock(void *opaque)
>       }
>       status = P9_LOCK_SUCCESS;
>   out:
> -    put_fid(fidp);
> +    put_fid(s, fidp);
>   out_nofid:
>       err = offset;
>       err += pdu_marshal(pdu, offset, "b", status);
> @@ -2515,7 +2534,7 @@ static void v9fs_getlock(void *opaque)
>                             &glock->client_id);
>       err = offset;
>   out:
> -    put_fid(fidp);
> +    put_fid(s, fidp);
>   out_nofid:
>       complete_pdu(s, pdu, err);
>       qemu_free(glock);
> @@ -2555,7 +2574,7 @@ static void v9fs_mkdir(void *opaque)
>       offset += pdu_marshal(pdu, offset, "Q",&qid);
>       err = offset;
>   out:
> -    put_fid(fidp);
> +    put_fid(pdu->s, fidp);
>   out_nofid:
>       complete_pdu(pdu->s, pdu, err);
>       v9fs_string_free(&fullname);
> @@ -2593,9 +2612,7 @@ static void v9fs_xattrwalk(void *opaque)
>           size = v9fs_co_llistxattr(s,&xattr_fidp->path, NULL, 0);
>           if (size<  0) {
>               err = size;
> -            put_fid(xattr_fidp);
>               free_fid(s, xattr_fidp->fid);
> -            xattr_fidp = NULL;
>               goto out;
>           }
>           /*
> @@ -2610,9 +2627,7 @@ static void v9fs_xattrwalk(void *opaque)
>                                        xattr_fidp->fs.xattr.value,
>                                        xattr_fidp->fs.xattr.len);
>               if (err<  0) {
> -                put_fid(xattr_fidp);
>                   free_fid(s, xattr_fidp->fid);
> -                xattr_fidp = NULL;
>                   goto out;
>               }
>           }
> @@ -2627,9 +2642,7 @@ static void v9fs_xattrwalk(void *opaque)
>                                    &name, NULL, 0);
>           if (size<  0) {
>               err = size;
> -            put_fid(xattr_fidp);
>               free_fid(s, xattr_fidp->fid);
> -            xattr_fidp = NULL;
>               goto out;
>           }
>           /*
> @@ -2644,9 +2657,7 @@ static void v9fs_xattrwalk(void *opaque)
>                                       &name, xattr_fidp->fs.xattr.value,
>                                       xattr_fidp->fs.xattr.len);
>               if (err<  0) {
> -                put_fid(xattr_fidp);
>                   free_fid(s, xattr_fidp->fid);
> -                xattr_fidp = NULL;
>                   goto out;
>               }
>           }
> @@ -2654,9 +2665,9 @@ static void v9fs_xattrwalk(void *opaque)
>           err = offset;
>       }
>   out:
> -    put_fid(file_fidp);
> +    put_fid(s, file_fidp);
>       if (xattr_fidp) {
> -        put_fid(xattr_fidp);
> +        put_fid(s, xattr_fidp);
>       }
>   out_nofid:
>       complete_pdu(s, pdu, err);
> @@ -2698,7 +2709,7 @@ static void v9fs_xattrcreate(void *opaque)
>           xattr_fidp->fs.xattr.value = NULL;
>       }
>       err = offset;
> -    put_fid(file_fidp);
> +    put_fid(s, file_fidp);
>   out_nofid:
>       complete_pdu(s, pdu, err);
>       v9fs_string_free(&name);
> @@ -2729,7 +2740,7 @@ static void v9fs_readlink(void *opaque)
>       err = offset;
>       v9fs_string_free(&target);
>   out:
> -    put_fid(fidp);
> +    put_fid(pdu->s, fidp);
>   out_nofid:
>       complete_pdu(pdu->s, pdu, err);
>   }
> diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h
> index ce93c20..e16e5f4 100644
> --- a/hw/9pfs/virtio-9p.h
> +++ b/hw/9pfs/virtio-9p.h
> @@ -204,6 +204,7 @@ struct V9fsFidState
>       } fs;
>       uid_t uid;
>       int ref;
> +    int clunked;
>       V9fsFidState *next;
>   };
>
> @@ -362,11 +363,5 @@ static inline size_t do_pdu_unpack(void *dst, struct iovec *sg, int sg_count,
>       return pdu_packunpack(dst, sg, sg_count, offset, size, 0);
>   }
>
> -static inline void put_fid(V9fsFidState *fidp)
> -{
> -    BUG_ON(!fidp->ref);
> -    fidp->ref--;
> -}
> -
>   extern void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq);
>   #endif

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [PATCH 3/6] hw/9pfs: Add file descriptor reclaim support
  2011-06-06 17:16 ` [Qemu-devel] [PATCH 3/6] hw/9pfs: Add file descriptor reclaim support Aneesh Kumar K.V
@ 2011-06-10  1:27   ` Venkateswararao Jujjuri
  0 siblings, 0 replies; 14+ messages in thread
From: Venkateswararao Jujjuri @ 2011-06-10  1:27 UTC (permalink / raw)
  To: Aneesh Kumar K.V; +Cc: aliguori, qemu-devel

On 06/06/2011 10:16 AM, Aneesh Kumar K.V wrote:
> Signed-off-by: Aneesh Kumar K.V<aneesh.kumar@linux.vnet.ibm.com>
Minor comments below; I think this looks good.

Reviewed-by : Venkateswararao Jujjuri <jvrao@linux.vnet.ibm.com>

> ---
>   hw/9pfs/codir.c            |    4 +-
>   hw/9pfs/cofile.c           |   19 ++++-
>   hw/9pfs/virtio-9p-coth.h   |    4 +-
>   hw/9pfs/virtio-9p-device.c |    1 +
>   hw/9pfs/virtio-9p.c        |  193 +++++++++++++++++++++++++++++++++++++++++++-
>   hw/9pfs/virtio-9p.h        |   23 +++++-
>   6 files changed, 229 insertions(+), 15 deletions(-)
>
> diff --git a/hw/9pfs/codir.c b/hw/9pfs/codir.c
> index 783d279..3347038 100644
> --- a/hw/9pfs/codir.c
> +++ b/hw/9pfs/codir.c
> @@ -101,12 +101,10 @@ int v9fs_co_opendir(V9fsState *s, V9fsFidState *fidp)
>       return err;
>   }
>
> -int v9fs_co_closedir(V9fsState *s, V9fsFidState *fidp)
> +int v9fs_co_closedir(V9fsState *s, DIR *dir)
>   {
>       int err;
> -    DIR *dir;
>
> -    dir = fidp->fs.dir;
>       v9fs_co_run_in_worker(
>           {
>               err = s->ops->closedir(&s->ctx, dir);
> diff --git a/hw/9pfs/cofile.c b/hw/9pfs/cofile.c
> index e388146..0caf1e3 100644
> --- a/hw/9pfs/cofile.c
> +++ b/hw/9pfs/cofile.c
> @@ -58,6 +58,12 @@ int v9fs_co_open(V9fsState *s, V9fsFidState *fidp, int flags)
>                   err = 0;
>               }
>           });
> +    if (!err) {
> +        total_open_fd++;
> +        if (total_open_fd>  open_fd_hw) {
> +            v9fs_reclaim_fd(s);
> +        }
> +    }
>       return err;
>   }
>
> @@ -79,15 +85,19 @@ int v9fs_co_open2(V9fsState *s, V9fsFidState *fidp, char *fullname, gid_t gid,
>                   err = -errno;
>               }
>           });
> +    if (!err) {
> +        total_open_fd++;
> +        if (total_open_fd>  open_fd_hw) {
> +            v9fs_reclaim_fd(s);
> +        }
> +    }
>       return err;
>   }
>
> -int v9fs_co_close(V9fsState *s, V9fsFidState *fidp)
> +int v9fs_co_close(V9fsState *s, int fd)
>   {
> -    int fd;
>       int err;
>
> -    fd = fidp->fs.fd;
>       v9fs_co_run_in_worker(
>           {
>               err = s->ops->close(&s->ctx, fd);
> @@ -95,6 +105,9 @@ int v9fs_co_close(V9fsState *s, V9fsFidState *fidp)
>                   err = -errno;
>               }
>           });
> +    if (!err) {
> +        total_open_fd--;
> +    }
>       return err;
>   }
>
> diff --git a/hw/9pfs/virtio-9p-coth.h b/hw/9pfs/virtio-9p-coth.h
> index 48defb7..b7be9b5 100644
> --- a/hw/9pfs/virtio-9p-coth.h
> +++ b/hw/9pfs/virtio-9p-coth.h
> @@ -83,8 +83,8 @@ extern int v9fs_co_open2(V9fsState *, V9fsFidState *, char *, gid_t, int, int);
>   extern int v9fs_co_lsetxattr(V9fsState *, V9fsString *, V9fsString *,
>                                void *, size_t, int);
>   extern int v9fs_co_lremovexattr(V9fsState *, V9fsString *, V9fsString *);
> -extern int v9fs_co_closedir(V9fsState *, V9fsFidState *);
> -extern int v9fs_co_close(V9fsState *, V9fsFidState *);
> +extern int v9fs_co_closedir(V9fsState *, DIR *);
> +extern int v9fs_co_close(V9fsState *, int);
>   extern int v9fs_co_fsync(V9fsState *, V9fsFidState *, int);
>   extern int v9fs_co_symlink(V9fsState *, V9fsFidState *, const char *,
>                              const char *, gid_t);
> diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c
> index 7811103..70629b2 100644
> --- a/hw/9pfs/virtio-9p-device.c
> +++ b/hw/9pfs/virtio-9p-device.c
> @@ -171,6 +171,7 @@ static PCIDeviceInfo virtio_9p_info = {
>   static void virtio_9p_register_devices(void)
>   {
>       pci_qdev_register(&virtio_9p_info);
> +    virtio_9p_set_fd_limit();
>   }
>
>   device_init(virtio_9p_register_devices)
> diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
> index f3127a5..21e07fb 100644
> --- a/hw/9pfs/virtio-9p.c
> +++ b/hw/9pfs/virtio-9p.c
> @@ -22,6 +22,9 @@
>   #include "virtio-9p-coth.h"
>
>   int debug_9p_pdu;
> +int open_fd_hw;
> +int total_open_fd;
> +static int open_fd_rc;
>
>   enum {
>       Oread   = 0x00,
> @@ -234,11 +237,40 @@ static size_t v9fs_string_size(V9fsString *str)
>
>   static V9fsFidState *get_fid(V9fsState *s, int32_t fid)
>   {
> +    int err;
>       V9fsFidState *f;
>
>       for (f = s->fid_list; f; f = f->next) {
>           if (f->fid == fid&&  !f->clunked) {
> +            /*
> +             * Update the fid ref upfront so that
> +             * we don't get reclaimed when we yield
> +             * in open later.
> +             */
>               f->ref++;
> +
> +            /*
> +             * check whether we need to reopen the
> +             * file. We might have closed the fd
> +             * while trying to free up some file
> +             * descriptors.
> +             */
> +            if (f->fid_type == P9_FID_FILE) {
> +                if (f->fs.fd == -1) {
> +                    do {
> +                        err = v9fs_co_open(s, f, f->open_flags);
> +                    } while (err == -EINTR);
> +                    if (err<  0) {
> +                        f->ref--;
> +                        return NULL;
> +                    }
> +                }
> +            }
> +            /*
> +             * Mark the fid as referenced so that the LRU
> +             * reclaim won't close the file descriptor
> +             */
> +            f->flags |= FID_REFERENCED;
>               return f;
>           }
>       }
> @@ -259,6 +291,11 @@ static V9fsFidState *alloc_fid(V9fsState *s, int32_t fid)
>       f->fid = fid;
>       f->fid_type = P9_FID_NONE;
>       f->ref = 1;
> +    /*
> +     * Mark the fid as referenced so that the LRU
> +     * reclaim won't close the file descriptor
> +     */
> +    f->flags |= FID_REFERENCED;
>       f->next = s->fid_list;
>       s->fid_list = f;
>
> @@ -304,9 +341,12 @@ static int release_fid(V9fsState *s, V9fsFidState *fidp)
>       int retval = 0;
>
>       if (fidp->fid_type == P9_FID_FILE) {
> -        retval = v9fs_co_close(s, fidp);
> +        /* If we reclaimed the fd no need to close */
> +        if (fidp->fs.fd != -1) {
> +            retval = v9fs_co_close(s, fidp->fs.fd);
> +        }
>       } else if (fidp->fid_type == P9_FID_DIR) {
> -        retval = v9fs_co_closedir(s, fidp);
> +        retval = v9fs_co_closedir(s, fidp->fs.dir);
>       } else if (fidp->fid_type == P9_FID_XATTR) {
>           retval = v9fs_xattr_fid_clunk(s, fidp);
>       }
> @@ -319,7 +359,10 @@ static void put_fid(V9fsState *s, V9fsFidState *fidp)
>   {
>       BUG_ON(!fidp->ref);
>       fidp->ref--;
> -    if (!fidp->ref&&  fidp->clunked) {
> +    /*
> +     * Don't free the fid if it is in reclaim list
> +     */
> +    if (!fidp->ref&&  fidp->clunked&&  !fidp->rclm_lst) {
>           release_fid(s, fidp);
>       }
>   }
> @@ -343,6 +386,105 @@ static int free_fid(V9fsState *s, int32_t fid)
>       return 0;
>   }
>
> +void v9fs_reclaim_fd(V9fsState *s)
> +{
> +    int reclaim_count = 0;
> +    V9fsFidState *f, head_fid, *reclaim_list = NULL;
> +
> +    /*
> +     * We don't want multiple coroutine to do reclaim
> +     */
> +    if (s->reclaim_in_prgs) {
> +        return;
> +    }
> +    s->reclaim_in_prgs = 1;
> +
> +    head_fid.next = s->fid_list;
> +    for (f = s->fid_list; f; f = f->next) {
> +        /*
> +         * Unlink fids cannot be reclaimed. Check
> +         * for them and skip them. Also skip fids
> +         * currently being operated on.
> +         */
> +        if (f->ref || f->flags&  FID_NON_RECLAIMABLE) {
> +            continue;
> +        }
> +        /*
> +         * if it is a recently referenced fid
> +         * we leave the fid untouched and clear the
> +         * reference bit. We come back to it later
> +         * in the next iteration. (a simple LRU without
> +         * moving list elements around)
> +         */
> +        if (f->flags&  FID_REFERENCED) {
> +            f->flags&= ~FID_REFERENCED;
> +            continue;
> +        }
> +        /*
> +         * Add fids to reclaim list.
> +         */
> +        if (f->fid_type == P9_FID_FILE) {
> +            if (f->fs.fd != -1) {
> +                f->rclm_lst = reclaim_list;
> +                reclaim_list = f;
> +                f->fs_reclaim.fd = f->fs.fd;
> +                f->fs.fd = -1;
> +                reclaim_count++;
> +            }
> +        }
> +        if (reclaim_count>= open_fd_rc) {
> +            break;
> +        }
> +    }
> +    /*
> +     * Now close the fid in reclaim list. Free them if they
> +     * are already clunked.
> +     */
> +    while (reclaim_list) {
> +        f = reclaim_list;
> +        reclaim_list = f->rclm_lst;
> +        if (f->clunked) {
> +            release_fid(s, f);
> +        } else {
> +            if (f->fid_type == P9_FID_FILE) {
> +                v9fs_co_close(s, f->fs_reclaim.fd);
> +            }
> +            f->rclm_lst = NULL;
> +        }
> +    }
> +    s->reclaim_in_prgs = 0;
> +}
> +
> +static int v9fs_mark_fids_unreclaim(V9fsState *s, V9fsString *str)
> +{
> +    int err;
> +    V9fsFidState *fidp, head_fid;
> +
> +    head_fid.next = s->fid_list;
> +    for (fidp = s->fid_list; fidp; fidp = fidp->next) {
> +        if (!strcmp(fidp->path.data, str->data)) {
&& !( fidp->flags && FID_NON_RECLAIMABLE)  To avoid unnecessarily 
resetting the flag.
> +            /* Mark the fid non reclaimable. */
> +            fidp->flags |= FID_NON_RECLAIMABLE;
> +            /* reopen the file if already closed */
> +            if (fidp->fs.fd == -1) {
> +                do {
> +                    err = v9fs_co_open(s, fidp, fidp->open_flags);
> +                } while (err == -EINTR);
> +                if (err<  0) {
> +                    return -1;
> +                }
> +                /*
> +                 * Go back to head of fid list because
> +                 * the list could have got updated when
> +                 * switched to the worker thread
> +                 */
> +                fidp =&head_fid;
> +            }
> +        }
> +    }
> +    return 0;
> +}
> +
>   #define P9_QID_TYPE_DIR         0x80
>   #define P9_QID_TYPE_SYMLINK     0x02
>
> @@ -1388,6 +1530,14 @@ static void v9fs_open(void *opaque)
>               goto out;
>           }
>           fidp->fid_type = P9_FID_FILE;
> +        fidp->open_flags = flags;
> +        if (flags&  O_EXCL) {
> +            /*
> +             * We let the host file system do O_EXCL check
> +             * We should not reclaim such fd
> +             */
> +            fidp->flags |= FID_NON_RECLAIMABLE;
> +        }
>           iounit = get_iounit(s,&fidp->path);
>           offset += pdu_marshal(pdu, offset, "Qd",&qid, iounit);
>           err = offset;
> @@ -1432,6 +1582,14 @@ static void v9fs_lcreate(void *opaque)
>           goto out;
>       }
>       fidp->fid_type = P9_FID_FILE;
> +    fidp->open_flags = flags;
> +    if (flags&  O_EXCL) {
> +        /*
> +         * We let the host file system do O_EXCL check
> +         * We should not reclaim such fd
> +         */
> +        fidp->flags |= FID_NON_RECLAIMABLE;
> +    }
>       iounit =  get_iounit(pdu->s,&fullname);
>
>       err = v9fs_co_lstat(pdu->s,&fullname,&stbuf);
> @@ -1993,6 +2151,14 @@ static void v9fs_create(void *opaque)
>               goto out;
>           }
>           fidp->fid_type = P9_FID_FILE;
> +        fidp->open_flags = omode_to_uflags(mode);
> +        if (fidp->open_flags&  O_EXCL) {
> +            /*
> +             * We let the host file system do O_EXCL check
> +             * We should not reclaim such fd
> +             */
> +            fidp->flags |= FID_NON_RECLAIMABLE;
> +        }
>       }
>       err = v9fs_co_lstat(pdu->s,&fullname,&stbuf);
>       if (err<  0) {
> @@ -2126,11 +2292,19 @@ static void v9fs_remove(void *opaque)
>           err = -EINVAL;
>           goto out_nofid;
>       }
> +    /*
> +     * IF the file is unlinked, we cannot reopen
> +     * the file later. So don't reclaim fd
> +     */
> +    err = v9fs_mark_fids_unreclaim(pdu->s,&fidp->path);
> +    if (err<  0) {
> +        goto out_err;
> +    }
>       err = v9fs_co_remove(pdu->s,&fidp->path);
>       if (!err) {
>           err = offset;
>       }
> -
> +out_err:
>       /* For TREMOVE we need to clunk the fid even on failed remove */
>       free_fid(pdu->s, fidp->fid);
>       put_fid(pdu->s, fidp);
> @@ -2826,3 +3000,14 @@ void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq)
>       }
>       free_pdu(s, pdu);
>   }
> +
> +void virtio_9p_set_fd_limit(void)
> +{
> +    struct rlimit rlim;
> +    if (getrlimit(RLIMIT_NOFILE,&rlim)<  0) {
> +        fprintf(stderr, "Failed to get the resource limit\n");
> +        exit(1);
> +    }
> +    open_fd_hw = rlim.rlim_cur - MIN(400, rlim.rlim_cur/3);
> +    open_fd_rc = rlim.rlim_cur/2;
Why not call it LW?
> +}
> diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h
> index e16e5f4..36aa4a5 100644
> --- a/hw/9pfs/virtio-9p.h
> +++ b/hw/9pfs/virtio-9p.h
> @@ -5,6 +5,7 @@
>   #include<dirent.h>
>   #include<sys/time.h>
>   #include<utime.h>
> +#include<sys/resource.h>
>   #include "hw/virtio.h"
>   #include "fsdev/file-op-9p.h"
>
> @@ -101,6 +102,9 @@ enum p9_proto_version {
>   #define P9_NOTAG    (u16)(~0)
>   #define P9_NOFID    (u32)(~0)
>   #define P9_MAXWELEM 16
> +
> +#define FID_REFERENCED          0x1
> +#define FID_NON_RECLAIMABLE     0x2
>   static inline const char *rpath(FsContext *ctx, const char *path, char *buffer)
>   {
>       snprintf(buffer, PATH_MAX, "%s/%s", ctx->fs_root, path);
> @@ -198,14 +202,21 @@ struct V9fsFidState
>       int32_t fid;
>       V9fsString path;
>       union {
> -	int fd;
> -	DIR *dir;
> -	V9fsXattr xattr;
> +        int fd;
> +        DIR *dir;
> +        V9fsXattr xattr;
>       } fs;
> +    union {
> +        int fd;
> +        DIR *dir;
> +    } fs_reclaim;
> +    int flags;
> +    int open_flags;
>       uid_t uid;
>       int ref;
>       int clunked;
>       V9fsFidState *next;
> +    V9fsFidState *rclm_lst;
>   };
>
>   typedef struct V9fsState
> @@ -222,6 +233,7 @@ typedef struct V9fsState
>       size_t config_size;
>       enum p9_proto_version proto_version;
>       int32_t msize;
> +    int reclaim_in_prgs;
>   } V9fsState;
>
>   typedef struct V9fsStatState {
> @@ -354,6 +366,9 @@ typedef struct V9fsGetlock
>       V9fsString client_id;
>   } V9fsGetlock;
>
> +extern int open_fd_hw;
> +extern int total_open_fd;
> +
>   size_t pdu_packunpack(void *addr, struct iovec *sg, int sg_count,
>                         size_t offset, size_t size, int pack);
>
> @@ -364,4 +379,6 @@ static inline size_t do_pdu_unpack(void *dst, struct iovec *sg, int sg_count,
>   }
>
>   extern void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq);
> +extern void virtio_9p_set_fd_limit(void);
> +extern void v9fs_reclaim_fd(V9fsState *s);
>   #endif

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [PATCH 5/6] hw/9pfs: Use v9fs_do_close instead of close
  2011-06-06 17:16 ` [Qemu-devel] [PATCH 5/6] hw/9pfs: Use v9fs_do_close instead of close Aneesh Kumar K.V
@ 2011-06-10  1:32   ` Venkateswararao Jujjuri
  0 siblings, 0 replies; 14+ messages in thread
From: Venkateswararao Jujjuri @ 2011-06-10  1:32 UTC (permalink / raw)
  To: qemu-devel

On 06/06/2011 10:16 AM, Aneesh Kumar K.V wrote:
> we should use the local abstraction instead of
> directly calling close.
>
Let us fold this also into our coroutine patches.

- JV

> Signed-off-by: Aneesh Kumar K.V<aneesh.kumar@linux.vnet.ibm.com>
> ---
>   hw/9pfs/virtio-9p.c |    4 ++--
>   1 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
> index 21e07fb..d322814 100644
> --- a/hw/9pfs/virtio-9p.c
> +++ b/hw/9pfs/virtio-9p.c
> @@ -1596,7 +1596,7 @@ static void v9fs_lcreate(void *opaque)
>       if (err<  0) {
>           fidp->fid_type = P9_FID_NONE;
>           if (fidp->fs.fd>  0) {
> -            close(fidp->fs.fd);
> +            v9fs_co_close(pdu->s, fidp->fs.fd);
>           }
>           goto out;
>       }
> @@ -2164,7 +2164,7 @@ static void v9fs_create(void *opaque)
>       if (err<  0) {
>           fidp->fid_type = P9_FID_NONE;
>           if (fidp->fs.fd) {
> -            close(fidp->fs.fd);
> +            v9fs_co_close(pdu->s, fidp->fs.fd);
>           }
>           goto out;
>       }

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [PATCH 6/6] hw/9pfs: Add directory reclaim support
  2011-06-06 17:16 ` [Qemu-devel] [PATCH 6/6] hw/9pfs: Add directory reclaim support Aneesh Kumar K.V
@ 2011-06-10  1:36   ` Venkateswararao Jujjuri
  0 siblings, 0 replies; 14+ messages in thread
From: Venkateswararao Jujjuri @ 2011-06-10  1:36 UTC (permalink / raw)
  To: qemu-devel

On 06/06/2011 10:16 AM, Aneesh Kumar K.V wrote:
> Signed-off-by: Aneesh Kumar K.V<aneesh.kumar@linux.vnet.ibm.com>
Reviewed-by: Venkateswararao Jujjuri <jvrao@linux.vnet.ibm.com>

> ---
>   hw/9pfs/codir.c     |    9 +++++++++
>   hw/9pfs/virtio-9p.c |   26 ++++++++++++++++++++++++--
>   2 files changed, 33 insertions(+), 2 deletions(-)
>
> diff --git a/hw/9pfs/codir.c b/hw/9pfs/codir.c
> index 3347038..2c26f72 100644
> --- a/hw/9pfs/codir.c
> +++ b/hw/9pfs/codir.c
> @@ -98,6 +98,12 @@ int v9fs_co_opendir(V9fsState *s, V9fsFidState *fidp)
>                   err = 0;
>               }
>           });
> +    if (!err) {
> +        total_open_fd++;
> +        if (total_open_fd>  open_fd_hw) {
> +            v9fs_reclaim_fd(s);
> +        }
> +    }
>       return err;
>   }
>
> @@ -112,5 +118,8 @@ int v9fs_co_closedir(V9fsState *s, DIR *dir)
>                   err = -errno;
>               }
>           });
> +    if (!err) {
> +        total_open_fd--;
> +    }
>       return err;
>   }
> diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
> index d322814..55aca93 100644
> --- a/hw/9pfs/virtio-9p.c
> +++ b/hw/9pfs/virtio-9p.c
> @@ -265,7 +265,17 @@ static V9fsFidState *get_fid(V9fsState *s, int32_t fid)
>                           return NULL;
>                       }
>                   }
> -            }
> +            } else if (f->fid_type == P9_FID_DIR) {
> +                if (f->fs.dir == NULL) {
> +                    do {
> +                        err = v9fs_co_opendir(s, f);
> +                    } while (err == -EINTR);
> +                    if (err<  0) {
> +                        f->ref--;
> +                        return NULL;
> +                    }
> +                }
> +             }
>               /*
>                * Mark the fid as referenced so that the LRU
>                * reclaim won't close the file descriptor
> @@ -346,7 +356,9 @@ static int release_fid(V9fsState *s, V9fsFidState *fidp)
>               retval = v9fs_co_close(s, fidp->fs.fd);
>           }
>       } else if (fidp->fid_type == P9_FID_DIR) {
> -        retval = v9fs_co_closedir(s, fidp->fs.dir);
> +        if (fidp->fs.dir != NULL) {
> +            retval = v9fs_co_closedir(s, fidp->fs.dir);
> +        }
>       } else if (fidp->fid_type == P9_FID_XATTR) {
>           retval = v9fs_xattr_fid_clunk(s, fidp);
>       }
> @@ -431,6 +443,14 @@ void v9fs_reclaim_fd(V9fsState *s)
>                   f->fs.fd = -1;
>                   reclaim_count++;
>               }
> +        } else if (f->fid_type == P9_FID_DIR) {
> +            if (f->fs.dir != NULL) {
> +                f->rclm_lst = reclaim_list;
> +                reclaim_list = f;
> +                f->fs_reclaim.dir = f->fs.dir;
> +                f->fs.dir = NULL;
> +                reclaim_count++;
> +            }
>           }
>           if (reclaim_count>= open_fd_rc) {
>               break;
> @@ -448,6 +468,8 @@ void v9fs_reclaim_fd(V9fsState *s)
>           } else {
>               if (f->fid_type == P9_FID_FILE) {
>                   v9fs_co_close(s, f->fs_reclaim.fd);
> +            } else if (f->fid_type == P9_FID_DIR) {
> +                v9fs_co_closedir(s, f->fs_reclaim.dir);
>               }
>               f->rclm_lst = NULL;
>           }

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [PATCH 2/6] hw/9pfs: Don't free fid in clunk
  2011-06-10  0:27   ` Venkateswararao Jujjuri
@ 2011-06-10  6:19     ` Aneesh Kumar K.V
  0 siblings, 0 replies; 14+ messages in thread
From: Aneesh Kumar K.V @ 2011-06-10  6:19 UTC (permalink / raw)
  To: Venkateswararao Jujjuri; +Cc: aliguori, qemu-devel

On Thu, 09 Jun 2011 17:27:00 -0700, Venkateswararao Jujjuri <jvrao@linux.vnet.ibm.com> wrote:
> On 06/06/2011 10:16 AM, Aneesh Kumar K.V wrote:
> > On interrupted syscall on client we can end up having fid
> > being acted upon by glib pool but still get a clunk request on that
> 
> Couple of comments below.
> 
> - JV
> 
> > Signed-off-by: Aneesh Kumar K.V<aneesh.kumar@linux.vnet.ibm.com>
> > ---
> >   hw/9pfs/virtio-9p.c |  139 +++++++++++++++++++++++++++-----------------------
> >   hw/9pfs/virtio-9p.h |    7 +--
> >   2 files changed, 76 insertions(+), 70 deletions(-)
> >
> > diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
> > index 03d8664..f3127a5 100644
> > --- a/hw/9pfs/virtio-9p.c
> > +++ b/hw/9pfs/virtio-9p.c
> > @@ -237,12 +237,11 @@ static V9fsFidState *get_fid(V9fsState *s, int32_t fid)
> >       V9fsFidState *f;
> >
> >       for (f = s->fid_list; f; f = f->next) {
> > -        if (f->fid == fid) {
> > +        if (f->fid == fid&&  !f->clunked) {
> >               f->ref++;
> >               return f;
> >           }
> >       }
> > -
> >       return NULL;
> >   }
> >
> > @@ -250,12 +249,12 @@ static V9fsFidState *alloc_fid(V9fsState *s, int32_t fid)
> >   {
> >       V9fsFidState *f;
> >
> > -    f = get_fid(s, fid);
> > -    if (f) {
> > -        f->ref--;
> > -        return NULL;
> > +    for (f = s->fid_list; f; f = f->next) {
> > +        /* If fid is already there return NULL */
> > +        if (f->fid == fid&&  !f->clunked) {
> > +            return NULL;
> > +        }
> >       }
> > -
> >       f = qemu_mallocz(sizeof(V9fsFidState));
> Memory leak if we find a cluncked fid here?
> More than that how do you handle this?

clunk request happening parallel to alloc request ? is that 
possible. Only when the alloc succeed the client will find the
fid initialized and only on initialized fid we send clunk request.

> >       f->fid = fid;
> >       f->fid_type = P9_FID_NONE;
> > @@ -300,9 +299,33 @@ free_value:
> >       return retval;
> >   }
> >
> > -static int free_fid(V9fsState *s, int32_t fid)
> > +static int release_fid(V9fsState *s, V9fsFidState *fidp)
> >   {
> >       int retval = 0;
> > +
> > +    if (fidp->fid_type == P9_FID_FILE) {
> > +        retval = v9fs_co_close(s, fidp);
> > +    } else if (fidp->fid_type == P9_FID_DIR) {
> > +        retval = v9fs_co_closedir(s, fidp);
> > +    } else if (fidp->fid_type == P9_FID_XATTR) {
> > +        retval = v9fs_xattr_fid_clunk(s, fidp);
> > +    }
> > +    v9fs_string_free(&fidp->path);
> > +    qemu_free(fidp);
> > +    return retval;
> > +}
> > +
> > +static void put_fid(V9fsState *s, V9fsFidState *fidp)
> > +{
> > +    BUG_ON(!fidp->ref);
> > +    fidp->ref--;
> > +    if (!fidp->ref&&  fidp->clunked) {
> > +        release_fid(s, fidp);
> > +    }
> > +}
> > +
> > +static int free_fid(V9fsState *s, int32_t fid)
> With the changed semantics; I would suggest you to swap the names of
> release_fid() and free_fid()
> 
> Or even better
> free_fid() -> clunk_fid()
> release_fid() -> free_fid()

ok 

-aneesh

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [PATCH 1/6] hw/9pfs: Add reference counting for fid
  2011-06-09 23:10 ` [Qemu-devel] [PATCH 1/6] hw/9pfs: Add reference counting for fid Venkateswararao Jujjuri
@ 2011-06-10  6:27   ` Aneesh Kumar K.V
  0 siblings, 0 replies; 14+ messages in thread
From: Aneesh Kumar K.V @ 2011-06-10  6:27 UTC (permalink / raw)
  To: Venkateswararao Jujjuri, qemu-devel

On Thu, 09 Jun 2011 16:10:39 -0700, Venkateswararao Jujjuri <jvrao@linux.vnet.ibm.com> wrote:
> On 06/06/2011 10:16 AM, Aneesh Kumar K.V wrote:
> > Signed-off-by: Aneesh Kumar K.V<aneesh.kumar@linux.vnet.ibm.com>
> 
> Just one minor issue below; otherwise
> 
> Reviewed-by: Venkateswararao Jujjuri "<jvrao@linux.vnet.ibm.com>
> 
> > ---
....

> >   hw/9pfs/virtio-9p.c |  205 +++++++++++++++++++++++++++++++++++----------------
> >
> >       pdu_unmarshal(pdu, offset, "dd",&fid,&datasync);
> > -    fidp = lookup_fid(s, fid);
> > +    fidp = get_fid(s, fid);
> >       if (fidp == NULL) {
> >           err = -ENOENT;
> >           goto out;
> > @@ -1444,6 +1465,7 @@ static void v9fs_fsync(void *opaque)
> >           err = offset;
> >       }
> >   out:
> > +    put_fid(fidp);
> It should be
> 
> put_fid(fidp);
> 
> out_nofid:
> 

ok


> >       complete_pdu(s, pdu, err);
> >   }


-aneesh

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Qemu-devel] [PATCH 1/6] hw/9pfs: Add reference counting for fid
  2011-08-25 15:03 [Qemu-devel] [PATCH 0/6] hw/9pfs: Implement file descriptor reclaim in VirtFS server Aneesh Kumar K.V
@ 2011-08-25 15:03 ` Aneesh Kumar K.V
  0 siblings, 0 replies; 14+ messages in thread
From: Aneesh Kumar K.V @ 2011-08-25 15:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, Aneesh Kumar K.V

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 hw/9pfs/virtio-9p.c |  273 ++++++++++++++++++++++++++++++++++-----------------
 hw/9pfs/virtio-9p.h |    2 +
 2 files changed, 184 insertions(+), 91 deletions(-)

diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
index ad70768..555f456 100644
--- a/hw/9pfs/virtio-9p.c
+++ b/hw/9pfs/virtio-9p.c
@@ -232,16 +232,17 @@ static size_t v9fs_string_size(V9fsString *str)
     return str->size;
 }
 
-static V9fsFidState *lookup_fid(V9fsState *s, int32_t fid)
+static V9fsFidState *get_fid(V9fsState *s, int32_t fid)
 {
     V9fsFidState *f;
 
     for (f = s->fid_list; f; f = f->next) {
+        BUG_ON(f->clunked);
         if (f->fid == fid) {
+            f->ref++;
             return f;
         }
     }
-
     return NULL;
 }
 
@@ -249,16 +250,17 @@ static V9fsFidState *alloc_fid(V9fsState *s, int32_t fid)
 {
     V9fsFidState *f;
 
-    f = lookup_fid(s, fid);
-    if (f) {
-        return NULL;
+    for (f = s->fid_list; f; f = f->next) {
+        /* If fid is already there return NULL */
+        BUG_ON(f->clunked);
+        if (f->fid == fid) {
+            return NULL;
+        }
     }
-
     f = g_malloc0(sizeof(V9fsFidState));
-
     f->fid = fid;
     f->fid_type = P9_FID_NONE;
-
+    f->ref = 1;
     f->next = s->fid_list;
     s->fid_list = f;
 
@@ -299,9 +301,33 @@ free_value:
     return retval;
 }
 
-static int free_fid(V9fsState *s, int32_t fid)
+static int free_fid(V9fsState *s, V9fsFidState *fidp)
 {
     int retval = 0;
+
+    if (fidp->fid_type == P9_FID_FILE) {
+        retval = v9fs_co_close(s, fidp);
+    } else if (fidp->fid_type == P9_FID_DIR) {
+        retval = v9fs_co_closedir(s, fidp);
+    } else if (fidp->fid_type == P9_FID_XATTR) {
+        retval = v9fs_xattr_fid_clunk(s, fidp);
+    }
+    v9fs_string_free(&fidp->path);
+    g_free(fidp);
+    return retval;
+}
+
+static void put_fid(V9fsState *s, V9fsFidState *fidp)
+{
+    BUG_ON(!fidp->ref);
+    fidp->ref--;
+    if (!fidp->ref && fidp->clunked) {
+        free_fid(s, fidp);
+    }
+}
+
+static int clunk_fid(V9fsState *s, int32_t fid)
+{
     V9fsFidState **fidpp, *fidp;
 
     for (fidpp = &s->fid_list; *fidpp; fidpp = &(*fidpp)->next) {
@@ -313,20 +339,10 @@ static int free_fid(V9fsState *s, int32_t fid)
     if (*fidpp == NULL) {
         return -ENOENT;
     }
-
     fidp = *fidpp;
     *fidpp = fidp->next;
-
-    if (fidp->fid_type == P9_FID_FILE) {
-        retval = v9fs_co_close(s, fidp);
-    } else if (fidp->fid_type == P9_FID_DIR) {
-        retval = v9fs_co_closedir(s, fidp);
-    } else if (fidp->fid_type == P9_FID_XATTR) {
-        retval = v9fs_xattr_fid_clunk(s, fidp);
-    }
-    v9fs_string_free(&fidp->path);
-    g_free(fidp);
-    return retval;
+    fidp->clunked = 1;
+    return 0;
 }
 
 #define P9_QID_TYPE_DIR         0x80
@@ -1014,19 +1030,21 @@ static void v9fs_attach(void *opaque)
     fidp = alloc_fid(s, fid);
     if (fidp == NULL) {
         err = -EINVAL;
-        goto out;
+        goto out_nofid;
     }
     fidp->uid = n_uname;
     v9fs_string_sprintf(&fidp->path, "%s", "/");
     err = fid_to_qid(s, fidp, &qid);
     if (err < 0) {
         err = -EINVAL;
-        free_fid(s, fid);
+        clunk_fid(s, fid);
         goto out;
     }
     offset += pdu_marshal(pdu, offset, "Q", &qid);
     err = offset;
 out:
+    put_fid(s, fidp);
+out_nofid:
     complete_pdu(s, pdu, err);
     v9fs_string_free(&uname);
     v9fs_string_free(&aname);
@@ -1044,10 +1062,11 @@ static void v9fs_stat(void *opaque)
     V9fsState *s = pdu->s;
 
     pdu_unmarshal(pdu, offset, "d", &fid);
-    fidp = lookup_fid(s, fid);
+
+    fidp = get_fid(s, fid);
     if (fidp == NULL) {
         err = -ENOENT;
-        goto out;
+        goto out_nofid;
     }
     err = v9fs_co_lstat(s, &fidp->path, &stbuf);
     if (err < 0) {
@@ -1061,6 +1080,8 @@ static void v9fs_stat(void *opaque)
     err = offset;
     v9fs_stat_free(&v9stat);
 out:
+    put_fid(s, fidp);
+out_nofid:
     complete_pdu(s, pdu, err);
 }
 
@@ -1078,10 +1099,10 @@ static void v9fs_getattr(void *opaque)
 
     pdu_unmarshal(pdu, offset, "dq", &fid, &request_mask);
 
-    fidp = lookup_fid(s, fid);
+    fidp = get_fid(s, fid);
     if (fidp == NULL) {
         retval = -ENOENT;
-        goto out;
+        goto out_nofid;
     }
     /*
      * Currently we only support BASIC fields in stat, so there is no
@@ -1095,6 +1116,8 @@ static void v9fs_getattr(void *opaque)
     retval = offset;
     retval += pdu_marshal(pdu, offset, "A", &v9stat_dotl);
 out:
+    put_fid(s, fidp);
+out_nofid:
     complete_pdu(s, pdu, retval);
 }
 
@@ -1122,10 +1145,10 @@ static void v9fs_setattr(void *opaque)
 
     pdu_unmarshal(pdu, offset, "dI", &fid, &v9iattr);
 
-    fidp = lookup_fid(s, fid);
+    fidp = get_fid(s, fid);
     if (fidp == NULL) {
         err = -EINVAL;
-        goto out;
+        goto out_nofid;
     }
     if (v9iattr.valid & ATTR_MODE) {
         err = v9fs_co_chmod(s, &fidp->path, v9iattr.mode);
@@ -1187,6 +1210,8 @@ static void v9fs_setattr(void *opaque)
     }
     err = offset;
 out:
+    put_fid(s, fidp);
+out_nofid:
     complete_pdu(s, pdu, err);
 }
 
@@ -1213,7 +1238,7 @@ static void v9fs_walk(void *opaque)
     int32_t fid, newfid;
     V9fsString *wnames = NULL;
     V9fsFidState *fidp;
-    V9fsFidState *newfidp;
+    V9fsFidState *newfidp = NULL;;
     V9fsPDU *pdu = opaque;
     V9fsState *s = pdu->s;
 
@@ -1229,12 +1254,12 @@ static void v9fs_walk(void *opaque)
 
     } else if (nwnames > P9_MAXWELEM) {
         err = -EINVAL;
-        goto out;
+        goto out_nofid;
     }
-    fidp = lookup_fid(s, fid);
+    fidp = get_fid(s, fid);
     if (fidp == NULL) {
         err = -ENOENT;
-        goto out;
+        goto out_nofid;
     }
     if (fid == newfid) {
         BUG_ON(fidp->fid_type != P9_FID_NONE);
@@ -1267,7 +1292,7 @@ static void v9fs_walk(void *opaque)
             v9fs_string_copy(&newfidp->path, &path);
             err = v9fs_co_lstat(s, &newfidp->path, &stbuf);
             if (err < 0) {
-                free_fid(s, newfidp->fid);
+                clunk_fid(s, newfidp->fid);
                 v9fs_string_free(&path);
                 goto out;
             }
@@ -1277,6 +1302,11 @@ static void v9fs_walk(void *opaque)
     }
     err = v9fs_walk_marshal(pdu, nwnames, qids);
 out:
+    put_fid(s, fidp);
+    if (newfidp) {
+        put_fid(s, newfidp);
+    }
+out_nofid:
     complete_pdu(s, pdu, err);
     if (nwnames && nwnames <= P9_MAXWELEM) {
         for (name_idx = 0; name_idx < nwnames; name_idx++) {
@@ -1325,10 +1355,10 @@ static void v9fs_open(void *opaque)
     } else {
         pdu_unmarshal(pdu, offset, "db", &fid, &mode);
     }
-    fidp = lookup_fid(s, fid);
+    fidp = get_fid(s, fid);
     if (fidp == NULL) {
         err = -ENOENT;
-        goto out;
+        goto out_nofid;
     }
     BUG_ON(fidp->fid_type != P9_FID_NONE);
 
@@ -1364,6 +1394,8 @@ static void v9fs_open(void *opaque)
         err = offset;
     }
 out:
+    put_fid(s, fidp);
+out_nofid:
     complete_pdu(s, pdu, err);
 }
 
@@ -1385,10 +1417,10 @@ static void v9fs_lcreate(void *opaque)
     pdu_unmarshal(pdu, offset, "dsddd", &dfid, &name, &flags,
                   &mode, &gid);
 
-    fidp = lookup_fid(pdu->s, dfid);
+    fidp = get_fid(pdu->s, dfid);
     if (fidp == NULL) {
         err = -ENOENT;
-        goto out;
+        goto out_nofid;
     }
     v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data);
 
@@ -1415,6 +1447,8 @@ static void v9fs_lcreate(void *opaque)
     offset += pdu_marshal(pdu, offset, "Qd", &qid, iounit);
     err = offset;
 out:
+    put_fid(pdu->s, fidp);
+out_nofid:
     complete_pdu(pdu->s, pdu, err);
     v9fs_string_free(&name);
     v9fs_string_free(&fullname);
@@ -1431,16 +1465,17 @@ static void v9fs_fsync(void *opaque)
     V9fsState *s = pdu->s;
 
     pdu_unmarshal(pdu, offset, "dd", &fid, &datasync);
-    fidp = lookup_fid(s, fid);
+    fidp = get_fid(s, fid);
     if (fidp == NULL) {
         err = -ENOENT;
-        goto out;
+        goto out_nofid;
     }
     err = v9fs_co_fsync(s, fidp, datasync);
     if (!err) {
         err = offset;
     }
-out:
+    put_fid(s, fidp);
+out_nofid:
     complete_pdu(s, pdu, err);
 }
 
@@ -1449,16 +1484,25 @@ static void v9fs_clunk(void *opaque)
     int err;
     int32_t fid;
     size_t offset = 7;
+    V9fsFidState *fidp;
     V9fsPDU *pdu = opaque;
     V9fsState *s = pdu->s;
 
     pdu_unmarshal(pdu, offset, "d", &fid);
-    err = free_fid(s, fid);
+
+    fidp = get_fid(s, fid);
+    if (fidp == NULL) {
+        err = -ENOENT;
+        goto out_nofid;
+    }
+    err = clunk_fid(s, fidp->fid);
     if (err < 0) {
         goto out;
     }
     err = offset;
 out:
+    put_fid(s, fidp);
+out_nofid:
     complete_pdu(s, pdu, err);
 }
 
@@ -1557,10 +1601,11 @@ static void v9fs_read(void *opaque)
     V9fsState *s = pdu->s;
 
     pdu_unmarshal(pdu, offset, "dqd", &fid, &off, &max_count);
-    fidp = lookup_fid(s, fid);
+
+    fidp = get_fid(s, fid);
     if (fidp == NULL) {
         err = -EINVAL;
-        goto out;
+        goto out_nofid;
     }
     if (fidp->fid_type == P9_FID_DIR) {
 
@@ -1612,6 +1657,8 @@ static void v9fs_read(void *opaque)
         err = -EINVAL;
     }
 out:
+    put_fid(s, fidp);
+out_nofid:
     complete_pdu(s, pdu, err);
 }
 
@@ -1696,8 +1743,12 @@ static void v9fs_readdir(void *opaque)
 
     pdu_unmarshal(pdu, offset, "dqd", &fid, &initial_offset, &max_count);
 
-    fidp = lookup_fid(s, fid);
-    if (fidp == NULL || !fidp->fs.dir) {
+    fidp = get_fid(s, fid);
+    if (fidp == NULL) {
+        retval = -EINVAL;
+        goto out_nofid;
+    }
+    if (!fidp->fs.dir) {
         retval = -EINVAL;
         goto out;
     }
@@ -1715,6 +1766,8 @@ static void v9fs_readdir(void *opaque)
     retval += pdu_marshal(pdu, offset, "d", count);
     retval += count;
 out:
+    put_fid(s, fidp);
+out_nofid:
     complete_pdu(s, pdu, retval);
 }
 
@@ -1779,10 +1832,11 @@ static void v9fs_write(void *opaque)
     V9fsState *s = pdu->s;
 
     pdu_unmarshal(pdu, offset, "dqdv", &fid, &off, &count, sg, &cnt);
-    fidp = lookup_fid(s, fid);
+
+    fidp = get_fid(s, fid);
     if (fidp == NULL) {
         err = -EINVAL;
-        goto out;
+        goto out_nofid;
     }
     if (fidp->fid_type == P9_FID_FILE) {
         if (fidp->fs.fd == -1) {
@@ -1822,6 +1876,8 @@ static void v9fs_write(void *opaque)
     offset += pdu_marshal(pdu, offset, "d", total);
     err = offset;
 out:
+    put_fid(s, fidp);
+out_nofid:
     complete_pdu(s, pdu, err);
 }
 
@@ -1846,10 +1902,10 @@ static void v9fs_create(void *opaque)
     pdu_unmarshal(pdu, offset, "dsdbs", &fid, &name,
                   &perm, &mode, &extension);
 
-    fidp = lookup_fid(pdu->s, fid);
+    fidp = get_fid(pdu->s, fid);
     if (fidp == NULL) {
         err = -EINVAL;
-        goto out;
+        goto out_nofid;
     }
 
     v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data);
@@ -1879,15 +1935,17 @@ static void v9fs_create(void *opaque)
         }
     } else if (perm & P9_STAT_MODE_LINK) {
         int32_t nfid = atoi(extension.data);
-        V9fsFidState *nfidp = lookup_fid(pdu->s, nfid);
+        V9fsFidState *nfidp = get_fid(pdu->s, nfid);
         if (nfidp == NULL) {
             err = -EINVAL;
             goto out;
         }
         err = v9fs_co_link(pdu->s, &nfidp->path, &fullname);
         if (err < 0) {
+            put_fid(pdu->s, nfidp);
             goto out;
         }
+        put_fid(pdu->s, nfidp);
     } else if (perm & P9_STAT_MODE_DEVICE) {
         char ctype;
         uint32_t major, minor;
@@ -1950,6 +2008,8 @@ static void v9fs_create(void *opaque)
     offset += pdu_marshal(pdu, offset, "Qd", &qid, iounit);
     err = offset;
 out:
+    put_fid(pdu->s, fidp);
+out_nofid:
    complete_pdu(pdu->s, pdu, err);
    v9fs_string_free(&name);
    v9fs_string_free(&extension);
@@ -1973,10 +2033,10 @@ static void v9fs_symlink(void *opaque)
     v9fs_string_init(&fullname);
     pdu_unmarshal(pdu, offset, "dssd", &dfid, &name, &symname, &gid);
 
-    dfidp = lookup_fid(pdu->s, dfid);
+    dfidp = get_fid(pdu->s, dfid);
     if (dfidp == NULL) {
         err = -EINVAL;
-        goto out;
+        goto out_nofid;
     }
 
     v9fs_string_sprintf(&fullname, "%s/%s", dfidp->path.data, name.data);
@@ -1992,6 +2052,8 @@ static void v9fs_symlink(void *opaque)
     offset += pdu_marshal(pdu, offset, "Q", &qid);
     err = offset;
 out:
+    put_fid(pdu->s, dfidp);
+out_nofid:
     complete_pdu(pdu->s, pdu, err);
     v9fs_string_free(&name);
     v9fs_string_free(&symname);
@@ -2021,13 +2083,13 @@ static void v9fs_link(void *opaque)
 
     pdu_unmarshal(pdu, offset, "dds", &dfid, &oldfid, &name);
 
-    dfidp = lookup_fid(s, dfid);
+    dfidp = get_fid(s, dfid);
     if (dfidp == NULL) {
         err = -ENOENT;
-        goto out;
+        goto out_nofid;
     }
 
-    oldfidp = lookup_fid(s, oldfid);
+    oldfidp = get_fid(s, oldfid);
     if (oldfidp == NULL) {
         err = -ENOENT;
         goto out;
@@ -2041,6 +2103,8 @@ static void v9fs_link(void *opaque)
     v9fs_string_free(&fullname);
 
 out:
+    put_fid(s, dfidp);
+out_nofid:
     v9fs_string_free(&name);
     complete_pdu(s, pdu, err);
 }
@@ -2055,10 +2119,10 @@ static void v9fs_remove(void *opaque)
 
     pdu_unmarshal(pdu, offset, "d", &fid);
 
-    fidp = lookup_fid(pdu->s, fid);
+    fidp = get_fid(pdu->s, fid);
     if (fidp == NULL) {
         err = -EINVAL;
-        goto out;
+        goto out_nofid;
     }
     err = v9fs_co_remove(pdu->s, &fidp->path);
     if (!err) {
@@ -2066,8 +2130,9 @@ static void v9fs_remove(void *opaque)
     }
 
     /* For TREMOVE we need to clunk the fid even on failed remove */
-    free_fid(pdu->s, fidp->fid);
-out:
+    clunk_fid(pdu->s, fidp->fid);
+    put_fid(pdu->s, fidp);
+out_nofid:
     complete_pdu(pdu->s, pdu, err);
 }
 
@@ -2076,14 +2141,14 @@ static int v9fs_complete_rename(V9fsState *s, V9fsFidState *fidp,
 {
     char *end;
     int err = 0;
+    V9fsFidState *dirfidp = NULL;
     char *old_name, *new_name;
 
     if (newdirfid != -1) {
-        V9fsFidState *dirfidp;
-        dirfidp = lookup_fid(s, newdirfid);
+        dirfidp = get_fid(s, newdirfid);
         if (dirfidp == NULL) {
             err = -ENOENT;
-            goto out;
+            goto out_nofid;
         }
         BUG_ON(dirfidp->fid_type != P9_FID_NONE);
 
@@ -2136,6 +2201,10 @@ static int v9fs_complete_rename(V9fsState *s, V9fsFidState *fidp,
         v9fs_string_copy(&fidp->path, name);
     }
 out:
+    if (dirfidp) {
+        put_fid(s, dirfidp);
+    }
+out_nofid:
     return err;
 }
 
@@ -2152,10 +2221,10 @@ static void v9fs_rename(void *opaque)
 
     pdu_unmarshal(pdu, offset, "dds", &fid, &newdirfid, &name);
 
-    fidp = lookup_fid(s, fid);
+    fidp = get_fid(s, fid);
     if (fidp == NULL) {
         err = -ENOENT;
-        goto out;
+        goto out_nofid;
     }
     BUG_ON(fidp->fid_type != P9_FID_NONE);
 
@@ -2163,7 +2232,8 @@ static void v9fs_rename(void *opaque)
     if (!err) {
         err = offset;
     }
-out:
+    put_fid(s, fidp);
+out_nofid:
     complete_pdu(s, pdu, err);
     v9fs_string_free(&name);
 }
@@ -2181,10 +2251,11 @@ static void v9fs_wstat(void *opaque)
     V9fsState *s = pdu->s;
 
     pdu_unmarshal(pdu, offset, "dwS", &fid, &unused, &v9stat);
-    fidp = lookup_fid(s, fid);
+
+    fidp = get_fid(s, fid);
     if (fidp == NULL) {
         err = -EINVAL;
-        goto out;
+        goto out_nofid;
     }
     /* do we need to sync the file? */
     if (donttouch_stat(&v9stat)) {
@@ -2250,6 +2321,8 @@ static void v9fs_wstat(void *opaque)
     }
     err = offset;
 out:
+    put_fid(s, fidp);
+out_nofid:
     v9fs_stat_free(&v9stat);
     complete_pdu(s, pdu, err);
 }
@@ -2310,10 +2383,10 @@ static void v9fs_statfs(void *opaque)
     V9fsState *s = pdu->s;
 
     pdu_unmarshal(pdu, offset, "d", &fid);
-    fidp = lookup_fid(s, fid);
+    fidp = get_fid(s, fid);
     if (fidp == NULL) {
         retval = -ENOENT;
-        goto out;
+        goto out_nofid;
     }
     retval = v9fs_co_statfs(s, &fidp->path, &stbuf);
     if (retval < 0) {
@@ -2322,6 +2395,8 @@ static void v9fs_statfs(void *opaque)
     retval = offset;
     retval += v9fs_fill_statfs(s, pdu, &stbuf);
 out:
+    put_fid(s, fidp);
+out_nofid:
     complete_pdu(s, pdu, retval);
     return;
 }
@@ -2347,10 +2422,10 @@ static void v9fs_mknod(void *opaque)
     pdu_unmarshal(pdu, offset, "dsdddd", &fid, &name, &mode,
                   &major, &minor, &gid);
 
-    fidp = lookup_fid(s, fid);
+    fidp = get_fid(s, fid);
     if (fidp == NULL) {
         err = -ENOENT;
-        goto out;
+        goto out_nofid;
     }
     v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data);
     err = v9fs_co_mknod(s, &fullname, fidp->uid, gid,
@@ -2366,6 +2441,8 @@ static void v9fs_mknod(void *opaque)
     err = offset;
     err += pdu_marshal(pdu, offset, "Q", &qid);
 out:
+    put_fid(s, fidp);
+out_nofid:
     complete_pdu(s, pdu, err);
     v9fs_string_free(&fullname);
     v9fs_string_free(&name);
@@ -2399,12 +2476,12 @@ static void v9fs_lock(void *opaque)
     /* We support only block flag now (that too ignored currently) */
     if (flock->flags & ~P9_LOCK_FLAGS_BLOCK) {
         err = -EINVAL;
-        goto out;
+        goto out_nofid;
     }
-    fidp = lookup_fid(s, fid);
+    fidp = get_fid(s, fid);
     if (fidp == NULL) {
         err = -ENOENT;
-        goto out;
+        goto out_nofid;
     }
     err = v9fs_co_fstat(s, fidp->fs.fd, &stbuf);
     if (err < 0) {
@@ -2412,6 +2489,8 @@ static void v9fs_lock(void *opaque)
     }
     status = P9_LOCK_SUCCESS;
 out:
+    put_fid(s, fidp);
+out_nofid:
     err = offset;
     err += pdu_marshal(pdu, offset, "b", status);
     complete_pdu(s, pdu, err);
@@ -2437,10 +2516,10 @@ static void v9fs_getlock(void *opaque)
                   &glock->start, &glock->length, &glock->proc_id,
                   &glock->client_id);
 
-    fidp = lookup_fid(s, fid);
+    fidp = get_fid(s, fid);
     if (fidp == NULL) {
         err = -ENOENT;
-        goto out;
+        goto out_nofid;
     }
     err = v9fs_co_fstat(s, fidp->fs.fd, &stbuf);
     if (err < 0) {
@@ -2452,6 +2531,8 @@ static void v9fs_getlock(void *opaque)
                           &glock->client_id);
     err = offset;
 out:
+    put_fid(s, fidp);
+out_nofid:
     complete_pdu(s, pdu, err);
     g_free(glock);
 }
@@ -2472,10 +2553,10 @@ static void v9fs_mkdir(void *opaque)
     v9fs_string_init(&fullname);
     pdu_unmarshal(pdu, offset, "dsdd", &fid, &name, &mode, &gid);
 
-    fidp = lookup_fid(pdu->s, fid);
+    fidp = get_fid(pdu->s, fid);
     if (fidp == NULL) {
         err = -ENOENT;
-        goto out;
+        goto out_nofid;
     }
     v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data);
     err = v9fs_co_mkdir(pdu->s, fullname.data, mode, fidp->uid, gid);
@@ -2490,6 +2571,8 @@ static void v9fs_mkdir(void *opaque)
     offset += pdu_marshal(pdu, offset, "Q", &qid);
     err = offset;
 out:
+    put_fid(pdu->s, fidp);
+out_nofid:
     complete_pdu(pdu->s, pdu, err);
     v9fs_string_free(&fullname);
     v9fs_string_free(&name);
@@ -2503,15 +2586,15 @@ static void v9fs_xattrwalk(void *opaque)
     size_t offset = 7;
     int32_t fid, newfid;
     V9fsFidState *file_fidp;
-    V9fsFidState *xattr_fidp;
+    V9fsFidState *xattr_fidp = NULL;
     V9fsPDU *pdu = opaque;
     V9fsState *s = pdu->s;
 
     pdu_unmarshal(pdu, offset, "dds", &fid, &newfid, &name);
-    file_fidp = lookup_fid(s, fid);
+    file_fidp = get_fid(s, fid);
     if (file_fidp == NULL) {
         err = -ENOENT;
-        goto out;
+        goto out_nofid;
     }
     xattr_fidp = alloc_fid(s, newfid);
     if (xattr_fidp == NULL) {
@@ -2526,7 +2609,7 @@ static void v9fs_xattrwalk(void *opaque)
         size = v9fs_co_llistxattr(s, &xattr_fidp->path, NULL, 0);
         if (size < 0) {
             err = size;
-            free_fid(s, xattr_fidp->fid);
+            clunk_fid(s, xattr_fidp->fid);
             goto out;
         }
         /*
@@ -2541,7 +2624,7 @@ static void v9fs_xattrwalk(void *opaque)
                                      xattr_fidp->fs.xattr.value,
                                      xattr_fidp->fs.xattr.len);
             if (err < 0) {
-                free_fid(s, xattr_fidp->fid);
+                clunk_fid(s, xattr_fidp->fid);
                 goto out;
             }
         }
@@ -2556,7 +2639,7 @@ static void v9fs_xattrwalk(void *opaque)
                                  &name, NULL, 0);
         if (size < 0) {
             err = size;
-            free_fid(s, xattr_fidp->fid);
+            clunk_fid(s, xattr_fidp->fid);
             goto out;
         }
         /*
@@ -2571,7 +2654,7 @@ static void v9fs_xattrwalk(void *opaque)
                                     &name, xattr_fidp->fs.xattr.value,
                                     xattr_fidp->fs.xattr.len);
             if (err < 0) {
-                free_fid(s, xattr_fidp->fid);
+                clunk_fid(s, xattr_fidp->fid);
                 goto out;
             }
         }
@@ -2579,6 +2662,11 @@ static void v9fs_xattrwalk(void *opaque)
         err = offset;
     }
 out:
+    put_fid(s, file_fidp);
+    if (xattr_fidp) {
+        put_fid(s, xattr_fidp);
+    }
+out_nofid:
     complete_pdu(s, pdu, err);
     v9fs_string_free(&name);
 }
@@ -2599,10 +2687,10 @@ static void v9fs_xattrcreate(void *opaque)
     pdu_unmarshal(pdu, offset, "dsqd",
                   &fid, &name, &size, &flags);
 
-    file_fidp = lookup_fid(s, fid);
+    file_fidp = get_fid(s, fid);
     if (file_fidp == NULL) {
         err = -EINVAL;
-        goto out;
+        goto out_nofid;
     }
     /* Make the file fid point to xattr */
     xattr_fidp = file_fidp;
@@ -2618,7 +2706,8 @@ static void v9fs_xattrcreate(void *opaque)
         xattr_fidp->fs.xattr.value = NULL;
     }
     err = offset;
-out:
+    put_fid(s, file_fidp);
+out_nofid:
     complete_pdu(s, pdu, err);
     v9fs_string_free(&name);
 }
@@ -2633,10 +2722,10 @@ static void v9fs_readlink(void *opaque)
     V9fsFidState *fidp;
 
     pdu_unmarshal(pdu, offset, "d", &fid);
-    fidp = lookup_fid(pdu->s, fid);
+    fidp = get_fid(pdu->s, fid);
     if (fidp == NULL) {
         err = -ENOENT;
-        goto out;
+        goto out_nofid;
     }
 
     v9fs_string_init(&target);
@@ -2648,6 +2737,8 @@ static void v9fs_readlink(void *opaque)
     err = offset;
     v9fs_string_free(&target);
 out:
+    put_fid(pdu->s, fidp);
+out_nofid:
     complete_pdu(pdu->s, pdu, err);
 }
 
diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h
index 1d8c1b1..e16e5f4 100644
--- a/hw/9pfs/virtio-9p.h
+++ b/hw/9pfs/virtio-9p.h
@@ -203,6 +203,8 @@ struct V9fsFidState
 	V9fsXattr xattr;
     } fs;
     uid_t uid;
+    int ref;
+    int clunked;
     V9fsFidState *next;
 };
 
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2011-08-25 15:04 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-06-06 17:16 [Qemu-devel] [PATCH 1/6] hw/9pfs: Add reference counting for fid Aneesh Kumar K.V
2011-06-06 17:16 ` [Qemu-devel] [PATCH 2/6] hw/9pfs: Don't free fid in clunk Aneesh Kumar K.V
2011-06-10  0:27   ` Venkateswararao Jujjuri
2011-06-10  6:19     ` Aneesh Kumar K.V
2011-06-06 17:16 ` [Qemu-devel] [PATCH 3/6] hw/9pfs: Add file descriptor reclaim support Aneesh Kumar K.V
2011-06-10  1:27   ` Venkateswararao Jujjuri
2011-06-06 17:16 ` [Qemu-devel] [PATCH 4/6] hw/9pfs: init fid list properly Aneesh Kumar K.V
2011-06-06 17:16 ` [Qemu-devel] [PATCH 5/6] hw/9pfs: Use v9fs_do_close instead of close Aneesh Kumar K.V
2011-06-10  1:32   ` Venkateswararao Jujjuri
2011-06-06 17:16 ` [Qemu-devel] [PATCH 6/6] hw/9pfs: Add directory reclaim support Aneesh Kumar K.V
2011-06-10  1:36   ` Venkateswararao Jujjuri
2011-06-09 23:10 ` [Qemu-devel] [PATCH 1/6] hw/9pfs: Add reference counting for fid Venkateswararao Jujjuri
2011-06-10  6:27   ` Aneesh Kumar K.V
  -- strict thread matches above, loose matches on Subject: below --
2011-08-25 15:03 [Qemu-devel] [PATCH 0/6] hw/9pfs: Implement file descriptor reclaim in VirtFS server Aneesh Kumar K.V
2011-08-25 15:03 ` [Qemu-devel] [PATCH 1/6] hw/9pfs: Add reference counting for fid Aneesh Kumar K.V

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).