[BACK]Return to softraidvar.h CVS log [TXT][DIR] Up to [local] / sys / dev

File: [local] / sys / dev / softraidvar.h (download)

Revision 1.1, Tue Mar 4 16:09:35 2008 UTC (16 years, 1 month ago) by nbrk
Branch point for: MAIN

Initial revision

/* $OpenBSD: softraidvar.h,v 1.32 2007/06/06 23:06:02 deraadt Exp $ */
/*
 * Copyright (c) 2006 Marco Peereboom <marco@peereboom.us>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <dev/biovar.h>

#include <sys/buf.h>
#include <sys/queue.h>
#include <sys/rwlock.h>

#include <scsi/scsi_all.h>
#include <scsi/scsi_disk.h>
#include <scsi/scsiconf.h>

#define DEVNAME(_s)     ((_s)->sc_dev.dv_xname)

/* #define SR_DEBUG */
#ifdef SR_DEBUG
extern u_int32_t		sr_debug;
#define DPRINTF(x...)		do { if (sr_debug) printf(x); } while(0)
#define DNPRINTF(n,x...)	do { if (sr_debug & n) printf(x); } while(0)
#define	SR_D_CMD		0x0001
#define	SR_D_INTR		0x0002
#define	SR_D_MISC		0x0004
#define	SR_D_IOCTL		0x0008
#define	SR_D_CCB		0x0010
#define	SR_D_WU			0x0020
#define	SR_D_META		0x0040
#define	SR_D_DIS		0x0080
#define	SR_D_STATE		0x0100
#else
#define DPRINTF(x...)
#define DNPRINTF(n,x...)
#endif

#define	SR_MAXFER		MAXPHYS
#define	SR_MAX_LD		1
#define	SR_MAX_CMDS		16
#define	SR_MAX_STATES		7

/* forward define to prevent dependency goo */
struct sr_softc;

#define SR_UUID_MAX		4
struct sr_uuid {
	u_int32_t		sui_id[SR_UUID_MAX];
} __packed;

struct sr_ccb {
	struct buf		ccb_buf;	/* MUST BE FIRST!! */

	struct sr_workunit	*ccb_wu;
	struct sr_discipline	*ccb_dis;

	int			ccb_target;
	int			ccb_state;
#define SR_CCB_FREE		0
#define SR_CCB_INPROGRESS	1
#define SR_CCB_OK		2
#define SR_CCB_FAILED		3

	TAILQ_ENTRY(sr_ccb)	ccb_link;
} __packed;

TAILQ_HEAD(sr_ccb_list, sr_ccb);

struct sr_workunit {
	struct scsi_xfer	*swu_xs;
	struct sr_discipline	*swu_dis;

	int			swu_state;
#define SR_WU_FREE		0
#define SR_WU_INPROGRESS	1
#define SR_WU_OK		2
#define SR_WU_FAILED		3
#define SR_WU_PARTIALLYFAILED	4
#define SR_WU_DEFERRED		5
#define SR_WU_PENDING		6
#define SR_WU_RESTART		7
#define SR_WU_REQUEUE		8

	int			swu_fake;	/* faked wu */
	/* workunit io range */
	daddr64_t		swu_blk_start;
	daddr64_t		swu_blk_end;

	/* in flight totals */
	u_int32_t		swu_ios_complete;
	u_int32_t		swu_ios_failed;
	u_int32_t		swu_ios_succeeded;

	/* number of ios that makes up the whole work unit */
	u_int32_t		swu_io_count;

	/* colliding wu */
	struct sr_workunit	*swu_collider;

	/* all ios that make up this workunit */
	struct sr_ccb_list	swu_ccb;

	TAILQ_ENTRY(sr_workunit) swu_link;
};

TAILQ_HEAD(sr_wu_list, sr_workunit);

/* RAID 1 */
#define SR_RAID1_NOWU		16
struct sr_raid1 {
	u_int32_t		sr1_counter;
};

/* RAID C */
#define SR_RAIDC_NOWU		16
struct sr_raidc {
	u_int64_t		src_sid;
	char			src_key[64];
};

#define SR_META_SIZE		32	/* save space at chunk beginning */
#define SR_META_OFFSET		16	/* skip 8192 bytes 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 & ssd_checksum */
	u_int64_t		ssd_magic;	/* magic id */
#define	SR_MAGIC		0x4d4152436372616dLLU
	u_int8_t		ssd_version;	/* meta data version */
	u_int8_t		ssd_pad1[3];
	u_int32_t		ssd_flags;	/* flags */

	/* meta-data */
	u_int32_t		ssd_checksum;	/* xor of the structure */
	u_int32_t		ssd_size;	/* sizeof(sr_metadata) */
	u_int32_t		ssd_ondisk;	/* on disk version counter */
	u_int32_t		ssd_pad2;
	struct sr_uuid		ssd_uuid;	/* unique identifier */

	/* virtual disk data */
	u_int32_t		ssd_vd_ver;	/* vd structure version */
	u_int32_t		ssd_vd_size;	/* vd structure size */
	u_int32_t		ssd_vd_volid;	/* volume id */
	u_int32_t		ssd_vd_chk;	/* vd structure xor */

	/* chunk data */
	u_int32_t		ssd_chunk_ver;	/* chunk structure version */
	u_int32_t		ssd_chunk_no;	/* number of chunks */
	u_int32_t		ssd_chunk_size;	/* chunk structure size */
	u_int32_t		ssd_chunk_id;	/* chunk identifier */
	u_int32_t		ssd_chunk_chk;	/* chunk structure xor */
	u_int32_t		ssd_pad3;

	/* optional metadata */
	u_int32_t		ssd_opt_ver;	/* optinal meta version */
	u_int32_t		ssd_opt_no;	/* nr of optional md elements */
	u_int32_t		ssd_opt_size;	/* sizeof optional metadata */
	u_int32_t		ssd_opt_chk;	/* optional metadata xor */
} __packed;

struct sr_metadata_list {
	struct sr_metadata	*sml_metadata;
	dev_t			sml_mm;
	int			sml_used;

	SLIST_ENTRY(sr_metadata_list) sml_link;
};

SLIST_HEAD(sr_metadata_list_head, sr_metadata_list);

#define SR_OPT_VERSION		1	/* bump when sr_opt_meta changes */
struct sr_opt_meta {
	u_int32_t		som_type;
	u_int32_t		som_pad;
#define SR_OPT_INVALID		0x00
#define SR_OPT_CRYPTO		0x01
	union {
		struct sr_raidc	smm_crypto;
	}			som_meta;
};

#define SR_CHUNK_VERSION	1	/* bump when sr_chunk_meta changes */
struct sr_chunk_meta {
	u_int32_t		scm_volid;	/* vd we belong to */
	u_int32_t		scm_chunk_id;	/* chunk id */
	u_int32_t		scm_status;	/* use bio bioc_disk status */
	u_int32_t		scm_pad1;
	char			scm_devname[32];/* /dev/XXXXX */
	int64_t			scm_size;	/* size of partition */
	int64_t			scm_coerced_size; /* coerced size of part */
	struct sr_uuid		scm_uuid;	/* unique identifier */
} __packed;

struct sr_chunk {
	struct sr_chunk_meta	src_meta;	/* chunk meta data */

	/* runtime data */
	dev_t			src_dev_mm;	/* major/minor */

	/* helper members before metadata makes it onto the chunk  */
	int			src_meta_ondisk;/* set when meta is on disk */
	char			src_devname[32];
	int64_t			src_size;

	SLIST_ENTRY(sr_chunk)	src_link;
};

SLIST_HEAD(sr_chunk_head, sr_chunk);

#define SR_VOL_VERSION	1	/* bump when sr_vol_meta changes */
struct sr_vol_meta {
	u_int32_t		svm_volid;	/* volume id */
	u_int32_t		svm_status; 	/* use bioc_vol status */
	u_int32_t		svm_flags;	/* flags */
#define	SR_VOL_DIRTY		0x01
	u_int32_t		svm_level;	/* raid level */
	int64_t			svm_size;	/* virtual disk size */
	char			svm_devname[32];/* /dev/XXXXX */
	char			svm_vendor[8];	/* scsi vendor */
	char			svm_product[16];/* scsi product */
	char			svm_revision[4];/* scsi revision */
	u_int32_t		svm_no_chunk;	/* number of chunks */
	struct sr_uuid 		svm_uuid;	/* volume unique identifier */
} __packed;

struct sr_volume {
	struct sr_vol_meta	sv_meta;	/* meta data */

	/* runtime data */
	struct sr_chunk_head	sv_chunk_list;	/* linked list of all chunks */
	struct sr_chunk		**sv_chunks;	/* array to same chunks */

	/* sensors */
	struct ksensor		sv_sensor;
	struct ksensordev	sv_sensordev;
	int			sv_sensor_valid;
};

struct sr_discipline {
	struct sr_softc		*sd_sc;		/* link back to sr softc */
	u_int8_t		sd_type;	/* type of discipline */
#define	SR_MD_RAID0		0
#define	SR_MD_RAID1		1
#define	SR_MD_RAID5		2
#define	SR_MD_CACHE		3
#define	SR_MD_RAIDC		4
	char			sd_name[10];	/* human readable dis name */
	u_int8_t		sd_scsibus;	/* scsibus discipline uses */
	struct scsi_link	sd_link;	/* link to midlayer */

	union {
	    struct sr_raid1	mdd_raid1;
	    struct sr_raidc	mdd_raidc;
	}			sd_dis_specific;/* dis specific members */
#define mds			sd_dis_specific

	/* discipline metadata */
	struct sr_metadata	*sd_meta;	/* in memory copy of metadata */
	u_int32_t		sd_meta_flags;

	int			sd_sync;
	int			sd_must_flush;

	struct device		*sd_scsibus_dev;
	void			(*sd_shutdownhook)(void *);

	/* discipline volume */
	struct sr_volume	sd_vol;		/* volume associated */

	/* discipline resources */
	struct sr_ccb		*sd_ccb;
	struct sr_ccb_list	sd_ccb_freeq;
	u_int32_t		sd_max_ccb_per_wu;

	struct sr_workunit	*sd_wu;		/* all workunits */
	u_int32_t		sd_max_wu;

	struct sr_wu_list	sd_wu_freeq;	/* free wu queue */
	struct sr_wu_list	sd_wu_pendq;	/* pending wu queue */
	struct sr_wu_list	sd_wu_defq;	/* deferred wu queue */

	/* discipline stats */
	int			sd_wu_pending;
	u_int64_t		sd_wu_collisions;

	/* discipline functions */
	int			(*sd_alloc_resources)(struct sr_discipline *);
	int			(*sd_assemble_volume)(void *);
	int			(*sd_bringup_volume)(void *);
	int			(*sd_shutdown_volume)(void *);
	int			(*sd_free_resources)(struct sr_discipline *);
	int			(*sd_quiesce_io)(struct sr_discipline *);
	void			(*sd_set_chunk_state)(struct sr_discipline *,
				    int, int);
	void			(*sd_set_vol_state)(struct sr_discipline *);

	/* SCSI emulation */
	struct scsi_sense_data	sd_scsi_sense;
	int			(*sd_scsi_rw)(struct sr_workunit *);
	int			(*sd_scsi_sync)(struct sr_workunit *);
	int			(*sd_scsi_tur)(struct sr_workunit *);
	int			(*sd_scsi_start_stop)(struct sr_workunit *);
	int			(*sd_scsi_inquiry)(struct sr_workunit *);
	int			(*sd_scsi_read_cap)(struct sr_workunit *);
	int			(*sd_scsi_req_sense)(struct sr_workunit *);
};

struct sr_softc {
	struct device		sc_dev;

	int			(*sc_ioctl)(struct device *, u_long, caddr_t);

	struct rwlock		sc_lock;

	int			sc_sensors_running;
	/*
	 * during scsibus attach this is the discipline that is in use
	 * this variable is protected by sc_lock and splhigh
	 */
	struct sr_discipline	*sc_attach_dis;

	/*
	 * XXX expensive, alternative would be nice but has to be cheap
	 * since the scsibus lookup happens on each IO
	 */
#define SR_MAXSCSIBUS		256
	struct sr_discipline	*sc_dis[SR_MAXSCSIBUS]; /* scsibus is u_int8_t */
};