diff options
-rw-r--r-- | fsdev/file-op-9p.h | 32 | ||||
-rw-r--r-- | hw/9pfs/codir.c | 16 | ||||
-rw-r--r-- | hw/9pfs/cofile.c | 37 | ||||
-rw-r--r-- | hw/9pfs/virtio-9p-coth.h | 6 | ||||
-rw-r--r-- | hw/9pfs/virtio-9p-handle.c | 96 | ||||
-rw-r--r-- | hw/9pfs/virtio-9p-local.c | 100 | ||||
-rw-r--r-- | hw/9pfs/virtio-9p.c | 12 | ||||
-rw-r--r-- | hw/9pfs/virtio-9p.h | 21 |
8 files changed, 179 insertions, 141 deletions
diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h index 5788ff911c..1928da2525 100644 --- a/fsdev/file-op-9p.h +++ b/fsdev/file-op-9p.h @@ -78,6 +78,8 @@ typedef struct V9fsPath { char *data; } V9fsPath; +typedef union V9fsFidOpenState V9fsFidOpenState; + void cred_init(FsCred *); typedef struct FileOperations @@ -94,22 +96,26 @@ typedef struct FileOperations const char *, FsCred *); int (*link)(FsContext *, V9fsPath *, V9fsPath *, const char *); int (*setuid)(FsContext *, uid_t); - int (*close)(FsContext *, int); - int (*closedir)(FsContext *, DIR *); - DIR *(*opendir)(FsContext *, V9fsPath *); - int (*open)(FsContext *, V9fsPath *, int); - int (*open2)(FsContext *, V9fsPath *, const char *, int, FsCred *); - void (*rewinddir)(FsContext *, DIR *); - off_t (*telldir)(FsContext *, DIR *); - int (*readdir_r)(FsContext *, DIR *, struct dirent *, struct dirent **); - void (*seekdir)(FsContext *, DIR *, off_t); - ssize_t (*preadv)(FsContext *, int, const struct iovec *, int, off_t); - ssize_t (*pwritev)(FsContext *, int, const struct iovec *, int, off_t); + int (*close)(FsContext *, V9fsFidOpenState *); + int (*closedir)(FsContext *, V9fsFidOpenState *); + int (*opendir)(FsContext *, V9fsPath *, V9fsFidOpenState *); + int (*open)(FsContext *, V9fsPath *, int, V9fsFidOpenState *); + int (*open2)(FsContext *, V9fsPath *, const char *, + int, FsCred *, V9fsFidOpenState *); + void (*rewinddir)(FsContext *, V9fsFidOpenState *); + off_t (*telldir)(FsContext *, V9fsFidOpenState *); + int (*readdir_r)(FsContext *, V9fsFidOpenState *, + struct dirent *, struct dirent **); + void (*seekdir)(FsContext *, V9fsFidOpenState *, off_t); + ssize_t (*preadv)(FsContext *, V9fsFidOpenState *, + const struct iovec *, int, off_t); + ssize_t (*pwritev)(FsContext *, V9fsFidOpenState *, + const struct iovec *, int, off_t); int (*mkdir)(FsContext *, V9fsPath *, const char *, FsCred *); - int (*fstat)(FsContext *, int, struct stat *); + int (*fstat)(FsContext *, V9fsFidOpenState *, struct stat *); int (*rename)(FsContext *, const char *, const char *); int (*truncate)(FsContext *, V9fsPath *, off_t); - int (*fsync)(FsContext *, int, int); + int (*fsync)(FsContext *, V9fsFidOpenState *, int); int (*statfs)(FsContext *s, V9fsPath *path, struct statfs *stbuf); ssize_t (*lgetxattr)(FsContext *, V9fsPath *, const char *, void *, size_t); diff --git a/hw/9pfs/codir.c b/hw/9pfs/codir.c index 72732e7c53..9b6d47d91d 100644 --- a/hw/9pfs/codir.c +++ b/hw/9pfs/codir.c @@ -29,7 +29,7 @@ int v9fs_co_readdir_r(V9fsPDU *pdu, V9fsFidState *fidp, struct dirent *dent, v9fs_co_run_in_worker( { errno = 0; - err = s->ops->readdir_r(&s->ctx, fidp->fs.dir, dent, result); + err = s->ops->readdir_r(&s->ctx, &fidp->fs, dent, result); if (!*result && errno) { err = -errno; } else { @@ -49,7 +49,7 @@ off_t v9fs_co_telldir(V9fsPDU *pdu, V9fsFidState *fidp) } v9fs_co_run_in_worker( { - err = s->ops->telldir(&s->ctx, fidp->fs.dir); + err = s->ops->telldir(&s->ctx, &fidp->fs); if (err < 0) { err = -errno; } @@ -65,7 +65,7 @@ void v9fs_co_seekdir(V9fsPDU *pdu, V9fsFidState *fidp, off_t offset) } v9fs_co_run_in_worker( { - s->ops->seekdir(&s->ctx, fidp->fs.dir, offset); + s->ops->seekdir(&s->ctx, &fidp->fs, offset); }); } @@ -77,7 +77,7 @@ void v9fs_co_rewinddir(V9fsPDU *pdu, V9fsFidState *fidp) } v9fs_co_run_in_worker( { - s->ops->rewinddir(&s->ctx, fidp->fs.dir); + s->ops->rewinddir(&s->ctx, &fidp->fs); }); } @@ -129,8 +129,8 @@ int v9fs_co_opendir(V9fsPDU *pdu, V9fsFidState *fidp) v9fs_path_read_lock(s); v9fs_co_run_in_worker( { - fidp->fs.dir = s->ops->opendir(&s->ctx, &fidp->path); - if (!fidp->fs.dir) { + err = s->ops->opendir(&s->ctx, &fidp->path, &fidp->fs); + if (err < 0) { err = -errno; } else { err = 0; @@ -146,7 +146,7 @@ int v9fs_co_opendir(V9fsPDU *pdu, V9fsFidState *fidp) return err; } -int v9fs_co_closedir(V9fsPDU *pdu, DIR *dir) +int v9fs_co_closedir(V9fsPDU *pdu, V9fsFidOpenState *fs) { int err; V9fsState *s = pdu->s; @@ -156,7 +156,7 @@ int v9fs_co_closedir(V9fsPDU *pdu, DIR *dir) } v9fs_co_run_in_worker( { - err = s->ops->closedir(&s->ctx, dir); + err = s->ops->closedir(&s->ctx, fs); if (err < 0) { err = -errno; } diff --git a/hw/9pfs/cofile.c b/hw/9pfs/cofile.c index 692811e5ab..586b0382f6 100644 --- a/hw/9pfs/cofile.c +++ b/hw/9pfs/cofile.c @@ -61,7 +61,7 @@ int v9fs_co_lstat(V9fsPDU *pdu, V9fsPath *path, struct stat *stbuf) return err; } -int v9fs_co_fstat(V9fsPDU *pdu, int fd, struct stat *stbuf) +int v9fs_co_fstat(V9fsPDU *pdu, V9fsFidState *fidp, struct stat *stbuf) { int err; V9fsState *s = pdu->s; @@ -71,7 +71,7 @@ int v9fs_co_fstat(V9fsPDU *pdu, int fd, struct stat *stbuf) } v9fs_co_run_in_worker( { - err = s->ops->fstat(&s->ctx, fd, stbuf); + err = s->ops->fstat(&s->ctx, &fidp->fs, stbuf); if (err < 0) { err = -errno; } @@ -90,8 +90,8 @@ int v9fs_co_open(V9fsPDU *pdu, V9fsFidState *fidp, int flags) v9fs_path_read_lock(s); v9fs_co_run_in_worker( { - fidp->fs.fd = s->ops->open(&s->ctx, &fidp->path, flags); - if (fidp->fs.fd == -1) { + err = s->ops->open(&s->ctx, &fidp->path, flags, &fidp->fs); + if (err == -1) { err = -errno; } else { err = 0; @@ -130,9 +130,9 @@ int v9fs_co_open2(V9fsPDU *pdu, V9fsFidState *fidp, V9fsString *name, gid_t gid, v9fs_path_read_lock(s); v9fs_co_run_in_worker( { - fidp->fs.fd = s->ops->open2(&s->ctx, &fidp->path, - name->data, flags, &cred); - if (fidp->fs.fd == -1) { + err = s->ops->open2(&s->ctx, &fidp->path, + name->data, flags, &cred, &fidp->fs); + if (err < 0) { err = -errno; } else { v9fs_path_init(&path); @@ -141,12 +141,12 @@ int v9fs_co_open2(V9fsPDU *pdu, V9fsFidState *fidp, V9fsString *name, gid_t gid, err = s->ops->lstat(&s->ctx, &path, stbuf); if (err < 0) { err = -errno; - s->ops->close(&s->ctx, fidp->fs.fd); + s->ops->close(&s->ctx, &fidp->fs); } else { v9fs_path_copy(&fidp->path, &path); } } else { - s->ops->close(&s->ctx, fidp->fs.fd); + s->ops->close(&s->ctx, &fidp->fs); } v9fs_path_free(&path); } @@ -161,7 +161,7 @@ int v9fs_co_open2(V9fsPDU *pdu, V9fsFidState *fidp, V9fsString *name, gid_t gid, return err; } -int v9fs_co_close(V9fsPDU *pdu, int fd) +int v9fs_co_close(V9fsPDU *pdu, V9fsFidOpenState *fs) { int err; V9fsState *s = pdu->s; @@ -171,7 +171,7 @@ int v9fs_co_close(V9fsPDU *pdu, int fd) } v9fs_co_run_in_worker( { - err = s->ops->close(&s->ctx, fd); + err = s->ops->close(&s->ctx, fs); if (err < 0) { err = -errno; } @@ -184,16 +184,15 @@ int v9fs_co_close(V9fsPDU *pdu, int fd) int v9fs_co_fsync(V9fsPDU *pdu, V9fsFidState *fidp, int datasync) { - int fd, err; + int err; V9fsState *s = pdu->s; if (v9fs_request_cancelled(pdu)) { return -EINTR; } - fd = fidp->fs.fd; v9fs_co_run_in_worker( { - err = s->ops->fsync(&s->ctx, fd, datasync); + err = s->ops->fsync(&s->ctx, &fidp->fs, datasync); if (err < 0) { err = -errno; } @@ -226,16 +225,15 @@ int v9fs_co_link(V9fsPDU *pdu, V9fsFidState *oldfid, int v9fs_co_pwritev(V9fsPDU *pdu, V9fsFidState *fidp, struct iovec *iov, int iovcnt, int64_t offset) { - int fd, err; + int err; V9fsState *s = pdu->s; if (v9fs_request_cancelled(pdu)) { return -EINTR; } - fd = fidp->fs.fd; v9fs_co_run_in_worker( { - err = s->ops->pwritev(&s->ctx, fd, iov, iovcnt, offset); + err = s->ops->pwritev(&s->ctx, &fidp->fs, iov, iovcnt, offset); if (err < 0) { err = -errno; } @@ -246,16 +244,15 @@ int v9fs_co_pwritev(V9fsPDU *pdu, V9fsFidState *fidp, int v9fs_co_preadv(V9fsPDU *pdu, V9fsFidState *fidp, struct iovec *iov, int iovcnt, int64_t offset) { - int fd, err; + int err; V9fsState *s = pdu->s; if (v9fs_request_cancelled(pdu)) { return -EINTR; } - fd = fidp->fs.fd; v9fs_co_run_in_worker( { - err = s->ops->preadv(&s->ctx, fd, iov, iovcnt, offset); + err = s->ops->preadv(&s->ctx, &fidp->fs, iov, iovcnt, offset); if (err < 0) { err = -errno; } diff --git a/hw/9pfs/virtio-9p-coth.h b/hw/9pfs/virtio-9p-coth.h index ca96b9cf2f..c4b74b0221 100644 --- a/hw/9pfs/virtio-9p-coth.h +++ b/hw/9pfs/virtio-9p-coth.h @@ -80,7 +80,7 @@ extern int v9fs_co_rename(V9fsPDU *, V9fsPath *, V9fsPath *); extern int v9fs_co_unlinkat(V9fsPDU *, V9fsPath *, V9fsString *, int flags); extern int v9fs_co_renameat(V9fsPDU *, V9fsPath *, V9fsString *, V9fsPath *, V9fsString *); -extern int v9fs_co_fstat(V9fsPDU *, int, struct stat *); +extern int v9fs_co_fstat(V9fsPDU *, V9fsFidState *, struct stat *); extern int v9fs_co_opendir(V9fsPDU *, V9fsFidState *); extern int v9fs_co_open(V9fsPDU *, V9fsFidState *, int); extern int v9fs_co_open2(V9fsPDU *, V9fsFidState *, V9fsString *, @@ -88,8 +88,8 @@ extern int v9fs_co_open2(V9fsPDU *, V9fsFidState *, V9fsString *, extern int v9fs_co_lsetxattr(V9fsPDU *, V9fsPath *, V9fsString *, void *, size_t, int); extern int v9fs_co_lremovexattr(V9fsPDU *, V9fsPath *, V9fsString *); -extern int v9fs_co_closedir(V9fsPDU *, DIR *); -extern int v9fs_co_close(V9fsPDU *, int); +extern int v9fs_co_closedir(V9fsPDU *, V9fsFidOpenState *); +extern int v9fs_co_close(V9fsPDU *, V9fsFidOpenState *); extern int v9fs_co_fsync(V9fsPDU *, V9fsFidState *, int); extern int v9fs_co_symlink(V9fsPDU *, V9fsFidState *, V9fsString *, const char *, gid_t, struct stat *); diff --git a/hw/9pfs/virtio-9p-handle.c b/hw/9pfs/virtio-9p-handle.c index 98809f1642..c38e0e7863 100644 --- a/hw/9pfs/virtio-9p-handle.c +++ b/hw/9pfs/virtio-9p-handle.c @@ -133,81 +133,91 @@ static ssize_t handle_readlink(FsContext *fs_ctx, V9fsPath *fs_path, return ret; } -static int handle_close(FsContext *ctx, int fd) +static int handle_close(FsContext *ctx, V9fsFidOpenState *fs) { - return close(fd); + return close(fs->fd); } -static int handle_closedir(FsContext *ctx, DIR *dir) +static int handle_closedir(FsContext *ctx, V9fsFidOpenState *fs) { - return closedir(dir); + return closedir(fs->dir); } -static int handle_open(FsContext *ctx, V9fsPath *fs_path, int flags) +static int handle_open(FsContext *ctx, V9fsPath *fs_path, + int flags, V9fsFidOpenState *fs) { struct handle_data *data = (struct handle_data *)ctx->private; - return open_by_handle(data->mountfd, fs_path->data, flags); + fs->fd = open_by_handle(data->mountfd, fs_path->data, flags); + return fs->fd; } -static DIR *handle_opendir(FsContext *ctx, V9fsPath *fs_path) +static int handle_opendir(FsContext *ctx, + V9fsPath *fs_path, V9fsFidOpenState *fs) { - int fd; - fd = handle_open(ctx, fs_path, O_DIRECTORY); - if (fd < 0) { - return NULL; + int ret; + ret = handle_open(ctx, fs_path, O_DIRECTORY, fs); + if (ret < 0) { + return -1; } - return fdopendir(fd); + fs->dir = fdopendir(ret); + if (!fs->dir) { + return -1; + } + return 0; } -static void handle_rewinddir(FsContext *ctx, DIR *dir) +static void handle_rewinddir(FsContext *ctx, V9fsFidOpenState *fs) { - return rewinddir(dir); + return rewinddir(fs->dir); } -static off_t handle_telldir(FsContext *ctx, DIR *dir) +static off_t handle_telldir(FsContext *ctx, V9fsFidOpenState *fs) { - return telldir(dir); + return telldir(fs->dir); } -static int handle_readdir_r(FsContext *ctx, DIR *dir, struct dirent *entry, +static int handle_readdir_r(FsContext *ctx, V9fsFidOpenState *fs, + struct dirent *entry, struct dirent **result) { - return readdir_r(dir, entry, result); + return readdir_r(fs->dir, entry, result); } -static void handle_seekdir(FsContext *ctx, DIR *dir, off_t off) +static void handle_seekdir(FsContext *ctx, V9fsFidOpenState *fs, off_t off) { - return seekdir(dir, off); + return seekdir(fs->dir, off); } -static ssize_t handle_preadv(FsContext *ctx, int fd, const struct iovec *iov, +static ssize_t handle_preadv(FsContext *ctx, V9fsFidOpenState *fs, + const struct iovec *iov, int iovcnt, off_t offset) { #ifdef CONFIG_PREADV - return preadv(fd, iov, iovcnt, offset); + return preadv(fs->fd, iov, iovcnt, offset); #else - int err = lseek(fd, offset, SEEK_SET); + int err = lseek(fs->fd, offset, SEEK_SET); if (err == -1) { return err; } else { - return readv(fd, iov, iovcnt); + return readv(fs->fd, iov, iovcnt); } #endif } -static ssize_t handle_pwritev(FsContext *ctx, int fd, const struct iovec *iov, +static ssize_t handle_pwritev(FsContext *ctx, V9fsFidOpenState *fs, + const struct iovec *iov, int iovcnt, off_t offset) { ssize_t ret; #ifdef CONFIG_PREADV - ret = pwritev(fd, iov, iovcnt, offset); + ret = pwritev(fs->fd, iov, iovcnt, offset); #else - int err = lseek(fd, offset, SEEK_SET); + int err = lseek(fs->fd, offset, SEEK_SET); if (err == -1) { return err; } else { - ret = writev(fd, iov, iovcnt); + ret = writev(fs->fd, iov, iovcnt); } #endif #ifdef CONFIG_SYNC_FILE_RANGE @@ -217,7 +227,7 @@ static ssize_t handle_pwritev(FsContext *ctx, int fd, const struct iovec *iov, * We want to ensure that we don't leave dirty pages in the cache * after write when writeout=immediate is sepcified. */ - sync_file_range(fd, offset, ret, + sync_file_range(fs->fd, offset, ret, SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE); } #endif @@ -274,13 +284,14 @@ static int handle_mkdir(FsContext *fs_ctx, V9fsPath *dir_path, return ret; } -static int handle_fstat(FsContext *fs_ctx, int fd, struct stat *stbuf) +static int handle_fstat(FsContext *fs_ctx, V9fsFidOpenState *fs, + struct stat *stbuf) { - return fstat(fd, stbuf); + return fstat(fs->fd, stbuf); } static int handle_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name, - int flags, FsCred *credp) + int flags, FsCred *credp, V9fsFidOpenState *fs) { int ret; int dirfd, fd; @@ -296,6 +307,8 @@ static int handle_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name, if (ret < 0) { close(fd); fd = ret; + } else { + fs->fd = fd; } } close(dirfd); @@ -411,12 +424,12 @@ static int handle_remove(FsContext *ctx, const char *path) return -1; } -static int handle_fsync(FsContext *ctx, int fd, int datasync) +static int handle_fsync(FsContext *ctx, V9fsFidOpenState *fs, int datasync) { if (datasync) { - return qemu_fdatasync(fd); + return qemu_fdatasync(fs->fd); } else { - return fsync(fd); + return fsync(fs->fd); } } @@ -575,7 +588,8 @@ static int handle_unlinkat(FsContext *ctx, V9fsPath *dir, static int handle_ioc_getversion(FsContext *ctx, V9fsPath *path, mode_t st_mode, uint64_t *st_gen) { - int err, fd; + int err; + V9fsFidOpenState fid_open; /* * Do not try to open special files like device nodes, fifos etc @@ -584,12 +598,12 @@ static int handle_ioc_getversion(FsContext *ctx, V9fsPath *path, if (!S_ISREG(st_mode) && !S_ISDIR(st_mode)) { return 0; } - fd = handle_open(ctx, path, O_RDONLY); - if (fd < 0) { - return fd; + err = handle_open(ctx, path, O_RDONLY, &fid_open); + if (err < 0) { + return err; } - err = ioctl(fd, FS_IOC_GETVERSION, st_gen); - handle_close(ctx, fd); + err = ioctl(fid_open.fd, FS_IOC_GETVERSION, st_gen); + handle_close(ctx, &fid_open); return err; } diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c index b611681c0f..782dc0ab21 100644 --- a/hw/9pfs/virtio-9p-local.c +++ b/hw/9pfs/virtio-9p-local.c @@ -156,81 +156,91 @@ static ssize_t local_readlink(FsContext *fs_ctx, V9fsPath *fs_path, return tsize; } -static int local_close(FsContext *ctx, int fd) +static int local_close(FsContext *ctx, V9fsFidOpenState *fs) { - return close(fd); + return close(fs->fd); } -static int local_closedir(FsContext *ctx, DIR *dir) +static int local_closedir(FsContext *ctx, V9fsFidOpenState *fs) { - return closedir(dir); + return closedir(fs->dir); } -static int local_open(FsContext *ctx, V9fsPath *fs_path, int flags) +static int local_open(FsContext *ctx, V9fsPath *fs_path, + int flags, V9fsFidOpenState *fs) { char buffer[PATH_MAX]; char *path = fs_path->data; - return open(rpath(ctx, path, buffer), flags); + fs->fd = open(rpath(ctx, path, buffer), flags); + return fs->fd; } -static DIR *local_opendir(FsContext *ctx, V9fsPath *fs_path) +static int local_opendir(FsContext *ctx, + V9fsPath *fs_path, V9fsFidOpenState *fs) { char buffer[PATH_MAX]; char *path = fs_path->data; - return opendir(rpath(ctx, path, buffer)); + fs->dir = opendir(rpath(ctx, path, buffer)); + if (!fs->dir) { + return -1; + } + return 0; } -static void local_rewinddir(FsContext *ctx, DIR *dir) +static void local_rewinddir(FsContext *ctx, V9fsFidOpenState *fs) { - return rewinddir(dir); + return rewinddir(fs->dir); } -static off_t local_telldir(FsContext *ctx, DIR *dir) +static off_t local_telldir(FsContext *ctx, V9fsFidOpenState *fs) { - return telldir(dir); + return telldir(fs->dir); } -static int local_readdir_r(FsContext *ctx, DIR *dir, struct dirent *entry, +static int local_readdir_r(FsContext *ctx, V9fsFidOpenState *fs, + struct dirent *entry, struct dirent **result) { - return readdir_r(dir, entry, result); + return readdir_r(fs->dir, entry, result); } -static void local_seekdir(FsContext *ctx, DIR *dir, off_t off) +static void local_seekdir(FsContext *ctx, V9fsFidOpenState *fs, off_t off) { - return seekdir(dir, off); + return seekdir(fs->dir, off); } -static ssize_t local_preadv(FsContext *ctx, int fd, const struct iovec *iov, +static ssize_t local_preadv(FsContext *ctx, V9fsFidOpenState *fs, + const struct iovec *iov, int iovcnt, off_t offset) { #ifdef CONFIG_PREADV - return preadv(fd, iov, iovcnt, offset); + return preadv(fs->fd, iov, iovcnt, offset); #else - int err = lseek(fd, offset, SEEK_SET); + int err = lseek(fs->fd, offset, SEEK_SET); if (err == -1) { return err; } else { - return readv(fd, iov, iovcnt); + return readv(fs->fd, iov, iovcnt); } #endif } -static ssize_t local_pwritev(FsContext *ctx, int fd, const struct iovec *iov, +static ssize_t local_pwritev(FsContext *ctx, V9fsFidOpenState *fs, + const struct iovec *iov, int iovcnt, off_t offset) { ssize_t ret ; #ifdef CONFIG_PREADV - ret = pwritev(fd, iov, iovcnt, offset); + ret = pwritev(fs->fd, iov, iovcnt, offset); #else - int err = lseek(fd, offset, SEEK_SET); + int err = lseek(fs->fd, offset, SEEK_SET); if (err == -1) { return err; } else { - ret = writev(fd, iov, iovcnt); + ret = writev(fs->fd, iov, iovcnt); } #endif #ifdef CONFIG_SYNC_FILE_RANGE @@ -240,7 +250,7 @@ static ssize_t local_pwritev(FsContext *ctx, int fd, const struct iovec *iov, * We want to ensure that we don't leave dirty pages in the cache * after write when writeout=immediate is sepcified. */ - sync_file_range(fd, offset, ret, + sync_file_range(fs->fd, offset, ret, SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE); } #endif @@ -356,10 +366,11 @@ out: return err; } -static int local_fstat(FsContext *fs_ctx, int fd, struct stat *stbuf) +static int local_fstat(FsContext *fs_ctx, + V9fsFidOpenState *fs, struct stat *stbuf) { int err; - err = fstat(fd, stbuf); + err = fstat(fs->fd, stbuf); if (err) { return err; } @@ -370,16 +381,20 @@ static int local_fstat(FsContext *fs_ctx, int fd, struct stat *stbuf) mode_t tmp_mode; dev_t tmp_dev; - if (fgetxattr(fd, "user.virtfs.uid", &tmp_uid, sizeof(uid_t)) > 0) { + if (fgetxattr(fs->fd, "user.virtfs.uid", + &tmp_uid, sizeof(uid_t)) > 0) { stbuf->st_uid = tmp_uid; } - if (fgetxattr(fd, "user.virtfs.gid", &tmp_gid, sizeof(gid_t)) > 0) { + if (fgetxattr(fs->fd, "user.virtfs.gid", + &tmp_gid, sizeof(gid_t)) > 0) { stbuf->st_gid = tmp_gid; } - if (fgetxattr(fd, "user.virtfs.mode", &tmp_mode, sizeof(mode_t)) > 0) { + if (fgetxattr(fs->fd, "user.virtfs.mode", + &tmp_mode, sizeof(mode_t)) > 0) { stbuf->st_mode = tmp_mode; } - if (fgetxattr(fd, "user.virtfs.rdev", &tmp_dev, sizeof(dev_t)) > 0) { + if (fgetxattr(fs->fd, "user.virtfs.rdev", + &tmp_dev, sizeof(dev_t)) > 0) { stbuf->st_rdev = tmp_dev; } } @@ -387,7 +402,7 @@ static int local_fstat(FsContext *fs_ctx, int fd, struct stat *stbuf) } static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name, - int flags, FsCred *credp) + int flags, FsCred *credp, V9fsFidOpenState *fs) { char *path; int fd = -1; @@ -428,6 +443,7 @@ static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name, } } err = fd; + fs->fd = fd; goto out; err_end: @@ -577,12 +593,12 @@ static int local_remove(FsContext *ctx, const char *path) return remove(rpath(ctx, path, buffer)); } -static int local_fsync(FsContext *ctx, int fd, int datasync) +static int local_fsync(FsContext *ctx, V9fsFidOpenState *fs, int datasync) { if (datasync) { - return qemu_fdatasync(fd); + return qemu_fdatasync(fs->fd); } else { - return fsync(fd); + return fsync(fs->fd); } } @@ -677,7 +693,9 @@ static int local_unlinkat(FsContext *ctx, V9fsPath *dir, static int local_ioc_getversion(FsContext *ctx, V9fsPath *path, mode_t st_mode, uint64_t *st_gen) { - int err, fd; + int err; + V9fsFidOpenState fid_open; + /* * Do not try to open special files like device nodes, fifos etc * We can get fd for regular files and directories only @@ -685,12 +703,12 @@ static int local_ioc_getversion(FsContext *ctx, V9fsPath *path, if (!S_ISREG(st_mode) && !S_ISDIR(st_mode)) { return 0; } - fd = local_open(ctx, path, O_RDONLY); - if (fd < 0) { - return fd; + err = local_open(ctx, path, O_RDONLY, &fid_open); + if (err < 0) { + return err; } - err = ioctl(fd, FS_IOC_GETVERSION, st_gen); - local_close(ctx, fd); + err = ioctl(fid_open.fd, FS_IOC_GETVERSION, st_gen); + local_close(ctx, &fid_open); return err; } diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c index e7618d72ba..0777ece816 100644 --- a/hw/9pfs/virtio-9p.c +++ b/hw/9pfs/virtio-9p.c @@ -455,11 +455,11 @@ static int free_fid(V9fsPDU *pdu, V9fsFidState *fidp) if (fidp->fid_type == P9_FID_FILE) { /* If we reclaimed the fd no need to close */ if (fidp->fs.fd != -1) { - retval = v9fs_co_close(pdu, fidp->fs.fd); + retval = v9fs_co_close(pdu, &fidp->fs); } } else if (fidp->fid_type == P9_FID_DIR) { if (fidp->fs.dir != NULL) { - retval = v9fs_co_closedir(pdu, fidp->fs.dir); + retval = v9fs_co_closedir(pdu, &fidp->fs); } } else if (fidp->fid_type == P9_FID_XATTR) { retval = v9fs_xattr_fid_clunk(pdu, fidp); @@ -567,9 +567,9 @@ void v9fs_reclaim_fd(V9fsPDU *pdu) f = reclaim_list; reclaim_list = f->rclm_lst; if (f->fid_type == P9_FID_FILE) { - v9fs_co_close(pdu, f->fs_reclaim.fd); + v9fs_co_close(pdu, &f->fs_reclaim); } else if (f->fid_type == P9_FID_DIR) { - v9fs_co_closedir(pdu, f->fs_reclaim.dir); + v9fs_co_closedir(pdu, &f->fs_reclaim); } f->rclm_lst = NULL; /* @@ -3009,7 +3009,7 @@ static void v9fs_lock(void *opaque) err = -ENOENT; goto out_nofid; } - err = v9fs_co_fstat(pdu, fidp->fs.fd, &stbuf); + err = v9fs_co_fstat(pdu, fidp, &stbuf); if (err < 0) { goto out; } @@ -3052,7 +3052,7 @@ static void v9fs_getlock(void *opaque) err = -ENOENT; goto out_nofid; } - err = v9fs_co_fstat(pdu, fidp->fs.fd, &stbuf); + err = v9fs_co_fstat(pdu, fidp, &stbuf); if (err < 0) { goto out; } diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h index 802f5809d1..6273b8589a 100644 --- a/hw/9pfs/virtio-9p.h +++ b/hw/9pfs/virtio-9p.h @@ -204,20 +204,23 @@ typedef struct V9fsXattr int flags; } V9fsXattr; +/* + * Filled by fs driver on open and other + * calls. + */ +union V9fsFidOpenState { + int fd; + DIR *dir; + V9fsXattr xattr; +}; + struct V9fsFidState { int fid_type; int32_t fid; V9fsPath path; - union { - int fd; - DIR *dir; - V9fsXattr xattr; - } fs; - union { - int fd; - DIR *dir; - } fs_reclaim; + V9fsFidOpenState fs; + V9fsFidOpenState fs_reclaim; int flags; int open_flags; uid_t uid; |