Miklos Szeredi <miklos@xxxxxxxxxx> wrote: > So even the p2 method will give at least 80k queries/s, which is quite > good, considering that the need to rescan the complete mount tree > should be exceedingly rare (and in case it mattered, could be > optimized by priming from /proc/self/mountinfo). One thing to note is that the test is actually a little biased in favour of the "p" test, where the mnt_id is looked up by path from /proc/fdinfo. That's not all that useful, except as an index into mountfs. I'm not sure how much use it as a check on whether the mount is the same mount or not since mount IDs can get reused. If I instead use the parent_id all round as the desired target value, I then see: For 10000 mounts, f=22899us f2=18240us p=101054us p2=117273us <-- prev email For 10000 mounts, f=24853us f2=20453us p=235581us p2= 59798us <-- parent_id Some observations: (1) fsinfo() gets a bit slower, reflecting the extra locking that must be done to access the topology information (it's using a different attribute). (2) Going via /proc/fdinfo now includes further a access into mountfs - and this makes the access ~2.3x slower than it was before. (3) Going via mount ID directly into mountfs (the "p2" test) appears faster than it did (when it shouldn't have changed), though it's still slower than fsinfo. This I ascribe to the caching of the inode and dentry from the "p" test. The attached patch adjusts the test program. David --- commit e9844e27f3061e4ef2d1511786b5ea60338dc610 Author: David Howells <dhowells@xxxxxxxxxx> Date: Tue Mar 31 21:14:58 2020 +0100 Get parent ID instead diff --git a/samples/vfs/test-fsinfo-perf.c b/samples/vfs/test-fsinfo-perf.c index fba40737f768..2bcde06ee78b 100644 --- a/samples/vfs/test-fsinfo-perf.c +++ b/samples/vfs/test-fsinfo-perf.c @@ -69,27 +69,27 @@ static void do_umount(void) perror("umount"); } -static unsigned long sum_mnt_id; +static unsigned long sum_check, sum_check_2; -static void get_mntid_by_fsinfo(int ix, const char *path) +static void get_id_by_fsinfo(int ix, const char *path) { - struct fsinfo_mount_info r; + struct fsinfo_mount_topology r; struct fsinfo_params params = { .flags = FSINFO_FLAGS_QUERY_PATH, - .request = FSINFO_ATTR_MOUNT_INFO, + .request = FSINFO_ATTR_MOUNT_TOPOLOGY, }; ERR(fsinfo(AT_FDCWD, path, ¶ms, sizeof(params), &r, sizeof(r)), "fsinfo"); - //printf("[%u] %u\n", ix, r.mnt_id); - sum_mnt_id += r.mnt_id; + sum_check += r.parent_id; + sum_check_2 += r.mnt_topology_changes; } -static void get_mntid_by_proc(int ix, const char *path) +static void get_id_by_proc(int ix, const char *path) { - unsigned int mnt_id; + unsigned int mnt_id, x; ssize_t len; - char procfile[100], buffer[4096], *p, *nl; + char procfile[100], buffer[4096], *p, *q, *nl; int fd, fd2; fd = open(path, O_PATH); @@ -130,12 +130,31 @@ static void get_mntid_by_proc(int ix, const char *path) exit(3); } - sum_mnt_id += mnt_id; - //printf("[%u] %u\n", ix, mnt_id); + /* Now look the ID up on mountfs */ + sprintf(procfile, "/mnt/%u/parent", mnt_id); + fd = open(procfile, O_RDONLY); + ERR(fd, procfile); + len = read(fd, buffer, sizeof(buffer) - 1); + ERR(len, "read/parent"); + close(fd); + if (len > 0 && buffer[len - 1] == '\n') + len--; + buffer[len] = 0; + + x = strtoul(buffer, &q, 10); + + if (*q) { + fprintf(stderr, "Bad format in %s '%s'\n", procfile, buffer); + exit(3); + } + + sum_check += x; + //printf("[%u] %u\n", ix, x); } -static void get_mntid_by_fsinfo_2(void) +static void get_id_by_fsinfo_2(void) { + struct fsinfo_mount_topology t; struct fsinfo_mount_child *children, *c, *end; struct fsinfo_mount_info r; struct fsinfo_params params = { @@ -171,15 +190,16 @@ static void get_mntid_by_fsinfo_2(void) for (i = 0; c < end; c++, i++) { //printf("[%u] %u\n", i, c->mnt_id); params.flags = FSINFO_FLAGS_QUERY_MOUNT; - params.request = FSINFO_ATTR_MOUNT_INFO; + params.request = FSINFO_ATTR_MOUNT_TOPOLOGY; sprintf(name, "%u", c->mnt_id); - ERR(fsinfo(AT_FDCWD, name, ¶ms, sizeof(params), &r, sizeof(r)), + ERR(fsinfo(AT_FDCWD, name, ¶ms, sizeof(params), &t, sizeof(t)), "fsinfo/child"); - sum_mnt_id += r.mnt_id; + sum_check += t.parent_id; + sum_check_2 += t.mnt_topology_changes; } } -static void get_mntid_by_mountfs(void) +static void get_id_by_mountfs(void) { unsigned int base_mnt_id, mnt_id, x; ssize_t len, s_children; @@ -260,11 +280,11 @@ static void get_mntid_by_mountfs(void) comma++; } - sprintf(procfile, "%u/id", mnt_id); + sprintf(procfile, "%u/parent", mnt_id); fd = openat(mntfd, procfile, O_RDONLY); ERR(fd, procfile); len = read(fd, buffer, sizeof(buffer) - 1); - ERR(len, "read/id"); + ERR(len, "read/parent"); close(fd); if (len > 0 && buffer[len - 1] == '\n') len--; @@ -278,7 +298,7 @@ static void get_mntid_by_mountfs(void) } if (0) printf("[%u] %u\n", i++, x); - sum_mnt_id += x; + sum_check += x; } while (p = comma, *comma); } @@ -318,32 +338,32 @@ int main(int argc, char **argv) iterate(make_mount); printf("--- test fsinfo by path ---\n"); - sum_mnt_id = 0; + sum_check = 0; ERR(gettimeofday(&f_before, NULL), "gettimeofday"); - iterate(get_mntid_by_fsinfo); + iterate(get_id_by_fsinfo); ERR(gettimeofday(&f_after, NULL), "gettimeofday"); - printf("sum(mnt_id) = %lu\n", sum_mnt_id); + printf("sum(mnt_id) = %lu\n", sum_check); printf("--- test fsinfo by mnt_id ---\n"); - sum_mnt_id = 0; + sum_check = 0; ERR(gettimeofday(&f2_before, NULL), "gettimeofday"); - get_mntid_by_fsinfo_2(); + get_id_by_fsinfo_2(); ERR(gettimeofday(&f2_after, NULL), "gettimeofday"); - printf("sum(mnt_id) = %lu\n", sum_mnt_id); + printf("sum(mnt_id) = %lu\n", sum_check); printf("--- test /proc/fdinfo ---\n"); - sum_mnt_id = 0; + sum_check = 0; ERR(gettimeofday(&p_before, NULL), "gettimeofday"); - iterate(get_mntid_by_proc); + iterate(get_id_by_proc); ERR(gettimeofday(&p_after, NULL), "gettimeofday"); - printf("sum(mnt_id) = %lu\n", sum_mnt_id); + printf("sum(mnt_id) = %lu\n", sum_check); printf("--- test mountfs ---\n"); - sum_mnt_id = 0; + sum_check = 0; ERR(gettimeofday(&p2_before, NULL), "gettimeofday"); - get_mntid_by_mountfs(); + get_id_by_mountfs(); ERR(gettimeofday(&p2_after, NULL), "gettimeofday"); - printf("sum(mnt_id) = %lu\n", sum_mnt_id); + printf("sum(mnt_id) = %lu\n", sum_check); f_dur = duration(&f_before, &f_after); f2_dur = duration(&f2_before, &f2_after);