summaryrefslogtreecommitdiffstats
path: root/Assemble.c
diff options
context:
space:
mode:
Diffstat (limited to 'Assemble.c')
-rw-r--r--Assemble.c34
1 files changed, 31 insertions, 3 deletions
diff --git a/Assemble.c b/Assemble.c
index cde0fa7..c01a66f 100644
--- a/Assemble.c
+++ b/Assemble.c
@@ -134,7 +134,7 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
int chosen_drive;
int change = 0;
int inargv = 0;
- int start_partial_ok = (runstop >= 0) && (force || devlist==NULL);
+ int start_partial_ok = (runstop >= 0) && (force || devlist==NULL || mdfd < 0);
unsigned int num_devs;
mddev_dev_t tmpdev;
struct mdinfo info;
@@ -293,11 +293,14 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
if (mdfd < 0) {
if (tst == NULL || super == NULL)
continue;
- if (tst->ss->match_home(super, homehost)==0) {
+ if (update == NULL &&
+ tst->ss->match_home(super, homehost)==0) {
if ((inargv && verbose >= 0) || verbose > 0)
fprintf(stderr, Name ": %s is not built for host %s.\n",
devname, homehost);
/* Auto-assemble, and this is not a usable host */
+ /* if update != NULL, we are updating the host
+ * name... */
continue;
}
}
@@ -846,7 +849,32 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
fprintf(stderr, " and %d spare%s", sparecnt, sparecnt==1?"":"s");
fprintf(stderr, ".\n");
}
- if (must_close) close(mdfd);
+ if (must_close) {
+ int usecs = 1;
+ close(mdfd);
+ /* There is a nasty race with 'mdadm --monitor'.
+ * If it opens this device before we close it,
+ * it gets an incomplete open on which IO
+ * doesn't work and the capacity if wrong.
+ * If we reopen (to check for layered devices)
+ * before --monitor closes, we loose.
+ *
+ * So: wait upto 1 second for there to be
+ * a non-zero capacity.
+ */
+ while (usecs < 1000) {
+ mdfd = open(mddev, O_RDONLY);
+ if (mdfd >= 0) {
+ unsigned long size;
+ if (ioctl(mdfd, BLKGETSIZE, &size) == 0 &&
+ size > 0)
+ break;
+ close(mdfd);
+ }
+ usleep(usecs);
+ usecs <<= 1;
+ }
+ }
return 0;
}
fprintf(stderr, Name ": failed to RUN_ARRAY %s: %s\n",