From: Karel Zak Date: Wed, 3 Jan 2024 13:13:28 +0000 (+0100) Subject: libmount: introduce /run/mount/utab.event X-Git-Tag: v2.40-rc1~50^2~2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=544824929a740ed5f8108c752872c7f082f301cf;p=thirdparty%2Futil-linux.git libmount: introduce /run/mount/utab.event 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. helpers. References: 477401f0de404aafbc7630f70c2f8b1d670e32f8 Signed-off-by: Karel Zak --- diff --git a/libmount/src/context.c b/libmount/src/context.c index 93fc3dbdcb..810dd70a3c 100644 --- a/libmount/src/context.c +++ b/libmount/src/context.c @@ -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; diff --git a/libmount/src/monitor.c b/libmount/src/monitor.c index f21cf7486e..0e08c9eb57 100644 --- a/libmount/src/monitor.c +++ b/libmount/src/monitor.c @@ -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) { diff --git a/libmount/src/mountP.h b/libmount/src/mountP.h index 2385e191db..704e940827 100644 --- a/libmount/src/mountP.h +++ b/libmount/src/mountP.h @@ -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); diff --git a/libmount/src/tab_update.c b/libmount/src/tab_update.c index 3a27937040..67baa8ead4 100644 --- a/libmount/src/tab_update.c +++ b/libmount/src/tab_update.c @@ -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