[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [RFC PATCH -V1 1/4] hw/9pfs: Add file descriptor reclai
From: |
Venkateswararao Jujjuri (JV) |
Subject: |
Re: [Qemu-devel] [RFC PATCH -V1 1/4] hw/9pfs: Add file descriptor reclaim support |
Date: |
Mon, 28 Feb 2011 17:44:56 -0800 |
User-agent: |
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.13) Gecko/20101207 Thunderbird/3.1.7 |
On 2/5/2011 10:08 AM, Aneesh Kumar K.V wrote:
> This add file descriptor recliam to 9p server
Please split it into two patches.
1. Introducing fsmap.
2. Introducing the reclaim mechanism.
Concern: With this we will be traversing the whole fid list for many operations
.. how is
the performance impact?
-Jv
>
> Signed-off-by: Aneesh Kumar K.V <address@hidden>
> ---
> hw/9pfs/virtio-9p.c | 424 +++++++++++++++++++++++++++++++-------------------
> hw/9pfs/virtio-9p.h | 22 ++-
> 2 files changed, 278 insertions(+), 168 deletions(-)
>
> diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
> index 27e7750..86a32a4 100644
> --- a/hw/9pfs/virtio-9p.c
> +++ b/hw/9pfs/virtio-9p.c
> @@ -20,6 +20,7 @@
> #include "virtio-9p-xattr.h"
>
> int debug_9p_pdu;
> +static void v9fs_reclaim_fd(V9fsState *s);
>
> enum {
> Oread = 0x00,
> @@ -107,7 +108,12 @@ static int v9fs_do_closedir(V9fsState *s, DIR *dir)
>
> static int v9fs_do_open(V9fsState *s, V9fsString *path, int flags)
> {
> - return s->ops->open(&s->ctx, path->data, flags);
> + int fd;
> + fd = s->ops->open(&s->ctx, path->data, flags);
> + if (fd > P9_FD_RECLAIM_THRES) {
> + v9fs_reclaim_fd(s);
> + }
> + return fd;
> }
>
> static DIR *v9fs_do_opendir(V9fsState *s, V9fsString *path)
> @@ -188,6 +194,7 @@ static int v9fs_do_fstat(V9fsState *s, int fd, struct
> stat *stbuf)
> static int v9fs_do_open2(V9fsState *s, char *fullname, uid_t uid, gid_t gid,
> int flags, int mode)
> {
> + int fd;
> FsCred cred;
>
> cred_init(&cred);
> @@ -196,7 +203,11 @@ static int v9fs_do_open2(V9fsState *s, char *fullname,
> uid_t uid, gid_t gid,
> cred.fc_mode = mode & 07777;
> flags = flags;
>
> - return s->ops->open2(&s->ctx, fullname, flags, &cred);
> + fd = s->ops->open2(&s->ctx, fullname, flags, &cred);
> + if (fd > P9_FD_RECLAIM_THRES) {
> + v9fs_reclaim_fd(s);
> + }
> + return fd;
> }
>
> static int v9fs_do_symlink(V9fsState *s, V9fsFidState *fidp,
> @@ -434,6 +445,23 @@ static V9fsFidState *lookup_fid(V9fsState *s, int32_t
> fid)
>
> for (f = s->fid_list; f; f = f->next) {
> if (f->fid == fid) {
> + /*
> + * check whether we need to reopen the
> + * file. We might have closed the fd
> + * while trying to free up some file
> + * descriptors.
> + */
> + if (f->fsmap.fid_type == P9_FID_FILE) {
> + /* FIXME!! should we remember the open flags ?*/
> + if (f->fsmap.fs.fd == -1) {
> + f->fsmap.fs.fd = v9fs_do_open(s, &f->fsmap.path, O_RDWR);
> + }
> + }
> + /*
> + * Mark the fid as referenced so that the LRU
> + * reclaim won't close the file descriptor
> + */
> + f->fsmap.flags |= FID_REFERENCED;
> return f;
> }
> }
> @@ -453,7 +481,7 @@ static V9fsFidState *alloc_fid(V9fsState *s, int32_t fid)
> f = qemu_mallocz(sizeof(V9fsFidState));
>
> f->fid = fid;
> - f->fid_type = P9_FID_NONE;
> + f->fsmap.fid_type = P9_FID_NONE;
>
> f->next = s->fid_list;
> s->fid_list = f;
> @@ -461,11 +489,67 @@ static V9fsFidState *alloc_fid(V9fsState *s, int32_t
> fid)
> return f;
> }
>
> +static void v9fs_reclaim_fd(V9fsState *s)
> +{
> + int reclaim_count = 0;
> + V9fsFidState *f;
> +
> + for (f = s->fid_list; f; f = f->next) {
> + /*
> + * Unlink fids cannot be reclaimed. Check
> + * for them and skip them
> + */
> + if (f->fsmap.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->fsmap.flags & FID_REFERENCED) {
> + f->fsmap.flags &= ~FID_REFERENCED;
> + continue;
> + }
> + /*
> + * reclaim fd, by closing the file descriptors
> + */
> + if (f->fsmap.fid_type == P9_FID_FILE) {
> + if (f->fsmap.fs.fd != -1) {
> + v9fs_do_close(s, f->fsmap.fs.fd);
> + f->fsmap.fs.fd = -1;
> + reclaim_count++;
> + }
> + }
> + if (reclaim_count >= P9_FD_RECLAIM_THRES/2) {
> + break;
> + }
> + }
> +}
> +
> +static void v9fs_mark_fids_unreclaim(V9fsState *s, V9fsString *str)
> +{
> + V9fsFidState *fidp;
> + for (fidp = s->fid_list; fidp; fidp = fidp->next) {
> + if (!strcmp(fidp->fsmap.path.data, str->data)) {
> + /* Mark the fid non reclaimable. */
> + fidp->fsmap.flags |= FID_NON_RECLAIMABLE;
> + /* reopen the file if already closed */
> + if (fidp->fsmap.fs.fd == -1) {
> + fidp->fsmap.fs.fd = v9fs_do_open(s, &fidp->fsmap.path,
> O_RDWR);
> + }
> + }
> + }
> +}
> +
> +
> static int v9fs_xattr_fid_clunk(V9fsState *s, V9fsFidState *fidp)
> {
> int retval = 0;
>
> - if (fidp->fs.xattr.copied_len == -1) {
> + if (fidp->fsmap.fs.xattr.copied_len == -1) {
> /* getxattr/listxattr fid */
> goto free_value;
> }
> @@ -473,24 +557,26 @@ static int v9fs_xattr_fid_clunk(V9fsState *s,
> V9fsFidState *fidp)
> * if this is fid for setxattr. clunk should
> * result in setxattr localcall
> */
> - if (fidp->fs.xattr.len != fidp->fs.xattr.copied_len) {
> + if (fidp->fsmap.fs.xattr.len != fidp->fsmap.fs.xattr.copied_len) {
> /* clunk after partial write */
> retval = -EINVAL;
> goto free_out;
> }
> - if (fidp->fs.xattr.len) {
> - retval = v9fs_do_lsetxattr(s, &fidp->path, &fidp->fs.xattr.name,
> - fidp->fs.xattr.value,
> - fidp->fs.xattr.len,
> - fidp->fs.xattr.flags);
> + if (fidp->fsmap.fs.xattr.len) {
> + retval = v9fs_do_lsetxattr(s, &fidp->fsmap.path,
> + &fidp->fsmap.fs.xattr.name,
> + fidp->fsmap.fs.xattr.value,
> + fidp->fsmap.fs.xattr.len,
> + fidp->fsmap.fs.xattr.flags);
> } else {
> - retval = v9fs_do_lremovexattr(s, &fidp->path, &fidp->fs.xattr.name);
> + retval = v9fs_do_lremovexattr(s, &fidp->fsmap.path,
> + &fidp->fsmap.fs.xattr.name);
> }
> free_out:
> - v9fs_string_free(&fidp->fs.xattr.name);
> + v9fs_string_free(&fidp->fsmap.fs.xattr.name);
> free_value:
> - if (fidp->fs.xattr.value) {
> - qemu_free(fidp->fs.xattr.value);
> + if (fidp->fsmap.fs.xattr.value) {
> + qemu_free(fidp->fsmap.fs.xattr.value);
> }
> return retval;
> }
> @@ -513,14 +599,17 @@ static int free_fid(V9fsState *s, int32_t fid)
> fidp = *fidpp;
> *fidpp = fidp->next;
>
> - if (fidp->fid_type == P9_FID_FILE) {
> - v9fs_do_close(s, fidp->fs.fd);
> - } else if (fidp->fid_type == P9_FID_DIR) {
> - v9fs_do_closedir(s, fidp->fs.dir);
> - } else if (fidp->fid_type == P9_FID_XATTR) {
> + if (fidp->fsmap.fid_type == P9_FID_FILE) {
> + /* I we reclaimed the fd no need to close */
> + if (fidp->fsmap.fs.fd != -1) {
> + v9fs_do_close(s, fidp->fsmap.fs.fd);
> + }
> + } else if (fidp->fsmap.fid_type == P9_FID_DIR) {
> + v9fs_do_closedir(s, fidp->fsmap.fs.dir);
> + } else if (fidp->fsmap.fid_type == P9_FID_XATTR) {
> retval = v9fs_xattr_fid_clunk(s, fidp);
> }
> - v9fs_string_free(&fidp->path);
> + v9fs_string_free(&fidp->fsmap.path);
> qemu_free(fidp);
>
> return retval;
> @@ -573,7 +662,7 @@ static int fid_to_qid(V9fsState *s, V9fsFidState *fidp,
> V9fsQID *qidp)
> struct stat stbuf;
> int err;
>
> - err = v9fs_do_lstat(s, &fidp->path, &stbuf);
> + err = v9fs_do_lstat(s, &fidp->fsmap.path, &stbuf);
> if (err) {
> return err;
> }
> @@ -1218,7 +1307,7 @@ static void v9fs_attach(V9fsState *s, V9fsPDU *pdu)
>
> fidp->uid = n_uname;
>
> - v9fs_string_sprintf(&fidp->path, "%s", "/");
> + v9fs_string_sprintf(&fidp->fsmap.path, "%s", "/");
> err = fid_to_qid(s, fidp, &qid);
> if (err) {
> err = -EINVAL;
> @@ -1242,7 +1331,7 @@ static void v9fs_stat_post_lstat(V9fsState *s,
> V9fsStatState *vs, int err)
> goto out;
> }
>
> - err = stat_to_v9stat(s, &vs->fidp->path, &vs->stbuf, &vs->v9stat);
> + err = stat_to_v9stat(s, &vs->fidp->fsmap.path, &vs->stbuf, &vs->v9stat);
> if (err) {
> goto out;
> }
> @@ -1275,7 +1364,7 @@ static void v9fs_stat(V9fsState *s, V9fsPDU *pdu)
> goto out;
> }
>
> - err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf);
> + err = v9fs_do_lstat(s, &vs->fidp->fsmap.path, &vs->stbuf);
> v9fs_stat_post_lstat(s, vs, err);
> return;
>
> @@ -1327,7 +1416,7 @@ static void v9fs_getattr(V9fsState *s, V9fsPDU *pdu)
> /* Currently we only support BASIC fields in stat, so there is no
> * need to look at request_mask.
> */
> - err = v9fs_do_lstat(s, &fidp->path, &vs->stbuf);
> + err = v9fs_do_lstat(s, &fidp->fsmap.path, &vs->stbuf);
> v9fs_getattr_post_lstat(s, vs, err);
> return;
>
> @@ -1370,7 +1459,7 @@ static void v9fs_setattr_post_chown(V9fsState *s,
> V9fsSetattrState *vs, int err)
> }
>
> if (vs->v9iattr.valid & (ATTR_SIZE)) {
> - err = v9fs_do_truncate(s, &vs->fidp->path, vs->v9iattr.size);
> + err = v9fs_do_truncate(s, &vs->fidp->fsmap.path, vs->v9iattr.size);
> }
> v9fs_setattr_post_truncate(s, vs, err);
> return;
> @@ -1400,8 +1489,9 @@ static void v9fs_setattr_post_utimensat(V9fsState *s,
> V9fsSetattrState *vs,
> if (!(vs->v9iattr.valid & ATTR_GID)) {
> vs->v9iattr.gid = -1;
> }
> - err = v9fs_do_chown(s, &vs->fidp->path, vs->v9iattr.uid,
> - vs->v9iattr.gid);
> + err = v9fs_do_chown(s, &vs->fidp->fsmap.path,
> + vs->v9iattr.uid,
> + vs->v9iattr.gid);
> }
> v9fs_setattr_post_chown(s, vs, err);
> return;
> @@ -1441,7 +1531,7 @@ static void v9fs_setattr_post_chmod(V9fsState *s,
> V9fsSetattrState *vs, int err)
> } else {
> times[1].tv_nsec = UTIME_OMIT;
> }
> - err = v9fs_do_utimensat(s, &vs->fidp->path, times);
> + err = v9fs_do_utimensat(s, &vs->fidp->fsmap.path, times);
> }
> v9fs_setattr_post_utimensat(s, vs, err);
> return;
> @@ -1470,7 +1560,7 @@ static void v9fs_setattr(V9fsState *s, V9fsPDU *pdu)
> }
>
> if (vs->v9iattr.valid & ATTR_MODE) {
> - err = v9fs_do_chmod(s, &vs->fidp->path, vs->v9iattr.mode);
> + err = v9fs_do_chmod(s, &vs->fidp->fsmap.path, vs->v9iattr.mode);
> }
>
> v9fs_setattr_post_chmod(s, vs, err);
> @@ -1520,11 +1610,11 @@ static void v9fs_walk_post_newfid_lstat(V9fsState *s,
> V9fsWalkState *vs,
>
> vs->name_idx++;
> if (vs->name_idx < vs->nwnames) {
> - v9fs_string_sprintf(&vs->path, "%s/%s", vs->newfidp->path.data,
> + v9fs_string_sprintf(&vs->path, "%s/%s", vs->newfidp->fsmap.path.data,
> vs->wnames[vs->name_idx].data);
> - v9fs_string_copy(&vs->newfidp->path, &vs->path);
> + v9fs_string_copy(&vs->newfidp->fsmap.path, &vs->path);
>
> - err = v9fs_do_lstat(s, &vs->newfidp->path, &vs->stbuf);
> + err = v9fs_do_lstat(s, &vs->newfidp->fsmap.path, &vs->stbuf);
> v9fs_walk_post_newfid_lstat(s, vs, err);
> return;
> }
> @@ -1550,10 +1640,11 @@ static void v9fs_walk_post_oldfid_lstat(V9fsState *s,
> V9fsWalkState *vs,
> if (vs->name_idx < vs->nwnames) {
>
> v9fs_string_sprintf(&vs->path, "%s/%s",
> - vs->fidp->path.data, vs->wnames[vs->name_idx].data);
> - v9fs_string_copy(&vs->fidp->path, &vs->path);
> + vs->fidp->fsmap.path.data,
> + vs->wnames[vs->name_idx].data);
> + v9fs_string_copy(&vs->fidp->fsmap.path, &vs->path);
>
> - err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf);
> + err = v9fs_do_lstat(s, &vs->fidp->fsmap.path, &vs->stbuf);
> v9fs_walk_post_oldfid_lstat(s, vs, err);
> return;
> }
> @@ -1601,16 +1692,17 @@ static void v9fs_walk(V9fsState *s, V9fsPDU *pdu)
> /* FIXME: is this really valid? */
> if (fid == newfid) {
>
> - BUG_ON(vs->fidp->fid_type != P9_FID_NONE);
> + BUG_ON(vs->fidp->fsmap.fid_type != P9_FID_NONE);
> v9fs_string_init(&vs->path);
> vs->name_idx = 0;
>
> if (vs->name_idx < vs->nwnames) {
> v9fs_string_sprintf(&vs->path, "%s/%s",
> - vs->fidp->path.data, vs->wnames[vs->name_idx].data);
> - v9fs_string_copy(&vs->fidp->path, &vs->path);
> + vs->fidp->fsmap.path.data,
> + vs->wnames[vs->name_idx].data);
> + v9fs_string_copy(&vs->fidp->fsmap.path, &vs->path);
>
> - err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf);
> + err = v9fs_do_lstat(s, &vs->fidp->fsmap.path, &vs->stbuf);
> v9fs_walk_post_oldfid_lstat(s, vs, err);
> return;
> }
> @@ -1624,14 +1716,15 @@ static void v9fs_walk(V9fsState *s, V9fsPDU *pdu)
> vs->newfidp->uid = vs->fidp->uid;
> v9fs_string_init(&vs->path);
> vs->name_idx = 0;
> - v9fs_string_copy(&vs->newfidp->path, &vs->fidp->path);
> + v9fs_string_copy(&vs->newfidp->fsmap.path, &vs->fidp->fsmap.path);
>
> if (vs->name_idx < vs->nwnames) {
> - v9fs_string_sprintf(&vs->path, "%s/%s", vs->newfidp->path.data,
> + v9fs_string_sprintf(&vs->path, "%s/%s",
> + vs->newfidp->fsmap.path.data,
> vs->wnames[vs->name_idx].data);
> - v9fs_string_copy(&vs->newfidp->path, &vs->path);
> + v9fs_string_copy(&vs->newfidp->fsmap.path, &vs->path);
>
> - err = v9fs_do_lstat(s, &vs->newfidp->path, &vs->stbuf);
> + err = v9fs_do_lstat(s, &vs->newfidp->fsmap.path, &vs->stbuf);
> v9fs_walk_post_newfid_lstat(s, vs, err);
> return;
> }
> @@ -1665,11 +1758,11 @@ static int32_t get_iounit(V9fsState *s, V9fsString
> *name)
>
> static void v9fs_open_post_opendir(V9fsState *s, V9fsOpenState *vs, int err)
> {
> - if (vs->fidp->fs.dir == NULL) {
> + if (vs->fidp->fsmap.fs.dir == NULL) {
> err = -errno;
> goto out;
> }
> - vs->fidp->fid_type = P9_FID_DIR;
> + vs->fidp->fsmap.fid_type = P9_FID_DIR;
> vs->offset += pdu_marshal(vs->pdu, vs->offset, "Qd", &vs->qid, 0);
> err = vs->offset;
> out:
> @@ -1689,12 +1782,12 @@ static void v9fs_open_post_getiounit(V9fsState *s,
> V9fsOpenState *vs)
>
> static void v9fs_open_post_open(V9fsState *s, V9fsOpenState *vs, int err)
> {
> - if (vs->fidp->fs.fd == -1) {
> + if (vs->fidp->fsmap.fs.fd == -1) {
> err = -errno;
> goto out;
> }
> - vs->fidp->fid_type = P9_FID_FILE;
> - vs->iounit = get_iounit(s, &vs->fidp->path);
> + vs->fidp->fsmap.fid_type = P9_FID_FILE;
> + vs->iounit = get_iounit(s, &vs->fidp->fsmap.path);
> v9fs_open_post_getiounit(s, vs);
> return;
> out:
> @@ -1714,7 +1807,7 @@ static void v9fs_open_post_lstat(V9fsState *s,
> V9fsOpenState *vs, int err)
> stat_to_qid(&vs->stbuf, &vs->qid);
>
> if (S_ISDIR(vs->stbuf.st_mode)) {
> - vs->fidp->fs.dir = v9fs_do_opendir(s, &vs->fidp->path);
> + vs->fidp->fsmap.fs.dir = v9fs_do_opendir(s, &vs->fidp->fsmap.path);
> v9fs_open_post_opendir(s, vs, err);
> } else {
> if (s->proto_version == V9FS_PROTO_2000L) {
> @@ -1725,7 +1818,7 @@ static void v9fs_open_post_lstat(V9fsState *s,
> V9fsOpenState *vs, int err)
> } else {
> flags = omode_to_uflags(vs->mode);
> }
> - vs->fidp->fs.fd = v9fs_do_open(s, &vs->fidp->path, flags);
> + vs->fidp->fsmap.fs.fd = v9fs_do_open(s, &vs->fidp->fsmap.path,
> flags);
> v9fs_open_post_open(s, vs, err);
> }
> return;
> @@ -1757,9 +1850,9 @@ static void v9fs_open(V9fsState *s, V9fsPDU *pdu)
> goto out;
> }
>
> - BUG_ON(vs->fidp->fid_type != P9_FID_NONE);
> + BUG_ON(vs->fidp->fsmap.fid_type != P9_FID_NONE);
>
> - err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf);
> + err = v9fs_do_lstat(s, &vs->fidp->fsmap.path, &vs->stbuf);
>
> v9fs_open_post_lstat(s, vs, err);
> return;
> @@ -1771,16 +1864,16 @@ out:
> static void v9fs_post_lcreate(V9fsState *s, V9fsLcreateState *vs, int err)
> {
> if (err == 0) {
> - v9fs_string_copy(&vs->fidp->path, &vs->fullname);
> + v9fs_string_copy(&vs->fidp->fsmap.path, &vs->fullname);
> stat_to_qid(&vs->stbuf, &vs->qid);
> vs->offset += pdu_marshal(vs->pdu, vs->offset, "Qd", &vs->qid,
> vs->iounit);
> err = vs->offset;
> } else {
> - vs->fidp->fid_type = P9_FID_NONE;
> + vs->fidp->fsmap.fid_type = P9_FID_NONE;
> err = -errno;
> - if (vs->fidp->fs.fd > 0) {
> - close(vs->fidp->fs.fd);
> + if (vs->fidp->fsmap.fs.fd > 0) {
> + close(vs->fidp->fsmap.fs.fd);
> }
> }
>
> @@ -1806,11 +1899,11 @@ out:
> static void v9fs_lcreate_post_do_open2(V9fsState *s, V9fsLcreateState *vs,
> int err)
> {
> - if (vs->fidp->fs.fd == -1) {
> + if (vs->fidp->fsmap.fs.fd == -1) {
> err = -errno;
> goto out;
> }
> - vs->fidp->fid_type = P9_FID_FILE;
> + vs->fidp->fsmap.fid_type = P9_FID_FILE;
> vs->iounit = get_iounit(s, &vs->fullname);
> v9fs_lcreate_post_get_iounit(s, vs, err);
> return;
> @@ -1841,13 +1934,13 @@ static void v9fs_lcreate(V9fsState *s, V9fsPDU *pdu)
> goto out;
> }
>
> - v9fs_string_sprintf(&vs->fullname, "%s/%s", vs->fidp->path.data,
> + v9fs_string_sprintf(&vs->fullname, "%s/%s", vs->fidp->fsmap.path.data,
> vs->name.data);
>
> /* Ignore direct disk access hint until the server supports it. */
> flags &= ~O_DIRECT;
>
> - vs->fidp->fs.fd = v9fs_do_open2(s, vs->fullname.data, vs->fidp->uid,
> + vs->fidp->fsmap.fs.fd = v9fs_do_open2(s, vs->fullname.data,
> vs->fidp->uid,
> gid, flags, mode);
> v9fs_lcreate_post_do_open2(s, vs, err);
> return;
> @@ -1881,7 +1974,7 @@ static void v9fs_fsync(V9fsState *s, V9fsPDU *pdu)
> v9fs_post_do_fsync(s, pdu, err);
> return;
> }
> - err = v9fs_do_fsync(s, fidp->fs.fd, datasync);
> + err = v9fs_do_fsync(s, fidp->fsmap.fs.fd, datasync);
> v9fs_post_do_fsync(s, pdu, err);
> }
>
> @@ -1938,7 +2031,7 @@ static void v9fs_read_post_dir_lstat(V9fsState *s,
> V9fsReadState *vs,
> &vs->v9stat);
> if ((vs->len != (vs->v9stat.size + 2)) ||
> ((vs->count + vs->len) > vs->max_count)) {
> - v9fs_do_seekdir(s, vs->fidp->fs.dir, vs->dir_pos);
> + v9fs_do_seekdir(s, vs->fidp->fsmap.fs.dir, vs->dir_pos);
> v9fs_read_post_seekdir(s, vs, err);
> return;
> }
> @@ -1946,11 +2039,11 @@ static void v9fs_read_post_dir_lstat(V9fsState *s,
> V9fsReadState *vs,
> v9fs_stat_free(&vs->v9stat);
> v9fs_string_free(&vs->name);
> vs->dir_pos = vs->dent->d_off;
> - vs->dent = v9fs_do_readdir(s, vs->fidp->fs.dir);
> + vs->dent = v9fs_do_readdir(s, vs->fidp->fsmap.fs.dir);
> v9fs_read_post_readdir(s, vs, err);
> return;
> out:
> - v9fs_do_seekdir(s, vs->fidp->fs.dir, vs->dir_pos);
> + v9fs_do_seekdir(s, vs->fidp->fsmap.fs.dir, vs->dir_pos);
> v9fs_read_post_seekdir(s, vs, err);
> return;
>
> @@ -1961,7 +2054,7 @@ static void v9fs_read_post_readdir(V9fsState *s,
> V9fsReadState *vs, ssize_t err)
> if (vs->dent) {
> memset(&vs->v9stat, 0, sizeof(vs->v9stat));
> v9fs_string_init(&vs->name);
> - v9fs_string_sprintf(&vs->name, "%s/%s", vs->fidp->path.data,
> + v9fs_string_sprintf(&vs->name, "%s/%s", vs->fidp->fsmap.path.data,
> vs->dent->d_name);
> err = v9fs_do_lstat(s, &vs->name, &vs->stbuf);
> v9fs_read_post_dir_lstat(s, vs, err);
> @@ -1978,7 +2071,7 @@ static void v9fs_read_post_readdir(V9fsState *s,
> V9fsReadState *vs, ssize_t err)
>
> static void v9fs_read_post_telldir(V9fsState *s, V9fsReadState *vs, ssize_t
> err)
> {
> - vs->dent = v9fs_do_readdir(s, vs->fidp->fs.dir);
> + vs->dent = v9fs_do_readdir(s, vs->fidp->fsmap.fs.dir);
> v9fs_read_post_readdir(s, vs, err);
> return;
> }
> @@ -1986,7 +2079,7 @@ static void v9fs_read_post_telldir(V9fsState *s,
> V9fsReadState *vs, ssize_t err)
> static void v9fs_read_post_rewinddir(V9fsState *s, V9fsReadState *vs,
> ssize_t err)
> {
> - vs->dir_pos = v9fs_do_telldir(s, vs->fidp->fs.dir);
> + vs->dir_pos = v9fs_do_telldir(s, vs->fidp->fsmap.fs.dir);
> v9fs_read_post_telldir(s, vs, err);
> return;
> }
> @@ -2005,7 +2098,7 @@ static void v9fs_read_post_preadv(V9fsState *s,
> V9fsReadState *vs, ssize_t err)
> if (0) {
> print_sg(vs->sg, vs->cnt);
> }
> - vs->len = v9fs_do_preadv(s, vs->fidp->fs.fd, vs->sg, vs->cnt,
> + vs->len = v9fs_do_preadv(s, vs->fidp->fsmap.fs.fd, vs->sg,
> vs->cnt,
> vs->off);
> if (vs->len > 0) {
> vs->off += vs->len;
> @@ -2032,7 +2125,7 @@ static void v9fs_xattr_read(V9fsState *s, V9fsReadState
> *vs)
> int read_count;
> int64_t xattr_len;
>
> - xattr_len = vs->fidp->fs.xattr.len;
> + xattr_len = vs->fidp->fsmap.fs.xattr.len;
> read_count = xattr_len - vs->off;
> if (read_count > vs->count) {
> read_count = vs->count;
> @@ -2044,7 +2137,7 @@ static void v9fs_xattr_read(V9fsState *s, V9fsReadState
> *vs)
> }
> vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", read_count);
> vs->offset += pdu_pack(vs->pdu, vs->offset,
> - ((char *)vs->fidp->fs.xattr.value) + vs->off,
> + ((char *)vs->fidp->fsmap.fs.xattr.value) +
> vs->off,
> read_count);
> err = vs->offset;
> complete_pdu(s, vs->pdu, err);
> @@ -2072,20 +2165,20 @@ static void v9fs_read(V9fsState *s, V9fsPDU *pdu)
> goto out;
> }
>
> - if (vs->fidp->fid_type == P9_FID_DIR) {
> + if (vs->fidp->fsmap.fid_type == P9_FID_DIR) {
> vs->max_count = vs->count;
> vs->count = 0;
> if (vs->off == 0) {
> - v9fs_do_rewinddir(s, vs->fidp->fs.dir);
> + v9fs_do_rewinddir(s, vs->fidp->fsmap.fs.dir);
> }
> v9fs_read_post_rewinddir(s, vs, err);
> return;
> - } else if (vs->fidp->fid_type == P9_FID_FILE) {
> + } else if (vs->fidp->fsmap.fid_type == P9_FID_FILE) {
> vs->sg = vs->iov;
> pdu_marshal(vs->pdu, vs->offset + 4, "v", vs->sg, &vs->cnt);
> vs->sg = cap_sg(vs->sg, vs->count, &vs->cnt);
> if (vs->total <= vs->count) {
> - vs->len = v9fs_do_preadv(s, vs->fidp->fs.fd, vs->sg, vs->cnt,
> + vs->len = v9fs_do_preadv(s, vs->fidp->fsmap.fs.fd, vs->sg,
> vs->cnt,
> vs->off);
> if (vs->len > 0) {
> vs->off += vs->len;
> @@ -2094,7 +2187,7 @@ static void v9fs_read(V9fsState *s, V9fsPDU *pdu)
> v9fs_read_post_preadv(s, vs, err);
> }
> return;
> - } else if (vs->fidp->fid_type == P9_FID_XATTR) {
> + } else if (vs->fidp->fsmap.fid_type == P9_FID_XATTR) {
> v9fs_xattr_read(s, vs);
> return;
> } else {
> @@ -2143,7 +2236,7 @@ static void v9fs_readdir_post_readdir(V9fsState *s,
> V9fsReadDirState *vs)
>
> if ((vs->count + V9_READDIR_DATA_SZ) > vs->max_count) {
> /* Ran out of buffer. Set dir back to old position and return */
> - v9fs_do_seekdir(s, vs->fidp->fs.dir, vs->saved_dir_pos);
> + v9fs_do_seekdir(s, vs->fidp->fsmap.fs.dir, vs->saved_dir_pos);
> v9fs_readdir_post_seekdir(s, vs);
> return;
> }
> @@ -2164,7 +2257,7 @@ static void v9fs_readdir_post_readdir(V9fsState *s,
> V9fsReadDirState *vs)
> vs->count += len;
> v9fs_string_free(&vs->name);
> vs->saved_dir_pos = vs->dent->d_off;
> - vs->dent = v9fs_do_readdir(s, vs->fidp->fs.dir);
> + vs->dent = v9fs_do_readdir(s, vs->fidp->fsmap.fs.dir);
> v9fs_readdir_post_readdir(s, vs);
> return;
> }
> @@ -2178,14 +2271,14 @@ static void v9fs_readdir_post_readdir(V9fsState *s,
> V9fsReadDirState *vs)
>
> static void v9fs_readdir_post_telldir(V9fsState *s, V9fsReadDirState *vs)
> {
> - vs->dent = v9fs_do_readdir(s, vs->fidp->fs.dir);
> + vs->dent = v9fs_do_readdir(s, vs->fidp->fsmap.fs.dir);
> v9fs_readdir_post_readdir(s, vs);
> return;
> }
>
> static void v9fs_readdir_post_setdir(V9fsState *s, V9fsReadDirState *vs)
> {
> - vs->saved_dir_pos = v9fs_do_telldir(s, vs->fidp->fs.dir);
> + vs->saved_dir_pos = v9fs_do_telldir(s, vs->fidp->fsmap.fs.dir);
> v9fs_readdir_post_telldir(s, vs);
> return;
> }
> @@ -2206,15 +2299,15 @@ static void v9fs_readdir(V9fsState *s, V9fsPDU *pdu)
> &vs->max_count);
>
> vs->fidp = lookup_fid(s, fid);
> - if (vs->fidp == NULL || !(vs->fidp->fs.dir)) {
> + if (vs->fidp == NULL || !(vs->fidp->fsmap.fs.dir)) {
> err = -EINVAL;
> goto out;
> }
>
> if (vs->initial_offset == 0) {
> - v9fs_do_rewinddir(s, vs->fidp->fs.dir);
> + v9fs_do_rewinddir(s, vs->fidp->fsmap.fs.dir);
> } else {
> - v9fs_do_seekdir(s, vs->fidp->fs.dir, vs->initial_offset);
> + v9fs_do_seekdir(s, vs->fidp->fsmap.fs.dir, vs->initial_offset);
> }
>
> v9fs_readdir_post_setdir(s, vs);
> @@ -2241,7 +2334,7 @@ static void v9fs_write_post_pwritev(V9fsState *s,
> V9fsWriteState *vs,
> if (0) {
> print_sg(vs->sg, vs->cnt);
> }
> - vs->len = v9fs_do_pwritev(s, vs->fidp->fs.fd, vs->sg, vs->cnt,
> + vs->len = v9fs_do_pwritev(s, vs->fidp->fsmap.fs.fd, vs->sg,
> vs->cnt,
> vs->off);
> if (vs->len > 0) {
> vs->off += vs->len;
> @@ -2267,7 +2360,7 @@ static void v9fs_xattr_write(V9fsState *s,
> V9fsWriteState *vs)
> int write_count;
> int64_t xattr_len;
>
> - xattr_len = vs->fidp->fs.xattr.len;
> + xattr_len = vs->fidp->fsmap.fs.xattr.len;
> write_count = xattr_len - vs->off;
> if (write_count > vs->count) {
> write_count = vs->count;
> @@ -2281,7 +2374,7 @@ static void v9fs_xattr_write(V9fsState *s,
> V9fsWriteState *vs)
> }
> vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", write_count);
> err = vs->offset;
> - vs->fidp->fs.xattr.copied_len += write_count;
> + vs->fidp->fsmap.fs.xattr.copied_len += write_count;
> /*
> * Now copy the content from sg list
> */
> @@ -2291,7 +2384,7 @@ static void v9fs_xattr_write(V9fsState *s,
> V9fsWriteState *vs)
> } else {
> to_copy = write_count;
> }
> - memcpy((char *)vs->fidp->fs.xattr.value + vs->off,
> + memcpy((char *)vs->fidp->fsmap.fs.xattr.value + vs->off,
> vs->sg[i].iov_base, to_copy);
> /* updating vs->off since we are not using below */
> vs->off += to_copy;
> @@ -2325,12 +2418,12 @@ static void v9fs_write(V9fsState *s, V9fsPDU *pdu)
> goto out;
> }
>
> - if (vs->fidp->fid_type == P9_FID_FILE) {
> - if (vs->fidp->fs.fd == -1) {
> + if (vs->fidp->fsmap.fid_type == P9_FID_FILE) {
> + if (vs->fidp->fsmap.fs.fd == -1) {
> err = -EINVAL;
> goto out;
> }
> - } else if (vs->fidp->fid_type == P9_FID_XATTR) {
> + } else if (vs->fidp->fsmap.fid_type == P9_FID_XATTR) {
> /*
> * setxattr operation
> */
> @@ -2342,7 +2435,8 @@ static void v9fs_write(V9fsState *s, V9fsPDU *pdu)
> }
> vs->sg = cap_sg(vs->sg, vs->count, &vs->cnt);
> if (vs->total <= vs->count) {
> - vs->len = v9fs_do_pwritev(s, vs->fidp->fs.fd, vs->sg, vs->cnt,
> vs->off);
> + vs->len = v9fs_do_pwritev(s, vs->fidp->fsmap.fs.fd,
> + vs->sg, vs->cnt, vs->off);
> if (vs->len > 0) {
> vs->off += vs->len;
> }
> @@ -2358,7 +2452,7 @@ out:
> static void v9fs_create_post_getiounit(V9fsState *s, V9fsCreateState *vs)
> {
> int err;
> - v9fs_string_copy(&vs->fidp->path, &vs->fullname);
> + v9fs_string_copy(&vs->fidp->fsmap.path, &vs->fullname);
> stat_to_qid(&vs->stbuf, &vs->qid);
>
> vs->offset += pdu_marshal(vs->pdu, vs->offset, "Qd", &vs->qid,
> vs->iounit);
> @@ -2374,7 +2468,7 @@ static void v9fs_create_post_getiounit(V9fsState *s,
> V9fsCreateState *vs)
> static void v9fs_post_create(V9fsState *s, V9fsCreateState *vs, int err)
> {
> if (err == 0) {
> - vs->iounit = get_iounit(s, &vs->fidp->path);
> + vs->iounit = get_iounit(s, &vs->fidp->fsmap.path);
> v9fs_create_post_getiounit(s, vs);
> return;
> }
> @@ -2397,10 +2491,10 @@ static void v9fs_create_post_perms(V9fsState *s,
> V9fsCreateState *vs, int err)
> static void v9fs_create_post_opendir(V9fsState *s, V9fsCreateState *vs,
> int err)
> {
> - if (!vs->fidp->fs.dir) {
> + if (!vs->fidp->fsmap.fs.dir) {
> err = -errno;
> }
> - vs->fidp->fid_type = P9_FID_DIR;
> + vs->fidp->fsmap.fid_type = P9_FID_DIR;
> v9fs_post_create(s, vs, err);
> }
>
> @@ -2412,7 +2506,7 @@ static void v9fs_create_post_dir_lstat(V9fsState *s,
> V9fsCreateState *vs,
> goto out;
> }
>
> - vs->fidp->fs.dir = v9fs_do_opendir(s, &vs->fullname);
> + vs->fidp->fsmap.fs.dir = v9fs_do_opendir(s, &vs->fullname);
> v9fs_create_post_opendir(s, vs, err);
> return;
>
> @@ -2438,8 +2532,8 @@ out:
> static void v9fs_create_post_fstat(V9fsState *s, V9fsCreateState *vs, int
> err)
> {
> if (err) {
> - vs->fidp->fid_type = P9_FID_NONE;
> - close(vs->fidp->fs.fd);
> + vs->fidp->fsmap.fid_type = P9_FID_NONE;
> + close(vs->fidp->fsmap.fs.fd);
> err = -errno;
> }
> v9fs_post_create(s, vs, err);
> @@ -2448,12 +2542,12 @@ static void v9fs_create_post_fstat(V9fsState *s,
> V9fsCreateState *vs, int err)
>
> static void v9fs_create_post_open2(V9fsState *s, V9fsCreateState *vs, int
> err)
> {
> - if (vs->fidp->fs.fd == -1) {
> + if (vs->fidp->fsmap.fs.fd == -1) {
> err = -errno;
> goto out;
> }
> - vs->fidp->fid_type = P9_FID_FILE;
> - err = v9fs_do_fstat(s, vs->fidp->fs.fd, &vs->stbuf);
> + vs->fidp->fsmap.fid_type = P9_FID_FILE;
> + err = v9fs_do_fstat(s, vs->fidp->fsmap.fs.fd, &vs->stbuf);
> v9fs_create_post_fstat(s, vs, err);
>
> return;
> @@ -2486,7 +2580,7 @@ static void v9fs_create_post_lstat(V9fsState *s,
> V9fsCreateState *vs, int err)
> err = -errno;
> v9fs_post_create(s, vs, err);
> }
> - err = v9fs_do_link(s, &nfidp->path, &vs->fullname);
> + err = v9fs_do_link(s, &nfidp->fsmap.path, &vs->fullname);
> v9fs_create_post_perms(s, vs, err);
> } else if (vs->perm & P9_STAT_MODE_DEVICE) {
> char ctype;
> @@ -2524,9 +2618,11 @@ static void v9fs_create_post_lstat(V9fsState *s,
> V9fsCreateState *vs, int err)
> 0, vs->fidp->uid, -1);
> v9fs_post_create(s, vs, err);
> } else {
> - vs->fidp->fs.fd = v9fs_do_open2(s, vs->fullname.data, vs->fidp->uid,
> - -1, omode_to_uflags(vs->mode)|O_CREAT, vs->perm);
> -
> + vs->fidp->fsmap.fs.fd = v9fs_do_open2(s, vs->fullname.data,
> + vs->fidp->uid,
> + -1,
> +
> omode_to_uflags(vs->mode)|O_CREAT,
> + vs->perm);
> v9fs_create_post_open2(s, vs, err);
> }
>
> @@ -2557,7 +2653,7 @@ static void v9fs_create(V9fsState *s, V9fsPDU *pdu)
> goto out;
> }
>
> - v9fs_string_sprintf(&vs->fullname, "%s/%s", vs->fidp->path.data,
> + v9fs_string_sprintf(&vs->fullname, "%s/%s", vs->fidp->fsmap.path.data,
> vs->name.data);
>
> err = v9fs_do_lstat(s, &vs->fullname, &vs->stbuf);
> @@ -2620,7 +2716,7 @@ static void v9fs_symlink(V9fsState *s, V9fsPDU *pdu)
> goto out;
> }
>
> - v9fs_string_sprintf(&vs->fullname, "%s/%s", vs->dfidp->path.data,
> + v9fs_string_sprintf(&vs->fullname, "%s/%s", vs->dfidp->fsmap.path.data,
> vs->name.data);
> err = v9fs_do_symlink(s, vs->dfidp, vs->symname.data,
> vs->fullname.data, gid);
> @@ -2664,9 +2760,9 @@ static void v9fs_link(V9fsState *s, V9fsPDU *pdu)
> goto out;
> }
>
> - v9fs_string_sprintf(&fullname, "%s/%s", dfidp->path.data, name.data);
> + v9fs_string_sprintf(&fullname, "%s/%s", dfidp->fsmap.path.data,
> name.data);
> err = offset;
> - err = v9fs_do_link(s, &oldfidp->path, &fullname);
> + err = v9fs_do_link(s, &oldfidp->fsmap.path, &fullname);
> if (err) {
> err = -errno;
> }
> @@ -2710,8 +2806,12 @@ static void v9fs_remove(V9fsState *s, V9fsPDU *pdu)
> err = -EINVAL;
> goto out;
> }
> -
> - err = v9fs_do_remove(s, &vs->fidp->path);
> + /*
> + * IF the file is unlinked, we cannot reopen
> + * the file later. So don't reclaim fd
> + */
> + v9fs_mark_fids_unreclaim(s, &vs->fidp->fsmap.path);
> + err = v9fs_do_remove(s, &vs->fidp->fsmap.path);
> v9fs_remove_post_remove(s, vs, err);
> return;
>
> @@ -2740,7 +2840,7 @@ static void v9fs_wstat_post_rename(V9fsState *s,
> V9fsWstatState *vs, int err)
> goto out;
> }
> if (vs->v9stat.length != -1) {
> - if (v9fs_do_truncate(s, &vs->fidp->path, vs->v9stat.length) < 0) {
> + if (v9fs_do_truncate(s, &vs->fidp->fsmap.path, vs->v9stat.length) <
> 0) {
> err = -errno;
> }
> }
> @@ -2768,15 +2868,15 @@ static int v9fs_complete_rename(V9fsState *s,
> V9fsRenameState *vs)
> goto out;
> }
>
> - BUG_ON(dirfidp->fid_type != P9_FID_NONE);
> + BUG_ON(dirfidp->fsmap.fid_type != P9_FID_NONE);
>
> - new_name = qemu_mallocz(dirfidp->path.size + vs->name.size + 2);
> + new_name = qemu_mallocz(dirfidp->fsmap.path.size + vs->name.size +
> 2);
>
> - strcpy(new_name, dirfidp->path.data);
> + strcpy(new_name, dirfidp->fsmap.path.data);
> strcat(new_name, "/");
> - strcat(new_name + dirfidp->path.size, vs->name.data);
> + strcat(new_name + dirfidp->fsmap.path.size, vs->name.data);
> } else {
> - old_name = vs->fidp->path.data;
> + old_name = vs->fidp->fsmap.path.data;
> end = strrchr(old_name, '/');
> if (end) {
> end++;
> @@ -2793,8 +2893,8 @@ static int v9fs_complete_rename(V9fsState *s,
> V9fsRenameState *vs)
> vs->name.data = qemu_strdup(new_name);
> vs->name.size = strlen(new_name);
>
> - if (strcmp(new_name, vs->fidp->path.data) != 0) {
> - if (v9fs_do_rename(s, &vs->fidp->path, &vs->name)) {
> + if (strcmp(new_name, vs->fidp->fsmap.path.data) != 0) {
> + if (v9fs_do_rename(s, &vs->fidp->fsmap.path, &vs->name)) {
> err = -errno;
> } else {
> V9fsFidState *fidp;
> @@ -2810,14 +2910,14 @@ static int v9fs_complete_rename(V9fsState *s,
> V9fsRenameState *vs)
> */
> continue;
> }
> - if (!strncmp(vs->fidp->path.data, fidp->path.data,
> - strlen(vs->fidp->path.data))) {
> + if (!strncmp(vs->fidp->fsmap.path.data,
> fidp->fsmap.path.data,
> + strlen(vs->fidp->fsmap.path.data))) {
> /* replace the name */
> - v9fs_fix_path(&fidp->path, &vs->name,
> - strlen(vs->fidp->path.data));
> + v9fs_fix_path(&fidp->fsmap.path, &vs->name,
> + strlen(vs->fidp->fsmap.path.data));
> }
> }
> - v9fs_string_copy(&vs->fidp->path, &vs->name);
> + v9fs_string_copy(&vs->fidp->fsmap.path, &vs->name);
> }
> }
> out:
> @@ -2878,7 +2978,7 @@ static void v9fs_rename(V9fsState *s, V9fsPDU *pdu)
> goto out;
> }
>
> - BUG_ON(vs->fidp->fid_type != P9_FID_NONE);
> + BUG_ON(vs->fidp->fsmap.fid_type != P9_FID_NONE);
>
> err = v9fs_complete_rename(s, vs);
> v9fs_rename_post_rename(s, vs, err);
> @@ -2895,7 +2995,7 @@ static void v9fs_wstat_post_utime(V9fsState *s,
> V9fsWstatState *vs, int err)
> }
>
> if (vs->v9stat.n_gid != -1 || vs->v9stat.n_uid != -1) {
> - if (v9fs_do_chown(s, &vs->fidp->path, vs->v9stat.n_uid,
> + if (v9fs_do_chown(s, &vs->fidp->fsmap.path, vs->v9stat.n_uid,
> vs->v9stat.n_gid)) {
> err = -errno;
> }
> @@ -2930,7 +3030,7 @@ static void v9fs_wstat_post_chmod(V9fsState *s,
> V9fsWstatState *vs, int err)
> times[1].tv_nsec = UTIME_OMIT;
> }
>
> - if (v9fs_do_utimensat(s, &vs->fidp->path, times)) {
> + if (v9fs_do_utimensat(s, &vs->fidp->fsmap.path, times)) {
> err = -errno;
> }
> }
> @@ -2972,7 +3072,7 @@ static void v9fs_wstat_post_lstat(V9fsState *s,
> V9fsWstatState *vs, int err)
> goto out;
> }
>
> - if (v9fs_do_chmod(s, &vs->fidp->path, v9mode_to_mode(vs->v9stat.mode,
> + if (v9fs_do_chmod(s, &vs->fidp->fsmap.path,
> v9mode_to_mode(vs->v9stat.mode,
> &vs->v9stat.extension))) {
> err = -errno;
> }
> @@ -3005,13 +3105,13 @@ static void v9fs_wstat(V9fsState *s, V9fsPDU *pdu)
>
> /* do we need to sync the file? */
> if (donttouch_stat(&vs->v9stat)) {
> - err = v9fs_do_fsync(s, vs->fidp->fs.fd, 0);
> + err = v9fs_do_fsync(s, vs->fidp->fsmap.fs.fd, 0);
> v9fs_wstat_post_fsync(s, vs, err);
> return;
> }
>
> if (vs->v9stat.mode != -1) {
> - err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf);
> + err = v9fs_do_lstat(s, &vs->fidp->fsmap.path, &vs->stbuf);
> v9fs_wstat_post_lstat(s, vs, err);
> return;
> }
> @@ -3089,7 +3189,7 @@ static void v9fs_statfs(V9fsState *s, V9fsPDU *pdu)
> goto out;
> }
>
> - err = v9fs_do_statfs(s, &vs->fidp->path, &vs->stbuf);
> + err = v9fs_do_statfs(s, &vs->fidp->fsmap.path, &vs->stbuf);
> v9fs_statfs_post_statfs(s, vs, err);
> return;
>
> @@ -3156,7 +3256,8 @@ static void v9fs_mknod(V9fsState *s, V9fsPDU *pdu)
> goto out;
> }
>
> - v9fs_string_sprintf(&vs->fullname, "%s/%s", fidp->path.data,
> vs->name.data);
> + v9fs_string_sprintf(&vs->fullname, "%s/%s", fidp->fsmap.path.data,
> + vs->name.data);
> err = v9fs_do_mknod(s, vs->fullname.data, mode, makedev(major, minor),
> fidp->uid, gid);
> v9fs_mknod_post_mknod(s, vs, err);
> @@ -3205,7 +3306,7 @@ static void v9fs_lock(V9fsState *s, V9fsPDU *pdu)
> goto out;
> }
>
> - err = v9fs_do_fstat(s, vs->fidp->fs.fd, &vs->stbuf);
> + err = v9fs_do_fstat(s, vs->fidp->fsmap.fs.fd, &vs->stbuf);
> if (err < 0) {
> err = -errno;
> goto out;
> @@ -3243,7 +3344,7 @@ static void v9fs_getlock(V9fsState *s, V9fsPDU *pdu)
> goto out;
> }
>
> - err = v9fs_do_fstat(s, vs->fidp->fs.fd, &vs->stbuf);
> + err = v9fs_do_fstat(s, vs->fidp->fsmap.fs.fd, &vs->stbuf);
> if (err < 0) {
> err = -errno;
> goto out;
> @@ -3315,7 +3416,8 @@ static void v9fs_mkdir(V9fsState *s, V9fsPDU *pdu)
> goto out;
> }
>
> - v9fs_string_sprintf(&vs->fullname, "%s/%s", fidp->path.data,
> vs->name.data);
> + v9fs_string_sprintf(&vs->fullname, "%s/%s", fidp->fsmap.path.data,
> + vs->name.data);
> err = v9fs_do_mkdir(s, vs->fullname.data, mode, fidp->uid, gid);
> v9fs_mkdir_post_mkdir(s, vs, err);
> return;
> @@ -3354,14 +3456,14 @@ static void v9fs_post_xattr_check(V9fsState *s,
> V9fsXattrState *vs, ssize_t err)
> /*
> * Read the xattr value
> */
> - vs->xattr_fidp->fs.xattr.len = vs->size;
> - vs->xattr_fidp->fid_type = P9_FID_XATTR;
> - vs->xattr_fidp->fs.xattr.copied_len = -1;
> + vs->xattr_fidp->fsmap.fs.xattr.len = vs->size;
> + vs->xattr_fidp->fsmap.fid_type = P9_FID_XATTR;
> + vs->xattr_fidp->fsmap.fs.xattr.copied_len = -1;
> if (vs->size) {
> - vs->xattr_fidp->fs.xattr.value = qemu_malloc(vs->size);
> - err = v9fs_do_lgetxattr(s, &vs->xattr_fidp->path,
> - &vs->name, vs->xattr_fidp->fs.xattr.value,
> - vs->xattr_fidp->fs.xattr.len);
> + vs->xattr_fidp->fsmap.fs.xattr.value = qemu_malloc(vs->size);
> + err = v9fs_do_lgetxattr(s, &vs->xattr_fidp->fsmap.path,
> + &vs->name,
> vs->xattr_fidp->fsmap.fs.xattr.value,
> + vs->xattr_fidp->fsmap.fs.xattr.len);
> }
> v9fs_post_xattr_getvalue(s, vs, err);
> return;
> @@ -3399,14 +3501,14 @@ static void v9fs_post_lxattr_check(V9fsState *s,
> /*
> * Read the xattr value
> */
> - vs->xattr_fidp->fs.xattr.len = vs->size;
> - vs->xattr_fidp->fid_type = P9_FID_XATTR;
> - vs->xattr_fidp->fs.xattr.copied_len = -1;
> + vs->xattr_fidp->fsmap.fs.xattr.len = vs->size;
> + vs->xattr_fidp->fsmap.fid_type = P9_FID_XATTR;
> + vs->xattr_fidp->fsmap.fs.xattr.copied_len = -1;
> if (vs->size) {
> - vs->xattr_fidp->fs.xattr.value = qemu_malloc(vs->size);
> - err = v9fs_do_llistxattr(s, &vs->xattr_fidp->path,
> - vs->xattr_fidp->fs.xattr.value,
> - vs->xattr_fidp->fs.xattr.len);
> + vs->xattr_fidp->fsmap.fs.xattr.value = qemu_malloc(vs->size);
> + err = v9fs_do_llistxattr(s, &vs->xattr_fidp->fsmap.path,
> + vs->xattr_fidp->fsmap.fs.xattr.value,
> + vs->xattr_fidp->fsmap.fs.xattr.len);
> }
> v9fs_post_lxattr_getvalue(s, vs, err);
> return;
> @@ -3439,12 +3541,12 @@ static void v9fs_xattrwalk(V9fsState *s, V9fsPDU *pdu)
> goto out;
> }
>
> - v9fs_string_copy(&vs->xattr_fidp->path, &vs->file_fidp->path);
> + v9fs_string_copy(&vs->xattr_fidp->fsmap.path,
> &vs->file_fidp->fsmap.path);
> if (vs->name.data[0] == 0) {
> /*
> * listxattr request. Get the size first
> */
> - vs->size = v9fs_do_llistxattr(s, &vs->xattr_fidp->path,
> + vs->size = v9fs_do_llistxattr(s, &vs->xattr_fidp->fsmap.path,
> NULL, 0);
> if (vs->size < 0) {
> err = vs->size;
> @@ -3456,7 +3558,7 @@ static void v9fs_xattrwalk(V9fsState *s, V9fsPDU *pdu)
> * specific xattr fid. We check for xattr
> * presence also collect the xattr size
> */
> - vs->size = v9fs_do_lgetxattr(s, &vs->xattr_fidp->path,
> + vs->size = v9fs_do_lgetxattr(s, &vs->xattr_fidp->fsmap.path,
> &vs->name, NULL, 0);
> if (vs->size < 0) {
> err = vs->size;
> @@ -3492,16 +3594,16 @@ static void v9fs_xattrcreate(V9fsState *s, V9fsPDU
> *pdu)
>
> /* Make the file fid point to xattr */
> vs->xattr_fidp = vs->file_fidp;
> - vs->xattr_fidp->fid_type = P9_FID_XATTR;
> - vs->xattr_fidp->fs.xattr.copied_len = 0;
> - vs->xattr_fidp->fs.xattr.len = vs->size;
> - vs->xattr_fidp->fs.xattr.flags = flags;
> - v9fs_string_init(&vs->xattr_fidp->fs.xattr.name);
> - v9fs_string_copy(&vs->xattr_fidp->fs.xattr.name, &vs->name);
> + vs->xattr_fidp->fsmap.fid_type = P9_FID_XATTR;
> + vs->xattr_fidp->fsmap.fs.xattr.copied_len = 0;
> + vs->xattr_fidp->fsmap.fs.xattr.len = vs->size;
> + vs->xattr_fidp->fsmap.fs.xattr.flags = flags;
> + v9fs_string_init(&vs->xattr_fidp->fsmap.fs.xattr.name);
> + v9fs_string_copy(&vs->xattr_fidp->fsmap.fs.xattr.name, &vs->name);
> if (vs->size)
> - vs->xattr_fidp->fs.xattr.value = qemu_malloc(vs->size);
> + vs->xattr_fidp->fsmap.fs.xattr.value = qemu_malloc(vs->size);
> else
> - vs->xattr_fidp->fs.xattr.value = NULL;
> + vs->xattr_fidp->fsmap.fs.xattr.value = NULL;
>
> out:
> complete_pdu(s, vs->pdu, err);
> @@ -3544,7 +3646,7 @@ static void v9fs_readlink(V9fsState *s, V9fsPDU *pdu)
> }
>
> v9fs_string_init(&vs->target);
> - err = v9fs_do_readlink(s, &fidp->path, &vs->target);
> + err = v9fs_do_readlink(s, &fidp->fsmap.path, &vs->target);
> v9fs_readlink_post_readlink(s, vs, err);
> return;
> out:
> diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h
> index 6c23319..82b4252 100644
> --- a/hw/9pfs/virtio-9p.h
> +++ b/hw/9pfs/virtio-9p.h
> @@ -101,7 +101,10 @@ enum p9_proto_version {
> #define P9_NOTAG (u16)(~0)
> #define P9_NOFID (u32)(~0)
> #define P9_MAXWELEM 16
> +#define P9_FD_RECLAIM_THRES 100
>
> +#define FID_REFERENCED 0x1
> +#define FID_NON_RECLAIMABLE 0x2
> /*
> * ample room for Twrite/Rread header
> * size[4] Tread/Twrite tag[2] fid[4] offset[8] count[4]
> @@ -185,17 +188,22 @@ typedef struct V9fsXattr
> int flags;
> } V9fsXattr;
>
> +typedef struct V9fsfidmap {
> + union {
> + int fd;
> + DIR *dir;
> + V9fsXattr xattr;
> + } fs;
> + int fid_type;
> + V9fsString path;
> + int flags;
> +} V9fsFidMap;
> +
> struct V9fsFidState
> {
> - int fid_type;
> int32_t fid;
> - V9fsString path;
> - union {
> - int fd;
> - DIR *dir;
> - V9fsXattr xattr;
> - } fs;
> uid_t uid;
> + V9fsFidMap fsmap;
> V9fsFidState *next;
> };
>