Monitoring mount point changes through / proc / mounts

According to the proc manual, you can track mount point changes on a linux system by opening "/ proc / mounts" and adding a file descriptor for reading fd_set to select() .

The following code snippet works on Ubuntu 9.04, not Ubuntu 10.04 (with the Linux kernel 2.6.32):

 int mfd = open("/proc/mounts", O_RDONLY, 0); fd_set rfds; struct timeval tv; int rv; FD_ZERO(&rfds); FD_SET(mfd, &rfds); tv.tv_sec = 5; tv.tv_usec = 0; int changes = 0; while ((rv = select(mfd+1, &rfds, NULL, NULL, &tv)) >= 0) { if (FD_ISSET(mfd, &rfds)) { fprintf(stdout, "Mount points changed. %d.\n", changes++); } FD_ZERO(&rfds); FD_SET(mfd, &rfds); tv.tv_sec = 5; tv.tv_usec = 0; if (changes > 10) { exit(EXIT_FAILURE); } } 

Compiled snippet.

The file descriptor is always read on one machine, and therefore it continues to pop up in the selected call. There are even no changes to the mounts.

Did I miss something?

Thanks in advance for your help!

man 5 proc:

/ proc / [pid] / mounts (since Linux 2.4.19)

This is a list of all file systems that are currently installed in the mount mount namespace. The format of this file is documented in fstab (5). Starting with version 2.6.15, this file is infected: after opening the file for reading, changing this file (i.e. mounting or disconnecting the file system) causes selection (2) to mark the file descriptor as readable, and poll (2) and epoll_wait ( 2) note that the file has an error condition.

+8
c linux filesystems mount procfs
source share
4 answers

There was a bugfix in the Linux kernel describing this behavior:

SUSv3 says: "Regular files should always poll TRUE for reading and writing." http://www.opengroup.org/onlinepubs/009695399/functions/poll.html

So you should use a poll with POLLPRI | Flags POLLERR. Something like that:

 int mfd = open("/proc/mounts", O_RDONLY, 0); struct pollfd pfd; int rv; int changes = 0; pfd.fd = mfd; pfd.events = POLLERR | POLLPRI; pfd.revents = 0; while ((rv = poll(&pfd, 1, 5)) >= 0) { if (pfd.revents & POLLERR) { fprintf(stdout, "Mount points changed. %d.\n", changes++); } pfd.revents = 0; if (changes > 10) { exit(EXIT_FAILURE); } }
int mfd = open("/proc/mounts", O_RDONLY, 0); struct pollfd pfd; int rv; int changes = 0; pfd.fd = mfd; pfd.events = POLLERR | POLLPRI; pfd.revents = 0; while ((rv = poll(&pfd, 1, 5)) >= 0) { if (pfd.revents & POLLERR) { fprintf(stdout, "Mount points changed. %d.\n", changes++); } pfd.revents = 0; if (changes > 10) { exit(EXIT_FAILURE); } } 
+12
source share

Invalid documentation that you pointed to. To wait for mount changes using select() , the file handle /proc/mounts or /proc/pid/mounts must be set to exceptfds, not readfds. Just replace the 2nd and 4th arguments in your program. File descriptors associated with regular files are required for POSIX to always read.

+4
source share

In addition to the main example posted to the question, here is another example using the GLib and GIO libraries to listen for mount changes by monitoring /proc/self/mountinfo :

 /* Compile with: * gcc -g -O0 `pkg-config --cflags --libs gio-2.0` -o test test.c */ #include <glib.h> #include <gio/gio.h> static gboolean proc_mounts_changed (GIOChannel *channel, GIOCondition cond, gpointer user_data) { if (cond & G_IO_ERR) { g_message ("MOUNTS CHANGED!"); } return TRUE; } int main (int argc, char *argv[]) { GIOChannel *proc_mounts_channel; GSource *proc_mounts_watch_source; GError *error = NULL; GMainLoop *loop; proc_mounts_channel = g_io_channel_new_file ("/proc/self/mountinfo", "r", &error); if (proc_mounts_channel == NULL) { g_warning ("Error creating IO channel for %s: %s (%s, %d)", "/proc/self/mountinfo", error->message, g_quark_to_string (error->domain), error->code); g_error_free (error); return error->code; } proc_mounts_watch_source = g_io_create_watch (proc_mounts_channel, G_IO_ERR); g_source_set_callback (proc_mounts_watch_source, (GSourceFunc) proc_mounts_changed, NULL, NULL); g_source_attach (proc_mounts_watch_source, g_main_context_get_thread_default ()); g_source_unref (proc_mounts_watch_source); g_io_channel_unref (proc_mounts_channel); loop = g_main_loop_new (NULL, FALSE); /* Run the main loop, program can be ended with CTRL+C */ g_main_loop_run (loop); g_main_loop_unref (loop); return 0; } 
+1
source share

If you do

 ls -l /proc/mounts 

You will see that time keeps changing, which means that mount data is constantly being updated, although little has changed. It looks like the current mount monitoring method is not working.

0
source share

All Articles