Message ID | 1394205380-31875-5-git-send-email-aneesh.kumar@linux.vnet.ibm.com |
---|---|
State | New |
Headers | show |
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); > } > > /* >
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. >
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 --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); } /*