diff options
author | Marco Peereboom <marco@cvs.openbsd.org> | 2007-04-19 02:44:30 +0000 |
---|---|---|
committer | Marco Peereboom <marco@cvs.openbsd.org> | 2007-04-19 02:44:30 +0000 |
commit | b4a19b16f553a38fe0e5b1ed4cd0d335add9458e (patch) | |
tree | d815894a369d29b361e9cb7a54e09920bb72cd66 /sys | |
parent | 45a77b9ce91aee4f88016934413f25ad07ae59ca (diff) |
Add initial metadata write function and hook it up.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/softraid.c | 134 | ||||
-rw-r--r-- | sys/dev/softraidvar.h | 10 |
2 files changed, 134 insertions, 10 deletions
diff --git a/sys/dev/softraid.c b/sys/dev/softraid.c index eaaf8a58cc8..f31841299d1 100644 --- a/sys/dev/softraid.c +++ b/sys/dev/softraid.c @@ -1,4 +1,4 @@ -/* $OpenBSD: softraid.c,v 1.23 2007/04/19 02:36:56 marco Exp $ */ +/* $OpenBSD: softraid.c,v 1.24 2007/04/19 02:44:29 marco Exp $ */ /* * Copyright (c) 2007 Marco Peereboom <marco@peereboom.us> * @@ -120,6 +120,11 @@ void sr_raid1_set_chunk_state(struct sr_discipline *, void sr_raid1_set_vol_state(struct sr_discipline *); void sr_raid1_startwu(struct sr_workunit *); +/* utility functions */ +void sr_get_uuid(struct sr_uuid *); +u_int32_t sr_checksum(char *, u_int32_t *, u_int32_t); +int sr_save_metadata(struct sr_discipline *); + struct scsi_adapter sr_switch = { sr_scsi_cmd, sr_minphys, NULL, NULL, sr_scsi_ioctl }; @@ -846,7 +851,8 @@ sr_ioctl_createraid(struct sr_softc *sc, struct bioc_createraid *bc) sc->sc_dis[sd->sd_link.scsibus] = sd; sb = sd->sd_link.scsibus; - rv = 0; + rv = sr_save_metadata(sd); /* save metadata to disk */ + return (rv); unwind: @@ -985,7 +991,7 @@ sr_parse_chunks(struct sr_softc *sc, char *lst, struct sr_chunk_head *cl) /* get partition size */ ss = name[strlen(name) - 1]; ch_entry->src_meta.scm_size = - label.d_partitions[ss - 'a'].p_size - SR_META_FUDGE; + label.d_partitions[ss - 'a'].p_size - SR_META_SIZE; if (ch_entry->src_meta.scm_size <= 0) { printf("%s: %s partition size = 0\n", DEVNAME(sc), name); @@ -1063,6 +1069,10 @@ sr_raid1_alloc_resources(struct sr_discipline *sd) sr_alloc_wu(sd); sr_alloc_ccb(sd); + sd->sd_meta = malloc(SR_META_SIZE * 512 , M_DEVBUF, M_WAITOK); + bzero(sd->sd_meta, SR_META_SIZE * 512); + + rv = 0; return (rv); } @@ -1081,6 +1091,8 @@ sr_raid1_free_resources(struct sr_discipline *sd) sr_free_wu(sd); sr_free_ccb(sd); + free(sd->sd_meta, M_DEVBUF); + rv = 0; return (rv); } @@ -1280,7 +1292,7 @@ sr_raid1_rw(struct sr_workunit *wu) else ios = sd->sd_vol.sv_meta.svm_no_chunk; - blk += SR_META_FUDGE; + blk += SR_META_SIZE; wu->swu_blk_start = blk; wu->swu_blk_end = blk + xs->datalen - 1; @@ -1318,7 +1330,7 @@ sr_raid1_rw(struct sr_workunit *wu) ragain: /* interleave reads */ x = sd->mds.mdd_raid1.sr1_counter++ % - sd->sd_vol.sv_meta.svm_no_chunk; + sd->sd_vol.sv_meta.svm_no_chunk; scp = sd->sd_vol.sv_chunks[x]; switch (scp->src_meta.scm_status) { case BIOC_SDONLINE: @@ -1712,3 +1724,115 @@ die: sd->sd_vol.sv_meta.svm_status = new_state; } + +u_int32_t +sr_checksum(char *s, u_int32_t *p, u_int32_t size) +{ + u_int32_t chk = 0; + int i; + + DNPRINTF(SR_D_MISC, "%s: sr_checksum %p %d\n", s, p, size); + + if (size % sizeof(u_int32_t)) + return (0); /* 0 is failure */ + + for (i = 0; i < size / sizeof(u_int32_t); i++) + chk ^= p[i]; + + return (chk); +} + +void +sr_get_uuid(struct sr_uuid *uuid) +{ + int i; + + for (i = 0; i < SR_UUID_MAX; i++) + uuid->sui_id[i] = arc4random(); +} + +int +sr_save_metadata(struct sr_discipline *sd) +{ + struct sr_softc *sc = sd->sd_sc; + struct sr_metadata *sm = sd->sd_meta; + struct sr_chunk *src; + struct buf b; + int i, rv = 1; + size_t sz = SR_META_SIZE * 512; + + DNPRINTF(SR_D_META, "%s: sr_save_metadata %s\n", + DEVNAME(sc), sd->sd_vol.sv_meta.svm_devname); + + if (sm->ssd_magic == 0) { + /* initial metadata */ + sm->ssd_magic = SR_MAGIC; + sm->ssd_version = SR_META_VERSION; + if (_BYTE_ORDER == _LITTLE_ENDIAN) + sm->ssd_big_endian = 0; + else + sm->ssd_big_endian = 1; + sm->ssd_size = sizeof(struct sr_metadata); + sm->ssd_ondisk = 1; + sr_get_uuid(&sm->ssd_uuid); + + /* volume */ + sm->ssd_vd_ver = SR_VOL_VERSION; + sm->ssd_vd_size = sizeof(struct sr_vol_meta); + + /* chunk */ + sm->ssd_chunk_ver = SR_CHUNK_VERSION; + sm->ssd_chunk_size = sizeof(struct sr_chunk_meta); + sm->ssd_chunk_no = sd->sd_vol.sv_meta.svm_no_chunk; + } + +#ifdef SR_DEBUG + /* metadata */ + DNPRINTF(SR_D_META, "\tmagic 0x%llx\n", sm->ssd_magic); + DNPRINTF(SR_D_META, "\tversion %d\n", sm->ssd_version); + DNPRINTF(SR_D_META, "\tbig endian %d\n", sm->ssd_big_endian); + DNPRINTF(SR_D_META, "\tchecksum 0x%x\n", sm->ssd_checksum); + DNPRINTF(SR_D_META, "\tsize %d\n", sm->ssd_size); + DNPRINTF(SR_D_META, "\ton disk version %u\n", sm->ssd_ondisk); + DNPRINTF(SR_D_META, "\tuuid "); + for (i = 0; i < SR_UUID_MAX; i++) + DNPRINTF(SR_D_META, "%x%s", sm->ssd_uuid.sui_id[i], + i < SR_UUID_MAX - 1 ? ":" : "\n"); +#endif + + for (i = 0; i < sm->ssd_chunk_no; i++) { + memset(&b, 0, sizeof(b)); + + src = sd->sd_vol.sv_chunks[i]; + b.b_flags = B_WRITE; + b.b_blkno = 2; /* skip past mbr and partition table */ + b.b_bcount = sz; + b.b_bufsize = sz; + b.b_resid = sz; + b.b_data = (void *)sm; + b.b_error = 0; + b.b_proc = curproc; + b.b_dev = src->src_dev_mm; + b.b_vp = src->src_dev_vn; + b.b_iodone = NULL; + LIST_INIT(&b.b_dep); + b.b_vp->v_numoutput++; + VOP_STRATEGY(&b); + biowait(&b); + + /* XXX do something smart here */ + if (b.b_flags & B_ERROR) { + printf("%s: %s i/o error on block %d while writing " + "metadata %d\n", DEVNAME(sc), + src->src_meta.scm_devname, b.b_blkno, b.b_error); + goto bad; + } + + DNPRINTF(SR_D_META, "%s: sr_save_metadata written to %s\n", + DEVNAME(sc), src->src_meta.scm_devname); + } + + rv = 0; +bad: + return (rv); +} diff --git a/sys/dev/softraidvar.h b/sys/dev/softraidvar.h index 5d889ffa3f8..7fba3477ae8 100644 --- a/sys/dev/softraidvar.h +++ b/sys/dev/softraidvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: softraidvar.h,v 1.8 2007/04/14 21:28:08 tedu Exp $ */ +/* $OpenBSD: softraidvar.h,v 1.9 2007/04/19 02:44:29 marco Exp $ */ /* * Copyright (c) 2006 Marco Peereboom <sro@peereboom.us> * @@ -113,10 +113,7 @@ struct sr_workunit { TAILQ_HEAD(sr_wu_list, sr_workunit); -#define SR_META_PD 1 /* only 1 PD per metadata block */ -#define SR_META_VD 1 /* only 1 VD per metadata block */ -#define SR_META_DATA 1 /* only 1 metadata block per disk */ -#define SR_META_FUDGE 32 /* save space at chunk beginning */ +#define SR_META_SIZE 32 /* save space at chunk beginning */ #define SR_META_VERSION 1 /* bump when sr_metadata changes */ struct sr_metadata { /* do not change order of ssd_magic, ssd_version and ssd_big_endian */ @@ -214,6 +211,9 @@ struct sr_discipline { } sd_dis_specific;/* dis specific members */ #define mds sd_dis_specific + /* discipline metadata */ + struct sr_metadata *sd_meta; /* in memory copy of metadata */ + /* discipline volume */ struct sr_volume sd_vol; /* volume associated */ |