diff mbox

[4/5] hw/9pfs: use g_strdup_printf() instead of PATH_MAX limitation

Message ID 1394205380-31875-5-git-send-email-aneesh.kumar@linux.vnet.ibm.com
State New
Headers show

Commit Message

Aneesh Kumar K.V March 7, 2014, 3:16 p.m. UTC
From: Chen Gang <gang.chen.5i5j@gmail.com>

When path is truncated by PATH_MAX limitation, it causes QEMU to access
incorrect file. So use original full path instead of PATH_MAX within
9pfs (need check/process ENOMEM for related memory allocation).

The related test:

 - Environments (for qemu-devel):

   - Host is under fedora17 desktop with ext4fs:

     qemu-system-x86_64 -hda test.img -m 1024 \
       -net nic,vlan=4,model=virtio,macaddr=00:16:35:AF:94:04 \
       -net tap,vlan=4,ifname=tap4,script=no,downscript=no \
       -device virtio-9p-pci,id=fs0,fsdev=fsdev0,mount_tag=hostshare \
       -fsdev local,security_model=passthrough,id=fsdev0,\
         path=/upstream/vm/data/share/1234567890abcdefghijklmnopqrstuvwxyz\
           ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890acdefghijklmnopqrstuvwxyz\
           ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890/111111111111111111111111111\
           1111111111111111111111111111111111111111111111111111222222222222\
           2222222222222222222222222222222222222222222222222222222222222222\
           2222222222222222222222222222222222233333333333333333333333333333\
           3333333333333333333333333333333333

    - Guest is ubuntu12 server with 9pfs.

      mount -t 9p -o trans=virtio,version=9p2000.L hostshare /share

    - Limitations:

      full path limitation is PATH_MAX (4096B include nul) under Linux.
      file/dir node name maximized length is 256 (include nul) under ext4.

 - Special test:

    Under host, modify the file: "/upstream/vm/data/share/1234567890abcdefg\
      hijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890acdefghijklmno\
      pqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890/111111111111111111111\
      111111111111111111111111111111111111111111111111111111111122222222222\
      222222222222222222222222222222222222222222222222222222222222222222222\
      222222222222222222222222222222233333333333333333333333333333333333333\
      3333333333333333333333333/4444444444444444444444444444444444444444444\
      444444444444444444444444444444444444444444444444444444444444444444444\
      444444444444444444444444444444444444444444444444444444444444444444444\
      444444444444444444444444444444444444444/55555555555555555555555555555\
      555555555555555555555555555555555555555555555555555555555555555555555\
      555555555555555555555555555555555555555555555555555555555555555555555\
      555555555555555555555555555555555555555555555555555555555555555555555\
      55555555/666666666666666666666666666666666666666666666666666666666666\
      666666666666666666666666666666666666666666666666666666666666666666666\
      666666666666666666666666666666666666666666666666666666666666666666666\
      666666666666666666666/77777777777777777777777777777777777777777777777\
      777777777777777777777777777777777777777777777777777777777777777777777\
      777777777777777777777777777777777777777777777777777777777777777777777\
      77777777777777777777777777777777777777777777777777777777777/888888888\
      888888888888888888888888888888888888888888888888888888888888888888888\
      888888888888888888888888888888888888888888888888888888888888888888888\
      888888888888888888888888888888888888888888888888888888888888888888888\
      888888888/99999999999999999999999999999999999999999999999999999999999\
      999999999999999999999999999999999999999999999999999999999999999999999\
      999999999999999999999999999999999999999999999999999999999999999999999\
      99999999999999999999999999999999999999999/000000000000000000000000000\
      000000000000000000000000000000000000000000000000000000000000000000000\
      000000000000000000000000000000000000000000000000000000000000000000000\
      000000000000000000000000000000000000000000000000/aaaaaaaaaaaaaaaaaaaa\
      aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
      aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
      aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbb\
      bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\
      bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\
      bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ccccccccc\
      ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc\
      ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc\
      ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc\
      cccccccccc/dddddddddddddddddddddddddddddddddddddddddddddddddddddddddd\
      ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd\
      ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd\
      dddddddddddddddddddddd/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\
      eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\
      eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\
      eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee/fffffffffffffff\
      fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\
      fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\
      ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff/gggggggggg\
      ggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg\
      ggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg\
      ggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg\
      ggggggggggggggggggggggg/iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii\
      iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii\
      iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii\
      iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii/jjjjjjjjjjjjj\
      jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj\
      jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj/ppppppppppppppppppppp\
      ppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp\
      ppppppppppppppppppppppppppppppppppppppp/test1234567890file.log"
        (need enter dir firstly, then modify file, or can not open it).

   Under guest, still allow modify "test1234567890file.log" (will generate
   "test123456" file with contents).

   After apply this patch, can not open "test1234567890file.log" under guest
   (permission denied).

 - Common test:

   All are still OK after apply this path.

     "mkdir -p", "create/open file/dir", "modify file/dir", "rm file/dir".
     change various mount point paths under host and/or guest.

Signed-off-by: Chen Gang <gang.chen.5i5j@gmail.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 hw/9pfs/cofs.c                 |  48 +++++--
 hw/9pfs/virtio-9p-handle.c     |   9 +-
 hw/9pfs/virtio-9p-local.c      | 287 +++++++++++++++++++++++++++--------------
 hw/9pfs/virtio-9p-posix-acl.c  |  52 ++++++--
 hw/9pfs/virtio-9p-xattr-user.c |  27 +++-
 hw/9pfs/virtio-9p-xattr.c      |   9 +-
 hw/9pfs/virtio-9p-xattr.h      |  27 +++-
 hw/9pfs/virtio-9p.h            |   6 +-
 8 files changed, 316 insertions(+), 149 deletions(-)

Comments

Chen Gang March 8, 2014, 1:58 p.m. UTC | #1
OK, thanks.

Next, I will/should continue to analyse the performance issue for 9pfs
when users drop into a long directory path under bash shell.

Although I am not quite sure, hope I can find the root cause within this
month (2014-03-31).

Welcome any suggestions, discussions, and completions for it.

Thanks.

On 03/07/2014 11:16 PM, Aneesh Kumar K.V wrote:
> From: Chen Gang <gang.chen.5i5j@gmail.com>
> 
> When path is truncated by PATH_MAX limitation, it causes QEMU to access
> incorrect file. So use original full path instead of PATH_MAX within
> 9pfs (need check/process ENOMEM for related memory allocation).
> 
> The related test:
> 
>  - Environments (for qemu-devel):
> 
>    - Host is under fedora17 desktop with ext4fs:
> 
>      qemu-system-x86_64 -hda test.img -m 1024 \
>        -net nic,vlan=4,model=virtio,macaddr=00:16:35:AF:94:04 \
>        -net tap,vlan=4,ifname=tap4,script=no,downscript=no \
>        -device virtio-9p-pci,id=fs0,fsdev=fsdev0,mount_tag=hostshare \
>        -fsdev local,security_model=passthrough,id=fsdev0,\
>          path=/upstream/vm/data/share/1234567890abcdefghijklmnopqrstuvwxyz\
>            ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890acdefghijklmnopqrstuvwxyz\
>            ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890/111111111111111111111111111\
>            1111111111111111111111111111111111111111111111111111222222222222\
>            2222222222222222222222222222222222222222222222222222222222222222\
>            2222222222222222222222222222222222233333333333333333333333333333\
>            3333333333333333333333333333333333
> 
>     - Guest is ubuntu12 server with 9pfs.
> 
>       mount -t 9p -o trans=virtio,version=9p2000.L hostshare /share
> 
>     - Limitations:
> 
>       full path limitation is PATH_MAX (4096B include nul) under Linux.
>       file/dir node name maximized length is 256 (include nul) under ext4.
> 
>  - Special test:
> 
>     Under host, modify the file: "/upstream/vm/data/share/1234567890abcdefg\
>       hijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890acdefghijklmno\
>       pqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890/111111111111111111111\
>       111111111111111111111111111111111111111111111111111111111122222222222\
>       222222222222222222222222222222222222222222222222222222222222222222222\
>       222222222222222222222222222222233333333333333333333333333333333333333\
>       3333333333333333333333333/4444444444444444444444444444444444444444444\
>       444444444444444444444444444444444444444444444444444444444444444444444\
>       444444444444444444444444444444444444444444444444444444444444444444444\
>       444444444444444444444444444444444444444/55555555555555555555555555555\
>       555555555555555555555555555555555555555555555555555555555555555555555\
>       555555555555555555555555555555555555555555555555555555555555555555555\
>       555555555555555555555555555555555555555555555555555555555555555555555\
>       55555555/666666666666666666666666666666666666666666666666666666666666\
>       666666666666666666666666666666666666666666666666666666666666666666666\
>       666666666666666666666666666666666666666666666666666666666666666666666\
>       666666666666666666666/77777777777777777777777777777777777777777777777\
>       777777777777777777777777777777777777777777777777777777777777777777777\
>       777777777777777777777777777777777777777777777777777777777777777777777\
>       77777777777777777777777777777777777777777777777777777777777/888888888\
>       888888888888888888888888888888888888888888888888888888888888888888888\
>       888888888888888888888888888888888888888888888888888888888888888888888\
>       888888888888888888888888888888888888888888888888888888888888888888888\
>       888888888/99999999999999999999999999999999999999999999999999999999999\
>       999999999999999999999999999999999999999999999999999999999999999999999\
>       999999999999999999999999999999999999999999999999999999999999999999999\
>       99999999999999999999999999999999999999999/000000000000000000000000000\
>       000000000000000000000000000000000000000000000000000000000000000000000\
>       000000000000000000000000000000000000000000000000000000000000000000000\
>       000000000000000000000000000000000000000000000000/aaaaaaaaaaaaaaaaaaaa\
>       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
>       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
>       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbb\
>       bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\
>       bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\
>       bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ccccccccc\
>       ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc\
>       ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc\
>       ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc\
>       cccccccccc/dddddddddddddddddddddddddddddddddddddddddddddddddddddddddd\
>       ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd\
>       ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd\
>       dddddddddddddddddddddd/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\
>       eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\
>       eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\
>       eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee/fffffffffffffff\
>       fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\
>       fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\
>       ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff/gggggggggg\
>       ggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg\
>       ggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg\
>       ggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg\
>       ggggggggggggggggggggggg/iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii\
>       iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii\
>       iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii\
>       iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii/jjjjjjjjjjjjj\
>       jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj\
>       jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj/ppppppppppppppppppppp\
>       ppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp\
>       ppppppppppppppppppppppppppppppppppppppp/test1234567890file.log"
>         (need enter dir firstly, then modify file, or can not open it).
> 
>    Under guest, still allow modify "test1234567890file.log" (will generate
>    "test123456" file with contents).
> 
>    After apply this patch, can not open "test1234567890file.log" under guest
>    (permission denied).
> 
>  - Common test:
> 
>    All are still OK after apply this path.
> 
>      "mkdir -p", "create/open file/dir", "modify file/dir", "rm file/dir".
>      change various mount point paths under host and/or guest.
> 
> Signed-off-by: Chen Gang <gang.chen.5i5j@gmail.com>
> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
> ---
>  hw/9pfs/cofs.c                 |  48 +++++--
>  hw/9pfs/virtio-9p-handle.c     |   9 +-
>  hw/9pfs/virtio-9p-local.c      | 287 +++++++++++++++++++++++++++--------------
>  hw/9pfs/virtio-9p-posix-acl.c  |  52 ++++++--
>  hw/9pfs/virtio-9p-xattr-user.c |  27 +++-
>  hw/9pfs/virtio-9p-xattr.c      |   9 +-
>  hw/9pfs/virtio-9p-xattr.h      |  27 +++-
>  hw/9pfs/virtio-9p.h            |   6 +-
>  8 files changed, 316 insertions(+), 149 deletions(-)
> 
> diff --git a/hw/9pfs/cofs.c b/hw/9pfs/cofs.c
> index 389105074852..0aba70ad792f 100644
> --- a/hw/9pfs/cofs.c
> +++ b/hw/9pfs/cofs.c
> @@ -17,35 +17,55 @@
>  #include "block/coroutine.h"
>  #include "virtio-9p-coth.h"
>  
> +static ssize_t __readlink(V9fsState *s, V9fsPath *path, V9fsString *buf)
> +{
> +    ssize_t len, maxlen = PATH_MAX;
> +
> +    buf->data = g_malloc(PATH_MAX);
> +    for (;;) {
> +        len = s->ops->readlink(&s->ctx, path, buf->data, maxlen);
> +        if (len < 0) {
> +            g_free(buf->data);
> +            buf->data = NULL;
> +            buf->size = 0;
> +            break;
> +        } else if (len == maxlen) {
> +            /*
> +             * We dodn't have space to put the NULL or we have more
> +             * to read. Increase the size and try again
> +             */
> +            maxlen *= 2;
> +            g_free(buf->data);
> +            buf->data = g_malloc(maxlen);
> +            continue;
> +        }
> +        /*
> +         * Null terminate the readlink output
> +         */
> +        buf->data[len] = '\0';
> +        buf->size = len;
> +        break;
> +    }
> +    return len;
> +}
> +
>  int v9fs_co_readlink(V9fsPDU *pdu, V9fsPath *path, V9fsString *buf)
>  {
>      int err;
> -    ssize_t len;
>      V9fsState *s = pdu->s;
>  
>      if (v9fs_request_cancelled(pdu)) {
>          return -EINTR;
>      }
> -    buf->data = g_malloc(PATH_MAX);
>      v9fs_path_read_lock(s);
>      v9fs_co_run_in_worker(
>          {
> -            len = s->ops->readlink(&s->ctx, path,
> -                                   buf->data, PATH_MAX - 1);
> -            if (len > -1) {
> -                buf->size = len;
> -                buf->data[len] = 0;
> -                err = 0;
> -            } else {
> +            err = __readlink(s, path, buf);
> +            if (err < 0) {
>                  err = -errno;
>              }
>          });
>      v9fs_path_unlock(s);
> -    if (err) {
> -        g_free(buf->data);
> -        buf->data = NULL;
> -        buf->size = 0;
> -    }
>      return err;
>  }
>  
> diff --git a/hw/9pfs/virtio-9p-handle.c b/hw/9pfs/virtio-9p-handle.c
> index 17002a3d2867..4b79cefd135e 100644
> --- a/hw/9pfs/virtio-9p-handle.c
> +++ b/hw/9pfs/virtio-9p-handle.c
> @@ -498,7 +498,7 @@ static int handle_lremovexattr(FsContext *ctx, V9fsPath *fs_path,
>  static int handle_name_to_path(FsContext *ctx, V9fsPath *dir_path,
>                                const char *name, V9fsPath *target)
>  {
> -    char buffer[PATH_MAX];
> +    char *buffer;
>      struct file_handle *fh;
>      int dirfd, ret, mnt_id;
>      struct handle_data *data = (struct handle_data *)ctx->private;
> @@ -513,7 +513,9 @@ static int handle_name_to_path(FsContext *ctx, V9fsPath *dir_path,
>          dirfd = open_by_handle(data->mountfd, dir_path->data, O_PATH);
>      } else {
>          /* relative to export root */
> -        dirfd = open(rpath(ctx, ".", buffer), O_DIRECTORY);
> +        buffer = rpath(ctx, ".");
> +        dirfd = open(buffer, O_DIRECTORY);
> +        g_free(buffer);
>      }
>      if (dirfd < 0) {
>          return dirfd;
> @@ -521,7 +523,7 @@ static int handle_name_to_path(FsContext *ctx, V9fsPath *dir_path,
>      fh = g_malloc(sizeof(struct file_handle) + data->handle_bytes);
>      fh->handle_bytes = data->handle_bytes;
>      /* add a "./" at the beginning of the path */
> -    snprintf(buffer, PATH_MAX, "./%s", name);
> +    buffer = g_strdup_printf("./%s", name);
>      /* flag = 0 imply don't follow symlink */
>      ret = name_to_handle(dirfd, buffer, fh, &mnt_id, 0);
>      if (!ret) {
> @@ -531,6 +533,7 @@ static int handle_name_to_path(FsContext *ctx, V9fsPath *dir_path,
>          g_free(fh);
>      }
>      close(dirfd);
> +    g_free(buffer);
>      return ret;
>  }
>  
> diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c
> index dc615a4d0fa4..56b302c122b6 100644
> --- a/hw/9pfs/virtio-9p-local.c
> +++ b/hw/9pfs/virtio-9p-local.c
> @@ -42,18 +42,18 @@
>  
>  #define VIRTFS_META_DIR ".virtfs_metadata"
>  
> -static const char *local_mapped_attr_path(FsContext *ctx,
> -                                          const char *path, char *buffer)
> +static char *local_mapped_attr_path(FsContext *ctx, const char *path)
>  {
>      char *dir_name;
>      char *tmp_path = g_strdup(path);
>      char *base_name = basename(tmp_path);
> +    char *buffer;
>  
>      /* NULL terminate the directory */
>      dir_name = tmp_path;
>      *(base_name - 1) = '\0';
>  
> -    snprintf(buffer, PATH_MAX, "%s/%s/%s/%s",
> +    buffer = g_strdup_printf("%s/%s/%s/%s",
>               ctx->fs_root, dir_name, VIRTFS_META_DIR, base_name);
>      g_free(tmp_path);
>      return buffer;
> @@ -92,10 +92,11 @@ static void local_mapped_file_attr(FsContext *ctx, const char *path,
>  {
>      FILE *fp;
>      char buf[ATTR_MAX];
> -    char attr_path[PATH_MAX];
> +    char *attr_path;
>  
> -    local_mapped_attr_path(ctx, path, attr_path);
> +    attr_path = local_mapped_attr_path(ctx, path);
>      fp = local_fopen(attr_path, "r");
> +    g_free(attr_path);
>      if (!fp) {
>          return;
>      }
> @@ -118,12 +119,13 @@ static void local_mapped_file_attr(FsContext *ctx, const char *path,
>  static int local_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf)
>  {
>      int err;
> -    char buffer[PATH_MAX];
> +    char *buffer;
>      char *path = fs_path->data;
>  
> -    err =  lstat(rpath(fs_ctx, path, buffer), stbuf);
> +    buffer = rpath(fs_ctx, path);
> +    err =  lstat(buffer, stbuf);
>      if (err) {
> -        return err;
> +        goto err_out;
>      }
>      if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
>          /* Actual credentials are part of extended attrs */
> @@ -131,41 +133,42 @@ static int local_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf)
>          gid_t tmp_gid;
>          mode_t tmp_mode;
>          dev_t tmp_dev;
> -        if (getxattr(rpath(fs_ctx, path, buffer), "user.virtfs.uid", &tmp_uid,
> -                    sizeof(uid_t)) > 0) {
> +        if (getxattr(buffer, "user.virtfs.uid", &tmp_uid, sizeof(uid_t)) > 0) {
>              stbuf->st_uid = tmp_uid;
>          }
> -        if (getxattr(rpath(fs_ctx, path, buffer), "user.virtfs.gid", &tmp_gid,
> -                    sizeof(gid_t)) > 0) {
> +        if (getxattr(buffer, "user.virtfs.gid", &tmp_gid, sizeof(gid_t)) > 0) {
>              stbuf->st_gid = tmp_gid;
>          }
> -        if (getxattr(rpath(fs_ctx, path, buffer), "user.virtfs.mode",
> +        if (getxattr(buffer, "user.virtfs.mode",
>                      &tmp_mode, sizeof(mode_t)) > 0) {
>              stbuf->st_mode = tmp_mode;
>          }
> -        if (getxattr(rpath(fs_ctx, path, buffer), "user.virtfs.rdev", &tmp_dev,
> -                        sizeof(dev_t)) > 0) {
> +        if (getxattr(buffer, "user.virtfs.rdev", &tmp_dev, sizeof(dev_t)) > 0) {
>                  stbuf->st_rdev = tmp_dev;
>          }
>      } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
>          local_mapped_file_attr(fs_ctx, path, stbuf);
>      }
> +
> +err_out:
> +    g_free(buffer);
>      return err;
>  }
>  
>  static int local_create_mapped_attr_dir(FsContext *ctx, const char *path)
>  {
>      int err;
> -    char attr_dir[PATH_MAX];
> +    char *attr_dir;
>      char *tmp_path = g_strdup(path);
>  
> -    snprintf(attr_dir, PATH_MAX, "%s/%s/%s",
> +    attr_dir = g_strdup_printf("%s/%s/%s",
>               ctx->fs_root, dirname(tmp_path), VIRTFS_META_DIR);
>  
>      err = mkdir(attr_dir, 0700);
>      if (err < 0 && errno == EEXIST) {
>          err = 0;
>      }
> +    g_free(attr_dir);
>      g_free(tmp_path);
>      return err;
>  }
> @@ -176,10 +179,11 @@ static int local_set_mapped_file_attr(FsContext *ctx,
>      FILE *fp;
>      int ret = 0;
>      char buf[ATTR_MAX];
> -    char attr_path[PATH_MAX];
> +    char *attr_path;
>      int uid = -1, gid = -1, mode = -1, rdev = -1;
>  
> -    fp = local_fopen(local_mapped_attr_path(ctx, path, attr_path), "r");
> +    attr_path = local_mapped_attr_path(ctx, path);
> +    fp = local_fopen(attr_path, "r");
>      if (!fp) {
>          goto create_map_file;
>      }
> @@ -241,6 +245,7 @@ update_map_file:
>      fclose(fp);
>  
>  err_out:
> +    g_free(attr_path);
>      return ret;
>  }
>  
> @@ -282,36 +287,43 @@ static int local_set_xattr(const char *path, FsCred *credp)
>  static int local_post_create_passthrough(FsContext *fs_ctx, const char *path,
>                                           FsCred *credp)
>  {
> -    char buffer[PATH_MAX];
> +    char *buffer;
>  
> -    if (lchown(rpath(fs_ctx, path, buffer), credp->fc_uid,
> -                credp->fc_gid) < 0) {
> +    buffer = rpath(fs_ctx, path);
> +    if (lchown(buffer, credp->fc_uid, credp->fc_gid) < 0) {
>          /*
>           * If we fail to change ownership and if we are
>           * using security model none. Ignore the error
>           */
>          if ((fs_ctx->export_flags & V9FS_SEC_MASK) != V9FS_SM_NONE) {
> -            return -1;
> +            goto err;
>          }
>      }
>  
> -    if (chmod(rpath(fs_ctx, path, buffer), credp->fc_mode & 07777) < 0) {
> -        return -1;
> +    if (chmod(buffer, credp->fc_mode & 07777) < 0) {
> +        goto err;
>      }
> +
> +    g_free(buffer);
>      return 0;
> +err:
> +    g_free(buffer);
> +    return -1;
>  }
>  
>  static ssize_t local_readlink(FsContext *fs_ctx, V9fsPath *fs_path,
>                                char *buf, size_t bufsz)
>  {
>      ssize_t tsize = -1;
> -    char buffer[PATH_MAX];
> +    char *buffer;
>      char *path = fs_path->data;
>  
>      if ((fs_ctx->export_flags & V9FS_SM_MAPPED) ||
>          (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE)) {
>          int fd;
> -        fd = open(rpath(fs_ctx, path, buffer), O_RDONLY | O_NOFOLLOW);
> +        buffer = rpath(fs_ctx, path);
> +        fd = open(buffer, O_RDONLY | O_NOFOLLOW);
> +        g_free(buffer);
>          if (fd == -1) {
>              return -1;
>          }
> @@ -322,7 +334,9 @@ static ssize_t local_readlink(FsContext *fs_ctx, V9fsPath *fs_path,
>          return tsize;
>      } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
>                 (fs_ctx->export_flags & V9FS_SM_NONE)) {
> -        tsize = readlink(rpath(fs_ctx, path, buffer), buf, bufsz);
> +        buffer = rpath(fs_ctx, path);
> +        tsize = readlink(buffer, buf, bufsz);
> +        g_free(buffer);
>      }
>      return tsize;
>  }
> @@ -340,20 +354,24 @@ static int local_closedir(FsContext *ctx, V9fsFidOpenState *fs)
>  static int local_open(FsContext *ctx, V9fsPath *fs_path,
>                        int flags, V9fsFidOpenState *fs)
>  {
> -    char buffer[PATH_MAX];
> +    char *buffer;
>      char *path = fs_path->data;
>  
> -    fs->fd = open(rpath(ctx, path, buffer), flags | O_NOFOLLOW);
> +    buffer = rpath(ctx, path);
> +    fs->fd = open(buffer, flags | O_NOFOLLOW);
> +    g_free(buffer);
>      return fs->fd;
>  }
>  
>  static int local_opendir(FsContext *ctx,
>                           V9fsPath *fs_path, V9fsFidOpenState *fs)
>  {
> -    char buffer[PATH_MAX];
> +    char *buffer;
>      char *path = fs_path->data;
>  
> -    fs->dir = opendir(rpath(ctx, path, buffer));
> +    buffer = rpath(ctx, path);
> +    fs->dir = opendir(buffer);
> +    g_free(buffer);
>      if (!fs->dir) {
>          return -1;
>      }
> @@ -441,18 +459,23 @@ static ssize_t local_pwritev(FsContext *ctx, V9fsFidOpenState *fs,
>  
>  static int local_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
>  {
> -    char buffer[PATH_MAX];
> +    char *buffer;
> +    int ret = -1;
>      char *path = fs_path->data;
>  
>      if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
> -        return local_set_xattr(rpath(fs_ctx, path, buffer), credp);
> +        buffer = rpath(fs_ctx, path);
> +        ret = local_set_xattr(buffer, credp);
> +        g_free(buffer);
>      } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
>          return local_set_mapped_file_attr(fs_ctx, path, credp);
>      } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
>                 (fs_ctx->export_flags & V9FS_SM_NONE)) {
> -        return chmod(rpath(fs_ctx, path, buffer), credp->fc_mode);
> +        buffer = rpath(fs_ctx, path);
> +        ret = chmod(buffer, credp->fc_mode);
> +        g_free(buffer);
>      }
> -    return -1;
> +    return ret;
>  }
>  
>  static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
> @@ -462,7 +485,7 @@ static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
>      int err = -1;
>      int serrno = 0;
>      V9fsString fullname;
> -    char buffer[PATH_MAX];
> +    char *buffer;
>  
>      v9fs_string_init(&fullname);
>      v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
> @@ -470,21 +493,23 @@ static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
>  
>      /* Determine the security model */
>      if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
> -        err = mknod(rpath(fs_ctx, path, buffer),
> -                SM_LOCAL_MODE_BITS|S_IFREG, 0);
> +        buffer = rpath(fs_ctx, path);
> +        err = mknod(buffer, SM_LOCAL_MODE_BITS|S_IFREG, 0);
>          if (err == -1) {
> +            g_free(buffer);
>              goto out;
>          }
> -        err = local_set_xattr(rpath(fs_ctx, path, buffer), credp);
> +        err = local_set_xattr(buffer, credp);
>          if (err == -1) {
>              serrno = errno;
>              goto err_end;
>          }
>      } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
>  
> -        err = mknod(rpath(fs_ctx, path, buffer),
> -                    SM_LOCAL_MODE_BITS|S_IFREG, 0);
> +        buffer = rpath(fs_ctx, path);
> +        err = mknod(buffer, SM_LOCAL_MODE_BITS|S_IFREG, 0);
>          if (err == -1) {
> +            g_free(buffer);
>              goto out;
>          }
>          err = local_set_mapped_file_attr(fs_ctx, path, credp);
> @@ -494,9 +519,10 @@ static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
>          }
>      } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
>                 (fs_ctx->export_flags & V9FS_SM_NONE)) {
> -        err = mknod(rpath(fs_ctx, path, buffer), credp->fc_mode,
> -                credp->fc_rdev);
> +        buffer = rpath(fs_ctx, path);
> +        err = mknod(buffer, credp->fc_mode, credp->fc_rdev);
>          if (err == -1) {
> +            g_free(buffer);
>              goto out;
>          }
>          err = local_post_create_passthrough(fs_ctx, path, credp);
> @@ -508,8 +534,9 @@ static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
>      goto out;
>  
>  err_end:
> -    remove(rpath(fs_ctx, path, buffer));
> +    remove(buffer);
>      errno = serrno;
> +    g_free(buffer);
>  out:
>      v9fs_string_free(&fullname);
>      return err;
> @@ -522,7 +549,7 @@ static int local_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
>      int err = -1;
>      int serrno = 0;
>      V9fsString fullname;
> -    char buffer[PATH_MAX];
> +    char *buffer;
>  
>      v9fs_string_init(&fullname);
>      v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
> @@ -530,19 +557,23 @@ static int local_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
>  
>      /* Determine the security model */
>      if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
> -        err = mkdir(rpath(fs_ctx, path, buffer), SM_LOCAL_DIR_MODE_BITS);
> +        buffer = rpath(fs_ctx, path);
> +        err = mkdir(buffer, SM_LOCAL_DIR_MODE_BITS);
>          if (err == -1) {
> +            g_free(buffer);
>              goto out;
>          }
>          credp->fc_mode = credp->fc_mode|S_IFDIR;
> -        err = local_set_xattr(rpath(fs_ctx, path, buffer), credp);
> +        err = local_set_xattr(buffer, credp);
>          if (err == -1) {
>              serrno = errno;
>              goto err_end;
>          }
>      } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
> -        err = mkdir(rpath(fs_ctx, path, buffer), SM_LOCAL_DIR_MODE_BITS);
> +        buffer = rpath(fs_ctx, path);
> +        err = mkdir(buffer, SM_LOCAL_DIR_MODE_BITS);
>          if (err == -1) {
> +            g_free(buffer);
>              goto out;
>          }
>          credp->fc_mode = credp->fc_mode|S_IFDIR;
> @@ -553,8 +584,10 @@ static int local_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
>          }
>      } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
>                 (fs_ctx->export_flags & V9FS_SM_NONE)) {
> -        err = mkdir(rpath(fs_ctx, path, buffer), credp->fc_mode);
> +        buffer = rpath(fs_ctx, path);
> +        err = mkdir(buffer, credp->fc_mode);
>          if (err == -1) {
> +            g_free(buffer);
>              goto out;
>          }
>          err = local_post_create_passthrough(fs_ctx, path, credp);
> @@ -566,8 +599,9 @@ static int local_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
>      goto out;
>  
>  err_end:
> -    remove(rpath(fs_ctx, path, buffer));
> +    remove(buffer);
>      errno = serrno;
> +    g_free(buffer);
>  out:
>      v9fs_string_free(&fullname);
>      return err;
> @@ -626,7 +660,7 @@ static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
>      int err = -1;
>      int serrno = 0;
>      V9fsString fullname;
> -    char buffer[PATH_MAX];
> +    char *buffer;
>  
>      /*
>       * Mark all the open to not follow symlinks
> @@ -639,21 +673,25 @@ static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
>  
>      /* Determine the security model */
>      if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
> -        fd = open(rpath(fs_ctx, path, buffer), flags, SM_LOCAL_MODE_BITS);
> +        buffer = rpath(fs_ctx, path);
> +        fd = open(buffer, flags, SM_LOCAL_MODE_BITS);
>          if (fd == -1) {
> +            g_free(buffer);
>              err = fd;
>              goto out;
>          }
>          credp->fc_mode = credp->fc_mode|S_IFREG;
>          /* Set cleint credentials in xattr */
> -        err = local_set_xattr(rpath(fs_ctx, path, buffer), credp);
> +        err = local_set_xattr(buffer, credp);
>          if (err == -1) {
>              serrno = errno;
>              goto err_end;
>          }
>      } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
> -        fd = open(rpath(fs_ctx, path, buffer), flags, SM_LOCAL_MODE_BITS);
> +        buffer = rpath(fs_ctx, path);
> +        fd = open(buffer, flags, SM_LOCAL_MODE_BITS);
>          if (fd == -1) {
> +            g_free(buffer);
>              err = fd;
>              goto out;
>          }
> @@ -666,8 +704,10 @@ static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
>          }
>      } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
>                 (fs_ctx->export_flags & V9FS_SM_NONE)) {
> -        fd = open(rpath(fs_ctx, path, buffer), flags, credp->fc_mode);
> +        buffer = rpath(fs_ctx, path);
> +        fd = open(buffer, flags, credp->fc_mode);
>          if (fd == -1) {
> +            g_free(buffer);
>              err = fd;
>              goto out;
>          }
> @@ -683,8 +723,9 @@ static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
>  
>  err_end:
>      close(fd);
> -    remove(rpath(fs_ctx, path, buffer));
> +    remove(buffer);
>      errno = serrno;
> +    g_free(buffer);
>  out:
>      v9fs_string_free(&fullname);
>      return err;
> @@ -698,7 +739,7 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
>      int serrno = 0;
>      char *newpath;
>      V9fsString fullname;
> -    char buffer[PATH_MAX];
> +    char *buffer;
>  
>      v9fs_string_init(&fullname);
>      v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
> @@ -708,10 +749,10 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
>      if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
>          int fd;
>          ssize_t oldpath_size, write_size;
> -        fd = open(rpath(fs_ctx, newpath, buffer),
> -                  O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW,
> -                  SM_LOCAL_MODE_BITS);
> +        buffer = rpath(fs_ctx, newpath);
> +        fd = open(buffer, O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW, SM_LOCAL_MODE_BITS);
>          if (fd == -1) {
> +            g_free(buffer);
>              err = fd;
>              goto out;
>          }
> @@ -730,7 +771,7 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
>          close(fd);
>          /* Set cleint credentials in symlink's xattr */
>          credp->fc_mode = credp->fc_mode|S_IFLNK;
> -        err = local_set_xattr(rpath(fs_ctx, newpath, buffer), credp);
> +        err = local_set_xattr(buffer, credp);
>          if (err == -1) {
>              serrno = errno;
>              goto err_end;
> @@ -738,10 +779,10 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
>      } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
>          int fd;
>          ssize_t oldpath_size, write_size;
> -        fd = open(rpath(fs_ctx, newpath, buffer),
> -                  O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW,
> -                  SM_LOCAL_MODE_BITS);
> +        buffer = rpath(fs_ctx, newpath);
> +        fd = open(buffer, O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW, SM_LOCAL_MODE_BITS);
>          if (fd == -1) {
> +            g_free(buffer);
>              err = fd;
>              goto out;
>          }
> @@ -767,12 +808,13 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
>          }
>      } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
>                 (fs_ctx->export_flags & V9FS_SM_NONE)) {
> -        err = symlink(oldpath, rpath(fs_ctx, newpath, buffer));
> +        buffer = rpath(fs_ctx, newpath);
> +        err = symlink(oldpath, buffer);
>          if (err) {
> +            g_free(buffer);
>              goto out;
>          }
> -        err = lchown(rpath(fs_ctx, newpath, buffer), credp->fc_uid,
> -                     credp->fc_gid);
> +        err = lchown(buffer, credp->fc_uid, credp->fc_gid);
>          if (err == -1) {
>              /*
>               * If we fail to change ownership and if we are
> @@ -788,8 +830,9 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
>      goto out;
>  
>  err_end:
> -    remove(rpath(fs_ctx, newpath, buffer));
> +    remove(buffer);
>      errno = serrno;
> +    g_free(buffer);
>  out:
>      v9fs_string_free(&fullname);
>      return err;
> @@ -800,13 +843,16 @@ static int local_link(FsContext *ctx, V9fsPath *oldpath,
>  {
>      int ret;
>      V9fsString newpath;
> -    char buffer[PATH_MAX], buffer1[PATH_MAX];
> +    char *buffer, *buffer1;
>  
>      v9fs_string_init(&newpath);
>      v9fs_string_sprintf(&newpath, "%s/%s", dirpath->data, name);
>  
> -    ret = link(rpath(ctx, oldpath->data, buffer),
> -               rpath(ctx, newpath.data, buffer1));
> +    buffer = rpath(ctx, oldpath->data);
> +    buffer1 = rpath(ctx, newpath.data);
> +    ret = link(buffer, buffer1);
> +    g_free(buffer);
> +    g_free(buffer1);
>  
>      /* now link the virtfs_metadata files */
>      if (!ret && (ctx->export_flags & V9FS_SM_MAPPED_FILE)) {
> @@ -815,8 +861,11 @@ static int local_link(FsContext *ctx, V9fsPath *oldpath,
>          if (ret < 0) {
>              goto err_out;
>          }
> -        ret = link(local_mapped_attr_path(ctx, oldpath->data, buffer),
> -                   local_mapped_attr_path(ctx, newpath.data, buffer1));
> +        buffer = local_mapped_attr_path(ctx, oldpath->data);
> +        buffer1 = local_mapped_attr_path(ctx, newpath.data);
> +        ret = link(buffer, buffer1);
> +        g_free(buffer);
> +        g_free(buffer1);
>          if (ret < 0 && errno != ENOENT) {
>              goto err_out;
>          }
> @@ -828,17 +877,21 @@ err_out:
>  
>  static int local_truncate(FsContext *ctx, V9fsPath *fs_path, off_t size)
>  {
> -    char buffer[PATH_MAX];
> +    char *buffer;
> +    int ret;
>      char *path = fs_path->data;
>  
> -    return truncate(rpath(ctx, path, buffer), size);
> +    buffer = rpath(ctx, path);
> +    ret = truncate(buffer, size);
> +    g_free(buffer);
> +    return ret;
>  }
>  
>  static int local_rename(FsContext *ctx, const char *oldpath,
>                          const char *newpath)
>  {
>      int err;
> -    char buffer[PATH_MAX], buffer1[PATH_MAX];
> +    char *buffer, *buffer1;
>  
>      if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
>          err = local_create_mapped_attr_dir(ctx, newpath);
> @@ -846,50 +899,69 @@ static int local_rename(FsContext *ctx, const char *oldpath,
>              return err;
>          }
>          /* rename the .virtfs_metadata files */
> -        err = rename(local_mapped_attr_path(ctx, oldpath, buffer),
> -                     local_mapped_attr_path(ctx, newpath, buffer1));
> +        buffer = local_mapped_attr_path(ctx, oldpath);
> +        buffer1 = local_mapped_attr_path(ctx, newpath);
> +        err = rename(buffer, buffer1);
> +        g_free(buffer);
> +        g_free(buffer1);
>          if (err < 0 && errno != ENOENT) {
>              return err;
>          }
>      }
> -    return rename(rpath(ctx, oldpath, buffer), rpath(ctx, newpath, buffer1));
> +
> +    buffer = rpath(ctx, oldpath);
> +    buffer1 = rpath(ctx, newpath);
> +    err = rename(buffer, buffer1);
> +    g_free(buffer);
> +    g_free(buffer1);
> +    return err;
>  }
>  
>  static int local_chown(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
>  {
> -    char buffer[PATH_MAX];
> +    char *buffer;
> +    int ret = -1;
>      char *path = fs_path->data;
>  
>      if ((credp->fc_uid == -1 && credp->fc_gid == -1) ||
>          (fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
>          (fs_ctx->export_flags & V9FS_SM_NONE)) {
> -        return lchown(rpath(fs_ctx, path, buffer),
> -                      credp->fc_uid, credp->fc_gid);
> +        buffer = rpath(fs_ctx, path);
> +        ret = lchown(buffer, credp->fc_uid, credp->fc_gid);
> +        g_free(buffer);
>      } else if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
> -        return local_set_xattr(rpath(fs_ctx, path, buffer), credp);
> +        buffer = rpath(fs_ctx, path);
> +        ret = local_set_xattr(buffer, credp);
> +        g_free(buffer);
>      } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
>          return local_set_mapped_file_attr(fs_ctx, path, credp);
>      }
> -    return -1;
> +    return ret;
>  }
>  
>  static int local_utimensat(FsContext *s, V9fsPath *fs_path,
>                             const struct timespec *buf)
>  {
> -    char buffer[PATH_MAX];
> +    char *buffer;
> +    int ret;
>      char *path = fs_path->data;
>  
> -    return qemu_utimens(rpath(s, path, buffer), buf);
> +    buffer = rpath(s, path);
> +    ret = qemu_utimens(buffer, buf);
> +    g_free(buffer);
> +    return ret;
>  }
>  
>  static int local_remove(FsContext *ctx, const char *path)
>  {
>      int err;
>      struct stat stbuf;
> -    char buffer[PATH_MAX];
> +    char *buffer;
>  
>      if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
> -        err =  lstat(rpath(ctx, path, buffer), &stbuf);
> +        buffer = rpath(ctx, path);
> +        err =  lstat(buffer, &stbuf);
> +        g_free(buffer);
>          if (err) {
>              goto err_out;
>          }
> @@ -898,9 +970,10 @@ static int local_remove(FsContext *ctx, const char *path)
>           * directory
>           */
>          if (S_ISDIR(stbuf.st_mode)) {
> -            snprintf(buffer, ARRAY_SIZE(buffer), "%s/%s/%s",
> -                     ctx->fs_root, path, VIRTFS_META_DIR);
> +            buffer = g_strdup_printf("%s/%s/%s", ctx->fs_root,
> +                                     path, VIRTFS_META_DIR);
>              err = remove(buffer);
> +            g_free(buffer);
>              if (err < 0 && errno != ENOENT) {
>                  /*
>                   * We didn't had the .virtfs_metadata file. May be file created
> @@ -913,7 +986,9 @@ static int local_remove(FsContext *ctx, const char *path)
>           * Now remove the name from parent directory
>           * .virtfs_metadata directory
>           */
> -        err = remove(local_mapped_attr_path(ctx, path, buffer));
> +        buffer = local_mapped_attr_path(ctx, path);
> +        err = remove(buffer);
> +        g_free(buffer);
>          if (err < 0 && errno != ENOENT) {
>              /*
>               * We didn't had the .virtfs_metadata file. May be file created
> @@ -922,7 +997,10 @@ static int local_remove(FsContext *ctx, const char *path)
>              goto err_out;
>          }
>      }
> -    return remove(rpath(ctx, path, buffer));
> +
> +    buffer = rpath(ctx, path);
> +    err = remove(buffer);
> +    g_free(buffer);
>  err_out:
>      return err;
>  }
> @@ -947,10 +1025,14 @@ static int local_fsync(FsContext *ctx, int fid_type,
>  
>  static int local_statfs(FsContext *s, V9fsPath *fs_path, struct statfs *stbuf)
>  {
> -    char buffer[PATH_MAX];
> +    char *buffer;
> +    int ret;
>      char *path = fs_path->data;
>  
> -    return statfs(rpath(s, path, buffer), stbuf);
> +    buffer = rpath(s, path);
> +    ret = statfs(buffer, stbuf);
> +    g_free(buffer);
> +    return ret;
>  }
>  
>  static ssize_t local_lgetxattr(FsContext *ctx, V9fsPath *fs_path,
> @@ -1023,7 +1105,7 @@ static int local_unlinkat(FsContext *ctx, V9fsPath *dir,
>  {
>      int ret;
>      V9fsString fullname;
> -    char buffer[PATH_MAX];
> +    char *buffer;
>  
>      v9fs_string_init(&fullname);
>  
> @@ -1034,9 +1116,10 @@ static int local_unlinkat(FsContext *ctx, V9fsPath *dir,
>               * If directory remove .virtfs_metadata contained in the
>               * directory
>               */
> -            snprintf(buffer, ARRAY_SIZE(buffer), "%s/%s/%s", ctx->fs_root,
> -                     fullname.data, VIRTFS_META_DIR);
> +            buffer = g_strdup_printf("%s/%s/%s", ctx->fs_root,
> +                                     fullname.data, VIRTFS_META_DIR);
>              ret = remove(buffer);
> +            g_free(buffer);
>              if (ret < 0 && errno != ENOENT) {
>                  /*
>                   * We didn't had the .virtfs_metadata file. May be file created
> @@ -1049,7 +1132,9 @@ static int local_unlinkat(FsContext *ctx, V9fsPath *dir,
>           * Now remove the name from parent directory
>           * .virtfs_metadata directory.
>           */
> -        ret = remove(local_mapped_attr_path(ctx, fullname.data, buffer));
> +        buffer = local_mapped_attr_path(ctx, fullname.data);
> +        ret = remove(buffer);
> +        g_free(buffer);
>          if (ret < 0 && errno != ENOENT) {
>              /*
>               * We didn't had the .virtfs_metadata file. May be file created
> @@ -1059,7 +1144,9 @@ static int local_unlinkat(FsContext *ctx, V9fsPath *dir,
>          }
>      }
>      /* Remove the name finally */
> -    ret = remove(rpath(ctx, fullname.data, buffer));
> +    buffer = rpath(ctx, fullname.data);
> +    ret = remove(buffer);
> +    g_free(buffer);
>  
>  err_out:
>      v9fs_string_free(&fullname);
> diff --git a/hw/9pfs/virtio-9p-posix-acl.c b/hw/9pfs/virtio-9p-posix-acl.c
> index 339c5ecae441..803d9d94f3b8 100644
> --- a/hw/9pfs/virtio-9p-posix-acl.c
> +++ b/hw/9pfs/virtio-9p-posix-acl.c
> @@ -26,8 +26,13 @@
>  static ssize_t mp_pacl_getxattr(FsContext *ctx, const char *path,
>                                  const char *name, void *value, size_t size)
>  {
> -    char buffer[PATH_MAX];
> -    return lgetxattr(rpath(ctx, path, buffer), MAP_ACL_ACCESS, value, size);
> +    char *buffer;
> +    ssize_t ret;
> +
> +    buffer = rpath(ctx, path);
> +    ret = lgetxattr(buffer, MAP_ACL_ACCESS, value, size);
> +    g_free(buffer);
> +    return ret;
>  }
>  
>  static ssize_t mp_pacl_listxattr(FsContext *ctx, const char *path,
> @@ -52,17 +57,23 @@ static ssize_t mp_pacl_listxattr(FsContext *ctx, const char *path,
>  static int mp_pacl_setxattr(FsContext *ctx, const char *path, const char *name,
>                              void *value, size_t size, int flags)
>  {
> -    char buffer[PATH_MAX];
> -    return lsetxattr(rpath(ctx, path, buffer), MAP_ACL_ACCESS, value,
> -            size, flags);
> +    char *buffer;
> +    int ret;
> +
> +    buffer = rpath(ctx, path);
> +    ret = lsetxattr(buffer, MAP_ACL_ACCESS, value, size, flags);
> +    g_free(buffer);
> +    return ret;
>  }
>  
>  static int mp_pacl_removexattr(FsContext *ctx,
>                                 const char *path, const char *name)
>  {
>      int ret;
> -    char buffer[PATH_MAX];
> -    ret  = lremovexattr(rpath(ctx, path, buffer), MAP_ACL_ACCESS);
> +    char *buffer;
> +
> +    buffer = rpath(ctx, path);
> +    ret  = lremovexattr(buffer, MAP_ACL_ACCESS);
>      if (ret == -1 && errno == ENODATA) {
>          /*
>           * We don't get ENODATA error when trying to remove a
> @@ -72,14 +83,20 @@ static int mp_pacl_removexattr(FsContext *ctx,
>          errno = 0;
>          ret = 0;
>      }
> +    g_free(buffer);
>      return ret;
>  }
>  
>  static ssize_t mp_dacl_getxattr(FsContext *ctx, const char *path,
>                                  const char *name, void *value, size_t size)
>  {
> -    char buffer[PATH_MAX];
> -    return lgetxattr(rpath(ctx, path, buffer), MAP_ACL_DEFAULT, value, size);
> +    char *buffer;
> +    ssize_t ret;
> +
> +    buffer = rpath(ctx, path);
> +    ret = lgetxattr(buffer, MAP_ACL_DEFAULT, value, size);
> +    g_free(buffer);
> +    return ret;
>  }
>  
>  static ssize_t mp_dacl_listxattr(FsContext *ctx, const char *path,
> @@ -104,17 +121,23 @@ static ssize_t mp_dacl_listxattr(FsContext *ctx, const char *path,
>  static int mp_dacl_setxattr(FsContext *ctx, const char *path, const char *name,
>                              void *value, size_t size, int flags)
>  {
> -    char buffer[PATH_MAX];
> -    return lsetxattr(rpath(ctx, path, buffer), MAP_ACL_DEFAULT, value,
> -            size, flags);
> +    char *buffer;
> +    int ret;
> +
> +    buffer = rpath(ctx, path);
> +    ret = lsetxattr(buffer, MAP_ACL_DEFAULT, value, size, flags);
> +    g_free(buffer);
> +    return ret;
>  }
>  
>  static int mp_dacl_removexattr(FsContext *ctx,
>                                 const char *path, const char *name)
>  {
>      int ret;
> -    char buffer[PATH_MAX];
> -    ret  = lremovexattr(rpath(ctx, path, buffer), MAP_ACL_DEFAULT);
> +    char *buffer;
> +
> +    buffer = rpath(ctx, path);
> +    ret  = lremovexattr(buffer, MAP_ACL_DEFAULT);
>      if (ret == -1 && errno == ENODATA) {
>          /*
>           * We don't get ENODATA error when trying to remove a
> @@ -124,6 +147,7 @@ static int mp_dacl_removexattr(FsContext *ctx,
>          errno = 0;
>          ret = 0;
>      }
> +    g_free(buffer);
>      return ret;
>  }
>  
> diff --git a/hw/9pfs/virtio-9p-xattr-user.c b/hw/9pfs/virtio-9p-xattr-user.c
> index e0c92ebf9e5d..46133e06dbdf 100644
> --- a/hw/9pfs/virtio-9p-xattr-user.c
> +++ b/hw/9pfs/virtio-9p-xattr-user.c
> @@ -21,7 +21,9 @@
>  static ssize_t mp_user_getxattr(FsContext *ctx, const char *path,
>                                  const char *name, void *value, size_t size)
>  {
> -    char buffer[PATH_MAX];
> +    char *buffer;
> +    ssize_t ret;
> +
>      if (strncmp(name, "user.virtfs.", 12) == 0) {
>          /*
>           * Don't allow fetch of user.virtfs namesapce
> @@ -30,7 +32,10 @@ static ssize_t mp_user_getxattr(FsContext *ctx, const char *path,
>          errno = ENOATTR;
>          return -1;
>      }
> -    return lgetxattr(rpath(ctx, path, buffer), name, value, size);
> +    buffer = rpath(ctx, path);
> +    ret = lgetxattr(buffer, name, value, size);
> +    g_free(buffer);
> +    return ret;
>  }
>  
>  static ssize_t mp_user_listxattr(FsContext *ctx, const char *path,
> @@ -69,7 +74,9 @@ static ssize_t mp_user_listxattr(FsContext *ctx, const char *path,
>  static int mp_user_setxattr(FsContext *ctx, const char *path, const char *name,
>                              void *value, size_t size, int flags)
>  {
> -    char buffer[PATH_MAX];
> +    char *buffer;
> +    int ret;
> +
>      if (strncmp(name, "user.virtfs.", 12) == 0) {
>          /*
>           * Don't allow fetch of user.virtfs namesapce
> @@ -78,13 +85,18 @@ static int mp_user_setxattr(FsContext *ctx, const char *path, const char *name,
>          errno = EACCES;
>          return -1;
>      }
> -    return lsetxattr(rpath(ctx, path, buffer), name, value, size, flags);
> +    buffer = rpath(ctx, path);
> +    ret = lsetxattr(buffer, name, value, size, flags);
> +    g_free(buffer);
> +    return ret;
>  }
>  
>  static int mp_user_removexattr(FsContext *ctx,
>                                 const char *path, const char *name)
>  {
> -    char buffer[PATH_MAX];
> +    char *buffer;
> +    int ret;
> +
>      if (strncmp(name, "user.virtfs.", 12) == 0) {
>          /*
>           * Don't allow fetch of user.virtfs namesapce
> @@ -93,7 +105,10 @@ static int mp_user_removexattr(FsContext *ctx,
>          errno = EACCES;
>          return -1;
>      }
> -    return lremovexattr(rpath(ctx, path, buffer), name);
> +    buffer = rpath(ctx, path);
> +    ret = lremovexattr(buffer, name);
> +    g_free(buffer);
> +    return ret;
>  }
>  
>  XattrOperations mapped_user_xattr = {
> diff --git a/hw/9pfs/virtio-9p-xattr.c b/hw/9pfs/virtio-9p-xattr.c
> index 3fae557a84ff..07183887c5ee 100644
> --- a/hw/9pfs/virtio-9p-xattr.c
> +++ b/hw/9pfs/virtio-9p-xattr.c
> @@ -67,21 +67,24 @@ ssize_t v9fs_list_xattr(FsContext *ctx, const char *path,
>                          void *value, size_t vsize)
>  {
>      ssize_t size = 0;
> -    char buffer[PATH_MAX];
> +    char *buffer;
>      void *ovalue = value;
>      XattrOperations *xops;
>      char *orig_value, *orig_value_start;
>      ssize_t xattr_len, parsed_len = 0, attr_len;
>  
>      /* Get the actual len */
> -    xattr_len = llistxattr(rpath(ctx, path, buffer), value, 0);
> +    buffer = rpath(ctx, path);
> +    xattr_len = llistxattr(buffer, value, 0);
>      if (xattr_len <= 0) {
> +        g_free(buffer);
>          return xattr_len;
>      }
>  
>      /* Now fetch the xattr and find the actual size */
>      orig_value = g_malloc(xattr_len);
> -    xattr_len = llistxattr(rpath(ctx, path, buffer), orig_value, xattr_len);
> +    xattr_len = llistxattr(buffer, orig_value, xattr_len);
> +    g_free(buffer);
>  
>      /* store the orig pointer */
>      orig_value_start = orig_value;
> diff --git a/hw/9pfs/virtio-9p-xattr.h b/hw/9pfs/virtio-9p-xattr.h
> index 41cc6cbc7ba0..327b32b5aa9e 100644
> --- a/hw/9pfs/virtio-9p-xattr.h
> +++ b/hw/9pfs/virtio-9p-xattr.h
> @@ -54,23 +54,38 @@ ssize_t pt_listxattr(FsContext *ctx, const char *path, char *name, void *value,
>  static inline ssize_t pt_getxattr(FsContext *ctx, const char *path,
>                                    const char *name, void *value, size_t size)
>  {
> -    char buffer[PATH_MAX];
> -    return lgetxattr(rpath(ctx, path, buffer), name, value, size);
> +    char *buffer;
> +    ssize_t ret;
> +
> +    buffer = rpath(ctx, path);
> +    ret = lgetxattr(buffer, name, value, size);
> +    g_free(buffer);
> +    return ret;
>  }
>  
>  static inline int pt_setxattr(FsContext *ctx, const char *path,
>                                const char *name, void *value,
>                                size_t size, int flags)
>  {
> -    char buffer[PATH_MAX];
> -    return lsetxattr(rpath(ctx, path, buffer), name, value, size, flags);
> +    char *buffer;
> +    int ret;
> +
> +    buffer = rpath(ctx, path);
> +    ret = lsetxattr(buffer, name, value, size, flags);
> +    g_free(buffer);
> +    return ret;
>  }
>  
>  static inline int pt_removexattr(FsContext *ctx,
>                                   const char *path, const char *name)
>  {
> -    char buffer[PATH_MAX];
> -    return lremovexattr(rpath(ctx, path, buffer), name);
> +    char *buffer;
> +    int ret;
> +
> +    buffer = rpath(ctx, path);
> +    ret = lremovexattr(path, name);
> +    g_free(buffer);
> +    return ret;
>  }
>  
>  static inline ssize_t notsup_getxattr(FsContext *ctx, const char *path,
> diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h
> index 1d6eedb7d8bc..2c3603aed0d0 100644
> --- a/hw/9pfs/virtio-9p.h
> +++ b/hw/9pfs/virtio-9p.h
> @@ -6,6 +6,7 @@
>  #include <sys/time.h>
>  #include <utime.h>
>  #include <sys/resource.h>
> +#include <glib.h>
>  #include "hw/virtio/virtio.h"
>  #include "fsdev/file-op-9p.h"
>  #include "fsdev/virtio-9p-marshal.h"
> @@ -112,10 +113,9 @@ enum p9_proto_version {
>  
>  #define FID_REFERENCED          0x1
>  #define FID_NON_RECLAIMABLE     0x2
> -static inline const char *rpath(FsContext *ctx, const char *path, char *buffer)
> +static inline char *rpath(FsContext *ctx, const char *path)
>  {
> -    snprintf(buffer, PATH_MAX, "%s/%s", ctx->fs_root, path);
> -    return buffer;
> +    return g_strdup_printf("%s/%s", ctx->fs_root, path);
>  }
>  
>  /*
>
Chen Gang March 16, 2014, 1:32 p.m. UTC | #2
On 03/08/2014 09:58 PM, Chen Gang wrote:
> OK, thanks.
>
> Next, I will/should continue to analyse the performance issue for 9pfs
> when users drop into a long directory path under bash shell.
>

After have a test, I am sure it is not 9pfs issue, either not Qemu's
issue, it's Linux kernel vfs or block sub-systems' issue. The related
test environments (originally, our 9pfs is upper on ext4):

 - for ext4 file system under my Fedora laptop (Qemu does not start).

 - for ntfs file system under my Fedora laptop (Qemu does not start).

 - for ext4 file system under my Ubuntu in Qemu.

For a very long file name (e.g. > 3K long), all of them are very very
slow. (and I also tested the ext2 /boot partition under Ubuntu in Qemu,
it is not slow, I guess the reson is its partition size is small).


Next, I will/shall communicate with upstream kernel for it.  :-)


> Although I am not quite sure, hope I can find the root cause within
> month (2014-03-31).
>
> Welcome any suggestions, discussions, and completions for it.
>
> Thanks.
>
Chen Gang March 23, 2014, 1:27 p.m. UTC | #3
On 03/16/2014 09:32 PM, Chen Gang wrote:
> On 03/08/2014 09:58 PM, Chen Gang wrote:
>> OK, thanks.
>>
>> Next, I will/should continue to analyse the performance issue for 9pfs
>> when users drop into a long directory path under bash shell.
>>
> 
> After have a test, I am sure it is not 9pfs issue, either not Qemu's
> issue, it's Linux kernel vfs or block sub-systems' issue. The related
> test environments (originally, our 9pfs is upper on ext4):
> 
>  - for ext4 file system under my Fedora laptop (Qemu does not start).
> 
>  - for ntfs file system under my Fedora laptop (Qemu does not start).
> 
>  - for ext4 file system under my Ubuntu in Qemu.
> 
> For a very long file name (e.g. > 3K long), all of them are very very
> slow. (and I also tested the ext2 /boot partition under Ubuntu in Qemu,
> it is not slow, I guess the reson is its partition size is small).
> 
> 
> Next, I will/shall communicate with upstream kernel for it.  :-)
> 
> 
>> Although I am not quite sure, hope I can find the root cause within
>> month (2014-03-31).
>>
>> Welcome any suggestions, discussions, and completions for it.
>>
>> Thanks.
>>
> 
> 

Sorry, after give a little more test, for the lower performance issue
under a long deep path, 'bash' is the direct cause (may also be root
cause).

Also sorry, 'bash' is out of my focusing border now, so I provide the
related information below, welcome any members (e.g. 'bash', fedora, or
ubuntu members) to help check, when they have time, thanks.

  Environments (e.g. fedora 17):

    [root@gchen ~]# uname -a
    Linux gchen 3.14.0-rc7-next-20140321 #2 SMP Sun Mar 23 19:46:37 CST 2014 x86_64 x86_64 x86_64 GNU/Linux
    [root@gchen ~]# cat /etc/*-release
    Fedora release 17 (Beefy Miracle)
    NAME=Fedora
    VERSION="17 (Beefy Miracle)"
    ID=fedora
    VERSION_ID=17
    PRETTY_NAME="Fedora 17 (Beefy Miracle)"
    ANSI_COLOR="0;34"
    CPE_NAME="cpe:/o:fedoraproject:fedora:17"
    Fedora release 17 (Beefy Miracle)
    Fedora release 17 (Beefy Miracle)

  'bash' is very busy under user mode (I am only one cpu):

    top - 20:12:01 up 23 min,  5 users,  load average: 0.60, 0.35, 0.33
    Tasks: 137 total,   2 running, 135 sleeping,   0 stopped,   0 zombie
    Cpu(s): 97.1%us,  2.9%sy,  0.0%ni,  0.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
    Mem:   1942468k total,   820896k used,  1121572k free,    40060k buffers
    Swap:        0k total,        0k used,        0k free,   446328k cached

      PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
     4010 root      20   0  113m 5236 3096 R 92.3  0.3   3:57.19 -bash
     2955 root      20   0  136m  21m  10m S  2.9  1.1   0:16.00 /usr/bin/Xorg :0 -background none -logverbose 7 -auth /var/run/gdm/auth-for-gdm-8
     3860 gchen     20   0  582m  28m  19m S  1.9  1.5   0:22.93 gnome-terminal
     3348 gchen     20   0 1405m 117m  46m S  1.0  6.2   0:23.34 /usr/bin/gnome-shell
     3728 gchen     20   0  442m 8248 6140 S  1.0  0.4   0:12.05 /usr/bin/ibus-daemon -r --xim
     ...

  The related 'bash' stack is below (each time, always drop into it):

    #0  0x00000036bb290c1c in strcoll_l () from /lib64/libc.so.6
    #1  0x000000000047ff48 in ?? ()
    #2  0x0000000000480517 in ?? ()
    #3  0x0000000000480fb7 in ?? ()
    #4  0x00000000004806e0 in ?? ()
    #5  0x0000000000480fb7 in ?? ()
    #6  0x00000000004806e0 in ?? ()
    #7  0x0000000000482528 in xstrmatch ()
    #8  0x0000000000456f79 in binary_test ()
    #9  0x000000000042f308 in ?? ()
    #10 0x000000000042f449 in ?? ()
    #11 0x0000000000432379 in execute_command_internal ()
    #12 0x000000000043583e in execute_command ()
    #13 0x000000000043295e in execute_command_internal ()
    #14 0x000000000043349f in execute_command_internal ()
    #15 0x000000000043583e in execute_command ()
    #16 0x0000000000433464 in execute_command_internal ()
    #17 0x000000000043583e in execute_command ()
    #18 0x0000000000433464 in execute_command_internal ()
    #19 0x000000000043583e in execute_command ()
    #20 0x0000000000433464 in execute_command_internal ()
    #21 0x000000000043583e in execute_command ()
    #22 0x0000000000433464 in execute_command_internal ()
    #23 0x000000000043583e in execute_command ()
    #24 0x0000000000433464 in execute_command_internal ()
    #25 0x000000000043583e in execute_command ()
    #26 0x0000000000433464 in execute_command_internal ()
    #27 0x0000000000432613 in execute_command_internal ()
    #28 0x000000000043440e in ?? ()
    #29 0x0000000000431a8c in ?? ()
    #30 0x0000000000432873 in execute_command_internal ()
    #31 0x000000000043583e in execute_command ()
    #32 0x000000000043310d in execute_command_internal ()
    #33 0x000000000043349f in execute_command_internal ()
    #34 0x000000000043583e in execute_command ()
    #35 0x0000000000433464 in execute_command_internal ()
    #36 0x000000000043583e in execute_command ()
    #37 0x0000000000433464 in execute_command_internal ()
    #38 0x000000000043583e in execute_command ()
    #39 0x0000000000433464 in execute_command_internal ()
    #40 0x000000000043583e in execute_command ()
    #41 0x0000000000433464 in execute_command_internal ()
    #42 0x000000000043583e in execute_command ()
    #43 0x0000000000433464 in execute_command_internal ()
    #44 0x000000000043583e in execute_command ()
    #45 0x0000000000433464 in execute_command_internal ()
    #46 0x000000000043583e in execute_command ()
    #47 0x0000000000433464 in execute_command_internal ()
    #48 0x000000000043583e in execute_command ()
    #49 0x0000000000433464 in execute_command_internal ()
    #50 0x000000000043583e in execute_command ()
    #51 0x0000000000433464 in execute_command_internal ()
    #52 0x0000000000432613 in execute_command_internal ()
    #53 0x000000000043440e in ?? ()
    #54 0x00000000004346b5 in execute_shell_function ()
    #55 0x00000000004693c7 in gen_compspec_completions ()
    #56 0x0000000000469b69 in ?? ()
    #57 0x0000000000469cac in programmable_completions ()
    #58 0x0000000000463d01 in ?? ()
    #59 0x000000000049130f in ?? ()
    #60 0x0000000000491d68 in rl_complete_internal ()
    #61 0x000000000048978d in _rl_dispatch_subseq ()
    #62 0x0000000000489cf8 in readline_internal_char ()
    #63 0x000000000048a1a5 in readline ()
    #64 0x000000000041e59c in ?? ()
    #65 0x0000000000420158 in ?? ()
    #66 0x0000000000422d76 in ?? ()
    #67 0x000000000042610b in yyparse ()
    #68 0x000000000041de6a in parse_command ()
    #69 0x000000000041df36 in read_command ()
    #70 0x000000000041e193 in reader_loop ()
    #71 0x000000000041c6e5 in main ()


Thanks.
diff mbox

Patch

diff --git a/hw/9pfs/cofs.c b/hw/9pfs/cofs.c
index 389105074852..0aba70ad792f 100644
--- a/hw/9pfs/cofs.c
+++ b/hw/9pfs/cofs.c
@@ -17,35 +17,55 @@ 
 #include "block/coroutine.h"
 #include "virtio-9p-coth.h"
 
+static ssize_t __readlink(V9fsState *s, V9fsPath *path, V9fsString *buf)
+{
+    ssize_t len, maxlen = PATH_MAX;
+
+    buf->data = g_malloc(PATH_MAX);
+    for (;;) {
+        len = s->ops->readlink(&s->ctx, path, buf->data, maxlen);
+        if (len < 0) {
+            g_free(buf->data);
+            buf->data = NULL;
+            buf->size = 0;
+            break;
+        } else if (len == maxlen) {
+            /*
+             * We dodn't have space to put the NULL or we have more
+             * to read. Increase the size and try again
+             */
+            maxlen *= 2;
+            g_free(buf->data);
+            buf->data = g_malloc(maxlen);
+            continue;
+        }
+        /*
+         * Null terminate the readlink output
+         */
+        buf->data[len] = '\0';
+        buf->size = len;
+        break;
+    }
+    return len;
+}
+
 int v9fs_co_readlink(V9fsPDU *pdu, V9fsPath *path, V9fsString *buf)
 {
     int err;
-    ssize_t len;
     V9fsState *s = pdu->s;
 
     if (v9fs_request_cancelled(pdu)) {
         return -EINTR;
     }
-    buf->data = g_malloc(PATH_MAX);
     v9fs_path_read_lock(s);
     v9fs_co_run_in_worker(
         {
-            len = s->ops->readlink(&s->ctx, path,
-                                   buf->data, PATH_MAX - 1);
-            if (len > -1) {
-                buf->size = len;
-                buf->data[len] = 0;
-                err = 0;
-            } else {
+            err = __readlink(s, path, buf);
+            if (err < 0) {
                 err = -errno;
             }
         });
     v9fs_path_unlock(s);
-    if (err) {
-        g_free(buf->data);
-        buf->data = NULL;
-        buf->size = 0;
-    }
     return err;
 }
 
diff --git a/hw/9pfs/virtio-9p-handle.c b/hw/9pfs/virtio-9p-handle.c
index 17002a3d2867..4b79cefd135e 100644
--- a/hw/9pfs/virtio-9p-handle.c
+++ b/hw/9pfs/virtio-9p-handle.c
@@ -498,7 +498,7 @@  static int handle_lremovexattr(FsContext *ctx, V9fsPath *fs_path,
 static int handle_name_to_path(FsContext *ctx, V9fsPath *dir_path,
                               const char *name, V9fsPath *target)
 {
-    char buffer[PATH_MAX];
+    char *buffer;
     struct file_handle *fh;
     int dirfd, ret, mnt_id;
     struct handle_data *data = (struct handle_data *)ctx->private;
@@ -513,7 +513,9 @@  static int handle_name_to_path(FsContext *ctx, V9fsPath *dir_path,
         dirfd = open_by_handle(data->mountfd, dir_path->data, O_PATH);
     } else {
         /* relative to export root */
-        dirfd = open(rpath(ctx, ".", buffer), O_DIRECTORY);
+        buffer = rpath(ctx, ".");
+        dirfd = open(buffer, O_DIRECTORY);
+        g_free(buffer);
     }
     if (dirfd < 0) {
         return dirfd;
@@ -521,7 +523,7 @@  static int handle_name_to_path(FsContext *ctx, V9fsPath *dir_path,
     fh = g_malloc(sizeof(struct file_handle) + data->handle_bytes);
     fh->handle_bytes = data->handle_bytes;
     /* add a "./" at the beginning of the path */
-    snprintf(buffer, PATH_MAX, "./%s", name);
+    buffer = g_strdup_printf("./%s", name);
     /* flag = 0 imply don't follow symlink */
     ret = name_to_handle(dirfd, buffer, fh, &mnt_id, 0);
     if (!ret) {
@@ -531,6 +533,7 @@  static int handle_name_to_path(FsContext *ctx, V9fsPath *dir_path,
         g_free(fh);
     }
     close(dirfd);
+    g_free(buffer);
     return ret;
 }
 
diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c
index dc615a4d0fa4..56b302c122b6 100644
--- a/hw/9pfs/virtio-9p-local.c
+++ b/hw/9pfs/virtio-9p-local.c
@@ -42,18 +42,18 @@ 
 
 #define VIRTFS_META_DIR ".virtfs_metadata"
 
-static const char *local_mapped_attr_path(FsContext *ctx,
-                                          const char *path, char *buffer)
+static char *local_mapped_attr_path(FsContext *ctx, const char *path)
 {
     char *dir_name;
     char *tmp_path = g_strdup(path);
     char *base_name = basename(tmp_path);
+    char *buffer;
 
     /* NULL terminate the directory */
     dir_name = tmp_path;
     *(base_name - 1) = '\0';
 
-    snprintf(buffer, PATH_MAX, "%s/%s/%s/%s",
+    buffer = g_strdup_printf("%s/%s/%s/%s",
              ctx->fs_root, dir_name, VIRTFS_META_DIR, base_name);
     g_free(tmp_path);
     return buffer;
@@ -92,10 +92,11 @@  static void local_mapped_file_attr(FsContext *ctx, const char *path,
 {
     FILE *fp;
     char buf[ATTR_MAX];
-    char attr_path[PATH_MAX];
+    char *attr_path;
 
-    local_mapped_attr_path(ctx, path, attr_path);
+    attr_path = local_mapped_attr_path(ctx, path);
     fp = local_fopen(attr_path, "r");
+    g_free(attr_path);
     if (!fp) {
         return;
     }
@@ -118,12 +119,13 @@  static void local_mapped_file_attr(FsContext *ctx, const char *path,
 static int local_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf)
 {
     int err;
-    char buffer[PATH_MAX];
+    char *buffer;
     char *path = fs_path->data;
 
-    err =  lstat(rpath(fs_ctx, path, buffer), stbuf);
+    buffer = rpath(fs_ctx, path);
+    err =  lstat(buffer, stbuf);
     if (err) {
-        return err;
+        goto err_out;
     }
     if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
         /* Actual credentials are part of extended attrs */
@@ -131,41 +133,42 @@  static int local_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf)
         gid_t tmp_gid;
         mode_t tmp_mode;
         dev_t tmp_dev;
-        if (getxattr(rpath(fs_ctx, path, buffer), "user.virtfs.uid", &tmp_uid,
-                    sizeof(uid_t)) > 0) {
+        if (getxattr(buffer, "user.virtfs.uid", &tmp_uid, sizeof(uid_t)) > 0) {
             stbuf->st_uid = tmp_uid;
         }
-        if (getxattr(rpath(fs_ctx, path, buffer), "user.virtfs.gid", &tmp_gid,
-                    sizeof(gid_t)) > 0) {
+        if (getxattr(buffer, "user.virtfs.gid", &tmp_gid, sizeof(gid_t)) > 0) {
             stbuf->st_gid = tmp_gid;
         }
-        if (getxattr(rpath(fs_ctx, path, buffer), "user.virtfs.mode",
+        if (getxattr(buffer, "user.virtfs.mode",
                     &tmp_mode, sizeof(mode_t)) > 0) {
             stbuf->st_mode = tmp_mode;
         }
-        if (getxattr(rpath(fs_ctx, path, buffer), "user.virtfs.rdev", &tmp_dev,
-                        sizeof(dev_t)) > 0) {
+        if (getxattr(buffer, "user.virtfs.rdev", &tmp_dev, sizeof(dev_t)) > 0) {
                 stbuf->st_rdev = tmp_dev;
         }
     } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
         local_mapped_file_attr(fs_ctx, path, stbuf);
     }
+
+err_out:
+    g_free(buffer);
     return err;
 }
 
 static int local_create_mapped_attr_dir(FsContext *ctx, const char *path)
 {
     int err;
-    char attr_dir[PATH_MAX];
+    char *attr_dir;
     char *tmp_path = g_strdup(path);
 
-    snprintf(attr_dir, PATH_MAX, "%s/%s/%s",
+    attr_dir = g_strdup_printf("%s/%s/%s",
              ctx->fs_root, dirname(tmp_path), VIRTFS_META_DIR);
 
     err = mkdir(attr_dir, 0700);
     if (err < 0 && errno == EEXIST) {
         err = 0;
     }
+    g_free(attr_dir);
     g_free(tmp_path);
     return err;
 }
@@ -176,10 +179,11 @@  static int local_set_mapped_file_attr(FsContext *ctx,
     FILE *fp;
     int ret = 0;
     char buf[ATTR_MAX];
-    char attr_path[PATH_MAX];
+    char *attr_path;
     int uid = -1, gid = -1, mode = -1, rdev = -1;
 
-    fp = local_fopen(local_mapped_attr_path(ctx, path, attr_path), "r");
+    attr_path = local_mapped_attr_path(ctx, path);
+    fp = local_fopen(attr_path, "r");
     if (!fp) {
         goto create_map_file;
     }
@@ -241,6 +245,7 @@  update_map_file:
     fclose(fp);
 
 err_out:
+    g_free(attr_path);
     return ret;
 }
 
@@ -282,36 +287,43 @@  static int local_set_xattr(const char *path, FsCred *credp)
 static int local_post_create_passthrough(FsContext *fs_ctx, const char *path,
                                          FsCred *credp)
 {
-    char buffer[PATH_MAX];
+    char *buffer;
 
-    if (lchown(rpath(fs_ctx, path, buffer), credp->fc_uid,
-                credp->fc_gid) < 0) {
+    buffer = rpath(fs_ctx, path);
+    if (lchown(buffer, credp->fc_uid, credp->fc_gid) < 0) {
         /*
          * If we fail to change ownership and if we are
          * using security model none. Ignore the error
          */
         if ((fs_ctx->export_flags & V9FS_SEC_MASK) != V9FS_SM_NONE) {
-            return -1;
+            goto err;
         }
     }
 
-    if (chmod(rpath(fs_ctx, path, buffer), credp->fc_mode & 07777) < 0) {
-        return -1;
+    if (chmod(buffer, credp->fc_mode & 07777) < 0) {
+        goto err;
     }
+
+    g_free(buffer);
     return 0;
+err:
+    g_free(buffer);
+    return -1;
 }
 
 static ssize_t local_readlink(FsContext *fs_ctx, V9fsPath *fs_path,
                               char *buf, size_t bufsz)
 {
     ssize_t tsize = -1;
-    char buffer[PATH_MAX];
+    char *buffer;
     char *path = fs_path->data;
 
     if ((fs_ctx->export_flags & V9FS_SM_MAPPED) ||
         (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE)) {
         int fd;
-        fd = open(rpath(fs_ctx, path, buffer), O_RDONLY | O_NOFOLLOW);
+        buffer = rpath(fs_ctx, path);
+        fd = open(buffer, O_RDONLY | O_NOFOLLOW);
+        g_free(buffer);
         if (fd == -1) {
             return -1;
         }
@@ -322,7 +334,9 @@  static ssize_t local_readlink(FsContext *fs_ctx, V9fsPath *fs_path,
         return tsize;
     } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
                (fs_ctx->export_flags & V9FS_SM_NONE)) {
-        tsize = readlink(rpath(fs_ctx, path, buffer), buf, bufsz);
+        buffer = rpath(fs_ctx, path);
+        tsize = readlink(buffer, buf, bufsz);
+        g_free(buffer);
     }
     return tsize;
 }
@@ -340,20 +354,24 @@  static int local_closedir(FsContext *ctx, V9fsFidOpenState *fs)
 static int local_open(FsContext *ctx, V9fsPath *fs_path,
                       int flags, V9fsFidOpenState *fs)
 {
-    char buffer[PATH_MAX];
+    char *buffer;
     char *path = fs_path->data;
 
-    fs->fd = open(rpath(ctx, path, buffer), flags | O_NOFOLLOW);
+    buffer = rpath(ctx, path);
+    fs->fd = open(buffer, flags | O_NOFOLLOW);
+    g_free(buffer);
     return fs->fd;
 }
 
 static int local_opendir(FsContext *ctx,
                          V9fsPath *fs_path, V9fsFidOpenState *fs)
 {
-    char buffer[PATH_MAX];
+    char *buffer;
     char *path = fs_path->data;
 
-    fs->dir = opendir(rpath(ctx, path, buffer));
+    buffer = rpath(ctx, path);
+    fs->dir = opendir(buffer);
+    g_free(buffer);
     if (!fs->dir) {
         return -1;
     }
@@ -441,18 +459,23 @@  static ssize_t local_pwritev(FsContext *ctx, V9fsFidOpenState *fs,
 
 static int local_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
 {
-    char buffer[PATH_MAX];
+    char *buffer;
+    int ret = -1;
     char *path = fs_path->data;
 
     if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
-        return local_set_xattr(rpath(fs_ctx, path, buffer), credp);
+        buffer = rpath(fs_ctx, path);
+        ret = local_set_xattr(buffer, credp);
+        g_free(buffer);
     } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
         return local_set_mapped_file_attr(fs_ctx, path, credp);
     } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
                (fs_ctx->export_flags & V9FS_SM_NONE)) {
-        return chmod(rpath(fs_ctx, path, buffer), credp->fc_mode);
+        buffer = rpath(fs_ctx, path);
+        ret = chmod(buffer, credp->fc_mode);
+        g_free(buffer);
     }
-    return -1;
+    return ret;
 }
 
 static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
@@ -462,7 +485,7 @@  static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
     int err = -1;
     int serrno = 0;
     V9fsString fullname;
-    char buffer[PATH_MAX];
+    char *buffer;
 
     v9fs_string_init(&fullname);
     v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
@@ -470,21 +493,23 @@  static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
 
     /* Determine the security model */
     if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
-        err = mknod(rpath(fs_ctx, path, buffer),
-                SM_LOCAL_MODE_BITS|S_IFREG, 0);
+        buffer = rpath(fs_ctx, path);
+        err = mknod(buffer, SM_LOCAL_MODE_BITS|S_IFREG, 0);
         if (err == -1) {
+            g_free(buffer);
             goto out;
         }
-        err = local_set_xattr(rpath(fs_ctx, path, buffer), credp);
+        err = local_set_xattr(buffer, credp);
         if (err == -1) {
             serrno = errno;
             goto err_end;
         }
     } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
 
-        err = mknod(rpath(fs_ctx, path, buffer),
-                    SM_LOCAL_MODE_BITS|S_IFREG, 0);
+        buffer = rpath(fs_ctx, path);
+        err = mknod(buffer, SM_LOCAL_MODE_BITS|S_IFREG, 0);
         if (err == -1) {
+            g_free(buffer);
             goto out;
         }
         err = local_set_mapped_file_attr(fs_ctx, path, credp);
@@ -494,9 +519,10 @@  static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
         }
     } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
                (fs_ctx->export_flags & V9FS_SM_NONE)) {
-        err = mknod(rpath(fs_ctx, path, buffer), credp->fc_mode,
-                credp->fc_rdev);
+        buffer = rpath(fs_ctx, path);
+        err = mknod(buffer, credp->fc_mode, credp->fc_rdev);
         if (err == -1) {
+            g_free(buffer);
             goto out;
         }
         err = local_post_create_passthrough(fs_ctx, path, credp);
@@ -508,8 +534,9 @@  static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
     goto out;
 
 err_end:
-    remove(rpath(fs_ctx, path, buffer));
+    remove(buffer);
     errno = serrno;
+    g_free(buffer);
 out:
     v9fs_string_free(&fullname);
     return err;
@@ -522,7 +549,7 @@  static int local_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
     int err = -1;
     int serrno = 0;
     V9fsString fullname;
-    char buffer[PATH_MAX];
+    char *buffer;
 
     v9fs_string_init(&fullname);
     v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
@@ -530,19 +557,23 @@  static int local_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
 
     /* Determine the security model */
     if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
-        err = mkdir(rpath(fs_ctx, path, buffer), SM_LOCAL_DIR_MODE_BITS);
+        buffer = rpath(fs_ctx, path);
+        err = mkdir(buffer, SM_LOCAL_DIR_MODE_BITS);
         if (err == -1) {
+            g_free(buffer);
             goto out;
         }
         credp->fc_mode = credp->fc_mode|S_IFDIR;
-        err = local_set_xattr(rpath(fs_ctx, path, buffer), credp);
+        err = local_set_xattr(buffer, credp);
         if (err == -1) {
             serrno = errno;
             goto err_end;
         }
     } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
-        err = mkdir(rpath(fs_ctx, path, buffer), SM_LOCAL_DIR_MODE_BITS);
+        buffer = rpath(fs_ctx, path);
+        err = mkdir(buffer, SM_LOCAL_DIR_MODE_BITS);
         if (err == -1) {
+            g_free(buffer);
             goto out;
         }
         credp->fc_mode = credp->fc_mode|S_IFDIR;
@@ -553,8 +584,10 @@  static int local_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
         }
     } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
                (fs_ctx->export_flags & V9FS_SM_NONE)) {
-        err = mkdir(rpath(fs_ctx, path, buffer), credp->fc_mode);
+        buffer = rpath(fs_ctx, path);
+        err = mkdir(buffer, credp->fc_mode);
         if (err == -1) {
+            g_free(buffer);
             goto out;
         }
         err = local_post_create_passthrough(fs_ctx, path, credp);
@@ -566,8 +599,9 @@  static int local_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
     goto out;
 
 err_end:
-    remove(rpath(fs_ctx, path, buffer));
+    remove(buffer);
     errno = serrno;
+    g_free(buffer);
 out:
     v9fs_string_free(&fullname);
     return err;
@@ -626,7 +660,7 @@  static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
     int err = -1;
     int serrno = 0;
     V9fsString fullname;
-    char buffer[PATH_MAX];
+    char *buffer;
 
     /*
      * Mark all the open to not follow symlinks
@@ -639,21 +673,25 @@  static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
 
     /* Determine the security model */
     if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
-        fd = open(rpath(fs_ctx, path, buffer), flags, SM_LOCAL_MODE_BITS);
+        buffer = rpath(fs_ctx, path);
+        fd = open(buffer, flags, SM_LOCAL_MODE_BITS);
         if (fd == -1) {
+            g_free(buffer);
             err = fd;
             goto out;
         }
         credp->fc_mode = credp->fc_mode|S_IFREG;
         /* Set cleint credentials in xattr */
-        err = local_set_xattr(rpath(fs_ctx, path, buffer), credp);
+        err = local_set_xattr(buffer, credp);
         if (err == -1) {
             serrno = errno;
             goto err_end;
         }
     } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
-        fd = open(rpath(fs_ctx, path, buffer), flags, SM_LOCAL_MODE_BITS);
+        buffer = rpath(fs_ctx, path);
+        fd = open(buffer, flags, SM_LOCAL_MODE_BITS);
         if (fd == -1) {
+            g_free(buffer);
             err = fd;
             goto out;
         }
@@ -666,8 +704,10 @@  static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
         }
     } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
                (fs_ctx->export_flags & V9FS_SM_NONE)) {
-        fd = open(rpath(fs_ctx, path, buffer), flags, credp->fc_mode);
+        buffer = rpath(fs_ctx, path);
+        fd = open(buffer, flags, credp->fc_mode);
         if (fd == -1) {
+            g_free(buffer);
             err = fd;
             goto out;
         }
@@ -683,8 +723,9 @@  static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
 
 err_end:
     close(fd);
-    remove(rpath(fs_ctx, path, buffer));
+    remove(buffer);
     errno = serrno;
+    g_free(buffer);
 out:
     v9fs_string_free(&fullname);
     return err;
@@ -698,7 +739,7 @@  static int local_symlink(FsContext *fs_ctx, const char *oldpath,
     int serrno = 0;
     char *newpath;
     V9fsString fullname;
-    char buffer[PATH_MAX];
+    char *buffer;
 
     v9fs_string_init(&fullname);
     v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
@@ -708,10 +749,10 @@  static int local_symlink(FsContext *fs_ctx, const char *oldpath,
     if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
         int fd;
         ssize_t oldpath_size, write_size;
-        fd = open(rpath(fs_ctx, newpath, buffer),
-                  O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW,
-                  SM_LOCAL_MODE_BITS);
+        buffer = rpath(fs_ctx, newpath);
+        fd = open(buffer, O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW, SM_LOCAL_MODE_BITS);
         if (fd == -1) {
+            g_free(buffer);
             err = fd;
             goto out;
         }
@@ -730,7 +771,7 @@  static int local_symlink(FsContext *fs_ctx, const char *oldpath,
         close(fd);
         /* Set cleint credentials in symlink's xattr */
         credp->fc_mode = credp->fc_mode|S_IFLNK;
-        err = local_set_xattr(rpath(fs_ctx, newpath, buffer), credp);
+        err = local_set_xattr(buffer, credp);
         if (err == -1) {
             serrno = errno;
             goto err_end;
@@ -738,10 +779,10 @@  static int local_symlink(FsContext *fs_ctx, const char *oldpath,
     } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
         int fd;
         ssize_t oldpath_size, write_size;
-        fd = open(rpath(fs_ctx, newpath, buffer),
-                  O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW,
-                  SM_LOCAL_MODE_BITS);
+        buffer = rpath(fs_ctx, newpath);
+        fd = open(buffer, O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW, SM_LOCAL_MODE_BITS);
         if (fd == -1) {
+            g_free(buffer);
             err = fd;
             goto out;
         }
@@ -767,12 +808,13 @@  static int local_symlink(FsContext *fs_ctx, const char *oldpath,
         }
     } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
                (fs_ctx->export_flags & V9FS_SM_NONE)) {
-        err = symlink(oldpath, rpath(fs_ctx, newpath, buffer));
+        buffer = rpath(fs_ctx, newpath);
+        err = symlink(oldpath, buffer);
         if (err) {
+            g_free(buffer);
             goto out;
         }
-        err = lchown(rpath(fs_ctx, newpath, buffer), credp->fc_uid,
-                     credp->fc_gid);
+        err = lchown(buffer, credp->fc_uid, credp->fc_gid);
         if (err == -1) {
             /*
              * If we fail to change ownership and if we are
@@ -788,8 +830,9 @@  static int local_symlink(FsContext *fs_ctx, const char *oldpath,
     goto out;
 
 err_end:
-    remove(rpath(fs_ctx, newpath, buffer));
+    remove(buffer);
     errno = serrno;
+    g_free(buffer);
 out:
     v9fs_string_free(&fullname);
     return err;
@@ -800,13 +843,16 @@  static int local_link(FsContext *ctx, V9fsPath *oldpath,
 {
     int ret;
     V9fsString newpath;
-    char buffer[PATH_MAX], buffer1[PATH_MAX];
+    char *buffer, *buffer1;
 
     v9fs_string_init(&newpath);
     v9fs_string_sprintf(&newpath, "%s/%s", dirpath->data, name);
 
-    ret = link(rpath(ctx, oldpath->data, buffer),
-               rpath(ctx, newpath.data, buffer1));
+    buffer = rpath(ctx, oldpath->data);
+    buffer1 = rpath(ctx, newpath.data);
+    ret = link(buffer, buffer1);
+    g_free(buffer);
+    g_free(buffer1);
 
     /* now link the virtfs_metadata files */
     if (!ret && (ctx->export_flags & V9FS_SM_MAPPED_FILE)) {
@@ -815,8 +861,11 @@  static int local_link(FsContext *ctx, V9fsPath *oldpath,
         if (ret < 0) {
             goto err_out;
         }
-        ret = link(local_mapped_attr_path(ctx, oldpath->data, buffer),
-                   local_mapped_attr_path(ctx, newpath.data, buffer1));
+        buffer = local_mapped_attr_path(ctx, oldpath->data);
+        buffer1 = local_mapped_attr_path(ctx, newpath.data);
+        ret = link(buffer, buffer1);
+        g_free(buffer);
+        g_free(buffer1);
         if (ret < 0 && errno != ENOENT) {
             goto err_out;
         }
@@ -828,17 +877,21 @@  err_out:
 
 static int local_truncate(FsContext *ctx, V9fsPath *fs_path, off_t size)
 {
-    char buffer[PATH_MAX];
+    char *buffer;
+    int ret;
     char *path = fs_path->data;
 
-    return truncate(rpath(ctx, path, buffer), size);
+    buffer = rpath(ctx, path);
+    ret = truncate(buffer, size);
+    g_free(buffer);
+    return ret;
 }
 
 static int local_rename(FsContext *ctx, const char *oldpath,
                         const char *newpath)
 {
     int err;
-    char buffer[PATH_MAX], buffer1[PATH_MAX];
+    char *buffer, *buffer1;
 
     if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
         err = local_create_mapped_attr_dir(ctx, newpath);
@@ -846,50 +899,69 @@  static int local_rename(FsContext *ctx, const char *oldpath,
             return err;
         }
         /* rename the .virtfs_metadata files */
-        err = rename(local_mapped_attr_path(ctx, oldpath, buffer),
-                     local_mapped_attr_path(ctx, newpath, buffer1));
+        buffer = local_mapped_attr_path(ctx, oldpath);
+        buffer1 = local_mapped_attr_path(ctx, newpath);
+        err = rename(buffer, buffer1);
+        g_free(buffer);
+        g_free(buffer1);
         if (err < 0 && errno != ENOENT) {
             return err;
         }
     }
-    return rename(rpath(ctx, oldpath, buffer), rpath(ctx, newpath, buffer1));
+
+    buffer = rpath(ctx, oldpath);
+    buffer1 = rpath(ctx, newpath);
+    err = rename(buffer, buffer1);
+    g_free(buffer);
+    g_free(buffer1);
+    return err;
 }
 
 static int local_chown(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
 {
-    char buffer[PATH_MAX];
+    char *buffer;
+    int ret = -1;
     char *path = fs_path->data;
 
     if ((credp->fc_uid == -1 && credp->fc_gid == -1) ||
         (fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
         (fs_ctx->export_flags & V9FS_SM_NONE)) {
-        return lchown(rpath(fs_ctx, path, buffer),
-                      credp->fc_uid, credp->fc_gid);
+        buffer = rpath(fs_ctx, path);
+        ret = lchown(buffer, credp->fc_uid, credp->fc_gid);
+        g_free(buffer);
     } else if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
-        return local_set_xattr(rpath(fs_ctx, path, buffer), credp);
+        buffer = rpath(fs_ctx, path);
+        ret = local_set_xattr(buffer, credp);
+        g_free(buffer);
     } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
         return local_set_mapped_file_attr(fs_ctx, path, credp);
     }
-    return -1;
+    return ret;
 }
 
 static int local_utimensat(FsContext *s, V9fsPath *fs_path,
                            const struct timespec *buf)
 {
-    char buffer[PATH_MAX];
+    char *buffer;
+    int ret;
     char *path = fs_path->data;
 
-    return qemu_utimens(rpath(s, path, buffer), buf);
+    buffer = rpath(s, path);
+    ret = qemu_utimens(buffer, buf);
+    g_free(buffer);
+    return ret;
 }
 
 static int local_remove(FsContext *ctx, const char *path)
 {
     int err;
     struct stat stbuf;
-    char buffer[PATH_MAX];
+    char *buffer;
 
     if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
-        err =  lstat(rpath(ctx, path, buffer), &stbuf);
+        buffer = rpath(ctx, path);
+        err =  lstat(buffer, &stbuf);
+        g_free(buffer);
         if (err) {
             goto err_out;
         }
@@ -898,9 +970,10 @@  static int local_remove(FsContext *ctx, const char *path)
          * directory
          */
         if (S_ISDIR(stbuf.st_mode)) {
-            snprintf(buffer, ARRAY_SIZE(buffer), "%s/%s/%s",
-                     ctx->fs_root, path, VIRTFS_META_DIR);
+            buffer = g_strdup_printf("%s/%s/%s", ctx->fs_root,
+                                     path, VIRTFS_META_DIR);
             err = remove(buffer);
+            g_free(buffer);
             if (err < 0 && errno != ENOENT) {
                 /*
                  * We didn't had the .virtfs_metadata file. May be file created
@@ -913,7 +986,9 @@  static int local_remove(FsContext *ctx, const char *path)
          * Now remove the name from parent directory
          * .virtfs_metadata directory
          */
-        err = remove(local_mapped_attr_path(ctx, path, buffer));
+        buffer = local_mapped_attr_path(ctx, path);
+        err = remove(buffer);
+        g_free(buffer);
         if (err < 0 && errno != ENOENT) {
             /*
              * We didn't had the .virtfs_metadata file. May be file created
@@ -922,7 +997,10 @@  static int local_remove(FsContext *ctx, const char *path)
             goto err_out;
         }
     }
-    return remove(rpath(ctx, path, buffer));
+
+    buffer = rpath(ctx, path);
+    err = remove(buffer);
+    g_free(buffer);
 err_out:
     return err;
 }
@@ -947,10 +1025,14 @@  static int local_fsync(FsContext *ctx, int fid_type,
 
 static int local_statfs(FsContext *s, V9fsPath *fs_path, struct statfs *stbuf)
 {
-    char buffer[PATH_MAX];
+    char *buffer;
+    int ret;
     char *path = fs_path->data;
 
-    return statfs(rpath(s, path, buffer), stbuf);
+    buffer = rpath(s, path);
+    ret = statfs(buffer, stbuf);
+    g_free(buffer);
+    return ret;
 }
 
 static ssize_t local_lgetxattr(FsContext *ctx, V9fsPath *fs_path,
@@ -1023,7 +1105,7 @@  static int local_unlinkat(FsContext *ctx, V9fsPath *dir,
 {
     int ret;
     V9fsString fullname;
-    char buffer[PATH_MAX];
+    char *buffer;
 
     v9fs_string_init(&fullname);
 
@@ -1034,9 +1116,10 @@  static int local_unlinkat(FsContext *ctx, V9fsPath *dir,
              * If directory remove .virtfs_metadata contained in the
              * directory
              */
-            snprintf(buffer, ARRAY_SIZE(buffer), "%s/%s/%s", ctx->fs_root,
-                     fullname.data, VIRTFS_META_DIR);
+            buffer = g_strdup_printf("%s/%s/%s", ctx->fs_root,
+                                     fullname.data, VIRTFS_META_DIR);
             ret = remove(buffer);
+            g_free(buffer);
             if (ret < 0 && errno != ENOENT) {
                 /*
                  * We didn't had the .virtfs_metadata file. May be file created
@@ -1049,7 +1132,9 @@  static int local_unlinkat(FsContext *ctx, V9fsPath *dir,
          * Now remove the name from parent directory
          * .virtfs_metadata directory.
          */
-        ret = remove(local_mapped_attr_path(ctx, fullname.data, buffer));
+        buffer = local_mapped_attr_path(ctx, fullname.data);
+        ret = remove(buffer);
+        g_free(buffer);
         if (ret < 0 && errno != ENOENT) {
             /*
              * We didn't had the .virtfs_metadata file. May be file created
@@ -1059,7 +1144,9 @@  static int local_unlinkat(FsContext *ctx, V9fsPath *dir,
         }
     }
     /* Remove the name finally */
-    ret = remove(rpath(ctx, fullname.data, buffer));
+    buffer = rpath(ctx, fullname.data);
+    ret = remove(buffer);
+    g_free(buffer);
 
 err_out:
     v9fs_string_free(&fullname);
diff --git a/hw/9pfs/virtio-9p-posix-acl.c b/hw/9pfs/virtio-9p-posix-acl.c
index 339c5ecae441..803d9d94f3b8 100644
--- a/hw/9pfs/virtio-9p-posix-acl.c
+++ b/hw/9pfs/virtio-9p-posix-acl.c
@@ -26,8 +26,13 @@ 
 static ssize_t mp_pacl_getxattr(FsContext *ctx, const char *path,
                                 const char *name, void *value, size_t size)
 {
-    char buffer[PATH_MAX];
-    return lgetxattr(rpath(ctx, path, buffer), MAP_ACL_ACCESS, value, size);
+    char *buffer;
+    ssize_t ret;
+
+    buffer = rpath(ctx, path);
+    ret = lgetxattr(buffer, MAP_ACL_ACCESS, value, size);
+    g_free(buffer);
+    return ret;
 }
 
 static ssize_t mp_pacl_listxattr(FsContext *ctx, const char *path,
@@ -52,17 +57,23 @@  static ssize_t mp_pacl_listxattr(FsContext *ctx, const char *path,
 static int mp_pacl_setxattr(FsContext *ctx, const char *path, const char *name,
                             void *value, size_t size, int flags)
 {
-    char buffer[PATH_MAX];
-    return lsetxattr(rpath(ctx, path, buffer), MAP_ACL_ACCESS, value,
-            size, flags);
+    char *buffer;
+    int ret;
+
+    buffer = rpath(ctx, path);
+    ret = lsetxattr(buffer, MAP_ACL_ACCESS, value, size, flags);
+    g_free(buffer);
+    return ret;
 }
 
 static int mp_pacl_removexattr(FsContext *ctx,
                                const char *path, const char *name)
 {
     int ret;
-    char buffer[PATH_MAX];
-    ret  = lremovexattr(rpath(ctx, path, buffer), MAP_ACL_ACCESS);
+    char *buffer;
+
+    buffer = rpath(ctx, path);
+    ret  = lremovexattr(buffer, MAP_ACL_ACCESS);
     if (ret == -1 && errno == ENODATA) {
         /*
          * We don't get ENODATA error when trying to remove a
@@ -72,14 +83,20 @@  static int mp_pacl_removexattr(FsContext *ctx,
         errno = 0;
         ret = 0;
     }
+    g_free(buffer);
     return ret;
 }
 
 static ssize_t mp_dacl_getxattr(FsContext *ctx, const char *path,
                                 const char *name, void *value, size_t size)
 {
-    char buffer[PATH_MAX];
-    return lgetxattr(rpath(ctx, path, buffer), MAP_ACL_DEFAULT, value, size);
+    char *buffer;
+    ssize_t ret;
+
+    buffer = rpath(ctx, path);
+    ret = lgetxattr(buffer, MAP_ACL_DEFAULT, value, size);
+    g_free(buffer);
+    return ret;
 }
 
 static ssize_t mp_dacl_listxattr(FsContext *ctx, const char *path,
@@ -104,17 +121,23 @@  static ssize_t mp_dacl_listxattr(FsContext *ctx, const char *path,
 static int mp_dacl_setxattr(FsContext *ctx, const char *path, const char *name,
                             void *value, size_t size, int flags)
 {
-    char buffer[PATH_MAX];
-    return lsetxattr(rpath(ctx, path, buffer), MAP_ACL_DEFAULT, value,
-            size, flags);
+    char *buffer;
+    int ret;
+
+    buffer = rpath(ctx, path);
+    ret = lsetxattr(buffer, MAP_ACL_DEFAULT, value, size, flags);
+    g_free(buffer);
+    return ret;
 }
 
 static int mp_dacl_removexattr(FsContext *ctx,
                                const char *path, const char *name)
 {
     int ret;
-    char buffer[PATH_MAX];
-    ret  = lremovexattr(rpath(ctx, path, buffer), MAP_ACL_DEFAULT);
+    char *buffer;
+
+    buffer = rpath(ctx, path);
+    ret  = lremovexattr(buffer, MAP_ACL_DEFAULT);
     if (ret == -1 && errno == ENODATA) {
         /*
          * We don't get ENODATA error when trying to remove a
@@ -124,6 +147,7 @@  static int mp_dacl_removexattr(FsContext *ctx,
         errno = 0;
         ret = 0;
     }
+    g_free(buffer);
     return ret;
 }
 
diff --git a/hw/9pfs/virtio-9p-xattr-user.c b/hw/9pfs/virtio-9p-xattr-user.c
index e0c92ebf9e5d..46133e06dbdf 100644
--- a/hw/9pfs/virtio-9p-xattr-user.c
+++ b/hw/9pfs/virtio-9p-xattr-user.c
@@ -21,7 +21,9 @@ 
 static ssize_t mp_user_getxattr(FsContext *ctx, const char *path,
                                 const char *name, void *value, size_t size)
 {
-    char buffer[PATH_MAX];
+    char *buffer;
+    ssize_t ret;
+
     if (strncmp(name, "user.virtfs.", 12) == 0) {
         /*
          * Don't allow fetch of user.virtfs namesapce
@@ -30,7 +32,10 @@  static ssize_t mp_user_getxattr(FsContext *ctx, const char *path,
         errno = ENOATTR;
         return -1;
     }
-    return lgetxattr(rpath(ctx, path, buffer), name, value, size);
+    buffer = rpath(ctx, path);
+    ret = lgetxattr(buffer, name, value, size);
+    g_free(buffer);
+    return ret;
 }
 
 static ssize_t mp_user_listxattr(FsContext *ctx, const char *path,
@@ -69,7 +74,9 @@  static ssize_t mp_user_listxattr(FsContext *ctx, const char *path,
 static int mp_user_setxattr(FsContext *ctx, const char *path, const char *name,
                             void *value, size_t size, int flags)
 {
-    char buffer[PATH_MAX];
+    char *buffer;
+    int ret;
+
     if (strncmp(name, "user.virtfs.", 12) == 0) {
         /*
          * Don't allow fetch of user.virtfs namesapce
@@ -78,13 +85,18 @@  static int mp_user_setxattr(FsContext *ctx, const char *path, const char *name,
         errno = EACCES;
         return -1;
     }
-    return lsetxattr(rpath(ctx, path, buffer), name, value, size, flags);
+    buffer = rpath(ctx, path);
+    ret = lsetxattr(buffer, name, value, size, flags);
+    g_free(buffer);
+    return ret;
 }
 
 static int mp_user_removexattr(FsContext *ctx,
                                const char *path, const char *name)
 {
-    char buffer[PATH_MAX];
+    char *buffer;
+    int ret;
+
     if (strncmp(name, "user.virtfs.", 12) == 0) {
         /*
          * Don't allow fetch of user.virtfs namesapce
@@ -93,7 +105,10 @@  static int mp_user_removexattr(FsContext *ctx,
         errno = EACCES;
         return -1;
     }
-    return lremovexattr(rpath(ctx, path, buffer), name);
+    buffer = rpath(ctx, path);
+    ret = lremovexattr(buffer, name);
+    g_free(buffer);
+    return ret;
 }
 
 XattrOperations mapped_user_xattr = {
diff --git a/hw/9pfs/virtio-9p-xattr.c b/hw/9pfs/virtio-9p-xattr.c
index 3fae557a84ff..07183887c5ee 100644
--- a/hw/9pfs/virtio-9p-xattr.c
+++ b/hw/9pfs/virtio-9p-xattr.c
@@ -67,21 +67,24 @@  ssize_t v9fs_list_xattr(FsContext *ctx, const char *path,
                         void *value, size_t vsize)
 {
     ssize_t size = 0;
-    char buffer[PATH_MAX];
+    char *buffer;
     void *ovalue = value;
     XattrOperations *xops;
     char *orig_value, *orig_value_start;
     ssize_t xattr_len, parsed_len = 0, attr_len;
 
     /* Get the actual len */
-    xattr_len = llistxattr(rpath(ctx, path, buffer), value, 0);
+    buffer = rpath(ctx, path);
+    xattr_len = llistxattr(buffer, value, 0);
     if (xattr_len <= 0) {
+        g_free(buffer);
         return xattr_len;
     }
 
     /* Now fetch the xattr and find the actual size */
     orig_value = g_malloc(xattr_len);
-    xattr_len = llistxattr(rpath(ctx, path, buffer), orig_value, xattr_len);
+    xattr_len = llistxattr(buffer, orig_value, xattr_len);
+    g_free(buffer);
 
     /* store the orig pointer */
     orig_value_start = orig_value;
diff --git a/hw/9pfs/virtio-9p-xattr.h b/hw/9pfs/virtio-9p-xattr.h
index 41cc6cbc7ba0..327b32b5aa9e 100644
--- a/hw/9pfs/virtio-9p-xattr.h
+++ b/hw/9pfs/virtio-9p-xattr.h
@@ -54,23 +54,38 @@  ssize_t pt_listxattr(FsContext *ctx, const char *path, char *name, void *value,
 static inline ssize_t pt_getxattr(FsContext *ctx, const char *path,
                                   const char *name, void *value, size_t size)
 {
-    char buffer[PATH_MAX];
-    return lgetxattr(rpath(ctx, path, buffer), name, value, size);
+    char *buffer;
+    ssize_t ret;
+
+    buffer = rpath(ctx, path);
+    ret = lgetxattr(buffer, name, value, size);
+    g_free(buffer);
+    return ret;
 }
 
 static inline int pt_setxattr(FsContext *ctx, const char *path,
                               const char *name, void *value,
                               size_t size, int flags)
 {
-    char buffer[PATH_MAX];
-    return lsetxattr(rpath(ctx, path, buffer), name, value, size, flags);
+    char *buffer;
+    int ret;
+
+    buffer = rpath(ctx, path);
+    ret = lsetxattr(buffer, name, value, size, flags);
+    g_free(buffer);
+    return ret;
 }
 
 static inline int pt_removexattr(FsContext *ctx,
                                  const char *path, const char *name)
 {
-    char buffer[PATH_MAX];
-    return lremovexattr(rpath(ctx, path, buffer), name);
+    char *buffer;
+    int ret;
+
+    buffer = rpath(ctx, path);
+    ret = lremovexattr(path, name);
+    g_free(buffer);
+    return ret;
 }
 
 static inline ssize_t notsup_getxattr(FsContext *ctx, const char *path,
diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h
index 1d6eedb7d8bc..2c3603aed0d0 100644
--- a/hw/9pfs/virtio-9p.h
+++ b/hw/9pfs/virtio-9p.h
@@ -6,6 +6,7 @@ 
 #include <sys/time.h>
 #include <utime.h>
 #include <sys/resource.h>
+#include <glib.h>
 #include "hw/virtio/virtio.h"
 #include "fsdev/file-op-9p.h"
 #include "fsdev/virtio-9p-marshal.h"
@@ -112,10 +113,9 @@  enum p9_proto_version {
 
 #define FID_REFERENCED          0x1
 #define FID_NON_RECLAIMABLE     0x2
-static inline const char *rpath(FsContext *ctx, const char *path, char *buffer)
+static inline char *rpath(FsContext *ctx, const char *path)
 {
-    snprintf(buffer, PATH_MAX, "%s/%s", ctx->fs_root, path);
-    return buffer;
+    return g_strdup_printf("%s/%s", ctx->fs_root, path);
 }
 
 /*