]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libmount: introduce /run/mount/utab.event
authorKarel Zak <kzak@redhat.com>
Wed, 3 Jan 2024 13:13:28 +0000 (14:13 +0100)
committerKarel Zak <kzak@redhat.com>
Wed, 3 Jan 2024 13:13:28 +0000 (14:13 +0100)
The mnt_monitor_...() API uses /run/mount/utab.lock to monitor utab
changes. The same file is used to control access to the utab file.

The utab can be updated more than once during one mount(8) call, for
example, one update is done in /sbin/mount.nfs and next in mount(8).
This situation triggers two (e.g. inotify) events when monitoring is
based on the lock file.

It seems better to introduce separate file to trigger the event and do
not trigger this event in /sbin/mount.<type> helpers.

References: 477401f0de404aafbc7630f70c2f8b1d670e32f8
Signed-off-by: Karel Zak <kzak@redhat.com>
libmount/src/context.c
libmount/src/monitor.c
libmount/src/mountP.h
libmount/src/tab_update.c

index 93fc3dbdcb6f35bce1e6ec1e66fb508c76ea8cb2..810dd70a3c06f918909c76135cf90b72082bb06d 100644 (file)
@@ -2209,7 +2209,7 @@ int mnt_context_update_tabs(struct libmnt_context *cxt)
 
                if (mnt_update_already_done(cxt->update, cxt->lock)) {
                        DBG(CXT, ul_debugobj(cxt, "don't update: error evaluate or already updated"));
-                       goto end;
+                       goto emit;
                }
        } else if (cxt->helper) {
                DBG(CXT, ul_debugobj(cxt, "don't update: external helper"));
@@ -2225,7 +2225,9 @@ int mnt_context_update_tabs(struct libmnt_context *cxt)
        }
 
        rc = mnt_update_table(cxt->update, cxt->lock);
-
+emit:
+       if (rc == 0 && !mnt_context_within_helper(cxt))
+               mnt_update_emit_event(cxt->update);
 end:
        if (!mnt_context_switch_ns(cxt, ns_old))
                return -MNT_ERR_NAMESPACE;
index f21cf7486e5f779be5f8b936068bf770554033a4..0e08c9eb57abe22e06bb1d1186573a163a9764e7 100644 (file)
@@ -226,18 +226,16 @@ static int userspace_add_watch(struct monitor_entry *me, int *final, int *fd)
        assert(me->path);
 
        /*
-        * libmount uses rename(2) to atomically update utab, monitor
-        * rename changes is too tricky. It seems better to monitor utab
-        * lockfile close.
+        * libmount uses utab.event file to monitor and control utab updates
         */
-       if (asprintf(&filename, "%s.lock", me->path) <= 0) {
+       if (asprintf(&filename, "%s.event", me->path) <= 0) {
                rc = -errno;
                goto done;
        }
 
-       /* try lock file if already exists */
+       /* try event file if already exists */
        errno = 0;
-       wd = inotify_add_watch(me->fd, filename, IN_CLOSE_NOWRITE);
+       wd = inotify_add_watch(me->fd, filename, IN_CLOSE_WRITE);
        if (wd >= 0) {
                DBG(MONITOR, ul_debug(" added inotify watch for %s [fd=%d]", filename, wd));
                rc = 0;
@@ -256,7 +254,7 @@ static int userspace_add_watch(struct monitor_entry *me, int *final, int *fd)
                if (!*filename)
                        break;
 
-               /* try directory where is the lock file */
+               /* try directory where is the event file */
                errno = 0;
                wd = inotify_add_watch(me->fd, filename, IN_CREATE|IN_ISDIR);
                if (wd >= 0) {
@@ -339,10 +337,10 @@ static int userspace_event_verify(struct libmnt_monitor *mn,
                        e = (const struct inotify_event *) p;
                        DBG(MONITOR, ul_debugobj(mn, " inotify event 0x%x [%s]\n", e->mask, e->len ? e->name : ""));
 
-                       if (e->mask & IN_CLOSE_NOWRITE)
+                       if (e->mask & IN_CLOSE_WRITE)
                                status = 1;
                        else {
-                               /* event on lock file */
+                               /* add watch for the event file */
                                userspace_add_watch(me, &status, &fd);
 
                                if (fd != e->wd) {
index 2385e191dbe4cce3482732af6a58f1988b248007..704e940827fd2042fe21722bc30abeb690265b0e 100644 (file)
@@ -663,6 +663,7 @@ extern int mnt_context_apply_fs(struct libmnt_context *cxt, struct libmnt_fs *fs
 extern struct libmnt_optlist *mnt_context_get_optlist(struct libmnt_context *cxt);
 
 /* tab_update.c */
+extern int mnt_update_emit_event(struct libmnt_update *upd);
 extern int mnt_update_set_filename(struct libmnt_update *upd, const char *filename);
 extern int mnt_update_already_done(struct libmnt_update *upd,
                                   struct libmnt_lock *lc);
index 3a27937040e87025e553fb6461e0f61585482aff..67baa8ead4a335f29f6abd9818fbb221ef708426 100644 (file)
@@ -1004,6 +1004,25 @@ done:
        return rc;
 }
 
+int mnt_update_emit_event(struct libmnt_update *upd)
+{
+       char *filename;
+       int fd;
+
+       if (!upd || !upd->filename)
+               return -EINVAL;
+
+       if (asprintf(&filename, "%s.event", upd->filename) <= 0)
+               return -errno;
+
+       fd = open(filename, O_WRONLY|O_CREAT|O_CLOEXEC,
+                           S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH);
+       free(filename);
+       if (fd < 0)
+               return -errno;
+       close(fd);
+       return 0;
+}
 
 #ifdef TEST_PROGRAM