aboutsummaryrefslogtreecommitdiff
path: root/hw/9pfs/9p.c
diff options
context:
space:
mode:
authorChristian Schoenebeck <qemu_oss@crudebyte.com>2020-07-29 10:39:12 +0200
committerChristian Schoenebeck <qemu_oss@crudebyte.com>2020-08-12 09:17:32 +0200
commitd2c5cf7ca15490b4737a5393e51abf0301b98971 (patch)
tree52f86dfd831fc9606c18c0ced3f3f2305437ecc5 /hw/9pfs/9p.c
parent0c4356ba7dafc8ecb5877a42fc0d68d45ccf5951 (diff)
downloadqemu-d2c5cf7ca15490b4737a5393e51abf0301b98971.zip
qemu-d2c5cf7ca15490b4737a5393e51abf0301b98971.tar.gz
qemu-d2c5cf7ca15490b4737a5393e51abf0301b98971.tar.bz2
9pfs: differentiate readdir lock between 9P2000.u vs. 9P2000.L
Previous patch suggests that it might make sense to use a different mutex type now while handling readdir requests, depending on the precise protocol variant, as v9fs_do_readdir_with_stat() (used by 9P2000.u) uses a CoMutex to avoid deadlocks that might happen with QemuMutex otherwise, whereas do_readdir_many() (used by 9P2000.L) should better use a QemuMutex, as the precise behaviour of a failed CoMutex lock on fs driver side would not be clear. And to avoid the wrong lock type being used, be now strict and error out if a 9P2000.L client sends a Tread on a directory, and likeweise error out if a 9P2000.u client sends a Treaddir request. This patch is just intended as transitional measure, as currently 9P2000.u vs. 9P2000.L implementations currently differ where the main logic of fetching directory entries is located at (9P2000.u still being more top half focused, while 9P2000.L already being bottom half focused in regards to fetching directory entries that is). Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com> Message-Id: <9a2ddc347e533b0d801866afd9dfac853d2d4106.1596012787.git.qemu_oss@crudebyte.com> Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
Diffstat (limited to 'hw/9pfs/9p.c')
-rw-r--r--hw/9pfs/9p.c21
1 files changed, 18 insertions, 3 deletions
diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index cc4094b..7bb994b 100644
--- a/hw/9pfs/9p.c
+++ b/hw/9pfs/9p.c
@@ -314,8 +314,8 @@ static V9fsFidState *alloc_fid(V9fsState *s, int32_t fid)
f->next = s->fid_list;
s->fid_list = f;
- v9fs_readdir_init(&f->fs.dir);
- v9fs_readdir_init(&f->fs_reclaim.dir);
+ v9fs_readdir_init(s->proto_version, &f->fs.dir);
+ v9fs_readdir_init(s->proto_version, &f->fs_reclaim.dir);
return f;
}
@@ -2228,7 +2228,14 @@ static void coroutine_fn v9fs_read(void *opaque)
goto out_nofid;
}
if (fidp->fid_type == P9_FID_DIR) {
-
+ if (s->proto_version != V9FS_PROTO_2000U) {
+ warn_report_once(
+ "9p: bad client: T_read request on directory only expected "
+ "with 9P2000.u protocol version"
+ );
+ err = -EOPNOTSUPP;
+ goto out;
+ }
if (off == 0) {
v9fs_co_rewinddir(pdu, fidp);
}
@@ -2446,6 +2453,14 @@ static void coroutine_fn v9fs_readdir(void *opaque)
retval = -EINVAL;
goto out;
}
+ if (s->proto_version != V9FS_PROTO_2000L) {
+ warn_report_once(
+ "9p: bad client: T_readdir request only expected with 9P2000.L "
+ "protocol version"
+ );
+ retval = -EOPNOTSUPP;
+ goto out;
+ }
count = v9fs_do_readdir(pdu, fidp, (off_t) initial_offset, max_count);
if (count < 0) {
retval = count;