diff options
author | Scott James Remnant <scott@ubuntu.com> | 2009-03-10 13:00:16 +0000 |
---|---|---|
committer | Scott James Remnant <scott@ubuntu.com> | 2009-03-12 10:02:37 +0000 |
commit | bb38678e3ccc02bcd970ccde3d8166a40edf92d3 (patch) | |
tree | 77c38998c139205350553b38bc727d0790e6bb0d /udev/lib | |
parent | c2c24d4d3c8f83c5f4507bb13ba6c989f9d6ea45 (diff) |
udevadm: settle - synchronise with the udev daemon
There's still a slight race condition when using udevadm settle, if the
udev daemon has a pending inotify event but hasn't yet generated the
"change" uevent for it, the kernel and udev sequence numbers will match
and settle will exit.
Now udevadm settle will send a control message to udevd, which will
respond by sending SIGUSR1 back to the waiting udevadm settle once it
has completed the main loop iteration in which it received the control
message.
If there were no pending inotify events, this will simply wake up the
udev daemon and allow settle to continue. If there are pending inotify
events, they are handled first in the main loop so when settle is
continued they will have been turned into uevents and the kernel
sequence number will have been incremented.
Since the inotify event is pending for udevd when the close() system
call returns (it's queued as part of the kernel handling for that system
call), and since the kernel sequence number is incremented by writing to
the uevent file (as udevd does), this solves the race.
When the settle continues, if there were pending inotify events that
udevd had not read, they are now pending uevents which settle can wait
for.
Signed-off-by: Scott James Remnant <scott@ubuntu.com>
Diffstat (limited to 'udev/lib')
-rw-r--r-- | udev/lib/libudev-ctrl.c | 16 | ||||
-rw-r--r-- | udev/lib/libudev-private.h | 2 |
2 files changed, 18 insertions, 0 deletions
diff --git a/udev/lib/libudev-ctrl.c b/udev/lib/libudev-ctrl.c index 570e91c89e..ca8b845b94 100644 --- a/udev/lib/libudev-ctrl.c +++ b/udev/lib/libudev-ctrl.c @@ -42,6 +42,7 @@ enum udev_ctrl_msg_type { UDEV_CTRL_SET_ENV, UDEV_CTRL_SET_MAX_CHILDS, UDEV_CTRL_SET_MAX_CHILDS_RUNNING, + UDEV_CTRL_SETTLE, }; struct udev_ctrl_msg_wire { @@ -58,6 +59,7 @@ struct udev_ctrl_msg { int refcount; struct udev_ctrl *uctrl; struct udev_ctrl_msg_wire ctrl_msg_wire; + pid_t pid; }; struct udev_ctrl { @@ -196,6 +198,11 @@ int udev_ctrl_send_set_max_childs(struct udev_ctrl *uctrl, int count) return ctrl_send(uctrl, UDEV_CTRL_SET_MAX_CHILDS, count, NULL); } +int udev_ctrl_send_settle(struct udev_ctrl *uctrl) +{ + return ctrl_send(uctrl, UDEV_CTRL_SETTLE, 0, NULL); +} + struct udev_ctrl_msg *udev_ctrl_receive_msg(struct udev_ctrl *uctrl) { struct udev_ctrl_msg *uctrl_msg; @@ -239,6 +246,8 @@ struct udev_ctrl_msg *udev_ctrl_receive_msg(struct udev_ctrl *uctrl) goto err; } + uctrl_msg->pid = cred->pid; + if (uctrl_msg->ctrl_msg_wire.magic != UDEV_CTRL_MAGIC) { err(uctrl->udev, "message magic 0x%08x doesn't match, ignore it\n", uctrl_msg->ctrl_msg_wire.magic); goto err; @@ -311,3 +320,10 @@ int udev_ctrl_get_set_max_childs(struct udev_ctrl_msg *ctrl_msg) return ctrl_msg->ctrl_msg_wire.intval; return -1; } + +pid_t udev_ctrl_get_settle(struct udev_ctrl_msg *ctrl_msg) +{ + if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_SETTLE) + return ctrl_msg->pid; + return -1; +} diff --git a/udev/lib/libudev-private.h b/udev/lib/libudev-private.h index 0627aea071..91e2d5f816 100644 --- a/udev/lib/libudev-private.h +++ b/udev/lib/libudev-private.h @@ -109,6 +109,7 @@ extern int udev_ctrl_send_set_log_level(struct udev_ctrl *uctrl, int priority); extern int udev_ctrl_send_stop_exec_queue(struct udev_ctrl *uctrl); extern int udev_ctrl_send_start_exec_queue(struct udev_ctrl *uctrl); extern int udev_ctrl_send_reload_rules(struct udev_ctrl *uctrl); +extern int udev_ctrl_send_settle(struct udev_ctrl *uctrl); extern int udev_ctrl_send_set_env(struct udev_ctrl *uctrl, const char *key); extern int udev_ctrl_send_set_max_childs(struct udev_ctrl *uctrl, int count); struct udev_ctrl_msg; @@ -120,6 +121,7 @@ extern int udev_ctrl_get_set_log_level(struct udev_ctrl_msg *ctrl_msg); extern int udev_ctrl_get_stop_exec_queue(struct udev_ctrl_msg *ctrl_msg); extern int udev_ctrl_get_start_exec_queue(struct udev_ctrl_msg *ctrl_msg); extern int udev_ctrl_get_reload_rules(struct udev_ctrl_msg *ctrl_msg); +extern pid_t udev_ctrl_get_settle(struct udev_ctrl_msg *ctrl_msg); extern const char *udev_ctrl_get_set_env(struct udev_ctrl_msg *ctrl_msg); extern int udev_ctrl_get_set_max_childs(struct udev_ctrl_msg *ctrl_msg); |