diff options
author | Anthony Liguori <aliguori@us.ibm.com> | 2011-08-25 07:48:15 -0500 |
---|---|---|
committer | Anthony Liguori <aliguori@us.ibm.com> | 2011-08-25 07:48:15 -0500 |
commit | 444dc48298c480e42e15a8fe676be737d8a6b2a1 (patch) | |
tree | bc76c5afaa746c8c27d0457e2035fe38ee45fb6c /hw | |
parent | 5b15f27516ce3249c80bd2e0458d8d61f20da415 (diff) | |
parent | 5f524c1ebcc5e0dec0de8940d34f9adb3c7887a1 (diff) |
Merge remote-tracking branch 'aneesh/for-upstream-2' into staging
Diffstat (limited to 'hw')
-rw-r--r-- | hw/9pfs/codir.c | 40 | ||||
-rw-r--r-- | hw/9pfs/cofile.c | 131 | ||||
-rw-r--r-- | hw/9pfs/cofs.c | 20 | ||||
-rw-r--r-- | hw/9pfs/coxattr.c | 34 | ||||
-rw-r--r-- | hw/9pfs/virtio-9p-coth.h | 21 | ||||
-rw-r--r-- | hw/9pfs/virtio-9p-local.c | 7 | ||||
-rw-r--r-- | hw/9pfs/virtio-9p.c | 1847 | ||||
-rw-r--r-- | hw/9pfs/virtio-9p.h | 79 |
8 files changed, 850 insertions, 1329 deletions
diff --git a/hw/9pfs/codir.c b/hw/9pfs/codir.c index 28f2ad7320..3a257b9027 100644 --- a/hw/9pfs/codir.c +++ b/hw/9pfs/codir.c @@ -17,16 +17,16 @@ #include "qemu-coroutine.h" #include "virtio-9p-coth.h" -int v9fs_co_readdir(V9fsState *s, V9fsFidState *fidp, struct dirent **dent) +int v9fs_co_readdir_r(V9fsState *s, V9fsFidState *fidp, struct dirent *dent, + struct dirent **result) { int err; v9fs_co_run_in_worker( { errno = 0; - /*FIXME!! need to switch to readdir_r */ - *dent = s->ops->readdir(&s->ctx, fidp->fs.dir); - if (!*dent && errno) { + err = s->ops->readdir_r(&s->ctx, fidp->fs.dir, dent, result); + if (!*result && errno) { err = -errno; } else { err = 0; @@ -83,3 +83,35 @@ int v9fs_co_mkdir(V9fsState *s, char *name, mode_t mode, uid_t uid, gid_t gid) }); return err; } + +int v9fs_co_opendir(V9fsState *s, V9fsFidState *fidp) +{ + int err; + + v9fs_co_run_in_worker( + { + fidp->fs.dir = s->ops->opendir(&s->ctx, fidp->path.data); + if (!fidp->fs.dir) { + err = -errno; + } else { + err = 0; + } + }); + return err; +} + +int v9fs_co_closedir(V9fsState *s, V9fsFidState *fidp) +{ + int err; + DIR *dir; + + dir = fidp->fs.dir; + v9fs_co_run_in_worker( + { + err = s->ops->closedir(&s->ctx, dir); + if (err < 0) { + err = -errno; + } + }); + return err; +} diff --git a/hw/9pfs/cofile.c b/hw/9pfs/cofile.c index a4c0ae75cc..e388146422 100644 --- a/hw/9pfs/cofile.c +++ b/hw/9pfs/cofile.c @@ -30,3 +30,134 @@ int v9fs_co_lstat(V9fsState *s, V9fsString *path, struct stat *stbuf) }); return err; } + +int v9fs_co_fstat(V9fsState *s, int fd, struct stat *stbuf) +{ + int err; + + v9fs_co_run_in_worker( + { + err = s->ops->fstat(&s->ctx, fd, stbuf); + if (err < 0) { + err = -errno; + } + }); + return err; +} + +int v9fs_co_open(V9fsState *s, V9fsFidState *fidp, int flags) +{ + int err; + + v9fs_co_run_in_worker( + { + fidp->fs.fd = s->ops->open(&s->ctx, fidp->path.data, flags); + if (fidp->fs.fd == -1) { + err = -errno; + } else { + err = 0; + } + }); + return err; +} + +int v9fs_co_open2(V9fsState *s, V9fsFidState *fidp, char *fullname, gid_t gid, + int flags, int mode) +{ + int err; + FsCred cred; + + cred_init(&cred); + cred.fc_mode = mode & 07777; + cred.fc_uid = fidp->uid; + cred.fc_gid = gid; + v9fs_co_run_in_worker( + { + fidp->fs.fd = s->ops->open2(&s->ctx, fullname, flags, &cred); + err = 0; + if (fidp->fs.fd == -1) { + err = -errno; + } + }); + return err; +} + +int v9fs_co_close(V9fsState *s, V9fsFidState *fidp) +{ + int fd; + int err; + + fd = fidp->fs.fd; + v9fs_co_run_in_worker( + { + err = s->ops->close(&s->ctx, fd); + if (err < 0) { + err = -errno; + } + }); + return err; +} + +int v9fs_co_fsync(V9fsState *s, V9fsFidState *fidp, int datasync) +{ + int fd; + int err; + + fd = fidp->fs.fd; + v9fs_co_run_in_worker( + { + err = s->ops->fsync(&s->ctx, fd, datasync); + if (err < 0) { + err = -errno; + } + }); + return err; +} + +int v9fs_co_link(V9fsState *s, V9fsString *oldpath, V9fsString *newpath) +{ + int err; + + v9fs_co_run_in_worker( + { + err = s->ops->link(&s->ctx, oldpath->data, newpath->data); + if (err < 0) { + err = -errno; + } + }); + return err; +} + +int v9fs_co_pwritev(V9fsState *s, V9fsFidState *fidp, + struct iovec *iov, int iovcnt, int64_t offset) +{ + int fd; + int err; + + fd = fidp->fs.fd; + v9fs_co_run_in_worker( + { + err = s->ops->pwritev(&s->ctx, fd, iov, iovcnt, offset); + if (err < 0) { + err = -errno; + } + }); + return err; +} + +int v9fs_co_preadv(V9fsState *s, V9fsFidState *fidp, + struct iovec *iov, int iovcnt, int64_t offset) +{ + int fd; + int err; + + fd = fidp->fs.fd; + v9fs_co_run_in_worker( + { + err = s->ops->preadv(&s->ctx, fd, iov, iovcnt, offset); + if (err < 0) { + err = -errno; + } + }); + return err; +} diff --git a/hw/9pfs/cofs.c b/hw/9pfs/cofs.c index 1f10632540..a78fccbe23 100644 --- a/hw/9pfs/cofs.c +++ b/hw/9pfs/cofs.c @@ -169,3 +169,23 @@ int v9fs_co_rename(V9fsState *s, V9fsString *oldpath, V9fsString *newpath) }); return err; } + +int v9fs_co_symlink(V9fsState *s, V9fsFidState *fidp, + const char *oldpath, const char *newpath, gid_t gid) +{ + int err; + FsCred cred; + + cred_init(&cred); + cred.fc_uid = fidp->uid; + cred.fc_gid = gid; + cred.fc_mode = 0777; + v9fs_co_run_in_worker( + { + err = s->ops->symlink(&s->ctx, oldpath, newpath, &cred); + if (err < 0) { + err = -errno; + } + }); + return err; +} diff --git a/hw/9pfs/coxattr.c b/hw/9pfs/coxattr.c index 2fba2c98c2..a289389e49 100644 --- a/hw/9pfs/coxattr.c +++ b/hw/9pfs/coxattr.c @@ -48,3 +48,37 @@ int v9fs_co_lgetxattr(V9fsState *s, V9fsString *path, }); return err; } + +int v9fs_co_lsetxattr(V9fsState *s, V9fsString *path, + V9fsString *xattr_name, void *value, + size_t size, int flags) +{ + int err; + + v9fs_co_run_in_worker( + { + err = s->ops->lsetxattr(&s->ctx, path->data, + xattr_name->data, value, + size, flags); + if (err < 0) { + err = -errno; + } + }); + return err; +} + +int v9fs_co_lremovexattr(V9fsState *s, V9fsString *path, + V9fsString *xattr_name) +{ + int err; + + v9fs_co_run_in_worker( + { + err = s->ops->lremovexattr(&s->ctx, path->data, + xattr_name->data); + if (err < 0) { + err = -errno; + } + }); + return err; +} diff --git a/hw/9pfs/virtio-9p-coth.h b/hw/9pfs/virtio-9p-coth.h index 11272d3357..48defb72ff 100644 --- a/hw/9pfs/virtio-9p-coth.h +++ b/hw/9pfs/virtio-9p-coth.h @@ -57,8 +57,8 @@ typedef struct V9fsThPool { extern void co_run_in_worker_bh(void *); extern int v9fs_init_worker_threads(void); extern int v9fs_co_readlink(V9fsState *, V9fsString *, V9fsString *); -extern int v9fs_co_readdir(V9fsState *, V9fsFidState *, - struct dirent **); +extern int v9fs_co_readdir_r(V9fsState *, V9fsFidState *, + struct dirent *, struct dirent **result); extern off_t v9fs_co_telldir(V9fsState *, V9fsFidState *); extern void v9fs_co_seekdir(V9fsState *, V9fsFidState *, off_t); extern void v9fs_co_rewinddir(V9fsState *, V9fsFidState *); @@ -76,4 +76,21 @@ extern int v9fs_co_mknod(V9fsState *, V9fsString *, uid_t, extern int v9fs_co_mkdir(V9fsState *, char *, mode_t, uid_t, gid_t); extern int v9fs_co_remove(V9fsState *, V9fsString *); extern int v9fs_co_rename(V9fsState *, V9fsString *, V9fsString *); +extern int v9fs_co_fstat(V9fsState *, int, struct stat *); +extern int v9fs_co_opendir(V9fsState *, V9fsFidState *); +extern int v9fs_co_open(V9fsState *, V9fsFidState *, int); +extern int v9fs_co_open2(V9fsState *, V9fsFidState *, char *, gid_t, int, int); +extern int v9fs_co_lsetxattr(V9fsState *, V9fsString *, V9fsString *, + void *, size_t, int); +extern int v9fs_co_lremovexattr(V9fsState *, V9fsString *, V9fsString *); +extern int v9fs_co_closedir(V9fsState *, V9fsFidState *); +extern int v9fs_co_close(V9fsState *, V9fsFidState *); +extern int v9fs_co_fsync(V9fsState *, V9fsFidState *, int); +extern int v9fs_co_symlink(V9fsState *, V9fsFidState *, const char *, + const char *, gid_t); +extern int v9fs_co_link(V9fsState *, V9fsString *, V9fsString *); +extern int v9fs_co_pwritev(V9fsState *, V9fsFidState *, + struct iovec *, int, int64_t); +extern int v9fs_co_preadv(V9fsState *, V9fsFidState *, + struct iovec *, int, int64_t); #endif diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c index 77904c37bd..61cbf8db14 100644 --- a/hw/9pfs/virtio-9p-local.c +++ b/hw/9pfs/virtio-9p-local.c @@ -165,9 +165,10 @@ static off_t local_telldir(FsContext *ctx, DIR *dir) return telldir(dir); } -static struct dirent *local_readdir(FsContext *ctx, DIR *dir) +static int local_readdir_r(FsContext *ctx, DIR *dir, struct dirent *entry, + struct dirent **result) { - return readdir(dir); + return readdir_r(dir, entry, result); } static void local_seekdir(FsContext *ctx, DIR *dir, off_t off) @@ -532,7 +533,7 @@ FileOperations local_ops = { .opendir = local_opendir, .rewinddir = local_rewinddir, .telldir = local_telldir, - .readdir = local_readdir, + .readdir_r = local_readdir_r, .seekdir = local_seekdir, .preadv = local_preadv, .pwritev = local_pwritev, diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c index eb33636565..ad70768dce 100644 --- a/hw/9pfs/virtio-9p.c +++ b/hw/9pfs/virtio-9p.c @@ -77,160 +77,6 @@ void cred_init(FsCred *credp) credp->fc_rdev = -1; } -static int v9fs_do_lstat(V9fsState *s, V9fsString *path, struct stat *stbuf) -{ - return s->ops->lstat(&s->ctx, path->data, stbuf); -} - -static int v9fs_do_close(V9fsState *s, int fd) -{ - return s->ops->close(&s->ctx, fd); -} - -static int v9fs_do_closedir(V9fsState *s, DIR *dir) -{ - return s->ops->closedir(&s->ctx, dir); -} - -static int v9fs_do_open(V9fsState *s, V9fsString *path, int flags) -{ - return s->ops->open(&s->ctx, path->data, flags); -} - -static DIR *v9fs_do_opendir(V9fsState *s, V9fsString *path) -{ - return s->ops->opendir(&s->ctx, path->data); -} - -static void v9fs_do_rewinddir(V9fsState *s, DIR *dir) -{ - return s->ops->rewinddir(&s->ctx, dir); -} - -static off_t v9fs_do_telldir(V9fsState *s, DIR *dir) -{ - return s->ops->telldir(&s->ctx, dir); -} - -static void v9fs_do_seekdir(V9fsState *s, DIR *dir, off_t off) -{ - return s->ops->seekdir(&s->ctx, dir, off); -} - -static int v9fs_do_preadv(V9fsState *s, int fd, const struct iovec *iov, - int iovcnt, int64_t offset) -{ - return s->ops->preadv(&s->ctx, fd, iov, iovcnt, offset); -} - -static int v9fs_do_pwritev(V9fsState *s, int fd, const struct iovec *iov, - int iovcnt, int64_t offset) -{ - return s->ops->pwritev(&s->ctx, fd, iov, iovcnt, offset); -} - -static int v9fs_do_chmod(V9fsState *s, V9fsString *path, mode_t mode) -{ - FsCred cred; - cred_init(&cred); - cred.fc_mode = mode; - return s->ops->chmod(&s->ctx, path->data, &cred); -} - -static int v9fs_do_mknod(V9fsState *s, char *name, - mode_t mode, dev_t dev, uid_t uid, gid_t gid) -{ - FsCred cred; - cred_init(&cred); - cred.fc_uid = uid; - cred.fc_gid = gid; - cred.fc_mode = mode; - cred.fc_rdev = dev; - return s->ops->mknod(&s->ctx, name, &cred); -} - -static int v9fs_do_fstat(V9fsState *s, int fd, struct stat *stbuf) -{ - return s->ops->fstat(&s->ctx, fd, stbuf); -} - -static int v9fs_do_open2(V9fsState *s, char *fullname, uid_t uid, gid_t gid, - int flags, int mode) -{ - FsCred cred; - - cred_init(&cred); - cred.fc_uid = uid; - cred.fc_gid = gid; - cred.fc_mode = mode & 07777; - - return s->ops->open2(&s->ctx, fullname, flags, &cred); -} - -static int v9fs_do_symlink(V9fsState *s, V9fsFidState *fidp, - const char *oldpath, const char *newpath, gid_t gid) -{ - FsCred cred; - cred_init(&cred); - cred.fc_uid = fidp->uid; - cred.fc_gid = gid; - cred.fc_mode = 0777; - - return s->ops->symlink(&s->ctx, oldpath, newpath, &cred); -} - -static int v9fs_do_link(V9fsState *s, V9fsString *oldpath, V9fsString *newpath) -{ - return s->ops->link(&s->ctx, oldpath->data, newpath->data); -} - -static int v9fs_do_truncate(V9fsState *s, V9fsString *path, off_t size) -{ - return s->ops->truncate(&s->ctx, path->data, size); -} - -static int v9fs_do_chown(V9fsState *s, V9fsString *path, uid_t uid, gid_t gid) -{ - FsCred cred; - cred_init(&cred); - cred.fc_uid = uid; - cred.fc_gid = gid; - - return s->ops->chown(&s->ctx, path->data, &cred); -} - -static int v9fs_do_utimensat(V9fsState *s, V9fsString *path, - const struct timespec times[2]) -{ - return s->ops->utimensat(&s->ctx, path->data, times); -} - -static int v9fs_do_fsync(V9fsState *s, int fd, int datasync) -{ - return s->ops->fsync(&s->ctx, fd, datasync); -} - -static int v9fs_do_statfs(V9fsState *s, V9fsString *path, struct statfs *stbuf) -{ - return s->ops->statfs(&s->ctx, path->data, stbuf); -} - -static int v9fs_do_lsetxattr(V9fsState *s, V9fsString *path, - V9fsString *xattr_name, - void *value, size_t size, int flags) -{ - return s->ops->lsetxattr(&s->ctx, path->data, - xattr_name->data, value, size, flags); -} - -static int v9fs_do_lremovexattr(V9fsState *s, V9fsString *path, - V9fsString *xattr_name) -{ - return s->ops->lremovexattr(&s->ctx, path->data, - xattr_name->data); -} - - static void v9fs_string_init(V9fsString *str) { str->data = NULL; @@ -437,12 +283,12 @@ static int v9fs_xattr_fid_clunk(V9fsState *s, V9fsFidState *fidp) goto free_out; } if (fidp->fs.xattr.len) { - retval = v9fs_do_lsetxattr(s, &fidp->path, &fidp->fs.xattr.name, + retval = v9fs_co_lsetxattr(s, &fidp->path, &fidp->fs.xattr.name, fidp->fs.xattr.value, fidp->fs.xattr.len, fidp->fs.xattr.flags); } else { - retval = v9fs_do_lremovexattr(s, &fidp->path, &fidp->fs.xattr.name); + retval = v9fs_co_lremovexattr(s, &fidp->path, &fidp->fs.xattr.name); } free_out: v9fs_string_free(&fidp->fs.xattr.name); @@ -472,15 +318,14 @@ static int free_fid(V9fsState *s, int32_t fid) *fidpp = fidp->next; if (fidp->fid_type == P9_FID_FILE) { - v9fs_do_close(s, fidp->fs.fd); + retval = v9fs_co_close(s, fidp); } else if (fidp->fid_type == P9_FID_DIR) { - v9fs_do_closedir(s, fidp->fs.dir); + retval = v9fs_co_closedir(s, fidp); } else if (fidp->fid_type == P9_FID_XATTR) { retval = v9fs_xattr_fid_clunk(s, fidp); } v9fs_string_free(&fidp->path); g_free(fidp); - return retval; } @@ -531,11 +376,10 @@ static int fid_to_qid(V9fsState *s, V9fsFidState *fidp, V9fsQID *qidp) struct stat stbuf; int err; - err = v9fs_do_lstat(s, &fidp->path, &stbuf); - if (err) { + err = v9fs_co_lstat(s, &fidp->path, &stbuf); + if (err < 0) { return err; } - stat_to_qid(&stbuf, qidp); return 0; } @@ -1161,8 +1005,8 @@ static void v9fs_attach(void *opaque) int32_t fid, afid, n_uname; V9fsString uname, aname; V9fsFidState *fidp; - V9fsQID qid; size_t offset = 7; + V9fsQID qid; ssize_t err; pdu_unmarshal(pdu, offset, "ddssd", &fid, &afid, &uname, &aname, &n_uname); @@ -1172,19 +1016,15 @@ static void v9fs_attach(void *opaque) err = -EINVAL; goto out; } - fidp->uid = n_uname; - v9fs_string_sprintf(&fidp->path, "%s", "/"); err = fid_to_qid(s, fidp, &qid); - if (err) { + if (err < 0) { err = -EINVAL; free_fid(s, fid); goto out; } - offset += pdu_marshal(pdu, offset, "Q", &qid); - err = offset; out: complete_pdu(s, pdu, err); @@ -1192,56 +1032,36 @@ out: v9fs_string_free(&aname); } -static void v9fs_stat_post_lstat(V9fsState *s, V9fsStatState *vs, int err) -{ - if (err == -1) { - err = -errno; - goto out; - } - - err = stat_to_v9stat(s, &vs->fidp->path, &vs->stbuf, &vs->v9stat); - if (err) { - goto out; - } - vs->offset += pdu_marshal(vs->pdu, vs->offset, "wS", 0, &vs->v9stat); - err = vs->offset; - -out: - complete_pdu(s, vs->pdu, err); - v9fs_stat_free(&vs->v9stat); - g_free(vs); -} - static void v9fs_stat(void *opaque) { - V9fsPDU *pdu = opaque; - V9fsState *s = pdu->s; int32_t fid; - V9fsStatState *vs; + V9fsStat v9stat; ssize_t err = 0; + size_t offset = 7; + struct stat stbuf; + V9fsFidState *fidp; + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; - vs = g_malloc(sizeof(*vs)); - vs->pdu = pdu; - vs->offset = 7; - - memset(&vs->v9stat, 0, sizeof(vs->v9stat)); - - pdu_unmarshal(vs->pdu, vs->offset, "d", &fid); - - vs->fidp = lookup_fid(s, fid); - if (vs->fidp == NULL) { + pdu_unmarshal(pdu, offset, "d", &fid); + fidp = lookup_fid(s, fid); + if (fidp == NULL) { err = -ENOENT; goto out; } - - err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf); - v9fs_stat_post_lstat(s, vs, err); - return; - + err = v9fs_co_lstat(s, &fidp->path, &stbuf); + if (err < 0) { + goto out; + } + err = stat_to_v9stat(s, &fidp->path, &stbuf, &v9stat); + if (err < 0) { + goto out; + } + offset += pdu_marshal(pdu, offset, "wS", 0, &v9stat); + err = offset; + v9fs_stat_free(&v9stat); out: - complete_pdu(s, vs->pdu, err); - v9fs_stat_free(&vs->v9stat); - g_free(vs); + complete_pdu(s, pdu, err); } static void v9fs_getattr(void *opaque) @@ -1370,171 +1190,101 @@ out: complete_pdu(s, pdu, err); } -static void v9fs_walk_complete(V9fsState *s, V9fsWalkState *vs, int err) -{ - complete_pdu(s, vs->pdu, err); - - if (vs->nwnames && vs->nwnames <= P9_MAXWELEM) { - for (vs->name_idx = 0; vs->name_idx < vs->nwnames; vs->name_idx++) { - v9fs_string_free(&vs->wnames[vs->name_idx]); - } - - g_free(vs->wnames); - g_free(vs->qids); - } -} - -static void v9fs_walk_marshal(V9fsWalkState *vs) +static int v9fs_walk_marshal(V9fsPDU *pdu, uint16_t nwnames, V9fsQID *qids) { int i; - vs->offset = 7; - vs->offset += pdu_marshal(vs->pdu, vs->offset, "w", vs->nwnames); - - for (i = 0; i < vs->nwnames; i++) { - vs->offset += pdu_marshal(vs->pdu, vs->offset, "Q", &vs->qids[i]); + size_t offset = 7; + offset += pdu_marshal(pdu, offset, "w", nwnames); + for (i = 0; i < nwnames; i++) { + offset += pdu_marshal(pdu, offset, "Q", &qids[i]); } -} - -static void v9fs_walk_post_newfid_lstat(V9fsState *s, V9fsWalkState *vs, - int err) -{ - if (err == -1) { - free_fid(s, vs->newfidp->fid); - v9fs_string_free(&vs->path); - err = -ENOENT; - goto out; - } - - stat_to_qid(&vs->stbuf, &vs->qids[vs->name_idx]); - - vs->name_idx++; - if (vs->name_idx < vs->nwnames) { - v9fs_string_sprintf(&vs->path, "%s/%s", vs->newfidp->path.data, - vs->wnames[vs->name_idx].data); - v9fs_string_copy(&vs->newfidp->path, &vs->path); - - err = v9fs_do_lstat(s, &vs->newfidp->path, &vs->stbuf); - v9fs_walk_post_newfid_lstat(s, vs, err); - return; - } - - v9fs_string_free(&vs->path); - v9fs_walk_marshal(vs); - err = vs->offset; -out: - v9fs_walk_complete(s, vs, err); -} - -static void v9fs_walk_post_oldfid_lstat(V9fsState *s, V9fsWalkState *vs, - int err) -{ - if (err == -1) { - v9fs_string_free(&vs->path); - err = -ENOENT; - goto out; - } - - stat_to_qid(&vs->stbuf, &vs->qids[vs->name_idx]); - vs->name_idx++; - if (vs->name_idx < vs->nwnames) { - - v9fs_string_sprintf(&vs->path, "%s/%s", - vs->fidp->path.data, vs->wnames[vs->name_idx].data); - v9fs_string_copy(&vs->fidp->path, &vs->path); - - err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf); - v9fs_walk_post_oldfid_lstat(s, vs, err); - return; - } - - v9fs_string_free(&vs->path); - v9fs_walk_marshal(vs); - err = vs->offset; -out: - v9fs_walk_complete(s, vs, err); + return offset; } static void v9fs_walk(void *opaque) { + int name_idx; + V9fsQID *qids = NULL; + int i, err = 0; + V9fsString path; + uint16_t nwnames; + struct stat stbuf; + size_t offset = 7; + int32_t fid, newfid; + V9fsString *wnames = NULL; + V9fsFidState *fidp; + V9fsFidState *newfidp; V9fsPDU *pdu = opaque; V9fsState *s = pdu->s; - int32_t fid, newfid; - V9fsWalkState *vs; - int err = 0; - int i; - - vs = g_malloc(sizeof(*vs)); - vs->pdu = pdu; - vs->wnames = NULL; - vs->qids = NULL; - vs->offset = 7; - vs->offset += pdu_unmarshal(vs->pdu, vs->offset, "ddw", &fid, - &newfid, &vs->nwnames); + offset += pdu_unmarshal(pdu, offset, "ddw", &fid, + &newfid, &nwnames); - if (vs->nwnames && vs->nwnames <= P9_MAXWELEM) { - vs->wnames = g_malloc0(sizeof(vs->wnames[0]) * vs->nwnames); - - vs->qids = g_malloc0(sizeof(vs->qids[0]) * vs->nwnames); - - for (i = 0; i < vs->nwnames; i++) { - vs->offset += pdu_unmarshal(vs->pdu, vs->offset, "s", - &vs->wnames[i]); + if (nwnames && nwnames <= P9_MAXWELEM) { + wnames = g_malloc0(sizeof(wnames[0]) * nwnames); + qids = g_malloc0(sizeof(qids[0]) * nwnames); + for (i = 0; i < nwnames; i++) { + offset += pdu_unmarshal(pdu, offset, "s", &wnames[i]); } - } else if (vs->nwnames > P9_MAXWELEM) { + + } else if (nwnames > P9_MAXWELEM) { err = -EINVAL; goto out; } - - vs->fidp = lookup_fid(s, fid); - if (vs->fidp == NULL) { + fidp = lookup_fid(s, fid); + if (fidp == NULL) { err = -ENOENT; goto out; } - - /* FIXME: is this really valid? */ if (fid == newfid) { - - BUG_ON(vs->fidp->fid_type != P9_FID_NONE); - v9fs_string_init(&vs->path); - vs->name_idx = 0; - - if (vs->name_idx < vs->nwnames) { - v9fs_string_sprintf(&vs->path, "%s/%s", - vs->fidp->path.data, vs->wnames[vs->name_idx].data); - v9fs_string_copy(&vs->fidp->path, &vs->path); - - err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf); - v9fs_walk_post_oldfid_lstat(s, vs, err); - return; + BUG_ON(fidp->fid_type != P9_FID_NONE); + v9fs_string_init(&path); + for (name_idx = 0; name_idx < nwnames; name_idx++) { + v9fs_string_sprintf(&path, "%s/%s", + fidp->path.data, wnames[name_idx].data); + v9fs_string_copy(&fidp->path, &path); + + err = v9fs_co_lstat(s, &fidp->path, &stbuf); + if (err < 0) { + v9fs_string_free(&path); + goto out; + } + stat_to_qid(&stbuf, &qids[name_idx]); } + v9fs_string_free(&path); } else { - vs->newfidp = alloc_fid(s, newfid); - if (vs->newfidp == NULL) { + newfidp = alloc_fid(s, newfid); + if (newfidp == NULL) { err = -EINVAL; goto out; } - - vs->newfidp->uid = vs->fidp->uid; - v9fs_string_init(&vs->path); - vs->name_idx = 0; - v9fs_string_copy(&vs->newfidp->path, &vs->fidp->path); - - if (vs->name_idx < vs->nwnames) { - v9fs_string_sprintf(&vs->path, "%s/%s", vs->newfidp->path.data, - vs->wnames[vs->name_idx].data); - v9fs_string_copy(&vs->newfidp->path, &vs->path); - - err = v9fs_do_lstat(s, &vs->newfidp->path, &vs->stbuf); - v9fs_walk_post_newfid_lstat(s, vs, err); - return; + newfidp->uid = fidp->uid; + v9fs_string_init(&path); + v9fs_string_copy(&newfidp->path, &fidp->path); + for (name_idx = 0; name_idx < nwnames; name_idx++) { + v9fs_string_sprintf(&path, "%s/%s", newfidp->path.data, + wnames[name_idx].data); + v9fs_string_copy(&newfidp->path, &path); + err = v9fs_co_lstat(s, &newfidp->path, &stbuf); + if (err < 0) { + free_fid(s, newfidp->fid); + v9fs_string_free(&path); + goto out; + } + stat_to_qid(&stbuf, &qids[name_idx]); } + v9fs_string_free(&path); } - - v9fs_walk_marshal(vs); - err = vs->offset; + err = v9fs_walk_marshal(pdu, nwnames, qids); out: - v9fs_walk_complete(s, vs, err); + complete_pdu(s, pdu, err); + if (nwnames && nwnames <= P9_MAXWELEM) { + for (name_idx = 0; name_idx < nwnames; name_idx++) { + v9fs_string_free(&wnames[name_idx]); + } + g_free(wnames); + g_free(qids); + } } static int32_t get_iounit(V9fsState *s, V9fsString *name) @@ -1546,467 +1296,323 @@ static int32_t get_iounit(V9fsState *s, V9fsString *name) * iounit should be multiples of f_bsize (host filesystem block size * and as well as less than (client msize - P9_IOHDRSZ)) */ - if (!v9fs_do_statfs(s, name, &stbuf)) { + if (!v9fs_co_statfs(s, name, &stbuf)) { iounit = stbuf.f_bsize; iounit *= (s->msize - P9_IOHDRSZ)/stbuf.f_bsize; } - if (!iounit) { iounit = s->msize - P9_IOHDRSZ; } return iounit; } -static void v9fs_open_post_opendir(V9fsState *s, V9fsOpenState *vs, int err) -{ - if (vs->fidp->fs.dir == NULL) { - err = -errno; - goto out; - } - vs->fidp->fid_type = P9_FID_DIR; - vs->offset += pdu_marshal(vs->pdu, vs->offset, "Qd", &vs->qid, 0); - err = vs->offset; -out: - complete_pdu(s, vs->pdu, err); - g_free(vs); - -} - -static void v9fs_open_post_getiounit(V9fsState *s, V9fsOpenState *vs) +static void v9fs_open(void *opaque) { - int err; - vs->offset += pdu_marshal(vs->pdu, vs->offset, "Qd", &vs->qid, vs->iounit); - err = vs->offset; - complete_pdu(s, vs->pdu, err); - g_free(vs); -} + int flags; + int iounit; + int32_t fid; + int32_t mode; + V9fsQID qid; + ssize_t err = 0; + size_t offset = 7; + struct stat stbuf; + V9fsFidState *fidp; + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; -static void v9fs_open_post_open(V9fsState *s, V9fsOpenState *vs, int err) -{ - if (vs->fidp->fs.fd == -1) { - err = -errno; + if (s->proto_version == V9FS_PROTO_2000L) { + pdu_unmarshal(pdu, offset, "dd", &fid, &mode); + } else { + pdu_unmarshal(pdu, offset, "db", &fid, &mode); + } + fidp = lookup_fid(s, fid); + if (fidp == NULL) { + err = -ENOENT; goto out; } - vs->fidp->fid_type = P9_FID_FILE; - vs->iounit = get_iounit(s, &vs->fidp->path); - v9fs_open_post_getiounit(s, vs); - return; -out: - complete_pdu(s, vs->pdu, err); - g_free(vs); -} - -static void v9fs_open_post_lstat(V9fsState *s, V9fsOpenState *vs, int err) -{ - int flags; + BUG_ON(fidp->fid_type != P9_FID_NONE); - if (err) { - err = -errno; + err = v9fs_co_lstat(s, &fidp->path, &stbuf); + if (err < 0) { goto out; } - - stat_to_qid(&vs->stbuf, &vs->qid); - - if (S_ISDIR(vs->stbuf.st_mode)) { - vs->fidp->fs.dir = v9fs_do_opendir(s, &vs->fidp->path); - v9fs_open_post_opendir(s, vs, err); + stat_to_qid(&stbuf, &qid); + if (S_ISDIR(stbuf.st_mode)) { + err = v9fs_co_opendir(s, fidp); + if (err < 0) { + goto out; + } + fidp->fid_type = P9_FID_DIR; + offset += pdu_marshal(pdu, offset, "Qd", &qid, 0); + err = offset; } else { if (s->proto_version == V9FS_PROTO_2000L) { - flags = vs->mode; + flags = mode; flags &= ~(O_NOCTTY | O_ASYNC | O_CREAT); /* Ignore direct disk access hint until the server supports it. */ flags &= ~O_DIRECT; } else { - flags = omode_to_uflags(vs->mode); + flags = omode_to_uflags(mode); } - vs->fidp->fs.fd = v9fs_do_open(s, &vs->fidp->path, flags); - v9fs_open_post_open(s, vs, err); - } - return; -out: - complete_pdu(s, vs->pdu, err); - g_free(vs); -} - -static void v9fs_open(void *opaque) -{ - V9fsPDU *pdu = opaque; - V9fsState *s = pdu->s; - int32_t fid; - V9fsOpenState *vs; - ssize_t err = 0; - - vs = g_malloc(sizeof(*vs)); - vs->pdu = pdu; - vs->offset = 7; - vs->mode = 0; - - if (s->proto_version == V9FS_PROTO_2000L) { - pdu_unmarshal(vs->pdu, vs->offset, "dd", &fid, &vs->mode); - } else { - pdu_unmarshal(vs->pdu, vs->offset, "db", &fid, &vs->mode); - } - - vs->fidp = lookup_fid(s, fid); - if (vs->fidp == NULL) { - err = -ENOENT; - goto out; - } - - BUG_ON(vs->fidp->fid_type != P9_FID_NONE); - - err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf); - - v9fs_open_post_lstat(s, vs, err); - return; -out: - complete_pdu(s, pdu, err); - g_free(vs); -} - -static void v9fs_post_lcreate(V9fsState *s, V9fsLcreateState *vs, int err) -{ - if (err == 0) { - v9fs_string_copy(&vs->fidp->path, &vs->fullname); - stat_to_qid(&vs->stbuf, &vs->qid); - vs->offset += pdu_marshal(vs->pdu, vs->offset, "Qd", &vs->qid, - vs->iounit); - err = vs->offset; - } else { - vs->fidp->fid_type = P9_FID_NONE; - err = -errno; - if (vs->fidp->fs.fd > 0) { - close(vs->fidp->fs.fd); + err = v9fs_co_open(s, fidp, flags); + if (err < 0) { + goto out; } + fidp->fid_type = P9_FID_FILE; + iounit = get_iounit(s, &fidp->path); + offset += pdu_marshal(pdu, offset, "Qd", &qid, iounit); + err = offset; } - - complete_pdu(s, vs->pdu, err); - v9fs_string_free(&vs->name); - v9fs_string_free(&vs->fullname); - g_free(vs); -} - -static void v9fs_lcreate_post_get_iounit(V9fsState *s, V9fsLcreateState *vs, - int err) -{ - if (err) { - err = -errno; - goto out; - } - err = v9fs_do_lstat(s, &vs->fullname, &vs->stbuf); - -out: - v9fs_post_lcreate(s, vs, err); -} - -static void v9fs_lcreate_post_do_open2(V9fsState *s, V9fsLcreateState *vs, - int err) -{ - if (vs->fidp->fs.fd == -1) { - err = -errno; - goto out; - } - vs->fidp->fid_type = P9_FID_FILE; - vs->iounit = get_iounit(s, &vs->fullname); - v9fs_lcreate_post_get_iounit(s, vs, err); - return; - out: - v9fs_post_lcreate(s, vs, err); + complete_pdu(s, pdu, err); } static void v9fs_lcreate(void *opaque) { - V9fsPDU *pdu = opaque; - V9fsState *s = pdu->s; int32_t dfid, flags, mode; gid_t gid; - V9fsLcreateState *vs; ssize_t err = 0; + ssize_t offset = 7; + V9fsString fullname; + V9fsString name; + V9fsFidState *fidp; + struct stat stbuf; + V9fsQID qid; + int32_t iounit; + V9fsPDU *pdu = opaque; - vs = g_malloc(sizeof(*vs)); - vs->pdu = pdu; - vs->offset = 7; - - v9fs_string_init(&vs->fullname); - - pdu_unmarshal(vs->pdu, vs->offset, "dsddd", &dfid, &vs->name, &flags, - &mode, &gid); + v9fs_string_init(&fullname); + pdu_unmarshal(pdu, offset, "dsddd", &dfid, &name, &flags, + &mode, &gid); - vs->fidp = lookup_fid(s, dfid); - if (vs->fidp == NULL) { + fidp = lookup_fid(pdu->s, dfid); + if (fidp == NULL) { err = -ENOENT; goto out; } - - v9fs_string_sprintf(&vs->fullname, "%s/%s", vs->fidp->path.data, - vs->name.data); + v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data); /* Ignore direct disk access hint until the server supports it. */ flags &= ~O_DIRECT; - vs->fidp->fs.fd = v9fs_do_open2(s, vs->fullname.data, vs->fidp->uid, - gid, flags, mode); - v9fs_lcreate_post_do_open2(s, vs, err); - return; - -out: - complete_pdu(s, vs->pdu, err); - v9fs_string_free(&vs->name); - g_free(vs); -} + err = v9fs_co_open2(pdu->s, fidp, fullname.data, gid, flags, mode); + if (err < 0) { + goto out; + } + fidp->fid_type = P9_FID_FILE; + iounit = get_iounit(pdu->s, &fullname); -static void v9fs_post_do_fsync(V9fsState *s, V9fsPDU *pdu, int err) -{ - if (err == -1) { - err = -errno; + err = v9fs_co_lstat(pdu->s, &fullname, &stbuf); + if (err < 0) { + fidp->fid_type = P9_FID_NONE; + if (fidp->fs.fd > 0) { + close(fidp->fs.fd); + } + goto out; } - complete_pdu(s, pdu, err); + v9fs_string_copy(&fidp->path, &fullname); + stat_to_qid(&stbuf, &qid); + offset += pdu_marshal(pdu, offset, "Qd", &qid, iounit); + err = offset; +out: + complete_pdu(pdu->s, pdu, err); + v9fs_string_free(&name); + v9fs_string_free(&fullname); } static void v9fs_fsync(void *opaque) { - V9fsPDU *pdu = opaque; - V9fsState *s = pdu->s; + int err; int32_t fid; + int datasync; size_t offset = 7; V9fsFidState *fidp; - int datasync; - int err; + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; pdu_unmarshal(pdu, offset, "dd", &fid, &datasync); fidp = lookup_fid(s, fid); if (fidp == NULL) { err = -ENOENT; - v9fs_post_do_fsync(s, pdu, err); - return; + goto out; + } + err = v9fs_co_fsync(s, fidp, datasync); + if (!err) { + err = offset; } - err = v9fs_do_fsync(s, fidp->fs.fd, datasync); - v9fs_post_do_fsync(s, pdu, err); +out: + complete_pdu(s, pdu, err); } static void v9fs_clunk(void *opaque) { - V9fsPDU *pdu = opaque; - V9fsState *s = pdu->s; + int err; int32_t fid; size_t offset = 7; - int err; + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; pdu_unmarshal(pdu, offset, "d", &fid); - err = free_fid(s, fid); if (err < 0) { goto out; } - - offset = 7; err = offset; out: complete_pdu(s, pdu, err); } -static void v9fs_read_post_readdir(V9fsState *, V9fsReadState *, ssize_t); - -static void v9fs_read_post_seekdir(V9fsState *s, V9fsReadState *vs, ssize_t err) +static int v9fs_xattr_read(V9fsState *s, V9fsPDU *pdu, + V9fsFidState *fidp, int64_t off, int32_t max_count) { - if (err) { - goto out; - } - vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", vs->count); - vs->offset += vs->count; - err = vs->offset; -out: - complete_pdu(s, vs->pdu, err); - v9fs_stat_free(&vs->v9stat); - v9fs_string_free(&vs->name); - g_free(vs); - return; -} + size_t offset = 7; + int read_count; + int64_t xattr_len; -static void v9fs_read_post_dir_lstat(V9fsState *s, V9fsReadState *vs, - ssize_t err) -{ - if (err) { - err = -errno; - goto out; - } - err = stat_to_v9stat(s, &vs->name, &vs->stbuf, &vs->v9stat); - if (err) { - goto out; + xattr_len = fidp->fs.xattr.len; + read_count = xattr_len - off; + if (read_count > max_count) { + read_count = max_count; + } else if (read_count < 0) { + /* + * read beyond XATTR value + */ + read_count = 0; } - - vs->len = pdu_marshal(vs->pdu, vs->offset + 4 + vs->count, "S", - &vs->v9stat); - if ((vs->len != (vs->v9stat.size + 2)) || - ((vs->count + vs->len) > vs->max_count)) { - v9fs_do_seekdir(s, vs->fidp->fs.dir, vs->dir_pos); - v9fs_read_post_seekdir(s, vs, err); - return; - } - vs->count += vs->len; - v9fs_stat_free(&vs->v9stat); - v9fs_string_free(&vs->name); - vs->dir_pos = vs->dent->d_off; - v9fs_co_readdir(s, vs->fidp, &vs->dent); - v9fs_read_post_readdir(s, vs, err); - return; -out: - v9fs_do_seekdir(s, vs->fidp->fs.dir, vs->dir_pos); - v9fs_read_post_seekdir(s, vs, err); - return; - + offset += pdu_marshal(pdu, offset, "d", read_count); + offset += pdu_pack(pdu, offset, + ((char *)fidp->fs.xattr.value) + off, + read_count); + return offset; } -static void v9fs_read_post_readdir(V9fsState *s, V9fsReadState *vs, ssize_t err) +static int v9fs_do_readdir_with_stat(V9fsState *s, V9fsPDU *pdu, + V9fsFidState *fidp, int32_t max_count) { - if (vs->dent) { - memset(&vs->v9stat, 0, sizeof(vs->v9stat)); - v9fs_string_init(&vs->name); - v9fs_string_sprintf(&vs->name, "%s/%s", vs->fidp->path.data, - vs->dent->d_name); - err = v9fs_do_lstat(s, &vs->name, &vs->stbuf); - v9fs_read_post_dir_lstat(s, vs, err); - return; - } - - vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", vs->count); - vs->offset += vs->count; - err = vs->offset; - complete_pdu(s, vs->pdu, err); - g_free(vs); - return; -} + V9fsString name; + V9fsStat v9stat; + int len, err = 0; + int32_t count = 0; + struct stat stbuf; + off_t saved_dir_pos; + struct dirent *dent, *result; -static void v9fs_read_post_telldir(V9fsState *s, V9fsReadState *vs, ssize_t err) -{ - v9fs_co_readdir(s, vs->fidp, &vs->dent); - v9fs_read_post_readdir(s, vs, err); - return; -} + /* save the directory position */ + saved_dir_pos = v9fs_co_telldir(s, fidp); + if (saved_dir_pos < 0) { + return saved_dir_pos; + } -static void v9fs_read_post_rewinddir(V9fsState *s, V9fsReadState *vs, - ssize_t err) -{ - vs->dir_pos = v9fs_do_telldir(s, vs->fidp->fs.dir); - v9fs_read_post_telldir(s, vs, err); - return; -} + dent = g_malloc(sizeof(struct dirent)); -static void v9fs_read_post_preadv(V9fsState *s, V9fsReadState *vs, ssize_t err) -{ - if (err < 0) { - /* IO error return the error */ - err = -errno; - goto out; - } - vs->total += vs->len; - vs->sg = adjust_sg(vs->sg, vs->len, &vs->cnt); - if (vs->total < vs->count && vs->len > 0) { - do { - if (0) { - print_sg(vs->sg, vs->cnt); - } - vs->len = v9fs_do_preadv(s, vs->fidp->fs.fd, vs->sg, vs->cnt, - vs->off); - if (vs->len > 0) { - vs->off += vs->len; - } - } while (vs->len == -1 && errno == EINTR); - if (vs->len == -1) { - err = -errno; + while (1) { + v9fs_string_init(&name); + err = v9fs_co_readdir_r(s, fidp, dent, &result); + if (err || !result) { + break; + } + v9fs_string_sprintf(&name, "%s/%s", fidp->path.data, dent->d_name); + err = v9fs_co_lstat(s, &name, &stbuf); + if (err < 0) { + goto out; } - v9fs_read_post_preadv(s, vs, err); - return; + err = stat_to_v9stat(s, &name, &stbuf, &v9stat); + if (err < 0) { + goto out; + } + /* 11 = 7 + 4 (7 = start offset, 4 = space for storing count) */ + len = pdu_marshal(pdu, 11 + count, "S", &v9stat); + if ((len != (v9stat.size + 2)) || ((count + len) > max_count)) { + /* Ran out of buffer. Set dir back to old position and return */ + v9fs_co_seekdir(s, fidp, saved_dir_pos); + v9fs_stat_free(&v9stat); + v9fs_string_free(&name); + g_free(dent); + return count; + } + count += len; + v9fs_stat_free(&v9stat); + v9fs_string_free(&name); + saved_dir_pos = dent->d_off; } - vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", vs->total); - vs->offset += vs->count; - err = vs->offset; - out: - complete_pdu(s, vs->pdu, err); - g_free(vs); -} - -static void v9fs_xattr_read(V9fsState *s, V9fsReadState *vs) -{ - ssize_t err = 0; - int read_count; - int64_t xattr_len; - - xattr_len = vs->fidp->fs.xattr.len; - read_count = xattr_len - vs->off; - if (read_count > vs->count) { - read_count = vs->count; - } else if (read_count < 0) { - /* - * read beyond XATTR value - */ - read_count = 0; + g_free(dent); + v9fs_string_free(&name); + if (err < 0) { + return err; } - vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", read_count); - vs->offset += pdu_pack(vs->pdu, vs->offset, - ((char *)vs->fidp->fs.xattr.value) + vs->off, - read_count); - err = vs->offset; - complete_pdu(s, vs->pdu, err); - g_free(vs); + return count; } static void v9fs_read(void *opaque) { - V9fsPDU *pdu = opaque; - V9fsState *s = pdu->s; int32_t fid; - V9fsReadState *vs; + int64_t off; ssize_t err = 0; + int32_t count = 0; + size_t offset = 7; + int32_t max_count; + V9fsFidState *fidp; + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; - vs = g_malloc(sizeof(*vs)); - vs->pdu = pdu; - vs->offset = 7; - vs->total = 0; - vs->len = 0; - vs->count = 0; - - pdu_unmarshal(vs->pdu, vs->offset, "dqd", &fid, &vs->off, &vs->count); - - vs->fidp = lookup_fid(s, fid); - if (vs->fidp == NULL) { + pdu_unmarshal(pdu, offset, "dqd", &fid, &off, &max_count); + fidp = lookup_fid(s, fid); + if (fidp == NULL) { err = -EINVAL; goto out; } + if (fidp->fid_type == P9_FID_DIR) { - if (vs->fidp->fid_type == P9_FID_DIR) { - vs->max_count = vs->count; - vs->count = 0; - if (vs->off == 0) { - v9fs_do_rewinddir(s, vs->fidp->fs.dir); - } - v9fs_read_post_rewinddir(s, vs, err); - return; - } else if (vs->fidp->fid_type == P9_FID_FILE) { - vs->sg = vs->iov; - pdu_marshal(vs->pdu, vs->offset + 4, "v", vs->sg, &vs->cnt); - vs->sg = cap_sg(vs->sg, vs->count, &vs->cnt); - if (vs->total <= vs->count) { - vs->len = v9fs_do_preadv(s, vs->fidp->fs.fd, vs->sg, vs->cnt, - vs->off); - if (vs->len > 0) { - vs->off += vs->len; - } - err = vs->len; - v9fs_read_post_preadv(s, vs, err); + if (off == 0) { + v9fs_co_rewinddir(s, fidp); } - return; - } else if (vs->fidp->fid_type == P9_FID_XATTR) { - v9fs_xattr_read(s, vs); - return; + count = v9fs_do_readdir_with_stat(s, pdu, fidp, max_count); + if (count < 0) { + err = count; + goto out; + } + err = offset; + err += pdu_marshal(pdu, offset, "d", count); + err += count; + } else if (fidp->fid_type == P9_FID_FILE) { + int32_t cnt; + int32_t len; + struct iovec *sg; + struct iovec iov[128]; /* FIXME: bad, bad, bad */ + + sg = iov; + pdu_marshal(pdu, offset + 4, "v", sg, &cnt); + sg = cap_sg(sg, max_count, &cnt); + do { + if (0) { + print_sg(sg, cnt); + } + /* Loop in case of EINTR */ + do { + len = v9fs_co_preadv(s, fidp, sg, cnt, off); + if (len >= 0) { + off += len; + count += len; + } + } while (len == -EINTR); + if (len < 0) { + /* IO error return the error */ + err = len; + goto out; + } + sg = adjust_sg(sg, len, &cnt); + } while (count < max_count && len > 0); + err = offset; + err += pdu_marshal(pdu, offset, "d", count); + err += count; + } else if (fidp->fid_type == P9_FID_XATTR) { + err = v9fs_xattr_read(s, pdu, fidp, off, max_count); } else { err = -EINVAL; } out: complete_pdu(s, pdu, err); - g_free(vs); } static size_t v9fs_readdir_data_size(V9fsString *name) @@ -2027,16 +1633,19 @@ static int v9fs_do_readdir(V9fsState *s, V9fsPDU *pdu, int len, err = 0; int32_t count = 0; off_t saved_dir_pos; - struct dirent *dent; + struct dirent *dent, *result; /* save the directory position */ saved_dir_pos = v9fs_co_telldir(s, fidp); if (saved_dir_pos < 0) { return saved_dir_pos; } + + dent = g_malloc(sizeof(struct dirent)); + while (1) { - err = v9fs_co_readdir(s, fidp, &dent); - if (err || !dent) { + err = v9fs_co_readdir_r(s, fidp, dent, &result); + if (err || !result) { break; } v9fs_string_init(&name); @@ -2045,6 +1654,7 @@ static int v9fs_do_readdir(V9fsState *s, V9fsPDU *pdu, /* Ran out of buffer. Set dir back to old position and return */ v9fs_co_seekdir(s, fidp, saved_dir_pos); v9fs_string_free(&name); + g_free(dent); return count; } /* @@ -2066,6 +1676,7 @@ static int v9fs_do_readdir(V9fsState *s, V9fsPDU *pdu, v9fs_string_free(&name); saved_dir_pos = dent->d_off; } + g_free(dent); if (err < 0) { return err; } @@ -2107,51 +1718,21 @@ out: complete_pdu(s, pdu, retval); } -static void v9fs_write_post_pwritev(V9fsState *s, V9fsWriteState *vs, - ssize_t err) -{ - if (err < 0) { - /* IO error return the error */ - err = -errno; - goto out; - } - vs->total += vs->len; - vs->sg = adjust_sg(vs->sg, vs->len, &vs->cnt); - if (vs->total < vs->count && vs->len > 0) { - do { - if (0) { - print_sg(vs->sg, vs->cnt); - } - vs->len = v9fs_do_pwritev(s, vs->fidp->fs.fd, vs->sg, vs->cnt, - vs->off); - if (vs->len > 0) { - vs->off += vs->len; - } - } while (vs->len == -1 && errno == EINTR); - if (vs->len == -1) { - err = -errno; - } - v9fs_write_post_pwritev(s, vs, err); - return; - } - vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", vs->total); - err = vs->offset; -out: - complete_pdu(s, vs->pdu, err); - g_free(vs); -} - -static void v9fs_xattr_write(V9fsState *s, V9fsWriteState *vs) +static int v9fs_xattr_write(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp, + int64_t off, int32_t count, + struct iovec *sg, int cnt) { int i, to_copy; ssize_t err = 0; int write_count; int64_t xattr_len; + size_t offset = 7; - xattr_len = vs->fidp->fs.xattr.len; - write_count = xattr_len - vs->off; - if (write_count > vs->count) { - write_count = vs->count; + + xattr_len = fidp->fs.xattr.len; + write_count = xattr_len - off; + if (write_count > count) { + write_count = count; } else if (write_count < 0) { /* * write beyond XATTR value len specified in @@ -2160,225 +1741,161 @@ static void v9fs_xattr_write(V9fsState *s, V9fsWriteState *vs) err = -ENOSPC; goto out; } - vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", write_count); - err = vs->offset; - vs->fidp->fs.xattr.copied_len += write_count; + offset += pdu_marshal(pdu, offset, "d", write_count); + err = offset; + fidp->fs.xattr.copied_len += write_count; /* * Now copy the content from sg list */ - for (i = 0; i < vs->cnt; i++) { - if (write_count > vs->sg[i].iov_len) { - to_copy = vs->sg[i].iov_len; + for (i = 0; i < cnt; i++) { + if (write_count > sg[i].iov_len) { + to_copy = sg[i].iov_len; } else { to_copy = write_count; } - memcpy((char *)vs->fidp->fs.xattr.value + vs->off, - vs->sg[i].iov_base, to_copy); + memcpy((char *)fidp->fs.xattr.value + off, sg[i].iov_base, to_copy); /* updating vs->off since we are not using below */ - vs->off += to_copy; + off += to_copy; write_count -= to_copy; } out: - complete_pdu(s, vs->pdu, err); - g_free(vs); + return err; } static void v9fs_write(void *opaque) { + int cnt; + ssize_t err; + int32_t fid; + int64_t off; + int32_t count; + int32_t len = 0; + int32_t total = 0; + size_t offset = 7; + V9fsFidState *fidp; + struct iovec iov[128]; /* FIXME: bad, bad, bad */ + struct iovec *sg = iov; V9fsPDU *pdu = opaque; V9fsState *s = pdu->s; - int32_t fid; - V9fsWriteState *vs; - ssize_t err; - - vs = g_malloc(sizeof(*vs)); - - vs->pdu = pdu; - vs->offset = 7; - vs->sg = vs->iov; - vs->total = 0; - vs->len = 0; - pdu_unmarshal(vs->pdu, vs->offset, "dqdv", &fid, &vs->off, &vs->count, - vs->sg, &vs->cnt); - - vs->fidp = lookup_fid(s, fid); - if (vs->fidp == NULL) { + pdu_unmarshal(pdu, offset, "dqdv", &fid, &off, &count, sg, &cnt); + fidp = lookup_fid(s, fid); + if (fidp == NULL) { err = -EINVAL; goto out; } - - if (vs->fidp->fid_type == P9_FID_FILE) { - if (vs->fidp->fs.fd == -1) { + if (fidp->fid_type == P9_FID_FILE) { + if (fidp->fs.fd == -1) { err = -EINVAL; goto out; } - } else if (vs->fidp->fid_type == P9_FID_XATTR) { + } else if (fidp->fid_type == P9_FID_XATTR) { /* * setxattr operation */ - v9fs_xattr_write(s, vs); - return; + err = v9fs_xattr_write(s, pdu, fidp, off, count, sg, cnt); + goto out; } else { err = -EINVAL; goto out; } - vs->sg = cap_sg(vs->sg, vs->count, &vs->cnt); - if (vs->total <= vs->count) { - vs->len = v9fs_do_pwritev(s, vs->fidp->fs.fd, vs->sg, vs->cnt, vs->off); - if (vs->len > 0) { - vs->off += vs->len; + sg = cap_sg(sg, count, &cnt); + do { + if (0) { + print_sg(sg, cnt); } - err = vs->len; - v9fs_write_post_pwritev(s, vs, err); - } - return; + /* Loop in case of EINTR */ + do { + len = v9fs_co_pwritev(s, fidp, sg, cnt, off); + if (len >= 0) { + off += len; + total += len; + } + } while (len == -EINTR); + if (len < 0) { + /* IO error return the error */ + err = len; + goto out; + } + sg = adjust_sg(sg, len, &cnt); + } while (total < count && len > 0); + offset += pdu_marshal(pdu, offset, "d", total); + err = offset; out: - complete_pdu(s, vs->pdu, err); - g_free(vs); -} - -static void v9fs_create_post_getiounit(V9fsState *s, V9fsCreateState *vs) -{ - int err; - v9fs_string_copy(&vs->fidp->path, &vs->fullname); - stat_to_qid(&vs->stbuf, &vs->qid); - - vs->offset += pdu_marshal(vs->pdu, vs->offset, "Qd", &vs->qid, vs->iounit); - err = vs->offset; - - complete_pdu(s, vs->pdu, err); - v9fs_string_free(&vs->name); - v9fs_string_free(&vs->extension); - v9fs_string_free(&vs->fullname); - g_free(vs); -} - -static void v9fs_post_create(V9fsState *s, V9fsCreateState *vs, int err) -{ - if (err == 0) { - vs->iounit = get_iounit(s, &vs->fidp->path); - v9fs_create_post_getiounit(s, vs); - return; - } - - complete_pdu(s, vs->pdu, err); - v9fs_string_free(&vs->name); - v9fs_string_free(&vs->extension); - v9fs_string_free(&vs->fullname); - g_free(vs); -} - -static void v9fs_create_post_perms(V9fsState *s, V9fsCreateState *vs, int err) -{ - if (err) { - err = -errno; - } - v9fs_post_create(s, vs, err); -} - -static void v9fs_create_post_opendir(V9fsState *s, V9fsCreateState *vs, - int err) -{ - if (!vs->fidp->fs.dir) { - err = -errno; - } - vs->fidp->fid_type = P9_FID_DIR; - v9fs_post_create(s, vs, err); + complete_pdu(s, pdu, err); } -static void v9fs_create_post_dir_lstat(V9fsState *s, V9fsCreateState *vs, - int err) +static void v9fs_create(void *opaque) { - if (err) { - err = -errno; - goto out; - } + int32_t fid; + int err = 0; + size_t offset = 7; + V9fsFidState *fidp; + V9fsQID qid; + int32_t perm; + int8_t mode; + struct stat stbuf; + V9fsString name; + V9fsString extension; + V9fsString fullname; + int iounit; + V9fsPDU *pdu = opaque; - vs->fidp->fs.dir = v9fs_do_opendir(s, &vs->fullname); - v9fs_create_post_opendir(s, vs, err); - return; + v9fs_string_init(&fullname); -out: - v9fs_post_create(s, vs, err); -} + pdu_unmarshal(pdu, offset, "dsdbs", &fid, &name, + &perm, &mode, &extension); -static void v9fs_create_post_mkdir(V9fsState *s, V9fsCreateState *vs, int err) -{ - if (err < 0) { + fidp = lookup_fid(pdu->s, fid); + if (fidp == NULL) { + err = -EINVAL; goto out; } - err = v9fs_do_lstat(s, &vs->fullname, &vs->stbuf); - v9fs_create_post_dir_lstat(s, vs, err); - return; - -out: - v9fs_post_create(s, vs, err); -} - -static void v9fs_create_post_fstat(V9fsState *s, V9fsCreateState *vs, int err) -{ - if (err) { - vs->fidp->fid_type = P9_FID_NONE; - close(vs->fidp->fs.fd); - err = -errno; - } - v9fs_post_create(s, vs, err); - return; -} - -static void v9fs_create_post_open2(V9fsState *s, V9fsCreateState *vs, int err) -{ - if (vs->fidp->fs.fd == -1) { - err = -errno; + v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data); + err = v9fs_co_lstat(pdu->s, &fullname, &stbuf); + if (!err) { + err = -EEXIST; goto out; - } - vs->fidp->fid_type = P9_FID_FILE; - err = v9fs_do_fstat(s, vs->fidp->fs.fd, &vs->stbuf); - v9fs_create_post_fstat(s, vs, err); - - return; - -out: - v9fs_post_create(s, vs, err); - -} - -static void v9fs_create_post_lstat(V9fsState *s, V9fsCreateState *vs, int err) -{ - - if (err == 0 || errno != ENOENT) { - err = -errno; + } else if (err != -ENOENT) { goto out; } - - if (vs->perm & P9_STAT_MODE_DIR) { - err = v9fs_co_mkdir(s, vs->fullname.data, vs->perm & 0777, - vs->fidp->uid, -1); - v9fs_create_post_mkdir(s, vs, err); - } else if (vs->perm & P9_STAT_MODE_SYMLINK) { - err = v9fs_do_symlink(s, vs->fidp, vs->extension.data, - vs->fullname.data, -1); - v9fs_create_post_perms(s, vs, err); - } else if (vs->perm & P9_STAT_MODE_LINK) { - int32_t nfid = atoi(vs->extension.data); - V9fsFidState *nfidp = lookup_fid(s, nfid); + if (perm & P9_STAT_MODE_DIR) { + err = v9fs_co_mkdir(pdu->s, fullname.data, perm & 0777, + fidp->uid, -1); + if (err < 0) { + goto out; + } + err = v9fs_co_opendir(pdu->s, fidp); + if (err < 0) { + goto out; + } + fidp->fid_type = P9_FID_DIR; + } else if (perm & P9_STAT_MODE_SYMLINK) { + err = v9fs_co_symlink(pdu->s, fidp, extension.data, + fullname.data, -1); + if (err < 0) { + goto out; + } + } else if (perm & P9_STAT_MODE_LINK) { + int32_t nfid = atoi(extension.data); + V9fsFidState *nfidp = lookup_fid(pdu->s, nfid); if (nfidp == NULL) { - err = -errno; - v9fs_post_create(s, vs, err); + err = -EINVAL; + goto out; + } + err = v9fs_co_link(pdu->s, &nfidp->path, &fullname); + if (err < 0) { + goto out; } - err = v9fs_do_link(s, &nfidp->path, &vs->fullname); - v9fs_create_post_perms(s, vs, err); - } else if (vs->perm & P9_STAT_MODE_DEVICE) { + } else if (perm & P9_STAT_MODE_DEVICE) { char ctype; uint32_t major, minor; mode_t nmode = 0; - if (sscanf(vs->extension.data, "%c %u %u", &ctype, &major, - &minor) != 3) { + if (sscanf(extension.data, "%c %u %u", &ctype, &major, &minor) != 3) { err = -errno; - v9fs_post_create(s, vs, err); + goto out; } switch (ctype) { @@ -2390,134 +1907,95 @@ static void v9fs_create_post_lstat(V9fsState *s, V9fsCreateState *vs, int err) break; default: err = -EIO; - v9fs_post_create(s, vs, err); - } - - nmode |= vs->perm & 0777; - err = v9fs_do_mknod(s, vs->fullname.data, nmode, - makedev(major, minor), vs->fidp->uid, -1); - v9fs_create_post_perms(s, vs, err); - } else if (vs->perm & P9_STAT_MODE_NAMED_PIPE) { - err = v9fs_do_mknod(s, vs->fullname.data, S_IFIFO | (vs->perm & 0777), - 0, vs->fidp->uid, -1); - v9fs_post_create(s, vs, err); - } else if (vs->perm & P9_STAT_MODE_SOCKET) { - err = v9fs_do_mknod(s, vs->fullname.data, S_IFSOCK | (vs->perm & 0777), - 0, vs->fidp->uid, -1); - v9fs_post_create(s, vs, err); - } else { - vs->fidp->fs.fd = v9fs_do_open2(s, vs->fullname.data, vs->fidp->uid, - -1, omode_to_uflags(vs->mode)|O_CREAT, vs->perm); - - v9fs_create_post_open2(s, vs, err); - } - - return; - -out: - v9fs_post_create(s, vs, err); -} - -static void v9fs_create(void *opaque) -{ - V9fsPDU *pdu = opaque; - V9fsState *s = pdu->s; - int32_t fid; - V9fsCreateState *vs; - int err = 0; - - vs = g_malloc(sizeof(*vs)); - vs->pdu = pdu; - vs->offset = 7; - - v9fs_string_init(&vs->fullname); - - pdu_unmarshal(vs->pdu, vs->offset, "dsdbs", &fid, &vs->name, - &vs->perm, &vs->mode, &vs->extension); - - vs->fidp = lookup_fid(s, fid); - if (vs->fidp == NULL) { - err = -EINVAL; - goto out; - } - - v9fs_string_sprintf(&vs->fullname, "%s/%s", vs->fidp->path.data, - vs->name.data); - - err = v9fs_do_lstat(s, &vs->fullname, &vs->stbuf); - v9fs_create_post_lstat(s, vs, err); - return; - -out: - complete_pdu(s, vs->pdu, err); - v9fs_string_free(&vs->name); - v9fs_string_free(&vs->extension); - g_free(vs); -} + goto out; + } -static void v9fs_post_symlink(V9fsState *s, V9fsSymlinkState *vs, int err) -{ - if (err == 0) { - stat_to_qid(&vs->stbuf, &vs->qid); - vs->offset += pdu_marshal(vs->pdu, vs->offset, "Q", &vs->qid); - err = vs->offset; + nmode |= perm & 0777; + err = v9fs_co_mknod(pdu->s, &fullname, fidp->uid, -1, + makedev(major, minor), nmode); + if (err < 0) { + goto out; + } + } else if (perm & P9_STAT_MODE_NAMED_PIPE) { + err = v9fs_co_mknod(pdu->s, &fullname, fidp->uid, -1, + 0, S_IFIFO | (perm & 0777)); + if (err < 0) { + goto out; + } + } else if (perm & P9_STAT_MODE_SOCKET) { + err = v9fs_co_mknod(pdu->s, &fullname, fidp->uid, -1, + 0, S_IFSOCK | (perm & 0777)); + if (err < 0) { + goto out; + } } else { - err = -errno; + err = v9fs_co_open2(pdu->s, fidp, fullname.data, -1, + omode_to_uflags(mode)|O_CREAT, perm); + if (err < 0) { + goto out; + } + fidp->fid_type = P9_FID_FILE; } - complete_pdu(s, vs->pdu, err); - v9fs_string_free(&vs->name); - v9fs_string_free(&vs->symname); - v9fs_string_free(&vs->fullname); - g_free(vs); -} - -static void v9fs_symlink_post_do_symlink(V9fsState *s, V9fsSymlinkState *vs, - int err) -{ - if (err) { + err = v9fs_co_lstat(pdu->s, &fullname, &stbuf); + if (err < 0) { + fidp->fid_type = P9_FID_NONE; + if (fidp->fs.fd) { + close(fidp->fs.fd); + } goto out; } - err = v9fs_do_lstat(s, &vs->fullname, &vs->stbuf); + iounit = get_iounit(pdu->s, &fidp->path); + v9fs_string_copy(&fidp->path, &fullname); + stat_to_qid(&stbuf, &qid); + offset += pdu_marshal(pdu, offset, "Qd", &qid, iounit); + err = offset; out: - v9fs_post_symlink(s, vs, err); + complete_pdu(pdu->s, pdu, err); + v9fs_string_free(&name); + v9fs_string_free(&extension); + v9fs_string_free(&fullname); } static void v9fs_symlink(void *opaque) { V9fsPDU *pdu = opaque; - V9fsState *s = pdu->s; + V9fsString name; + V9fsString symname; + V9fsString fullname; + V9fsFidState *dfidp; + V9fsQID qid; + struct stat stbuf; int32_t dfid; - V9fsSymlinkState *vs; int err = 0; gid_t gid; + size_t offset = 7; - vs = g_malloc(sizeof(*vs)); - vs->pdu = pdu; - vs->offset = 7; - - v9fs_string_init(&vs->fullname); - - pdu_unmarshal(vs->pdu, vs->offset, "dssd", &dfid, &vs->name, - &vs->symname, &gid); + v9fs_string_init(&fullname); + pdu_unmarshal(pdu, offset, "dssd", &dfid, &name, &symname, &gid); - vs->dfidp = lookup_fid(s, dfid); - if (vs->dfidp == NULL) { + dfidp = lookup_fid(pdu->s, dfid); + if (dfidp == NULL) { err = -EINVAL; goto out; } - v9fs_string_sprintf(&vs->fullname, "%s/%s", vs->dfidp->path.data, - vs->name.data); - err = v9fs_do_symlink(s, vs->dfidp, vs->symname.data, - vs->fullname.data, gid); - v9fs_symlink_post_do_symlink(s, vs, err); - return; - + v9fs_string_sprintf(&fullname, "%s/%s", dfidp->path.data, name.data); + err = v9fs_co_symlink(pdu->s, dfidp, symname.data, fullname.data, gid); + if (err < 0) { + goto out; + } + err = v9fs_co_lstat(pdu->s, &fullname, &stbuf); + if (err < 0) { + goto out; + } + stat_to_qid(&stbuf, &qid); + offset += pdu_marshal(pdu, offset, "Q", &qid); + err = offset; out: - complete_pdu(s, vs->pdu, err); - v9fs_string_free(&vs->name); - v9fs_string_free(&vs->symname); - g_free(vs); + complete_pdu(pdu->s, pdu, err); + v9fs_string_free(&name); + v9fs_string_free(&symname); + v9fs_string_free(&fullname); } static void v9fs_flush(void *opaque) @@ -2545,21 +2023,20 @@ static void v9fs_link(void *opaque) dfidp = lookup_fid(s, dfid); if (dfidp == NULL) { - err = -errno; + err = -ENOENT; goto out; } oldfidp = lookup_fid(s, oldfid); if (oldfidp == NULL) { - err = -errno; + err = -ENOENT; goto out; } v9fs_string_sprintf(&fullname, "%s/%s", dfidp->path.data, name.data); - err = offset; - err = v9fs_do_link(s, &oldfidp->path, &fullname); - if (err) { - err = -errno; + err = v9fs_co_link(s, &oldfidp->path, &fullname); + if (!err) { + err = offset; } v9fs_string_free(&fullname); @@ -2594,39 +2071,6 @@ out: complete_pdu(pdu->s, pdu, err); } -static void v9fs_wstat_post_truncate(V9fsState *s, V9fsWstatState *vs, int err) -{ - if (err < 0) { - goto out; - } - - err = vs->offset; - -out: - v9fs_stat_free(&vs->v9stat); - complete_pdu(s, vs->pdu, err); - g_free(vs); -} - -static void v9fs_wstat_post_rename(V9fsState *s, V9fsWstatState *vs, int err) -{ - if (err < 0) { - goto out; - } - if (vs->v9stat.length != -1) { - if (v9fs_do_truncate(s, &vs->fidp->path, vs->v9stat.length) < 0) { - err = -errno; - } - } - v9fs_wstat_post_truncate(s, vs, err); - return; - -out: - v9fs_stat_free(&vs->v9stat); - complete_pdu(s, vs->pdu, err); - g_free(vs); -} - static int v9fs_complete_rename(V9fsState *s, V9fsFidState *fidp, int32_t newdirfid, V9fsString *name) { @@ -2695,24 +2139,6 @@ out: return err; } -static void v9fs_wstat_post_chown(V9fsState *s, V9fsWstatState *vs, int err) -{ - if (err < 0) { - goto out; - } - - if (vs->v9stat.name.size != 0) { - err = v9fs_complete_rename(s, vs->fidp, -1, &vs->v9stat.name); - } - v9fs_wstat_post_rename(s, vs, err); - return; - -out: - v9fs_stat_free(&vs->v9stat); - complete_pdu(s, vs->pdu, err); - g_free(vs); -} - static void v9fs_rename(void *opaque) { int32_t fid; @@ -2742,143 +2168,90 @@ out: v9fs_string_free(&name); } -static void v9fs_wstat_post_utime(V9fsState *s, V9fsWstatState *vs, int err) +static void v9fs_wstat(void *opaque) { - if (err < 0) { - goto out; - } + int32_t fid; + int err = 0; + int16_t unused; + V9fsStat v9stat; + size_t offset = 7; + struct stat stbuf; + V9fsFidState *fidp; + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; - if (vs->v9stat.n_gid != -1 || vs->v9stat.n_uid != -1) { - if (v9fs_do_chown(s, &vs->fidp->path, vs->v9stat.n_uid, - vs->v9stat.n_gid)) { - err = -errno; - } + pdu_unmarshal(pdu, offset, "dwS", &fid, &unused, &v9stat); + fidp = lookup_fid(s, fid); + if (fidp == NULL) { + err = -EINVAL; + goto out; } - v9fs_wstat_post_chown(s, vs, err); - return; - -out: - v9fs_stat_free(&vs->v9stat); - complete_pdu(s, vs->pdu, err); - g_free(vs); -} - -static void v9fs_wstat_post_chmod(V9fsState *s, V9fsWstatState *vs, int err) -{ - if (err < 0) { + /* do we need to sync the file? */ + if (donttouch_stat(&v9stat)) { + err = v9fs_co_fsync(s, fidp, 0); goto out; } - - if (vs->v9stat.mtime != -1 || vs->v9stat.atime != -1) { + if (v9stat.mode != -1) { + uint32_t v9_mode; + err = v9fs_co_lstat(s, &fidp->path, &stbuf); + if (err < 0) { + goto out; + } + v9_mode = stat_to_v9mode(&stbuf); + if ((v9stat.mode & P9_STAT_MODE_TYPE_BITS) != + (v9_mode & P9_STAT_MODE_TYPE_BITS)) { + /* Attempting to change the type */ + err = -EIO; + goto out; + } + err = v9fs_co_chmod(s, &fidp->path, + v9mode_to_mode(v9stat.mode, + &v9stat.extension)); + if (err < 0) { + goto out; + } + } + if (v9stat.mtime != -1 || v9stat.atime != -1) { struct timespec times[2]; - if (vs->v9stat.atime != -1) { - times[0].tv_sec = vs->v9stat.atime; + if (v9stat.atime != -1) { + times[0].tv_sec = v9stat.atime; times[0].tv_nsec = 0; } else { times[0].tv_nsec = UTIME_OMIT; } - if (vs->v9stat.mtime != -1) { - times[1].tv_sec = vs->v9stat.mtime; + if (v9stat.mtime != -1) { + times[1].tv_sec = v9stat.mtime; times[1].tv_nsec = 0; } else { times[1].tv_nsec = UTIME_OMIT; } - - if (v9fs_do_utimensat(s, &vs->fidp->path, times)) { - err = -errno; + err = v9fs_co_utimensat(s, &fidp->path, times); + if (err < 0) { + goto out; } } - - v9fs_wstat_post_utime(s, vs, err); - return; - -out: - v9fs_stat_free(&vs->v9stat); - complete_pdu(s, vs->pdu, err); - g_free(vs); -} - -static void v9fs_wstat_post_fsync(V9fsState *s, V9fsWstatState *vs, int err) -{ - if (err == -1) { - err = -errno; - } - v9fs_stat_free(&vs->v9stat); - complete_pdu(s, vs->pdu, err); - g_free(vs); -} - -static void v9fs_wstat_post_lstat(V9fsState *s, V9fsWstatState *vs, int err) -{ - uint32_t v9_mode; - - if (err == -1) { - err = -errno; - goto out; - } - - v9_mode = stat_to_v9mode(&vs->stbuf); - - if ((vs->v9stat.mode & P9_STAT_MODE_TYPE_BITS) != - (v9_mode & P9_STAT_MODE_TYPE_BITS)) { - /* Attempting to change the type */ - err = -EIO; + if (v9stat.n_gid != -1 || v9stat.n_uid != -1) { + err = v9fs_co_chown(s, &fidp->path, v9stat.n_uid, v9stat.n_gid); + if (err < 0) { goto out; + } } - - if (v9fs_do_chmod(s, &vs->fidp->path, v9mode_to_mode(vs->v9stat.mode, - &vs->v9stat.extension))) { - err = -errno; - } - v9fs_wstat_post_chmod(s, vs, err); - return; - -out: - v9fs_stat_free(&vs->v9stat); - complete_pdu(s, vs->pdu, err); - g_free(vs); -} - -static void v9fs_wstat(void *opaque) -{ - V9fsPDU *pdu = opaque; - V9fsState *s = pdu->s; - int32_t fid; - V9fsWstatState *vs; - int err = 0; - - vs = g_malloc(sizeof(*vs)); - vs->pdu = pdu; - vs->offset = 7; - - pdu_unmarshal(pdu, vs->offset, "dwS", &fid, &vs->unused, &vs->v9stat); - - vs->fidp = lookup_fid(s, fid); - if (vs->fidp == NULL) { - err = -EINVAL; - goto out; - } - - /* do we need to sync the file? */ - if (donttouch_stat(&vs->v9stat)) { - err = v9fs_do_fsync(s, vs->fidp->fs.fd, 0); - v9fs_wstat_post_fsync(s, vs, err); - return; + if (v9stat.name.size != 0) { + err = v9fs_complete_rename(s, fidp, -1, &v9stat.name); + if (err < 0) { + goto out; + } } - - if (vs->v9stat.mode != -1) { - err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf); - v9fs_wstat_post_lstat(s, vs, err); - return; + if (v9stat.length != -1) { + err = v9fs_co_truncate(s, &fidp->path, v9stat.length); + if (err < 0) { + goto out; + } } - - v9fs_wstat_post_chmod(s, vs, err); - return; - + err = offset; out: - v9fs_stat_free(&vs->v9stat); - complete_pdu(s, vs->pdu, err); - g_free(vs); + v9fs_stat_free(&v9stat); + complete_pdu(s, pdu, err); } static int v9fs_fill_statfs(V9fsState *s, V9fsPDU *pdu, struct statfs *stbuf) @@ -3006,89 +2379,81 @@ out: * do any thing in * qemu 9p server side lock code path. * So when a TLOCK request comes, always return success */ - static void v9fs_lock(void *opaque) { + int8_t status; + V9fsFlock *flock; + size_t offset = 7; + struct stat stbuf; + V9fsFidState *fidp; + int32_t fid, err = 0; V9fsPDU *pdu = opaque; V9fsState *s = pdu->s; - int32_t fid, err = 0; - V9fsLockState *vs; - - vs = g_malloc0(sizeof(*vs)); - vs->pdu = pdu; - vs->offset = 7; - vs->flock = g_malloc(sizeof(*vs->flock)); - pdu_unmarshal(vs->pdu, vs->offset, "dbdqqds", &fid, &vs->flock->type, - &vs->flock->flags, &vs->flock->start, &vs->flock->length, - &vs->flock->proc_id, &vs->flock->client_id); - - vs->status = P9_LOCK_ERROR; + flock = g_malloc(sizeof(*flock)); + pdu_unmarshal(pdu, offset, "dbdqqds", &fid, &flock->type, + &flock->flags, &flock->start, &flock->length, + &flock->proc_id, &flock->client_id); + status = P9_LOCK_ERROR; /* We support only block flag now (that too ignored currently) */ - if (vs->flock->flags & ~P9_LOCK_FLAGS_BLOCK) { + if (flock->flags & ~P9_LOCK_FLAGS_BLOCK) { err = -EINVAL; goto out; } - vs->fidp = lookup_fid(s, fid); - if (vs->fidp == NULL) { + fidp = lookup_fid(s, fid); + if (fidp == NULL) { err = -ENOENT; goto out; } - - err = v9fs_do_fstat(s, vs->fidp->fs.fd, &vs->stbuf); + err = v9fs_co_fstat(s, fidp->fs.fd, &stbuf); if (err < 0) { - err = -errno; goto out; } - vs->status = P9_LOCK_SUCCESS; + status = P9_LOCK_SUCCESS; out: - vs->offset += pdu_marshal(vs->pdu, vs->offset, "b", vs->status); - complete_pdu(s, vs->pdu, err); - g_free(vs->flock); - g_free(vs); + err = offset; + err += pdu_marshal(pdu, offset, "b", status); + complete_pdu(s, pdu, err); + g_free(flock); } /* * When a TGETLOCK request comes, always return success because all lock * handling is done by client's VFS layer. */ - static void v9fs_getlock(void *opaque) { + size_t offset = 7; + struct stat stbuf; + V9fsFidState *fidp; + V9fsGetlock *glock; + int32_t fid, err = 0; V9fsPDU *pdu = opaque; V9fsState *s = pdu->s; - int32_t fid, err = 0; - V9fsGetlockState *vs; - vs = g_malloc0(sizeof(*vs)); - vs->pdu = pdu; - vs->offset = 7; + glock = g_malloc(sizeof(*glock)); + pdu_unmarshal(pdu, offset, "dbqqds", &fid, &glock->type, + &glock->start, &glock->length, &glock->proc_id, + &glock->client_id); - vs->glock = g_malloc(sizeof(*vs->glock)); - pdu_unmarshal(vs->pdu, vs->offset, "dbqqds", &fid, &vs->glock->type, - &vs->glock->start, &vs->glock->length, &vs->glock->proc_id, - &vs->glock->client_id); - - vs->fidp = lookup_fid(s, fid); - if (vs->fidp == NULL) { + fidp = lookup_fid(s, fid); + if (fidp == NULL) { err = -ENOENT; goto out; } - - err = v9fs_do_fstat(s, vs->fidp->fs.fd, &vs->stbuf); + err = v9fs_co_fstat(s, fidp->fs.fd, &stbuf); if (err < 0) { - err = -errno; goto out; } - vs->glock->type = F_UNLCK; - vs->offset += pdu_marshal(vs->pdu, vs->offset, "bqqds", vs->glock->type, - vs->glock->start, vs->glock->length, vs->glock->proc_id, - &vs->glock->client_id); + glock->type = F_UNLCK; + offset += pdu_marshal(pdu, offset, "bqqds", glock->type, + glock->start, glock->length, glock->proc_id, + &glock->client_id); + err = offset; out: - complete_pdu(s, vs->pdu, err); - g_free(vs->glock); - g_free(vs); + complete_pdu(s, pdu, err); + g_free(glock); } static void v9fs_mkdir(void *opaque) diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h index 46d79da920..1d8c1b1093 100644 --- a/hw/9pfs/virtio-9p.h +++ b/hw/9pfs/virtio-9p.h @@ -222,31 +222,6 @@ typedef struct V9fsState int32_t msize; } V9fsState; -typedef struct V9fsCreateState { - V9fsPDU *pdu; - size_t offset; - V9fsFidState *fidp; - V9fsQID qid; - int32_t perm; - int8_t mode; - struct stat stbuf; - V9fsString name; - V9fsString extension; - V9fsString fullname; - int iounit; -} V9fsCreateState; - -typedef struct V9fsLcreateState { - V9fsPDU *pdu; - size_t offset; - V9fsFidState *fidp; - V9fsQID qid; - int32_t iounit; - struct stat stbuf; - V9fsString name; - V9fsString fullname; -} V9fsLcreateState; - typedef struct V9fsStatState { V9fsPDU *pdu; size_t offset; @@ -278,19 +253,6 @@ typedef struct V9fsStatDotl { uint64_t st_data_version; } V9fsStatDotl; -typedef struct V9fsWalkState { - V9fsPDU *pdu; - size_t offset; - uint16_t nwnames; - int name_idx; - V9fsQID *qids; - V9fsFidState *fidp; - V9fsFidState *newfidp; - V9fsString path; - V9fsString *wnames; - struct stat stbuf; -} V9fsWalkState; - typedef struct V9fsOpenState { V9fsPDU *pdu; size_t offset; @@ -333,28 +295,6 @@ typedef struct V9fsWriteState { int cnt; } V9fsWriteState; -typedef struct V9fsWstatState -{ - V9fsPDU *pdu; - size_t offset; - int16_t unused; - V9fsStat v9stat; - V9fsFidState *fidp; - struct stat stbuf; -} V9fsWstatState; - -typedef struct V9fsSymlinkState -{ - V9fsPDU *pdu; - size_t offset; - V9fsString name; - V9fsString symname; - V9fsString fullname; - V9fsFidState *dfidp; - V9fsQID qid; - struct stat stbuf; -} V9fsSymlinkState; - typedef struct V9fsIattr { int32_t valid; @@ -403,16 +343,6 @@ typedef struct V9fsFlock V9fsString client_id; } V9fsFlock; -typedef struct V9fsLockState -{ - V9fsPDU *pdu; - size_t offset; - int8_t status; - struct stat stbuf; - V9fsFidState *fidp; - V9fsFlock *flock; -} V9fsLockState; - typedef struct V9fsGetlock { uint8_t type; @@ -422,15 +352,6 @@ typedef struct V9fsGetlock V9fsString client_id; } V9fsGetlock; -typedef struct V9fsGetlockState -{ - V9fsPDU *pdu; - size_t offset; - struct stat stbuf; - V9fsFidState *fidp; - V9fsGetlock *glock; -} V9fsGetlockState; - size_t pdu_packunpack(void *addr, struct iovec *sg, int sg_count, size_t offset, size_t size, int pack); |