diff options
author | Dan Williams <dan.j.williams@intel.com> | 2008-09-16 05:58:43 +0200 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2008-09-16 05:58:43 +0200 |
commit | 313a4a82f130e6668ba0f4550200662e168aa945 (patch) | |
tree | 56f6b17ba26b00684153bbbc976dd1c1f825b122 /msg.c | |
parent | sysfs: detect disks that are in the process of being removed (diff) | |
download | mdadm-313a4a82f130e6668ba0f4550200662e168aa945.tar.xz mdadm-313a4a82f130e6668ba0f4550200662e168aa945.zip |
ping_manager() to prevent 'add' before 'remove' completes
It is currently possible to remove a device and re-add it without the
manager noticing, i.e. without detecting a mdstat->devcnt
container->devcnt mismatch. Introduce ping_manager() to arrange for
mdmon to run manage_container() prior to mdadm dropping the exclusive
open() on the container. Despite these precautions sysfs_read() may
still fail. If this happens invalidate container->devcnt to ensure
manage_container() runs at the next event.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'msg.c')
-rw-r--r-- | msg.c | 33 |
1 files changed, 29 insertions, 4 deletions
@@ -81,12 +81,12 @@ static int recv_buf(int fd, void* buf, int len, int tmo) int send_message(int fd, struct metadata_update *msg, int tmo) { - __u32 len = msg->len; + __s32 len = msg->len; int rv; rv = send_buf(fd, &start_magic, 4, tmo); rv = rv ?: send_buf(fd, &len, 4, tmo); - if (len) + if (len > 0) rv = rv ?: send_buf(fd, msg->buf, msg->len, tmo); rv = send_buf(fd, &end_magic, 4, tmo); @@ -96,7 +96,7 @@ int send_message(int fd, struct metadata_update *msg, int tmo) int receive_message(int fd, struct metadata_update *msg, int tmo) { __u32 magic; - __u32 len; + __s32 len; int rv; rv = recv_buf(fd, &magic, 4, tmo); @@ -105,7 +105,7 @@ int receive_message(int fd, struct metadata_update *msg, int tmo) rv = recv_buf(fd, &len, 4, tmo); if (rv < 0 || len > MSG_MAX_LEN) return -1; - if (len) { + if (len > 0) { msg->buf = malloc(len); if (msg->buf == NULL) return -1; @@ -177,6 +177,7 @@ int connect_monitor(char *devname) return sfd; } +/* give the monitor a chance to update the metadata */ int ping_monitor(char *devname) { int sfd = connect_monitor(devname); @@ -196,3 +197,27 @@ int ping_monitor(char *devname) close(sfd); return err; } + +/* give the manager a chance to view the updated container state. This + * would naturally happen due to the manager noticing a change in + * /proc/mdstat; however, pinging encourages this detection to happen + * while an exclusive open() on the container is active + */ +int ping_manager(char *devname) +{ + int sfd = connect_monitor(devname); + struct metadata_update msg = { .len = -1 }; + int err = 0; + + if (sfd < 0) + return sfd; + + err = send_message(sfd, &msg, 20); + + /* check the reply */ + if (!err && wait_reply(sfd, 20) != 0) + err = -1; + + close(sfd); + return err; +} |