summaryrefslogtreecommitdiff
path: root/msg.c
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2008-09-15 20:58:43 -0700
committerDan Williams <dan.j.williams@intel.com>2008-09-15 20:58:43 -0700
commit313a4a82f130e6668ba0f4550200662e168aa945 (patch)
tree56f6b17ba26b00684153bbbc976dd1c1f825b122 /msg.c
parent4795982e68f72ef44bd29c9883e5f6291088a3e1 (diff)
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.c33
1 files changed, 29 insertions, 4 deletions
diff --git a/msg.c b/msg.c
index 013bcb99..5a4839fa 100644
--- a/msg.c
+++ b/msg.c
@@ -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;
+}