close(lfd);
return 1;
}
+ if (tst->ss->external) {
+ /*
+ * Before dropping our exclusive open we make an
+ * attempt at preventing mdmon from seeing an
+ * 'add' event before reconciling this 'remove'
+ * event.
+ */
+ char *name = devnum2devname(fd2devnum(fd));
+
+ if (!name) {
+ fprintf(stderr, Name ": unable to get container name\n");
+ return 1;
+ }
+
+ ping_manager(name);
+ free(name);
+ }
close(lfd);
if (verbose >= 0)
fprintf(stderr, Name ": hot removed %s\n",
* These need to be remove from, or added to, the array
*/
mdi = sysfs_read(-1, mdstat->devnum, GET_DEVS);
- if (!mdi)
+ if (!mdi) {
+ /* invalidate the current count so we can try again */
+ container->devcnt = -1;
return;
+ }
/* check for removals */
for (cdp = &container->devs; *cdp; ) {
struct metadata_update *mu;
- if (msg->len == 0) {
- int cnt;
-
+ if (msg->len <= 0)
while (update_queue_pending || update_queue) {
check_update_queue(container);
usleep(15*1000);
}
+ if (msg->len == 0) { /* ping_monitor */
+ int cnt;
+
cnt = monitor_loop_cnt;
if (cnt & 1)
cnt += 2; /* wait until next pselect */
while (monitor_loop_cnt - cnt < 0)
usleep(10 * 1000);
+ } else if (msg->len == -1) { /* ping_manager */
+ struct mdstat_ent *mdstat = mdstat_read(1, 0);
+
+ manage(mdstat, container);
+ free_mdstat(mdstat);
} else {
mu = malloc(sizeof(*mu));
mu->len = msg->len;
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);
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);
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;
return sfd;
}
+/* give the monitor a chance to update the metadata */
int ping_monitor(char *devname)
{
int sfd = connect_monitor(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;
+}
extern int wait_reply(int fd, int tmo);
extern int connect_monitor(char *devname);
extern int ping_monitor(char *devname);
+extern int ping_manager(char *devname);
#define MSG_MAX_LEN (4*1024*1024)