Re: Upcoming: Notifications, FS notifications and fsinfo()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Apr 1, 2020 at 3:58 PM David Howells <dhowells@xxxxxxxxxx> wrote:
>
> David Howells <dhowells@xxxxxxxxxx> wrote:
>
> > > Attached patch applies against readfile patch.
> >
> > But doesn't actually do what Karel asked for.  show_mountinfo() itself does
> > not give you what Karel asked for.

Not sure what you mean.  I think it shows precisely the information
Karel asked for.

>  Plus there's more information you need to
> > add to it.

The mountinfo format is extensible (see
Documentation/filesystems/proc.txt) so for example adding the change
counters would be simple.

> And arguably, it's worse than just reading /proc/mounts.  If you get a
> notification that something changed (ie. you poll /proc/mounts or mount
> notifications gives you an overrun) you now have to read *every*
> /mountfs/*/info file.  That is way more expensive.

fsinfo(2) will never be substantially cheaper than reading and parsing
/mnt/MNT_ID/info.  In fact reading a large part of the mount table
using fsinfo(2) will be substantially slower than parsing
/proc/self/mountinfo (this doesn't actually do the parsing but that
would add a very small amount of overhead):

root@kvm:~# ./test-fsinfo-perf /tmp/a 30000
--- make mounts ---
--- test fsinfo by path ---
sum(mnt_id) = 960000
--- test fsinfo by mnt_id ---
sum(mnt_id) = 960000
--- test /proc/fdinfo ---
sum(mnt_id) = 960000
--- test mountfs ---
sum(mnt_id) = 960000
--- test mountinfo ---
sum(mnt_id) = 960000
For   30000 mounts, f=    154963us f2=    148337us p=   1803699us p2=
  257019us; m=     53996us; p=11.6*f p=12.2*f2 p=7.0*p2 p=33.4*m
--- umount ---

Yes, that's 33 times faster!

Thanks,
Miklos
---
 samples/vfs/test-fsinfo-perf.c |   91 +++++++++++++++++++++++++++++++++++++++--
 1 file changed, 87 insertions(+), 4 deletions(-)

--- a/samples/vfs/test-fsinfo-perf.c
+++ b/samples/vfs/test-fsinfo-perf.c
@@ -339,6 +339,79 @@ static void get_id_by_mountfs(void)
 	} while (p = comma, *comma);
 }
 
+static void get_id_by_mountinfo(void)
+{
+	unsigned int base_mnt_id, mnt_id, x;
+	ssize_t len;
+	char procfile[100], buffer[4096], *p, *nl;
+	int fd, fd2, mntfd;
+
+	/* Start off by reading the mount ID from the base path */
+	fd = open(base_path, O_PATH);
+	ERR(fd, "open/path");
+	sprintf(procfile, "/proc/self/fdinfo/%u", fd);
+	fd2 = open(procfile, O_RDONLY);
+	ERR(fd2, "open/proc");
+	len = read(fd2, buffer, sizeof(buffer) - 1);
+	ERR(len, "read");
+	buffer[len] = 0;
+	close(fd2);
+	close(fd);
+
+	p = buffer;
+	do {
+		nl = strchr(p, '\n');
+		if (nl)
+			*nl++ = '\0';
+		else
+			nl = NULL;
+
+		if (strncmp(p, "mnt_id:", 7) != 0)
+			continue;
+		p += 7;
+		while (isblank(*p))
+			p++;
+		/* Have to allow for extra numbers being added to the line */
+		if (sscanf(p, "%u", &base_mnt_id) != 1) {
+			fprintf(stderr, "Bad format %s\n", procfile);
+			exit(3);
+		}
+		break;
+
+	} while ((p = nl));
+
+	if (!p) {
+		fprintf(stderr, "Missing field %s\n", procfile);
+		exit(3);
+	}
+
+	if (0) printf("[B] %u\n", base_mnt_id);
+
+	mntfd = open("/proc/self/mountinfo", O_RDONLY);
+	ERR(mntfd, "/proc/self/mountinfo");
+
+	while ((len = read(mntfd, buffer, sizeof(buffer)))) {
+		ERR(len, "read/mountinfo");
+
+		for (p = buffer; p < buffer + len; p = nl + 1) {
+			nl = strchr(p, '\n');
+			if (!nl) {
+				fprintf(stderr, "error parsing mountinfo\n");
+				exit(3);
+			}
+			*nl = '\0';
+			if (sscanf(p, "%i %i", &mnt_id, &x) != 2) {
+				fprintf(stderr, "error parsing mountinfo\n");
+				exit(3);
+			}
+			if (x == base_mnt_id)
+				sum_check += x;
+		}
+	}
+
+	close(mntfd);
+}
+
 static unsigned long duration(struct timeval *before, struct timeval *after)
 {
 	unsigned long a, b;
@@ -354,8 +427,9 @@ int main(int argc, char **argv)
 	struct timeval f2_before, f2_after;
 	struct timeval p_before, p_after;
 	struct timeval p2_before, p2_after;
+	struct timeval m_before, m_after;
 	const char *path;
-	unsigned long f_dur, f2_dur, p_dur, p2_dur;
+	unsigned long f_dur, f2_dur, p_dur, p2_dur, m_dur;
 
 	if (argc < 2) {
 		fprintf(stderr, "Format: %s <path> [nr_mounts]\n", argv[0]);
@@ -402,17 +476,26 @@ int main(int argc, char **argv)
 	ERR(gettimeofday(&p2_after, NULL), "gettimeofday");
 	printf("sum(mnt_id) = %lu\n", sum_check);
 
+	printf("--- test mountinfo ---\n");
+	sum_check = 0;
+	ERR(gettimeofday(&m_before, NULL), "gettimeofday");
+	get_id_by_mountinfo();
+	ERR(gettimeofday(&m_after, NULL), "gettimeofday");
+	printf("sum(mnt_id) = %lu\n", sum_check);
+
 	f_dur  = duration(&f_before,  &f_after);
 	f2_dur = duration(&f2_before, &f2_after);
 	p_dur  = duration(&p_before,  &p_after);
 	p2_dur = duration(&p2_before, &p2_after);
+	m_dur  = duration(&m_before,  &m_after);
 	//printf("fsinfo duration %10luus for %d mounts\n", f_dur, nr_mounts);
 	//printf("procfd duration %10luus for %d mounts\n", p_dur, nr_mounts);
 
-	printf("For %7d mounts, f=%10luus f2=%10luus p=%10luus p2=%10luus; p=%.1f*f p=%.1f*f2 p=%.1f*p2\n",
-	       nr_mounts, f_dur, f2_dur, p_dur, p2_dur,
+	printf("For %7d mounts, f=%10luus f2=%10luus p=%10luus p2=%10luus; m=%10luus; p=%.1f*f p=%.1f*f2 p=%.1f*p2 p=%.1f*m\n",
+	       nr_mounts, f_dur, f2_dur, p_dur, p2_dur, m_dur,
 	       (double)p_dur / (double)f_dur,
 	       (double)p_dur / (double)f2_dur,
-	       (double)p_dur / (double)p2_dur);
+	       (double)p_dur / (double)p2_dur,
+	       (double)p_dur / (double)m_dur);
 	return 0;
 }

[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux