summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/softraid.c89
1 files changed, 49 insertions, 40 deletions
diff --git a/sys/dev/softraid.c b/sys/dev/softraid.c
index f8942494d07..d9308455ba0 100644
--- a/sys/dev/softraid.c
+++ b/sys/dev/softraid.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: softraid.c,v 1.256 2011/11/11 17:26:24 jsing Exp $ */
+/* $OpenBSD: softraid.c,v 1.257 2011/11/13 13:57:43 jsing Exp $ */
/*
* Copyright (c) 2007, 2008, 2009 Marco Peereboom <marco@peereboom.us>
* Copyright (c) 2008 Chris Kuethe <ckuethe@openbsd.org>
@@ -2810,13 +2810,14 @@ int
sr_rebuild_init(struct sr_discipline *sd, dev_t dev, int hotspare)
{
struct sr_softc *sc = sd->sd_sc;
- int rv = EINVAL, part;
- int c, found, open = 0;
- char devname[32];
+ struct sr_chunk *chunk = NULL;
+ struct sr_meta_chunk *meta;
+ struct disklabel label;
struct vnode *vn;
daddr64_t size, csize;
- struct disklabel label;
- struct sr_meta_chunk *old, *new;
+ char devname[32];
+ int rv = EINVAL, open = 0;
+ int cid, i, part, status;
/*
* Attempt to initiate a rebuild onto the specified device.
@@ -2839,34 +2840,36 @@ sr_rebuild_init(struct sr_discipline *sd, dev_t dev, int hotspare)
goto done;
}
- /* find offline chunk */
- for (c = 0, found = -1; c < sd->sd_meta->ssdi.ssd_chunk_no; c++)
- if (sd->sd_vol.sv_chunks[c]->src_meta.scm_status ==
+ /* Find first offline chunk. */
+ for (cid = 0; cid < sd->sd_meta->ssdi.ssd_chunk_no; cid++) {
+ if (sd->sd_vol.sv_chunks[cid]->src_meta.scm_status ==
BIOC_SDOFFLINE) {
- found = c;
- new = &sd->sd_vol.sv_chunks[c]->src_meta;
- csize = new->scmi.scm_coerced_size;
- if (c > 0)
- break; /* roll at least once over the for */
- } else {
- old = &sd->sd_vol.sv_chunks[c]->src_meta;
- if (found != -1)
- break;
+ chunk = sd->sd_vol.sv_chunks[cid];
+ break;
}
- if (found == -1) {
+ }
+ if (chunk == NULL) {
printf("%s: no offline chunks available for rebuild\n",
DEVNAME(sc));
goto done;
}
- /* populate meta entry */
+ /* Get coerced size from another online chunk. */
+ for (i = 0; i < sd->sd_meta->ssdi.ssd_chunk_no; i++) {
+ if (sd->sd_vol.sv_chunks[i]->src_meta.scm_status ==
+ BIOC_SDONLINE) {
+ meta = &sd->sd_vol.sv_chunks[i]->src_meta;
+ csize = meta->scmi.scm_coerced_size;
+ break;
+ }
+ }
+
sr_meta_getdevname(sc, dev, devname, sizeof(devname));
if (bdevvp(dev, &vn)) {
printf("%s:, sr_rebuild_init: can't allocate vnode\n",
DEVNAME(sc));
goto done;
}
-
if (VOP_OPEN(vn, FREAD | FWRITE, NOCRED, curproc)) {
DNPRINTF(SR_D_META,"%s: sr_ioctl_setstate can't "
"open %s\n", DEVNAME(sc), devname);
@@ -2875,7 +2878,7 @@ sr_rebuild_init(struct sr_discipline *sd, dev_t dev, int hotspare)
}
open = 1; /* close dev on error */
- /* get partition */
+ /* Get disklabel and check partition. */
part = DISKPART(dev);
if (VOP_IOCTL(vn, DIOCGDINFO, (caddr_t)&label, FREAD,
NOCRED, curproc)) {
@@ -2890,7 +2893,7 @@ sr_rebuild_init(struct sr_discipline *sd, dev_t dev, int hotspare)
goto done;
}
- /* is partition large enough? */
+ /* Is the partition large enough? */
size = DL_GETPSIZE(&label.d_partitions[part]) - SR_DATA_OFFSET;
if (size < csize) {
printf("%s: partition too small, at least %llu B required\n",
@@ -2900,10 +2903,10 @@ sr_rebuild_init(struct sr_discipline *sd, dev_t dev, int hotspare)
printf("%s: partition too large, wasting %llu B\n",
DEVNAME(sc), (size - csize) << DEV_BSHIFT);
- /* make sure we are not stomping on some other partition */
- c = sr_chunk_in_use(sc, dev);
- if (c != BIOC_SDINVALID && c != BIOC_SDOFFLINE &&
- !(hotspare && c == BIOC_SDHOTSPARE)) {
+ /* Ensure that this chunk is not already in use. */
+ status = sr_chunk_in_use(sc, dev);
+ if (status != BIOC_SDINVALID && status != BIOC_SDOFFLINE &&
+ !(hotspare && status == BIOC_SDHOTSPARE)) {
printf("%s: %s is already in use\n", DEVNAME(sc), devname);
goto done;
}
@@ -2911,21 +2914,27 @@ sr_rebuild_init(struct sr_discipline *sd, dev_t dev, int hotspare)
/* Reset rebuild counter since we rebuilding onto a new chunk. */
sd->sd_meta->ssd_rebuild = 0;
- /* recreate metadata */
open = 0; /* leave dev open from here on out */
- sd->sd_vol.sv_chunks[found]->src_dev_mm = dev;
- sd->sd_vol.sv_chunks[found]->src_vn = vn;
- new->scmi.scm_volid = old->scmi.scm_volid;
- new->scmi.scm_chunk_id = found;
- strlcpy(new->scmi.scm_devname, devname,
- sizeof new->scmi.scm_devname);
- new->scmi.scm_size = size;
- new->scmi.scm_coerced_size = old->scmi.scm_coerced_size;
- bcopy(&old->scmi.scm_uuid, &new->scmi.scm_uuid,
- sizeof new->scmi.scm_uuid);
- sr_checksum(sc, new, &new->scm_checksum,
+
+ /* Fix up chunk. */
+ chunk->src_dev_mm = dev;
+ chunk->src_vn = vn;
+
+ /* Reconstruct metadata. */
+ meta = &chunk->src_meta;
+ meta->scmi.scm_volid = sd->sd_meta->ssdi.ssd_volid;
+ meta->scmi.scm_chunk_id = cid;
+ strlcpy(meta->scmi.scm_devname, devname,
+ sizeof(meta->scmi.scm_devname));
+ meta->scmi.scm_size = size;
+ meta->scmi.scm_coerced_size = csize;
+ bcopy(&sd->sd_meta->ssdi.ssd_uuid, &meta->scmi.scm_uuid,
+ sizeof(meta->scmi.scm_uuid));
+ sr_checksum(sc, meta, &meta->scm_checksum,
sizeof(struct sr_meta_chunk_invariant));
- sd->sd_set_chunk_state(sd, found, BIOC_SDREBUILD);
+
+ sd->sd_set_chunk_state(sd, cid, BIOC_SDREBUILD);
+
if (sr_meta_save(sd, SR_META_DIRTY)) {
printf("%s: could not save metadata to %s\n",
DEVNAME(sc), devname);