9pfs: Fix severe performance issue of Treaddir requests.

-----BEGIN PGP SIGNATURE-----
 
 iQJLBAABCgA1FiEEltjREM96+AhPiFkBNMK1h2Wkc5UFAl8zvx0XHHFlbXVfb3Nz
 QGNydWRlYnl0ZS5jb20ACgkQNMK1h2Wkc5Uthw//cXXwifzzjUaLccxkTCRejdZH
 tRLVhx8Asp4JG5WV+djF78dAh8UGw6DPMGIejqgZyBW3fDwQzbJGSycMWCfLtDwS
 176rDS0yYfpHM4hVW3dVIvSC6ea1hXlzZQP4STe1ZSghVXYLjFLY6u5aFJmvtS2E
 vh33VecxE/MyKvJlTBpNG4h/oNz5PIJXPOsBI/N9kIX7sBDXZMI/X90SSJ0m/MJa
 heT/DRXTDJo+9m8K4Eibso/Akx8h+ZuyMwSR+b5e/9OKqylMdFKKBoGSSPDY2h8r
 q5OweV0Aewfj885qnD7BfH/Iis6re/qbFcQz6gxqZW0j/aW71yRoFXbFucvgX0ie
 1HLiLHd/gv9HAwT8TeYUT7bldIDyk2jiD14cvhkE9PXlWmGigu0aMiXhPJ2/Jbx2
 uJUIbLRXk6d/eds8q+2KO8+H6c6PmXMy40rqXDMFbUHCJIYDVH0K3hvH+4h8uE63
 PKRuwoI+XOryw6dxEQlx206CfDUrjnZ+X4+v7UloTEy6/4BxlcagFQDCgyHEqyJL
 PVlkOjRyJWDt8Q1k6YpZImj+OaTzLmnLE8/ucLzCnaHEVqWQUJwwO/jeeCgFt3a0
 oAUoTZUnpS7OM/oNWRx6YiheM8Ynk9nb6rAjeCpGnNgDhihq9Oh9/PKsXwTXUdyL
 sywT9dVI0Y4m3LyF7ok=
 =1Qh/
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/cschoenebeck/tags/pull-9p-20200812' into staging

9pfs: Fix severe performance issue of Treaddir requests.

# gpg: Signature made Wed 12 Aug 2020 11:06:21 BST
# gpg:                using RSA key 96D8D110CF7AF8084F88590134C2B58765A47395
# gpg:                issuer "qemu_oss@crudebyte.com"
# gpg: Good signature from "Christian Schoenebeck <qemu_oss@crudebyte.com>" [unknown]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: ECAB 1A45 4014 1413 BA38  4926 30DB 47C3 A012 D5F4
#      Subkey fingerprint: 96D8 D110 CF7A F808 4F88  5901 34C2 B587 65A4 7395

* remotes/cschoenebeck/tags/pull-9p-20200812:
  9pfs: clarify latency of v9fs_co_run_in_worker()
  9pfs: differentiate readdir lock between 9P2000.u vs. 9P2000.L
  9pfs: T_readdir latency optimization
  9pfs: add new function v9fs_co_readdir_many()
  9pfs: split out fs driver core of v9fs_co_readdir()
  9pfs: make v9fs_readdir_response_size() public
  tests/virtio-9p: added split readdir tests

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2020-08-24 16:39:52 +01:00
commit 30aa19446d
5 changed files with 441 additions and 94 deletions

View file

@ -578,6 +578,7 @@ static bool fs_dirents_contain_name(struct V9fsDirent *e, const char* name)
return false;
}
/* basic readdir test where reply fits into a single response message */
static void fs_readdir(void *obj, void *data, QGuestAllocator *t_alloc)
{
QVirtio9P *v9p = obj;
@ -631,6 +632,89 @@ static void fs_readdir(void *obj, void *data, QGuestAllocator *t_alloc)
g_free(wnames[0]);
}
/* readdir test where overall request is split over several messages */
static void fs_readdir_split(void *obj, void *data, QGuestAllocator *t_alloc,
uint32_t count)
{
QVirtio9P *v9p = obj;
alloc = t_alloc;
char *const wnames[] = { g_strdup(QTEST_V9FS_SYNTH_READDIR_DIR) };
uint16_t nqid;
v9fs_qid qid;
uint32_t nentries, npartialentries;
struct V9fsDirent *entries, *tail, *partialentries;
P9Req *req;
int fid;
uint64_t offset;
fs_attach(v9p, NULL, t_alloc);
fid = 1;
offset = 0;
entries = NULL;
nentries = 0;
tail = NULL;
req = v9fs_twalk(v9p, 0, fid, 1, wnames, 0);
v9fs_req_wait_for_reply(req, NULL);
v9fs_rwalk(req, &nqid, NULL);
g_assert_cmpint(nqid, ==, 1);
req = v9fs_tlopen(v9p, fid, O_DIRECTORY, 0);
v9fs_req_wait_for_reply(req, NULL);
v9fs_rlopen(req, &qid, NULL);
/*
* send as many Treaddir requests as required to get all directory
* entries
*/
while (true) {
npartialentries = 0;
partialentries = NULL;
req = v9fs_treaddir(v9p, fid, offset, count, 0);
v9fs_req_wait_for_reply(req, NULL);
v9fs_rreaddir(req, &count, &npartialentries, &partialentries);
if (npartialentries > 0 && partialentries) {
if (!entries) {
entries = partialentries;
nentries = npartialentries;
tail = partialentries;
} else {
tail->next = partialentries;
nentries += npartialentries;
}
while (tail->next) {
tail = tail->next;
}
offset = tail->offset;
} else {
break;
}
}
g_assert_cmpint(
nentries, ==,
QTEST_V9FS_SYNTH_READDIR_NFILES + 2 /* "." and ".." */
);
/*
* Check all file names exist in returned entries, ignore their order
* though.
*/
g_assert_cmpint(fs_dirents_contain_name(entries, "."), ==, true);
g_assert_cmpint(fs_dirents_contain_name(entries, ".."), ==, true);
for (int i = 0; i < QTEST_V9FS_SYNTH_READDIR_NFILES; ++i) {
char *name = g_strdup_printf(QTEST_V9FS_SYNTH_READDIR_FILE, i);
g_assert_cmpint(fs_dirents_contain_name(entries, name), ==, true);
g_free(name);
}
v9fs_free_dirents(entries);
g_free(wnames[0]);
}
static void fs_walk_no_slash(void *obj, void *data, QGuestAllocator *t_alloc)
{
QVirtio9P *v9p = obj;
@ -793,6 +877,24 @@ static void fs_flush_ignored(void *obj, void *data, QGuestAllocator *t_alloc)
g_free(wnames[0]);
}
static void fs_readdir_split_128(void *obj, void *data,
QGuestAllocator *t_alloc)
{
fs_readdir_split(obj, data, t_alloc, 128);
}
static void fs_readdir_split_256(void *obj, void *data,
QGuestAllocator *t_alloc)
{
fs_readdir_split(obj, data, t_alloc, 256);
}
static void fs_readdir_split_512(void *obj, void *data,
QGuestAllocator *t_alloc)
{
fs_readdir_split(obj, data, t_alloc, 512);
}
static void register_virtio_9p_test(void)
{
qos_add_test("config", "virtio-9p", pci_config, NULL);
@ -810,6 +912,12 @@ static void register_virtio_9p_test(void)
qos_add_test("fs/flush/ignored", "virtio-9p", fs_flush_ignored,
NULL);
qos_add_test("fs/readdir/basic", "virtio-9p", fs_readdir, NULL);
qos_add_test("fs/readdir/split_512", "virtio-9p",
fs_readdir_split_512, NULL);
qos_add_test("fs/readdir/split_256", "virtio-9p",
fs_readdir_split_256, NULL);
qos_add_test("fs/readdir/split_128", "virtio-9p",
fs_readdir_split_128, NULL);
}
libqos_init(register_virtio_9p_test);