summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDoug Ledford <dledford@redhat.com>2010-04-16 15:24:03 -0400
committerDoug Ledford <dledford@redhat.com>2010-04-16 15:24:03 -0400
commitf907ef185bc01d277086aeab2c10c4f2c818815e (patch)
tree44d50fb16055f0af0d01fc0f356c85fa4ef42b2d
parentf13d2c5adf133a4963ed38a3dc85aa035cf88bcf (diff)
downloadmdadm-f907ef185bc01d277086aeab2c10c4f2c818815e.tar.gz
mdadm-f907ef185bc01d277086aeab2c10c4f2c818815e.tar.xz
mdadm-f907ef185bc01d277086aeab2c10c4f2c818815e.zip
Refactor IncrementalNew into two distinct routines, one for whenever
we might need to repartition a device, and one for when we will be using the block device directly. Signed-off-by: Doug Ledford <dledford@redhat.com>
-rw-r--r--Incremental.c158
-rw-r--r--mdadm.c4
-rw-r--r--mdadm.h2
3 files changed, 110 insertions, 54 deletions
diff --git a/Incremental.c b/Incremental.c
index 5fdf509..ad6be86 100644
--- a/Incremental.c
+++ b/Incremental.c
@@ -35,6 +35,10 @@ static int count_active(struct supertype *st, int mdfd, char **availp,
static void find_reject(int mdfd, struct supertype *st, struct mdinfo *sra,
int number, __u64 events, int verbose,
char *array_name);
+static int IncrementalNewPart(char *devname, int verbose, int export,
+ struct domain_ent *domain);
+static int IncrementalNewDisk(char *devname, int verbose, int export,
+ struct domain_ent *domain);
int Incremental(char *devname, int verbose, int runstop,
struct supertype *st, char *homehost, int require_homehost,
@@ -884,77 +888,129 @@ int IncrementalRemove(char *devname, int verbose)
}
/*
- * IncrementalNewDisk - Check to see if the passed in device belongs to any
- * DOMAIN entries from the config file, and if so, perform the required
- * action.
- *
- * @devname - The device we are supposed to examine. This is a currently
- * non-raid device, decide if we should claim it and if so, perform the
- * required actions.
- *
- * Special note: Due to limitations of the whole hotplug model, any time we
- * have a partitioned device, the bare drive will get called into this
- * function because only the partitions will register as already being raid
- * members, the bare drive itself won't. We need to be smart enough here
- * so that even if we have a DOMAIN line that says partition, that we don't
- * actually do the partitioning if the right partition table is already there.
+ * IncrementalNewPart - We have a partition or a whole disk device, and we
+ * have a domain that says not to partition the device, so we will either
+ * use the whole disk or the partition directly.
*/
-int IncrementalNewDisk(char *devname, int verbose, int export)
+static int IncrementalNewPart(char *devname, int verbose, int export,
+ struct domain_ent *domain)
{
- struct stat stb;
struct mdstat_ent *mdstat, *md;
struct domain_ent *domain;
int dfd;
- domain = conf_get_domain(devname);
- if (!domain)
- return 0;
- if (action(domain) <= incremental)
- /* Nothing to do. We only get called in the case that there
- * is no current superblock on the device in question, and
- * since our matching domain says we should either ignore or
- * use devices incrementally, they have to already have a
- * superblock. Since we don't, we're done.
- */
- return 0;
- if (action(domain) != partition &&
- (mdstat = arrays_in_domain(devname, domain)) == NULL) {
- /* As a technical design decision, we *must* have at least one
- * array in our domain that we can add this device to or else
- * we simply can't do anything with this device.
- */
- printf("No arrays found in domain!\n");
- return 1;
- }
+ mdstat = arrays_in_domain(devname, domain);
+ for (md = mdstat; md; md = md->next)
+ printf(Name ": %s\n", md->dev);
/* We've finished with the easy tests that allow us to kick drives
* out without touching actual physical media, now we need to start
* the slower checks.
*/
- dfd = dev_open(devname, O_RDONLY|O_EXCL);
- if (dfd < 0) {
- fprintf(stderr, Name ": cannot open %s: %s.\n",
- devname, strerror(errno));
+ dfd = dev_open_check(devname, O_RDONLY|O_EXCL);
+ if (dfd < 0)
return 1;
- }
- if (fstat(dfd, &stb) < 0) {
- fprintf(stderr, Name ": fstat failed for %s: %s.\n",
- devname, strerror(errno));
- close(dfd);
- return 1;
- }
- if ((stb.st_mode & S_IFMT) != S_IFBLK) {
- fprintf(stderr, Name ": %s is not a block device.\n", devname);
+ if (guess_super(dfd) != NULL) {
+ /* This won't happen with our udev rules, but someone might
+ * try this by hand, make them use normal incremental mode
+ * instead if the device has a superblock already */
+ fprintf(stderr, Name ": superblock present on %s.\n", devname);
close(dfd);
return 1;
}
+ /*
+ * OK, at this point we have a valid block device without a
+ * superblock. If we aren't in force mode, then don't use the
+ * device unless it's "clean", meaning no filesystems, no lvm,
+ * no anything. The requirement here is that both the first and
+ * last 4k of the device must be one of three patterns: 0x00, 0x5a,
+ * or 0xff.
+ */
+
+ return 0;
+}
+
+/*
+ * IncrementalNewDisk - We have a whole disk device, and we have a domain
+ * that says to partition the disk. However, we will get called whether
+ * the partition is the correct partition or not, so we need to skip devs
+ * that already have the right partition and partition bare devs or
+ * repartition devs with stuff already on them only if the force option
+ * is present on our domain.
+ */
+static int IncrementalNewDisk(char *devname, int verbose, int export,
+ struct domain_ent *domain)
+{
+ struct mdstat_ent *mdstat, *md;
+ struct domain_ent *domain;
+ int dfd;
+ dfd = dev_open_check(devname, O_RDONLY|O_EXCL);
+ if (dfd < 0)
+ return 1;
if (guess_super(dfd) != NULL) {
+ /* This won't happen with our udev rules, but someone might
+ * try this by hand, make them use normal incremental mode
+ * instead if the device has a superblock already */
fprintf(stderr, Name ": superblock present on %s.\n", devname);
close(dfd);
return 1;
}
+ /*
+ * OK, at this point we have a valid block device without a
+ * superblock. If we aren't in force mode, then don't use the
+ * device unless it's "clean", meaning no filesystems, no lvm,
+ * no anything. The requirement here is that both the first and
+ * last 4k of the device must be one of three patterns: 0x00, 0x5a,
+ * or 0xff.
+ */
- for (md = mdstat; md; md = md->next)
- printf(Name ": %s\n", md->dev);
return 0;
}
+
+/*
+ * IncrementalNew - We've got a device that doesn't appear to have any
+ * current existing raid superblock on it, check to see if we should be
+ * claiming it based on DOMAIN entries in the config file.
+ *
+ * @devname - The device to investigate
+ *
+ * Special note: if we have partitioned devices, the whole disk device is
+ * going to get called into this code, we need to detect that the device
+ * is already in use and leave it be, where as if we get a truly new
+ * device we may need to partition it and set it up for the partitions to
+ * be added to various arrays later on in the hot plug process.
+ */
+int IncrementalNew(char *devname, int verbose, int export)
+{
+ struct domain_ent *domain;
+ char *devpath;
+ int rv;
+
+ domain = conf_get_domain(devname);
+ if (!domain)
+ return 0;
+ if (action(domain) <= incremental)
+ /* Nothing to do. We only get called in the case that there
+ * is no current superblock on the device in question, and
+ * since our matching domain says we should either ignore or
+ * use devices incrementally, they have to already have a
+ * superblock. Since we don't, we're done.
+ */
+ return 0;
+ devpath = get_devpath_from_devname(devname);
+ if (strstr(devpath, "part") || action(domain) != partition)
+ /* We are on a partition, not a whole disk, or we are on a
+ * whole disk but we want to use the whole disk instead
+ * of partitioning it */
+ rv = IncrementalNewPart(devname, verbose, export, domain);
+ else
+ /* Only use this if we are dealing with a disk that would
+ * need partitioned. This will get called even when our
+ * disk actually already belongs to all the right arrays
+ * and there is nothing to be done, so only do work here
+ * if we really need to */
+ rv = IncrementalNewDisk(devname, verbose, export, domain);
+ free(devpath);
+ return rv;
+}
+
diff --git a/mdadm.c b/mdadm.c
index 35d1f7d..c6410aa 100644
--- a/mdadm.c
+++ b/mdadm.c
@@ -1563,8 +1563,8 @@ int main(int argc, char *argv[])
if (devmode == 'f')
rv = IncrementalRemove(devlist->devname, verbose-quiet);
else if (new_disk > 0)
- rv = IncrementalNewDisk(devlist->devname, verbose-quiet,
- export);
+ rv = IncrementalNew(devlist->devname, verbose-quiet,
+ export);
else
rv = Incremental(devlist->devname, verbose-quiet,
runstop, ss, homehost,
diff --git a/mdadm.h b/mdadm.h
index 7c037ea..a11cfa8 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -874,7 +874,7 @@ extern int Incremental_container(struct supertype *st, char *devname,
extern void RebuildMap(void);
extern int IncrementalScan(int verbose);
extern int IncrementalRemove(char *devname, int verbose);
-extern int IncrementalNewDisk(char *devname, int verbose, int export);
+extern int IncrementalNew(char *devname, int verbose, int export);
extern int CreateBitmap(char *filename, int force, char uuid[16],
unsigned long chunksize, unsigned long daemon_sleep,
unsigned long write_behind,