CVSROOT: /cvs/dm Module name: dmraid Changes by: heinzm@xxxxxxxxxxxxxx 2008-06-20 21:52:19 Modified files: . : configure configure.in include/dmraid : display.h dmraid.h format.h lib_context.h list.h locking.h metadata.h misc.h reconfig.h lib : .export.sym version.h lib/activate : activate.c devmapper.c lib/datastruct : byteorder.h lib/device : ata.c ata.h dev-io.h scan.c scsi.c scsi.h lib/display : display.c lib/format : format.c register.h lib/format/ataraid: asr.c asr.h hpt37x.c hpt37x.h hpt45x.c hpt45x.h isw.c isw.h jm.c jm.h lsi.c lsi.h nv.c nv.h pdc.c pdc.h sil.c sil.h via.c via.h lib/format/ddf : ddf1.c ddf1.h ddf1_crc.c ddf1_cvt.c ddf1_cvt.h ddf1_dump.c ddf1_lib.c ddf1_lib.h lib/format/partition: dos.c dos.h lib/format/template: template.c template.h lib/locking : locking.c lib/log : log.c lib/metadata : log_ops.c metadata.c reconfig.c lib/misc : file.c init.c lib_context.c misc.c workaround.c lib/mm : dbg_malloc.c man : dmraid.8 tools : VERSION commands.c commands.h dmraid.c toollib.c toollib.h Log message: Intel Software RAID create/delete/spare/rebuild support Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/configure.diff?cvsroot=dm&r1=1.1&r2=1.2 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/configure.in.diff?cvsroot=dm&r1=1.1&r2=1.2 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/include/dmraid/display.h.diff?cvsroot=dm&r1=1.1&r2=1.2 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/include/dmraid/dmraid.h.diff?cvsroot=dm&r1=1.2&r2=1.3 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/include/dmraid/format.h.diff?cvsroot=dm&r1=1.1&r2=1.2 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/include/dmraid/lib_context.h.diff?cvsroot=dm&r1=1.2&r2=1.3 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/include/dmraid/list.h.diff?cvsroot=dm&r1=1.2&r2=1.3 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/include/dmraid/locking.h.diff?cvsroot=dm&r1=1.1&r2=1.2 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/include/dmraid/metadata.h.diff?cvsroot=dm&r1=1.2&r2=1.3 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/include/dmraid/misc.h.diff?cvsroot=dm&r1=1.1&r2=1.2 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/include/dmraid/reconfig.h.diff?cvsroot=dm&r1=1.1&r2=1.2 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/.export.sym.diff?cvsroot=dm&r1=1.1&r2=1.2 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/version.h.diff?cvsroot=dm&r1=1.5&r2=1.6 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/activate/activate.c.diff?cvsroot=dm&r1=1.3&r2=1.4 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/activate/devmapper.c.diff?cvsroot=dm&r1=1.3&r2=1.4 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/datastruct/byteorder.h.diff?cvsroot=dm&r1=1.1&r2=1.2 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/device/ata.c.diff?cvsroot=dm&r1=1.1&r2=1.2 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/device/ata.h.diff?cvsroot=dm&r1=1.1&r2=1.2 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/device/dev-io.h.diff?cvsroot=dm&r1=1.1&r2=1.2 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/device/scan.c.diff?cvsroot=dm&r1=1.1&r2=1.2 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/device/scsi.c.diff?cvsroot=dm&r1=1.1&r2=1.2 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/device/scsi.h.diff?cvsroot=dm&r1=1.1&r2=1.2 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/display/display.c.diff?cvsroot=dm&r1=1.1&r2=1.2 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/format/format.c.diff?cvsroot=dm&r1=1.4&r2=1.5 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/format/register.h.diff?cvsroot=dm&r1=1.2&r2=1.3 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/format/ataraid/asr.c.diff?cvsroot=dm&r1=1.4&r2=1.5 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/format/ataraid/asr.h.diff?cvsroot=dm&r1=1.2&r2=1.3 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/format/ataraid/hpt37x.c.diff?cvsroot=dm&r1=1.2&r2=1.3 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/format/ataraid/hpt37x.h.diff?cvsroot=dm&r1=1.2&r2=1.3 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/format/ataraid/hpt45x.c.diff?cvsroot=dm&r1=1.2&r2=1.3 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/format/ataraid/hpt45x.h.diff?cvsroot=dm&r1=1.1&r2=1.2 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/format/ataraid/isw.c.diff?cvsroot=dm&r1=1.3&r2=1.4 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/format/ataraid/isw.h.diff?cvsroot=dm&r1=1.1&r2=1.2 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/format/ataraid/jm.c.diff?cvsroot=dm&r1=1.3&r2=1.4 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/format/ataraid/jm.h.diff?cvsroot=dm&r1=1.1&r2=1.2 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/format/ataraid/lsi.c.diff?cvsroot=dm&r1=1.3&r2=1.4 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/format/ataraid/lsi.h.diff?cvsroot=dm&r1=1.2&r2=1.3 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/format/ataraid/nv.c.diff?cvsroot=dm&r1=1.3&r2=1.4 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/format/ataraid/nv.h.diff?cvsroot=dm&r1=1.1&r2=1.2 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/format/ataraid/pdc.c.diff?cvsroot=dm&r1=1.4&r2=1.5 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/format/ataraid/pdc.h.diff?cvsroot=dm&r1=1.2&r2=1.3 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/format/ataraid/sil.c.diff?cvsroot=dm&r1=1.2&r2=1.3 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/format/ataraid/sil.h.diff?cvsroot=dm&r1=1.2&r2=1.3 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/format/ataraid/via.c.diff?cvsroot=dm&r1=1.2&r2=1.3 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/format/ataraid/via.h.diff?cvsroot=dm&r1=1.1&r2=1.2 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/format/ddf/ddf1.c.diff?cvsroot=dm&r1=1.3&r2=1.4 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/format/ddf/ddf1.h.diff?cvsroot=dm&r1=1.1&r2=1.2 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/format/ddf/ddf1_crc.c.diff?cvsroot=dm&r1=1.3&r2=1.4 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/format/ddf/ddf1_cvt.c.diff?cvsroot=dm&r1=1.1&r2=1.2 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/format/ddf/ddf1_cvt.h.diff?cvsroot=dm&r1=1.1&r2=1.2 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/format/ddf/ddf1_dump.c.diff?cvsroot=dm&r1=1.1&r2=1.2 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/format/ddf/ddf1_lib.c.diff?cvsroot=dm&r1=1.2&r2=1.3 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/format/ddf/ddf1_lib.h.diff?cvsroot=dm&r1=1.1&r2=1.2 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/format/partition/dos.c.diff?cvsroot=dm&r1=1.3&r2=1.4 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/format/partition/dos.h.diff?cvsroot=dm&r1=1.1&r2=1.2 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/format/template/template.c.diff?cvsroot=dm&r1=1.1&r2=1.2 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/format/template/template.h.diff?cvsroot=dm&r1=1.1&r2=1.2 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/locking/locking.c.diff?cvsroot=dm&r1=1.2&r2=1.3 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/log/log.c.diff?cvsroot=dm&r1=1.1&r2=1.2 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/metadata/log_ops.c.diff?cvsroot=dm&r1=1.1&r2=1.2 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/metadata/metadata.c.diff?cvsroot=dm&r1=1.4&r2=1.5 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/metadata/reconfig.c.diff?cvsroot=dm&r1=1.1&r2=1.2 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/misc/file.c.diff?cvsroot=dm&r1=1.2&r2=1.3 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/misc/init.c.diff?cvsroot=dm&r1=1.1&r2=1.2 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/misc/lib_context.c.diff?cvsroot=dm&r1=1.2&r2=1.3 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/misc/misc.c.diff?cvsroot=dm&r1=1.1&r2=1.2 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/misc/workaround.c.diff?cvsroot=dm&r1=1.1&r2=1.2 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/mm/dbg_malloc.c.diff?cvsroot=dm&r1=1.1&r2=1.2 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/man/dmraid.8.diff?cvsroot=dm&r1=1.2&r2=1.3 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/tools/VERSION.diff?cvsroot=dm&r1=1.5&r2=1.6 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/tools/commands.c.diff?cvsroot=dm&r1=1.2&r2=1.3 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/tools/commands.h.diff?cvsroot=dm&r1=1.2&r2=1.3 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/tools/dmraid.c.diff?cvsroot=dm&r1=1.1&r2=1.2 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/tools/toollib.c.diff?cvsroot=dm&r1=1.1&r2=1.2 http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/tools/toollib.h.diff?cvsroot=dm&r1=1.1&r2=1.2 --- dmraid/configure 2008/02/22 16:50:38 1.1 +++ dmraid/configure 2008/06/20 21:52:15 1.2 @@ -854,8 +854,10 @@ --enable-jobs=NUM Number of jobs to run simultaneously --enable-libselinux Use this to link the tools to libselinux --enable-libsepol Use this to link the tools to libsepol - --enable-mini Use this to create a minimal binrary suitable + --enable-mini Use this to create a minimal binary suitable for early boot environments + --enable-led Use this to enable LED support + --enable-intel_led Use this to enable Intel LED support --disable-native_log Disable native metadata logging. Default is enabled --enable-static_link Use this to link the tools to the dmraid and devmapper libraries statically. Default is dynamic linking @@ -4513,6 +4515,22 @@ DMRAID_MINI=no fi; +# Check whether --enable-led or --disable-led was given. +if test "${enable_led+set}" = set; then + enableval="$enable_led" + DMRAID_LED=$enableval +else + DMRAID_LED=no +fi; + +# Check whether --enable-intel_led or --disable-intel_led was given. +if test "${enable_intel_led+set}" = set; then + enableval="$enable_intel_led" + DMRAID_INTEL_LED=$enableval +else + DMRAID_INTEL_LED=no +fi; + echo $ac_n "checking whether to disable native metadata logging""... $ac_c" 1>&6 # Check whether --enable-native_log or --disable-native_log was given. if test "${enable_native_log+set}" = set; then @@ -4577,6 +4595,14 @@ fi fi +if test x$DMRAID_LED = xyes; then + CFLAGS="$CFLAGS -DDMRAID_LED" +fi + +if test x$DMRAID_INTEL_LED = xyes; then + CFLAGS="$CFLAGS -DDMRAID_LED -DDMRAID_INTEL_LED" +fi + if test x$DEBUG = xyes; then FLAVOUR="${FLAVOUR}debug " fi --- dmraid/configure.in 2008/02/22 16:50:38 1.1 +++ dmraid/configure.in 2008/06/20 21:52:15 1.2 @@ -107,9 +107,15 @@ AC_ARG_ENABLE(libsepol, [ --enable-libsepol Use this to link the tools to libsepol ], LIBSEPOL=$enableval, LIBSEPOL=no) dnl Enables mini binary -AC_ARG_ENABLE(mini, [ --enable-mini Use this to create a minimal binrary suitable +AC_ARG_ENABLE(mini, [ --enable-mini Use this to create a minimal binary suitable for early boot environments], DMRAID_MINI=$enableval, DMRAID_MINI=no) +dnl Enables LED support +AC_ARG_ENABLE(led, [ --enable-led Use this to enable LED support], DMRAID_LED=$enableval, DMRAID_LED=no) + +dnl Enables Intel LED support +AC_ARG_ENABLE(intel_led, [ --enable-intel_led Use this to enable Intel LED support], DMRAID_INTEL_LED=$enableval, DMRAID_INTEL_LED=no) + echo $ac_n "checking whether to disable native metadata logging""... $ac_c" 1>&6 dnl Disable native metadata logging AC_ARG_ENABLE(native_log, [ --disable-native_log Disable native metadata logging. Default is enabled], \ @@ -155,6 +161,14 @@ fi fi +if test x$DMRAID_LED = xyes; then + CFLAGS="$CFLAGS -DDMRAID_LED" +fi + +if test x$DMRAID_INTEL_LED = xyes; then + CFLAGS="$CFLAGS -DDMRAID_LED -DDMRAID_INTEL_LED" +fi + if test x$DEBUG = xyes; then FLAVOUR="${FLAVOUR}debug " fi --- dmraid/include/dmraid/display.h 2008/02/22 16:57:35 1.1 +++ dmraid/include/dmraid/display.h 2008/06/20 21:52:16 1.2 @@ -9,15 +9,15 @@ #define _DISPLAY_H_ enum dev_type { - DEVICE = 0x01, /* ALL devices */ - RAID = 0x02, /* RAID devices */ - NATIVE = 0x04, /* Native metadata of RAID devices */ - SET = 0x08, /* RAID sets */ + DEVICE = 0x01, /* ALL devices */ + RAID = 0x02, /* RAID devices */ + NATIVE = 0x04, /* Native metadata of RAID devices */ + SET = 0x08, /* RAID sets */ }; enum active_type { - D_ALL = 0x01, /* All devices */ - D_ACTIVE = 0x02, /* Active devices only */ + D_ALL = 0x01, /* All devices */ + D_ACTIVE = 0x02, /* Active devices only */ D_INACTIVE = 0x04, /* Inactive devices only */ }; --- dmraid/include/dmraid/dmraid.h 2008/02/22 17:04:35 1.2 +++ dmraid/include/dmraid/dmraid.h 2008/06/20 21:52:16 1.3 @@ -1,7 +1,10 @@ /* - * Copyright (C) 2004,2005 Heinz Mauelshagen, Red Hat GmbH. + * Copyright (C) 2004-2008 Heinz Mauelshagen, Red Hat GmbH. * All rights reserved. * + * Copyright (C) 2007 Intel Corporation. All rights reserved. + * November, 2007 - additions for Create, Delete, Rebuild & Raid 10. + * * See file LICENSE at the top of this source tree for license information. */ @@ -56,7 +59,7 @@ */ extern const char *get_set_type(struct lib_context *lc, void *rs); extern const char *get_set_name(struct lib_context *lc, void *rs); -extern int group_set(struct lib_context *lc, char *name); +extern int group_set(struct lib_context *lc, char **name); extern char *libdmraid_make_table(struct lib_context *lc, struct raid_set *rs); enum activate_type { @@ -65,8 +68,8 @@ }; extern void process_sets(struct lib_context *lc, - int (*func)(struct lib_context *lc, void *rs, int arg), - int arg, enum set_type type); + int (*func) (struct lib_context * lc, void *rs, + int arg), int arg, enum set_type type); extern int change_set(struct lib_context *lc, enum activate_type what, void *rs); --- dmraid/include/dmraid/format.h 2008/02/22 16:57:35 1.1 +++ dmraid/include/dmraid/format.h 2008/06/20 21:52:16 1.2 @@ -1,6 +1,9 @@ /* - * Copyright (C) 2004,2005 Heinz Mauelshagen, Red Hat GmbH. + * Copyright (C) 2004-2008 Heinz Mauelshagen, Red Hat GmbH. * All rights reserved. + * + * Copyright (C) 2007 Intel Corporation. All rights reserved. + * November, 2007 - additions for Create, Delete, Rebuild & Raid 10. * * See file LICENSE at the top of this source tree for license information. */ @@ -40,7 +43,7 @@ struct event_rd { struct raid_set *rs; struct raid_dev *rd; - enum rd_action action; + enum rd_action action; }; /* @@ -51,10 +54,46 @@ */ struct event_handlers { /* Handle IO error */ - int (*io)(struct lib_context *lc, struct event_io *e_io); + int (*io) (struct lib_context * lc, struct event_io * e_io); /* Handle RAID device add/remove. */ - int (*rd)(struct lib_context *lc, struct event_rd *e_rd); + int (*rd) (struct lib_context * lc, struct event_rd * e_rd); +}; + +/* + * Hot-spare search types list: it can be searched locally/globally + */ +enum scope { + t_scope_local = 0x01, + t_scope_global = 0x02 +}; + +/* Metadata Handler commands */ +enum handler_commands { + UPDATE_REBUILD_STATE, + GET_REBUILD_STATE, + GET_REBUILD_DRIVE, + GET_REBUILD_DRIVE_NO, + CHECK_HOT_SPARE, + /* ... */ +}; + +/* Union to return metadata_handler information. */ +struct handler_info { + unsigned short size; + + union { + char *str; + void *ptr; + int8_t i8; + int16_t i16; + int32_t i32; + int64_t i64; + uint8_t u8; + uint16_t u16; + uint32_t u32; + uint64_t u64; + } data; }; /* @@ -69,33 +108,54 @@ /* * Read RAID metadata off a device and unify it. */ - struct raid_dev* (*read)(struct lib_context *lc, struct dev_info* di); + struct raid_dev *(*read) (struct lib_context * lc, + struct dev_info * di); /* * Write RAID metadata to a device deunifying it * or erase ondisk metadata if erase != 0. */ - int (*write)(struct lib_context *lc, struct raid_dev* rd, int erase); + int (*write) (struct lib_context * lc, struct raid_dev * rd, int erase); + + /* + * delete RAID metadata to devices. + */ + int (*delete) (struct lib_context * lc, struct raid_set * rs); + + /* + * create RAID metadata to devices. + */ + int (*create) (struct lib_context * lc, struct raid_set * rs); /* * Group a RAID device into a set. */ - struct raid_set* (*group)(struct lib_context *lc, struct raid_dev *rd); + struct raid_set *(*group) (struct lib_context * lc, + struct raid_dev * rd); /* * Check consistency of the RAID set metadata. */ - int (*check)(struct lib_context *lc, struct raid_set *rs); + int (*check) (struct lib_context * lc, struct raid_set * rs); + + /* Metadata handler. */ + int (*metadata_handler) (struct lib_context * lc, + enum handler_commands command, + struct handler_info * info, void *ptr); /* * Event handlers (eg, I/O error). */ struct event_handlers *events; + /* + * Hot-spare disk search scope + */ + enum scope scope; /* * Display RAID disk metadata native. */ - void (*log)(struct lib_context *lc, struct raid_dev *rd); + void (*log) (struct lib_context * lc, struct raid_dev * rd); }; /* Chain of registered format handlers (needed for library context). */ @@ -113,14 +173,13 @@ */ #define NO_CHECK_RD NULL extern int check_raid_set(struct lib_context *lc, struct raid_set *rs, - unsigned int (*f_devices)(struct raid_dev *rd, - void *context), + unsigned int (*f_devices) (struct raid_dev * rd, + void *context), void *f_devices_context, - int (*f_check)(struct lib_context *lc, - struct raid_set *rs, - struct raid_dev *rd, void *context), - void *f_check_context, - const char *handler); + int (*f_check) (struct lib_context * lc, + struct raid_set * rs, + struct raid_dev * rd, void *context), + void *f_check_context, const char *handler); extern int check_valid_format(struct lib_context *lc, char *fmt); extern int init_raid_set(struct lib_context *lc, struct raid_set *rs, struct raid_dev *rd, unsigned int stride, @@ -135,22 +194,29 @@ uint64_t u64; }; -struct raid_dev *read_raid_dev( - struct lib_context *lc, - struct dev_info *di, - void* (*f_read_metadata)(struct lib_context *lc, struct dev_info *di, - size_t *size, uint64_t *offset, - union read_info *info), - size_t size, uint64_t offset, - void (*f_to_cpu)(void *meta), - int (*f_is_meta)(struct lib_context *lc, struct dev_info *di, - void *meta), - void (*f_file_metadata)(struct lib_context *lc, struct dev_info *di, - void *meta), - int (*f_setup_rd)(struct lib_context *lc, struct raid_dev *rd, - struct dev_info *di, void *meta, - union read_info *info), - const char *handler); +struct raid_dev *read_raid_dev(struct lib_context *lc, + struct dev_info *di, + void *(*f_read_metadata) (struct lib_context * + lc, + struct dev_info * di, + size_t * size, + uint64_t * offset, + union read_info * + info), size_t size, + uint64_t offset, void (*f_to_cpu) (void *meta), + int (*f_is_meta) (struct lib_context * lc, + struct dev_info * di, + void *meta), + void (*f_file_metadata) (struct lib_context * + lc, + struct dev_info * di, + void *meta), + int (*f_setup_rd) (struct lib_context * lc, + struct raid_dev * rd, + struct dev_info * di, + void *meta, + union read_info * info), + const char *handler); extern void *alloc_meta_areas(struct lib_context *lc, struct raid_dev *rd, const char *who, unsigned int n); @@ -158,14 +224,17 @@ size_t size); extern void *alloc_private_and_read(struct lib_context *lc, const char *who, size_t size, char *path, loff_t offset); -extern struct raid_set *join_superset( - struct lib_context *lc, - char *(*f_name)(struct lib_context *lc, struct raid_dev *rd, - unsigned int subset), - void (*f_create)(struct raid_set *super, void *private), - int (*f_set_sort)(struct list_head *pos, struct list_head *new), - struct raid_set *rs, struct raid_dev *rd -); +extern struct raid_set *join_superset(struct lib_context *lc, + char *(*f_name) (struct lib_context * lc, + struct raid_dev * rd, + unsigned int subset), + void (*f_create) (struct raid_set * + super, void *private), + int (*f_set_sort) (struct list_head * + pos, + struct list_head * + new), + struct raid_set *rs, struct raid_dev *rd); extern int register_format_handler(struct lib_context *lc, struct dmraid_format *fmt); extern int write_metadata(struct lib_context *lc, const char *handler, @@ -175,7 +244,7 @@ #define to_disk to_cpu -#define struct_offset(s, member) ((unsigned short) &((struct s *) 0)->member) +#define struct_offset(s, member) ((size_t) &((struct s *) 0)->member) /* Print macros used in log methods. */ --- dmraid/include/dmraid/lib_context.h 2008/04/02 13:35:31 1.2 +++ dmraid/include/dmraid/lib_context.h 2008/06/20 21:52:16 1.3 @@ -1,7 +1,10 @@ /* - * Copyright (C) 2004,2005 Heinz Mauelshagen, Red Hat GmbH. + * Copyright (C) 2004-2008 Heinz Mauelshagen, Red Hat GmbH. * All rights reserved. * + * Copyright (C) 2007 Intel Corporation. All rights reserved. + * November, 2007 - additions for Create, Delete, Rebuild & Raid 10. + * * See file LICENSE at the top of this source tree for license information. */ @@ -13,12 +16,12 @@ #include <dmraid/misc.h> enum lc_lists { - LC_FORMATS = 0, /* Metadata format handlers. */ - LC_DISK_INFOS, /* Disks discovered. */ - LC_RAID_DEVS, /* Raid devices discovered. */ - LC_RAID_SETS, /* Raid sets grouped. */ + LC_FORMATS = 0, /* Metadata format handlers. */ + LC_DISK_INFOS, /* Disks discovered. */ + LC_RAID_DEVS, /* Raid devices discovered. */ + LC_RAID_SETS, /* Raid sets grouped. */ /* Add new lists below here ! */ - LC_LISTS_SIZE, /* Must be the last enumerator. */ + LC_LISTS_SIZE, /* Must be the last enumerator. */ }; /* List access macros. */ @@ -39,8 +42,12 @@ LC_IGNORELOCKING, LC_SEPARATOR, LC_DEVICES, - LC_PARTCHAR, /* Add new options below this one ! */ - LC_OPTIONS_SIZE, /* Must be the last enumerator. */ + LC_PARTCHAR, + LC_CREATE, + LC_REBUILD_SET, + LC_REBUILD_DISK, + LC_HOT_SPARE_SET, /* Add new options below this one ! */ + LC_OPTIONS_SIZE, /* Must be the last enumerator. */ }; /* Options access macros. */ @@ -57,6 +64,9 @@ #define OPT_TEST(lc) (lc_opt(lc, LC_TEST)) #define OPT_VERBOSE(lc) (lc_opt(lc, LC_VERBOSE)) #define OPT_PARTCHAR(lc) (lc_opt(lc, LC_PARTCHAR)) +#define OPT_CREATE(lc) (lc_opt(lc, LC_CREATE)) +#define OPT_HOT_SPARE_SET(lc) (lc_opt(lc, LC_HOT_SPARE_SET)) +#define OPT_REBUILD_DISK(lc) (lc_opt(lc, LC_REBUILD_DISK)) /* Return option value. */ #define OPT_STR(lc, o) (lc->options[o].arg.str) @@ -64,6 +74,8 @@ #define OPT_STR_FORMAT(lc) OPT_STR(lc, LC_FORMAT) #define OPT_STR_SEPARATOR(lc) OPT_STR(lc, LC_SEPARATOR) #define OPT_STR_PARTCHAR(lc) OPT_STR(lc, LC_PARTCHAR) +#define OPT_STR_HOT_SPARE_SET(lc) OPT_STR(lc, LC_HOT_SPARE_SET) +#define OPT_STR_REBUILD_DISK(lc) OPT_STR(lc, LC_REBUILD_DISK) struct lib_version { const char *text; @@ -95,29 +107,116 @@ /* * Lists for: * - * o metadata format handlers the library supports - * o block devices discovered - * o RAID devices discovered - * o RAID sets grouped + * o metadata format handlers the library supports + * o block devices discovered + * o RAID devices discovered + * o RAID sets grouped */ struct list_head lists[LC_LISTS_SIZE]; - char *locking_name; /* Locking mechanism selector. */ - struct locking *lock; /* Resource locking. */ + char *locking_name; /* Locking mechanism selector. */ + struct locking *lock; /* Resource locking. */ - mode_t mode; /* File/directrory create modes. */ + mode_t mode; /* File/directrory create modes. */ struct { const char *error; /* For error mappings. */ } path; }; + +/* Options actions dmraid performs. */ +enum action { + UNDEF = 0x0, + ACTIVATE = 0x1, + DEACTIVATE = 0x2, + FORMAT = 0x4, +#ifndef DMRAID_MINI + BLOCK_DEVICES = 0x8, + COLUMN = 0x10, + DBG = 0x20, + DUMP = 0x40, + DMERASE = 0x80, + GROUP = 0x100, +#endif + HELP = 0x200, +#ifndef DMRAID_MINI + LIST_FORMATS = 0x400, +# ifdef DMRAID_NATIVE_LOG + NATIVE_LOG = 0x800, +# endif +#endif + NOPARTITIONS = 0x1000, +#ifndef DMRAID_MINI + RAID_DEVICES = 0x2000, + RAID_SETS = 0x4000, + TEST = 0x8000, + VERBOSE = 0x10000, + ACTIVE = 0x20000, + INACTIVE = 0x40000, + SEPARATOR = 0x80000, +#endif + VERSION = 0x100000, + IGNORELOCKING = 0x200000, +#ifndef DMRAID_MINI + DEL_SETS = 0x400000, + CREATE = 0x800000, + REBUILD = 0x1000000, + SPARE = 0x2000000, + MEDIA = 0x4000000, + END_REBUILD = 0x8000000, + GET_MEMBERS = 0x10000000, + PARTCHAR = 0x20000000, + +#endif +}; + +/* Arguments allowed ? */ +enum args { + NO_ARGS, + ARGS, +}; + +/* Define which metadata is needed before we can call post functions. */ +enum metadata_need { + M_NONE = 0x00, + M_DEVICE = 0x01, + M_RAID = 0x02, + M_SET = 0x04, +}; + +enum id { + ROOT, + ANY_ID, +}; + +enum lock { + LOCK, + NO_LOCK, +}; + +/* + * Pre and Post functions to perform for an option. + */ +struct prepost { + enum action action; + enum metadata_need metadata; + enum id id; + enum lock lock; + int (*pre) (int arg); + int arg; + int (*post) (struct lib_context * lc, int arg); +}; + + + + extern struct lib_context *alloc_lib_context(char **argv); extern void free_lib_context(struct lib_context *lc); extern int lc_opt(struct lib_context *lc, enum lc_options o); const char *lc_opt_arg(struct lib_context *lc, enum lc_options o); const char *lc_stralloc_opt(struct lib_context *lc, enum lc_options o, - char *arg); + char *arg); const char *lc_strcat_opt(struct lib_context *lc, enum lc_options o, char *arg, const char delim); extern int lc_inc_opt(struct lib_context *lc, int o); --- dmraid/include/dmraid/list.h 2008/02/22 17:04:35 1.2 +++ dmraid/include/dmraid/list.h 2008/06/20 21:52:16 1.3 @@ -1,7 +1,10 @@ /* - * Copyright (C) 2004,2005 Heinz Mauelshagen, Red Hat GmbH. + * Copyright (C) 2004-2008 Heinz Mauelshagen, Red Hat GmbH. * All rights reserved. * + * Copyright (C) 2007 Intel Corporation. All rights reserved. + * November, 2007 - additions for Create, Delete, Rebuild & Raid 10. + * * See file LICENSE at the top of this source tree for license information. */ @@ -23,9 +26,9 @@ #define list_empty(pos) ((pos)->next == pos) -static inline void __list_add(struct list_head *new, - struct list_head *prev, - struct list_head *next) +static inline void +__list_add(struct list_head *new, + struct list_head *prev, struct list_head *next) { next->prev = new; new->next = next; @@ -74,4 +77,10 @@ pos != (head); \ pos = n, n = pos->next) +#define list_for_each_entry_safe(pos, n, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member),\ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ +pos = n, n = list_entry(pos->member.next, typeof(*pos), member)) + #endif --- dmraid/include/dmraid/locking.h 2008/02/22 16:57:35 1.1 +++ dmraid/include/dmraid/locking.h 2008/06/20 21:52:16 1.2 @@ -17,9 +17,9 @@ struct lib_context; struct locking { const char *name; - int (*lock)(struct lib_context *lc, struct resource *res); - void (*unlock)(struct lib_context *lc, struct resource *res); - void *private; /* Private context. */ + int (*lock) (struct lib_context * lc, struct resource * res); + void (*unlock) (struct lib_context * lc, struct resource * res); + void *private; /* Private context. */ }; extern int init_locking(struct lib_context *lc); --- dmraid/include/dmraid/metadata.h 2008/02/22 17:04:35 1.2 +++ dmraid/include/dmraid/metadata.h 2008/06/20 21:52:16 1.3 @@ -1,7 +1,10 @@ /* - * Copyright (C) 2004,2005 Heinz Mauelshagen, Red Hat GmbH. + * Copyright (C) 2004-2008 Heinz Mauelshagen, Red Hat GmbH. * All rights reserved. * + * Copyright (C) 2007 Intel Corporation. All rights reserved. + * November, 2007 - additions for Create, Delete, Rebuild & Raid 10. + * * See file LICENSE at the top of this source tree for license information. */ @@ -15,23 +18,23 @@ * Unified RAID set types. */ enum type { - t_undef = 0x01, - t_group = 0x02, /* To group subsets (eg, Intel Software RAID). */ - t_partition = 0x04, /* FIXME: remove in favour of kpartx ? */ - t_spare = 0x08, - t_linear = 0x10, - t_raid0 = 0x20, - t_raid1 = 0x40, + t_undef = 0x01, + t_group = 0x02, /* To group subsets (eg, Intel Software RAID). */ + t_partition = 0x04, /* FIXME: remove in favour of kpartx ? */ + t_spare = 0x08, + t_linear = 0x10, + t_raid0 = 0x20, + t_raid1 = 0x40, /* * Higher RAID types below not supported (yet) * because of device-mapper constraints. */ - t_raid4 = 0x80, - t_raid5_ls = 0x100, - t_raid5_rs = 0x200, - t_raid5_la = 0x400, - t_raid5_ra = 0x800, - t_raid6 = 0x1000, + t_raid4 = 0x80, + t_raid5_ls = 0x100, + t_raid5_rs = 0x200, + t_raid5_la = 0x400, + t_raid5_ra = 0x800, + t_raid6 = 0x1000, }; /* Check macros for types. */ @@ -64,21 +67,23 @@ * from format specific types to the unified ones above. */ struct types { - unsigned int type; /* Must be long enough for vendor definition. */ - enum type unified_type; + unsigned int type; /* Must be long enough for vendor definition. */ + enum type unified_type; }; /* RAID disk/set status. */ enum status { - s_undef = 0x01, - s_broken = 0x02, /* Completely broken (not accessible). */ - s_inconsistent = 0x04, /* RAID disk/set inconsistent (needs + s_undef = 0x01, + s_broken = 0x02, /* Completely broken (not accessible). */ + s_inconsistent = 0x04, /* RAID disk/set inconsistent (needs synchronization or reconfiguration). */ /* FIXME: is s_nosync sufficient or do I need s_upgrade (eg, NVidia) */ - s_nosync = 0x08, /* RAID disk/set *not* in sync + s_nosync = 0x08, /* RAID disk/set *not* in sync (needs synchronization). */ - s_ok = 0x10, /* Fully operational. */ - s_setup = 0x20, /* Only during RAID setup transition. */ + s_ok = 0x10, /* Fully operational. */ + s_setup = 0x20, /* Only during RAID setup transition. */ + s_init = 0x40, /* RAID set to be created */ + s_config = 0x80, /* RAID set hasn't been configured */ }; /* @@ -104,24 +109,24 @@ /* find_*() function enums */ enum find { - FIND_TOP, /* Search top level RAID sets only. */ - FIND_ALL, /* Decend all RAID set trees. */ + FIND_TOP, /* Search top level RAID sets only. */ + FIND_ALL, /* Decend all RAID set trees. */ }; /* Device information. */ struct dev_info { struct list_head list; /* Global chain of discovered devices. */ - char *path; /* Actual device node path. */ - char *serial; /* ATA/SCSI serial number. */ - uint64_t sectors; /* Device size. */ + char *path; /* Actual device node path. */ + char *serial; /* ATA/SCSI serial number. */ + uint64_t sectors; /* Device size. */ }; /* Metadata areas and size stored on a RAID device. */ struct meta_areas { - uint64_t offset; /* on disk metadata offset in sectors. */ - size_t size; /* on disk metadata size in bytes. */ - void *area; /* pointer to format specific metadata. */ + uint64_t offset; /* on disk metadata offset in sectors. */ + size_t size; /* on disk metadata size in bytes. */ + void *area; /* pointer to format specific metadata. */ }; /* @@ -131,29 +136,29 @@ * exist at the lowest level of a RAID set stack (eg, for RAID10). */ struct raid_dev { - struct list_head list; /* Global chain of RAID devices. */ - struct list_head devs; /* Chain of devices belonging to set. */ + struct list_head list; /* Global chain of RAID devices. */ + struct list_head devs; /* Chain of devices belonging to set. */ - char *name; /* Metadata format handler generated - name of set this device belongs to.*/ + char *name; /* Metadata format handler generated + name of set this device belongs to. */ - struct dev_info *di; /* Pointer to dev_info. */ + struct dev_info *di; /* Pointer to dev_info. */ struct dmraid_format *fmt; /* Format handler for this device. */ - enum status status; /* Status of device. */ - enum type type; /* Type of device. */ + enum status status; /* Status of device. */ + enum type type; /* Type of device. */ - uint64_t offset; /* Data offset on device. */ - uint64_t sectors; /* Length of the segment to map. */ + uint64_t offset; /* Data offset on device. */ + uint64_t sectors; /* Length of the segment to map. */ - unsigned int areas; /* # of metadata areas on the device. */ + unsigned int areas; /* # of metadata areas on the device. */ struct meta_areas *meta_areas; /* Dynamic array of metadata areas. */ /* * For format handler use (eg, to keep references between calls). * * WARNING: non pointer members need to get zeroed before exit, - * because the metadata layer frees private->ptr on cleanup. + * because the metadata layer frees private->ptr on cleanup. */ union { void *ptr; @@ -169,16 +174,16 @@ * Defines RAID attributes for the set as a whole (eg: RAID0, Status). */ enum flags { - f_maximize = 0x01, /* If set, maximize set capacity, + f_maximize = 0x01, /* If set, maximize set capacity, if not set, limit to smallest device. */ - f_partitions = 0x02, /* Set has partitions. */ + f_partitions = 0x02, /* Set has partitions. */ }; #define F_MAXIMIZE(rs) ((rs)->flags & f_maximize) #define F_PARTITIONS(rs) ((rs)->flags & f_partitions) struct raid_set { - struct list_head list; /* Chain of independent sets. */ + struct list_head list; /* Chain of independent sets. */ /* * List of subsets (eg, RAID10) which make up RAID set stacks. @@ -199,12 +204,13 @@ unsigned int total_devs; /* The number of devices expected */ unsigned int found_devs; /* The number of devices found */ - char *name; /* Name of the set. */ + char *name; /* Name of the set. */ - unsigned int stride; /* Stride size. */ - enum type type; /* Unified raid type. */ - enum flags flags; /* Set flags. */ - enum status status; /* Status of set. */ + uint64_t size; /* size of a raid set */ + unsigned int stride; /* Stride size. */ + enum type type; /* Unified raid type. */ + enum flags flags; /* Set flags. */ + enum status status; /* Status of set. */ }; extern struct raid_set *get_raid_set(struct lib_context *lc, @@ -220,29 +226,31 @@ extern struct raid_dev *alloc_raid_dev(struct lib_context *lc, const char *who); extern void free_raid_dev(struct lib_context *lc, struct raid_dev **rd); extern void list_add_sorted(struct lib_context *lc, - struct list_head *to, struct list_head *new, - int (*sort)(struct list_head *pos, - struct list_head *new)); + struct list_head *to, struct list_head *new, + int (*sort) (struct list_head * pos, + struct list_head * new)); extern struct raid_set *alloc_raid_set(struct lib_context *lc, const char *who); extern unsigned int count_sets(struct lib_context *lc, struct list_head *list); extern unsigned int count_devs(struct lib_context *lc, struct raid_set *rs, - enum count_type type); + enum count_type type); extern void free_raid_set(struct lib_context *lc, struct raid_set *rs); -extern struct raid_set *find_set(struct lib_context *lc, struct list_head *list, - const char *name, enum find where); +extern struct raid_set *find_set(struct lib_context *lc, + struct list_head *list, const char *name, + enum find where); extern struct raid_set *find_or_alloc_raid_set(struct lib_context *lc, - char *name, enum find where, - struct raid_dev *rd, - struct list_head *list, - void (*create) (struct raid_set *super, - void *private), - void *private); + char *name, enum find where, + struct raid_dev *rd, + struct list_head *list, + void (*create) (struct raid_set + * super, + void *private), + void *private); #define NO_RD NULL #define NO_LIST NULL #define NO_CREATE NULL #define NO_CREATE_ARG NULL extern const char *get_set_name(struct lib_context *lc, void *rs); -extern int group_set(struct lib_context *lc, char *name); +extern int group_set(struct lib_context *lc, char **name); enum set_type { SETS, @@ -250,8 +258,8 @@ }; extern void process_sets(struct lib_context *lc, - int (*func)(struct lib_context *lc, void *rs, int arg), - int arg, enum set_type type); + int (*func) (struct lib_context * lc, void *rs, + int arg), int arg, enum set_type type); extern int write_set(struct lib_context *lc, void *rs); extern int partitioned_set(struct lib_context *lc, void *rs); extern int base_partitioned_set(struct lib_context *lc, void *rs); @@ -262,10 +270,12 @@ enum compare cmp); extern enum type rd_type(struct types *types, unsigned int type); extern void file_metadata(struct lib_context *lc, const char *handler, - char *path, void *data, size_t size, uint64_t offset); + char *path, void *data, size_t size, uint64_t offset); extern void file_dev_size(struct lib_context *lc, const char *handler, - struct dev_info *di); + struct dev_info *di); extern int write_dev(struct lib_context *lc, struct raid_dev *rd, int erase); extern int erase_metadata(struct lib_context *lc); - +extern int delete_raidsets(struct lib_context *lc); +extern int lib_perform(struct lib_context *lc, enum action action, + struct prepost *p, char **argv); #endif --- dmraid/include/dmraid/misc.h 2008/02/22 16:57:35 1.1 +++ dmraid/include/dmraid/misc.h 2008/06/20 21:52:16 1.2 @@ -1,13 +1,18 @@ /* - * Copyright (C) 2004,2005 Heinz Mauelshagen, Red Hat GmbH. + * Copyright (C) 2004-2005 Heinz Mauelshagen, Red Hat GmbH. * All rights reserved. * + * Copyright (C) 2007 Intel Corporation. All rights reserved. + * November, 2007 - additions for Create, Delete, Rebuild & Raid 10. + * * See file LICENSE at the top of this source tree for license information. */ #ifndef _MISC_H_ #define _MISC_H_ +#define DM_ASSERT(__cond) do { if (!(__cond)) { printf("ASSERT file:%s line:%d fuction:%s cond: %s\n", __FILE__, __LINE__, __FUNCTION__, #__cond); } } while(0); + extern struct lib_context *libdmraid_init(int argc, char **argv); extern void libdmraid_exit(struct lib_context *lc); @@ -16,8 +21,10 @@ extern char *get_basename(struct lib_context *lc, char *str); extern char *get_dirname(struct lib_context *lc, char *str); extern char *remove_white_space(struct lib_context *lc, char *str, size_t len); +extern void remove_tail_space(char *str); extern char *remove_delimiter(char *ptr, char c); extern void add_delimiter(char **ptr, char c); +extern char *replace_delimiter(char *str, char delim, char c); extern int mk_dir(struct lib_context *lc, const char *dir); @@ -31,21 +38,33 @@ extern void free_string(struct lib_context *lc, char **string); extern int p_fmt(struct lib_context *lc, char **string, const char *fmt, ...); -static inline uint64_t round_down(uint64_t what, unsigned int by) +static inline uint64_t +round_down(uint64_t what, unsigned int by) { return what & ~((uint64_t) by - 1); } -static inline uint64_t round_up(uint64_t what, unsigned int by) +static inline uint64_t +round_up(uint64_t what, unsigned int by) { uint64_t t = round_down(what, by); return t == what ? t : t + by; } -static inline uint64_t div_up(uint64_t what, unsigned int by) +static inline uint64_t +div_up(uint64_t what, unsigned int by) { return round_up(what, by) / by; } + +#ifdef DMRAID_LED +/* Definitions for LED support */ +#define LED_OFF 0 +#define LED_REBUILD 1 + +int led(char *rd, int status); +#endif + #endif --- dmraid/include/dmraid/reconfig.h 2008/02/22 17:04:35 1.1 +++ dmraid/include/dmraid/reconfig.h 2008/06/20 21:52:16 1.2 @@ -2,8 +2,8 @@ * Copyright (C) 2006 Darrick Wong, IBM. * All rights reserved. * - * Copyright (C) 2006 Heinz Mauelshagen Red Hat GmbH. - * All rights reserved. + * Copyright (C) 2006-2008 Heinz Mauelshagen Red Hat GmbH. + * All rights reserved. * * See the file LICENSE at the top of this source tree for license information. */ @@ -50,5 +50,9 @@ struct raid_dev *rd); extern void end_log(struct lib_context *lc, struct list_head *log); extern int revert_log(struct lib_context *lc, struct list_head *log); +extern int hot_spare_add(struct lib_context *lc, struct raid_set *rs); +extern struct raid_set *find_group(struct lib_context *lc, + struct raid_set *sub_rs); +extern int rebuild_raidset(struct lib_context *lc, char *set_name); #endif --- dmraid/lib/.export.sym 2008/02/22 16:57:35 1.1 +++ dmraid/lib/.export.sym 2008/06/20 21:52:16 1.2 @@ -1,51 +1,58 @@ -Base { - global: - add_delimiter; - change_set; - check_valid_format; - collapse_delimiter; - count_devices; - count_devs; - count_sets; - _dbg_free; - _dbg_malloc; - _dbg_realloc; - _dbg_strdup; - discover_devices; - discover_partitions; - discover_raid_devices; - display_devices; - display_set; - dm_version; - erase_metadata; - find_set; - get_dm_type; - get_set_type; - get_set_name; - get_status; - get_type; - group_set; - init_locking; - lc_inc_opt; - lc_list; - lc_opt; - lc_stralloc_opt; - lc_strcat_opt; - libdmraid_exit; - libdmraid_init; - libdmraid_date; - libdmraid_version; - libdmraid_make_table; - list_formats; - lock_resource; - log_alloc_err; - plog; - process_sets; - remove_delimiter; - remove_white_space; - total_sectors; - unlock_resource; - - local: - *; -}; +Base { + global: + add_delimiter; + change_set; + check_valid_format; + collapse_delimiter; + count_devices; + count_devs; + count_sets; + _dbg_free; + _dbg_malloc; + _dbg_realloc; + _dbg_strdup; + discover_devices; + discover_partitions; + discover_raid_devices; + display_devices; + display_set; + dm_version; + erase_metadata; + find_set; + get_dm_type; + get_set_type; + get_set_name; + get_status; + get_type; + group_set; + init_locking; + lc_inc_opt; + lc_list; + lc_opt; + lc_stralloc_opt; + lc_strcat_opt; + libdmraid_exit; + libdmraid_init; + libdmraid_date; + libdmraid_version; + libdmraid_make_table; + list_formats; + lock_resource; + log_alloc_err; + plog; + process_sets; + remove_delimiter; + remove_white_space; + total_sectors; + unlock_resource; + add_dev_to_array; + delete_raidsets; + lib_perform; + rebuild_raidset; + dso_end_rebuild; + hot_spare_add; + dso_get_members; + local: + *; +}; + --- dmraid/lib/version.h 2008/04/02 13:35:31 1.5 +++ dmraid/lib/version.h 2008/06/20 21:52:16 1.6 @@ -7,6 +7,6 @@ #define DMRAID_LIB_SUBMINOR_VERSION 0 #define DMRAID_LIB_VERSION_SUFFIX "rc15" -#define DMRAID_LIB_DATE "(2008.04.02)" +#define DMRAID_LIB_DATE "(2008.06.20)" #endif --- dmraid/lib/activate/activate.c 2008/04/02 13:35:31 1.3 +++ dmraid/lib/activate/activate.c 2008/06/20 21:52:16 1.4 @@ -1,7 +1,10 @@ /* - * Copyright (C) 2004,2005 Heinz Mauelshagen, Red Hat GmbH. + * Copyright (C) 2004-2008 Heinz Mauelshagen, Red Hat GmbH. * All rights reserved. * + * Copyright (C) 2007 Intel Corporation. All rights reserved. + * November, 2007 - additions for Create, Delete, Rebuild & Raid 10. + * * See file LICENSE at the top of this source tree for license information. */ @@ -12,26 +15,28 @@ #include "internal.h" #include "devmapper.h" -static int valid_rd(struct raid_dev *rd) +static int +valid_rd(struct raid_dev *rd) { return S_OK(rd->status) && !T_SPARE(rd); } -static int valid_rs(struct raid_set *rs) +static int +valid_rs(struct raid_set *rs) { return S_OK(rs->status) && !T_SPARE(rs); } /* Return rounded size in case of unbalanced mappings */ -static uint64_t maximize(struct raid_set *rs, uint64_t sectors, - uint64_t last, uint64_t min) +static uint64_t +maximize(struct raid_set *rs, uint64_t sectors, uint64_t last, uint64_t min) { return sectors > min ? min(last, sectors) : last; } /* Find smallest set/disk larger than given minimum. */ -static uint64_t _smallest(struct lib_context *lc, - struct raid_set *rs, uint64_t min) +static uint64_t +_smallest(struct lib_context *lc, struct raid_set *rs, uint64_t min) { uint64_t ret = ~0; struct raid_set *r; @@ -45,7 +50,7 @@ ret = maximize(rs, rd->sectors, ret, min); } - return ret == (uint64_t) ~0 ? 0 : ret; + return ret == (uint64_t) ~ 0 ? 0 : ret; } /* @@ -53,33 +58,38 @@ */ /* Undefined/-supported mapping. */ -static int _dm_un(struct lib_context *lc, char **table, - struct raid_set *rs, const char *what) +static int +_dm_un(struct lib_context *lc, char **table, + struct raid_set *rs, const char *what) { LOG_ERR(lc, 0, "Un%sed RAID type %s[%u] on %s", what, get_set_type(lc, rs), rs->type, rs->name); } -static int dm_undef(struct lib_context *lc, char **table, struct raid_set *rs) +static int +dm_undef(struct lib_context *lc, char **table, struct raid_set *rs) { return _dm_un(lc, table, rs, "defin"); } -static int dm_unsup(struct lib_context *lc, char **table, struct raid_set *rs) +static int +dm_unsup(struct lib_context *lc, char **table, struct raid_set *rs) { return _dm_un(lc, table, rs, "support"); } /* "Spare mapping". */ -static int dm_spare(struct lib_context *lc, char **table, struct raid_set *rs) +static int +dm_spare(struct lib_context *lc, char **table, struct raid_set *rs) { - LOG_ERR(lc, 0, "spare set"); + LOG_ERR(lc, 0, "spare set \"%s\" cannot be activated", rs->name); } /* Push path and offset onto a table. */ -static int _dm_path_offset(struct lib_context *lc, char **table, - int valid, const char *path, uint64_t offset) +static int +_dm_path_offset(struct lib_context *lc, char **table, + int valid, const char *path, uint64_t offset) { return p_fmt(lc, table, " %s %U", valid ? path : lc->path.error, offset); @@ -88,17 +98,17 @@ /* * Create dm table for linear mapping. */ -static int _dm_linear(struct lib_context *lc, char **table, int valid, - const char *path, uint64_t start, uint64_t sectors, - uint64_t offset) +static int +_dm_linear(struct lib_context *lc, char **table, int valid, + const char *path, uint64_t start, uint64_t sectors, uint64_t offset) { return p_fmt(lc, table, "%U %U %s", start, sectors, get_dm_type(lc, t_linear)) ? - _dm_path_offset(lc, table, valid, path, offset) : 0; + _dm_path_offset(lc, table, valid, path, offset) : 0; } -static int dm_linear(struct lib_context *lc, char **table, - struct raid_set *rs) +static int +dm_linear(struct lib_context *lc, char **table, struct raid_set *rs) { unsigned int segments = 0; uint64_t start = 0, sectors = 0; @@ -113,14 +123,14 @@ if (!(path = mkdm_path(lc, r->name))) goto err; - + sectors = total_sectors(lc, r); ret = _dm_linear(lc, table, valid_rs(r), path, start, sectors, 0); dbg_free(path); segments++; start += sectors; - + if (!ret || (r->sets.next != &rs->sets && !p_fmt(lc, table, "\n"))) @@ -131,10 +141,11 @@ /* Devices of a linear set. */ list_for_each_entry(rd, &rs->devs, devs) { if (!T_SPARE(rd)) { - if (!_dm_linear(lc, table, valid_rd(rd), rd->di->path, - start, rd->sectors, rd->offset)) + if (!_dm_linear + (lc, table, valid_rd(rd), rd->di->path, start, + rd->sectors, rd->offset)) goto err; - + segments++; start += rd->sectors; @@ -146,7 +157,7 @@ return segments ? 1 : 0; - err: + err: return log_alloc_err(lc, __func__); } @@ -156,8 +167,8 @@ * Partitioned RAID set with 1 RAID device * defining a linear partition mapping. */ -static int dm_partition(struct lib_context *lc, char **table, - struct raid_set *rs) +static int +dm_partition(struct lib_context *lc, char **table, struct raid_set *rs) { return dm_linear(lc, table, rs); } @@ -178,21 +189,22 @@ * */ /* Push begin of line onto a RAID0 table. */ -static int _dm_raid0_bol(struct lib_context *lc, char **table, - uint64_t min, uint64_t last_min, - unsigned int n, unsigned int stride) +static int +_dm_raid0_bol(struct lib_context *lc, char **table, + uint64_t min, uint64_t last_min, + unsigned int n, unsigned int stride) { return p_fmt(lc, table, n > 1 ? "%U %U %s %u %u" : "%U %U %s", last_min * n, (min - last_min) * n, - get_dm_type(lc, n > 1 ? t_raid0 : t_linear), - n, stride); + get_dm_type(lc, n > 1 ? t_raid0 : t_linear), n, stride); } /* Push end of line onto a RAID0 table. */ -static int _dm_raid0_eol(struct lib_context *lc, - char **table, struct raid_set *rs, - unsigned int *stripes, uint64_t last_min) +static int +_dm_raid0_eol(struct lib_context *lc, + char **table, struct raid_set *rs, + unsigned int *stripes, uint64_t last_min) { struct raid_set *r; struct raid_dev *rd; @@ -216,7 +228,7 @@ (*stripes)++; } } - + list_for_each_entry(rd, &rs->devs, devs) { if (!T_SPARE(rd) && rd->sectors > last_min && @@ -229,13 +241,13 @@ return 1; - err: + err: return 0; } /* Count RAID sets/devices larger than given minimum size. */ -static unsigned int _dm_raid_devs(struct lib_context *lc, - struct raid_set *rs, uint64_t min) +static unsigned int +_dm_raid_devs(struct lib_context *lc, struct raid_set *rs, uint64_t min) { unsigned int ret = 0; struct raid_set *r; @@ -246,7 +258,7 @@ if (!T_SPARE(r) && total_sectors(lc, r) > min) ret++; } - + list_for_each_entry(rd, &rs->devs, devs) { if (!T_SPARE(rd) && rd->sectors > min) ret++; @@ -254,9 +266,9 @@ return ret; } - -static int dm_raid0(struct lib_context *lc, char **table, - struct raid_set *rs) + +static int +dm_raid0(struct lib_context *lc, char **table, struct raid_set *rs) { unsigned int stripes = 0; uint64_t min, last_min = 0; @@ -266,9 +278,10 @@ goto err; if (!_dm_raid0_bol(lc, table, round_down(min, rs->stride), - last_min, _dm_raid_devs(lc, rs, last_min), - rs->stride) || - !_dm_raid0_eol(lc, table, rs, &stripes, last_min)) + last_min, _dm_raid_devs(lc, rs, + last_min), + rs->stride) + || !_dm_raid0_eol(lc, table, rs, &stripes, last_min)) goto err; if (!F_MAXIMIZE(rs)) @@ -277,7 +290,7 @@ return stripes ? 1 : 0; - err: + err: return log_alloc_err(lc, __func__); } @@ -286,20 +299,21 @@ */ /* Calculate dirty log region size. */ -static unsigned int calc_region_size(struct lib_context *lc, uint64_t sectors) +static unsigned int +calc_region_size(struct lib_context *lc, uint64_t sectors) { - const unsigned int mb_128 = 128*2*1024; + const unsigned int mb_128 = 128 * 2 * 1024; unsigned int max, region_size; if ((max = sectors / 1024) > mb_128) max = mb_128; for (region_size = 128; region_size < max; region_size <<= 1); - return region_size >> 1; } -static unsigned int get_rds(struct raid_set *rs, int valid) +static unsigned int +get_rds(struct raid_set *rs, int valid) { unsigned int ret = 0; struct raid_dev *rd; @@ -315,7 +329,8 @@ return ret; } -static unsigned int get_dm_devs(struct raid_set *rs, int valid) +static unsigned int +get_dm_devs(struct raid_set *rs, int valid) { unsigned int ret = 0; struct raid_set *r; @@ -329,30 +344,68 @@ ret++; } - ret+= get_rds(rs, valid); + return ret + get_rds(rs, valid); +} - return ret; +/* Retrieve number of drive to rebuild from metadata format handler. */ +static int +get_rebuild_drive(struct lib_context *lc, struct raid_set *rs, + struct handler_info *info) +{ + /* Initialize drive to rebuild invalid. */ + info->data.i32 = -1; + + if (lc->options[LC_REBUILD_SET].opt) { + struct raid_dev *rd; + + if (list_empty(&rs->devs)) + LOG_ERR(lc, 0, "RAID set has no devices!"); + + rd = list_entry(rs->devs.next, typeof(*rd), devs); + if (rd->fmt->metadata_handler) { + if (!rd-> + fmt->metadata_handler(lc, GET_REBUILD_DRIVE_NO, + info, rs)) + LOG_ERR(lc, 0, "Can't get rebuild drive #!"); + } else + LOG_ERR(lc, 0, + "Can't rebuild w/o metadata_handler for %s", + rd->fmt->name); + } + + return 1; } +/* Return true if RAID set needs rebuilding. */ +static inline int +rs_need_sync(struct raid_set *rs) +{ + return S_INCONSISTENT(rs->status) || S_NOSYNC(rs->status); +} + + /* Push begin of line onto a RAID1 table. */ /* FIXME: persistent dirty log. */ -static int _dm_raid1_bol(struct lib_context *lc, char **table, - struct raid_set *rs, - uint64_t sectors, unsigned int mirrors) +static int +_dm_raid1_bol(struct lib_context *lc, char **table, + struct raid_set *rs, + uint64_t sectors, unsigned int mirrors, int need_sync) { return (p_fmt(lc, table, "0 %U %s core 2 %u %s %u", sectors, get_dm_type(lc, t_raid1), calc_region_size(lc, sectors), - (S_INCONSISTENT(rs->status) || S_NOSYNC(rs->status)) ? - "sync" : "nosync", mirrors)); + (need_sync) ? "sync" : "nosync", mirrors)); } -static int dm_raid1(struct lib_context *lc, char **table, struct raid_set *rs) +static int +dm_raid1(struct lib_context *lc, char **table, struct raid_set *rs) { + int need_sync; + struct handler_info rebuild_drive; uint64_t sectors = 0; unsigned int mirrors = get_dm_devs(rs, 1); - struct raid_set *r; - struct raid_dev *rd; + struct raid_set *r, *swap_rs; + struct raid_dev *rd, *swap_rd; switch (mirrors) { case 0: @@ -367,23 +420,36 @@ rs->name); return dm_linear(lc, table, rs); } - + if (!(sectors = _smallest(lc, rs, 0))) LOG_ERR(lc, 0, "can't find smallest mirror!"); - if (!_dm_raid1_bol(lc, table, rs, sectors, mirrors)) + /* + * Get drive for reordering - copy is made from first + * drive (i.e. the master) to the other mirrors. + */ + need_sync = rs_need_sync(rs); + if (need_sync && !get_rebuild_drive(lc, rs, &rebuild_drive)) + return 0; + + if (!_dm_raid1_bol(lc, table, rs, sectors, mirrors, need_sync)) goto err; /* Stacked mirror sets. */ + swap_rs = NULL; list_for_each_entry(r, &rs->sets, list) { if (valid_rs(r)) { - int ret; + int ret = 1; char *path; if (!(path = mkdm_path(lc, r->name))) goto err; - ret = _dm_path_offset(lc, table, 1, path, 0); + if (!rebuild_drive.data.i32 && !swap_rs) + swap_rs = r; + else + ret = _dm_path_offset(lc, table, 1, path, 0); + dbg_free(path); if (!ret) @@ -391,20 +457,47 @@ } } - /* Lowest level mirror devices */ - list_for_each_entry(rd, &rs->devs, devs) { - if (valid_rd(rd) && - !_dm_path_offset(lc, table, 1, rd->di->path, rd->offset)) + /* Add rebuild target to the end of the list. */ + if (swap_rs && valid_rs(swap_rs)) { + int ret = 1; + char *path; + + if (!(path = mkdm_path(lc, swap_rs->name))) goto err; + + ret = _dm_path_offset(lc, table, 1, path, 0); + dbg_free(path); + + if (!ret) + goto err; + } + + /* Lowest level mirror devices. */ + swap_rd = NULL; + list_for_each_entry(rd, &rs->devs, devs) { + if (valid_rd(rd)) { + if (!rebuild_drive.data.i32 && !swap_rd) + swap_rd = rd; + else if (!_dm_path_offset(lc, table, 1, + rd->di->path, rd->offset)) + goto err; + } } - /* Append the flag/feature required for dmraid1 - * event handling in the kernel driver + /* Add rebuild target to the end of the list. */ + if (swap_rd && valid_rd(swap_rd)) + if (!_dm_path_offset(lc, table, valid_rd(swap_rd), + swap_rd->di->path, swap_rd->offset)) + goto err; + + /* + * Append the flag/feature required for dmraid1 + * event handling in the kernel driver. */ - if(p_fmt(lc, table, " 1 handle_errors")) + if (p_fmt(lc, table, " 1 handle_errors")) return 1; - err: + err: return log_alloc_err(lc, __func__); } @@ -414,19 +507,28 @@ /* Push begin of line onto a RAID5 table. */ /* FIXME: persistent dirty log. */ -static int _dm_raid45_bol(struct lib_context *lc, char **table, - struct raid_set *rs, - uint64_t sectors, unsigned int members) +static int +_dm_raid45_bol(struct lib_context *lc, char **table, struct raid_set *rs, + uint64_t sectors, unsigned int members) { - return p_fmt(lc, table, "0 %U %s core 2 %u %s %s 1 %u %u -1", + int need_sync = rs_need_sync(rs); + struct handler_info rebuild_drive; + + /* Get drive as rebuild target. */ + if (need_sync && !get_rebuild_drive(lc, rs, &rebuild_drive)) + return 0; + + return p_fmt(lc, table, "0 %U %s core 2 %u %s %s 1 %u %u %d", sectors, get_dm_type(lc, rs->type), - calc_region_size(lc, total_sectors(lc, rs) / _dm_raid_devs(lc, rs, 0)), - (S_INCONSISTENT(rs->status) || S_NOSYNC(rs->status)) ? - "sync" : "nosync", - get_type(lc, rs->type), rs->stride, members); + calc_region_size(lc, + total_sectors(lc, rs) / + _dm_raid_devs(lc, rs, 0)), + (need_sync) ? "sync" : "nosync", get_type(lc, rs->type), + rs->stride, members, rebuild_drive.data.i32); } -static int dm_raid45(struct lib_context *lc, char **table, struct raid_set *rs) +static int +dm_raid45(struct lib_context *lc, char **table, struct raid_set *rs) { uint64_t sectors = 0; unsigned int members = get_dm_devs(rs, 0); @@ -465,14 +567,14 @@ /* Lowest level RAID devices */ list_for_each_entry(rd, &rs->devs, devs) { - if (!_dm_path_offset(lc, table, valid_rd(rd), rd->di->path, - rd->offset)) + if (!_dm_path_offset(lc, table, valid_rd(rd), rd->di->path, + rd->offset)) goto err; } return 1; - err: + err: return log_alloc_err(lc, __func__); } @@ -485,25 +587,28 @@ */ static struct type_handler { const enum type type; - int(*f)(struct lib_context *lc, char **table, struct raid_set *rs); + int (*f) (struct lib_context * lc, char **table, struct raid_set * rs); } type_handler[] = { - { t_undef, dm_undef }, /* Needs to stay here! */ - { t_partition, dm_partition }, - { t_spare, dm_spare }, - { t_linear, dm_linear }, - { t_raid0, dm_raid0 }, - { t_raid1, dm_raid1 }, - { t_raid4, dm_raid45 }, - { t_raid5_ls, dm_raid45 }, - { t_raid5_rs, dm_raid45 }, - { t_raid5_la, dm_raid45 }, - { t_raid5_ra, dm_raid45 }, - /* RAID types below not supported (yet) */ - { t_raid6, dm_unsup }, -}; + { + t_undef, dm_undef}, /* Needs to stay here! */ + { + t_partition, dm_partition}, { + t_spare, dm_spare}, { + t_linear, dm_linear}, { + t_raid0, dm_raid0}, { + t_raid1, dm_raid1}, { + t_raid4, dm_raid45}, { + t_raid5_ls, dm_raid45}, { + t_raid5_rs, dm_raid45}, { + t_raid5_la, dm_raid45}, { + t_raid5_ra, dm_raid45}, + /* RAID types below not supported (yet) */ + { +t_raid6, dm_unsup},}; /* Retrieve type handler from array. */ -static struct type_handler *handler(struct raid_set *rs) +static struct type_handler * +handler(struct raid_set *rs) { struct type_handler *th = type_handler; @@ -516,7 +621,8 @@ } /* Return mapping table */ -char *libdmraid_make_table(struct lib_context *lc, struct raid_set *rs) +char * +libdmraid_make_table(struct lib_context *lc, struct raid_set *rs) { char *ret = NULL; @@ -531,23 +637,25 @@ } -enum dm_what { DM_ACTIVATE, DM_REGISTER}; +enum dm_what { DM_ACTIVATE, DM_REGISTER }; /* Register devices of the RAID set with the dmeventd. */ /* REMOVEME: dummy functions once linking to the real ones. */ #define ALL_EVENTS 0xffffffff -static int dm_register_for_event(char *a, char *b, int c) +static int +dm_register_for_event(char *a, char *b, int c) { return 1; } -static int dm_unregister_for_event(char *a, char *b, int c) +static int +dm_unregister_for_event(char *a, char *b, int c) { return 1; } -static int do_device(struct lib_context *lc, struct raid_set *rs, - int (*f)()) // char *, char *, enum event_type)) +static int +do_device(struct lib_context *lc, struct raid_set *rs, int (*f) ()) { int ret = 0; struct raid_dev *rd; @@ -555,7 +663,7 @@ if (OPT_TEST(lc)) return 1; - return 1; /* REMOVEME: */ + return 1; /* REMOVEME: */ list_for_each_entry(rd, &rs->devs, devs) { if (!(ret = f("dmraid", rd->di->path, ALL_EVENTS))) @@ -565,24 +673,27 @@ return ret ? 1 : 0; } -static int register_devices(struct lib_context *lc, struct raid_set *rs) +static int +register_devices(struct lib_context *lc, struct raid_set *rs) { return do_device(lc, rs, dm_register_for_event); } /* Unregister devices of the RAID set with the dmeventd. */ -static int unregister_devices(struct lib_context *lc, struct raid_set *rs) +static int +unregister_devices(struct lib_context *lc, struct raid_set *rs) { return do_device(lc, rs, dm_unregister_for_event); } /* Reload a single set. */ -static int reload_subset(struct lib_context *lc, struct raid_set *rs) +static int +reload_subset(struct lib_context *lc, struct raid_set *rs) { int ret = 0; char *table = NULL; - if (T_GROUP(rs)) + if (T_GROUP(rs) || T_RAID0(rs)) return 1; /* Suspend device */ @@ -603,23 +714,21 @@ /* Try to resume */ if (ret) dm_resume(lc, rs); - else - if (!(ret = dm_resume(lc, rs))) - LOG_ERR(lc, ret, "Device resume failed."); + else if (!(ret = dm_resume(lc, rs))) + LOG_ERR(lc, ret, "Device resume failed."); return ret; } /* Reload a RAID set recursively (eg, RAID1 on top of RAID0). */ -static int reload_set(struct lib_context *lc, struct raid_set *rs) +static int +reload_set(struct lib_context *lc, struct raid_set *rs) { struct raid_set *r; /* FIXME: Does it matter if the set is (in)active? */ #if 0 - if (!OPT_TEST(lc) && - what == DM_ACTIVATE && - dm_status(lc, rs)) { + if (!OPT_TEST(lc) && what == DM_ACTIVATE && dm_status(lc, rs)) { log_print(lc, "RAID set \"%s\" already active", rs->name); return 1; } @@ -629,15 +738,15 @@ list_for_each_entry(r, &rs->sets, list) { /* Activate set below this one */ if (!reload_set(lc, r) && !T_GROUP(rs)) - return 0; + continue; } return reload_subset(lc, rs); } /* Activate a single set. */ -static int activate_subset(struct lib_context *lc, struct raid_set *rs, - enum dm_what what) +static int +activate_subset(struct lib_context *lc, struct raid_set *rs, enum dm_what what) { int ret = 0; char *table = NULL; @@ -652,8 +761,12 @@ if ((ret = (handler(rs))->f(lc, &table, rs))) { if (OPT_TEST(lc)) display_table(lc, rs->name, table); + else if ((ret = dm_create(lc, rs, table))) + log_print(lc, "RAID set \"%s\" was activated", + rs->name); else - ret = dm_create(lc, rs, table); + log_print(lc, "RAID set \"%s\" was not activated", + rs->name); } else log_err(lc, "no mapping possible for RAID set %s", rs->name); @@ -663,14 +776,12 @@ } /* Activate a RAID set recursively (eg, RAID1 on top of RAID0). */ -static int activate_set(struct lib_context *lc, struct raid_set *rs, - enum dm_what what) +static int +activate_set(struct lib_context *lc, struct raid_set *rs, enum dm_what what) { struct raid_set *r; - if (!OPT_TEST(lc) && - what == DM_ACTIVATE && - dm_status(lc, rs)) { + if (!OPT_TEST(lc) && what == DM_ACTIVATE && dm_status(lc, rs)) { log_print(lc, "RAID set \"%s\" already active", rs->name); return 1; } @@ -686,30 +797,29 @@ } /* Deactivate a single set (one level of a device stack). */ -static int deactivate_superset(struct lib_context *lc, struct raid_set *rs, - enum dm_what what) +static int +deactivate_superset(struct lib_context *lc, struct raid_set *rs, + enum dm_what what) { int ret = 1, status; if (what == DM_REGISTER) return unregister_devices(lc, rs); - + status = dm_status(lc, rs); if (OPT_TEST(lc)) log_print(lc, "%s [%sactive]", rs->name, status ? "" : "in"); else if (status) ret = dm_remove(lc, rs); - else { + else log_print(lc, "RAID set \"%s\" is not active", rs->name); - ret = 1; - } return ret; } /* Deactivate a RAID set. */ -static int deactivate_set(struct lib_context *lc, struct raid_set *rs, - enum dm_what what) +static int +deactivate_set(struct lib_context *lc, struct raid_set *rs, enum dm_what what) { struct raid_set *r; @@ -717,8 +827,7 @@ * Deactivate myself if not a group set, * which gets never activated itself. */ - if (!T_GROUP(rs) && - !deactivate_superset(lc, rs, what)) + if (!T_GROUP(rs) && !deactivate_superset(lc, rs, what)) return 0; /* Deactivate any subsets recursively. */ @@ -732,25 +841,30 @@ /* External (de)activate interface. */ -int change_set(struct lib_context *lc, enum activate_type what, void *v) +int +change_set(struct lib_context *lc, enum activate_type what, void *v) { - int ret = 0; + int ret; struct raid_set *rs = v; switch (what) { case A_ACTIVATE: ret = activate_set(lc, rs, DM_ACTIVATE) && - activate_set(lc, rs, DM_REGISTER); + activate_set(lc, rs, DM_REGISTER); break; case A_DEACTIVATE: ret = deactivate_set(lc, rs, DM_REGISTER) && - deactivate_set(lc, rs, DM_ACTIVATE); + deactivate_set(lc, rs, DM_ACTIVATE); break; case A_RELOAD: ret = reload_set(lc, rs); break; + + default: + log_err(lc, "%s: invalid activate type!", __func__); + ret = 0; } return ret; --- dmraid/lib/activate/devmapper.c 2008/04/02 13:35:31 1.3 +++ dmraid/lib/activate/devmapper.c 2008/06/20 21:52:16 1.4 @@ -1,7 +1,10 @@ /* - * Copyright (C) 2004,2005 Heinz Mauelshagen, Red Hat GmbH. + * Copyright (C) 2004-2008 Heinz Mauelshagen, Red Hat GmbH. * All rights reserved. * + * Copyright (C) 2007 Intel Corporation. All rights reserved. + * November, 2007 - additions for Create, Delete, Rebuild & Raid 10. + * * See file LICENSE at the top of this source tree for license information. */ @@ -24,7 +27,8 @@ #include <linux/dm-ioctl.h> /* Make up a dm path. */ -char *mkdm_path(struct lib_context *lc, const char *name) +char * +mkdm_path(struct lib_context *lc, const char *name) { char *ret; const char *dir = dm_dir(); @@ -38,20 +42,22 @@ } /* Device-mapper NULL log function. */ -static void dmraid_log(int level, const char *file, int line, - const char *f, ...) +static void +dmraid_log(int level, const char *file, int line, const char *f, ...) { return; } /* Init device-mapper library. */ -static void _init_dm(void) +static void +_init_dm(void) { dm_log_init(dmraid_log); } /* Cleanup at exit. */ -static void _exit_dm(struct dm_task *dmt) +static void +_exit_dm(struct dm_task *dmt) { if (dmt) dm_task_destroy(dmt); @@ -65,17 +71,18 @@ * * dm-library must get inititalized by caller. */ -static struct dm_versions *get_target_list(void) +static struct dm_versions * +get_target_list(void) { struct dm_task *dmt; return (dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS)) && - dm_task_run(dmt) ? dm_task_get_versions(dmt) : NULL; + dm_task_run(dmt) ? dm_task_get_versions(dmt) : NULL; } /* Check a target's name against registered ones. */ -static int valid_ttype(struct lib_context *lc, char *ttype, - struct dm_versions *targets) +static int +valid_ttype(struct lib_context *lc, char *ttype, struct dm_versions *targets) { struct dm_versions *t, *last; @@ -94,18 +101,20 @@ return 1; last = t; - t = (void*) t + t->next; + t = (void *) t + t->next; } while (last != t); - LOG_ERR(lc, 0, "device-mapper target type \"%s\" not in kernel", ttype); + LOG_ERR(lc, 0, + "device-mapper target type \"%s\" is not in the kernel", ttype); } /* * Parse a mapping table and create the appropriate targets or * check that a target type is registered with the device-mapper core. */ -static int handle_table(struct lib_context *lc, struct dm_task *dmt, - char *table, struct dm_versions *targets) +static int +handle_table(struct lib_context *lc, struct dm_task *dmt, + char *table, struct dm_versions *targets) { int line = 0, n, ret = 0; uint64_t start, size; @@ -138,21 +147,25 @@ } /* Parse a mapping table and create the appropriate targets. */ -static int parse_table(struct lib_context *lc, struct dm_task *dmt, char *table) +static int +parse_table(struct lib_context *lc, struct dm_task *dmt, char *table) { return handle_table(lc, dmt, table, NULL); } /* Check if a target type is not registered with the kernel after a failure. */ -static int check_table(struct lib_context *lc, char *table) +static int +check_table(struct lib_context *lc, char *table) { return handle_table(lc, NULL, table, get_target_list()); } /* Build a UUID for a dmraid device * Return 1 for sucess; 0 for failure*/ -static int dmraid_uuid(struct lib_context *lc, struct raid_set *rs, - char *uuid, uint uuid_len) { +static int +dmraid_uuid(struct lib_context *lc, struct raid_set *rs, + char *uuid, uint uuid_len) +{ int r; /* Clear garbage data from uuid string */ @@ -164,35 +177,39 @@ } /* Create a task, set its name and run it. */ -static int run_task(struct lib_context *lc, struct raid_set *rs, - char *table, int type) +static int +run_task(struct lib_context *lc, struct raid_set *rs, char *table, int type) { - /* DM_UUID_LEN is defined in dm-ioctl.h as 129 characters; + /* + * DM_UUID_LEN is defined in dm-ioctl.h as 129 characters; * though not all 129 must be used (md uses just 16 from * a quick review of md.c. - * We will be using: (len vol grp name)*/ + * We will be using: (len vol grp name) + */ char uuid[DM_UUID_LEN]; int ret; struct dm_task *dmt; _init_dm(); - ret = (dmt = dm_task_create(type)) && - dm_task_set_name(dmt, rs->name); + ret = (dmt = dm_task_create(type)) && dm_task_set_name(dmt, rs->name); if (ret && table) ret = parse_table(lc, dmt, table); - if (ret && - DM_DEVICE_CREATE == type) - ret = dmraid_uuid(lc, rs, uuid, DM_UUID_LEN) && - dm_task_set_uuid(dmt, uuid) && - dm_task_run(dmt); + if (ret) { + if (DM_DEVICE_CREATE == type) { + ret = dmraid_uuid(lc, rs, uuid, DM_UUID_LEN) && + dm_task_set_uuid(dmt, uuid) && dm_task_run(dmt); + } else + ret = dm_task_run(dmt); + } _exit_dm(dmt); return ret; } - + /* Create a mapped device. */ -int dm_create(struct lib_context *lc, struct raid_set *rs, char *table) +int +dm_create(struct lib_context *lc, struct raid_set *rs, char *table) { int ret; @@ -210,21 +227,24 @@ } /* Suspend a mapped device. */ -int dm_suspend(struct lib_context *lc, struct raid_set *rs) +int +dm_suspend(struct lib_context *lc, struct raid_set *rs) { /* Suspend <dev_name> */ return run_task(lc, rs, NULL, DM_DEVICE_SUSPEND); } /* Resume a mapped device. */ -int dm_resume(struct lib_context *lc, struct raid_set *rs) +int +dm_resume(struct lib_context *lc, struct raid_set *rs) { /* Resume <dev_name> */ return run_task(lc, rs, NULL, DM_DEVICE_RESUME); } /* Reload a mapped device. */ -int dm_reload(struct lib_context *lc, struct raid_set *rs, char *table) +int +dm_reload(struct lib_context *lc, struct raid_set *rs, char *table) { int ret; @@ -242,7 +262,8 @@ } /* Remove a mapped device. */ -int dm_remove(struct lib_context *lc, struct raid_set *rs) +int +dm_remove(struct lib_context *lc, struct raid_set *rs) { /* Remove <dev_name> */ return run_task(lc, rs, NULL, DM_DEVICE_REMOVE); @@ -250,7 +271,8 @@ /* Retrieve status of a mapped device. */ /* FIXME: more status for device monitoring... */ -int dm_status(struct lib_context *lc, struct raid_set *rs) +int +dm_status(struct lib_context *lc, struct raid_set *rs) { int ret; struct dm_task *dmt; @@ -260,18 +282,15 @@ /* Status <dev_name>. */ ret = (dmt = dm_task_create(DM_DEVICE_STATUS)) && - dm_task_set_name(dmt, rs->name) && - dm_task_run(dmt) && - dm_task_get_info(dmt, &info) && - info.exists; - + dm_task_set_name(dmt, rs->name) && + dm_task_run(dmt) && dm_task_get_info(dmt, &info) && info.exists; _exit_dm(dmt); - return ret; } /* Retrieve device-mapper driver version. */ -int dm_version(struct lib_context *lc, char *version, size_t size) +int +dm_version(struct lib_context *lc, char *version, size_t size) { int ret; struct dm_task *dmt; @@ -282,10 +301,8 @@ _init_dm(); ret = (dmt = dm_task_create(DM_DEVICE_VERSION)) && - dm_task_run(dmt) && - dm_task_get_driver_version(dmt, version, size); - + dm_task_run(dmt) && + dm_task_get_driver_version(dmt, version, size); _exit_dm(dmt); - return ret; } --- dmraid/lib/datastruct/byteorder.h 2008/02/22 16:57:35 1.1 +++ dmraid/lib/datastruct/byteorder.h 2008/06/20 21:52:16 1.2 @@ -16,30 +16,33 @@ #ifdef DM_BYTEORDER_SWAB -static inline uint64_t le64_to_cpu(uint64_t x) +static inline uint64_t +le64_to_cpu(uint64_t x) { - return((((uint64_t)x & 0x00000000000000ffULL) << 56) | - (((uint64_t)x & 0x000000000000ff00ULL) << 40) | - (((uint64_t)x & 0x0000000000ff0000ULL) << 24) | - (((uint64_t)x & 0x00000000ff000000ULL) << 8) | - (((uint64_t)x & 0x000000ff00000000ULL) >> 8) | - (((uint64_t)x & 0x0000ff0000000000ULL) >> 24) | - (((uint64_t)x & 0x00ff000000000000ULL) >> 40) | - (((uint64_t)x & 0xff00000000000000ULL) >> 56)); + return ((((uint64_t) x & 0x00000000000000ffULL) << 56) | + (((uint64_t) x & 0x000000000000ff00ULL) << 40) | + (((uint64_t) x & 0x0000000000ff0000ULL) << 24) | + (((uint64_t) x & 0x00000000ff000000ULL) << 8) | + (((uint64_t) x & 0x000000ff00000000ULL) >> 8) | + (((uint64_t) x & 0x0000ff0000000000ULL) >> 24) | + (((uint64_t) x & 0x00ff000000000000ULL) >> 40) | + (((uint64_t) x & 0xff00000000000000ULL) >> 56)); } -static inline int32_t le32_to_cpu(int32_t x) +static inline int32_t +le32_to_cpu(int32_t x) { - return((((u_int32_t)x & 0x000000ffU) << 24) | - (((u_int32_t)x & 0x0000ff00U) << 8) | - (((u_int32_t)x & 0x00ff0000U) >> 8) | - (((u_int32_t)x & 0xff000000U) >> 24)); + return ((((u_int32_t) x & 0x000000ffU) << 24) | + (((u_int32_t) x & 0x0000ff00U) << 8) | + (((u_int32_t) x & 0x00ff0000U) >> 8) | + (((u_int32_t) x & 0xff000000U) >> 24)); } -static inline int16_t le16_to_cpu(int16_t x) +static inline int16_t +le16_to_cpu(int16_t x) { - return((((u_int16_t)x & 0x00ff) << 8) | - (((u_int16_t)x & 0xff00) >> 8)); + return ((((u_int16_t) x & 0x00ff) << 8) | + (((u_int16_t) x & 0xff00) >> 8)); } #define CVT64(x) do { x = le64_to_cpu(x); } while(0) --- dmraid/lib/device/ata.c 2008/02/22 16:57:35 1.1 +++ dmraid/lib/device/ata.c 2008/06/20 21:52:17 1.2 @@ -15,7 +15,8 @@ #include "dev-io.h" #include "ata.h" -int get_ata_serial(struct lib_context *lc, int fd, struct dev_info *di) +int +get_ata_serial(struct lib_context *lc, int fd, struct dev_info *di) { int ret = 0; const int cmd_offset = 4; @@ -26,11 +27,14 @@ buf[0] = ATA_IDENTIFY_DEVICE; buf[3] = 1; if (!ioctl(fd, HDIO_DRIVE_CMD, buf)) { - ata_ident = (struct ata_identify*) &buf[cmd_offset]; - if ((di->serial = dbg_strdup(remove_white_space(lc, (char*) ata_ident->serial, ATA_SERIAL_LEN)))) + ata_ident = (struct ata_identify *) &buf[cmd_offset]; + if ((di->serial = + dbg_strdup(remove_white_space + (lc, (char *) ata_ident->serial, + ATA_SERIAL_LEN)))) ret = 1; } - + dbg_free(buf); } --- dmraid/lib/device/ata.h 2008/02/22 16:57:35 1.1 +++ dmraid/lib/device/ata.h 2008/06/20 21:52:17 1.2 @@ -13,10 +13,10 @@ struct ata_identify { unsigned short dummy[10]; #define ATA_SERIAL_LEN 20 - unsigned char serial[ATA_SERIAL_LEN]; + unsigned char serial[ATA_SERIAL_LEN]; unsigned short dummy1[3]; - unsigned char fw_rev[8]; - unsigned char model[40]; + unsigned char fw_rev[8]; + unsigned char model[40]; unsigned short dummy2[33]; unsigned short major_rev_num; unsigned short minor_rev_num; --- dmraid/lib/device/dev-io.h 2008/02/22 16:57:35 1.1 +++ dmraid/lib/device/dev-io.h 2008/06/20 21:52:17 1.2 @@ -12,8 +12,8 @@ #include <sys/stat.h> #include "internal.h" -#define BLKGETSIZE _IO(0x12, 0x60) /* get block device size */ -#define BLKSSZGET _IO(0x12, 0x68) /* get block device sector size */ +#define BLKGETSIZE _IO(0x12, 0x60) /* get block device size */ +#define BLKSSZGET _IO(0x12, 0x68) /* get block device sector size */ #define DMRAID_SECTOR_SIZE 512 --- dmraid/lib/device/scan.c 2008/02/22 16:57:35 1.1 +++ dmraid/lib/device/scan.c 2008/06/20 21:52:17 1.2 @@ -32,7 +32,8 @@ #define _PATH_MOUNTS "/proc/mounts" #endif -static char *find_sysfs_mp(struct lib_context *lc) +static char * +find_sysfs_mp(struct lib_context *lc) { #ifndef __KLIBC__ char *ret = NULL; @@ -57,12 +58,14 @@ return ret; #else - return (char*) "/sys"; + return (char *) "/sys"; #endif } /* Make up an absolute sysfs path given a relative one. */ -static char *mk_sysfs_path(struct lib_context *lc, char const *path) { +static char * +mk_sysfs_path(struct lib_context *lc, char const *path) +{ static char *ret = NULL, *sysfs_mp; if (!(sysfs_mp = find_sysfs_mp(lc))) @@ -78,18 +81,19 @@ /* Test with sparse mapped devices. */ #ifdef DMRAID_TEST -static int dm_test_device(struct lib_context *lc, char *path) +static int +dm_test_device(struct lib_context *lc, char *path) { struct stat s; return !lstat(path, &s) && - S_ISLNK(s.st_mode) && - !strncmp(get_basename(lc, path), "dm-", 3); + S_ISLNK(s.st_mode) && + !strncmp(get_basename(lc, path), "dm-", 3); } /* Fake a SCSI serial number by reading it from a file. */ -static int get_dm_test_serial(struct lib_context *lc, - struct dev_info *di, char *path) +static int +get_dm_test_serial(struct lib_context *lc, struct dev_info *di, char *path) { int ret = 1; char *serial, buffer[32]; @@ -121,19 +125,20 @@ * Ioctl for sector, optionally for device size * and get device serial number. */ -static int get_device_serial(struct lib_context *lc, int fd, - struct dev_info *di) +static int +get_device_serial(struct lib_context *lc, int fd, struct dev_info *di) { /* * In case new generic SCSI ioctl fails, * try ATA and fall back to old SCSI ioctl. */ - return get_scsi_serial(lc, fd, di, SG) || /* SG: generic scsi ioctl. */ - get_ata_serial(lc, fd, di) || /* Get ATA serial number. */ - get_scsi_serial(lc, fd, di, OLD); /* OLD: Old scsi ioctl. */ + return get_scsi_serial(lc, fd, di, SG) || /* SG: generic scsi ioctl. */ + get_ata_serial(lc, fd, di) || /* Get ATA serial number. */ + get_scsi_serial(lc, fd, di, OLD); /* OLD: Old scsi ioctl. */ } -static int di_ioctl(struct lib_context *lc, int fd, struct dev_info *di) +static int +di_ioctl(struct lib_context *lc, int fd, struct dev_info *di) { unsigned int sector_size = 0; unsigned long size; @@ -156,11 +161,12 @@ return get_dm_test_serial(lc, di, di->path); else #endif - return get_device_serial(lc, fd, di); + return get_device_serial(lc, fd, di); } /* Are we interested in this device ? */ -static int interested(struct lib_context *lc, char *path) +static int +interested(struct lib_context *lc, char *path) { char *name = get_basename(lc, path); @@ -168,19 +174,19 @@ * Whole IDE and SCSI disks only. */ return (!isdigit(name[strlen(name) - 1]) && - (*(name + 1) == 'd' && (*name == 'h' || *name == 's'))) - + (*(name + 1) == 'd' && (*name == 'h' || *name == 's'))) #ifdef DMRAID_TEST - /* - * Include dm devices for testing. - */ + /* + * Include dm devices for testing. + */ || dm_test_device(lc, path) #endif - ; + ; } /* Ask sysfs, if a device is removable. */ -int removable_device(struct lib_context *lc, char *dev_path) +int +removable_device(struct lib_context *lc, char *dev_path) { int ret = 0; char buf[2], *name, *sysfs_path, *sysfs_file; @@ -200,8 +206,7 @@ sprintf(sysfs_file, "%s/%s/%s", sysfs_path, name, sysfs_removable); if ((f = fopen(sysfs_file, "r"))) { /* Using fread for klibc compatibility. */ - if (fread(buf, sizeof(char), sizeof(buf) - 1, f) && - *buf == '1') { + if (fread(buf, sizeof(char), sizeof(buf) - 1, f) && *buf == '1') { log_notice(lc, "skipping removable device %s", dev_path); ret = 1; @@ -212,7 +217,7 @@ dbg_free(sysfs_file); - out: + out: dbg_free(sysfs_path); return ret; @@ -222,8 +227,9 @@ * Read the size in sectors from the sysfs "size" file. * Avoid access to removable devices. */ -static int sysfs_get_size(struct lib_context *lc, struct dev_info *di, - const char *path, char *name) +static int +sysfs_get_size(struct lib_context *lc, struct dev_info *di, + const char *path, char *name) { int ret = 0; char buf[22], *sysfs_file; @@ -253,8 +259,8 @@ return ret; } -static int get_size(struct lib_context *lc, char *path, - char *name, int sysfs) +static int +get_size(struct lib_context *lc, char *path, char *name, int sysfs) { int fd, ret = 0; char *dev_path; @@ -282,7 +288,7 @@ close(fd); - out: + out: dbg_free(dev_path); if (!ret && di) @@ -295,7 +301,8 @@ * Find disk devices in sysfs or directly * in /dev (for Linux 2.4) and keep information. */ -int discover_devices(struct lib_context *lc, char **devnodes) +int +discover_devices(struct lib_context *lc, char **devnodes) { int sysfs, ret = 0; char *path, *p; @@ -307,7 +314,7 @@ path = p; } else { sysfs = 0; - path = (char*) _PATH_DEV; + path = (char *) _PATH_DEV; log_print(lc, "carrying on with %s", path); } @@ -328,7 +335,7 @@ closedir(d); ret = 1; - out: + out: if (p) dbg_free(p); --- dmraid/lib/device/scsi.c 2008/02/22 16:57:35 1.1 +++ dmraid/lib/device/scsi.c 2008/06/20 21:52:17 1.2 @@ -1,7 +1,10 @@ /* - * Copyright (C) 2004,2005 Heinz Mauelshagen, Red Hat GmbH. + * Copyright (C) 2004-2008 Heinz Mauelshagen, Red Hat GmbH. * All rights reserved. * + * Copyright (C) 2007 Intel Corporation. All rights reserved. + * November, 2007 - additions for Create, Delete, Rebuild & Raid 10. + * * See file LICENSE at the top of this source tree for license information. */ @@ -21,11 +24,12 @@ /* Thx scsiinfo. */ /* Initialize SCSI inquiry command block (used both with SG and old ioctls). */ -static void set_cmd(unsigned char *cmd, size_t len) +static void +set_cmd(unsigned char *cmd, size_t len) { - cmd[0] = 0x12; /* INQUIRY */ + cmd[0] = 0x12; /* INQUIRY */ cmd[1] = 1; - cmd[2] = 0x80; /* page code: SCSI serial */ + cmd[2] = 0x80; /* page code: SCSI serial */ cmd[3] = 0; cmd[4] = (unsigned char) (len & 0xff); cmd[5] = 0; @@ -34,7 +38,8 @@ /* * SCSI SG_IO ioctl to get serial number of a unit. */ -static int sg_inquiry(int fd, unsigned char *response, size_t response_len) +static int +sg_inquiry(int fd, unsigned char *response, size_t response_len) { unsigned char cmd[6]; struct sg_io_hdr io_hdr; @@ -43,30 +48,29 @@ /* Initialize generic (SG) SCSI ioctl header. */ memset(&io_hdr, 0, sizeof(io_hdr)); - io_hdr.interface_id = 'S'; - io_hdr.cmdp = cmd; - io_hdr.cmd_len = sizeof(cmd); - io_hdr.sbp = NULL; - io_hdr.mx_sb_len = 0; - io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; - io_hdr.dxferp = response; - io_hdr.dxfer_len = response_len; - io_hdr.timeout = 6000; /* [ms] */ - + io_hdr.interface_id = 'S'; + io_hdr.cmdp = cmd; + io_hdr.cmd_len = sizeof(cmd); + io_hdr.sbp = NULL; + io_hdr.mx_sb_len = 0; + io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; + io_hdr.dxferp = response; + io_hdr.dxfer_len = response_len; + io_hdr.timeout = 6000; /* [ms] */ return ioctl(fd, SG_IO, &io_hdr) ? 0 : 1; } /* * Old SCSI ioctl as fallback to get serial number of a unit. */ -static int old_inquiry(int fd, unsigned char *response, size_t response_len) +static int +old_inquiry(int fd, unsigned char *response, size_t response_len) { - unsigned int *i = (unsigned int*) response; - - i[0] = 0; /* input data length */ - i[1] = response_len; /* output buffer length */ - set_cmd((unsigned char*) &i[2], response_len); + unsigned int *i = (unsigned int *) response; + i[0] = 0; /* input data length */ + i[1] = response_len; /* output buffer length */ + set_cmd((unsigned char *) &i[2], response_len); return ioctl(fd, SCSI_IOCTL_SEND_COMMAND, response) ? 0 : 1; } @@ -74,8 +78,9 @@ * Retrieve SCSI serial number. */ #define MAX_RESPONSE_LEN 255 -int get_scsi_serial(struct lib_context *lc, int fd, struct dev_info *di, - enum ioctl_type type) +int +get_scsi_serial(struct lib_context *lc, int fd, struct dev_info *di, + enum ioctl_type type) { int ret = 0; size_t actual_len; @@ -85,11 +90,11 @@ * string length field (serial string follows length field immediately) */ struct { - int (*ioctl_func)(int, unsigned char*, size_t); + int (*ioctl_func) (int, unsigned char *, size_t); unsigned int start; } param[] = { - { sg_inquiry , 3 }, - { old_inquiry, 11 }, + { sg_inquiry, 3}, + { old_inquiry, 11}, }, *p = (SG == type) ? param : param + 1; if (!(response = dbg_malloc(MAX_RESPONSE_LEN))) @@ -104,10 +109,32 @@ ret = p->ioctl_func(fd, response, actual_len); } - ret = ret && (di->serial = dbg_strdup(remove_white_space(lc, (char*) &response[p->start + 1], serial_len))); + ret = ret && + (di->serial = dbg_strdup(remove_white_space (lc, (char *) &response[p->start + 1], serial_len))); } dbg_free(response); + return ret; +} + +int +get_scsi_id(struct lib_context *lc, int fd, struct sg_scsi_id *sg_id) +{ + int ret = 1; + + struct scsi_idlun { + int four_in_one; + int host_uniqe_id; + } lun; + + if (!ioctl(fd, SCSI_IOCTL_GET_IDLUN, &lun)) { + sg_id->host_no = (lun.four_in_one >> 24) & 0xff; + sg_id->channel = (lun.four_in_one >> 16) & 0xff; + sg_id->scsi_id = lun.four_in_one & 0xff; + sg_id->lun = (lun.four_in_one >> 8) & 0xff; + } else + ret = 0; return ret; + } --- dmraid/lib/device/scsi.h 2008/02/22 16:57:35 1.1 +++ dmraid/lib/device/scsi.h 2008/06/20 21:52:17 1.2 @@ -1,13 +1,18 @@ /* - * Copyright (C) 2004,2005 Heinz Mauelshagen, Red Hat GmbH. + * Copyright (C) 2004-2008 Heinz Mauelshagen, Red Hat GmbH. * All rights reserved. * + * Copyright (C) 2007 Intel Corporation. All rights reserved. + * November, 2007 - additions for Create, Delete, Rebuild & Raid 10. + * * See file LICENSE at the top of this source tree for license information. */ #ifndef _SCSI_H_ #define _SCSI_H_ +#include <scsi/sg.h> + /* Ioctl types possible (SG = SCSI generic, OLD = old SCSI command ioctl. */ enum ioctl_type { SG, @@ -16,5 +21,6 @@ int get_scsi_serial(struct lib_context *lc, int fd, struct dev_info *di, enum ioctl_type type); +int get_scsi_id(struct lib_context *lc, int fd, struct sg_scsi_id *sg_id); #endif --- dmraid/lib/display/display.c 2008/02/22 16:57:35 1.1 +++ dmraid/lib/display/display.c 2008/06/20 21:52:17 1.2 @@ -14,28 +14,32 @@ struct log_handler { const char *field; const unsigned char minlen; - void (*log_func)(struct lib_context*, void *arg); + void (*log_func) (struct lib_context *, void *arg); void *arg; }; -static void log_string(struct lib_context *lc, void *arg) +static void +log_string(struct lib_context *lc, void *arg) { - log_print_nnl(lc, "%s", (char*) arg); + log_print_nnl(lc, "%s", (char *) arg); } -static void log_uint64(struct lib_context *lc, void *arg) +static void +log_uint64(struct lib_context *lc, void *arg) { - log_print_nnl(lc, "%" PRIu64, *((uint64_t*) arg)); + log_print_nnl(lc, "%" PRIu64, *((uint64_t *) arg)); } -static void log_uint(struct lib_context *lc, void *arg) +static void +log_uint(struct lib_context *lc, void *arg) { - log_print_nnl(lc, "%u", *((unsigned int*) arg)); + log_print_nnl(lc, "%u", *((unsigned int *) arg)); } /* Log a structure member by field name. */ -static int log_field(struct lib_context *lc, const struct log_handler *lh, - size_t lh_size, char *field) +static int +log_field(struct lib_context *lc, const struct log_handler *lh, + size_t lh_size, char *field) { const struct log_handler *h; @@ -55,13 +59,14 @@ } /* Log a list of structure members by field name. */ -static void log_fields(struct lib_context *lc, const struct log_handler *lh, - size_t lh_size) { +static void +log_fields(struct lib_context *lc, const struct log_handler *lh, size_t lh_size) +{ int logged = 0, last_logged = 0; const char delim = *OPT_STR_SEPARATOR(lc); char *p, *sep, *sep_sav; - if (!(sep_sav = dbg_strdup((char*) OPT_STR_COLUMN(lc)))) { + if (!(sep_sav = dbg_strdup((char *) OPT_STR_COLUMN(lc)))) { log_alloc_err(lc, __func__); return; } @@ -83,28 +88,30 @@ } /* Display information about a block device */ -static void log_disk(struct lib_context *lc, struct list_head *pos) +static void +log_disk(struct lib_context *lc, struct list_head *pos) { struct dev_info *di = list_entry(pos, typeof(*di), list); if (OPT_STR_COLUMN(lc)) { const struct log_handler log_handlers[] = { - { "devpath", 1, log_string, di->path}, - { "path", 1, log_string, di->path}, - { "sectors", 3, log_uint64, &di->sectors}, - { "serialnumber", 3, log_string, - di->serial ? (void*) di->serial : (void*) "N/A"}, - { "size", 2, log_uint64, &di->sectors}, + {"devpath", 1, log_string, di->path}, + {"path", 1, log_string, di->path}, + {"sectors", 3, log_uint64, &di->sectors}, + {"serialnumber", 3, log_string, + di->serial ? (void *) di->serial : (void *) "N/A"}, + {"size", 2, log_uint64, &di->sectors}, }; log_fields(lc, log_handlers, ARRAY_SIZE(log_handlers)); - } else { + } + else { const char *fmt[] = { "%s: %12" PRIu64 " total, \"%s\"", "%s", "%s:%" PRIu64 ":\"%s\"", }; - + log_print(lc, fmt[ARRAY_LIMIT(fmt, OPT_COLUMN(lc))], di->path, di->sectors, di->serial ? di->serial : "N/A"); @@ -112,54 +119,59 @@ } /* Turn NULL (= "unknown") into a displayable string. */ -static const char *check_null(const char *str) +static const char * +check_null(const char *str) { return str ? str : "unknown"; } /* Log native RAID device information. */ -static void log_rd_native(struct lib_context *lc, struct list_head *pos) +static void +log_rd_native(struct lib_context *lc, struct list_head *pos) { struct raid_dev *rd = list_entry(pos, typeof(*rd), list); if (rd->fmt->log) { rd->fmt->log(lc, rd); log_print(lc, ""); - } else + } + else log_print(lc, "\"%s\" doesn't support native logging of RAID " "device information", rd->fmt->name); } /* Display information about a RAID device */ -static void log_rd(struct lib_context *lc, struct list_head *pos) +static void +log_rd(struct lib_context *lc, struct list_head *pos) { struct raid_dev *rd = list_entry(pos, typeof(*rd), list); if (OPT_STR_COLUMN(lc)) { const struct log_handler log_handlers[] = { - { "dataoffset", 2, log_uint64, &rd->offset}, - { "devpath", 2, log_string, rd->di->path }, - { "format", 1, log_string, (void*) rd->fmt->name }, - { "offset", 1, log_uint64, &rd->offset}, - { "path", 1, log_string, rd->di->path }, - { "raidname", 1, log_string, rd->name }, - { "type", 1, log_string, - (void*) check_null(get_type(lc, rd->type)) }, - { "sectors", 2, log_uint64, &rd->sectors}, - { "size", 2, log_uint64, &rd->sectors}, - { "status", 2, log_string, - (void*) check_null(get_status(lc, rd->status)) }, + {"dataoffset", 2, log_uint64, &rd->offset}, + {"devpath", 2, log_string, rd->di->path}, + {"format", 1, log_string, (void *) rd->fmt->name}, + {"offset", 1, log_uint64, &rd->offset}, + {"path", 1, log_string, rd->di->path}, + {"raidname", 1, log_string, rd->name}, + {"type", 1, log_string, + (void *) check_null(get_type(lc, rd->type))}, + {"sectors", 2, log_uint64, &rd->sectors}, + {"size", 2, log_uint64, &rd->sectors}, + {"status", 2, log_string, + (void *) check_null(get_status(lc, rd->status))}, }; log_fields(lc, log_handlers, ARRAY_SIZE(log_handlers)); - } else { + } + else { const char *fmt[] = { "%s: %s, \"%s\", %s, %s, %" PRIu64 " sectors, " - "data@ %" PRIu64, + "data@ %" PRIu64, "%s", "%s:%s:%s:%s:%s:%" PRIu64 ":%" PRIu64, }; - + log_print(lc, fmt[ARRAY_LIMIT(fmt, OPT_COLUMN(lc))], rd->di->path, rd->fmt->name, rd->name, check_null(get_type(lc, rd->type)), @@ -169,17 +181,18 @@ } /* Dispatch log functions. */ -static void log_devices(struct lib_context *lc, enum dev_type type) +static void +log_devices(struct lib_context *lc, enum dev_type type) { struct list_head *pos; struct { enum dev_type type; struct list_head *list; - void (*log)(struct lib_context *, struct list_head *); + void (*log) (struct lib_context *, struct list_head *); } types[] = { { DEVICE, LC_DI(lc), log_disk }, { NATIVE, LC_RD(lc), log_rd_native }, - { RAID, LC_RD(lc), log_rd }, + { RAID, LC_RD(lc), log_rd }, }, *t = types; do { @@ -189,13 +202,14 @@ return; } - } while (t++ < ARRAY_END(types)); + } while (++t < ARRAY_END(types)); - LOG_ERR(lc, , "%s: unknown device type", __func__); + LOG_ERR(lc,, "%s: unknown device type", __func__); } /* Display information about a dmraid format handler */ -static void log_format(struct lib_context *lc, struct dmraid_format *fmt) +static void +log_format(struct lib_context *lc, struct dmraid_format *fmt) { log_print_nnl(lc, "%-7s : %s", fmt->name, fmt->descr); if (fmt->caps) @@ -205,7 +219,8 @@ } /* Pretty print a mapping table. */ -void display_table(struct lib_context *lc, char *rs_name, char *table) +void +display_table(struct lib_context *lc, char *rs_name, char *table) { char *nl = table, *p; @@ -217,89 +232,92 @@ } /* Display information about devices depending on device type. */ -void display_devices(struct lib_context *lc, enum dev_type type) +void +display_devices(struct lib_context *lc, enum dev_type type) { int devs; if ((devs = count_devices(lc, type))) { log_info(lc, "%s device%s discovered:\n", - (type & (RAID|NATIVE)) ? "RAID" : "Block", - devs == 1 ? "" : "s"); + (type & (RAID | NATIVE)) ? "RAID" : "Block", + devs == 1 ? "" : "s"); log_devices(lc, type); } } /* Retrieve format name from (hierarchical) raid set. */ -static void *get_format_name(struct raid_set *rs) +static void * +get_format_name(struct raid_set *rs) { struct dmraid_format *fmt = get_format(rs); - return (void*) check_null(fmt ? fmt->name : NULL); + return (void *) check_null(fmt ? fmt->name : NULL); } -static void log_rs(struct lib_context *lc, struct raid_set *rs) +static void +log_rs(struct lib_context *lc, struct raid_set *rs) { unsigned int devs = 0, spares = 0, subsets = 0; uint64_t sectors = 0; if (T_GROUP(rs) && !OPT_GROUP(lc)) return; - + sectors = total_sectors(lc, rs); subsets = count_sets(lc, &rs->sets); - devs = count_devs(lc, rs, ct_dev); - spares = count_devs(lc, rs, ct_spare); - + devs = count_devs(lc, rs, ct_dev); + spares = count_devs(lc, rs, ct_spare); + if (OPT_STR_COLUMN(lc)) { const struct log_handler log_handlers[] = { - { "devices", 1, log_uint, &devs }, - { "format", 1, log_string, get_format_name(rs) }, - { "raidname", 1, log_string, rs->name }, - { "sectors", 2, log_uint64, §ors }, - { "size", 2, log_uint64, §ors }, - { "spares", 2, log_uint, &spares }, - { "status", 3, log_string, - (void*) check_null(get_status(lc, rs->status)) }, - { "stride", 3, log_uint, &rs->stride }, - { "subsets", 2, log_uint, &subsets }, - { "type", 1, log_string, - (void*) check_null(get_set_type(lc, rs)) }, + {"devices", 1, log_uint, &devs}, + {"format", 1, log_string, get_format_name(rs)}, + {"raidname", 1, log_string, rs->name}, + {"sectors", 2, log_uint64, §ors}, + {"size", 2, log_uint64, §ors}, + {"spares", 2, log_uint, &spares}, + {"status", 3, log_string, + (void *) check_null(get_status(lc, rs->status))}, + {"stride", 3, log_uint, &rs->stride}, + {"subsets", 2, log_uint, &subsets}, + {"type", 1, log_string, + (void *) check_null(get_set_type(lc, rs))}, }; log_fields(lc, log_handlers, ARRAY_SIZE(log_handlers)); - } else { + } + else { const char *fmt[] = { "name : %s\n" - "size : %" PRIu64 "\n" - "stride : %u\n" - "type : %s\n" - "status : %s\n" - "subsets: %u\n" - "devs : %u\n" - "spares : %u", + "size : %" PRIu64 "\n" + "stride : %u\n" + "type : %s\n" + "status : %s\n" + "subsets: %u\n" "devs : %u\n" "spares : %u", "%s", "%s:%" PRIu64 ":%u:%s:%s:%u:%u:%u", }; unsigned int o = ARRAY_LIMIT(fmt, lc_opt(lc, LC_COLUMN)); - + log_print(lc, fmt[o], rs->name, sectors, rs->stride, check_null(get_set_type(lc, rs)), check_null(get_status(lc, rs->status)), subsets, devs, spares); - + } if (OPT_COLUMN(lc) > 2) { struct raid_dev *rd; - + list_for_each_entry(rd, &rs->devs, devs) log_rd(lc, &rd->list); } } -static int group_active(struct lib_context *lc, struct raid_set *rs) +static int +group_active(struct lib_context *lc, struct raid_set *rs) { struct raid_set *r; @@ -312,8 +330,8 @@ } /* FIXME: Spock, do something better (neater). */ -void display_set(struct lib_context *lc, void *v, - enum active_type active, int top) +void +display_set(struct lib_context *lc, void *v, enum active_type active, int top) { struct raid_set *rs = v; struct raid_set *r; @@ -328,20 +346,19 @@ log_print(lc, "*** Group superset %s", rs->name); else { log_print(lc, "%s %s%s%set", - top ? "-->" : "***", - S_INCONSISTENT(rs->status) ? - "*Inconsistent* " : "", - dm_status(lc, rs) ? "Active " : "", - SETS(rs) ? "Supers" : (top ? "Subs" : "S")); + top ? "-->" : "***", + S_INCONSISTENT(rs->status) ? + "*Inconsistent* " : "", + dm_status(lc, rs) ? "Active " : "", + SETS(rs) ? "Supers" : (top ? "Subs" : "S")); } } log_rs(lc, rs); /* Optionally display subsets. */ - if (T_GROUP(rs) || /* Always display for GROUP sets. */ - OPT_SETS(lc) > 1 || - OPT_COLUMN(lc) > 2) { + if (T_GROUP(rs) || /* Always display for GROUP sets. */ + OPT_SETS(lc) > 1 || OPT_COLUMN(lc) > 2) { list_for_each_entry(r, &rs->sets, list) display_set(lc, r, active, ++top); } @@ -351,7 +368,8 @@ * Display information about supported RAID metadata formats * (ie. registered format handlers) */ -static void _list_formats(struct lib_context *lc, enum fmt_type type) +static void +_list_formats(struct lib_context *lc, enum fmt_type type) { struct format_list *fmt_list; @@ -361,7 +379,8 @@ } } -int list_formats(struct lib_context *lc, int arg) +int +list_formats(struct lib_context *lc, int arg) { log_info(lc, "supported metadata formats:"); _list_formats(lc, FMT_RAID); --- dmraid/lib/format/format.c 2008/04/02 13:35:31 1.4 +++ dmraid/lib/format/format.c 2008/06/20 21:52:17 1.5 @@ -1,7 +1,10 @@ /* - * Copyright (C) 2004,2005 Heinz Mauelshagen, Red Hat GmbH. + * Copyright (C) 2004-2008 Heinz Mauelshagen, Red Hat GmbH. * All rights reserved. * + * Copyright (C) 2007 Intel Corporation. All rights reserved. + * November, 2007 - additions for Create, Delete, Rebuild & Raid 10. + * * See file LICENSE at the top of this source tree for license information. */ @@ -46,30 +49,39 @@ { "name", offset(name), FMT_ALL }, { "description", offset(descr), FMT_ALL }, { "capabilities", offset(caps), 0 }, - { "read", offset(read), FMT_ALL|FMT_METHOD }, + { "read", offset(read), FMT_ALL | FMT_METHOD }, { "write", offset(write), FMT_METHOD }, - { "group", offset(group), FMT_ALL|FMT_METHOD }, - { "check", offset(check), FMT_ALL|FMT_METHOD }, + { "create", offset(create), FMT_METHOD }, + { "delete", offset(delete), FMT_METHOD }, + { "group", offset(group), FMT_ALL | FMT_METHOD }, + { "check", offset(check), FMT_ALL | FMT_METHOD }, { "events array", offset(events), 0 }, #ifdef NATIVE_LOG { "log", offset(log), FMT_METHOD }, #endif }; + #undef offset -static int check_member(struct lib_context *lc, struct dmraid_format *fmt, - struct format_member *member) +static int +check_member(struct lib_context *lc, struct dmraid_format *fmt, + struct format_member *member) { if ((!IS_FMT_ALL(member) && fmt->format != FMT_RAID) || - *((unsigned long*) (((unsigned char*) fmt) + member->offset))) + *((unsigned long *) (((unsigned char *) fmt) + member->offset))) return 0; - LOG_ERR(lc, 1, "%s: missing metadata format handler %s%s", - fmt->name, member->msg, IS_FMT_METHOD(member) ? " method" : ""); + /* show error in case method is required for all handlers */ + if (IS_FMT_ALL(member)) + LOG_ERR(lc, 1, "%s: missing metadata format handler %s%s", + fmt->name, member->msg, + IS_FMT_METHOD(member) ? " method" : ""); + + return 0; } -static int check_format_handler(struct lib_context *lc, - struct dmraid_format *fmt) +static int +check_format_handler(struct lib_context *lc, struct dmraid_format *fmt) { unsigned int error = 0; struct format_member *fm = format_member; @@ -87,7 +99,8 @@ /* * Register a RAID metadata format handler. */ -int register_format_handler(struct lib_context *lc, struct dmraid_format *fmt) +int +register_format_handler(struct lib_context *lc, struct dmraid_format *fmt) { struct format_list *fl; @@ -99,7 +112,8 @@ if ((fl = dbg_malloc(sizeof(*fl)))) { fl->fmt = fmt; list_add_tail(&fl->list, LC_FMT(lc)); - } + } else + log_alloc_err(lc, __func__); return fl ? 1 : 0; } @@ -110,13 +124,14 @@ * I use an array because of the growing number... */ static struct register_fh { - int (*func)(struct lib_context *lc); + int (*func) (struct lib_context * lc); } register_fh[] = { #include "register.h" { NULL }, }; -void unregister_format_handlers(struct lib_context *lc) +void +unregister_format_handlers(struct lib_context *lc) { struct list_head *elem, *tmp; @@ -126,7 +141,8 @@ } } -int register_format_handlers(struct lib_context *lc) +int +register_format_handlers(struct lib_context *lc) { int ret = 1; struct register_fh *fh; @@ -143,6 +159,7 @@ return ret; } + /* END metadata format handler registry. */ @@ -151,7 +168,8 @@ */ /* Allocate private space in format handlers (eg, for on-disk metadata). */ -void *alloc_private(struct lib_context *lc, const char *who, size_t size) +void * +alloc_private(struct lib_context *lc, const char *who, size_t size) { void *ret; @@ -162,8 +180,9 @@ } /* Allocate private space in format handlers and read data off device. */ -void *alloc_private_and_read(struct lib_context *lc, const char *who, - size_t size, char *path, loff_t offset) +void * +alloc_private_and_read(struct lib_context *lc, const char *who, + size_t size, char *path, loff_t offset) { void *ret; @@ -179,8 +198,9 @@ /* Allocate metadata sector array in format handlers. */ -void *alloc_meta_areas(struct lib_context *lc, struct raid_dev *rd, - const char *who, unsigned int n) +void * +alloc_meta_areas(struct lib_context *lc, struct raid_dev *rd, + const char *who, unsigned int n) { void *ret; @@ -191,8 +211,9 @@ } /* Simple metadata write function for format handlers. */ -static int _write_metadata(struct lib_context *lc, const char *handler, - struct raid_dev *rd, int idx, int erase) +static int +_write_metadata(struct lib_context *lc, const char *handler, + struct raid_dev *rd, int idx, int erase) { int ret = 0; void *p, *tmp; @@ -205,25 +226,26 @@ !(p = alloc_private(lc, handler, rd->meta_areas[idx].size))) goto out; - ret = write_file(lc, handler, rd->di->path, (void*) p, + ret = write_file(lc, handler, rd->di->path, (void *) p, rd->meta_areas[idx].size, rd->meta_areas[idx].offset << 9); - log_level(lc, ret ? _PLOG_DEBUG : _PLOG_ERR, + log_level(lc, ret ? _PLOG_DEBUG : _PLOG_ERR, "writing metadata to %s, offset %" PRIu64 " sectors, " "size %zu bytes returned %d", rd->di->path, rd->meta_areas[idx].offset, - rd->meta_areas[idx].size, ret); + rd->meta_areas[idx].size, ret); if (p != tmp) dbg_free(p); - out: + out: return ret; } -int write_metadata(struct lib_context *lc, const char *handler, - struct raid_dev *rd, int idx, int erase) +int +write_metadata(struct lib_context *lc, const char *handler, + struct raid_dev *rd, int idx, int erase) { unsigned int i; @@ -244,16 +266,16 @@ * a. spares in a mirror set need to be large enough. * b. # of devices correct. */ -static void _check_raid_set(struct lib_context *lc, struct raid_set *rs, - unsigned int (*f_devices)(struct raid_dev *rd, - void *context), - void *f_devices_context, - int (*f_check)(struct lib_context *lc, - struct raid_set *rs, - struct raid_dev *rd, - void *context), - void *f_check_context, - const char *handler) +static void +_check_raid_set(struct lib_context *lc, struct raid_set *rs, + unsigned int (*f_devices) (struct raid_dev * rd, + void *context), + void *f_devices_context, + int (*f_check) (struct lib_context * lc, + struct raid_set * rs, + struct raid_dev * rd, + void *context), + void *f_check_context, const char *handler) { unsigned int devs; uint64_t sectors; @@ -270,8 +292,7 @@ rs->found_devs = devices; log_dbg(lc, "checking %s device \"%s\"", handler, rd->di->path); - if (T_SPARE(rd) && - rs->type == t_raid1 && /* FIXME: rs->type check ? */ + if (T_SPARE(rd) && rs->type == t_raid1 && /* FIXME: rs->type check ? */ rd->sectors != sectors) { rd->status = s_inconsistent; log_err(lc, "%s: size mismatch in set \"%s\", spare " @@ -280,12 +301,11 @@ } if (devs != devices && - f_check && - !f_check(lc, rs, rd, f_check_context)) { + f_check && !f_check(lc, rs, rd, f_check_context)) { rd->status = s_broken; log_err(lc, "%s: wrong # of devices in RAID " "set \"%s\" [%u/%u] on %s", - handler, rs->name, devs, devices, rd->di->path); + handler, rs->name, devs, devices, rd->di->path); } else rd->status = s_ok; } @@ -301,8 +321,9 @@ * In case of lowest level RAID sets, check consistence of devices * and make the above decision at the device level. */ -static void _set_rs_status(struct lib_context *lc, struct raid_set *rs, - unsigned int i, unsigned int operational) +static void +_set_rs_status(struct lib_context *lc, struct raid_set *rs, + unsigned int i, unsigned int operational) { if (operational == i) rs->status = s_ok; @@ -314,7 +335,8 @@ log_dbg(lc, "set status of set \"%s\" to %u", rs->name, rs->status); } -static int set_rs_status(struct lib_context *lc, struct raid_set *rs) +static int +set_rs_status(struct lib_context *lc, struct raid_set *rs) { unsigned int i = 0, operational = 0; struct raid_set *r; @@ -327,16 +349,15 @@ if (S_OK(r->status) || S_INCONSISTENT(r->status)) operational++; } - + /* Check status of devices... */ list_for_each_entry(rd, &rs->devs, devs) { i++; if (S_OK(rd->status)) operational++; } - - _set_rs_status(lc, rs, i, operational); + _set_rs_status(lc, rs, i, operational); return S_BROKEN(rs->status) ? 0 : 1; } @@ -346,14 +367,14 @@ * This tiny helper function avoids coding recursive * RAID set stack unrolling in every metadata format handler. */ -int check_raid_set(struct lib_context *lc, struct raid_set *rs, - unsigned int (*f_devices)(struct raid_dev *rd, - void *context), - void *f_devices_context, - int (*f_check)(struct lib_context *lc, struct raid_set *r, - struct raid_dev *rd, void *context), - void *f_check_context, - const char *handler) +int +check_raid_set(struct lib_context *lc, struct raid_set *rs, + unsigned int (*f_devices) (struct raid_dev * rd, + void *context), + void *f_devices_context, + int (*f_check) (struct lib_context * lc, struct raid_set * r, + struct raid_dev * rd, void *context), + void *f_check_context, const char *handler) { struct raid_set *r; @@ -370,9 +391,10 @@ } /* Initialize a RAID sets type and stride. */ -int init_raid_set(struct lib_context *lc, struct raid_set *rs, - struct raid_dev *rd, unsigned int stride, - unsigned int type, const char *handler) +int +init_raid_set(struct lib_context *lc, struct raid_set *rs, + struct raid_dev *rd, unsigned int stride, + unsigned int type, const char *handler) { if (T_UNDEF(rd)) LOG_ERR(lc, 0, "%s: RAID type %u not supported", handler, type); @@ -395,22 +417,21 @@ } /* Discover RAID metadata and setup RAID device. */ -struct raid_dev *read_raid_dev( - struct lib_context *lc, - struct dev_info *di, - void* (*f_read_metadata)(struct lib_context *lc, struct dev_info *di, - size_t *size, uint64_t *offset, - union read_info *info), - size_t size, uint64_t offset, - void (*f_to_cpu)(void *meta), - int (*f_is_meta)(struct lib_context *lc, struct dev_info *di, - void *meta), - void (*f_file_metadata)(struct lib_context *lc, struct dev_info *di, +struct raid_dev * +read_raid_dev(struct lib_context *lc, + struct dev_info *di, + void *(*f_read_metadata) (struct lib_context * lc, + struct dev_info * di, size_t * size, + uint64_t * offset, + union read_info * info), size_t size, + uint64_t offset, void (*f_to_cpu) (void *meta), + int (*f_is_meta) (struct lib_context * lc, struct dev_info * di, void *meta), - int (*f_setup_rd)(struct lib_context *lc, struct raid_dev *rd, - struct dev_info *di, void *meta, - union read_info *info), - const char *handler) + void (*f_file_metadata) (struct lib_context * lc, + struct dev_info * di, void *meta), + int (*f_setup_rd) (struct lib_context * lc, struct raid_dev * rd, + struct dev_info * di, void *meta, + union read_info * info), const char *handler) { struct raid_dev *rd = NULL; void *meta; @@ -421,10 +442,9 @@ * metadata read function, use that. If not, allocate and * read size from offset. */ - meta = f_read_metadata ? f_read_metadata(lc, di, &size, &offset, - &info) : - alloc_private_and_read(lc, handler, size, - di->path, offset); + meta = f_read_metadata ? + f_read_metadata(lc, di, &size, &offset, &info) : + alloc_private_and_read(lc, handler, size, di->path, offset); if (!meta) goto out; @@ -456,14 +476,15 @@ free_raid_dev(lc, &rd); goto out; - bad: + bad: dbg_free(meta); - out: + out: return rd; } /* Check if format identifier is valid. */ -int check_valid_format(struct lib_context *lc, char *name) +int +check_valid_format(struct lib_context *lc, char *name) { struct format_list *fl; @@ -479,13 +500,14 @@ /* * Set up a format capabilities (ie, RAID levels) string array. */ -const char **get_format_caps(struct lib_context *lc, struct dmraid_format *fmt) +const char ** +get_format_caps(struct lib_context *lc, struct dmraid_format *fmt) { int i; char *caps, *p; const char **ret = NULL, delim = ','; - if (fmt->caps && (caps = dbg_strdup((char*) fmt->caps))) { + if (fmt->caps && (caps = dbg_strdup((char *) fmt->caps))) { /* Count capabilities delimiters. */ for (i = 0, p = caps; (p = remove_delimiter(p, delim)); i++) add_delimiter(&p, delim); @@ -494,17 +516,20 @@ for (i = 0, p = caps - 1; p; (p = remove_delimiter(p, delim))) ret[i++] = ++p; - } else + } else { + log_alloc_err(lc, __func__); dbg_free(caps); + } } return ret; } -void free_format_caps(struct lib_context *lc, const char **caps) +void +free_format_caps(struct lib_context *lc, const char **caps) { if (caps) { - dbg_free((char*) *caps); + dbg_free((char *) *caps); dbg_free(caps); } } @@ -512,16 +537,16 @@ /* * Allocate a RAID superset and link the subset to it. */ -struct raid_set *join_superset(struct lib_context *lc, - char *(*f_name)(struct lib_context *lc, - struct raid_dev *rd, - unsigned int subset), - void (*f_create)(struct raid_set *super, - void *private), - int (*f_set_sort)(struct list_head *pos, - struct list_head *new), - struct raid_set *rs, - struct raid_dev *rd) +struct raid_set * +join_superset(struct lib_context *lc, + char *(*f_name) (struct lib_context * lc, + struct raid_dev * rd, + unsigned int subset), + void (*f_create) (struct raid_set * super, + void *private), + int (*f_set_sort) (struct list_head * pos, + struct list_head * new), + struct raid_set *rs, struct raid_dev *rd) { char *n; struct raid_set *ret = NULL; @@ -539,7 +564,8 @@ } /* Display 'zero sectors on RAID' device error. */ -int log_zero_sectors(struct lib_context *lc, char *path, const char *handler) +int +log_zero_sectors(struct lib_context *lc, char *path, const char *handler) { LOG_ERR(lc, 0, "%s: zero sectors on %s", handler, path); } --- dmraid/lib/format/register.h 2008/02/22 17:04:35 1.2 +++ dmraid/lib/format/register.h 2008/06/20 21:52:17 1.3 @@ -15,7 +15,7 @@ #define xx(type) { register_ ## type }, /* Metadata format handlers. */ - xx(asr) +xx(asr) xx(ddf1) xx(hpt37x) xx(hpt45x) @@ -29,6 +29,5 @@ /* DOS partition type handler. */ xx(dos) - #undef xx #endif --- dmraid/lib/format/ataraid/asr.c 2008/04/02 13:35:31 1.4 +++ dmraid/lib/format/ataraid/asr.c 2008/06/20 21:52:17 1.5 @@ -30,7 +30,9 @@ static const char *spare_array = ".asr_spares"; /* Map ASR disk status to dmraid status */ -static enum status disk_status(struct asr_raid_configline *disk) { +static enum status +disk_status(struct asr_raid_configline *disk) +{ static struct states states[] = { { LSU_COMPONENT_STATE_OPTIMAL, s_ok }, { LSU_COMPONENT_STATE_DEGRADED, s_broken }, @@ -45,13 +47,14 @@ return rd_status(states, disk->raidstate, EQUAL); } - + /* Extract config line from metadata */ -static struct asr_raid_configline *get_config(struct asr *asr, uint32_t magic) +static struct asr_raid_configline * +get_config(struct asr *asr, uint32_t magic) { struct asr_raidtable *rt = asr->rt; struct asr_raid_configline *cl = rt->ent + rt->elmcnt; - + while (cl-- > rt->ent) { if (cl->raidmagic == magic) return cl; @@ -61,14 +64,15 @@ } /* Get this disk's configuration */ -static struct asr_raid_configline *this_disk(struct asr *asr) +static struct asr_raid_configline * +this_disk(struct asr *asr) { return get_config(asr, asr->rb.drivemagic); } /* Make up RAID device name. */ -static size_t _name(struct lib_context *lc, struct asr *asr, char *str, - size_t len) +static size_t +_name(struct lib_context *lc, struct asr *asr, char *str, size_t len) { struct asr_raid_configline *cl = this_disk(asr); @@ -79,7 +83,8 @@ } /* Figure out a name for the RAID device. */ -static char *name(struct lib_context *lc, struct asr *asr) +static char * +name(struct lib_context *lc, struct asr *asr) { size_t len; char *ret; @@ -93,9 +98,10 @@ } /* Stride size */ -static inline unsigned stride(struct asr_raid_configline *cl) +static inline unsigned +stride(struct asr_raid_configline *cl) { - return cl ? cl->strpsize: 0; + return cl ? cl->strpsize : 0; } /* @@ -105,14 +111,15 @@ * do any of those right now (RAID4 and RAID5 are in the works). */ /* Map the ASR raid type codes into dmraid type codes. */ -static enum type type(struct asr_raid_configline *cl) +static enum type +type(struct asr_raid_configline *cl) { /* Mapping of template types to generic types */ static struct types types[] = { - { ASR_RAID0, t_raid0 }, - { ASR_RAID1, t_raid1 }, + { ASR_RAID0, t_raid0 }, + { ASR_RAID1, t_raid1 }, { ASR_RAIDSPR, t_spare }, - { 0, t_undef}, + { 0, t_undef }, }; return cl ? rd_type(types, (unsigned) cl->raidtype) : t_undef; @@ -122,10 +129,11 @@ * Read an ASR RAID device. Fields are big endian, so * need to convert them if we're on a LE machine (i386, etc). */ -enum { ASR_BLOCK = 0x01, ASR_TABLE = 0x02, ASR_EXTTABLE = 0x04 }; +enum { ASR_BLOCK = 0x01, ASR_TABLE = 0x02, ASR_EXTTABLE = 0x04 }; #if BYTE_ORDER == LITTLE_ENDIAN -static void cvt_configline(struct asr_raid_configline *cl) +static void +cvt_configline(struct asr_raid_configline *cl) { CVT16(cl->raidcnt); CVT16(cl->raidseq); @@ -141,12 +149,13 @@ CVT32(cl->appBurstCount); } -static void to_cpu(void *meta, unsigned cvt) +static void +to_cpu(void *meta, unsigned cvt) { struct asr *asr = meta; struct asr_raidtable *rt = asr->rt; unsigned i, elmcnt = rt->elmcnt, - use_old_elmcnt = (rt->ridcode == RVALID2); + use_old_elmcnt = (rt->ridcode == RVALID2); if (cvt & ASR_BLOCK) { CVT32(asr->rb.b0idcode); @@ -179,7 +188,7 @@ CVT32(rt->recreateDate); /* Convert the first seven config lines */ - for (i = 0; i < (min(elmcnt, ASR_TBLELMCNT)); i++) + for (i = 0; i < (min(elmcnt, ASR_TBLELMCNT)); i++) cvt_configline(rt->ent + i); } @@ -194,10 +203,11 @@ #endif /* Compute the checksum of RAID metadata */ -static unsigned compute_checksum(struct asr *asr) +static unsigned +compute_checksum(struct asr *asr) { struct asr_raidtable *rt = asr->rt; - uint8_t *ptr = (uint8_t*) rt->ent; + uint8_t *ptr = (uint8_t *) rt->ent; unsigned checksum = 0, end = sizeof(*rt->ent) * rt->elmcnt; /* Compute checksum. */ @@ -209,7 +219,8 @@ /* (Un)truncate white space at the end of a name */ enum truncate { TRUNCATE, UNTRUNCATE }; -static void handle_white_space(uint8_t *p, enum truncate truncate) +static void +handle_white_space(uint8_t * p, enum truncate truncate) { unsigned j = ASR_NAMELEN; uint8_t c = truncate == TRUNCATE ? 0 : ' '; @@ -219,14 +230,14 @@ } /* Read extended metadata areas */ -static int read_extended(struct lib_context *lc, struct dev_info *di, - struct asr *asr) +static int +read_extended(struct lib_context *lc, struct dev_info *di, struct asr *asr) { unsigned remaining, i, chk; struct asr_raidtable *rt = asr->rt; log_notice(lc, "%s: reading extended data on %s", handler, di->path); - + /* Read the RAID table. */ if (!read_file(lc, handler, di->path, rt, ASR_DISK_BLOCK_SIZE, (uint64_t) asr->rb.raidtbl * ASR_DISK_BLOCK_SIZE)) @@ -235,7 +246,7 @@ /* Convert it */ to_cpu(asr, ASR_TABLE); - + /* Is this ok? */ if (rt->ridcode != RVALID2) LOG_ERR(lc, 0, "%s: Invalid magic number in RAID table; " @@ -256,7 +267,7 @@ if (rt->elmcnt > ASR_TBLELMCNT) { remaining = rt->elmsize * (rt->elmcnt - 7); if (!read_file(lc, handler, di->path, rt->ent + 7, - remaining, (uint64_t)(asr->rb.raidtbl + 1) * + remaining, (uint64_t) (asr->rb.raidtbl + 1) * ASR_DISK_BLOCK_SIZE)) return 0; @@ -267,10 +278,10 @@ if (rt->rversion < 2) { if ((chk = compute_checksum(asr)) != rt->rchksum) log_err(lc, "%s: Invalid RAID config table checksum " - "(0x%X vs. 0x%X) on %s", + "(0x%X vs. 0x%X) on %s", handler, chk, rt->rchksum, di->path); } - + /* Process the name of each line of the config line. */ for (i = 0; i < rt->elmcnt; i++) { /* @@ -296,9 +307,8 @@ * This is nuts. */ if (!*rt->ent[i].name) - strncpy((char*) rt->ent[i].name, - (char*) rt->ent->name, - ASR_NAMELEN); + strncpy((char *) rt->ent[i].name, + (char *) rt->ent->name, ASR_NAMELEN); /* Now truncate trailing whitespace in the name. */ handle_white_space(rt->ent[i].name, TRUNCATE); @@ -307,7 +317,8 @@ return 1; } -static int is_asr(struct lib_context *lc, struct dev_info *di, void *meta) +static int +is_asr(struct lib_context *lc, struct dev_info *di, void *meta) { struct asr *asr = meta; @@ -315,11 +326,10 @@ * Check our magic numbers and that the version == v8. * We don't support anything other than that right now. */ - if (asr->rb.b0idcode == B0RESRVD && - asr->rb.smagic == SVALID) { + if (asr->rb.b0idcode == B0RESRVD && asr->rb.smagic == SVALID) { if (asr->rb.resver == RBLOCK_VER) return 1; - + log_err(lc, "%s: ASR v%d detected, but we only support v8", handler, asr->rb.resver); } @@ -340,9 +350,9 @@ * lacks this sort of visibility as to where its block devices come from. * This is EXTREMELY DANGEROUS if you aren't careful! */ -static void *read_metadata_areas(struct lib_context *lc, struct dev_info *di, - size_t *sz, uint64_t *offset, - union read_info *info) +static void * +read_metadata_areas(struct lib_context *lc, struct dev_info *di, + size_t * sz, uint64_t * offset, union read_info *info) { size_t size = ASR_DISK_BLOCK_SIZE; uint64_t asr_sboffset = ASR_CONFIGOFFSET; @@ -357,7 +367,7 @@ */ if (!(asr = alloc_private(lc, handler, sizeof(*asr)))) goto bad0; - + if (!(asr->rt = alloc_private(lc, handler, sizeof(*asr->rt)))) goto bad1; @@ -370,8 +380,7 @@ to_cpu(asr, ASR_BLOCK); /* Check Signature and read optional extended metadata. */ - if (!is_asr(lc, di, asr) || - !read_extended(lc, di, asr)) + if (!is_asr(lc, di, asr) || !read_extended(lc, di, asr)) goto bad2; /* @@ -383,21 +392,21 @@ goto out; - bad2: + bad2: dbg_free(asr->rt); - bad1: + bad1: asr->rt = NULL; dbg_free(asr); - bad0: + bad0: asr = NULL; - out: + out: return asr; } /* Read the whole metadata chunk at once */ -static uint8_t *read_metadata_chunk(struct lib_context *lc, struct dev_info *di, - uint64_t start) +static uint8_t * +read_metadata_chunk(struct lib_context *lc, struct dev_info *di, uint64_t start) { uint8_t *ret; size_t size = (di->sectors - start) * ASR_DISK_BLOCK_SIZE; @@ -420,8 +429,8 @@ * "File the metadata areas" -- I think this function is supposed to declare * which parts of the drive are metadata and thus off-limits to dmraid. */ -static void file_metadata_areas(struct lib_context *lc, struct dev_info *di, - void *meta) +static void +file_metadata_areas(struct lib_context *lc, struct dev_info *di, void *meta) { uint8_t *buf; struct asr *asr = meta; @@ -432,19 +441,18 @@ /* Register the raid tables. */ file_metadata(lc, handler, di->path, buf, - ASR_DISK_BLOCK_SIZE * 17, - start * ASR_DISK_BLOCK_SIZE); - + ASR_DISK_BLOCK_SIZE * 17, start * ASR_DISK_BLOCK_SIZE); + dbg_free(buf); - + /* Record the device size if -D was specified. */ file_dev_size(lc, handler, di); } static int setup_rd(struct lib_context *lc, struct raid_dev *rd, struct dev_info *di, void *meta, union read_info *info); -static struct raid_dev *asr_read(struct lib_context *lc, - struct dev_info *di) +static struct raid_dev * +asr_read(struct lib_context *lc, struct dev_info *di) { /* * NOTE: Everything called after read_metadata_areas assumes that @@ -455,7 +463,8 @@ file_metadata_areas, setup_rd, handler); } -static int set_sort(struct list_head *dont, struct list_head *care) +static int +set_sort(struct list_head *dont, struct list_head *care) { return 0; } @@ -465,16 +474,18 @@ * Is hba:ch:lun:id ok? * It seems to be the way the binary driver does it... */ -static inline uint64_t compose_id(struct asr_raid_configline *cl) +static inline uint64_t +compose_id(struct asr_raid_configline *cl) { - return ((uint64_t) cl->raidhba << 48) + return ((uint64_t) cl->raidhba << 48) | ((uint64_t) cl->raidchnl << 40) - | ((uint64_t) cl->raidlun << 32) + | ((uint64_t) cl->raidlun << 32) | (uint64_t) cl->raidid; } /* Sort ASR devices by for a RAID set. */ -static int dev_sort(struct list_head *pos, struct list_head *new) +static int +dev_sort(struct list_head *pos, struct list_head *new) { return compose_id(this_disk(META(RD(new), asr))) < compose_id(this_disk(META(RD(pos), asr))); @@ -483,7 +494,8 @@ /* * Find the top-level RAID set for an ASR context. */ -static int find_toplevel(struct lib_context *lc, struct asr *asr) +static int +find_toplevel(struct lib_context *lc, struct asr *asr) { int i, toplevel = -1; struct asr_raidtable *rt = asr->rt; @@ -496,7 +508,7 @@ break; } } - + return toplevel; } @@ -504,7 +516,8 @@ * Find the logical drive configuration that goes with this * physical disk configuration. */ -static struct asr_raid_configline *find_logical(struct asr *asr) +static struct asr_raid_configline * +find_logical(struct asr *asr) { int i, j; struct asr_raidtable *rt = asr->rt; @@ -522,11 +535,13 @@ return NULL; } -static struct raid_dev *find_spare(struct lib_context *lc) { +static struct raid_dev * +find_spare(struct lib_context *lc) +{ struct raid_dev *spare; - + list_for_each_entry(spare, LC_RD(lc), list) { - if (spare->type == t_spare) + if (spare->type == t_spare) return spare; } @@ -534,8 +549,8 @@ } /* Wrapper for name() */ -static char *js_name(struct lib_context *lc, struct raid_dev *rd, - unsigned subset) +static char * +js_name(struct lib_context *lc, struct raid_dev *rd, unsigned subset) { return name(lc, META(rd, asr)); } @@ -543,7 +558,8 @@ /* * IO error event handler. */ -static int event_io(struct lib_context *lc, struct event_io *e_io) +static int +event_io(struct lib_context *lc, struct event_io *e_io) { struct raid_dev *rd = e_io->rd; struct asr *asr = META(rd, asr); @@ -553,7 +569,7 @@ /* Ignore if we've already marked this disk broken(?) */ if (rd->status & s_broken) return 0; - + log_err(lc, "%s: I/O error on device %s at sector %lu", handler, e_io->rd->di->path, e_io->sector); @@ -563,13 +579,14 @@ fwl->raidstate = LSU_COMPONENT_STATE_DEGRADED; /* FIXME: Do we have to mark a parent too? */ - return 1; /* Indicate that this is indeed a failure. */ + return 1; /* Indicate that this is indeed a failure. */ } /* * Helper routines for asr_group() */ -static struct raid_set *do_spare(struct lib_context *lc, struct raid_dev *rd) +static struct raid_set * +do_spare(struct lib_context *lc, struct raid_dev *rd) { struct raid_set *rs; @@ -585,11 +602,11 @@ * it. * * rs = find_set(lc, name(lc, asr), FIND_TOP, rd, LC_RS(lc), - * NO_CREATE, NO_CREATE_ARG); + * NO_CREATE, NO_CREATE_ARG); */ /* Otherwise, make a global spare pool. */ - rs = find_or_alloc_raid_set(lc, (char*)spare_array, FIND_TOP, rd, + rs = find_or_alloc_raid_set(lc, (char *) spare_array, FIND_TOP, rd, LC_RS(lc), NO_CREATE, NO_CREATE_ARG); /* @@ -604,8 +621,9 @@ } #define BUFSIZE 128 -static struct raid_set *do_stacked(struct lib_context *lc, struct raid_dev *rd, - struct asr_raid_configline *cl) +static struct raid_set * +do_stacked(struct lib_context *lc, struct raid_dev *rd, + struct asr_raid_configline *cl) { char buf[BUFSIZE], *path = rd->di->path; struct raid_set *rs, *ss; @@ -616,12 +634,11 @@ fwl = find_logical(asr); if (!fwl) LOG_ERR(lc, NULL, "%s: Failed to find RAID configuration " - "line on %s", - handler, path); + "line on %s", handler, path); snprintf(buf, BUFSIZE, ".asr_%s_%x_donotuse", fwl->name, fwl->raidmagic); - + /* Now find said parent. */ rs = find_or_alloc_raid_set(lc, buf, FIND_ALL, rd, NO_LIST, NO_CREATE, NO_CREATE_ARG); @@ -635,7 +652,7 @@ /* Add the disk to the set. */ list_add_sorted(lc, &rs->devs, &rd->devs, dev_sort); - + /* Find the top level set. */ ss = join_superset(lc, js_name, NO_CREATE, set_sort, rs, rd); if (!ss) @@ -645,7 +662,7 @@ ss->stride = stride(cl); ss->status = s_ok; /* FIXME: correct type (this crashed in stacked set code) */ - ss->type = t_raid1; // type(&asr->rt->ent[top_idx]); + ss->type = t_raid1; // type(&asr->rt->ent[top_idx]); return ss; } @@ -654,7 +671,8 @@ * which this disk belongs, and then attaching it. Note that there are other * complications, such as two-layer arrays (RAID10). */ -static struct raid_set *asr_group(struct lib_context *lc, struct raid_dev *rd) +static struct raid_set * +asr_group(struct lib_context *lc, struct raid_dev *rd) { int top_idx; struct asr *asr = META(rd, asr); @@ -668,8 +686,7 @@ top_idx = find_toplevel(lc, asr); if (top_idx < 0) LOG_ERR(lc, NULL, "%s: Can't find a logical array config " - "for disk %x", - handler, asr->rb.drivemagic); + "for disk %x", handler, asr->rb.drivemagic); /* This is a simple RAID0/1 array. Find the set. */ if (asr->rt->ent[top_idx].raidlevel == FWL) { @@ -700,7 +717,8 @@ } /* deletes configline from metadata of given asr, by index. */ -static void delete_configline(struct asr *asr, int index) +static void +delete_configline(struct asr *asr, int index) { struct asr_raid_configline *cl, *end; struct asr_raidtable *rt = asr->rt; @@ -715,13 +733,14 @@ } /* Find the newest configline entry in raid set and return a pointer to it. */ -static struct raid_dev *find_newest_drive(struct raid_set *rs) +static struct raid_dev * +find_newest_drive(struct raid_set *rs) { struct asr_raidtable *rt; struct raid_dev *device, *newest = NULL; uint16_t newest_raidseq = 0; - int i; - + int i; + list_for_each_entry(device, &rs->devs, devs) { rt = META(device, asr)->rt; // FIXME: We should be able to assume each configline @@ -734,19 +753,21 @@ } } } - + return newest; } /* Creates a random integer for a drive magic section */ -static uint32_t create_drivemagic() { +static uint32_t +create_drivemagic() +{ srand(time(NULL)); return rand() + rand(); } -static int spare(struct lib_context *lc, struct raid_dev *rd, - struct asr *asr) +static int +spare(struct lib_context *lc, struct raid_dev *rd, struct asr *asr) { struct asr_raid_configline *cl; @@ -781,13 +802,13 @@ cl->raidtype = ASR_RAIDSPR; cl->lcapcty = rd->di->sectors; cl->raidlevel = FWP; - return 1; } /* Returns (boolean) whether or not the drive described by the given configline * is in the given raid_set. */ -static int in_raid_set(struct asr_raid_configline *cl, struct raid_set *rs) +static int +in_raid_set(struct asr_raid_configline *cl, struct raid_set *rs) { struct asr *asr; struct raid_dev *d; @@ -797,11 +818,13 @@ if (cl->raidmagic == asr->rb.drivemagic) return 1; } + return 0; } /* Delete extra configlines which would otherwise trip us up. */ -static int cleanup_configlines(struct raid_dev *rd, struct raid_set *rs) +static int +cleanup_configlines(struct raid_dev *rd, struct raid_set *rs) { struct asr *a; struct raid_dev *d; @@ -810,7 +833,7 @@ list_for_each_entry(d, &rs->devs, devs) { a = META(d, asr); - + cl = a->rt->ent; for (clcnt = 0; clcnt < a->rt->elmcnt; /* done in loop */ ) { /* If it's in the seen list, or is a logical drive, @@ -833,19 +856,21 @@ } } } + return 1; } /* Add a CL entry */ -static int create_configline(struct raid_set *rs, struct asr *asr, - struct asr *a, struct raid_dev* newest) +static int +create_configline(struct raid_set *rs, struct asr *asr, + struct asr *a, struct raid_dev *newest) { struct asr *newest_asr = META(newest, asr); struct asr_raid_configline *cl; - + if (asr->rt->elmcnt >= RCTBL_MAX_ENTRIES) return 0; - + cl = asr->rt->ent + asr->rt->elmcnt; asr->rt->elmcnt++; @@ -858,7 +883,7 @@ cl->strpsize = newest_asr->rt->ent[0].strpsize; /* Starts after "asr_" */ - strcpy((char*) cl->name, &rs->name[sizeof(HANDLER)]); + strcpy((char *) cl->name, &rs->name[sizeof(HANDLER)]); cl->raidcnt = 0; /* Convert rs->type to an ASR_RAID type for the CL */ @@ -872,6 +897,7 @@ default: return 0; } + cl->lcapcty = newest_asr->rt->ent[0].lcapcty; cl->raidlevel = FWP; return 1; @@ -879,8 +905,8 @@ /* Update metadata to reflect the current raid set configuration. * Returns boolean success. */ -static int update_metadata(struct lib_context *lc, struct raid_dev *rd, - struct asr *asr) +static int +update_metadata(struct lib_context *lc, struct raid_dev *rd, struct asr *asr) { struct raid_set *rs; struct asr_raid_configline *cl; @@ -895,7 +921,7 @@ rt->elmcnt = 0; return 1; } - + /* If this is the spare array... */ if (!strcmp(spare_array, rs->name)) return spare(lc, rd, asr); @@ -911,11 +937,11 @@ /* Make sure the raid type agrees with the metadata */ if (type(this_disk(asr)) == t_spare) { struct asr *newest_asr = META(newest, asr); - - /* copy entire table from newest drive */ + + /* copy entire table from newest drive */ rt->elmcnt = newest_asr->rt->elmcnt; memcpy(rt->ent, newest_asr->rt->ent, - rt->elmcnt * sizeof(*rt->ent)); + rt->elmcnt * sizeof(*rt->ent)); } /* Increment the top level CL's raid count */ @@ -935,26 +961,25 @@ } /* If the magic is 0xFFFFFFFF, assign a random one */ - if (a->rb.drivemagic == 0xFFFFFFFF) { + if (a->rb.drivemagic == 0xFFFFFFFF) a->rb.drivemagic = create_drivemagic(); - } - + if (!(newest = find_newest_drive(rs))) return 0; - + create_configline(rs, asr, a, newest); } cleanup_configlines(rd, rs); - return 1; } /* Write metadata. */ -static int asr_write(struct lib_context *lc, struct raid_dev *rd, int erase) +static int +asr_write(struct lib_context *lc, struct raid_dev *rd, int erase) { - struct asr *asr = META(rd, asr); + struct asr *asr = META(rd, asr); int elmcnt = asr->rt->elmcnt, i, ret; /* Update the metadata if we're not erasing it. */ @@ -969,19 +994,19 @@ asr->rt->rchksum = compute_checksum(asr); /* Convert back to disk format */ - to_disk(asr, ASR_BLOCK | ASR_TABLE | ASR_EXTTABLE); + to_disk(asr, ASR_BLOCK | ASR_TABLE | ASR_EXTTABLE); /* Write data */ - ret = write_metadata(lc, handler, rd, -1, erase); - + ret = write_metadata(lc, handler, rd, -1, erase); + /* Go back to CPU format */ - to_cpu(asr, ASR_BLOCK | ASR_TABLE | ASR_EXTTABLE); - + to_cpu(asr, ASR_BLOCK | ASR_TABLE | ASR_EXTTABLE); + /* Truncate trailing whitespace in the name. */ for (i = 0; i < elmcnt; i++) handle_white_space(asr->rt->ent[i].name, TRUNCATE); - return ret; + return ret; } /* @@ -989,7 +1014,8 @@ */ /* Retrieve the number of devices that should be in this set. */ -static unsigned device_count(struct raid_dev *rd, void *context) +static unsigned +device_count(struct raid_dev *rd, void *context) { /* Get the logical drive */ struct asr_raid_configline *cl = find_logical(META(rd, asr)); @@ -998,15 +1024,17 @@ } /* Check a RAID device */ -static int check_rd(struct lib_context *lc, struct raid_set *rs, - struct raid_dev *rd, void *context) +static int +check_rd(struct lib_context *lc, struct raid_set *rs, + struct raid_dev *rd, void *context) { /* FIXME: Assume non-broken means ok. */ return rd->type != s_broken; } /* Start the recursive RAID set check. */ -static int asr_check(struct lib_context *lc, struct raid_set *rs) +static int +asr_check(struct lib_context *lc, struct raid_set *rs) { return check_raid_set(lc, rs, device_count, NULL, check_rd, NULL, handler); @@ -1018,7 +1046,8 @@ }; /* Dump a reserved block */ -static void dump_rb(struct lib_context *lc, struct asr_reservedblock *rb) +static void +dump_rb(struct lib_context *lc, struct asr_reservedblock *rb) { DP("block magic:\t\t0x%X", rb, rb->b0idcode); DP("sb0flags:\t\t\t0x%X", rb, rb->sb0flags); @@ -1033,7 +1062,8 @@ } /* Dump a raid config line */ -static void dump_cl(struct lib_context *lc, struct asr_raid_configline *cl) +static void +dump_cl(struct lib_context *lc, struct asr_raid_configline *cl) { DP("config ID:\t\t0x%X", cl, cl->raidmagic); DP(" name:\t\t\t\"%s\"", cl, cl->name); @@ -1062,7 +1092,8 @@ } /* Dump a raid config table */ -static void dump_rt(struct lib_context *lc, struct asr_raidtable *rt) +static void +dump_rt(struct lib_context *lc, struct asr_raidtable *rt) { unsigned i; @@ -1093,7 +1124,8 @@ /* * Log native information about the RAID device. */ -static void asr_log(struct lib_context *lc, struct raid_dev *rd) +static void +asr_log(struct lib_context *lc, struct raid_dev *rd) { struct asr *asr = META(rd, asr); @@ -1104,22 +1136,23 @@ #endif static struct dmraid_format asr_format = { - .name = HANDLER, - .descr = "Adaptec HostRAID ASR", - .caps = "0,1,10", + .name = HANDLER, + .descr = "Adaptec HostRAID ASR", + .caps = "0,1,10", .format = FMT_RAID, - .read = asr_read, - .write = asr_write, - .group = asr_group, - .check = asr_check, - .events = &asr_event_handlers, + .read = asr_read, + .write = asr_write, + .group = asr_group, + .check = asr_check, + .events = &asr_event_handlers, #ifdef DMRAID_NATIVE_LOG - .log = asr_log, + .log = asr_log, #endif }; /* Register this format handler with the format core */ -int register_asr(struct lib_context *lc) +int +register_asr(struct lib_context *lc) { return register_format_handler(lc, &asr_format); } @@ -1127,15 +1160,17 @@ /* * Set up a RAID device from what we've assembled out of the metadata. */ -static int setup_rd(struct lib_context *lc, struct raid_dev *rd, - struct dev_info *di, void *meta, union read_info *info) +static int +setup_rd(struct lib_context *lc, struct raid_dev *rd, + struct dev_info *di, void *meta, union read_info *info) { struct asr *asr = meta; struct meta_areas *ma; struct asr_raid_configline *cl = this_disk(asr); if (!cl) - LOG_ERR(lc, 0, "%s: Could not find current disk!", handler); + LOG_ERR(lc, 0, "%s: Could not find current disk!", handler); + /* We need two metadata areas */ if (!(ma = rd->meta_areas = alloc_meta_areas(lc, rd, handler, 2))) return 0; @@ -1151,11 +1186,12 @@ ma->area = asr->rt; /* Now set up the rest of the metadata info */ - rd->di = di; + rd->di = di; rd->fmt = &asr_format; rd->status = disk_status(cl); - rd->type = type(cl); + rd->type = type(cl); rd->offset = ASR_DATAOFFSET; + if (!(rd->sectors = cl->lcapcty)) return log_zero_sectors(lc, di->path, handler); --- dmraid/lib/format/ataraid/asr.h 2008/02/22 17:04:35 1.2 +++ dmraid/lib/format/ataraid/asr.h 2008/06/20 21:52:17 1.3 @@ -89,12 +89,12 @@ /*** RAID CONFIGURATION TABLE STRUCTURE ***/ -#define RVALID2 0x900765C4 /* Version 2+ RAID table ID code - signature */ +#define RVALID2 0x900765C4 /* Version 2+ RAID table ID code + signature */ #define RCTBL_MAX_ENTRIES 127 #define HBA_RCTBL_MAX_ENTRIES 255 -#define RTBLBLOCKS 16 /* Size of drive's raid table - in blocks */ +#define RTBLBLOCKS 16 /* Size of drive's raid table + in blocks */ /* flag bits */ #define RCTBLCHNG 0x80 /* Set on comp OR log (NOT AND) if tbl updates needed */ @@ -106,185 +106,182 @@ #define PREDICTIVE_ENABLE 0x02 #define RAID_ENTRY_FLAGS_ALARM_OFF_M 0x01 -struct asr_raid_configline -{ - uint16_t raidcnt; /* Component count of an OSL/FWL array */ - uint16_t raidseq; /* Sequence # of component to look for */ - uint32_t raidmagic; /* Magic # of component to look for */ - uint8_t raidlevel; /* Array level = OSL/FWL/OSI/FWP */ - uint8_t raidtype; /* Array type = RAID0/1/3/5, RAIDRED, - RAIDSPR */ - uint8_t raidstate; /* State of logical or physical drive */ - - uint8_t flags; /* misc flags set bit positions above */ - - uint8_t refcnt; /* Number of references to this log entry */ - uint8_t raidhba; /* -- not used -- Host bus adapter number - or RAIDID */ - uint8_t raidchnl; /* Channel number */ - uint8_t raidlun; /* SCSI LUN of log/phys drv */ - uint32_t raidid; /* SCSI ID of log/phys drv */ - uint32_t loffset; /* Offset of data for this comp in the - array */ - uint32_t lcapcty; /* Capacity of log drv or space used on - phys */ - uint16_t strpsize; /* Stripe size in blocks of this drive */ - uint16_t biosInfo; /* bios info - set by - I2O_EXEC_BIOS_INFO_SET */ - uint32_t lsu; /* Pointer to phys/log lun of this entry */ - uint8_t addedDrives; - uint8_t appSleepRate; - uint16_t blockStorageTid; - uint32_t curAppBlock; - uint32_t appBurstCount; +struct asr_raid_configline { + uint16_t raidcnt; /* Component count of an OSL/FWL array */ + uint16_t raidseq; /* Sequence # of component to look for */ + uint32_t raidmagic; /* Magic # of component to look for */ + uint8_t raidlevel; /* Array level = OSL/FWL/OSI/FWP */ + uint8_t raidtype; /* Array type = RAID0/1/3/5, RAIDRED, + RAIDSPR */ + uint8_t raidstate; /* State of logical or physical drive */ + + uint8_t flags; /* misc flags set bit positions above */ + + uint8_t refcnt; /* Number of references to this log entry */ + uint8_t raidhba; /* -- not used -- Host bus adapter number + or RAIDID */ + uint8_t raidchnl; /* Channel number */ + uint8_t raidlun; /* SCSI LUN of log/phys drv */ + uint32_t raidid; /* SCSI ID of log/phys drv */ + uint32_t loffset; /* Offset of data for this comp in the + array */ + uint32_t lcapcty; /* Capacity of log drv or space used on + phys */ + uint16_t strpsize; /* Stripe size in blocks of this drive */ + uint16_t biosInfo; /* bios info - set by + I2O_EXEC_BIOS_INFO_SET */ + uint32_t lsu; /* Pointer to phys/log lun of this entry */ + uint8_t addedDrives; + uint8_t appSleepRate; + uint16_t blockStorageTid; + uint32_t curAppBlock; + uint32_t appBurstCount; #define ASR_NAMELEN 16 - uint8_t name[ASR_NAMELEN]; /* Full name of the array. */ + uint8_t name[ASR_NAMELEN]; /* Full name of the array. */ } __attribute__ ((packed)); -struct asr_raidtable -{ +struct asr_raidtable { /* raid Flag defines 32 bits 0 - FFFFFFFF */ #define RAID_FLAGS_ALARM_OFF_M 0x00000001 - uint32_t ridcode; /* RAID table signature - 0x900765C4 */ - uint32_t rversion; /* Version of the RAID config table */ - uint16_t maxelm; /* Maximum number of elements */ - uint16_t elmcnt; /* Element Count (number used) */ + uint32_t ridcode; /* RAID table signature - 0x900765C4 */ + uint32_t rversion; /* Version of the RAID config table */ + uint16_t maxelm; /* Maximum number of elements */ + uint16_t elmcnt; /* Element Count (number used) */ #define ASR_TBLELMCNT 7 - uint16_t elmsize; /* Size of an individual raidCLine */ - uint16_t rchksum; /* RAID table check sum - (no rconfTblV2)*/ - uint32_t res1; /* Reserved */ - uint16_t res2; /* was bldRate - Time in 1/10s - between idle build bursts */ - uint16_t res3; /* was bldAmount - Block to build - during a build burst */ - uint32_t raidFlags; - uint32_t timestamp; /* used for iROC. A stamp to find - which is latest */ - uint8_t irocFlags; + uint16_t elmsize; /* Size of an individual raidCLine */ + uint16_t rchksum; /* RAID table check sum + (no rconfTblV2) */ + uint32_t res1; /* Reserved */ + uint16_t res2; /* was bldRate - Time in 1/10s + between idle build bursts */ + uint16_t res3; /* was bldAmount - Block to build + during a build burst */ + uint32_t raidFlags; + uint32_t timestamp; /* used for iROC. A stamp to find + which is latest */ + uint8_t irocFlags; #define ASR_IF_VERIFY_WITH_AUTOFIX 0x01 #define ASR_IF_BOOTABLE 0x80 - uint8_t dirty; /* Records "open state" for array */ + uint8_t dirty; /* Records "open state" for array */ #define ARRAY_STATE_OK 0x00 #define ARRAY_STATE_DIRTY 0x03 - uint8_t actionPriority; - uint8_t spareid; /* Stored in member disk meta data - to declare the ID of dedicated - spare to show up. */ - uint32_t sparedrivemagic;/* drivemagic (in RB) of the spare + uint8_t actionPriority; + uint8_t spareid; /* Stored in member disk meta data + to declare the ID of dedicated + spare to show up. */ + uint32_t sparedrivemagic; /* drivemagic (in RB) of the spare at above ID. */ - uint32_t raidmagic; /* used to identify spare drive with - its mirror set. */ - uint32_t verifyDate; /* used by iomgr */ - uint32_t recreateDate; /* used by iomgr */ - uint8_t res4[12]; /* Reserved */ + uint32_t raidmagic; /* used to identify spare drive with + its mirror set. */ + uint32_t verifyDate; /* used by iomgr */ + uint32_t recreateDate; /* used by iomgr */ + uint8_t res4[12]; /* Reserved */ struct asr_raid_configline ent[RCTBL_MAX_ENTRIES]; } __attribute__ ((packed)); -#define RBLOCK_VER 8 /* Version of the reserved block */ -#define B0RESRVD 0x37FC4D1E /* Signature of the reserved block */ -#define SVALID 0x4450544D /* ASCII code for "DPTM" DPT Mirror */ - -struct asr_reservedblock -{ - uint32_t b0idcode; /* 0x00 - ID code signifying block 0 - reserved */ - uint8_t lunsave[8]; /* 0x04 - NOT USED - LUN mappings for - all drives */ - uint16_t sdtype; /* 0x0C - NOT USED - drive type in - boot prom */ - uint16_t ssavecyl; /* 0x0E - NOT USED - Set Parameters - cylinders */ - uint8_t ssavehed; /* 0x10 - NOT USED - Set Parameters - heads */ - uint8_t ssavesec; /* 0x11 - NOT USED - Set Parameters - sectors */ - uint8_t sb0flags; /* 0x12 - flags saved in reserved - block */ - uint8_t jbodEnable; /* 0x13 - jbod enable -- DEC drive - hiding */ - uint8_t lundsave; /* 0x14 - NOT USED - LUNMAP disable - flags */ - uint8_t svpdirty; /* 0x15 - NOT USED - saved percentage - dirty */ - uint16_t biosInfo; /* 0x16 - bios info - set by - I2O_EXEC_BIOS_INFO_SET */ - uint16_t svwbskip; /* 0x18 - NOT USED - saved write-back - skip value */ - uint16_t svwbcln; /* 0x1A - NOT USED - saved maximum - clean blocks in write-back */ - uint16_t svwbmax; /* 0x1C - NOT USED - saved maximum - write-back length */ - uint16_t res3; /* 0x1E - unused (was write-back burst - block count) */ - uint16_t svwbmin; /* 0x20 - NOT USED - saved minimum - block count to write */ - uint16_t res4; /* 0x22 - unused (was minimum - look-ahead length) */ - uint16_t svrcacth; /* 0x24 - NOT USED - saved read cache - threshold */ - uint16_t svwcacth; /* 0x26 - NOT USED - saved write - cache threshold */ - uint16_t svwbdly; /* 0x28 - NOT USED - saved write-back - delay */ - uint8_t svsdtime; /* 0x2A - NOT USED - saved spin down - time */ - uint8_t res5; /* 0x2B - unused */ - uint16_t firmval; /* 0x2C - NOT USED - firmware on - drive (dw) */ - uint16_t firmbln; /* 0x2E - NOT USED - length in blocks - for firmware */ - uint32_t firmblk; /* 0x30 - NOT USED - starting block - for firmware */ - uint32_t fstrsvrb; /* 0x34 - 1st block reserved by - Storage Manager */ - uint16_t svBlockStorageTid; /* 0x38 - */ - uint16_t svtid; /* 0x3A - */ - uint8_t svseccfl; /* 0x3C - NOT USED - reserved block - scsi bus ecc flags */ - uint8_t res6; /* 0x3D - unused */ - uint8_t svhbanum; /* 0x3E - NOT USED - HBA's unique - RAID number */ - uint8_t resver; /* 0x3F - reserved block version - number */ - uint32_t drivemagic; /* 0x40 - Magic number of this drive - - used w/ RCTBLs */ - uint8_t reserved[20]; /* 0x44 - unused */ - uint8_t testnum; /* 0x58 - NOT USED - diagnostic test - number */ - uint8_t testflags; /* 0x59 - NOT USED - diagnostic test - flags */ - uint16_t maxErrorCount; /* 0x5A - NOT USED - diagnostic test - maximum error count */ - uint32_t count; /* 0x5C - NOT USED - diagnostic test - cycles - # of iterations */ - uint32_t startTime; /* 0x60 - NOT USED - diagnostic test - absolute test start time in - seconds */ - uint32_t interval; /* 0x64 - NOT USED - diagnostic test - interval in seconds */ - uint8_t tstxt0; /* 0x68 - not used - originally - diagnostic test exclusion period - start hour */ - uint8_t tstxt1; /* 0x69 - not used - originally - diagnostic test exclusion period - end hour */ - uint8_t serNum[32]; /* 0x6A - reserved */ - uint8_t res8[102]; /* 0x8A - reserved */ - uint32_t fwTestMagic; /* 0xF0 - test magic number - used by - FW Test for automated tests */ - uint32_t fwTestSeqNum; /* 0xF4 - test sequence number - used - by FW Test for automated tests */ - uint8_t fwTestRes[8]; /* 0xF6 - reserved by FW Test for - automated tests */ - uint32_t smagic; /* 0x100 - magic value saying software - half is valid */ - uint32_t raidtbl; /* 0x104 - pointer to first block of - raid table */ - uint16_t raidline; /* 0x108 - line number of this raid - table entry - only if version <7 */ - uint8_t res9[0xF6]; /* 0x10A - reserved for software stuff*/ +#define RBLOCK_VER 8 /* Version of the reserved block */ +#define B0RESRVD 0x37FC4D1E /* Signature of the reserved block */ +#define SVALID 0x4450544D /* ASCII code for "DPTM" DPT Mirror */ + +struct asr_reservedblock { + uint32_t b0idcode; /* 0x00 - ID code signifying block 0 + reserved */ + uint8_t lunsave[8]; /* 0x04 - NOT USED - LUN mappings for + all drives */ + uint16_t sdtype; /* 0x0C - NOT USED - drive type in + boot prom */ + uint16_t ssavecyl; /* 0x0E - NOT USED - Set Parameters + cylinders */ + uint8_t ssavehed; /* 0x10 - NOT USED - Set Parameters + heads */ + uint8_t ssavesec; /* 0x11 - NOT USED - Set Parameters + sectors */ + uint8_t sb0flags; /* 0x12 - flags saved in reserved + block */ + uint8_t jbodEnable; /* 0x13 - jbod enable -- DEC drive + hiding */ + uint8_t lundsave; /* 0x14 - NOT USED - LUNMAP disable + flags */ + uint8_t svpdirty; /* 0x15 - NOT USED - saved percentage + dirty */ + uint16_t biosInfo; /* 0x16 - bios info - set by + I2O_EXEC_BIOS_INFO_SET */ + uint16_t svwbskip; /* 0x18 - NOT USED - saved write-back + skip value */ + uint16_t svwbcln; /* 0x1A - NOT USED - saved maximum + clean blocks in write-back */ + uint16_t svwbmax; /* 0x1C - NOT USED - saved maximum + write-back length */ + uint16_t res3; /* 0x1E - unused (was write-back burst + block count) */ + uint16_t svwbmin; /* 0x20 - NOT USED - saved minimum + block count to write */ + uint16_t res4; /* 0x22 - unused (was minimum + look-ahead length) */ + uint16_t svrcacth; /* 0x24 - NOT USED - saved read cache + threshold */ + uint16_t svwcacth; /* 0x26 - NOT USED - saved write + cache threshold */ + uint16_t svwbdly; /* 0x28 - NOT USED - saved write-back + delay */ + uint8_t svsdtime; /* 0x2A - NOT USED - saved spin down + time */ + uint8_t res5; /* 0x2B - unused */ + uint16_t firmval; /* 0x2C - NOT USED - firmware on + drive (dw) */ + uint16_t firmbln; /* 0x2E - NOT USED - length in blocks + for firmware */ + uint32_t firmblk; /* 0x30 - NOT USED - starting block + for firmware */ + uint32_t fstrsvrb; /* 0x34 - 1st block reserved by + Storage Manager */ + uint16_t svBlockStorageTid; /* 0x38 - */ + uint16_t svtid; /* 0x3A - */ + uint8_t svseccfl; /* 0x3C - NOT USED - reserved block + scsi bus ecc flags */ + uint8_t res6; /* 0x3D - unused */ + uint8_t svhbanum; /* 0x3E - NOT USED - HBA's unique + RAID number */ + uint8_t resver; /* 0x3F - reserved block version + number */ + uint32_t drivemagic; /* 0x40 - Magic number of this drive - + used w/ RCTBLs */ + uint8_t reserved[20]; /* 0x44 - unused */ + uint8_t testnum; /* 0x58 - NOT USED - diagnostic test + number */ + uint8_t testflags; /* 0x59 - NOT USED - diagnostic test + flags */ + uint16_t maxErrorCount; /* 0x5A - NOT USED - diagnostic test + maximum error count */ + uint32_t count; /* 0x5C - NOT USED - diagnostic test + cycles - # of iterations */ + uint32_t startTime; /* 0x60 - NOT USED - diagnostic test + absolute test start time in + seconds */ + uint32_t interval; /* 0x64 - NOT USED - diagnostic test + interval in seconds */ + uint8_t tstxt0; /* 0x68 - not used - originally + diagnostic test exclusion period + start hour */ + uint8_t tstxt1; /* 0x69 - not used - originally + diagnostic test exclusion period + end hour */ + uint8_t serNum[32]; /* 0x6A - reserved */ + uint8_t res8[102]; /* 0x8A - reserved */ + uint32_t fwTestMagic; /* 0xF0 - test magic number - used by + FW Test for automated tests */ + uint32_t fwTestSeqNum; /* 0xF4 - test sequence number - used + by FW Test for automated tests */ + uint8_t fwTestRes[8]; /* 0xF6 - reserved by FW Test for + automated tests */ + uint32_t smagic; /* 0x100 - magic value saying software + half is valid */ + uint32_t raidtbl; /* 0x104 - pointer to first block of + raid table */ + uint16_t raidline; /* 0x108 - line number of this raid + table entry - only if version <7 */ + uint8_t res9[0xF6]; /* 0x10A - reserved for software stuff */ } __attribute__ ((packed)); @@ -310,7 +307,7 @@ #define ID_MAP_PHYSICAL_M 1 /* Logical Map Physical */ #define ID_MAP_LOGICAL_M 2 /* Either Dual Level or Single Level - Logical*/ + Logical */ #define MAX_LSU_COUNT 256 @@ -369,10 +366,10 @@ #define LSU_COMPONENT_STATE_REPLACED 0x04 #define LSU_COMPONENT_STATE_UNINITIALIZED 0x0A -#define LSU_COMPONENT_SUBSTATE_BUILDING 0x10 /* drive is being built - for first time */ -#define LSU_COMPONENT_SUBSTATE_REBUILDING 0x20 /* drive is being - rebuilt */ +#define LSU_COMPONENT_SUBSTATE_BUILDING 0x10 /* drive is being built + for first time */ +#define LSU_COMPONENT_SUBSTATE_REBUILDING 0x20 /* drive is being + rebuilt */ #define LSU_ARRAY_SUBSTATE_AWAIT_FORMAT 0x50 /* etc. */ --- dmraid/lib/format/ataraid/hpt37x.c 2008/02/22 17:04:35 1.2 +++ dmraid/lib/format/ataraid/hpt37x.c 2008/06/20 21:52:17 1.3 @@ -1,7 +1,7 @@ /* * Highpoint 37X ATARAID series metadata format handler. * - * Copyright (C) 2004,2005 Heinz Mauelshagen, Red Hat GmbH. + * Copyright (C) 2004-2008 Heinz Mauelshagen, Red Hat GmbH. * All rights reserved. * * See file LICENSE at the top of this source tree for license information. @@ -26,16 +26,16 @@ /* Make up RAID set name from magic_[01] numbers */ /* FIXME: better name ? */ -static size_t _name(struct hpt37x *hpt, char *str, size_t len, - unsigned int subset) +static size_t +_name(struct hpt37x *hpt, char *str, size_t len, unsigned int subset) { const char *fmt; if (hpt->magic_0) fmt = (subset && (hpt->type == HPT37X_T_RAID01_RAID0 || - hpt->type == HPT37X_T_RAID01_RAID1)) ? - "hpt37x_%u-%u" : "hpt37x_%u"; + hpt->type == HPT37X_T_RAID01_RAID1)) ? + "hpt37x_%u-%u" : "hpt37x_%u"; else fmt = "hpt37x_SPARE"; @@ -44,8 +44,8 @@ hpt->magic_1 ? hpt->magic_1 : hpt->magic_0, hpt->order); } -static char *name(struct lib_context *lc, struct raid_dev *rd, - unsigned int subset) +static char * +name(struct lib_context *lc, struct raid_dev *rd, unsigned int subset) { size_t len; char *ret; @@ -65,52 +65,57 @@ * Retrieve status of device. * FIXME: is this sufficient to cover all state ? */ -static enum status status(struct hpt37x *hpt) +static enum status +status(struct hpt37x *hpt) { return hpt->magic == HPT37X_MAGIC_BAD ? s_broken : s_ok; } /* Neutralize disk type. */ -static enum type type(struct hpt37x *hpt) +static enum type +type(struct hpt37x *hpt) { /* Mapping of HPT 37X types to generic types. */ static struct types types[] = { - { HPT37X_T_SINGLEDISK, t_linear}, - { HPT37X_T_SPAN, t_linear}, - { HPT37X_T_RAID0, t_raid0}, - { HPT37X_T_RAID1, t_raid1}, - { HPT37X_T_RAID01_RAID0, t_raid0}, - { HPT37X_T_RAID01_RAID1, t_raid1}, + { HPT37X_T_SINGLEDISK, t_linear }, + { HPT37X_T_SPAN, t_linear }, + { HPT37X_T_RAID0, t_raid0 }, + { HPT37X_T_RAID1, t_raid1 }, + { HPT37X_T_RAID01_RAID0, t_raid0 }, + { HPT37X_T_RAID01_RAID1, t_raid1 }, /* FIXME: support RAID 3+5 */ - { 0, t_undef}, + { 0, t_undef }, }; return hpt->magic_0 ? - rd_type(types, (unsigned int) hpt->type) : t_spare; + rd_type(types, (unsigned int) hpt->type) : t_spare; } /* Decide about ordering sequence of RAID device. */ -static int dev_sort(struct list_head *pos, struct list_head *new) +static int +dev_sort(struct list_head *pos, struct list_head *new) { - return (META(RD(new), hpt37x))->disk_number < - (META(RD(pos), hpt37x))->disk_number; + return META(RD(new), hpt37x)->disk_number < + META(RD(pos), hpt37x)->disk_number; } /* Decide about ordering sequence of RAID subset. */ -static int set_sort(struct list_head *pos, struct list_head *new) +static int +set_sort(struct list_head *pos, struct list_head *new) { - return (META(RD_RS(RS(new)), hpt37x))->order < - (META(RD_RS(RS(pos)), hpt37x))->order; + return META(RD_RS(RS(new)), hpt37x)->order < + META(RD_RS(RS(pos)), hpt37x)->order; } /* Magic check. */ -static int check_magic(void *meta) +static int +check_magic(void *meta) { struct hpt37x *hpt = meta; return (hpt->magic == HPT37X_MAGIC_OK || hpt->magic == HPT37X_MAGIC_BAD) && - hpt->disk_number < 8; + hpt->disk_number < 8; } /* @@ -120,7 +125,8 @@ #if BYTE_ORDER == LITTLE_ENDIAN # define to_cpu NULL #else -static void to_cpu(void *meta) +static void +to_cpu(void *meta) { struct hpt37x *hpt = meta; @@ -138,8 +144,7 @@ for (l = hpt->errorlog; l < hpt->errorlog + - min(hpt->error_log_entries, HPT37X_MAX_ERRORLOG); - l++) { + min(hpt->error_log_entries, HPT37X_MAX_ERRORLOG); l++) { CVT32(l->timestamp); CVT32(l->lba); } @@ -148,14 +153,16 @@ #endif /* Use magic check to tell, if this is Highpoint 37x */ -static int is_hpt37x(struct lib_context *lc, struct dev_info *di, void *meta) +static int +is_hpt37x(struct lib_context *lc, struct dev_info *di, void *meta) { return check_magic(meta); } static int setup_rd(struct lib_context *lc, struct raid_dev *rd, struct dev_info *di, void *meta, union read_info *info); -static struct raid_dev *hpt37x_read(struct lib_context *lc, struct dev_info *di) +static struct raid_dev * +hpt37x_read(struct lib_context *lc, struct dev_info *di) { return read_raid_dev(lc, di, NULL, sizeof(struct hpt37x), HPT37X_CONFIGOFFSET, @@ -165,8 +172,8 @@ /* * Write a Highpoint 37X RAID device. */ -static int hpt37x_write(struct lib_context *lc, - struct raid_dev *rd, int erase) +static int +hpt37x_write(struct lib_context *lc, struct raid_dev *rd, int erase) { int ret; #if BYTE_ORDER != LITTLE_ENDIAN @@ -188,28 +195,32 @@ * Check device hierarchy and create sub sets appropriately. * */ -static unsigned int stride(struct hpt37x *hpt) +static unsigned int +stride(struct hpt37x *hpt) { return hpt->raid0_shift ? 1 << hpt->raid0_shift : 0; } -static int mismatch(struct lib_context *lc, struct raid_dev *rd, char magic) +static int +mismatch(struct lib_context *lc, struct raid_dev *rd, char magic) { LOG_ERR(lc, 0, "%s: magic_%c mismatch on %s", handler, magic, rd->di->path); } -static void super_created(struct raid_set *ss, void *private) +static void +super_created(struct raid_set *ss, void *private) { struct hpt37x *hpt = META(private, hpt37x); - ss->type = hpt->type == HPT37X_T_RAID01_RAID0 ? t_raid1 : t_raid0; + ss->type = hpt->type == HPT37X_T_RAID01_RAID0 ? t_raid1 : t_raid0; ss->stride = stride(hpt); } /* FIXME: handle spares in mirrors and check that types are correct. */ -static int group_rd(struct lib_context *lc, struct raid_set *rs, - struct raid_set **ss, struct raid_dev *rd) +static int +group_rd(struct lib_context *lc, struct raid_set *rs, + struct raid_set **ss, struct raid_dev *rd) { struct hpt37x *h, *hpt = META(rd, hpt37x); @@ -248,8 +259,8 @@ /* * Add a Highpoint RAID device to a set. */ -static struct raid_set *hpt37x_group(struct lib_context *lc, - struct raid_dev *rd) +static struct raid_set * +hpt37x_group(struct lib_context *lc, struct raid_dev *rd) { struct raid_set *rs, *ss = NULL; @@ -268,22 +279,25 @@ * * FIXME: more sanity checks. */ -static unsigned int devices(struct raid_dev *rd, void *context) +static unsigned int +devices(struct raid_dev *rd, void *context) { - return (META(rd, hpt37x))->raid_disks; + return META(rd, hpt37x)->raid_disks; } -static int check_rd(struct lib_context *lc, struct raid_set *rs, - struct raid_dev *rd, void *context) +static int +check_rd(struct lib_context *lc, struct raid_set *rs, + struct raid_dev *rd, void *context) { /* * FIXME: raid_disks member wrong ? - * (eg, Peter Jonas RAID1 metadata, 2 disks and raid_disks = 1) + * (eg, Peter Jonas RAID1 metadata, 2 disks and raid_disks = 1) */ return T_RAID1(rd); } -static int hpt37x_check(struct lib_context *lc, struct raid_set *rs) +static int +hpt37x_check(struct lib_context *lc, struct raid_set *rs) { return check_raid_set(lc, rs, devices, NULL, check_rd, NULL, handler); } @@ -291,7 +305,8 @@ /* * IO error event handler. */ -static int event_io(struct lib_context *lc, struct event_io *e_io) +static int +event_io(struct lib_context *lc, struct event_io *e_io) { struct raid_dev *rd = e_io->rd; struct hpt37x *hpt = META(rd, hpt37x); @@ -301,20 +316,20 @@ return 0; hpt->magic = HPT37X_MAGIC_BAD; - return 1; } static struct event_handlers hpt37x_event_handlers = { .io = event_io, - .rd = NULL, /* FIXME: no device add/remove event handler yet. */ + .rd = NULL, /* FIXME: no device add/remove event handler yet. */ }; #ifdef DMRAID_NATIVE_LOG /* * Log native information about an HPT37X RAID device. */ -static void hpt37x_log(struct lib_context *lc, struct raid_dev *rd) +static void +hpt37x_log(struct lib_context *lc, struct raid_dev *rd) { struct hpt37x *hpt = META(rd, hpt37x); struct hpt37x_errorlog *el; @@ -348,33 +363,35 @@ DP("status: %u", hpt, el->status); DP("sectors: %u", hpt, el->sectors); DP("lba: %u", hpt, el->lba); - }; + }; } #endif static struct dmraid_format hpt37x_format = { - .name = HANDLER, - .descr = "Highpoint HPT37X", - .caps = "S,0,1,10,01", + .name = HANDLER, + .descr = "Highpoint HPT37X", + .caps = "S,0,1,10,01", .format = FMT_RAID, - .read = hpt37x_read, - .write = hpt37x_write, - .group = hpt37x_group, - .check = hpt37x_check, - .events = &hpt37x_event_handlers, + .read = hpt37x_read, + .write = hpt37x_write, + .group = hpt37x_group, + .check = hpt37x_check, + .events = &hpt37x_event_handlers, #ifdef DMRAID_NATIVE_LOG - .log = hpt37x_log, + .log = hpt37x_log, #endif }; /* Register this format handler with the format core. */ -int register_hpt37x(struct lib_context *lc) +int +register_hpt37x(struct lib_context *lc) { return register_format_handler(lc, &hpt37x_format); } /* Calculate RAID device size in sectors depending on RAID type. */ -static uint64_t sectors(struct raid_dev *rd, struct hpt37x *hpt) +static uint64_t +sectors(struct raid_dev *rd, struct hpt37x *hpt) { uint64_t ret = 0; struct dev_info *di = rd->di; @@ -397,8 +414,9 @@ } /* Derive the RAID device contents from the Highpoint ones. */ -static int setup_rd(struct lib_context *lc, struct raid_dev *rd, - struct dev_info *di, void *meta, union read_info *info) +static int +setup_rd(struct lib_context *lc, struct raid_dev *rd, + struct dev_info *di, void *meta, union read_info *info) { struct hpt37x *hpt = meta; @@ -407,18 +425,18 @@ rd->meta_areas->offset = HPT37X_CONFIGOFFSET >> 9; rd->meta_areas->size = sizeof(*hpt); - rd->meta_areas->area = (void*) hpt; + rd->meta_areas->area = (void *) hpt; - rd->di = di; + rd->di = di; rd->fmt = &hpt37x_format; rd->status = status(hpt); - rd->type = type(hpt); + rd->type = type(hpt); /* Data offset from start of device; first device is special */ - rd->offset = hpt->disk_number ? HPT37X_DATAOFFSET : 0; - if (!(rd->sectors = sectors(rd, hpt))) + rd->offset = hpt->disk_number ? HPT37X_DATAOFFSET : 0; + if (!(rd->sectors = sectors(rd, hpt))) return log_zero_sectors(lc, di->path, handler); - return (rd->name = name(lc, rd, 1)) ? 1 : 0; + return (rd->name = name(lc, rd, 1)) ? 1 : 0; } --- dmraid/lib/format/ataraid/hpt37x.h 2008/02/22 17:04:35 1.2 +++ dmraid/lib/format/ataraid/hpt37x.h 2008/06/20 21:52:17 1.3 @@ -39,60 +39,59 @@ #include <stdint.h> /* HPT 37x config data byte offset on disk */ -#define HPT37X_CONFIGOFFSET (9 << 9) /* 9 sectors */ +#define HPT37X_CONFIGOFFSET (9 << 9) /* 9 sectors */ #define HPT37X_DATAOFFSET 10 /* Data offset in sectors */ /* Ondisk metadata for Highpoint ATARAID */ struct hpt37x { - uint8_t filler1[32]; + uint8_t filler1[32]; - uint32_t magic; + uint32_t magic; #define HPT37X_MAGIC_OK 0x5a7816f0 -#define HPT37X_MAGIC_BAD 0x5a7816fd +#define HPT37X_MAGIC_BAD 0x5a7816fd - uint32_t magic_0; /* Set identifier */ - uint32_t magic_1; /* Array identifier */ + uint32_t magic_0; /* Set identifier */ + uint32_t magic_1; /* Array identifier */ - uint32_t order; -#define HPT_O_MIRROR 0x01 + uint32_t order; +#define HPT_O_MIRROR 0x01 #define HPT_O_STRIPE 0x02 #define HPT_O_OK 0x04 - uint8_t raid_disks; - uint8_t raid0_shift; + uint8_t raid_disks; + uint8_t raid0_shift; - uint8_t type; -#define HPT37X_T_RAID0 0x00 + uint8_t type; +#define HPT37X_T_RAID0 0x00 #define HPT37X_T_RAID1 0x01 #define HPT37X_T_RAID01_RAID0 0x02 #define HPT37X_T_SPAN 0x03 -#define HPT37X_T_RAID_3 0x04 +#define HPT37X_T_RAID_3 0x04 #define HPT37X_T_RAID_5 0x05 #define HPT37X_T_SINGLEDISK 0x06 #define HPT37X_T_RAID01_RAID1 0x07 - uint8_t disk_number; - uint32_t total_secs; - uint32_t disk_mode; - uint32_t boot_mode; - uint8_t boot_disk; - uint8_t boot_protect; - uint8_t error_log_entries; - uint8_t error_log_index; + uint8_t disk_number; + uint32_t total_secs; + uint32_t disk_mode; + uint32_t boot_mode; + uint8_t boot_disk; + uint8_t boot_protect; + uint8_t error_log_entries; + uint8_t error_log_index; #define HPT37X_MAX_ERRORLOG 32 - struct hpt37x_errorlog - { - uint32_t timestamp; - uint8_t reason; -#define HPT_R_REMOVED 0xfe -#define HPT_R_BROKEN 0xff - - uint8_t disk; - uint8_t status; - uint8_t sectors; - uint32_t lba; - } errorlog[HPT37X_MAX_ERRORLOG]; - uint8_t filler[60]; + struct hpt37x_errorlog { + uint32_t timestamp; + uint8_t reason; +#define HPT_R_REMOVED 0xfe +#define HPT_R_BROKEN 0xff + + uint8_t disk; + uint8_t status; + uint8_t sectors; + uint32_t lba; + } errorlog[HPT37X_MAX_ERRORLOG]; + uint8_t filler[60]; } __attribute__ ((packed)); #endif --- dmraid/lib/format/ataraid/hpt45x.c 2008/02/22 17:04:35 1.2 +++ dmraid/lib/format/ataraid/hpt45x.c 2008/06/20 21:52:17 1.3 @@ -1,7 +1,7 @@ /* * Highpoint 45X ATARAID series metadata format handler. * - * Copyright (C) 2004,2005 Heinz Mauelshagen, Red Hat GmbH. + * Copyright (C) 2004-2008 Heinz Mauelshagen, Red Hat GmbH. * All rights reserved. * * See file LICENSE at the top of this source tree for license information. @@ -26,8 +26,8 @@ /* Make up RAID set name from magic_0 number */ /* FIXME: better name ? */ -static size_t _name(struct hpt45x *hpt, char *str, size_t len, - unsigned int subset) +static size_t +_name(struct hpt45x *hpt, char *str, size_t len, unsigned int subset) { const char *fmt; @@ -39,8 +39,8 @@ return snprintf(str, len, fmt, hpt->magic_0, hpt->raid1_disk_number); } -static char *name(struct lib_context *lc, struct raid_dev *rd, - unsigned int subset) +static char * +name(struct lib_context *lc, struct raid_dev *rd, unsigned int subset) { size_t len; char *ret; @@ -60,39 +60,43 @@ * Retrieve status of device. * FIXME: is this sufficient to cover all state ? */ -static enum status status(struct hpt45x *hpt) +static enum status +status(struct hpt45x *hpt) { return hpt->magic == HPT45X_MAGIC_BAD ? s_broken : s_ok; } /* Neutralize disk type */ -static enum type type(struct hpt45x *hpt) +static enum type +type(struct hpt45x *hpt) { /* Mapping of HPT 45X types to generic types */ static struct types types[] = { - { HPT45X_T_SPAN, t_linear}, - { HPT45X_T_RAID0, t_raid0}, - { HPT45X_T_RAID1, t_raid1}, + { HPT45X_T_SPAN, t_linear }, + { HPT45X_T_RAID0, t_raid0 }, + { HPT45X_T_RAID1, t_raid1 }, /* FIXME: handle RAID 4+5 */ - { 0, t_undef}, + { 0, t_undef }, }; return hpt->magic_0 ? rd_type(types, (unsigned int) hpt->type) : - t_spare; + t_spare; } /* Decide about ordering sequence of RAID device. */ -static int dev_sort(struct list_head *pos, struct list_head *new) +static int +dev_sort(struct list_head *pos, struct list_head *new) { - return (META(RD(new), hpt45x))->disk_number < - (META(RD(pos), hpt45x))->disk_number; + return META(RD(new), hpt45x)->disk_number < + META(RD(pos), hpt45x)->disk_number; } /* Decide about ordering sequence of RAID subset. */ -static int set_sort(struct list_head *pos, struct list_head *new) +static int +set_sort(struct list_head *pos, struct list_head *new) { - return (META(RD_RS(RS(new)), hpt45x))->raid1_disk_number < - (META(RD_RS(RS(pos)), hpt45x))->raid1_disk_number; + return META(RD_RS(RS(new)), hpt45x)->raid1_disk_number < + META(RD_RS(RS(pos)), hpt45x)->raid1_disk_number; } /* @@ -100,19 +104,22 @@ * * Check device hierarchy and create super set appropriately. */ -static unsigned int stride(unsigned int shift) +static unsigned int +stride(unsigned int shift) { - return shift ? 1 << shift : 0; + return shift ? (1 << shift) : 0; } -static void super_created(struct raid_set *super, void *private) +static void +super_created(struct raid_set *super, void *private) { - super->type = t_raid1; + super->type = t_raid1; super->stride = stride(META((private), hpt45x)->raid1_shift); } -static int group_rd(struct lib_context *lc, struct raid_set *rs, - struct raid_set **ss, struct raid_dev *rd) +static int +group_rd(struct lib_context *lc, struct raid_set *rs, + struct raid_set **ss, struct raid_dev *rd) { struct hpt45x *hpt = META(rd, hpt45x); @@ -125,7 +132,7 @@ switch (hpt->type) { case HPT45X_T_SPAN: case HPT45X_T_RAID1: - no_raid10: + no_raid10: if (!find_set(lc, NULL, rs->name, FIND_TOP)) list_add_tail(&rs->list, LC_RS(lc)); @@ -152,8 +159,8 @@ /* * Add a Highpoint RAID device to a set. */ -static struct raid_set *hpt45x_group(struct lib_context *lc, - struct raid_dev *rd) +static struct raid_set * +hpt45x_group(struct lib_context *lc, struct raid_dev *rd) { struct raid_set *rs, *ss = NULL; @@ -174,7 +181,8 @@ #if BYTE_ORDER == LITTLE_ENDIAN # define to_cpu NULL #else -static void to_cpu(void *meta) +static void +to_cpu(void *meta) { struct hpt45x *hpt = meta; @@ -186,19 +194,20 @@ #endif /* Magic check. */ -static int is_hpt45x(struct lib_context *lc, struct dev_info *di, void *meta) +static int +is_hpt45x(struct lib_context *lc, struct dev_info *di, void *meta) { struct hpt45x *hpt = meta; return (hpt->magic == HPT45X_MAGIC_OK || hpt->magic == HPT45X_MAGIC_BAD) && - hpt->disk_number < 8; + hpt->disk_number < 8; } static int setup_rd(struct lib_context *lc, struct raid_dev *rd, struct dev_info *di, void *meta, union read_info *info); -static struct raid_dev *hpt45x_read(struct lib_context *lc, - struct dev_info *di) +static struct raid_dev * +hpt45x_read(struct lib_context *lc, struct dev_info *di) { return read_raid_dev(lc, di, NULL, sizeof(struct hpt45x), HPT45X_CONFIGOFFSET, @@ -208,8 +217,8 @@ /* * Write a Highpoint 45X RAID device. */ -static int hpt45x_write(struct lib_context *lc, - struct raid_dev *rd, int erase) +static int +hpt45x_write(struct lib_context *lc, struct raid_dev *rd, int erase) { int ret; #if BYTE_ORDER != LITTLE_ENDIAN @@ -229,12 +238,14 @@ * * FIXME: more sanity checks. */ -static unsigned int devices(struct raid_dev *rd, void *context) +static unsigned int +devices(struct raid_dev *rd, void *context) { - return (META(rd, hpt45x))->raid_disks; + return META(rd, hpt45x)->raid_disks; } -static int hpt45x_check(struct lib_context *lc, struct raid_set *rs) +static int +hpt45x_check(struct lib_context *lc, struct raid_set *rs) { return check_raid_set(lc, rs, devices, NULL, NO_CHECK_RD, NULL, handler); @@ -243,7 +254,8 @@ /* * IO error event handler. */ -static int event_io(struct lib_context *lc, struct event_io *e_io) +static int +event_io(struct lib_context *lc, struct event_io *e_io) { struct raid_dev *rd = e_io->rd; struct hpt45x *hpt = META(rd, hpt45x); @@ -253,20 +265,20 @@ return 0; hpt->magic = HPT45X_MAGIC_BAD; - return 1; } static struct event_handlers hpt45x_event_handlers = { .io = event_io, - .rd = NULL, /* FIXME: no device add/remove event handler yet. */ + .rd = NULL, /* FIXME: no device add/remove event handler yet. */ }; #ifdef DMRAID_NATIVE_LOG /* * Log native information about an HPT45X RAID device. */ -static void hpt45x_log(struct lib_context *lc, struct raid_dev *rd) +static void +hpt45x_log(struct lib_context *lc, struct raid_dev *rd) { unsigned int i; struct hpt45x *hpt = META(rd, hpt45x); @@ -293,35 +305,37 @@ #endif static struct dmraid_format hpt45x_format = { - .name = HANDLER, - .descr = "Highpoint HPT45X", - .caps = "S,0,1,10", + .name = HANDLER, + .descr = "Highpoint HPT45X", + .caps = "S,0,1,10", .format = FMT_RAID, - .read = hpt45x_read, - .write = hpt45x_write, - .group = hpt45x_group, - .check = hpt45x_check, - .events = &hpt45x_event_handlers, + .read = hpt45x_read, + .write = hpt45x_write, + .group = hpt45x_group, + .check = hpt45x_check, + .events = &hpt45x_event_handlers, #ifdef DMRAID_NATIVE_LOG - .log = hpt45x_log, + .log = hpt45x_log, #endif }; /* Register this format handler with the format core. */ -int register_hpt45x(struct lib_context *lc) +int +register_hpt45x(struct lib_context *lc) { return register_format_handler(lc, &hpt45x_format); } /* Calculate RAID device size in sectors depending on RAID type. */ -static uint64_t sectors(struct raid_dev *rd, void *meta) +static uint64_t +sectors(struct raid_dev *rd, void *meta) { struct hpt45x *hpt = meta; switch (rd->type) { case t_raid0: return hpt->total_secs / - (hpt->raid_disks ? hpt->raid_disks : 1); + (hpt->raid_disks ? hpt->raid_disks : 1); case t_raid1: return hpt->total_secs; @@ -332,8 +346,9 @@ } /* Set the RAID device contents up derived from the Highpoint ones */ -static int setup_rd(struct lib_context *lc, struct raid_dev *rd, - struct dev_info *di, void *meta, union read_info *info) +static int +setup_rd(struct lib_context *lc, struct raid_dev *rd, + struct dev_info *di, void *meta, union read_info *info) { struct hpt45x *hpt = meta; @@ -342,18 +357,18 @@ rd->meta_areas->offset = HPT45X_CONFIGOFFSET >> 9; rd->meta_areas->size = sizeof(*hpt); - rd->meta_areas->area = (void*) hpt; + rd->meta_areas->area = (void *) hpt; rd->di = di; rd->fmt = &hpt45x_format; rd->status = status(hpt); - rd->type = type(hpt); + rd->type = type(hpt); rd->offset = HPT45X_DATAOFFSET; if (!(rd->sectors = sectors(rd, hpt))) return log_zero_sectors(lc, di->path, handler); return (rd->name = name(lc, rd, hpt->raid1_type == HPT45X_T_RAID1)) ? - 1 : 0; + 1 : 0; } --- dmraid/lib/format/ataraid/hpt45x.h 2008/02/22 16:57:36 1.1 +++ dmraid/lib/format/ataraid/hpt45x.h 2008/06/20 21:52:17 1.2 @@ -15,36 +15,36 @@ /* Highpoint 45x config data sector offset off end of disk */ #define HPT45X_CONFIGOFFSET ((di->sectors - 11) << 9) -#define HPT45X_DATAOFFSET 0 /* Data offset in sectors */ +#define HPT45X_DATAOFFSET 0 /* Data offset in sectors */ /* Ondisk metadata for Highpoint 45X ATARAID */ struct hpt45x { - uint32_t magic; /* 0x0 - 0x03 */ + uint32_t magic; /* 0x0 - 0x03 */ #define HPT45X_MAGIC_OK 0x5a7816f3 #define HPT45X_MAGIC_BAD 0x5a7816fd - uint32_t magic_0; /* 0x04 - 0x07 Set identifier */ - uint32_t magic_1; /* 0x08 - 0x0A (Sub-)Array identifier */ + uint32_t magic_0; /* 0x04 - 0x07 Set identifier */ + uint32_t magic_1; /* 0x08 - 0x0A (Sub-)Array identifier */ - uint32_t total_secs; /* 0x0B - 0x0F */ + uint32_t total_secs; /* 0x0B - 0x0F */ - uint8_t type; /* 0x10 */ + uint8_t type; /* 0x10 */ #define HPT45X_T_SPAN 0x04 #define HPT45X_T_RAID0 0x05 #define HPT45X_T_RAID1 0x06 - uint8_t raid_disks; /* 0x11 */ - uint8_t disk_number; /* 0x12 */ - uint8_t raid0_shift; /* 0x13 */ - - uint32_t dummy[3]; /* 0x14 - 0x1F */ - - uint8_t raid1_type; /* 0x20 */ - uint8_t raid1_raid_disks; /* 0x21 */ - uint8_t raid1_disk_number; /* 0x22 */ - uint8_t raid1_shift; /* 0x23 */ + uint8_t raid_disks; /* 0x11 */ + uint8_t disk_number; /* 0x12 */ + uint8_t raid0_shift; /* 0x13 */ + + uint32_t dummy[3]; /* 0x14 - 0x1F */ + + uint8_t raid1_type; /* 0x20 */ + uint8_t raid1_raid_disks; /* 0x21 */ + uint8_t raid1_disk_number; /* 0x22 */ + uint8_t raid1_shift; /* 0x23 */ - uint32_t dummy1[3]; /* 0x24 - 0x2F */ + uint32_t dummy1[3]; /* 0x24 - 0x2F */ } __attribute__ ((packed)); #endif --- dmraid/lib/format/ataraid/isw.c 2008/04/02 13:35:31 1.3 +++ dmraid/lib/format/ataraid/isw.c 2008/06/20 21:52:17 1.4 @@ -1,9 +1,12 @@ /* * Intel Software RAID metadata format handler. * - * Copyright (C) 2004,2005 Heinz Mauelshagen, Red Hat GmbH. + * Copyright (C) 2004-2008 Heinz Mauelshagen, Red Hat GmbH. * All rights reserved. * + * Copyright (C) 2007,2008 Intel Corporation. All rights reserved. + * November, 2007 - additions for Create, Delete, Rebuild & Raid 10. + * * See file LICENSE at the top of this source tree for license information. */ @@ -15,7 +18,9 @@ */ #define HANDLER "isw" +#include <time.h> #include "internal.h" +#include <device/scsi.h> #define FORMAT_HANDLER #include "isw.h" @@ -24,74 +29,168 @@ # include <datastruct/byteorder.h> #endif +#define GB_DIV 1024/1024/2 + static const char *handler = HANDLER; -/* - * Make up RAID set name from family_num and volume name. - */ -static size_t _name(struct isw *isw, struct isw_dev *dev, - char *str, size_t len) -{ - return snprintf(str, len, dev ? "isw_%u_%s" : "isw_%u", - isw->family_num, (char*) dev->volume); +/* Return minimum/maximum disks for a given RAID level. */ +static uint16_t +_num_disks(uint8_t raid_level, int max) +{ + struct mm { + uint8_t level; + uint16_t min, max; + }; + static struct mm mm[] = { + {ISW_T_RAID0, 2, 6}, + {ISW_T_RAID1, 2, 2}, + {ISW_T_RAID10, 4, 4}, + {ISW_T_RAID5, 3, 6}, + }; + struct mm *m = ARRAY_END(mm); + + while (m-- > mm) { + if (raid_level == m->level) + return max ? m->max : m->min; + } + + return 1; } -static char *name(struct lib_context *lc, struct isw *isw, struct isw_dev *dev) +static inline uint16_t +min_num_disks(uint8_t raid_level) { - size_t len; - char *ret; + return _num_disks(raid_level, 0); +} - if ((ret = dbg_malloc((len = _name(isw, dev, NULL, 0) + 1)))) { - _name(isw, dev, ret, len); - mk_alpha(lc, ret + HANDLER_LEN, len - HANDLER_LEN - - (dev ? strlen((char*) dev->volume) - 2 : 1)); - } else - log_alloc_err(lc, handler); +static inline uint16_t +max_num_disks(uint8_t raid_level) +{ + return _num_disks(raid_level, 1); +} - return ret; +/* Check if given device belongs to a RAID10 mapping. */ +static int +is_raid10(struct isw_dev *dev) +{ + return dev ? (dev->vol.map.raid_level == ISW_T_RAID10 || + (dev->vol.map.raid_level == ISW_T_RAID1 && + dev->vol.map.num_members >= + min_num_disks(ISW_T_RAID10))) : 0; } /* Find a disk table slot by serial number. */ -static struct isw_disk *_get_disk(struct isw *isw, struct dev_info *di) +static struct isw_disk * +_get_disk(struct isw *isw, struct dev_info *di) { if (di->serial) { + int i = isw->num_disks; struct isw_disk *disk = isw->disk; - do { - if (!strncmp(di->serial, (const char*) disk->serial, + while (i--) { + if (!strncmp(di->serial, (const char *) disk[i].serial, MAX_RAID_SERIAL_LEN)) - return disk; - } while (++disk < isw->disk + isw->num_disks); + return disk + i; + } } return NULL; } -static struct isw_disk *get_disk(struct lib_context *lc, - struct dev_info *di, struct isw *isw) +static struct isw_disk * +get_disk(struct lib_context *lc, struct dev_info *di, struct isw *isw) { struct isw_disk *disk; if ((disk = _get_disk(isw, di))) return disk; - LOG_ERR(lc, NULL, "%s: Error finding disk table slot for %s", + LOG_ERR(lc, NULL, "%s: Could not find disk %s in the metadata", handler, di->path); } + +enum name_type { N_PATH, N_NUMBER, N_VOLUME, N_VOLUME_FORCE }; +static size_t +_name(struct lib_context *lc, struct isw *isw, char *str, size_t len, + enum name_type nt, int num, struct isw_dev *dev, struct raid_dev *rd) +{ + struct { + const char *fmt, *what; + } formats[] = { + { + "isw_%u_%s", rd->di->path}, { + "isw_%u", NULL}, { + "isw_%u_%s", (const char *) dev->volume}, { + "isw_%u_%s-%u", (const char *) dev->volume},}, *f = formats; + + if (nt < 0 || nt > N_VOLUME_FORCE) + LOG_ERR(lc, 0, "unsupported name type"); + + if (nt == N_VOLUME_FORCE) + f += N_VOLUME; + else { + f += nt; + if (nt == N_VOLUME) + f += (is_raid10(dev) ? 1 : 0); + } + + return snprintf(str, len, f->fmt, isw->family_num, f->what, num); +} + +static char * +name(struct lib_context *lc, struct raid_dev *rd, + struct isw_dev *dev, enum name_type nt) +{ + size_t len; + char *ret = NULL; + int id = 0; + struct isw *isw = META(rd, isw); + struct isw_disk *disk = isw->disk; + + if (nt == N_VOLUME && is_raid10(dev)) { + if ((disk = _get_disk(isw, rd->di))) { + int i = max_num_disks(ISW_T_RAID10); + + while (i--) { + if (disk == isw->disk + i) { + id = i % 2; + goto ok; + } + } + + return NULL; + } + } + + ok: + if ((ret = alloc_private(lc, handler, + (len = _name(lc, isw, ret, 0, nt, id, + dev, rd) + 1)))) { + _name(lc, isw, ret, len, nt, id, dev, rd); + len = snprintf(ret, 0, "%u", isw->family_num); + mk_alpha(lc, ret + HANDLER_LEN, len); + } + else + log_alloc_err(lc, handler); + + return ret; +} + /* * Retrieve status of device. * * FIXME: is this sufficient to cover all state ? */ -static enum status __status(unsigned int status) +static enum status +__status(unsigned status) { - return ((status & (CONFIGURED_DISK|USABLE_DISK)) && - !(FAILED_DISK & status)) ? - s_ok : s_broken; + return ((status & (CONFIGURED_DISK | USABLE_DISK)) && + !(FAILED_DISK & status)) ? s_ok : s_broken; } -static enum status status(struct lib_context *lc, struct raid_dev *rd) +static enum status +status(struct lib_context *lc, struct raid_dev *rd) { struct isw_disk *disk; @@ -101,30 +200,53 @@ return s_undef; } +/* Mapping of Intel types to generic types. */ +static struct types types[] = { + {ISW_T_RAID0, t_raid0}, + {ISW_T_RAID1, t_raid1}, + {ISW_T_RAID5, t_raid5_la}, + /* Only left asymmetric supported now. + { ISW_T_RAID5, t_raid5_ls}, + { ISW_T_RAID5, t_raid5_ra}, + { ISW_T_RAID5, t_raid5_rs}, */ + {ISW_T_RAID10, t_raid1}, + {ISW_T_SPARE, t_spare}, + {ISW_T_UNDEF, t_undef}, +}; + +static uint8_t +_get_raid_level(enum type raid_type) +{ + int i; + + for (i = 0; + types[i].unified_type != t_undef && + types[i].unified_type != raid_type; i++); + + return types[i].type; +} + /* Neutralize disk type. */ -static enum type type(struct raid_dev *rd) +static enum type +type(struct isw_dev *dev) { - /* Mapping of Intel types to generic types. */ - static struct types types[] = { - { ISW_T_RAID0, t_raid0}, - { ISW_T_RAID1, t_raid1}, - { ISW_T_RAID5, t_raid5_la}, - { 0, t_undef}, - }; - struct isw_dev *dev = rd->private.ptr; - return dev ? rd_type(types, (unsigned int) dev->vol.map.raid_level) : - t_group; + if (is_raid10(dev)) + return t_raid1; + + return dev ? rd_type(types, (unsigned) dev->vol.map.raid_level) : + t_group; } /* * Generate checksum of Raid metadata for mpb_size/sizeof(u32) words * (checksum field itself ignored for this calculation). */ -static uint32_t _checksum(struct isw *isw) +static uint32_t +_checksum(struct isw *isw) { uint32_t end = isw->mpb_size / sizeof(end), - *p = (uint32_t*) isw, ret = 0; + *p = (uint32_t *) isw, ret = 0; while (end--) ret += *p++; @@ -133,16 +255,17 @@ } /* Calculate next isw device offset. */ -static struct isw_dev *advance_dev(struct isw_dev *dev, - struct isw_map *map, size_t add) +static struct isw_dev * +advance_dev(struct isw_dev *dev, struct isw_map *map, size_t add) { - return (struct isw_dev*) ((uint8_t*) dev + - (map->num_members - 1) * - sizeof(map->disk_ord_tbl) + add); + return (struct isw_dev *) ((uint8_t *) dev + + (map->num_members - 1) * + sizeof(map->disk_ord_tbl) + add); } /* Advance to the next isw_dev from a given one. */ -static struct isw_dev *advance_raiddev(struct isw_dev *dev) +static struct isw_dev * +advance_raiddev(struct isw_dev *dev) { struct isw_vol *vol = &dev->vol; struct isw_map *map = &vol->map; @@ -150,16 +273,18 @@ /* Correction: yes, it sits here! */ dev = advance_dev(dev, map, sizeof(*dev)); - if (vol->migr_state) /* need to add space for another map */ + if (vol->migr_state) + /* Need to add space for another map. */ dev = advance_dev(dev, map, sizeof(*map)); return dev; } /* Return isw_dev by table index. */ -static struct isw_dev *raiddev(struct isw *isw, unsigned int i) +static struct isw_dev * +raiddev(struct isw *isw, unsigned i) { - struct isw_dev *dev = (struct isw_dev*) (isw->disk + isw->num_disks); + struct isw_dev *dev = (struct isw_dev *) (isw->disk + isw->num_disks); while (i--) dev = advance_raiddev(dev); @@ -179,9 +304,10 @@ * We can differ from the read_raid_dev template here, * because we don't get called from there. */ -static void to_cpu(struct isw *isw, enum convert cvt) +static void +to_cpu(struct isw *isw, enum convert cvt) { - unsigned int i, j; + unsigned i, j; struct isw_disk *dsk; struct isw_dev *dev; @@ -211,7 +337,7 @@ CVT32(dev->reserved_blocks); /* RAID volume has 8 bit members only. */ - + /* RAID map. */ CVT32(dev->vol.map.pba_of_lba0); CVT32(dev->vol.map.blocks_per_member); @@ -224,29 +350,45 @@ } #endif -static int is_isw(struct lib_context *lc, struct dev_info *di, struct isw *isw) +/* Return sector rounded size of isw metadata. */ +static size_t +isw_size(struct isw *isw) +{ + return round_up(isw->mpb_size, ISW_DISK_BLOCK_SIZE); +} + +/* Set metadata area size in bytes and config offset in sectors. */ +static void +set_metadata_sizoff(struct raid_dev *rd, size_t size) +{ + rd->meta_areas->size = size; + rd->meta_areas->offset = ISW_CONFIGSECTOR(rd->di) - + size / ISW_DISK_BLOCK_SIZE + 1; +} + +/* Check for isw signature (magic) and version. */ +static int +is_isw(struct lib_context *lc, struct dev_info *di, struct isw *isw) { - if (strncmp((const char *) isw->sig, MPB_SIGNATURE, - sizeof(MPB_SIGNATURE) - 1)) + if (strncmp((const char *) isw->sig, MPB_SIGNATURE, MPB_SIGNATURE_SIZE)) return 0; - /* Check version info, older versions supported */ - if (strncmp((const char*) isw->sig + sizeof(MPB_SIGNATURE) - 1, - MPB_VERSION_RAID2, sizeof(MPB_VERSION_RAID2) - 1) > 0) - log_print(lc, "%s: untested metadata version %s found on %s", - handler, isw->sig + sizeof(MPB_SIGNATURE) - 1, - di->path); + /* Check version info; older versions supported. */ + if (strncmp((const char *) isw->sig + MPB_SIGNATURE_SIZE, + MPB_VERSION_RAID2, MPB_VERSION_RAID2_SIZE) > 0) + log_print(lc, + "%s: untested metadata version %s found on %s", + handler, isw->sig + MPB_SIGNATURE_SIZE, di->path); return 1; } -static void isw_file_metadata(struct lib_context *lc, struct dev_info *di, - void *meta) +static void +isw_file_metadata(struct lib_context *lc, struct dev_info *di, void *meta) { struct isw *isw = meta; - /* Get the rounded up value for the metadata size */ - size_t size = round_up(isw->mpb_size, ISW_DISK_BLOCK_SIZE); + size_t size = isw_size(isw); file_metadata(lc, handler, di->path, meta + (size / ISW_DISK_BLOCK_SIZE > 1 ? @@ -255,62 +397,54 @@ file_dev_size(lc, handler, di); } -static int isw_read_extended(struct lib_context *lc, struct dev_info *di, - struct isw **isw, - uint64_t *isw_sboffset, size_t *size) +static int +isw_read_extended(struct lib_context *lc, struct dev_info *di, + struct isw **isw, uint64_t * isw_sboffset, size_t * size) { struct isw *isw_tmp; - /* Get the rounded up value for the metadata blocks */ size_t blocks = div_up((*isw)->mpb_size, ISW_DISK_BLOCK_SIZE); - /* No extended metadata to read ? */ - if (blocks < 2) - return 1; - - /* - * Allocate memory for the extended Intel superblock - * and read it in. Reserve one more disk block in order - * to be able to file the metadata in the proper sequence. - * (ie, sectors 1, 2-n, 1 in core so that the filing can start at 2). - */ + /* Allocate memory for the extended Intel superblock and read it in. */ *size = blocks * ISW_DISK_BLOCK_SIZE; *isw_sboffset -= *size - ISW_DISK_BLOCK_SIZE; - if ((isw_tmp = alloc_private(lc, handler, - *size + ISW_DISK_BLOCK_SIZE))) { + if ((isw_tmp = alloc_private(lc, handler, *size))) { + /* Copy in first metadata sector. */ + memcpy(isw_tmp, *isw, ISW_DISK_BLOCK_SIZE); + /* Read extended metadata to offset ISW_DISK_BLOCK_SIZE */ - if (read_file(lc, handler, di->path, - (void*) isw_tmp + ISW_DISK_BLOCK_SIZE, - *size - ISW_DISK_BLOCK_SIZE, *isw_sboffset)) - /* Copy in first metadata sector. */ - memcpy(isw_tmp, *isw, ISW_DISK_BLOCK_SIZE); - else { + if (blocks > 1 && + !read_file(lc, handler, di->path, + (void *) isw_tmp + ISW_DISK_BLOCK_SIZE, + *size - ISW_DISK_BLOCK_SIZE, *isw_sboffset)) { dbg_free(isw_tmp); isw_tmp = NULL; } } + else + return 0; dbg_free(*isw); *isw = isw_tmp; - - return isw_tmp ? 1 : 0; + return *isw ? 1 : 0; } /* Check for RAID disk ok. */ -static int disk_ok(struct lib_context *lc, struct dev_info *di, struct isw *isw) +static int +disk_ok(struct lib_context *lc, struct dev_info *di, struct isw *isw) { struct isw_disk *disk = get_disk(lc, di, isw); return disk && __status(disk->status) == s_ok; } -static void *isw_read_metadata(struct lib_context *lc, struct dev_info *di, - size_t *sz, uint64_t *offset, - union read_info *info) +static void * +isw_read_metadata(struct lib_context *lc, struct dev_info *di, + size_t * sz, uint64_t * offset, union read_info *info) { size_t size = ISW_DISK_BLOCK_SIZE; - uint64_t isw_sboffset = ISW_CONFIGOFFSET; + uint64_t isw_sboffset = ISW_CONFIGOFFSET(di); struct isw *isw; if (!(isw = alloc_private_and_read(lc, handler, size, @@ -336,57 +470,60 @@ if (disk_ok(lc, di, isw)) { *sz = size; - *offset = isw_sboffset; - info->u64 = isw_sboffset; + *offset = info->u64 = isw_sboffset; goto out; } - - bad: + + bad: dbg_free(isw); isw = NULL; - out: - return (void*) isw; + out: + return (void *) isw; } static int setup_rd(struct lib_context *lc, struct raid_dev *rd, struct dev_info *di, void *meta, union read_info *info); -static struct raid_dev *isw_read(struct lib_context *lc, struct dev_info *di) +static struct raid_dev * +isw_read(struct lib_context *lc, struct dev_info *di) { return read_raid_dev(lc, di, isw_read_metadata, 0, 0, NULL, NULL, isw_file_metadata, setup_rd, handler); } /* - * Write an Intel Software RAID device. + * Write metadata to an Intel Software RAID device. */ -static int isw_write(struct lib_context *lc, struct raid_dev *rd, int erase) +static int +isw_write(struct lib_context *lc, struct raid_dev *rd, int erase) { int ret; struct isw *isw = META(rd, isw); - int large = div_up(isw->mpb_size, ISW_DISK_BLOCK_SIZE) > 1; + void *dst, *src = isw; + uint32_t size = isw->mpb_size; to_disk(isw, FULL); - if (large) { - /* - * Copy 1st metadata sector to after the extended ones - * and increment metadata area pointer by one block, so - * that the metadata is filed in the proper sequence. - */ - memcpy((void*) isw + rd->meta_areas->size, isw, - ISW_DISK_BLOCK_SIZE); - rd->meta_areas->area += ISW_DISK_BLOCK_SIZE; - } + /* Flip sectors for write_metadata() to work if extended metadata. */ + if (size > ISW_DISK_BLOCK_SIZE) { + /* sunil */ + dst = alloc_private(lc, handler, 2 * ISW_DISK_BLOCK_SIZE); + if (!dst) + return 0; + memcpy(dst, src + ISW_DISK_BLOCK_SIZE, ISW_DISK_BLOCK_SIZE); + memcpy(dst + ISW_DISK_BLOCK_SIZE, src, ISW_DISK_BLOCK_SIZE); + } + else + dst = isw; + rd->meta_areas->area = dst; ret = write_metadata(lc, handler, rd, -1, erase); + rd->meta_areas->area = isw; - /* Correct metadata area pointer. */ - if (large) - rd->meta_areas->area -= ISW_DISK_BLOCK_SIZE; + if (dst != isw) + dbg_free(dst); to_cpu(isw, FULL); - return ret; } @@ -395,137 +532,222 @@ * multiple RAID sets and RAID disks. */ /* Check state if isw device map. */ -static int _check_map_state(struct lib_context *lc, struct raid_dev *rd, - struct isw_dev *dev) +static int +_check_map_state(struct lib_context *lc, struct raid_dev *rd, + struct isw_dev *dev) { /* FIXME: FAILED_MAP etc. */ switch (dev->vol.map.map_state) { case ISW_T_STATE_NORMAL: case ISW_T_STATE_UNINITIALIZED: + case ISW_T_STATE_DEGRADED: + case ISW_T_STATE_FAILED: break; default: - LOG_ERR(lc, 0, "%s: unsupported map state 0x%x on %s for %s", + LOG_ERR(lc, 0, + "%s: unsupported map state 0x%x on %s for %s", handler, dev->vol.map.map_state, rd->di->path, - (char*) dev->volume); + (char *) dev->volume); } return 1; } /* Create a RAID device to map a volumes segment. */ -static struct raid_dev *_create_rd(struct lib_context *lc, struct raid_dev *rd, - struct isw *isw, struct isw_dev *dev) +static struct raid_dev * +_create_rd(struct lib_context *lc, + struct raid_dev *rd, struct isw *isw, struct isw_dev *dev) { struct raid_dev *r; - if (!_check_map_state(lc, rd, dev) || - !(r = alloc_raid_dev(lc, handler))) + if (!(r = alloc_raid_dev(lc, handler))) return NULL; + if (!(r->meta_areas = alloc_meta_areas(lc, rd, handler, 1))) + goto free; + + /* Configuration for spare disk. */ + if (isw->disk[0].status & SPARE_DISK) { + r->meta_areas->offset = rd->meta_areas->offset; + r->meta_areas->size = rd->meta_areas->size; + r->meta_areas->area = + alloc_private(lc, handler, rd->meta_areas->size); + memcpy(r->meta_areas->area, rd->meta_areas->area, + rd->meta_areas->size); + + r->type = t_spare; + if (!(r->name = name(lc, rd, NULL, N_PATH))) + goto free; + + r->di = rd->di; + r->fmt = rd->fmt; + r->sectors = ISW_CONFIGSECTOR(r->di); + goto out; + } + + if (!_check_map_state(lc, rd, dev)) + goto free; + if (!(r->private.ptr = alloc_private(lc, handler, sizeof(*dev)))) goto free; memcpy(r->private.ptr, dev, sizeof(*dev)); - if ((r->type = type(r)) == t_undef) { + + r->meta_areas->offset = rd->meta_areas->offset; + r->meta_areas->size = rd->meta_areas->size; + r->meta_areas->area = alloc_private(lc, handler, rd->meta_areas->size); + memcpy(r->meta_areas->area, rd->meta_areas->area, rd->meta_areas->size); + + if ((r->type = type(dev)) == t_undef) { log_err(lc, "%s: RAID type %u not supported", - handler, (unsigned int) dev->vol.map.raid_level); + handler, (unsigned) dev->vol.map.raid_level); goto free; } - if (!(r->name = name(lc, isw, dev))) + if (!(r->name = name(lc, rd, dev, N_VOLUME))) goto free; r->di = rd->di; r->fmt = rd->fmt; - - r->offset = dev->vol.map.pba_of_lba0; + r->offset = dev->vol.map.pba_of_lba0; if ((r->sectors = dev->vol.map.blocks_per_member)) goto out; log_zero_sectors(lc, rd->di->path, handler); - free: + free: free_raid_dev(lc, &r); - out: + out: return r; } /* Find an Intel RAID set or create it. */ -static void create_rs(struct raid_set *rs, void* private) +static void +create_rs(struct raid_set *rs, void *private) { - rs->stride = ((struct isw_dev*) private)->vol.map.blocks_per_strip; + rs->stride = ((struct isw_dev *) private)->vol.map.blocks_per_strip; } /* Decide about ordering sequence of RAID device. */ -static int dev_sort(struct list_head *pos, struct list_head *new) +static int +dev_sort(struct list_head *pos, struct list_head *new) { struct isw *isw = RD(new)->private.ptr; - + return _get_disk(isw, RD(new)->di) < _get_disk(isw, RD(pos)->di); } +static void +super_created(struct raid_set *super, void *private) +{ + super->type = t_raid0; + super->stride = ((struct isw_dev *) private)->vol.map.blocks_per_strip; +} + /* * rs_group contains the top-level group RAID set (type: t_group) on entry * and shall be returned on success (or NULL on error). */ -static struct raid_set *group_rd(struct lib_context *lc, - struct raid_set *rs_group, - struct raid_dev *rd_meta) +static struct raid_set * +group_rd(struct lib_context *lc, + struct raid_set *rs_group, struct raid_dev *rd_meta) { - unsigned int d; + unsigned d; void *private; struct isw *isw = META(rd_meta, isw); struct isw_dev *dev; struct raid_dev *rd; - struct raid_set *rs; + struct raid_set *rs, *ss; + char *ss_name = NULL; - /* Loop the device/volume table. */ - for (d = 0; d < isw->num_raid_devs; d++) { - dev = raiddev(isw, d); + /* Configuration for spare disk. */ + if (isw->disk[0].status & SPARE_DISK) { + + /* Spare disk has no device description. */ + dev = NULL; if (!(rd = _create_rd(lc, rd_meta, isw, dev))) return NULL; - if (!(rs = find_or_alloc_raid_set(lc, rd->name, FIND_ALL, - rd, &rs_group->sets, - create_rs, dev))) { + if (!(rs = find_or_alloc_raid_set(lc, rd->name, + FIND_ALL, rd, + &rs_group->sets, NULL, + NULL))) { free_raid_dev(lc, &rd); return NULL; } - /* Save and set to enable dev_sort(). */ - private = rd->private.ptr; - rd->private.ptr = isw; - + rs->status = s_ok; list_add_sorted(lc, &rs->devs, &rd->devs, dev_sort); + } + else { + /* Loop the device/volume table. */ + for (d = 0; d < isw->num_raid_devs; d++) { + dev = raiddev(isw, d); + + if (!(rd = _create_rd(lc, rd_meta, isw, dev))) + return NULL; + if (is_raid10(dev)) { + ss_name = name(lc, rd, dev, N_VOLUME_FORCE); + ss = find_or_alloc_raid_set(lc, ss_name, + FIND_ALL, rd, + &rs_group->sets, + super_created, dev); + + if (!ss) { + dbg_free(ss_name); + free_raid_dev(lc, &rd); + return NULL; + } + } + else + ss = rs_group; + + if (!(rs = find_or_alloc_raid_set(lc, rd->name, + FIND_ALL, rd, + &ss->sets, create_rs, + dev))) { + free_raid_dev(lc, &rd); + return NULL; + } + + rs->status = s_ok; + + /* Save and set to enable dev_sort(). */ + private = rd->private.ptr; + rd->private.ptr = isw; + list_add_sorted(lc, &rs->devs, &rd->devs, dev_sort); + /* Restore. */ + rd->private.ptr = private; - /* Restore. */ - rd->private.ptr = private; + } } return rs_group; } /* Add an Intel SW RAID device to a set */ -static struct raid_set *isw_group(struct lib_context *lc, - struct raid_dev *rd_meta) +static struct raid_set * +isw_group(struct lib_context *lc, struct raid_dev *rd_meta) { - struct raid_set *rs_group; + struct raid_set *rs_group = NULL; - if (T_SPARE(rd_meta)) - return NULL; /* * Once we get here, an Intel SW RAID disk containing a metadata area - * with a volume table has been discovered by isw_read. + * with a volume table has been discovered by isw_read. There is one + * goup RAID set for each metadata configuration. The volume defined in + * the metadata is a subset of the group RAID set. */ + /* Check if a top level group RAID set already exists. */ - if (!(rs_group = find_or_alloc_raid_set(lc, rd_meta->name, FIND_TOP, - rd_meta, LC_RS(lc), - NO_CREATE, NO_CREATE_ARG))) + if (!(rs_group = + find_or_alloc_raid_set(lc, rd_meta->name, FIND_TOP, rd_meta, + LC_RS(lc), NO_CREATE, NO_CREATE_ARG))) return NULL; + /* * Add the whole underlying (meta) RAID device to the group set. * Sorting is no problem here, because RAID sets and devices will @@ -535,6 +757,13 @@ list_add_sorted(lc, &rs_group->devs, &rd_meta->devs, dev_sort); rd_meta->private.ptr = NULL; + + /* mark spare set as group set */ + if (T_SPARE(rs_group)) + rs_group->type = t_group; + + + /* * We need to run through the volume table and create a RAID set and * RAID devices hanging off it for every volume, @@ -543,264 +772,1894 @@ * A pointer to the top-level group RAID set * gets returned or NULL on error. */ - return group_rd(lc, rs_group, rd_meta); + struct raid_set *ret = group_rd(lc, rs_group, rd_meta); + + return ret; } -/* - * Check an Intel SW RAID set. - * - * FIXME: more sanity checks. - */ -static unsigned int devices(struct raid_dev *rd, void *context) +static unsigned +adjust_length(struct isw_dev *dev, struct isw_dev *dev_rebuilt, + unsigned map_size) { - return ((struct isw_dev*) rd->private.ptr)->vol.map.num_members; + return (dev == dev_rebuilt || !dev->vol.migr_state) ? + map_size : 2 * map_size; } -static int check_rd(struct lib_context *lc, struct raid_set *rs, - struct raid_dev *rd, void *context) +/* + * Find out index of a raid device in isw_dev array by name. + * The function returns -1 if no relevant device can be found. + */ +static int +rd_idx_by_name(struct isw *isw, const char *name) { - struct isw_dev *dev = rd->private.ptr; + int i = isw->num_raid_devs; - /* FIXME: more status checks ? */ - if (dev->status) - LOG_ERR(lc, 0, "%s device for volume \"%s\" broken on %s " - "in RAID set \"%s\"", - handler, dev->volume, rd->di->path, rs->name); + while (i--) { + if (strstr(name, (const char *) raiddev(isw, i)->volume)) + return i; + } - return 1; + return -ENOENT; } -static int _isw_check(struct lib_context *lc, struct raid_set *rs) +/* Return RAID device for serial string. */ +static struct raid_dev * +rd_by_serial(struct raid_set *rs, const char *serial) { - return check_raid_set(lc, rs, devices, NULL, check_rd, NULL, handler); -} + struct raid_dev *rd; -static int isw_check(struct lib_context *lc, struct raid_set *rs) -{ - return T_GROUP(rs) ? _isw_check(lc, rs) : 0; + list_for_each_entry(rd, &rs->devs, devs) { + if (rd->di && + !strncmp(rd->di->serial, serial, MAX_RAID_SERIAL_LEN)) + return rd; + } + + return NULL; } -/* - * IO error event handler. - */ -static int event_io(struct lib_context *lc, struct event_io *e_io) +static struct isw * +update_metadata_after_rebuild(struct lib_context *lc, struct raid_set *rs) { - struct raid_dev *rd = e_io->rd; - struct isw *isw = META(rd, isw); - struct isw_disk *disk; - - if (!(disk = get_disk(lc, rd->di, isw))) - LOG_ERR(lc, 0, "%s: disk", handler); + struct raid_dev *rd = list_entry(rs->devs.next, struct raid_dev, devs); + struct isw *old_isw = META(rd, isw), *new_isw; + struct isw_dev *old_vol0 = NULL, *old_vol1 = NULL, *vol_rebuilt = NULL; + int vol_rebuilt_idx; + int remove_disk; + unsigned map_size, new_isw_size; + unsigned old_isw_offs, new_isw_offs; + unsigned i; + + + old_vol0 = raiddev(old_isw, 0); + if (old_isw->num_raid_devs > 1) + old_vol1 = raiddev(old_isw, 1); + + /* Determine the volume being rebuilt. */ + vol_rebuilt_idx = + rd_idx_by_name(old_isw, + lc->options[LC_REBUILD_SET].arg.str + + strlen(rs->name) + 1); + if (vol_rebuilt_idx < 0) + return NULL; - /* Avoid write trashing. */ - if (S_BROKEN(status(lc, rd))) - return 0; + /* Modify metadata related to the volume being rebuilt. */ + vol_rebuilt = vol_rebuilt_idx ? old_vol1 : old_vol0; + vol_rebuilt->vol.migr_type = 0; /* FIXME: replace magic numbers */ + vol_rebuilt->vol.migr_state = 0; /* FIXME: replace magic number */ + vol_rebuilt->vol.map.failed_disk_num = 255; /* FIXME: replace magic number */ + + /* Are we going to remove the failed disk from the metadata ? */ + remove_disk = (!old_vol0->vol.migr_type && old_vol1) ? + !old_vol1->vol.migr_type : 1; + + /* Calculate new metadata's size and allocate memory for it. */ + map_size = sizeof(struct isw_map) + + (vol_rebuilt->vol.map.num_members - 1) * + sizeof(((struct isw_map *) NULL)->disk_ord_tbl); + + /* If we remove a disk. */ + new_isw_size = old_isw->mpb_size - /* old size */ + remove_disk * sizeof(struct isw_disk) - map_size; + new_isw = alloc_private(lc, handler, new_isw_size); + + /* Copy metadata structures: struct isw without disks' array. */ + new_isw_offs = old_isw_offs = i = + sizeof(struct isw) - sizeof(struct isw_disk); + memcpy(new_isw, old_isw, i); + + /* Copy metadata structures: disks' array. */ + i = (old_isw->num_disks - remove_disk) * sizeof(struct isw_disk); + memcpy((void *) new_isw + new_isw_offs, + (void *) old_isw + old_isw_offs, i); + new_isw_offs += i; + old_isw_offs += i + remove_disk * sizeof(struct isw_disk); + + /* Copy metadata structures: isw_dev record #0. */ + i = sizeof(struct isw_dev) - sizeof(struct isw_map) + + adjust_length(old_vol0, vol_rebuilt, map_size); + + memcpy((void *) new_isw + new_isw_offs, + (void *) old_isw + old_isw_offs, i); + new_isw_offs += i; + old_isw_offs += i; + if (old_vol0 == vol_rebuilt) + old_isw_offs += map_size; + + /* Copy metadata structures: isw_dev record #1 (if present). */ + if (old_vol1) { + i = sizeof(struct isw_dev) - sizeof(struct isw_map) + + adjust_length(old_vol1, vol_rebuilt, map_size); + memcpy((void *) new_isw + new_isw_offs, + (void *) old_isw + old_isw_offs, i); + new_isw_offs += i; + old_isw_offs += i; - disk->status &= ~USABLE_DISK; - disk->status |= FAILED_DISK; + if (old_vol1 == vol_rebuilt) + old_isw_offs += map_size; + } - return 1; + /* finally update new metadata's fields */ + new_isw->mpb_size = new_isw_size; + new_isw->num_disks -= remove_disk; + new_isw->generation_num++; + new_isw->check_sum = _checksum(new_isw); + return new_isw; } -static struct event_handlers isw_event_handlers = { - .io = event_io, - .rd = NULL, /* FIXME: no device add/remove event handler yet. */ -}; -#ifdef DMRAID_NATIVE_LOG -/* - * Log native information about an ISW RAID device. - */ -static void isw_log(struct lib_context *lc, struct raid_dev *rd) +/* Handle rebuild state. */ +static int +get_rebuild_state(struct lib_context *lc, + struct raid_set *rs, struct raid_dev *rd) { - unsigned int d, i; - struct isw *isw = META(rd, isw); - struct isw_disk *disk; + int idx; + struct raid_dev *check_rd; + struct isw *isw; struct isw_dev *dev; + struct isw_disk *disk; - log_print(lc, "%s (%s):", rd->di->path, handler); - P("sig: \"%*s\"", isw, isw->sig, MAX_SIGNATURE_LENGTH, isw->sig); - DP("check_sum: %u", isw, isw->check_sum); - DP("mpb_size: %u", isw, isw->mpb_size); - DP("family_num: %u", isw, isw->family_num); - DP("generation_num: %u", isw, isw->generation_num); - DP("reserved[0]: %u", isw, isw->reserved[0]); - DP("reserved[1]: %u", isw, isw->reserved[1]); - DP("num_disks: %u", isw, isw->num_disks); - DP("num_raid_devs: %u", isw, isw->num_raid_devs); - DP("fill[0]: %u", isw, isw->fill[0]); - DP("fill[1]: %u", isw, isw->fill[1]); + list_for_each_entry(check_rd, &rs->devs, devs) { + if (check_rd->meta_areas) { + isw = META(check_rd, isw); + + idx = rd_idx_by_name(isw, + lc->options[LC_REBUILD_SET]. + arg.str); + if (idx < 0) + return 0; + + dev = raiddev(isw, idx); + disk = isw->disk; + + if (dev->vol.migr_state && + dev->vol.migr_type && + dev->vol.map.failed_disk_num < isw->num_disks) { + /* + * If rd that belongs to RAID set is + * pointed at by failed disk number + * the RAID set state is migration. + */ + rd = rd_by_serial(rs, + (const char *) disk[dev-> + vol.map.failed_disk_num].serial); + if (rd) + /* + * Found RAID device that belongs to + * RAID set is marked as failed in + * metadata. + */ + return s_nosync; + } + else if (dev->vol.map.map_state == ISW_T_STATE_DEGRADED) + return s_inconsistent; + } + + /* + * Check only first metadata on the + * first rd that has a metadata. + */ + return s_inconsistent; - for (i = 0; i < ISW_FILLERS; i++) { - if (isw->filler[i]) - P("filler[%i]: %u", isw, - isw->filler[i], i, isw->filler[i]); } - /* Disk table. */ - for (d = 0, disk = isw->disk; d < isw->num_disks; d++, disk++) { - if (!disk->totalBlocks) - continue; + return s_inconsistent; +} - P("disk[%u].serial: \"%*s\"", isw, - disk->serial, d, MAX_RAID_SERIAL_LEN, disk->serial); - P("disk[%u].totalBlocks: %u", isw, - disk->totalBlocks, d, disk->totalBlocks); - P("disk[%u].scsiId: 0x%x", isw, disk->scsiId, d, disk->scsiId); - P("disk[%u].status: 0x%x", isw, disk->status, d, disk->status); - for (i = 0; i < ISW_DISK_FILLERS; i++) { - if (disk->filler[i]) - P("disk[%u].filler[%u]: %u", isw, - disk->filler[i], d, i, disk->filler[i]); +/* isw metadata handler routine. */ +static int +isw_metadata_handler(struct lib_context *lc, enum handler_commands command, + struct handler_info *info, void *context) +{ + int idx, ret = 0; + struct raid_set *rs = context; + struct raid_dev *rd = list_entry(rs->devs.next, struct raid_dev, devs); + struct isw *isw, *new_isw; + struct isw_dev *dev; + struct isw_disk *disk; + + switch (command) { + case UPDATE_REBUILD_STATE: + new_isw = update_metadata_after_rebuild(lc, rs); + if (!new_isw) + return 0; + + /* Embed the new metadata on disks. */ + list_for_each_entry(rd, &rs->devs, devs) { + set_metadata_sizoff(rd, isw_size(new_isw)); + memcpy(rd->meta_areas->area, new_isw, + new_isw->mpb_size); + + /* FIXME: use fmt->write from metadata.c instead ? */ + /* FIXME: log update. */ + ret = isw_write(lc, rd, 0); + if (!ret) + break; } - } - /* RAID device/volume table. */ - for (d = 0; d < isw->num_raid_devs; d++) { - dev = raiddev(isw, d); + break; - /* RAID device */ - P("isw_dev[%u].volume: \"%*s\"", isw, - dev->volume, d, MAX_RAID_SERIAL_LEN, dev->volume); - P("isw_dev[%u].SizeHigh: %u", isw, - dev->SizeHigh, d, dev->SizeHigh); - P("isw_dev[%u].SizeLow: %u", isw, - dev->SizeLow, d, dev->SizeLow); - P("isw_dev[%u].status: 0x%x", isw, dev->status, d, dev->status); - P("isw_dev[%u].reserved_blocks: %u", isw, - dev->reserved_blocks, d, dev->reserved_blocks); + case GET_REBUILD_STATE: + return get_rebuild_state(lc, rs, rd); - for (i = 0; i < ISW_DEV_FILLERS; i++) { - if (dev->filler[i]) - P("isw_dev[%u].filler[%u]: %u", isw, - dev->filler[i], d, i, dev->filler[i]); + case GET_REBUILD_DRIVE: + isw = META(rd, isw); + dev = raiddev(isw, 0); + disk = isw->disk + dev->vol.map.failed_disk_num; + + rd = rd_by_serial(rs, (const char *) disk->serial); + if (rd) { + if (info && info->data.str && info->size) { + strncpy(info->data.str, rd->di->path, + info->size); + log_print(lc, + "Rebuild Drive: %s Serial No: %s\n", + rd->di->path, rd->di->serial); + ret = 1; + } + else + log_err(lc, + "Can't provide rebuild drive path!"); } - /* RAID volume */ - for (i = 0; i < 2; i++) { - if (dev->vol.reserved[i]) - P("isw_dev[%u].vol.reserved[%u]: %u", isw, - dev->vol.reserved[i], d, i, - dev->vol.reserved[i]); + break; + + case GET_REBUILD_DRIVE_NO: + rd = list_entry(rs->devs.next, typeof(*rd), devs); + isw = META(rd, isw); + idx = rd_idx_by_name(isw, lc->options[LC_REBUILD_SET].arg.str); + if (idx < 0) + return 0; + + dev = raiddev(isw, idx); + disk = isw->disk; + + if (info) { + if (dev->vol.map.failed_disk_num < + dev->vol.map.num_members) { + info->data.i32 = is_raid10(dev) ? + dev->vol.map.failed_disk_num / + dev->vol.map.num_domains : + dev->vol.map.failed_disk_num; + + ret = 1; + } + else + info->data.i32 = -1; } - P("isw_dev[%u].vol.migr_state: %u", isw, - dev->vol.migr_state, d, dev->vol.migr_state); - P("isw_dev[%u].vol.migr_type: %u", isw, - dev->vol.migr_type, d, dev->vol.migr_type); - P("isw_dev[%u].vol.dirty: %u", isw, - dev->vol.dirty, d, dev->vol.dirty); - P("isw_dev[%u].vol.fill[0]: %u", isw, - dev->vol.fill[0], d, dev->vol.fill[0]); + break; /* case GET_REBUILD_DRIVE_NO */ - for (i = 0; i < 5; i++) { - if (dev->vol.filler[i]) - P("isw_dev[%u].vol.filler[%u]: %u", isw, - dev->vol.filler[i], d, i, - dev->vol.filler[i]); - } - - /* RAID map */ - P("isw_dev[%u].vol.map.pba_of_lba0: %u", isw, - dev->vol.map.pba_of_lba0, d, - dev->vol.map.pba_of_lba0); - P("isw_dev[%u].vol.map.blocks_per_member: %u", isw, - dev->vol.map.blocks_per_member, d, - dev->vol.map.blocks_per_member); - P("isw_dev[%u].vol.map.num_data_stripes: %u", isw, - dev->vol.map.num_data_stripes, d, - dev->vol.map.num_data_stripes); - P("isw_dev[%u].vol.map.blocks_per_strip: %u", isw, - dev->vol.map.blocks_per_strip, d, - dev->vol.map.blocks_per_strip); - P("isw_dev[%u].vol.map.map_state: %u", isw, - dev->vol.map.map_state, d, - dev->vol.map.map_state); - P("isw_dev[%u].vol.map.raid_level: %u", isw, - dev->vol.map.raid_level, d, - dev->vol.map.raid_level); - P("isw_dev[%u].vol.map.num_members: %u", isw, - dev->vol.map.num_members, d, - dev->vol.map.num_members); - - for (i = 0; i < 3; i++) { - if (dev->vol.map.reserved[i]) - P("isw_dev[%u].vol.map.reserved[%u]: %u", isw, - dev->vol.map.reserved[i], d, i, - dev->vol.map.reserved[i]); - } - - for (i = 0; i < 7; i++) { - if (dev->vol.map.filler[i]) - P("isw_dev[%u].vol.map.filler[%u]: %u", isw, - dev->vol.map.filler[i], d, i, - dev->vol.map.filler[i]); - } - - for (i = 0; i < isw->num_disks; i++) { - P("isw_dev[%u].vol.map.disk_ord_tbl[%u]: 0x%x", isw, - dev->vol.map.disk_ord_tbl[i], d, i, - dev->vol.map.disk_ord_tbl[i]); - } - } -} -#endif + default: + LOG_ERR(lc, 0, "%u not yet supported", command); -static struct dmraid_format isw_format = { - .name = HANDLER, - .descr = "Intel Software RAID", - .caps = "0,1,5", - .format = FMT_RAID, - .read = isw_read, - .write = isw_write, - .group = isw_group, - .check = isw_check, - .events = &isw_event_handlers, -#ifdef DMRAID_NATIVE_LOG - .log = isw_log, -#endif -}; + } -/* Register this format handler with the format core. */ -int register_isw(struct lib_context *lc) -{ - return register_format_handler(lc, &isw_format); + return ret; } /* - * Set the RAID device contents up derived from the Intel ones. + * Check an Intel SW RAID set. * - * This is the first one we get with here and we potentially need to - * create many in isw_group() in case of multiple Intel SW RAID devices - * on this RAID disk. + * FIXME: more sanity checks. */ -static int setup_rd(struct lib_context *lc, struct raid_dev *rd, - struct dev_info *di, void *meta, union read_info *info) +static unsigned +devices(struct raid_dev *rd, void *context) { - struct isw *isw = meta; + return rd->type != t_spare ? + ((struct isw_dev *) rd->private.ptr)->vol.map.num_members : 0; +} - /* Superblock checksum */ - if (isw->check_sum != _checksum(isw)) - LOG_ERR(lc, 0, "%s: extended superblock for %s " - "has wrong checksum", - handler, di->path); +static unsigned +devices_per_domain(struct raid_dev *rd, void *context) +{ + return ((struct isw_dev *) rd->private.ptr)->vol.map.num_members / + ((struct isw_dev *) rd->private.ptr)->vol.map.num_domains; +} - if (!(rd->meta_areas = alloc_meta_areas(lc, rd, handler, 1))) - return 0; +static int +check_rd(struct lib_context *lc, struct raid_set *rs, + struct raid_dev *rd, void *context) +{ + struct isw_dev *dev = rd->private.ptr; - rd->meta_areas->offset = info->u64 >> 9; - rd->meta_areas->size = round_up(isw->mpb_size, ISW_DISK_BLOCK_SIZE); - rd->meta_areas->area = (void*) isw; + /* FIXME: more status checks ? */ + if (dev->status) { + LOG_ERR(lc, 0, "%s device for volume \"%s\" broken on %s " + "in RAID set \"%s\"", + handler, dev->volume, rd->di->path, rs->name); - rd->di = di; - rd->fmt = &isw_format; + } - rd->offset = ISW_DATAOFFSET; - if (!(rd->sectors = info->u64 >> 9)) - return log_zero_sectors(lc, di->path, handler); + return 1; +} - rd->status = status(lc, rd); - rd->type = t_group; +static int +_isw_check(struct lib_context *lc, struct raid_set *rs) +{ + struct raid_set *r; + + list_for_each_entry(r, &rs->sets, list) { + if (SETS(r)) + check_raid_set(lc, r, devices_per_domain, NULL, + check_rd, NULL, handler); + else + check_raid_set(lc, r, devices, NULL, check_rd, + NULL, handler); + } + + return 1; +} + +static char * +get_rs_basename(char *str) +{ + char *ret, *end; + + if (!(end = strchr(str, '_'))) + return str; + + if (!(end = strchr((++end), '_'))) + return str; + + if ((ret = strstr(str, "isw_")) == str && strlen(end) > 1) + return ++end; + + return str; +} + +/* Check that volume name is unique. */ +static int +is_name_unique(struct lib_context *lc, struct raid_set *rs) +{ + struct raid_set *rs1, *rs2; + char *bn; + + list_for_each_entry(rs1, LC_RS(lc), list) { + if (rs1->type == t_group) { + list_for_each_entry(rs2, &rs1->sets, list) { + bn = get_rs_basename(rs2->name); + if (!strcmp(bn, rs->name)) + goto out_used; + } + } + else { + bn = get_rs_basename(rs1->name); + if (!strcmp(bn, rs->name)) + goto out_used; + } + } + + return 1; + + out_used: + log_dbg(lc, "%s is being used", bn); + return 0; +} + +static int +check_capability(struct raid_set *rs) +{ + uint8_t raid_level = _get_raid_level(rs->type); + + if (SETS(rs)) { + struct raid_set *rs1 = + list_entry(rs->sets.next, struct raid_set, list); + + if (raid_level == ISW_T_RAID0 && rs1->type == t_raid1) + raid_level = ISW_T_RAID10; + else + raid_level = ISW_T_UNDEF; + } + + return raid_level; +} + +static int +match_hd_array(struct raid_set *rs, struct isw *isw) +{ + int broken = 0, found = 0; // , i = isw->num_disks; +// struct isw_disk *disk = isw->disk; + struct raid_dev *rd; + +/* FIXME: all disks broken in case of no SCSI IDs + while (i--) { + if (disk[i].scsiId == UNKNOWN_SCSI_ID) + broken++; + } +*/ + + list_for_each_entry(rd, &rs->devs, devs) { + if (_get_disk(isw, rd->di)) + found++; + } + + return isw->num_disks == broken + found && found == rs->total_devs; +} + +static int +is_hd_array_available(struct lib_context *lc, struct raid_set *rs) +{ + struct raid_dev *rd1, *rd2; + + list_for_each_entry(rd1, &rs->devs, devs) { + list_for_each_entry(rd2, LC_RD(lc), list) { + if (!strcmp(rd1->di->path, rd2->di->path) && + rd1->fmt == rd2->fmt) + return match_hd_array(rs, META(rd2, isw)); + } + } + + return 0; +} + +#define MIN_VOLUME_SIZE 204800 +static void +enforce_size_limit(struct raid_set *rs) +{ + /* the min size is 100M bytes */ + if (rs->size && rs->size < MIN_VOLUME_SIZE) + rs->size = MIN_VOLUME_SIZE; +} + +static int +is_first_volume(struct lib_context *lc, struct raid_set *rs) +{ + struct raid_dev *rd1, *rd2; + + list_for_each_entry(rd1, &rs->devs, devs) { + list_for_each_entry(rd2, LC_RD(lc), list) { + if (!strcmp(rd1->di->path, rd2->di->path) && + rd1->fmt == rd2->fmt) { + /* No choice for the 2nd volume. */ + rs->size = 0; + return 0; + } + } + } + + enforce_size_limit(rs); + return 1; +} + +/* Retrieve and make up SCSI ID. */ +static unsigned +get_scsiId(struct lib_context *lc, char *path) +{ + int fd; + Sg_scsi_id sg_id; + + memset(&sg_id, 0, sizeof(sg_id)); + + if ((fd = open(path, O_RDONLY)) == -1) + return UNKNOWN_SCSI_ID; + + if (!get_scsi_id(lc, fd, &sg_id)) { + close(fd); + return UNKNOWN_SCSI_ID; + } + + close(fd); + return (sg_id.host_no << 16) | (sg_id.scsi_id << 8) | sg_id.lun; +} + +static int +isw_config_disks(struct lib_context *lc, struct isw_disk *disk, + struct raid_set *rs) +{ + int i = 0; + struct raid_dev *rd; + + list_for_each_entry(rd, &rs->devs, devs) { + strncpy((char *) disk[i].serial, rd->di->serial, + MAX_RAID_SERIAL_LEN); + disk[i].totalBlocks = rd->di->sectors; + + /* FIXME: when scsiID == UNKNOWN_SCSI_ID */ + disk[i].scsiId = get_scsiId(lc, rd->di->path); + disk[i++].status = CLAIMED_DISK | + CONFIG_ON_DISK | + DETECTED_DISK | USABLE_DISK | + ((rs->type == ISW_T_SPARE) ? + SPARE_DISK : CONFIGURED_DISK); + } + + return i; +} + +static void +isw_config_vol(struct raid_set *rs, struct isw_vol *vol) +{ + if (rs->status == s_init) { + vol->migr_state = 0; + vol->migr_type = 0; + } +} + +static uint32_t +_get_stride_size(struct raid_set *rs) +{ + /* In blocks (512-bytes). */ + /* First member is default stride size. */ + static const uint32_t s_raid0[] = { 256, 8, 16, 32, 64, 128, 256, 0 }; + static const uint32_t s_raid1[] = { 128, 128, 0 }; + static const uint32_t s_raid10[] = { 128, 8, 16, 32, 64, 128, 256, 0 }; + static const uint32_t s_raid5[] = { 128, 32, 64, 128, 256, 0 }; + struct strip_options { + const uint8_t level; + const uint32_t *options; + }; + static struct strip_options strip_options[] = { + {ISW_T_RAID0, s_raid0}, + {ISW_T_RAID1, s_raid1}, + {ISW_T_RAID10, s_raid10}, + {ISW_T_RAID5, s_raid5}, + }; + struct strip_options *so = ARRAY_END(strip_options); + + while (so-- > strip_options) { + if (rs->type == so->level) { + int i; + + if (rs->stride) { + i = 1; + while (so->options[i + 1] && + rs->stride > so->options[i]) + i++; + } + else + i = 0; + + return so->options[i]; + } + } + + return 0; +} + +static void +_find_factors(struct raid_set *rs, uint8_t * div, uint8_t * sub) +{ + struct factors { + const uint8_t level; + const uint8_t div, sub; + }; + static struct factors factors[] = { + {ISW_T_RAID0, 1, 0}, + {ISW_T_RAID1, 2, 0}, + {ISW_T_RAID10, 2, 0}, + {ISW_T_RAID5, 1, 1}, + }; + struct factors *f = ARRAY_END(factors); + + while (f-- > factors) { + if (rs->type == f->level) { + *div = f->div; + *sub = f->sub; + return; + } + } + + *div = 1; + *sub = 0; +} + +/* Configure an isw map. */ +static void +isw_config_map(struct raid_set *rs, struct isw_map *map, + uint64_t size, uint32_t first) +{ + int i; + uint8_t div, sub; + + _find_factors(rs, &div, &sub); + map->pba_of_lba0 = first; + map->blocks_per_strip = _get_stride_size(rs); + map->num_data_stripes = size / (map->blocks_per_strip) / + ((rs->total_devs - sub) / div); + map->blocks_per_member = map->blocks_per_strip * map->num_data_stripes + + RAID_DS_JOURNAL; + + map->map_state = ISW_T_STATE_NORMAL; + map->raid_level = rs->type == ISW_T_RAID10 ? ISW_T_RAID1 : rs->type; + map->num_members = rs->found_devs; + map->num_domains = (rs->type == ISW_T_RAID1 || + rs->type == ISW_T_RAID10) ? 2 : 1; + +/* FIXME */ + for (i = 0; i < map->num_members; i++) + map->disk_ord_tbl[i] = i; +} + +/* Calculate the (new) array size. */ +static uint64_t +_cal_array_size(struct isw_disk *disk, struct raid_set *rs, struct isw_dev *dev) +{ + int n = 0; + uint8_t div, sub; + uint64_t min_ds = ~0, max_ds; + struct raid_dev *rd; + + list_for_each_entry(rd, &rs->devs, devs) { + if (min_ds > rd->di->sectors) + min_ds = rd->di->sectors; + n++; + } + + if (min_ds < DISK_RESERVED_BLOCKS) + return 0; + + min_ds -= DISK_RESERVED_BLOCKS; + + /* blank disks */ + if (dev) { + /* One volume existed and started from the beginning */ + if (!dev->vol.map.pba_of_lba0) { + max_ds = dev->vol.map.blocks_per_member + + DISK_RESERVED_BLOCKS; + + if (min_ds > max_ds) + min_ds -= max_ds; + else + return 1; + /* An existing volume at the bottom */ + } + else if (dev->vol.map.pba_of_lba0 >= + RAID_VOLUME_RESERVED_BLOCKS) + min_ds = dev->vol.map.pba_of_lba0 - + RAID_VOLUME_RESERVED_BLOCKS; + else + return 1; + } + else { + if (min_ds > DISK_RESERVED_BLOCKS) + min_ds -= DISK_RESERVED_BLOCKS; + else + return 1; + } + + _find_factors(rs, &div, &sub); + max_ds = min_ds * (n - sub) / div; + return max_ds; +} + +#define METADATA_BLOCKS 2 +static int +isw_config_dev(struct lib_context *lc, struct raid_set *rs, + struct isw_dev *dev1, struct isw_dev *dev2, uint64_t max_size) +{ + uint64_t tmp = rs->size ? rs->size : max_size; + + strncpy((char *) dev2->volume, rs->name, MAX_RAID_SERIAL_LEN); + dev2->SizeLow = (uint32_t) tmp; + dev2->SizeHigh = (uint32_t) (tmp >> 32); + /* FIXME: isi this status ok, Radoslaw ? */ + dev2->status = ISW_DEV_READ_COALESCING | ISW_DEV_WRITE_COALESCING; + isw_config_vol(rs, &dev2->vol); + + if (!dev1) { + isw_config_map(rs, &dev2->vol.map, tmp, 0); + return 1; + } + + if (!dev1->vol.map.pba_of_lba0) /* Start at the begginning. */ + isw_config_map(rs, &dev2->vol.map, tmp, + dev1->vol.map.blocks_per_member + + MIGR_OPT_SPACE); + else { + isw_config_map(rs, &dev2->vol.map, tmp, 0); + + if (dev2->vol.map.blocks_per_member + MIGR_OPT_SPACE > + dev1->vol.map.pba_of_lba0) + LOG_ERR(lc, 0, "%s: not enough space to create " + "requested volume", handler); + + } + + return 1; +} + +static void +display_new_volume(struct raid_set *rs, struct isw *isw, struct isw_dev *dev) +{ + enum type rt; + const char *type_name = NULL; + struct raid_dev *r; + + if (rs->type == ISW_T_SPARE) { /* Case if spare disk. */ + printf("\n\n Create a SPARE DISK with ISW metadata " + "format \n\nDISK: "); + } + else { + rt = type(dev); + switch (rt) { + case t_raid0: + type_name = "RAID0"; + break; + + case t_raid1: + type_name = dev->vol.map.num_members == + min_num_disks(ISW_T_RAID10) ? + "RAID01 (isw RAID10)" : "RAID1"; + break; + + case t_raid5_la: + type_name = "RAID5"; + break; + + default: + return; + } + + printf("\n\n Create a RAID set with ISW " + "metadata format \n\n"); + printf("RAID name: %s\n", dev->volume); + printf("RAID type: %s\n", type_name); + printf("RAID size: %lluG", + ((unsigned long long) dev->SizeLow + + ((unsigned long long) dev->SizeHigh << 32)) / GB_DIV); + printf("(%llublocks)\n", + ((unsigned long long) dev->SizeLow + + ((unsigned long long) dev->SizeHigh << 32))); + + if (rt != t_raid1) + printf("RAID strip: %uk(%ublocks)\n", + dev->vol.map.blocks_per_strip / 2, + dev->vol.map.blocks_per_strip); + + printf("DISKS: "); + } + + list_for_each_entry(r, &rs->devs, devs) { + if (_get_disk(isw, r->di)) + printf("%s%s ", r->di->path, + rs->type == ISW_T_SPARE ? "" : ","); + } + + printf("\n\n\n"); +} + +static struct isw * +_isw_create_first_volume(struct lib_context *lc, struct raid_set *rs) +{ + + uint16_t isw_size; + uint64_t total_size; + struct isw *isw; + struct isw_dev *dev = NULL; + struct isw_disk *disk = NULL; + + total_size = _cal_array_size(disk, rs, NULL); + if (rs->size > total_size) + LOG_ERR(lc, 0, + "%s: the size exceeds the max %lluG(%llublocks)", + handler, total_size / GB_DIV, total_size); + + /* allocate min 2 sectors space for isw metadata. */ + isw_size = METADATA_BLOCKS * ISW_DISK_BLOCK_SIZE; + if (!(isw = alloc_private(lc, handler, isw_size))) + LOG_ERR(lc, 0, "%s: failed to allocate memory", handler); + + disk = isw->disk; + isw->num_disks = isw_config_disks(lc, disk, rs); + isw_size = sizeof(*isw) + sizeof(*disk) * (isw->num_disks - 1); + + if (rs->type != ISW_T_SPARE) { + dev = (struct isw_dev *) (disk + isw->num_disks); + if (!isw_config_dev(lc, rs, NULL, dev, total_size)) { + dbg_free(isw); + return NULL; + } + + isw_size += sizeof(*dev) + sizeof(dev->vol.map.disk_ord_tbl) * + (isw->num_disks - 1); + } + + display_new_volume(rs, isw, dev); + + strncpy((char *) isw->sig, MPB_SIGNATURE, MPB_SIGNATURE_SIZE); + strncpy((char *) isw->sig + MPB_SIGNATURE_SIZE, + MPB_VERSION_RAID2, MPB_VERSION_RAID2_SIZE); + isw->mpb_size = isw_size; + isw->generation_num = 0; + isw->num_raid_devs = (rs->type == ISW_T_SPARE) ? 0 : 1; + isw->family_num = isw->orig_family_num = _checksum(isw) + time(NULL); + isw->check_sum = 0; + isw->check_sum = _checksum(isw); + return isw; +} + +static struct raid_set * +_find_group(struct lib_context *lc, struct raid_set *rs) +{ + struct raid_set *r; + struct raid_dev *rd1, *rd2; + int match = 0; + + list_for_each_entry(r, LC_RS(lc), list) { + if (r->type != t_group) + continue; + + list_for_each_entry(rd2, &rs->devs, devs) { + list_for_each_entry(rd1, &r->devs, devs) { + if (!strcmp(rd1->di->path, rd2->di->path)) { + match++; + break; + } + } + } + + if (match) { + if (match == rs->found_devs) + return r; + + LOG_ERR(lc, NULL, + "%s: mismatch in the number of drives " + "found", handler); + } + } + + return NULL; +} + +static struct isw * +_isw_create_second_volume(struct lib_context *lc, struct raid_set *rs) +{ + uint16_t isw_size; + uint64_t total_size; + struct raid_set *rs_group; + struct raid_dev *rd; + struct isw *isw, *isw_v1; + struct isw_dev *dev1, *dev2; + + if (!(rs_group = _find_group(lc, rs))) + return NULL; + + rd = list_entry(rs_group->devs.next, struct raid_dev, devs); + /* Note: size of a volume data structure is smaller than a sector. */ + + /* FIXME: >=2 ? */ + isw_v1 = rd->meta_areas->area; + if (isw_v1->num_raid_devs >= 2) + LOG_ERR(lc, NULL, "%s: only two volumes allowed per array", + handler); + + if (!(dev1 = raiddev(isw_v1, 0))) + LOG_ERR(lc, NULL, "%s: failed to get the first volume info", + handler); + + total_size = _cal_array_size(isw_v1->disk, rs, dev1); + if (total_size < MIN_VOLUME_SIZE) + LOG_ERR(lc, NULL, "%s: either not enough disk space or the " + "requested volume size is too small", handler); + + isw_size = rd->meta_areas->size + ISW_DISK_BLOCK_SIZE; + if (!(isw = alloc_private(lc, handler, isw_size))) + LOG_ERR(lc, NULL, "%s: failed to allocate memory", handler); + + memcpy(isw, isw_v1, isw_size - ISW_DISK_BLOCK_SIZE); + isw_size = isw_v1->mpb_size; + dev2 = raiddev(isw, 1); + if (!isw_config_dev(lc, rs, dev1, dev2, total_size)) { + dbg_free(isw); + return NULL; + } + + isw_size += sizeof(*dev2) + sizeof(dev2->vol.map.disk_ord_tbl) * + (isw->num_disks - 1); + + display_new_volume(rs, isw, dev2); + isw->mpb_size = isw_size; + isw->generation_num++; + isw->num_raid_devs++; + isw->check_sum = 0; + isw->check_sum = _checksum(isw); + return isw; +} + +static struct isw_dev * +get_raiddev(struct isw *isw, char *name) +{ + struct isw_dev *dev; + int i; + + for (i = 0; i < isw->num_raid_devs; i++) { + dev = raiddev(isw, i); + if (!strcmp((const char *) dev->volume, (const char *) name)) + return dev; + } + + return NULL; +} + +/* + * Update the metadata attached to each raid + * device and the name of the RAID set. + */ +static int +update_raidset(struct lib_context *lc, struct raid_set *rs, struct isw *isw) +{ + int blocks = div_up(isw->mpb_size, ISW_DISK_BLOCK_SIZE); + size_t size = blocks * ISW_DISK_BLOCK_SIZE; + struct raid_dev *rd; + struct isw_dev *dev; + + list_for_each_entry(rd, &rs->devs, devs) { + if (rd->meta_areas) { + if (rd->meta_areas->area) + dbg_free(rd->meta_areas->area); + + dbg_free(rd->meta_areas); + } + + if (!(rd->meta_areas = alloc_meta_areas(lc, rd, handler, 1))) + return 0; + + if (!(rd->meta_areas->area = alloc_private(lc, handler, size))) + return 0; + + set_metadata_sizoff(rd, size); + memcpy(rd->meta_areas->area, isw, size); + rd->type = t_group; + + dev = NULL; + if (rs->type != ISW_T_SPARE && + !(dev = get_raiddev(isw, rs->name))) + return 0; + + if (!(rd->name = name(lc, rd, dev, N_NUMBER))) + return 0; + } + + if (rs->type != ISW_T_SPARE) { + if (!(dev = get_raiddev(isw, rs->name))) + return 0; + + dbg_free(rs->name); + rd = list_entry(rs->devs.next, struct raid_dev, devs); + if (!(rs->name = name(lc, rd, dev, N_VOLUME))) + return 0; + } + + return 1; +} + +/* Create a RAID set (i.e. an isw volume). */ +static int +_isw_create_raidset(struct lib_context *lc, struct raid_set *rs) +{ + uint16_t min, max = 0; + struct isw *isw; + + /* The type is changed into the ISW defination */ + if ((rs->type = check_capability(rs)) == ISW_T_UNDEF) + LOG_ERR(lc, 0, "%s: unsupported raid level", handler); + + if (rs->type != ISW_T_SPARE && rs->name) { + if (!is_name_unique(lc, rs)) + LOG_ERR(lc, 0, "%s: the name %s is already in use, " + "please try another name", handler, rs->name); + } + + if ((min = min_num_disks(rs->type)) > rs->found_devs || + (max = max_num_disks(rs->type)) < rs->found_devs) + LOG_ERR(lc, 0, "%s: the RAID set cannot have %s " + "than %d hard drives", + handler, max ? "more" : "less", max ? max : min); + + /* + * The size of the RAID set is set to 0 if there is one volume + * detected. Also, the mininum size is enforced to 0.1G. + */ + if (is_first_volume(lc, rs)) + isw = _isw_create_first_volume(lc, rs); + else if (rs->type == ISW_T_SPARE) + LOG_ERR(lc, 0, "%s: SPARE disk must use all space " + "on the disk", handler); + else if (is_hd_array_available(lc, rs)) + isw = _isw_create_second_volume(lc, rs); + else + LOG_ERR(lc, 0, + "%s: second volume must use all drives on the " + "existing array", handler); + + /* isw spare disk is created without own name. */ + if (isw) { + static const char *fmts[] = { + "About to create a RAID set with the above settings. " + "Name <%s> will lost. Continue", + "About to create a RAID set with the above settings. " + "Continue", + }; + const char *fmt = fmts[!(rs->type == ISW_T_SPARE && rs->name)]; + + if (yes_no_prompt(lc, fmt, rs->name)) { + if (!update_raidset(lc, rs, isw)) { + dbg_free(isw); + LOG_ERR(lc, 0, "%s: failed to update metadata " + "on the raid_dev data structure ", + handler); + } + } + else { + dbg_free(isw); + return 0; + } + + dbg_free(isw); + rs->status = s_config; + return 1; + } + + return 0; +} + +static int update_metadata(struct lib_context *lc, struct raid_set *rs); +static int +isw_create(struct lib_context *lc, struct raid_set *rs) +{ + + int ret = 0; + + if (rs->status == s_init) { + enum type raid_type; + + /* + * The field size and type get changed + * later to faciliate processing. + */ + raid_type = rs->type; + ret = _isw_create_raidset(lc, rs); + rs->type = raid_type; + } + else if (rs->status == s_nosync) + ret = update_metadata(lc, rs); + + return ret; +} + +static int +isw_check(struct lib_context *lc, struct raid_set *rs) +{ + if (rs->status == s_init) + return 1; + else + return T_GROUP(rs) ? _isw_check(lc, rs) : 0; +} + +/* + * IO error event handler. + */ +static int +event_io(struct lib_context *lc, struct event_io *e_io) +{ + struct raid_dev *rd = e_io->rd; + struct isw *isw = META(rd, isw); + struct isw_disk *disk; + + if (!(disk = get_disk(lc, rd->di, isw))) + LOG_ERR(lc, 0, "%s: disk", handler); + + /* Avoid write trashing. */ + if (S_BROKEN(status(lc, rd))) + return 0; + + disk->status &= ~USABLE_DISK; + disk->status |= FAILED_DISK; + + return 1; +} + +static struct event_handlers isw_event_handlers = { + .io = event_io, + .rd = NULL, /* FIXME: no device add/remove event handler yet. */ +}; + +static void +_isw_log(struct lib_context *lc, struct isw *isw) +{ + unsigned d, i, m; + struct isw_disk *disk; + struct isw_dev *dev; + + P("sig: \"%*s\"", isw, isw->sig, MAX_SIGNATURE_LENGTH, isw->sig); + DP("check_sum: %u", isw, isw->check_sum); + DP("mpb_size: %u", isw, isw->mpb_size); + DP("family_num: %u", isw, isw->family_num); + DP("generation_num: %u", isw, isw->generation_num); + DP("error_log_size: %u", isw, isw->error_log_size); + DP("attributes: %u", isw, isw->attributes); + DP("num_disks: %u", isw, isw->num_disks); + DP("num_raid_devs: %u", isw, isw->num_raid_devs); + DP("error_log_pos: %u", isw, isw->error_log_pos); + DP("cache_size: %u", isw, isw->cache_size); + DP("orig_family_num: %u", isw, isw->orig_family_num); + + for (i = 0; i < ISW_FILLERS; i++) { + if (isw->filler[i]) + P("filler[%i]: %u", isw, isw->filler[i], i, + isw->filler[i]); + } + + /* Disk table. */ + for (d = 0, disk = isw->disk; d < isw->num_disks; d++, disk++) { + if (!disk->totalBlocks) + continue; + + P("disk[%u].serial: \"%*s\"", isw, + disk->serial, d, MAX_RAID_SERIAL_LEN, disk->serial); + P("disk[%u].totalBlocks: %u", isw, + disk->totalBlocks, d, disk->totalBlocks); + P("disk[%u].scsiId: 0x%x", isw, disk->scsiId, d, disk->scsiId); + P("disk[%u].status: 0x%x", isw, disk->status, d, disk->status); + P("disk[%u].owner_cfg_num: 0x%x", isw, disk->owner_cfg_num, + d, disk->owner_cfg_num); + for (i = 0; i < ISW_DISK_FILLERS; i++) { + if (disk->filler[i]) + P("disk[%u].filler[%u]: %u", isw, + disk->filler[i], d, i, disk->filler[i]); + } + } + + /* RAID device/volume table. */ + for (d = 0; d < isw->num_raid_devs; d++) { + dev = raiddev(isw, d); + + /* RAID device */ + P("isw_dev[%u].volume: \"%*s\"", isw, + dev->volume, d, MAX_RAID_SERIAL_LEN, dev->volume); + P("isw_dev[%u].SizeHigh: %u", isw, dev->SizeHigh, d, + dev->SizeHigh); + P("isw_dev[%u].SizeLow: %u", isw, dev->SizeLow, d, + dev->SizeLow); + P("isw_dev[%u].status: 0x%x", isw, dev->status, d, dev->status); + P("isw_dev[%u].reserved_blocks: %u", isw, + dev->reserved_blocks, d, dev->reserved_blocks); + P("isw_dev[%u].migr_priority: %u", isw, dev->migr_priority, + d, dev->migr_priority); + P("isw_dev[%u].num_sub_vol: %u", isw, dev->num_sub_vol, d, + dev->num_sub_vol); + P("isw_dev[%u].tid: %u", isw, dev->tid, d, dev->tid); + P("isw_dev[%u].cng_master_disk: %u", isw, + dev->cng_master_disk, d, dev->cng_master_disk); + P("isw_dev[%u].cache_policy: %u", isw, + dev->cache_policy, d, dev->cache_policy); + P("isw_dev[%u].cng_state: %u", isw, dev->cng_state, d, + dev->cng_state); + P("isw_dev[%u].cng_sub_state: %u", isw, dev->cng_sub_state, + d, dev->cng_sub_state); + + for (i = 0; i < ISW_DEV_FILLERS; i++) { + if (dev->filler[i]) + P("isw_dev[%u].filler[%u]: %u", isw, + dev->filler[i], d, i, dev->filler[i]); + } + + /* RAID volume */ + P("isw_dev[%u].vol.curr_migr_unit: %u", isw, + dev->vol.curr_migr_unit, d, dev->vol.curr_migr_unit); + P("isw_dev[%u].vol.check_point_id: %u", isw, + dev->vol.check_point_id, d, dev->vol.check_point_id); + + P("isw_dev[%u].vol.migr_state: %u", isw, + dev->vol.migr_state, d, dev->vol.migr_state); + P("isw_dev[%u].vol.migr_type: %u", isw, + dev->vol.migr_type, d, dev->vol.migr_type); + P("isw_dev[%u].vol.dirty: %u", isw, dev->vol.dirty, d, + dev->vol.dirty); + P("isw_dev[%u].vol.fs_state: %u", isw, dev->vol.fs_state, + d, dev->vol.fs_state); + P("isw_dev[%u].vol.verify_errors: %u", isw, + dev->vol.verify_errors, d, dev->vol.verify_errors); + P("isw_dev[%u].vol.verify_bad_blocks: %u", isw, + dev->vol.verify_bad_blocks, d, dev->vol.verify_bad_blocks); + + for (i = 0; i < ISW_RAID_VOL_FILLERS; i++) { + if (dev->vol.filler[i]) + P("isw_dev[%u].vol.filler[%u]: %u", isw, + dev->vol.filler[i], d, i, dev->vol.filler[i]); + } + + + struct isw_map *map = &dev->vol.map; + for (m = 0; m < 2; m++) { + /* RAID map */ + + P("isw_dev[%u].vol.map[%d].pba_of_lba0: %u", isw, + map->pba_of_lba0, d, m, map->pba_of_lba0); + P("isw_dev[%u].vol.map[%d].blocks_per_member: %u", + isw, map->blocks_per_member, d, m, + map->blocks_per_member); + P("isw_dev[%u].vol.map[%d].num_data_stripes: %u", + isw, map->num_data_stripes, d, m, + map->num_data_stripes); + P("isw_dev[%u].vol.map[%d].blocks_per_strip: %u", + isw, map->blocks_per_strip, d, m, + map->blocks_per_strip); + P("isw_dev[%u].vol.map[%d].map_state: %u", isw, + map->map_state, d, m, map->map_state); + P("isw_dev[%u].vol.map[%d].raid_level: %u", isw, + map->raid_level, d, m, map->raid_level); + P("isw_dev[%u].vol.map[%d].num_members: %u", isw, + map->num_members, d, m, map->num_members); + P("isw_dev[%u].vol.map[%d].num_domains: %u", isw, + map->num_domains, d, m, map->num_domains); + P("isw_dev[%u].vol.map[%d].failed_disk_num: %u", + isw, map->failed_disk_num, d, m, + map->failed_disk_num); + P("isw_dev[%u].vol.map[%d].ddf: %u", isw, map->ddf, + d, m, map->ddf); + + for (i = 0; i < 7; i++) { + if (map->filler[i]) + P("isw_dev[%u].vol.map[%d].filler[%u]: %u", isw, map->filler[i], d, m, i, map->filler[i]); + } + + for (i = 0; i < map->num_members; i++) { + P("isw_dev[%u].vol.map[%d].disk_ord_tbl[%u]: 0x%x", isw, map->disk_ord_tbl[i], d, m, i, map->disk_ord_tbl[i]); + } + + if (!dev->vol.migr_state) + break; + + map = (struct isw_map *) ((char *) map + + (map->num_members - 1) * + sizeof(map->disk_ord_tbl) + + sizeof(struct isw_map)); + } + } +} + +#ifdef DMRAID_NATIVE_LOG +/* + * Log native information about an ISW RAID device. + */ +static void +isw_log(struct lib_context *lc, struct raid_dev *rd) +{ + struct isw *isw = META(rd, isw); + + log_print(lc, "%s (%s):", rd->di->path, handler); + _isw_log(lc, isw); +} +#endif + +static void +isw_erase_metadata(struct lib_context *lc, struct raid_set *rs) +{ + struct raid_dev *rd; + + list_for_each_entry(rd, &rs->devs, devs) + isw_write(lc, rd, 1); +} + +/* + * Write an Intel Software RAID device. + */ +static int +isw_write_all(struct lib_context *lc, struct raid_set *rs, struct isw *isw) +{ + struct raid_dev *rd, *r; + struct meta_areas ma = { + .size = isw_size(isw), + .area = isw, + }; + + if (!(rd = alloc_raid_dev(lc, handler))) + return 0; + + rd->meta_areas = &ma; + rd->type = t_raid0; //dummy code + rd->areas = 1; + + list_for_each_entry(r, &rs->devs, devs) { + rd->di = r->di; + set_metadata_sizoff(rd, ma.size); + rd->fmt = r->fmt; + isw_write(lc, rd, 0); + } + + dbg_free(rd); + return 1; +} + +/* Remove an isw device. */ +static void +isw_remove_dev(struct lib_context *lc, struct raid_set *rs, + struct isw *isw, struct isw_dev *dev) +{ + struct isw *isw_tmp; + size_t size, dev_size; + + size = div_up(isw->mpb_size, ISW_DISK_BLOCK_SIZE); + if (!(isw_tmp = alloc_private(lc, handler, + (size + 1) * ISW_DISK_BLOCK_SIZE))) + log_err(lc, "%s: failed to allocate memory", handler); + + size = sizeof(*isw) + sizeof(struct isw_disk) * (isw->num_disks - 1); + memcpy(isw_tmp, isw, size); + + dev_size = sizeof(*dev) + + sizeof(uint32_t) * (dev->vol.map.num_members - 1); + memcpy((char *) isw_tmp + size, dev, dev_size); + + isw_tmp->mpb_size = size + dev_size; + isw_tmp->num_raid_devs--; + isw_tmp->check_sum = _checksum(isw_tmp); + isw_write_all(lc, rs, isw_tmp); + dbg_free(isw_tmp); +} + +static int +_isw_delete_all(struct lib_context *lc, struct raid_set *rs_group) +{ + struct raid_set *rs; + struct raid_dev *rd; + char *name; + struct isw *isw; + struct isw_dev *dev1, *dev2; + int num = 0; + + if (!(rs = list_entry(rs_group->sets.next, struct raid_set, list))) + LOG_ERR(lc, 0, "%s: failed to find a RAID set in a group", + handler); + + if (!(rd = list_entry(rs_group->devs.next, struct raid_dev, devs))) + LOG_ERR(lc, 0, + "%s: failed to find a raid device in RS %s", + handler, rs_group->name); + + if (!(isw = (struct isw *) rd->meta_areas->area)) + LOG_ERR(lc, 0, "%s: failed to locate metadata on drive %s", + handler, rd->di->path); + + if (isw->num_raid_devs != 2) + LOG_ERR(lc, 0, "%s: the number of raid volumes is not 2", + handler); + + if ((!(dev1 = raiddev(isw, 0))) || (!(dev2 = raiddev(isw, 1)))) + LOG_ERR(lc, 0, "%s: failed to get two volume info", handler); + + list_for_each_entry(rs, &rs_group->sets, list) { + if (!(name = get_rs_basename(rs->name))) + LOG_ERR(lc, 0, + "%s: could not find the volume to be " + "deleted", handler); + + if (!strcmp((const char *) dev1->volume, (const char *) name)) + num++; + + if (!strcmp((const char *) dev2->volume, (const char *) name)) + num++; + } + if (num != 2) + LOG_ERR(lc, 0, + "%s: failed to find all of the RAID sets to be " + "deleted", handler); + + isw_erase_metadata(lc, rs_group); + return 1; +} + +/* Delete metadata according to the RAID set. */ +static int +isw_delete(struct lib_context *lc, struct raid_set *rs_group) +{ + struct raid_set *rs; + struct raid_dev *rd; + char *name; + struct isw *isw; + struct isw_dev *dev1, *dev2; + int num = 0; + + if (rs_group->type != t_group) + LOG_ERR(lc, 0, "%s: RAID set is not a t-group type", handler); + + list_for_each_entry(rs, &rs_group->sets, list) + num++; + + if (num > 1) + return _isw_delete_all(lc, rs_group); + + if (!(rs = list_entry(rs_group->sets.next, struct raid_set, list))) + LOG_ERR(lc, 0, + "%s: failed to find a RAID set in the group", + handler); + + if (!(name = get_rs_basename(rs->name))) + LOG_ERR(lc, 0, + "%s: failed to find the volume to be deleted", handler); + + if (!(rd = list_entry(rs_group->devs.next, struct raid_dev, devs))) + LOG_ERR(lc, 0, + "%s: failed to find a raid device in RS %s", + handler, rs_group->name); + + if (!(isw = (struct isw *) rd->meta_areas->area)) + LOG_ERR(lc, 0, + "%s: failed to locate metadata on device %s", + handler, rd->di->path); + + /* case if metadata on spare disk is delete */ + if (!isw->num_raid_devs && isw->num_disks == 1 && + (isw->disk[0].status & SPARE_DISK)) { + isw_erase_metadata(lc, rs_group); + return 1; + } + + if (!(dev1 = raiddev(isw, 0))) + LOG_ERR(lc, 0, + "%s: failed to find a RAID set in the group", handler); + + if (isw->num_raid_devs == 1) { + if (!strcmp((const char *) dev1->volume, (const char *) name)) { + isw_erase_metadata(lc, rs_group); + return 1; + } + else + LOG_ERR(lc, 0, "%s: failed to find the volume %s", + handler, name); + } + + if (!(dev2 = raiddev(isw, 1))) + LOG_ERR(lc, 0, + "%s: failed to find a RAID set in the group", handler); + + if (!strcmp((const char *) dev1->volume, (const char *) name)) + isw_remove_dev(lc, rs_group, isw, dev2); + else if (!strcmp((const char *) dev2->volume, (const char *) name)) + isw_remove_dev(lc, rs_group, isw, dev1); + else + return 0; + + return 1; +} + + +static struct dmraid_format isw_format = { + .name = HANDLER, + .descr = "Intel Software RAID", + .caps = "0,1,01", + .format = FMT_RAID, + .read = isw_read, + .write = isw_write, + .create = isw_create, + .delete = isw_delete, + .group = isw_group, + .check = isw_check, + .metadata_handler = isw_metadata_handler, + .events = &isw_event_handlers, + .scope = t_scope_global /* | t_scope_local */ , +#ifdef DMRAID_NATIVE_LOG + .log = isw_log, +#endif +}; + +static struct raid_set * +change_set_name(struct lib_context *lc, struct list_head *list, + char *o_name, char *n_name) +{ + struct raid_set *r, *ret = NULL; + + list_for_each_entry(r, list, list) { + if (!strcmp(r->name, o_name)) { + ret = r; + r->name = n_name; + break; + } + } + + list_for_each_entry(r, list, list) { + if ((ret = change_set_name(lc, &r->sets, o_name, n_name))) + r->name = n_name; + } + + return ret; +} + + +/* + * Create part of metadata (struct isw_dev) in new_isw based on + * certain parameters. + * + * Note that new_isw must have its data preceedning isw_dev field already set. + * The function returns size of created isw_dev (including map(s)). + */ +static unsigned +update_metadata_isw_dev(struct isw *new_isw, + int failed_disk_idx, + struct isw *old_isw, + int isw_dev_idx, unsigned isw_dev_offs) +{ + int i, map_size; + struct isw_dev *new_dev, *old_dev = raiddev(old_isw, isw_dev_idx); + + /* Append old volume information record (the first one); + * note that at the moment there is only one isw_map record + * (as in the old isw_dev/isw_vol record/subrecord) and we + * need two of them till data transfer is finished. + */ + memcpy((void *) (new_isw->disk + new_isw->num_disks) + + isw_dev_offs, old_dev, sizeof(struct isw_dev)); + + /* Update new volume information. */ + new_dev = raiddev(new_isw, isw_dev_idx); + new_dev->vol.migr_state = 1; /* FIXME: replace magic numbers */ + new_dev->vol.migr_type = 1; /* FIXME: replace magic numbers */ + + /* Update information in the first map. */ + new_dev->vol.map.map_state = ISW_T_STATE_NORMAL; + new_dev->vol.map.failed_disk_num = failed_disk_idx; + + /* + * FIXME: disk_ord_tbl should be updated too but at the moment + * we may leave it as it is coded below without any harm. + */ + for (i = 0; i < new_isw->num_disks - 1; i++) + new_dev->vol.map.disk_ord_tbl[i] = i; + + /* + * FIXME: code commented out + * new_isw->family_num = _checksum(new_isw) + time(NULL); + */ + + /* now let's proceed with the second, temporary map + FIXME: we just copy the first map and update it a bit */ + map_size = + sizeof(struct isw_map) + (new_dev->vol.map.num_members - + 1) * + sizeof(((struct isw_map *) NULL)->disk_ord_tbl); + memcpy((void *) &new_dev->vol.map + map_size, + (void *) &new_dev->vol.map, map_size); + + /* + * FIXME: the code below should be put into + * a new function 'raid_is_rebuildable()'. + */ + ((struct isw_map *) + ((void *) &new_dev->vol.map + map_size))->map_state = + new_dev->vol.map.raid_level == ISW_T_RAID0 ? + ISW_T_STATE_FAILED : ISW_T_STATE_DEGRADED; + + return (unsigned) + ((unsigned long) &new_dev->vol.map + 2 * map_size) - + ((unsigned long) new_isw->disk + new_isw->num_disks) - + isw_dev_offs; +} + +/* Update metadata wit hdrive to rebuild. */ +static int +update_metadata(struct lib_context *lc, struct raid_set *rs) +{ + int failed_disk_idx = -1; /* zero-based index of failed disk */ + int i, idx, found = 0, failed_disks_num = 0, new_isw_size, ret = 0; + unsigned isw_dev_offs; + const char *rebuild_set_name = lc->options[LC_REBUILD_SET].arg.str; + struct raid_dev *rd = list_entry(rs->devs.next, struct raid_dev, devs); + struct raid_set *sub_rs = NULL; + struct dev_info *di = NULL; + struct isw *isw = META(rd, isw), *new_isw = NULL; + struct isw_disk *disk = isw->disk, *new_disk = NULL; + struct isw_dev *new_dev = NULL; + + + /* + * Find the index of the failed disk - + * at most we can handle 1 failed disk. + */ + i = isw->num_disks; + while (i--) { + /* Check if the disk is listed. */ + list_for_each_entry(di, LC_DI(lc), list) { + if (!strncmp(di->serial, (const char *) disk[i].serial, + MAX_RAID_SERIAL_LEN)) + goto goon; + } + + /* Disk not found in system, i.e. it's the failed one. */ + failed_disk_idx = i; + failed_disks_num++; + + /* Mark disk as not usable. */ + disk[i].scsiId = UNKNOWN_SCSI_ID; + disk[i].status &= ~USABLE_DISK; + disk[i].status |= FAILED_DISK; + goon: + ; + } + + /* We must have one failed disk */ + if (failed_disks_num != 1) + LOG_ERR(lc, 0, "%s: only one failed disk supported", handler); + + /* Now let's find the disk for rebuild. */ + if (failed_disk_idx == -1) + /* + * Could not find failed disk... maybe this place can + * be used to search for and add a spare disk. + */ + return 0; + + /* Search for a raid_dev in s_init state. */ + sub_rs = find_set(lc, NULL, rebuild_set_name, FIND_ALL); + found = 0; + list_for_each_entry(rd, &sub_rs->devs, devs) { + if (rd->status == s_init) { + di = rd->di; + DM_ASSERT(di); + log_print(lc, "%s: drive to rebuild: %s\n", + handler, di->path); + found = 1; + break; + } + } + + /* FIXME: "TBD - remove later" */ + if (!found && lc->options[LC_REBUILD_DISK].opt) { + list_for_each_entry(di, LC_DI(lc), list) { + if (!strncmp(di->path, + lc->options[LC_REBUILD_DISK].arg.str, + strlen(di->path))) { + found = 1; + break; + } + } + } + + if (!found) /* Error: no disk to rebuild found - exit. */ + LOG_ERR(lc, 0, "%s: no drive to rebuild", handler); + + /* Now let's start building the new metadata. */ + + /* MPB can have at most two block size. */ + new_isw_size = 2 * ISW_DISK_BLOCK_SIZE; + new_isw = alloc_private(lc, handler, new_isw_size); + if (!new_isw) + return 0; + + /* Copy a few first metadata bytes. */ + memcpy(new_isw, isw, sizeof(struct isw) - sizeof(struct isw_disk)); + + /* some field will be updated later on; they are marked below: + * check_sum + * mpb_size + family_num + * generation_num + error_log_size + attributes + * num_disks + num_raid_devs + error_log_pos + cache_size + orig_family_num + FIXME: OROM changes some fields that are not marked above, + so we should too + */ + + /* Add the new disk. */ + new_disk = alloc_private(lc, handler, sizeof(struct isw_disk)); + if (!new_disk) + goto bad_free_new_isw; + + new_disk->totalBlocks = di->sectors; + new_disk->scsiId = get_scsiId(lc, di->path); + /* FIXME: is this state ok, Radoslaw ? Was 0x53a */ + new_disk->status = CONFIG_ON_DISK | + DISK_SMART_EVENT_SUPPORTED | + CLAIMED_DISK | DETECTED_DISK | USABLE_DISK | CONFIGURED_DISK; + strncpy((char *) new_disk->serial, di->serial, MAX_RAID_SERIAL_LEN); + + /* build new isw_disk array */ + for (i = 0; i < isw->num_disks; i++) { + /* + * Replace failed disk with the new one or + * Leave previous drives as they are. + */ + memcpy(new_isw->disk + i, + i == failed_disk_idx ? new_disk : isw->disk + i, + sizeof(struct isw_disk)); + } + + /* + * Append the failed disk at the end of the disks array in + * the metadata; as designed in the intermediate rebuilding + * step we have 3 disks and two maps per isw_dev: the new one + * (at index 0) and the old one (at index 1). + */ + memcpy(new_isw->disk + i, isw->disk + failed_disk_idx, + sizeof(struct isw_disk)); + new_isw->disk[i].status = CONFIGURED_DISK; + new_isw->num_disks++; + + /* Create isw_dev record for volume(s). */ + isw_dev_offs = update_metadata_isw_dev(new_isw, failed_disk_idx, + isw, 0, 0); + if (isw->num_raid_devs > 1) + isw_dev_offs += update_metadata_isw_dev(new_isw, + failed_disk_idx, isw, + 1, isw_dev_offs); + + /* now we may update new metadata's fields */ + new_isw->mpb_size = + (unsigned long) (new_isw->disk + new_isw->num_disks) - + (unsigned long) (new_isw) + isw_dev_offs; + new_isw->generation_num++; + new_isw->check_sum = _checksum(new_isw); + + /* embed new metadata on physical devices */ + idx = rd_idx_by_name(new_isw, rebuild_set_name + strlen(rs->name) + 1); + if (idx < 0) + return 0; + + new_dev = raiddev(new_isw, idx); + sub_rs = find_set(lc, NULL, rebuild_set_name, FIND_ALL); + list_for_each_entry(rd, &sub_rs->devs, devs) { + if (rd->meta_areas && rd->meta_areas->area) { + + dbg_free(rd->meta_areas->area); + } + if (!rd->meta_areas || rd->status == s_init) { + if (rd->meta_areas) + dbg_free(rd->meta_areas); + + rd->meta_areas = alloc_meta_areas(lc, rd, handler, 1); + if (!rd->meta_areas) + goto bad_free_new_disk; + + rd->di = di; + rd->fmt = &isw_format; + rd->meta_areas->area = + alloc_private(lc, handler, new_isw_size); + memcpy(rd->meta_areas->area, new_isw, new_isw_size); + rd->offset = new_dev->vol.map.pba_of_lba0; + rd->sectors = new_dev->vol.map.blocks_per_member; + } + else { + rd->meta_areas->area = + alloc_private(lc, handler, new_isw_size); + if (!rd->meta_areas->area) + goto bad_free_new_disk; + + memcpy(rd->meta_areas->area, new_isw, new_isw_size); + } + + if (!rd->areas) + rd->areas++; + set_metadata_sizoff(rd, isw_size(new_isw)); + + if (rd->status == s_init) { + rd->status = s_ok; + if (rd->name) + dbg_free(rd->name); + + if (!(rd->name = name(lc, rd, new_dev, N_VOLUME))) + goto bad_free_new_disk; + } + + rd->status = s_ok; + } + + list_for_each_entry(rd, &rs->devs, devs) { + if (rd->meta_areas && rd->meta_areas->area) + dbg_free(rd->meta_areas->area); + + if (!rd->meta_areas || rd->status == s_init) { + if (rd->meta_areas && rd->meta_areas->area) + dbg_free(rd->meta_areas->area); + + rd->meta_areas = alloc_meta_areas(lc, rd, handler, 1); + if (!rd->meta_areas) + goto bad_free_new_disk; + + rd->di = di; + rd->fmt = &isw_format; + rd->offset = new_dev->vol.map.pba_of_lba0; + rd->sectors = new_dev->vol.map.blocks_per_member; + } + rd->meta_areas->area = alloc_private(lc, handler, new_isw_size); + if (!rd->meta_areas->area) + goto bad_free_new_disk; + set_metadata_sizoff(rd, isw_size(new_isw)); + memcpy(rd->meta_areas->area, new_isw, new_isw_size); + + + if (rd->status == s_init) { + + if (rd->name) + dbg_free(rd->name); + + if (!(rd->name = name(lc, rd, new_dev, N_VOLUME))) + goto bad_free_new_disk; + + /* FIXME: code commented out + new_name = name(lc, rd, new_dev, 0); + */ + } + + rd->status = s_ok; + } + + /* FIXME: code commented out + change_set_name(lc, LC_RS(lc), rs->name, new_name); + */ + + ret = 1; + bad_free_new_disk: + dbg_free(new_disk); + bad_free_new_isw: + dbg_free(new_isw); + return ret; +} + +/* Register this format handler with the format core. */ +int +register_isw(struct lib_context *lc) +{ + return register_format_handler(lc, &isw_format); +} + +/* + * Set the RAID device contents up derived from the Intel ones. + * + * This is the first one we get with here and we potentially need to + * create many in isw_group() in case of multiple Intel SW RAID devices + * on this RAID disk. + */ +static int +setup_rd(struct lib_context *lc, struct raid_dev *rd, + struct dev_info *di, void *meta, union read_info *info) +{ + struct isw *isw = meta; + struct isw_disk *disk; + + + /* Superblock checksum */ + if (isw->check_sum != _checksum(isw)) + LOG_ERR(lc, 0, "%s: extended superblock for %s " + "has wrong checksum", handler, di->path); + + if (!(rd->meta_areas = alloc_meta_areas(lc, rd, handler, 1))) + return 0; + + rd->meta_areas->offset = info->u64 >> 9; + rd->meta_areas->size = isw_size(isw); + rd->meta_areas->area = isw; + + rd->di = di; + rd->fmt = &isw_format; + + rd->offset = ISW_DATAOFFSET; + if (!(rd->sectors = info->u64 >> 9)) + return log_zero_sectors(lc, di->path, handler); + + rd->status = status(lc, rd); + + /* Mark disk as spare disk. */ + disk = get_disk(lc, di, isw); + if (disk->status & SPARE_DISK) + rd->type = t_spare; + else + rd->type = t_group; - return (rd->name = name(lc, isw, NULL)) ? 1 : 0; + disk->scsiId = get_scsiId(lc, di->path); + return (rd->name = name(lc, rd, NULL, N_NUMBER)) ? 1 : 0; } --- dmraid/lib/format/ataraid/isw.h 2008/02/22 16:57:36 1.1 +++ dmraid/lib/format/ataraid/isw.h 2008/06/20 21:52:17 1.2 @@ -5,6 +5,9 @@ * Copyright (C) 2004,2005 Heinz Mauelshagen, Red Hat GmbH. * All rights reserved. * + * Copyright (C) 2007 Intel Corporation. All rights reserved. + * November, 2007 - additions for Create, Delete, Rebuild & Raid 10. + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) @@ -31,85 +34,156 @@ #undef FORMAT_HANDLER /* Intel metadata offset in bytes */ -#define ISW_CONFIGOFFSET ((di->sectors - 2) << 9) +#define ISW_CONFIGSECTOR(di) ((di)->sectors - 2) +#define ISW_CONFIGOFFSET(di) (ISW_CONFIGSECTOR(di) << 9) #define ISW_DATAOFFSET 0 /* Data offset in sectors */ #define MPB_SIGNATURE "Intel Raid ISM Cfg Sig. " -#define MPB_VERSION_RAID2 "1.2.02" +#define MPB_SIGNATURE_SIZE (sizeof(MPB_SIGNATURE) - 1) +#define MPB_VERSION_RAID2 "1.2.02" +#define MPB_VERSION_RAID2_SIZE (sizeof(MPB_VERSION_RAID2) - 1) #define MAX_SIGNATURE_LENGTH 32 #define MAX_RAID_SERIAL_LEN 16 #define ISW_DISK_BLOCK_SIZE 512 #define TYPICAL_MPBSIZE 1024 +#define RAID_DS_JOURNAL 259 +#define MIGR_OPT_SPACE 4096 +#define RAID_VOLUME_RESERVED_BLOCKS (RAID_DS_JOURNAL+MIGR_OPT_SPACE) +#define RAID_DISK_RESERVED_BLOCKS 417 +#define DISK_RESERVED_BLOCKS (RAID_DISK_RESERVED_BLOCKS+RAID_VOLUME_RESERVED_BLOCKS) +#define UNKNOWN_SCSI_ID ((uint32_t)~0) + /* Disk configuration info. */ struct isw_disk { - int8_t serial[MAX_RAID_SERIAL_LEN];/* 0xD8 - 0xE7 ascii serial number */ + int8_t serial[MAX_RAID_SERIAL_LEN]; /* 0xD8 - 0xE7 ascii serial number */ uint32_t totalBlocks; /* 0xE8 - 0xEB total blocks */ uint32_t scsiId; /* 0xEC - 0xEF scsi ID */ uint32_t status; /* 0xF0 - 0xF3 */ -#define SPARE_DISK 0x01 /* Spare */ -#define CONFIGURED_DISK 0x02 /* Member of some RaidDev */ -#define FAILED_DISK 0x04 /* Permanent failure */ -#define USABLE_DISK 0x08 /* Fully usable unless FAILED_DISK is set */ - -#define ISW_DISK_FILLERS 5 - uint32_t filler[ISW_DISK_FILLERS]; /* 0xF4 - 0x107 MPB_DISK_FILLERS for future expansion */ +#define SPARE_DISK 0x01 /* Spare */ +#define CONFIGURED_DISK 0x02 /* Member of some RaidDev */ +#define FAILED_DISK 0x04 /* Permanent failure */ +#define USABLE_DISK 0x08 /* Fully usable unless FAILED_DISK is set */ +#define DETECTED_DISK 0x10 /* Device attach received */ +#define CLAIMED_DISK 0X20 /* Device has been claimed ? */ +#define PASSTHRU_DISK 0X40 /* Device should be ignored */ +#define OFFLINE_DISK 0X80 /* Device has been marked offline by user */ +#define CONFIG_ON_DISK 0x100 /* Device currently has MPB stored on it */ +#define DISK_SMART_EVENT_TRIGGERED 0x200 +#define DISK_SMART_EVENT_SUPPORTED 0x400 +#define FORMATTING_DISK 0x800 /* Device is formatting */ +#define FORMAT_SUCCEEDED 0x1000 /* This bit is used with FORMATTING_DISK */ +#define FORMAT_FAILED 0x2000 /* This bit is used with FORMATTING_DISK */ +#define ELIGIBLE_FOR_SPARE 0x4000 /* Device may be used as a spare if needed. */ +#define READ_CONFIG_NEEDED 0x8000 /* Device needs to have its config read */ +#define CONFIG_IS_UPREV 0x10000 /* Config on device but cannot be handled */ +#define UNKNOW_DISK_FAILURE 0x40000 /* Any reading errors */ +#define DO_READ_CONFIG 0x80000 /* Device's config will be read and merged on nexted call */ +#define POWERED_OFF_DISK 0x100000 /* Device is spun down */ +#define PASSTHRU_CLAIMABLE 0x200000 /* Passthru device is claimable */ +#define CLONE_DISK_MODIFIED 0x400000 +#define PASSTHRU_DISK_WMPB 0X800000 + + uint32_t owner_cfg_num; /* 0xF4 - 0xF7 */ +#define ISW_DISK_FILLERS 4 + uint32_t filler[ISW_DISK_FILLERS]; /* 0xF7 - 0x107 MPB_DISK_FILLERS for future expansion */ }; /* RAID map configuration infos. */ struct isw_map { - uint32_t pba_of_lba0; // start address of partition + uint32_t pba_of_lba0; // start address of partition uint32_t blocks_per_member; // blocks per member uint32_t num_data_stripes; // number of data stripes uint16_t blocks_per_strip; - uint8_t map_state; // Normal, Uninitialized, Degraded, Failed -#define ISW_T_STATE_NORMAL 0 -#define ISW_T_STATE_UNINITIALIZED 1 - uint8_t raid_level; + uint8_t map_state; // Normal, Uninitialized, Degraded, Failed +#define ISW_T_STATE_NORMAL 0x00 +#define ISW_T_STATE_UNINITIALIZED 0X01 +#define ISW_T_STATE_DEGRADED 0x02 +#define ISW_T_STATE_FAILED 0x03 + + uint8_t raid_level; #define ISW_T_RAID0 0 #define ISW_T_RAID1 1 -#define ISW_T_RAID5 5 // since metadata version 1.2.02 ? - uint8_t num_members; // number of member disks - uint8_t reserved[3]; - uint32_t filler[7]; // expansion area +#define ISW_T_RAID10 2 +#define ISW_T_RAID5 5 // since metadata version 1.2.02 ? +#define ISW_T_SPARE 8 +#define ISW_T_UNDEF 0xff + uint8_t num_members; // number of member disks + uint8_t num_domains; + uint8_t failed_disk_num; +#define ISW_DEV_NONE_FAILED 255 + uint8_t ddf; + + uint32_t filler[7]; // expansion area uint32_t disk_ord_tbl[1]; /* disk_ord_tbl[num_members], top byte special */ } __attribute__ ((packed)); struct isw_vol { - uint32_t reserved[2]; - uint8_t migr_state; // Normal or Migrating - uint8_t migr_type; // Initializing, Rebuilding, ... - uint8_t dirty; - uint8_t fill[1]; - uint32_t filler[5]; + uint32_t curr_migr_unit; + uint32_t check_point_id; + uint8_t migr_state; // Normal or Migrating + uint8_t migr_type; // Initializing, Rebuilding, ... + uint8_t dirty; + uint8_t fs_state; + uint16_t verify_errors; + uint16_t verify_bad_blocks; +#define ISW_RAID_VOL_FILLERS 4 + uint32_t filler[ISW_RAID_VOL_FILLERS]; struct isw_map map; // here comes another one if migr_state } __attribute__ ((packed)); struct isw_dev { - uint8_t volume[MAX_RAID_SERIAL_LEN]; + uint8_t volume[MAX_RAID_SERIAL_LEN]; uint32_t SizeLow; uint32_t SizeHigh; uint32_t status; /* Persistent RaidDev status */ - uint32_t reserved_blocks; /* Reserved blocks at beginning of volume */ -#define ISW_DEV_FILLERS 12 +#define ISW_DEV_BOOTABLE 0x01 +#define ISW_DEV_BOOT_DEVICE 0x02 +#define ISW_DEV_READ_COALESCING 0x04 +#define ISW_DEV_WRITE_COALESCING 0x08 +#define ISW_DEV_LAST_SHUTDOWN_DIRTY 0x10 +#define ISW_DEV_HIDDEN_AT_BOOT 0x20 +#define ISW_DEV_CURRENTLY_HIDDEN 0x40 +#define ISW_DEV_VERIFY_AND_FIX 0x80 +#define ISW_DEV_MAP_STATE_UNINIT 0x100 +#define ISW_DEV_NO_AUTO_RECOVERY 0x200 +#define ISW_DEV_CLONE_N_GO 0x400 +#define ISW_DEV_CLONE_MAN_SYNC 0x800 +#define ISW_DEV_CNG_MASTER_DISK_NUM 0x1000 + + uint32_t reserved_blocks; /* Reserved blocks at beginning of volume */ + uint8_t migr_priority; /* Medium, Low, High */ + uint8_t num_sub_vol; /* number of subvolumes */ + uint8_t tid; /* target Id */ + uint8_t cng_master_disk; /* */ + uint16_t cache_policy; /* Persistent cache info */ + uint8_t cng_state; + uint8_t cng_sub_state; + +#define ISW_DEV_FILLERS 10 uint32_t filler[ISW_DEV_FILLERS]; struct isw_vol vol; } __attribute__ ((packed)); struct isw { - int8_t sig[MAX_SIGNATURE_LENGTH];/* 0x0 - 0x1F */ - uint32_t check_sum; /* 0x20 - 0x23 MPB Checksum */ - uint32_t mpb_size; /* 0x24 - 0x27 Size of MPB */ - uint32_t family_num; /* 0x28 - 0x2B Checksum from first time this config was written */ + int8_t sig[MAX_SIGNATURE_LENGTH]; /* 0x0 - 0x1F */ + uint32_t check_sum; /* 0x20 - 0x23 MPB Checksum */ + uint32_t mpb_size; /* 0x24 - 0x27 Size of MPB */ + uint32_t family_num; /* 0x28 - 0x2B Checksum from first time this config was written */ /* 0x2C - 0x2F Incremented each time this array's MPB is written */ uint32_t generation_num; - uint32_t reserved[2]; /* 0x30 - 0x37 */ - uint8_t num_disks; /* 0x38 Number of configured disks */ - uint8_t num_raid_devs; /* 0x39 Number of configured volumes */ - uint8_t fill[2]; /* 0x3A - 0x3B */ -#define ISW_FILLERS 39 + uint32_t error_log_size; /* 0x30 - 0x33 in bytes */ + uint32_t attributes; /* 0x34 - 0x37 */ + + uint8_t num_disks; /* 0x38 Number of configured disks */ + uint8_t num_raid_devs; /* 0x39 Number of configured volumes */ + uint8_t error_log_pos; /* 0x3A */ + uint8_t fill[1]; /* 0x3B */ + uint32_t cache_size; /* 0x3c - 0x40 in mb */ + uint32_t orig_family_num; /* 0x40 - 0x43 original family num */ +#define ISW_FILLERS 37 uint32_t filler[ISW_FILLERS]; /* 0x3C - 0xD7 RAID_MPB_FILLERS */ struct isw_disk disk[1]; /* 0xD8 diskTbl[numDisks] */ // here comes isw_dev[num_raid_devs] --- dmraid/lib/format/ataraid/jm.c 2008/04/02 13:35:31 1.3 +++ dmraid/lib/format/ataraid/jm.c 2008/06/20 21:52:17 1.4 @@ -1,7 +1,7 @@ /* * JMicron metadata format handler. * - * Copyright (C) 2006,2007 Heinz Mauelshagen, Red Hat GmbH. + * Copyright (C) 2006-2008 Heinz Mauelshagen, Red Hat GmbH. * All rights reserved. * * See file LICENSE at the top of this source tree for license information. @@ -22,8 +22,8 @@ /* RAID set name */ static int member(struct jm *jm); -static char *name(struct lib_context *lc, struct raid_dev *rd, - unsigned int subset) +static char * +name(struct lib_context *lc, struct raid_dev *rd, unsigned int subset) { int i; size_t len; @@ -55,50 +55,57 @@ * Retrieve status of device. * FIXME: is this sufficient to cover all state ? */ -static enum status status(struct jm *jm) +static enum status +status(struct jm *jm) { - return jm->attribute & ~(JM_MOUNT|JM_BOOTABLE|JM_BADSEC|JM_ACTIVE|JM_UNSYNC|JM_NEWEST) ? s_broken : s_ok; + return jm->attribute & ~(JM_MOUNT | JM_BOOTABLE | JM_BADSEC | JM_ACTIVE + | JM_UNSYNC | JM_NEWEST) ? s_broken : s_ok; } /* Neutralize disk type */ -static enum type type(struct jm *jm) +static enum type +type(struct jm *jm) { /* Mapping of JM types to generic types */ static struct types types[] = { - { JM_T_JBOD, t_linear}, - { JM_T_RAID0, t_raid0}, - { JM_T_RAID01, t_raid1}, - { JM_T_RAID1, t_raid1}, - { 0, t_undef}, + { JM_T_JBOD, t_linear }, + { JM_T_RAID0, t_raid0 }, + { JM_T_RAID01, t_raid1 }, + { JM_T_RAID1, t_raid1 }, + { 0, t_undef }, }; return rd_type(types, (unsigned int) jm->mode); } /* Calculate checksum on metadata */ -static int checksum(struct jm *jm) +static int +checksum(struct jm *jm) { int count = 64; - uint16_t *p = (uint16_t*) jm, sum = 0; + uint16_t *p = (uint16_t *) jm, sum = 0; - while (count--) + while (count--) sum += *p++; /* FIXME: shouldn't this be one value only ? */ - return sum == 0 || sum == 1; + return !sum || sum == 1; } -static inline unsigned int segment(uint32_t m) +static inline unsigned int +segment(uint32_t m) { return (unsigned int) (m & JM_SEG_MASK); } -static inline unsigned int disk(unsigned int m) +static inline unsigned int +disk(unsigned int m) { return (unsigned int) (m & JM_HDD_MASK); } -static int member(struct jm *jm) +static int +member(struct jm *jm) { unsigned int i = JM_MEMBERS; @@ -111,25 +118,29 @@ } /* Decide about ordering sequence of RAID device. */ -static int dev_sort(struct list_head *pos, struct list_head *new) +static int +dev_sort(struct list_head *pos, struct list_head *new) { return member(META(RD(new), jm)) < member(META(RD(pos), jm)); } /* Decide about ordering sequence of RAID subset. */ -static int set_sort(struct list_head *pos, struct list_head *new) +static int +set_sort(struct list_head *pos, struct list_head *new) { return member(META(RD_RS(RS(pos)), jm)) > 1; } -static unsigned int stride(unsigned int shift) +static unsigned int +stride(unsigned int shift) { return 1 << (shift + 1); } -static void super_created(struct raid_set *super, void *private) +static void +super_created(struct raid_set *super, void *private) { - super->type = t_raid0; + super->type = t_raid0; super->stride = stride(META((private), jm)->block); } @@ -138,8 +149,9 @@ * * Check device hierarchy and create super set appropriately. */ -static int group_rd(struct lib_context *lc, struct raid_set *rs, - struct raid_set **ss, struct raid_dev *rd) +static int +group_rd(struct lib_context *lc, struct raid_set *rs, + struct raid_set **ss, struct raid_dev *rd) { struct jm *jm = META(rd, jm); @@ -154,7 +166,6 @@ case JM_T_RAID1: if (!find_set(lc, NULL, rs->name, FIND_TOP)) list_add_tail(&rs->list, LC_RS(lc)); - break; case JM_T_RAID01: @@ -169,8 +180,8 @@ /* * Add a JMicron RAID device to a set. */ -static struct raid_set *jm_group(struct lib_context *lc, - struct raid_dev *rd) +static struct raid_set * +jm_group(struct lib_context *lc, struct raid_dev *rd) { struct raid_set *rs, *ss = NULL; @@ -191,7 +202,8 @@ #if BYTE_ORDER == LITTLE_ENDIAN # define to_cpu NULL #else -static void to_cpu(void *meta) +static void +to_cpu(void *meta) { unsigned int i; struct jm *jm = meta; @@ -215,19 +227,20 @@ #endif /* Magic check. */ -static int is_jm(struct lib_context *lc, struct dev_info *di, void *meta) +static int +is_jm(struct lib_context *lc, struct dev_info *di, void *meta) { struct jm *jm = meta; - return !strncmp((const char*) jm->signature, - JM_SIGNATURE, JM_SIGNATURE_LEN) - && checksum(jm); + return !strncmp((const char *) jm->signature, + JM_SIGNATURE, JM_SIGNATURE_LEN) && + checksum(jm); } static int setup_rd(struct lib_context *lc, struct raid_dev *rd, struct dev_info *di, void *meta, union read_info *info); -static struct raid_dev *jm_read(struct lib_context *lc, - struct dev_info *di) +static struct raid_dev * +jm_read(struct lib_context *lc, struct dev_info *di) { return read_raid_dev(lc, di, NULL, sizeof(struct jm), JM_CONFIGOFFSET, @@ -237,8 +250,8 @@ /* * Write a JMicron RAID device. */ -static int jm_write(struct lib_context *lc, - struct raid_dev *rd, int erase) +static int +jm_write(struct lib_context *lc, struct raid_dev *rd, int erase) { int ret; #if BYTE_ORDER != LITTLE_ENDIAN @@ -258,17 +271,18 @@ * * FIXME: more sanity checks. */ -static unsigned int devices(struct raid_dev *rd, void *context) +static unsigned int +devices(struct raid_dev *rd, void *context) { unsigned int r = JM_MEMBERS; struct jm *jm = META(rd, jm); while (r-- && !jm->member[r]); - return ++r; } -static int jm_check(struct lib_context *lc, struct raid_set *rs) +static int +jm_check(struct lib_context *lc, struct raid_set *rs) { return check_raid_set(lc, rs, devices, NULL, NO_CHECK_RD, NULL, handler); @@ -277,7 +291,8 @@ /* * IO error event handler. */ -static int event_io(struct lib_context *lc, struct event_io *e_io) +static int +event_io(struct lib_context *lc, struct event_io *e_io) { struct raid_dev *rd = e_io->rd; struct jm *jm = META(rd, jm); @@ -286,21 +301,21 @@ if (S_BROKEN(status(jm))) return 0; - jm->checksum = 1; /* FIXME: how to flag a JMicron disk bad? */ - + jm->checksum = 1; /* FIXME: how to flag a JMicron disk bad? */ return 1; } static struct event_handlers jm_event_handlers = { .io = event_io, - .rd = NULL, /* FIXME: no device add/remove event handler yet. */ + .rd = NULL, /* FIXME: no device add/remove event handler yet. */ }; #ifdef DMRAID_NATIVE_LOG /* * Log native information about an JM RAID device. */ -static void jm_log(struct lib_context *lc, struct raid_dev *rd) +static void +jm_log(struct lib_context *lc, struct raid_dev *rd) { unsigned int i; struct jm *jm = META(rd, jm); @@ -319,44 +334,49 @@ DP("name: %u", jm, jm->mode); DP("block: %u", jm, jm->block); DP("attribute: %u", jm, jm->attribute); + for (i = 0; i < JM_SPARES; i++) P2("spare[%d]: 0x%x", jm, i, jm->spare[i]); + for (i = 0; i < JM_MEMBERS; i++) P2("member[%d]: 0x%x", jm, i, jm->member[i]); } #endif static struct dmraid_format jm_format = { - .name = HANDLER, - .descr = "JMicron ATARAID", - .caps = "S,0,1", + .name = HANDLER, + .descr = "JMicron ATARAID", + .caps = "S,0,1", .format = FMT_RAID, - .read = jm_read, - .write = jm_write, - .group = jm_group, - .check = jm_check, - .events = &jm_event_handlers, + .read = jm_read, + .write = jm_write, + .group = jm_group, + .check = jm_check, + .events = &jm_event_handlers, #ifdef DMRAID_NATIVE_LOG - .log = jm_log, + .log = jm_log, #endif }; /* Register this format handler with the format core. */ -int register_jm(struct lib_context *lc) +int +register_jm(struct lib_context *lc) { return register_format_handler(lc, &jm_format); } /* Calculate RAID device size in sectors depending on RAID type. */ -static inline uint64_t sectors(struct jm *jm) +static inline uint64_t +sectors(struct jm *jm) { /* range * 32MB[sectors] + range2 */ - return jm->segment.range * 32*2048 + jm->segment.range2; + return jm->segment.range * 32 * 2048 + jm->segment.range2; } /* Set the RAID device contents up derived from the JMicron ones */ -static int setup_rd(struct lib_context *lc, struct raid_dev *rd, - struct dev_info *di, void *meta, union read_info *info) +static int +setup_rd(struct lib_context *lc, struct raid_dev *rd, + struct dev_info *di, void *meta, union read_info *info) { struct jm *jm = meta; @@ -365,13 +385,13 @@ rd->meta_areas->offset = JM_CONFIGOFFSET >> 9; rd->meta_areas->size = sizeof(*jm); - rd->meta_areas->area = (void*) jm; + rd->meta_areas->area = (void *) jm; rd->di = di; rd->fmt = &jm_format; rd->status = status(jm); - rd->type = type(jm); + rd->type = type(jm); rd->offset = jm->segment.base; if (!(rd->sectors = sectors(jm))) --- dmraid/lib/format/ataraid/jm.h 2008/02/22 16:57:36 1.1 +++ dmraid/lib/format/ataraid/jm.h 2008/06/20 21:52:17 1.2 @@ -22,35 +22,35 @@ struct jm { #define JM_SIGNATURE "JM" #define JM_SIGNATURE_LEN 2 - int8_t signature[JM_SIGNATURE_LEN]; /* 0x0 - 0x01 */ + int8_t signature[JM_SIGNATURE_LEN]; /* 0x0 - 0x01 */ - uint16_t version; /* 0x03 - 0x04 JMicron version */ + uint16_t version; /* 0x03 - 0x04 JMicron version */ #define JM_MINOR_VERSION(jm) (jm->version & 0xFF) #define JM_MAJOR_VERSION(jm) (jm->version >> 8) - uint16_t checksum; /* 0x04 - 0x05 */ - uint8_t filler[10]; + uint16_t checksum; /* 0x04 - 0x05 */ + uint8_t filler[10]; - uint32_t identity; /* 0x10 - 0x13 */ + uint32_t identity; /* 0x10 - 0x13 */ struct { - uint32_t base; /* 0x14 - 0x17 */ - uint32_t range; /* 0x18 - 0x1B range */ - uint16_t range2; /* 0x1C - 0x1D range2 */ + uint32_t base; /* 0x14 - 0x17 */ + uint32_t range; /* 0x18 - 0x1B range */ + uint16_t range2; /* 0x1C - 0x1D range2 */ } segment; #define JM_NAME_LEN 16 - int8_t name[JM_NAME_LEN]; /* 0x20 - 0x2F */ + int8_t name[JM_NAME_LEN]; /* 0x20 - 0x2F */ - uint8_t mode; /* 0x30 RAID level */ + uint8_t mode; /* 0x30 RAID level */ #define JM_T_RAID0 0 #define JM_T_RAID1 1 #define JM_T_RAID01 2 /* RAID 0+1 (striped with mirrors underneath) */ #define JM_T_JBOD 3 #define JM_T_RAID5 5 - uint8_t block; /* 0x31 stride size (2=4K, 3=8K, ...) */ - uint16_t attribute; /* 0x32 - 0x33 */ + uint8_t block; /* 0x31 stride size (2=4K, 3=8K, ...) */ + uint16_t attribute; /* 0x32 - 0x33 */ #define JM_MOUNT 0x01 #define JM_BOOTABLE 0x02 #define JM_BADSEC 0x03 @@ -58,16 +58,16 @@ #define JM_UNSYNC 0x06 #define JM_NEWEST 0x07 - uint8_t filler1[4]; + uint8_t filler1[4]; #define JM_SPARES 2 #define JM_MEMBERS 8 - uint32_t spare[JM_SPARES]; /* 0x38 - 0x3F */ - uint32_t member[JM_MEMBERS]; /* 0x40 - 0x5F */ + uint32_t spare[JM_SPARES]; /* 0x38 - 0x3F */ + uint32_t member[JM_MEMBERS]; /* 0x40 - 0x5F */ #define JM_HDD_MASK 0xFFFFFFF0 #define JM_SEG_MASK 0x0F - uint8_t filler2[0x20]; + uint8_t filler2[0x20]; } __attribute__ ((packed)); #endif --- dmraid/lib/format/ataraid/lsi.c 2008/04/02 13:35:31 1.3 +++ dmraid/lib/format/ataraid/lsi.c 2008/06/20 21:52:17 1.4 @@ -1,7 +1,7 @@ /* * LSI Logic MegaRAID (and MegaIDE ?) ATARAID metadata format handler. * - * Copyright (C) 2004,2005 Heinz Mauelshagen, Red Hat GmbH. + * Copyright (C) 2004-2008 Heinz Mauelshagen, Red Hat GmbH. * All rights reserved. * * See file LICENSE at the top of this source tree for license information. @@ -26,26 +26,29 @@ /* Make up RAID device name. */ /* FIXME: senseful name ;) */ -static unsigned int get_disk_slot(struct lsi *lsi) +static unsigned int +get_disk_slot(struct lsi *lsi) { return lsi->set_number * 2 + lsi->disk_number; } -static struct lsi_disk *get_disk(struct lsi *lsi) +static struct lsi_disk * +get_disk(struct lsi *lsi) { return lsi->disks + get_disk_slot(lsi); } -static size_t _name(struct lsi *lsi, char *str, size_t len, unsigned int subset) +static size_t +_name(struct lsi *lsi, char *str, size_t len, unsigned int subset) { return snprintf(str, len, subset ? "lsi_%u%u-%u" : "lsi_%u%u", - lsi->set_id, lsi->set_number, - (get_disk(lsi))->raid10_mirror); + lsi->set_id, lsi->set_number, + get_disk(lsi)->raid10_mirror); } -static char *name(struct lib_context *lc, struct raid_dev *rd, - unsigned int subset) +static char * +name(struct lib_context *lc, struct raid_dev *rd, unsigned int subset) { size_t len; char *ret; @@ -63,14 +66,15 @@ } /* Neutralize disk type */ -static enum type type(struct lsi *lsi) +static enum type +type(struct lsi *lsi) { /* Mapping of LSI Logic types to generic types */ static struct types types[] = { { LSI_T_RAID0, t_raid0 }, { LSI_T_RAID1, t_raid1 }, { LSI_T_RAID10, t_raid0 }, - { 0, t_undef} + { 0, t_undef } }; return rd_type(types, (unsigned int) lsi->type); @@ -78,28 +82,31 @@ /* LSI device status. */ /* FIXME: add flesh. */ -static int status(struct lsi *lsi) +static int +status(struct lsi *lsi) { return s_ok; } /* Decide about ordering sequence of RAID device. */ -static int dev_sort(struct list_head *pos, struct list_head *new) +static int +dev_sort(struct list_head *pos, struct list_head *new) { struct lsi *p = META(RD(pos), lsi), *n = META(RD(new), lsi); switch (n->type) { case LSI_T_RAID10: - return (get_disk(n))->raid10_stripe < - (get_disk(p))->raid10_stripe; + return (get_disk(n))->raid10_stripe < + (get_disk(p))->raid10_stripe; - default: /* RAID0 + RAID01 */ + default: /* RAID0 + RAID01 */ return get_disk_slot(n) < get_disk_slot(p); } } /* Decide about ordering sequence of RAID subset. */ -static int set_sort(struct list_head *pos, struct list_head *new) +static int +set_sort(struct list_head *pos, struct list_head *new) { struct lsi *p = META(RD_RS(pos), lsi), *n = META(RD_RS(new), lsi); @@ -114,7 +121,8 @@ #if BYTE_ORDER == LITTLE_ENDIAN # define to_cpu NULL #else -static void to_cpu(void *meta) +static void +to_cpu(void *meta) { struct lsi *lsi = meta; struct lsi_disk *disk; @@ -130,25 +138,28 @@ } #endif -static int is_lsi(struct lib_context *lc, struct dev_info *di, void *meta) +static int +is_lsi(struct lib_context *lc, struct dev_info *di, void *meta) { - return !strncmp((const char*) ((struct lsi *) meta)->magic_name, - LSI_MAGIC_NAME, LSI_MAGIC_NAME_LEN); + return !strncmp((const char *) ((struct lsi *) meta)->magic_name, + LSI_MAGIC_NAME, LSI_MAGIC_NAME_LEN); } static int setup_rd(struct lib_context *lc, struct raid_dev *rd, struct dev_info *di, void *meta, union read_info *info); -static struct raid_dev *lsi_read(struct lib_context *lc, struct dev_info *di) +static struct raid_dev * +lsi_read(struct lib_context *lc, struct dev_info *di) { return read_raid_dev(lc, di, NULL, - sizeof(struct lsi), LSI_CONFIGOFFSET, + sizeof(struct lsi), LSI_CONFIGOFFSET, to_cpu, is_lsi, NULL, setup_rd, handler); } /* * Write a LSI Logic RAID device. */ -static int lsi_write(struct lib_context *lc, struct raid_dev *rd, int erase) +static int +lsi_write(struct lib_context *lc, struct raid_dev *rd, int erase) { int ret; #if BYTE_ORDER != LITTLE_ENDIAN @@ -168,14 +179,16 @@ * * FIXME: this needs more work together with the metadata reengineering. */ -static void super_created(struct raid_set *ss, void *private) +static void +super_created(struct raid_set *ss, void *private) { - ss->type = t_raid1; + ss->type = t_raid1; ss->stride = META(private, lsi)->stride; } -static int group_rd(struct lib_context *lc, struct raid_set *rs, - struct raid_set **ss, struct raid_dev *rd) +static int +group_rd(struct lib_context *lc, struct raid_set *rs, + struct raid_set **ss, struct raid_dev *rd) { struct lsi *lsi = META(rd, lsi); @@ -204,8 +217,8 @@ return 1; } -static struct raid_set *lsi_group(struct lib_context *lc, - struct raid_dev *rd) +static struct raid_set * +lsi_group(struct lib_context *lc, struct raid_dev *rd) { struct raid_set *rs, *ss = NULL; @@ -220,9 +233,10 @@ } /* Figure total number of disks depending on RAID type. */ -static unsigned int devices(struct raid_dev *rd, void *context) +static unsigned int +devices(struct raid_dev *rd, void *context) { - switch ((META(rd, lsi))->type) { + switch (META(rd, lsi)->type) { case LSI_T_RAID10: return 4; @@ -239,7 +253,8 @@ * * FIXME: more sanity checks!!! */ -static int lsi_check(struct lib_context *lc, struct raid_set *rs) +static int +lsi_check(struct lib_context *lc, struct raid_set *rs) { return check_raid_set(lc, rs, devices, NULL, NO_CHECK_RD, NULL, handler); @@ -248,7 +263,8 @@ /* * IO error event handler. */ -static int event_io(struct lib_context *lc, struct event_io *e_io) +static int +event_io(struct lib_context *lc, struct event_io *e_io) { struct raid_dev *rd = e_io->rd; struct lsi *lsi = META(rd, lsi); @@ -258,18 +274,18 @@ return 0; // FIXME: lsi->? = BAD; - return 1; } static struct event_handlers lsi_event_handlers = { .io = event_io, - .rd = NULL, /* FIXME: no device add/remove event handler yet. */ + .rd = NULL, /* FIXME: no device add/remove event handler yet. */ }; #ifdef DMRAID_NATIVE_LOG /* Log native information about an LSI Logic RAID device. */ -static void lsi_log(struct lib_context *lc, struct raid_dev *rd) +static void +lsi_log(struct lib_context *lc, struct raid_dev *rd) { unsigned int i; struct lsi *lsi = META(rd, lsi); @@ -294,12 +310,12 @@ disk->unknown, disk->unknown); P("disks[%u].magic_0: 0x%x, %x, %x", lsi, disk->magic_0, i, disk->magic_0, - (unsigned char) (((char*) &disk->magic_0)[0]), - (unsigned char) (((char*) &disk->magic_0)[1])); + (unsigned char) (((char *) &disk->magic_0)[0]), + (unsigned char) (((char *) &disk->magic_0)[1])); P("disks[%u].magic_1: 0x%x, %x, %x", lsi, disk->magic_1, i, disk->magic_1, - (unsigned char) (((char*) &disk->magic_1)[0]), - (unsigned char) (((char*) &disk->magic_1)[1])); + (unsigned char) (((char *) &disk->magic_1)[0]), + (unsigned char) (((char *) &disk->magic_1)[1])); P("disks[%u].disk_number: %u", lsi, disk->disk_number, i, disk->disk_number); P("disks[%u].set_number: %u", lsi, disk->set_number, @@ -315,29 +331,31 @@ #endif static struct dmraid_format lsi_format = { - .name = HANDLER, - .descr = "LSI Logic MegaRAID", - .caps = "0,1,10", + .name = HANDLER, + .descr = "LSI Logic MegaRAID", + .caps = "0,1,10", .format = FMT_RAID, - .read = lsi_read, - .write = lsi_write, - .group = lsi_group, - .check = lsi_check, - .events = &lsi_event_handlers, + .read = lsi_read, + .write = lsi_write, + .group = lsi_group, + .check = lsi_check, + .events = &lsi_event_handlers, #ifdef DMRAID_NATIVE_LOG - .log = lsi_log, + .log = lsi_log, #endif }; /* Register this format handler with the format core. */ -int register_lsi(struct lib_context *lc) +int +register_lsi(struct lib_context *lc) { return register_format_handler(lc, &lsi_format); } /* Set the RAID device contents up derived from the LSI ones */ -static int setup_rd(struct lib_context *lc, struct raid_dev *rd, - struct dev_info *di, void *meta, union read_info *info) +static int +setup_rd(struct lib_context *lc, struct raid_dev *rd, + struct dev_info *di, void *meta, union read_info *info) { struct lsi *lsi = meta; @@ -345,19 +363,19 @@ return 0; rd->meta_areas->offset = LSI_CONFIGOFFSET >> 9; - rd->meta_areas->size = sizeof(*lsi); - rd->meta_areas->area = (void*) lsi; + rd->meta_areas->size = sizeof(*lsi); + rd->meta_areas->area = (void *) lsi; - rd->di = di; + rd->di = di; rd->fmt = &lsi_format; rd->status = status(lsi); - rd->type = type(lsi); + rd->type = type(lsi); rd->offset = LSI_DATAOFFSET; /* FIXME: propper size ? */ if (!(rd->sectors = rd->meta_areas->offset)) return log_zero_sectors(lc, di->path, handler); - return (rd->name = name(lc, rd, 1)) ? 1 : 0; + return (rd->name = name(lc, rd, 1)) ? 1 : 0; } --- dmraid/lib/format/ataraid/lsi.h 2008/04/02 13:35:31 1.2 +++ dmraid/lib/format/ataraid/lsi.h 2008/06/20 21:52:17 1.3 @@ -36,21 +36,21 @@ #define LSI_MAGIC_NAME "$XIDE$" #define LSI_MAGIC_NAME_LEN (sizeof(LSI_MAGIC_NAME) - 1) uint8_t magic_name[LSI_MAGIC_NAME_LEN]; /* 0x0 - 0x05 */ - uint8_t dummy; /* 0x06 */ - uint8_t seqno; /* 0x07 */ - uint32_t dummy2; /* 0x08 - 0x0B */ - uint32_t dummy3; /* 0x0C - 0x0F */ - uint8_t type; /* 0x10 */ + uint8_t dummy; /* 0x06 */ + uint8_t seqno; /* 0x07 */ + uint32_t dummy2; /* 0x08 - 0x0B */ + uint32_t dummy3; /* 0x0C - 0x0F */ + uint8_t type; /* 0x10 */ #define LSI_T_RAID0 1 #define LSI_T_RAID1 2 #define LSI_T_RAID10 3 uint8_t dummy4; /* 0x11 */ - uint16_t stride; /* 0x12 - 0x13 */ - uint8_t filler[0x20-0x14]; /* 0x14 - 0x1F */ + uint16_t stride; /* 0x12 - 0x13 */ + uint8_t filler[0x20 - 0x14]; /* 0x14 - 0x1F */ #define LSI_MAX_DISKS 4 - struct lsi_disk disks[LSI_MAX_DISKS];/* 0x20 - 0x5F */ + struct lsi_disk disks[LSI_MAX_DISKS]; /* 0x20 - 0x5F */ #define LSI_DISK(lsi) (lsi->set_number * 2 + lsi->disk_number) #define LSI_MAGIC_0(lsi) (lsi->disks[LSI_DISK(lsi)].magic_0) @@ -59,13 +59,13 @@ #define LSI_SET_NUMBER(lsi) (lsi->disks[LSI_DISK(lsi)].set_number) #undef LSI_DISK - uint8_t filler1[0x1F0-0x60]; /* 0x70 - 0x1EF */ + uint8_t filler1[0x1F0 - 0x60]; /* 0x70 - 0x1EF */ - uint8_t disk_number; /* 0x1F0 */ - uint8_t set_number; /* 0x1F1 */ - uint32_t set_id; /* 0x1F2 - 0x1F5 */ + uint8_t disk_number; /* 0x1F0 */ + uint8_t set_number; /* 0x1F1 */ + uint32_t set_id; /* 0x1F2 - 0x1F5 */ - uint8_t filler2[0x200-0x1F6]; /* 0x1F6 - 0x200 */ + uint8_t filler2[0x200 - 0x1F6]; /* 0x1F6 - 0x200 */ } __attribute__ ((packed)); #endif --- dmraid/lib/format/ataraid/nv.c 2008/04/02 13:35:31 1.3 +++ dmraid/lib/format/ataraid/nv.c 2008/06/20 21:52:17 1.4 @@ -2,7 +2,8 @@ * NVidia NVRAID metadata format handler. * * Copyright (C) 2004 NVidia Corporation. All rights reserved. - * Copyright (C) 2004,2005 Heinz Mauelshagen, Red Hat GmbH. + * + * Copyright (C) 2004-2008 Heinz Mauelshagen, Red Hat GmbH. * All rights reserved. * * See file LICENSE at the top of this source tree for license information. @@ -27,12 +28,14 @@ * The subset parameter indicates the requirement to create * name suffixes in case the RAID set is hierarchical. */ -static unsigned int _subset(struct nv *nv) +static unsigned int +_subset(struct nv *nv) { return nv->unitNumber >= nv->array.stripeWidth; } -static size_t _name(struct nv *nv, char *str, size_t len, unsigned int subset) +static size_t +_name(struct nv *nv, char *str, size_t len, unsigned int subset) { unsigned int i = NV_SIGNATURES; uint32_t sum = 0; @@ -44,8 +47,8 @@ handler, sum, _subset(nv)); } -static char *name(struct lib_context *lc, struct raid_dev *rd, - unsigned int subset) +static char * +name(struct lib_context *lc, struct raid_dev *rd, unsigned int subset) { size_t len; char *ret; @@ -61,7 +64,8 @@ return ret; } -static enum status status(struct nv *nv) +static enum status +status(struct nv *nv) { static struct states states[] = { { NV_IDLE, s_ok }, @@ -77,7 +81,8 @@ } /* Neutralize disk type using generic metadata type mapping function. */ -static enum type type(struct nv *nv) +static enum type +type(struct nv *nv) { uint8_t stripeWidth = nv->array.stripeWidth; /* Mapping of nv types to generic types */ @@ -89,17 +94,17 @@ { NV_LEVEL_1_0, t_raid0 }, { NV_LEVEL_3, t_raid4 }, { NV_LEVEL_5_SYM, t_raid5_ls }, - { NV_LEVEL_UNKNOWN, t_spare}, /* FIXME: UNKNOWN = spare ? */ + { NV_LEVEL_UNKNOWN, t_spare }, /* FIXME: UNKNOWN = spare ? */ /* FIXME: The ones below don't really map to anything ?? */ { NV_LEVEL_10, t_undef }, - { NV_LEVEL_5, t_undef }, /* Asymmetric RAID 5 is not used */ + { NV_LEVEL_5, t_undef }, /* Asymmetric RAID 5 is not used */ }; /* * FIXME: is there a direct way to decide what - * a spare is (eg, NV_LEVEL_UNKNOWN) ? + * a spare is (eg, NV_LEVEL_UNKNOWN) ? */ - switch(NV_RAIDLEVEL(nv)) { + switch (NV_RAIDLEVEL(nv)) { case NV_LEVEL_1_0: case NV_LEVEL_10: case NV_LEVEL_1: @@ -109,27 +114,29 @@ case NV_LEVEL_5_SYM: stripeWidth += 1; break; - - default: + + default: break; } if (nv->array.totalVolumes >= stripeWidth && - nv->unitNumber >= stripeWidth) + nv->unitNumber >= stripeWidth) return t_spare; return rd_type(types, (unsigned int) NV_RAIDLEVEL(nv)); } /* Decide about ordering sequence of RAID device. */ -static int dev_sort(struct list_head *pos, struct list_head *new) +static int +dev_sort(struct list_head *pos, struct list_head *new) { - return (META(RD(new), nv))->unitNumber < - (META(RD(pos), nv))->unitNumber; + return META(RD(new), nv)->unitNumber < + META(RD(pos), nv)->unitNumber; } /* Decide about ordering sequence of RAID subset. */ -static int set_sort(struct list_head *pos, struct list_head *new) +static int +set_sort(struct list_head *pos, struct list_head *new) { return _subset((META(RD_RS(RS(new)), nv))) < _subset((META(RD_RS(RS(pos)), nv))); @@ -141,7 +148,8 @@ #if BYTE_ORDER == LITTLE_ENDIAN # define to_cpu NULL #else -static void to_cpu(void *meta) +static void +to_cpu(void *meta) { struct nv *nv = meta; unsigned int i = NV_SIGNATURES; @@ -173,7 +181,8 @@ #endif /* Check the metadata checksum. */ -static int checksum(struct nv *nv) +static int +checksum(struct nv *nv) { uint32_t sum = 0; unsigned int s = nv->size; @@ -181,18 +190,19 @@ if (s != sizeof(*nv) / sizeof(sum)) return 0; - while (s--) - sum += ((uint32_t*) nv)[s]; + while (s--) + sum += ((uint32_t *) nv)[s]; /* Ignore chksum member itself. */ return nv->chksum - sum == nv->chksum; } -static int is_nv(struct lib_context *lc, struct dev_info *di, void *meta) +static int +is_nv(struct lib_context *lc, struct dev_info *di, void *meta) { struct nv *nv = meta; - if (strncmp((char*) nv->vendor, NV_ID_STRING, sizeof(NV_ID_STRING) - 1)) + if (strncmp((char *) nv->vendor, NV_ID_STRING, sizeof(NV_ID_STRING) -1)) return 0; if (checksum(nv)) @@ -200,10 +210,11 @@ LOG_ERR(lc, 0, "%s: bad checksum on %s", handler, di->path); } - + static int setup_rd(struct lib_context *lc, struct raid_dev *rd, struct dev_info *di, void *meta, union read_info *info); -static struct raid_dev *nv_read(struct lib_context *lc, struct dev_info *di) +static struct raid_dev * +nv_read(struct lib_context *lc, struct dev_info *di) { return read_raid_dev(lc, di, NULL, sizeof(struct nv), NV_CONFIGOFFSET, @@ -211,7 +222,8 @@ } /* Write private RAID metadata to device */ -static int nv_write(struct lib_context *lc, struct raid_dev *rd, int erase) +static int +nv_write(struct lib_context *lc, struct raid_dev *rd, int erase) { int ret; #if BYTE_ORDER != LITTLE_ENDIAN @@ -226,15 +238,17 @@ return ret; } -static void super_created(struct raid_set *ss, void *private) +static void +super_created(struct raid_set *ss, void *private) { - ss->type = t_raid1; + ss->type = t_raid1; ss->stride = META(private, nv)->array.stripeBlockSize; } /* FIXME: handle spares in mirrors and check that types are correct. */ -static int group_rd(struct lib_context *lc, struct raid_set *rs, - struct raid_set **ss, struct raid_dev *rd) +static int +group_rd(struct lib_context *lc, struct raid_set *rs, + struct raid_set **ss, struct raid_dev *rd) { struct nv *nv = META(rd, nv); @@ -251,7 +265,6 @@ case NV_LEVEL_5_SYM: if (!find_set(lc, NULL, rs->name, FIND_TOP)) list_add_tail(&rs->list, LC_RS(lc)); - break; case NV_LEVEL_1_0: @@ -264,8 +277,8 @@ } /* Add an NVidia RAID device to a set. */ -static struct raid_set *nv_group(struct lib_context *lc, - struct raid_dev *rd) +static struct raid_set * +nv_group(struct lib_context *lc, struct raid_dev *rd) { struct raid_set *rs, *ss = NULL; @@ -282,14 +295,16 @@ * * FIXME: more sanity checks. */ -static unsigned int devices(struct raid_dev *rd, void *context) +static unsigned int +devices(struct raid_dev *rd, void *context) { struct nv *nv = META(rd, nv); return nv->array.totalVolumes / (NVRAID_1_0(nv) ? 2 : 1); } -static int nv_check(struct lib_context *lc, struct raid_set *rs) +static int +nv_check(struct lib_context *lc, struct raid_set *rs) { return check_raid_set(lc, rs, devices, NULL, NO_CHECK_RD, NULL, handler); @@ -298,7 +313,8 @@ /* * IO error event handler. */ -static int event_io(struct lib_context *lc, struct event_io *e_io) +static int +event_io(struct lib_context *lc, struct event_io *e_io) { struct raid_dev *rd = e_io->rd; struct nv *nv = META(rd, nv); @@ -315,14 +331,15 @@ static struct event_handlers nv_event_handlers = { .io = event_io, - .rd = NULL, /* FIXME: no device add/remove event handler yet. */ + .rd = NULL, /* FIXME: no device add/remove event handler yet. */ }; #ifdef DMRAID_NATIVE_LOG /* * Log native information about the RAID device. */ -static void nv_log(struct lib_context *lc, struct raid_dev *rd) +static void +nv_log(struct lib_context *lc, struct raid_dev *rd) { unsigned int i, j; #define LEN NV_PRODUCTIDS + 1 @@ -379,29 +396,31 @@ #endif static struct dmraid_format nv_format = { - .name = HANDLER, - .descr = "NVidia RAID", - .caps = "S,0,1,10,5", + .name = HANDLER, + .descr = "NVidia RAID", + .caps = "S,0,1,10,5", .format = FMT_RAID, - .read = nv_read, - .write = nv_write, - .group = nv_group, - .check = nv_check, - .events = &nv_event_handlers, + .read = nv_read, + .write = nv_write, + .group = nv_group, + .check = nv_check, + .events = &nv_event_handlers, #ifdef DMRAID_NATIVE_LOG - .log = nv_log, + .log = nv_log, #endif }; /* Register this format handler with the format core. */ -int register_nv(struct lib_context *lc) +int +register_nv(struct lib_context *lc) { return register_format_handler(lc, &nv_format); } /* Set the RAID device contents up derived from the NV ones */ -static int setup_rd(struct lib_context *lc, struct raid_dev *rd, - struct dev_info *di, void *meta, union read_info *info) +static int +setup_rd(struct lib_context *lc, struct raid_dev *rd, + struct dev_info *di, void *meta, union read_info *info) { struct nv *nv = meta; @@ -410,17 +429,17 @@ rd->meta_areas->offset = NV_CONFIGOFFSET >> 9; rd->meta_areas->size = sizeof(*nv); - rd->meta_areas->area = (void*) nv; + rd->meta_areas->area = (void *) nv; - rd->di = di; + rd->di = di; rd->fmt = &nv_format; rd->status = status(nv); - rd->type = type(nv); + rd->type = type(nv); rd->offset = NV_DATAOFFSET; if (!(rd->sectors = rd->meta_areas->offset)) return log_zero_sectors(lc, di->path, handler); - return (rd->name = name(lc, rd, 1)) ? 1 : 0; + return (rd->name = name(lc, rd, 1)) ? 1 : 0; } --- dmraid/lib/format/ataraid/nv.h 2008/02/22 16:57:36 1.1 +++ dmraid/lib/format/ataraid/nv.h 2008/06/20 21:52:17 1.2 @@ -28,29 +28,29 @@ #define NV_ID_LENGTH 8 #define NV_ID_STRING "NVIDIA" -#define NV_VERSION 100 +#define NV_VERSION 100 #define NV_SECTOR_SIZE 512 -#define NV_PRODUCT_ID_LEN 16 /* Product ID size in bytes */ +#define NV_PRODUCT_ID_LEN 16 /* Product ID size in bytes */ typedef uint32_t lba_t; /* Array info */ struct nv_array_base { uint32_t version; /* Version of this struct */ - /* 0x640000 + sizeof(nv_array_base) */ + /* 0x640000 + sizeof(nv_array_base) */ #define NV_SIGNATURES 4 - uint32_t signature[NV_SIGNATURES]; /* Unique signature for array */ + uint32_t signature[NV_SIGNATURES]; /* Unique signature for array */ - uint8_t raidJobCode; /* State of array */ + uint8_t raidJobCode; /* State of array */ #define NV_IDLE 0 #define NV_SCDB_INIT_RAID 2 #define NV_SCDB_REBUILD_RAID 3 #define NV_SCDB_UPGRADE_RAID 4 #define NV_SCDB_SYNC_RAID 5 - uint8_t stripeWidth; /* Array stripe width */ - uint8_t totalVolumes; /* Total # of disks in array, including spare */ - uint8_t originalWidth; /* Stripe width before morph */ + uint8_t stripeWidth; /* Array stripe width */ + uint8_t totalVolumes; /* Total # of disks in array, including spare */ + uint8_t originalWidth; /* Stripe width before morph */ uint32_t raidLevel; /* Array RAID level */ #define NV_RAIDLEVEL(nv) ((nv)->array.raidLevel) @@ -66,45 +66,45 @@ #define NV_LEVEL_5_SYM_FLAG 0x10 #define NV_LEVEL_5_SYM (NV_LEVEL_5|NV_LEVEL_5_SYM_FLAG) - lba_t stripeBlockSize; /* Array stripe block size in sectors */ + lba_t stripeBlockSize; /* Array stripe block size in sectors */ uint32_t stripeBlockByteSize; /* stripeBlockSize in bytes */ uint32_t stripeBlockPower; /* Array stripe block size in log2 */ - lba_t stripeMask; /* stripeBlockSize - 1 */ - lba_t stripeSize; /* stripeBlockSize * stripeWidth */ + lba_t stripeMask; /* stripeBlockSize - 1 */ + lba_t stripeSize; /* stripeBlockSize * stripeWidth */ uint32_t stripeByteSize; /* stripeSize in bytes */ - lba_t raidJobMark; /* Ignored if array is idle, otherwise the */ - /* LBA where job is finished */ + lba_t raidJobMark; /* Ignored if array is idle, otherwise the */ + /* LBA where job is finished */ uint32_t originalLevel; /* RAID level before morph */ - lba_t originalCapacity; /* Array capacity before morph */ + lba_t originalCapacity; /* Array capacity before morph */ uint32_t flags; /* Flags for array */ -#define NV_ARRAY_FLAG_BOOT (0x00000001) /* BIOS use only */ -#define NV_ARRAY_FLAG_ERROR (0x00000002) /* Degraded or offling */ -#define NV_ARRAY_FLAG_PARITY_VALID (0x00000004) /* RAID-3/5 parity valid */ +#define NV_ARRAY_FLAG_BOOT (0x00000001) /* BIOS use only */ +#define NV_ARRAY_FLAG_ERROR (0x00000002) /* Degraded or offling */ +#define NV_ARRAY_FLAG_PARITY_VALID (0x00000004) /* RAID-3/5 parity valid */ #define NV_BROKEN(n) (n->array.flags & NV_ARRAY_FLAG_ERROR) #define NV_SET_BROKEN(n) (n->array.flags |= NV_ARRAY_FLAG_ERROR) } __attribute__ ((packed)); /* Ondisk metadata */ struct nv { - uint8_t vendor[NV_ID_LENGTH]; /* 0x00 - 0x07 ID string */ + uint8_t vendor[NV_ID_LENGTH]; /* 0x00 - 0x07 ID string */ uint32_t size; /* 0x08 - 0x0B Size of metadata in dwords */ uint32_t chksum; /* 0x0C - 0x0F Checksum of this struct */ uint16_t version; /* 0x10 - 0x11 NV version */ - uint8_t unitNumber; /* 0x12 Disk index in array */ - uint8_t reserved; /* 0x13 */ - lba_t capacity; /* 0x14 - 0x17 Array capacity in sectors */ + uint8_t unitNumber; /* 0x12 Disk index in array */ + uint8_t reserved; /* 0x13 */ + lba_t capacity; /* 0x14 - 0x17 Array capacity in sectors */ uint32_t sectorSize; /* 0x18 - 0x1B Sector size */ #define NV_PRODUCTIDS 16 - /* 0x1C - 0x2B Array product ID */ - uint8_t productID[NV_PRODUCTIDS]; - /* Match INQUIRY data */ + /* 0x1C - 0x2B Array product ID */ + uint8_t productID[NV_PRODUCTIDS]; + /* Match INQUIRY data */ #define NV_PRODUCTREVISIONS 4 - /* 0x2C - 0x2F Array product revision */ - uint8_t productRevision[NV_PRODUCTREVISIONS]; - /* Match INQUIRY data */ + /* 0x2C - 0x2F Array product revision */ + uint8_t productRevision[NV_PRODUCTREVISIONS]; + /* Match INQUIRY data */ uint32_t unitFlags; /* 0x30 - 0x33 Flags for this disk */ - struct nv_array_base array; /* Array information */ + struct nv_array_base array; /* Array information */ } __attribute__ ((packed)); #endif --- dmraid/lib/format/ataraid/pdc.c 2008/04/02 13:35:31 1.4 +++ dmraid/lib/format/ataraid/pdc.c 2008/06/20 21:52:17 1.5 @@ -27,19 +27,21 @@ /* * Make up Promise RAID device name. */ -static unsigned set_number(struct pdc *pdc) +static unsigned +set_number(struct pdc *pdc) { return pdc->raid.disk_number >= (pdc->raid.total_disks / 2); } -static size_t __name(struct pdc *pdc, char *str, size_t len, int subset) +static size_t +__name(struct pdc *pdc, char *str, size_t len, int subset) { return snprintf(str, len, subset ? "pdc_%u-%u" : "pdc_%u", pdc->raid.magic_1, set_number(pdc)); } -static char *_name(struct lib_context *lc, struct pdc *pdc, - unsigned subset) +static char * +_name(struct lib_context *lc, struct pdc *pdc, unsigned subset) { size_t len; char *ret = NULL; @@ -54,8 +56,8 @@ return ret; } -static char *name(struct lib_context *lc, struct raid_dev *rd, - unsigned subset) +static char * +name(struct lib_context *lc, struct raid_dev *rd, unsigned subset) { return _name(lc, META(rd, pdc), subset); } @@ -65,28 +67,31 @@ * * FIXME: need to identify state definitions. */ -static enum status status(struct pdc *pdc) +static enum status +status(struct pdc *pdc) { return PDC_BROKEN(pdc) ? s_broken : s_ok; } #define PDC_T_RAID10 0x2 /* Not defind by Promise (yet). */ -static int is_raid10(struct pdc *pdc) +static int +is_raid10(struct pdc *pdc) { return pdc->raid.type == PDC_T_RAID10 || (pdc->raid.type == PDC_T_RAID1 && pdc->raid.total_disks > 3); } /* Neutralize disk type */ -static enum type type(struct pdc *pdc) +static enum type +type(struct pdc *pdc) { /* Mapping of Promise types to generic types. */ static struct types types[] = { - { PDC_T_SPAN, t_linear}, - { PDC_T_RAID0, t_raid0}, - { PDC_T_RAID1, t_raid1}, - { PDC_T_RAID10, t_raid0}, - { 0, t_undef} + { PDC_T_SPAN, t_linear }, + { PDC_T_RAID0, t_raid0 }, + { PDC_T_RAID1, t_raid1 }, + { PDC_T_RAID10, t_raid0 }, + { 0, t_undef } }; if (is_raid10(pdc)) @@ -96,10 +101,11 @@ } /* Calculate checksum on Promise metadata. */ -static uint32_t checksum(struct pdc *pdc) +static uint32_t +checksum(struct pdc *pdc) { unsigned i = 511, sum = 0; - uint32_t *p = (uint32_t*) pdc; + uint32_t *p = (uint32_t *) pdc; while (i--) sum += *p++; @@ -115,7 +121,8 @@ #if BYTE_ORDER == LITTLE_ENDIAN # define to_cpu NULL #else -static void to_cpu(void *meta) +static void +to_cpu(void *meta) { struct pdc *pdc = meta; struct pdc_disk *disk; @@ -130,8 +137,7 @@ CVT32(pdc->raid.magic_1); for (disk = pdc->raid.disk; - disk < pdc->raid.disk + pdc->raid.total_disks; - disk++) { + disk < pdc->raid.disk + pdc->raid.total_disks; disk++) { CVT32(disk->magic_0); CVT32(disk->disk_number); } @@ -139,16 +145,17 @@ #endif /* Check for Promis signature. */ -static int is_signature(struct pdc *pdc) +static int +is_signature(struct pdc *pdc) { - return !strncmp((const char*) pdc->promise_id, + return !strncmp((const char *) pdc->promise_id, PDC_MAGIC, PDC_ID_LENGTH); } /* Read and try to discover Promise signature. */ -static void *pdc_read_metadata(struct lib_context *lc, struct dev_info *di, - size_t *size, uint64_t *offset, - union read_info *info) +static void * +pdc_read_metadata(struct lib_context *lc, struct dev_info *di, + size_t * size, uint64_t * offset, union read_info *info) { struct pdc *ret; unsigned ma, sub; @@ -175,7 +182,7 @@ /* Check all sector offsets for metadata signature. */ for (; *s && !info->u32; s++) { sector = sub ? di->sectors - *s : *s; - + /* ...and all possible optional metadata signatures. */ for (ma = 0; ma < PDC_MAX_META_AREAS && @@ -203,7 +210,7 @@ s = begin_sectors; } while (!info->u32 && sub--); - out: + out: /* No metadata signature(s) found. */ if (!info->u32) { dbg_free(ret); @@ -214,7 +221,8 @@ } /* Magic check. */ -static int is_pdc(struct lib_context *lc, struct dev_info *di, void *meta) +static int +is_pdc(struct lib_context *lc, struct dev_info *di, void *meta) { struct pdc *pdc = meta; @@ -226,7 +234,6 @@ pdc->raid.total_disks < PDC_MAXDISKS) return 1; - LOG_ERR(lc, 0, "%s: identifying %s, magic_0: 0x%x/0x%x, " "magic_1: 0x%x/0x%x, total_disks: %u", handler, di->path, @@ -236,8 +243,9 @@ static int setup_rd(struct lib_context *lc, struct raid_dev *rd, struct dev_info *di, void *meta, union read_info *info); -static struct raid_dev *pdc_read(struct lib_context *lc, struct dev_info *di) -{ +static struct raid_dev * +pdc_read(struct lib_context *lc, struct dev_info *di) +{ return read_raid_dev(lc, di, pdc_read_metadata, 0, 0, to_cpu, is_pdc, NULL, setup_rd, handler); } @@ -245,7 +253,8 @@ /* * Write a Promise FastTrak RAID device. */ -static int pdc_write(struct lib_context *lc, struct raid_dev *rd, int erase) +static int +pdc_write(struct lib_context *lc, struct raid_dev *rd, int erase) { int ret; #if BYTE_ORDER != LITTLE_ENDIAN @@ -261,14 +270,16 @@ } /* Decide about ordering sequence of RAID device. */ -static int dev_sort(struct list_head *pos, struct list_head *new) +static int +dev_sort(struct list_head *pos, struct list_head *new) { - return (META(RD(new), pdc))->raid.disk_number < - (META(RD(pos), pdc))->raid.disk_number; + return META(RD(new), pdc)->raid.disk_number < + META(RD(pos), pdc)->raid.disk_number; } /* Decide about ordering sequence of RAID subset. */ -static int set_sort(struct list_head *pos, struct list_head *new) +static int +set_sort(struct list_head *pos, struct list_head *new) { return !set_number(META(RD_RS(RS(new)), pdc)); } @@ -276,46 +287,49 @@ /* * Group the RAID disk into a Promise set. */ -static unsigned stride(struct pdc *pdc) +static unsigned +stride(struct pdc *pdc) { - return pdc->raid.raid0_shift ? 1 << pdc->raid.raid0_shift : 0; + return pdc->raid.raid0_shift ? (1 << pdc->raid.raid0_shift) : 0; } -static void super_created(struct raid_set *super, void *private) +static void +super_created(struct raid_set *super, void *private) { - super->type = t_raid1; + super->type = t_raid1; super->stride = stride(META((private), pdc)); } /* Calculate RAID device size in sectors depending on RAID type. */ -static uint64_t sectors(struct raid_dev *rd, unsigned meta_sector) +static uint64_t +sectors(struct raid_dev *rd, unsigned meta_sector) { struct pdc *pdc = META(rd, pdc); switch (pdc->raid.type) { case PDC_T_RAID10: - return pdc->raid.total_secs / (pdc->raid.total_disks / 2); + return pdc->raid.total_secs / (pdc->raid.total_disks / 2); case PDC_T_RAID1: - return pdc->raid.total_secs; + return pdc->raid.total_secs; case PDC_T_RAID0: - return pdc->raid.total_secs / pdc->raid.total_disks; + return pdc->raid.total_secs / pdc->raid.total_disks; case PDC_T_SPAN: - return rd->di->sectors - meta_sector; + return rd->di->sectors - meta_sector; } return 0; } -static struct raid_dev *_create_rd(struct lib_context *lc, struct raid_dev *rd, - struct pdc *pdc, unsigned idx) +static struct raid_dev * +_create_rd(struct lib_context *lc, struct raid_dev *rd, + struct pdc *pdc, unsigned idx) { struct raid_dev *r; - if (!is_pdc(lc, rd->di, pdc) || - !(r = alloc_raid_dev(lc, handler))) + if (!is_pdc(lc, rd->di, pdc) || !(r = alloc_raid_dev(lc, handler))) return NULL; if ((r->type = type(pdc)) == t_undef) { @@ -324,7 +338,7 @@ goto bad_free; } - if (!(r->name = _name(lc, pdc, is_raid10(pdc)))) + if (!(r->name = _name(lc, pdc, is_raid10(pdc)))) goto bad_free; /* Allocate meta_areas for devices() to work. */ @@ -356,15 +370,16 @@ log_zero_sectors(lc, r->di->path, handler); - bad_free: + bad_free: free_raid_dev(lc, &r); - out: + out: return r; } /* Add a PDC RAID device to a set. */ -static int _group_rd(struct lib_context *lc, struct raid_set *rs, - struct raid_set **ss, struct raid_dev *rd, struct pdc *pdc) +static int +_group_rd(struct lib_context *lc, struct raid_set *rs, + struct raid_set **ss, struct raid_dev *rd, struct pdc *pdc) { if (!init_raid_set(lc, rs, rd, stride(pdc), pdc->raid.type, handler)) return 0; @@ -396,7 +411,8 @@ return 1; } -static inline unsigned count_meta_areas(struct pdc *pdc) +static inline unsigned +count_meta_areas(struct pdc *pdc) { unsigned r; @@ -410,8 +426,9 @@ } /* FIXME: different super sets possible with multiple metadata areas ? */ -static int group_rd(struct lib_context *lc, struct raid_set *rs, - struct raid_set **ss, struct raid_dev *rd) +static int +group_rd(struct lib_context *lc, struct raid_set *rs, + struct raid_set **ss, struct raid_dev *rd) { int r; struct pdc *pdc = META(rd, pdc); @@ -442,7 +459,8 @@ return r; } -static struct raid_set *pdc_group(struct lib_context *lc, struct raid_dev *rd) +static struct raid_set * +pdc_group(struct lib_context *lc, struct raid_dev *rd) { struct raid_set *rs, *ss = NULL; @@ -461,23 +479,26 @@ * * FIXME: more sanity checks. */ -static unsigned devices(struct raid_dev *rd, void *context) +static unsigned +devices(struct raid_dev *rd, void *context) { struct pdc *pdc = META(rd, pdc); if (context && pdc->raid.type != PDC_T_SPAN) - *((uint64_t*) context) += rd->sectors; + *((uint64_t *) context) += rd->sectors; return pdc->raid.total_disks; } -static int check_rd(struct lib_context *lc, struct raid_set *rs, - struct raid_dev *rd, void *context) +static int +check_rd(struct lib_context *lc, struct raid_set *rs, + struct raid_dev *rd, void *context) { - return *((uint64_t*) context) >= (META(rd, pdc))->raid.total_secs; + return *((uint64_t *) context) >= (META(rd, pdc))->raid.total_secs; } -static int pdc_check(struct lib_context *lc, struct raid_set *rs) +static int +pdc_check(struct lib_context *lc, struct raid_set *rs) { uint64_t total_secs = 0; @@ -494,7 +515,8 @@ /* * IO error event handler. */ -static int event_io(struct lib_context *lc, struct event_io *e_io) +static int +event_io(struct lib_context *lc, struct event_io *e_io) { struct raid_dev *rd = e_io->rd; struct pdc *pdc = META(rd, pdc); @@ -504,19 +526,18 @@ return 0; PDC_SET_BROKEN(pdc); - return 1; } static struct event_handlers pdc_event_handlers = { .io = event_io, - .rd = NULL, /* FIXME: no device add/remove event handler yet. */ + .rd = NULL, /* FIXME: no device add/remove event handler yet. */ }; #ifdef DMRAID_NATIVE_LOG /* Log native information about a Promise RAID device. */ -static void _pdc_log(struct lib_context *lc, struct dev_info *di, - struct pdc *pdc) +static void +_pdc_log(struct lib_context *lc, struct dev_info *di, struct pdc *pdc) { unsigned i; struct pdc_disk *disk; @@ -539,7 +560,7 @@ DP("raid.device: %u", pdc, pdc->raid.device); DP("raid.magic_0: 0x%x", pdc, pdc->raid.magic_0); P("raid.unknown_1: 0x%x %u", - pdc, pdc->raid.unknown_1, pdc->raid.unknown_1, pdc->raid.unknown_1); + pdc, pdc->raid.unknown_1, pdc->raid.unknown_1, pdc->raid.unknown_1); P("raid.start: 0x%x %u", pdc, pdc->raid.start, pdc->raid.start, pdc->raid.start); DP("raid.disk_secs: %u", pdc, pdc->raid.disk_secs); @@ -562,8 +583,7 @@ pdc, pdc->raid.unknown_5, pdc->raid.unknown_5, pdc->raid.unknown_5); for (disk = pdc->raid.disk, i = 0; - i < pdc->raid.total_disks; - disk++, i++) { + i < pdc->raid.total_disks; disk++, i++) { P2("raid.disk[%d].unknown_0: 0x%x", pdc, i, disk->unknown_0); P2("raid.disk[%d].channel: %u", pdc, i, disk->channel); P2("raid.disk[%d].device: %u", pdc, i, disk->device); @@ -572,39 +592,42 @@ } P("checksum: 0x%x %s", pdc, pdc->checksum, pdc->checksum, - checksum(pdc) ? "Ok" : "BAD"); + checksum(pdc) ? "Ok" : "BAD"); } -static void pdc_log(struct lib_context *lc, struct raid_dev *rd) +static void +pdc_log(struct lib_context *lc, struct raid_dev *rd) { _pdc_log(lc, rd->di, META(rd, pdc)); } #endif static struct dmraid_format pdc_format = { - .name = HANDLER, - .descr = "Promise FastTrack", - .caps = "S,0,1,10", + .name = HANDLER, + .descr = "Promise FastTrack", + .caps = "S,0,1,10", .format = FMT_RAID, - .read = pdc_read, - .write = pdc_write, - .group = pdc_group, - .check = pdc_check, - .events = &pdc_event_handlers, + .read = pdc_read, + .write = pdc_write, + .group = pdc_group, + .check = pdc_check, + .events = &pdc_event_handlers, #ifdef DMRAID_NATIVE_LOG - .log = pdc_log, + .log = pdc_log, #endif }; /* Register this format handler with the format core. */ -int register_pdc(struct lib_context *lc) +int +register_pdc(struct lib_context *lc) { return register_format_handler(lc, &pdc_format); } /* Set the RAID device contents up derived from the PDC ones */ -static int setup_rd(struct lib_context *lc, struct raid_dev *rd, - struct dev_info *di, void *meta, union read_info *info) +static int +setup_rd(struct lib_context *lc, struct raid_dev *rd, + struct dev_info *di, void *meta, union read_info *info) { unsigned meta_sector; struct pdc *pdc = meta; @@ -620,7 +643,7 @@ rd->meta_areas->size = sizeof(*pdc); rd->meta_areas->area = pdc; - rd->di = di; + rd->di = di; rd->fmt = &pdc_format; rd->status = status(pdc); @@ -634,5 +657,5 @@ if (!(rd->sectors = sectors(rd, meta_sector))) return log_zero_sectors(lc, di->path, handler); - return (rd->name = _name(lc, pdc, is_raid10(pdc))) ? 1 : 0; + return (rd->name = _name(lc, pdc, is_raid10(pdc))) ? 1 : 0; } --- dmraid/lib/format/ataraid/pdc.h 2008/04/02 13:35:31 1.2 +++ dmraid/lib/format/ataraid/pdc.h 2008/06/20 21:52:17 1.3 @@ -29,54 +29,54 @@ uint8_t promise_id[PDC_ID_LENGTH]; /* 0x00 - 0x17 */ #define PDC_MAGIC "Promise Technology, Inc." - uint32_t unknown_0; /* 0x18 - 0x1B */ - uint32_t magic_0; /* 0x1C - 0x1F */ - uint32_t unknown_1; /* 0x20 - 0x23 */ - uint32_t magic_1; /* 0x24 - 0x27 */ - uint16_t unknown_2; /* 0x28 - 0x2B */ - uint8_t filler1[470]; /* 0x2C - 0x1FF */ + uint32_t unknown_0; /* 0x18 - 0x1B */ + uint32_t magic_0; /* 0x1C - 0x1F */ + uint32_t unknown_1; /* 0x20 - 0x23 */ + uint32_t magic_1; /* 0x24 - 0x27 */ + uint16_t unknown_2; /* 0x28 - 0x2B */ + uint8_t filler1[470]; /* 0x2C - 0x1FF */ struct { - uint32_t flags; /* 0x200 - 0x203 */ - uint8_t unknown_0; /* 0x204 */ - uint8_t disk_number; /* 0x205 */ - uint8_t channel; /* 0x206 */ - uint8_t device; /* 0x207 */ - uint32_t magic_0; /* 0x208 - 0x20B */ - uint32_t unknown_1; /* 0x20C - 0x20F */ - // uint32_t unknown_2; /* 0x210 - 0x213 */ - uint32_t start; /* 0x210 - 0x213 */ - uint32_t disk_secs; /* 0x214 - 0x217 */ - uint32_t unknown_3; /* 0x218 - 0x21B */ - uint16_t unknown_4; /* 0x21C - 0x21D */ - uint8_t status; /* 0x21E */ + uint32_t flags; /* 0x200 - 0x203 */ + uint8_t unknown_0; /* 0x204 */ + uint8_t disk_number; /* 0x205 */ + uint8_t channel; /* 0x206 */ + uint8_t device; /* 0x207 */ + uint32_t magic_0; /* 0x208 - 0x20B */ + uint32_t unknown_1; /* 0x20C - 0x20F */ + // uint32_t unknown_2; /* 0x210 - 0x213 */ + uint32_t start; /* 0x210 - 0x213 */ + uint32_t disk_secs; /* 0x214 - 0x217 */ + uint32_t unknown_3; /* 0x218 - 0x21B */ + uint16_t unknown_4; /* 0x21C - 0x21D */ + uint8_t status; /* 0x21E */ /* FIXME: bit 0x80 doesn't seem to indicate error as previously assumed. */ -// #define PDC_BROKEN(pdc) ((pdc)->raid.status & 0x80) +// #define PDC_BROKEN(pdc) ((pdc)->raid.status & 0x80) #define PDC_BROKEN(pdc) ((pdc)->raid.status & 0x00) #define PDC_SET_BROKEN(pdc) ((pdc)->raid.status |= 0x80) - uint8_t type; /* 0x21F */ + uint8_t type; /* 0x21F */ #define PDC_T_RAID0 0x0 #define PDC_T_RAID1 0x1 #define PDC_T_SPAN 0x8 - uint8_t total_disks; /* 0x220 */ - uint8_t raid0_shift; /* 0x221 */ - uint8_t raid0_disks; /* 0x222 */ - uint8_t array_number; /* 0x223 */ - uint32_t total_secs; /* 0x224 - 0x227 */ - uint16_t cylinders; /* 0x228 - 0x229 */ - uint8_t heads; /* 0x22A */ - uint8_t sectors; /* 0x22B */ - uint32_t magic_1; /* 0x22C - 0x2EF */ - uint32_t unknown_5; /* 0x230 - 0x233 */ + uint8_t total_disks; /* 0x220 */ + uint8_t raid0_shift; /* 0x221 */ + uint8_t raid0_disks; /* 0x222 */ + uint8_t array_number; /* 0x223 */ + uint32_t total_secs; /* 0x224 - 0x227 */ + uint16_t cylinders; /* 0x228 - 0x229 */ + uint8_t heads; /* 0x22A */ + uint8_t sectors; /* 0x22B */ + uint32_t magic_1; /* 0x22C - 0x2EF */ + uint32_t unknown_5; /* 0x230 - 0x233 */ struct pdc_disk { uint16_t unknown_0; /* 0x234 - 0x235 */ uint8_t channel; /* 0x236 */ - uint8_t device; /* 0x237 */ + uint8_t device; /* 0x237 */ uint32_t magic_0; /* 0x238 - 0x23B */ uint32_t disk_number; /* 0x23C - 0x23F */ } disk[8]; } raid; - uint32_t filler2[346]; /* 0x294 - */ + uint32_t filler2[346]; /* 0x294 - */ uint32_t checksum; } __attribute__ ((packed)); --- dmraid/lib/format/ataraid/sil.c 2008/02/22 17:04:35 1.2 +++ dmraid/lib/format/ataraid/sil.c 2008/06/20 21:52:17 1.3 @@ -22,19 +22,20 @@ /* Make up RAID device name from some 'magic' numbers */ /* FIXME: better name ? */ -static size_t _name(struct sil *sil, char *str, size_t len, unsigned int subset) +static size_t +_name(struct sil *sil, char *str, size_t len, unsigned int subset) { return snprintf(str, len, subset ? "sil_%02u%02u%02u%02u%02u%02u-%u" : - "sil_%02u%02u%02u%02u%02u%02u", + "sil_%02u%02u%02u%02u%02u%02u", sil->year, sil->month, sil->day, sil->hour, sil->minutes % 60, sil->seconds % 60, sil->type == SIL_T_RAID1 ? sil->mirrored_set_number : - sil->striped_set_number); + sil->striped_set_number); } -static char *name(struct lib_context *lc, struct raid_dev *rd, - unsigned int subset) +static char * +name(struct lib_context *lc, struct raid_dev *rd, unsigned int subset) { size_t len; char *ret; @@ -45,7 +46,8 @@ _name(sil, ret, len, subset); mk_alpha(lc, ret + HANDLER_LEN, len - HANDLER_LEN - (strrchr(ret, '-') ? 3 : 1)); - } else + } + else log_alloc_err(lc, handler); return ret; @@ -55,43 +57,46 @@ * Retrieve status of device. * FIXME: is this sufficient to cover all state ? */ -static enum status status(struct sil *sil) +static enum status +status(struct sil *sil) { struct states states[] = { - { SIL_OK, s_ok }, - { SIL_MIRROR_SYNC, s_ok }, - { SIL_MIRROR_NOSYNC, s_nosync }, - { 0, s_broken }, + {SIL_OK, s_ok}, + {SIL_MIRROR_SYNC, s_ok}, + {SIL_MIRROR_NOSYNC, s_nosync}, + {0, s_broken}, }; return rd_status(states, sil->mirrored_set_state, EQUAL); } /* Neutralize disk type */ -static enum type type(struct sil *sil) +static enum type +type(struct sil *sil) { /* Mapping of SIL 680 types to generic types */ static struct types types[] = { - { SIL_T_SPARE, t_spare}, - { SIL_T_JBOD, t_linear}, - { SIL_T_RAID0, t_raid0}, - { SIL_T_RAID5, t_raid5_ls}, - { SIL_T_RAID1, t_raid1}, - { SIL_T_RAID10, t_raid0}, - { 0, t_undef} + {SIL_T_SPARE, t_spare}, + {SIL_T_JBOD, t_linear}, + {SIL_T_RAID0, t_raid0}, + {SIL_T_RAID5, t_raid5_ls}, + {SIL_T_RAID1, t_raid1}, + {SIL_T_RAID10, t_raid0}, + {0, t_undef} }; return rd_type(types, (unsigned int) sil->type); } /* Calculate checksum on metadata */ -static int checksum(struct sil *sil) +static int +checksum(struct sil *sil) { int sum = 0; - unsigned int count = struct_offset(sil, checksum1) / 2; - uint16_t *p = (uint16_t*) sil; + unsigned short count = struct_offset(sil, checksum1) / 2; + uint16_t *p = (uint16_t *) sil; - while (count--) + while (count--) sum += *p++; return (-sum & 0xFFFF) == sil->checksum1; @@ -104,7 +109,8 @@ #if BYTE_ORDER == LITTLE_ENDIAN # define to_cpu NULL #else -static void to_cpu(void *meta) +static void +to_cpu(void *meta) { struct sil *sil = meta; @@ -128,13 +134,15 @@ #define AREAS 4 #define SIL_META_AREA(i) (SIL_CONFIGOFFSET - (i * 512 << 9)) -static inline int is_sil(struct sil *sil) +static inline int +is_sil(struct sil *sil) { return SIL_MAGIC_OK(sil) && sil->disk_number < 8; } -static int sil_valid(struct lib_context *lc, struct dev_info *di, - void *meta, unsigned int area) +static int +sil_valid(struct lib_context *lc, struct dev_info *di, + void *meta, unsigned int area) { struct sil *sil = meta; @@ -158,7 +166,8 @@ return 1; } -static void free_sils(struct sil **sils, unsigned int i) +static void +free_sils(struct sil **sils, unsigned int i) { for (; i < AREAS; i++) dbg_free(sils[i]); @@ -166,9 +175,9 @@ dbg_free(sils); } -static void *sil_read_metadata(struct lib_context *lc, struct dev_info *di, - size_t *size, uint64_t *offset, - union read_info *info) +static void * +sil_read_metadata(struct lib_context *lc, struct dev_info *di, + size_t * size, uint64_t * offset, union read_info *info) { unsigned int i, valid; char str[9] = { 0, }; @@ -190,8 +199,9 @@ if (sil_valid(lc, di, sil, i + 1)) { sils[valid] = sil; sprintf(&str[strlen(str)], "%s%u", - valid++ ? "," : "", i + 1); - } else + valid++ ? "," : "", i + 1); + } + else dbg_free(sil); } @@ -201,21 +211,23 @@ valid == 1 ? "is" : "are"); goto out; } - - bad: + + bad: free_sils(sils, 0); sils = NULL; - out: - return (void*) sils; + out: + return (void *) sils; } -static int _file_name(char *str, size_t len, char *n, int i) +static int +_file_name(char *str, size_t len, char *n, int i) { return snprintf(str, len, "%s_%d", n, i) + 1; } -static char *file_name(struct lib_context *lc, char *n, int i) +static char * +file_name(struct lib_context *lc, char *n, int i) { size_t len; char *ret; @@ -229,13 +241,13 @@ } /* File all metadata areas. */ -static void sil_file_metadata(struct lib_context *lc, struct dev_info *di, - void *meta) +static void +sil_file_metadata(struct lib_context *lc, struct dev_info *di, void *meta) { unsigned int i; char *n; struct sil **sils = meta; - + for (i = 0; i < AREAS; i++) { if (!(n = file_name(lc, di->path, i))) break; @@ -250,7 +262,8 @@ static int setup_rd(struct lib_context *lc, struct raid_dev *rd, struct dev_info *di, void *meta, union read_info *info); -static struct raid_dev *sil_read(struct lib_context *lc, struct dev_info *di) +static struct raid_dev * +sil_read(struct lib_context *lc, struct dev_info *di) { return read_raid_dev(lc, di, sil_read_metadata, 0, 0, NULL, NULL, sil_file_metadata, setup_rd, handler); @@ -260,7 +273,8 @@ /* * Write a Silicon Image RAID device. */ -static int sil_write(struct lib_context *lc, struct raid_dev *rd, int erase) +static int +sil_write(struct lib_context *lc, struct raid_dev *rd, int erase) { int ret; #if BYTE_ORDER != LITTLE_ENDIAN @@ -276,17 +290,19 @@ } /* Decide about ordering sequence of RAID device. */ -static int dev_sort(struct list_head *pos, struct list_head *new) +static int +dev_sort(struct list_head *pos, struct list_head *new) { return (META(RD(new), sil))->disk_number < - (META(RD(pos), sil))->disk_number; + (META(RD(pos), sil))->disk_number; } /* Decide about ordering sequence of RAID subset. */ -static int set_sort(struct list_head *pos, struct list_head *new) +static int +set_sort(struct list_head *pos, struct list_head *new) { return (META(RD_RS(RS(new)), sil))->mirrored_set_number < - (META(RD_RS(RS(pos)), sil))->mirrored_set_number; + (META(RD_RS(RS(pos)), sil))->mirrored_set_number; } /* @@ -294,15 +310,17 @@ * * Check device hierarchy and create super set appropriately. */ -static void super_created(struct raid_set *ss, void *private) +static void +super_created(struct raid_set *ss, void *private) { - ss->type = t_raid1; + ss->type = t_raid1; ss->stride = META(private, sil)->raid0_stride; } /* FIXME: handle spares. */ -static int group_rd(struct lib_context *lc, struct raid_set *rs, - struct raid_set **ss, struct raid_dev *rd) +static int +group_rd(struct lib_context *lc, struct raid_set *rs, + struct raid_set **ss, struct raid_dev *rd) { struct sil *sil = META(rd, sil); @@ -336,7 +354,8 @@ } /* Add a SIL RAID device to a set */ -static struct raid_set *sil_group(struct lib_context *lc, struct raid_dev *rd) +static struct raid_set * +sil_group(struct lib_context *lc, struct raid_dev *rd) { struct raid_set *rs, *ss = NULL; @@ -355,7 +374,8 @@ * * FIXME: more sanity checks. */ -static unsigned int devices(struct raid_dev *rd, void *context) +static unsigned int +devices(struct raid_dev *rd, void *context) { int ret; struct sil *sil = META(rd, sil); @@ -377,7 +397,8 @@ return ret; } -static int sil_check(struct lib_context *lc, struct raid_set *rs) +static int +sil_check(struct lib_context *lc, struct raid_set *rs) { return check_raid_set(lc, rs, devices, NULL, NO_CHECK_RD, NULL, handler); @@ -386,7 +407,8 @@ /* * IO error event handler. */ -static int event_io(struct lib_context *lc, struct event_io *e_io) +static int +event_io(struct lib_context *lc, struct event_io *e_io) { struct raid_dev *rd = e_io->rd; struct sil *sil = META(rd, sil); @@ -402,14 +424,15 @@ static struct event_handlers sil_event_handlers = { .io = event_io, - .rd = NULL, /* FIXME: no device add/remove event handler yet. */ + .rd = NULL, /* FIXME: no device add/remove event handler yet. */ }; #ifdef DMRAID_NATIVE_LOG /* * Log native information about a Silicon Image RAID device. */ -static void sil_log(struct lib_context *lc, struct raid_dev *rd) +static void +sil_log(struct lib_context *lc, struct raid_dev *rd) { char *tt; struct sil *sil = META(rd, sil); @@ -464,46 +487,49 @@ #endif static struct dmraid_format sil_format = { - .name = HANDLER, - .descr = "Silicon Image(tm) Medley(tm)", - .caps = "0,1,10", + .name = HANDLER, + .descr = "Silicon Image(tm) Medley(tm)", + .caps = "0,1,10", .format = FMT_RAID, - .read = sil_read, - .write = sil_write, - .group = sil_group, - .check = sil_check, - .events = &sil_event_handlers, + .read = sil_read, + .write = sil_write, + .group = sil_group, + .check = sil_check, + .events = &sil_event_handlers, #ifdef DMRAID_NATIVE_LOG - .log = sil_log, + .log = sil_log, #endif }; /* Register this format handler with the format core. */ -int register_sil(struct lib_context *lc) +int +register_sil(struct lib_context *lc) { return register_format_handler(lc, &sil_format); } /* Set the RAID device contents up derived from the SIL ones. */ -static int stripes(struct sil *sil) +static int +stripes(struct sil *sil) { return sil->drives_per_striped_set > -1 && - sil->disk_number < sil->drives_per_striped_set; + sil->disk_number < sil->drives_per_striped_set; } -static uint64_t sectors(struct raid_dev *rd) +static uint64_t +sectors(struct raid_dev *rd) { uint64_t array_sectors, ret = 0; struct sil *sil = META(rd, sil); array_sectors = (((uint64_t) sil->array_sectors_high) << 32) + - sil->array_sectors_low; + sil->array_sectors_low; switch (sil->type) { case SIL_T_SPARE: /* Cook them up... */ ret = rd->di->sectors - (AREAS - 1) * 512 - - ((rd->di->sectors & 1) ? 1 : 2); + ((rd->di->sectors & 1) ? 1 : 2); break; case SIL_T_RAID0: @@ -519,7 +545,7 @@ default: /* Cook them up... */ ret = rd->di->sectors - (AREAS - 1) * 512 - - ((rd->di->sectors & 1) ? 1 : 2); + ((rd->di->sectors & 1) ? 1 : 2); break; } @@ -527,19 +553,19 @@ } /* Quorate SIL metadata copies. */ -static struct sil *quorate(struct lib_context *lc, struct dev_info *di, - struct sil *sils[]) +static struct sil * +quorate(struct lib_context *lc, struct dev_info *di, struct sil *sils[]) { unsigned int areas = 0, i, ident = 0, j; struct sil *sil = NULL, *tmp; - + /* Count valid metadata areas. */ while (areas < AREAS && sils[areas]) areas++; if (areas != AREAS) log_err(lc, "%s: only %u/%u metadata areas found on " - "%s, %sing...", + "%s, %sing...", handler, areas, AREAS, di->path, areas > 1 ? "elect" : "pick"); @@ -551,7 +577,7 @@ } if (ident > areas / 2); - break; + break; } if (ident) { @@ -563,8 +589,9 @@ return sil; } -static int setup_rd(struct lib_context *lc, struct raid_dev *rd, - struct dev_info *di, void *meta, union read_info *info) +static int +setup_rd(struct lib_context *lc, struct raid_dev *rd, + struct dev_info *di, void *meta, union read_info *info) { unsigned int i; struct meta_areas *ma; @@ -573,13 +600,13 @@ if (!(rd->meta_areas = alloc_meta_areas(lc, rd, handler, AREAS))) goto bad; - sil = quorate(lc, di, sils); /* Quorate one copy+save a pointer.*/ - free_sils(sils, 1); /* Free the other copies. */ + sil = quorate(lc, di, sils); /* Quorate one copy+save a pointer. */ + free_sils(sils, 1); /* Free the other copies. */ for (i = 0, ma = rd->meta_areas; i < rd->areas; i++, ma++) { ma->offset = SIL_META_AREA(i) >> 9; ma->size = sizeof(*sil); - ma->area = (void*) sil; + ma->area = (void *) sil; } rd->di = di; @@ -590,11 +617,11 @@ return log_zero_sectors(lc, di->path, handler); rd->status = status(sil); - rd->type = type(sil); + rd->type = type(sil); - return (rd->name = name(lc, rd, sil->type == SIL_T_RAID10)) ? 1 : 0; + return (rd->name = name(lc, rd, sil->type == SIL_T_RAID10)) ? 1 : 0; - bad: + bad: free_sils(sils, 0); return 0; --- dmraid/lib/format/ataraid/sil.h 2008/02/22 17:04:35 1.2 +++ dmraid/lib/format/ataraid/sil.h 2008/06/20 21:52:17 1.3 @@ -14,64 +14,64 @@ #include <stdint.h> #define SIL_CONFIGOFFSET ((di->sectors - 1) << 9) -#define SIL_DATAOFFSET 0 /* Data offset in sectors */ +#define SIL_DATAOFFSET 0 /* Data offset in sectors */ struct sil { - uint8_t unknown0[0x2E]; /* 0x4 - 0x2D */ - uint8_t ascii_version[0x36 - 0x2E];/* 0x2E - 0x35 */ - int8_t diskname[0x56 - 0x36]; /* 0x36 - 0x55 */ - int8_t unknown1[0x60 - 0x56]; /* 0x56 - 0x59 */ - uint32_t magic; /* 0x60 - 0x63 */ + uint8_t unknown0[0x2E]; /* 0x4 - 0x2D */ + uint8_t ascii_version[0x36 - 0x2E]; /* 0x2E - 0x35 */ + int8_t diskname[0x56 - 0x36]; /* 0x36 - 0x55 */ + int8_t unknown1[0x60 - 0x56]; /* 0x56 - 0x59 */ + uint32_t magic; /* 0x60 - 0x63 */ #define SIL_MAGIC 0x3000000 #define SIL_MAGIC_OK(sil) ((sil->magic & 0x3ffffff) == SIL_MAGIC) - int8_t unknown1a[0x6C - 0x64]; /* 0x64 - 0x6B */ - uint32_t array_sectors_low; /* 0x6C - 0x6F */ - uint32_t array_sectors_high; /* 0x70 - 0x73 */ - int8_t unknown2[0x78 - 0x74]; /* 0x74 - 0x77 */ - uint32_t thisdisk_sectors; /* 0x78 - 0x7B */ - int8_t unknown3[0x100 - 0x7C]; /* 0x7C - 0xFF */ - int8_t unknown4[0x104 - 0x100];/* 0x100 - 0x103 */ - uint16_t product_id; /* 0x104 + 0x105 */ - uint16_t vendor_id; /* 0x106 + 0x107 */ - uint16_t minor_ver; /* 0x108 + 0x109 */ - uint16_t major_ver; /* 0x10A + 0x10B */ - uint8_t seconds; /* 0x10C */ - uint8_t minutes; /* 0x10D */ - uint8_t hour; /* 0x10E */ - uint8_t day; /* 0x10F */ - uint8_t month; /* 0x110 */ - uint8_t year; /* 0x111 */ - uint16_t raid0_stride; /* 0x112 + 0x113 */ - int8_t unknown6[0x116 - 0x114];/* 0x114 + 0x115 */ - uint8_t disk_number; /* 0x116 */ - uint8_t type; /* 0x117 */ + int8_t unknown1a[0x6C - 0x64]; /* 0x64 - 0x6B */ + uint32_t array_sectors_low; /* 0x6C - 0x6F */ + uint32_t array_sectors_high; /* 0x70 - 0x73 */ + int8_t unknown2[0x78 - 0x74]; /* 0x74 - 0x77 */ + uint32_t thisdisk_sectors; /* 0x78 - 0x7B */ + int8_t unknown3[0x100 - 0x7C]; /* 0x7C - 0xFF */ + int8_t unknown4[0x104 - 0x100]; /* 0x100 - 0x103 */ + uint16_t product_id; /* 0x104 + 0x105 */ + uint16_t vendor_id; /* 0x106 + 0x107 */ + uint16_t minor_ver; /* 0x108 + 0x109 */ + uint16_t major_ver; /* 0x10A + 0x10B */ + uint8_t seconds; /* 0x10C */ + uint8_t minutes; /* 0x10D */ + uint8_t hour; /* 0x10E */ + uint8_t day; /* 0x10F */ + uint8_t month; /* 0x110 */ + uint8_t year; /* 0x111 */ + uint16_t raid0_stride; /* 0x112 + 0x113 */ + int8_t unknown6[0x116 - 0x114]; /* 0x114 + 0x115 */ + uint8_t disk_number; /* 0x116 */ + uint8_t type; /* 0x117 */ #define SIL_T_RAID0 0 #define SIL_T_RAID1 1 #define SIL_T_RAID10 2 #define SIL_T_RAID5 16 #define SIL_T_SPARE 3 #define SIL_T_JBOD 255 - int8_t drives_per_striped_set; /* 0x118 */ - int8_t striped_set_number; /* 0x119 */ - int8_t drives_per_mirrored_set;/* 0x11A */ - int8_t mirrored_set_number; /* 0x11B */ - uint32_t rebuild_ptr_low; /* 0x11C - 0x12F */ - uint32_t rebuild_ptr_high; /* 0x120 - 0x123 */ - uint32_t incarnation_no; /* 0x124 - 0x127 */ - uint8_t member_status; /* 0x128 */ - uint8_t mirrored_set_state; /* 0x129 */ + int8_t drives_per_striped_set; /* 0x118 */ + int8_t striped_set_number; /* 0x119 */ + int8_t drives_per_mirrored_set; /* 0x11A */ + int8_t mirrored_set_number; /* 0x11B */ + uint32_t rebuild_ptr_low; /* 0x11C - 0x12F */ + uint32_t rebuild_ptr_high; /* 0x120 - 0x123 */ + uint32_t incarnation_no; /* 0x124 - 0x127 */ + uint8_t member_status; /* 0x128 */ + uint8_t mirrored_set_state; /* 0x129 */ #define SIL_OK 0 #define SIL_MIRROR_NOSYNC 1 #define SIL_MIRROR_SYNC 2 - uint8_t reported_device_location;/* 0x12A */ - uint8_t idechannel; /* 0x12B */ - uint8_t auto_rebuild; /* 0x12C */ + uint8_t reported_device_location; /* 0x12A */ + uint8_t idechannel; /* 0x12B */ + uint8_t auto_rebuild; /* 0x12C */ #define SIL_MIRROR_NOAUTOREBUILD 0 - uint8_t unknown8; /* 0x12D */ - uint8_t text_type[0x13E - 0x12E]; /* 0x12E - 0x13D */ - uint16_t checksum1; /* 0x13E + 0x13F */ - int8_t assumed_zeros[0x1FE - 0x140];/* 0x140 - 0x1FD */ - uint16_t checksum2; /* 0x1FE + 0x1FF */ + uint8_t unknown8; /* 0x12D */ + uint8_t text_type[0x13E - 0x12E]; /* 0x12E - 0x13D */ + uint16_t checksum1; /* 0x13E + 0x13F */ + int8_t assumed_zeros[0x1FE - 0x140]; /* 0x140 - 0x1FD */ + uint16_t checksum2; /* 0x1FE + 0x1FF */ } __attribute__ ((packed)); #endif --- dmraid/lib/format/ataraid/via.c 2008/02/22 17:04:35 1.2 +++ dmraid/lib/format/ataraid/via.c 2008/06/20 21:52:17 1.3 @@ -21,16 +21,18 @@ static const char *handler = HANDLER; -static int _subset(struct via *via) +static int +_subset(struct via *via) { return VIA_T_RAID01_MIRROR(via); } /* Make up VIA RAID device name suffix from the serial_checksum array. */ -static uint32_t sum_serial(struct via *via) +static uint32_t +sum_serial(struct via *via) { unsigned int i = VIA_MAX_DISKS; - uint32_t ret = via->array.disk_array_ex; /* FIXME: correct ? */ + uint32_t ret = via->array.disk_array_ex; /* FIXME: correct ? */ while (i--) ret += via->serial_checksum[i]; @@ -38,7 +40,8 @@ return ret; } -static char *_name_suffix(struct via *via) +static char * +_name_suffix(struct via *via) { size_t len; uint32_t sum = sum_serial(via); @@ -51,15 +54,16 @@ } /* Make up RAID device name. */ -static size_t _name(struct lib_context *lc, struct via *via, char *str, - size_t len, char *suffix, unsigned int subset) +static size_t +_name(struct lib_context *lc, struct via *via, char *str, + size_t len, char *suffix, unsigned int subset) { return snprintf(str, len, subset ? "via_%s-%u" : "via_%s", suffix, _subset(via)); } -static char *name(struct lib_context *lc, struct raid_dev *rd, - unsigned int subset) +static char * +name(struct lib_context *lc, struct raid_dev *rd, unsigned int subset) { size_t len; char *ret, *suffix; @@ -74,7 +78,8 @@ _name(lc, via, ret, len, suffix, subset); mk_alpha(lc, ret + HANDLER_LEN, len - HANDLER_LEN - (subset ? 3 : 1)); - } else + } + else log_alloc_err(lc, handler); dbg_free(suffix); @@ -86,7 +91,8 @@ * Retrieve status of device. * FIXME: is this sufficient to cover all state ? */ -static enum status status(struct via *via) +static enum status +status(struct via *via) { if (via->array.disk.tolerance) return s_broken; @@ -95,15 +101,16 @@ } /* Neutralize disk type using generic metadata type mapping function */ -static enum type type(struct via *via) +static enum type +type(struct via *via) { /* Mapping of via types to generic types */ static struct types types[] = { - { VIA_T_SPAN, t_linear }, - { VIA_T_RAID0, t_raid0 }, - { VIA_T_RAID1, t_raid1 }, - { VIA_T_RAID01, t_raid0 }, - { 0, t_undef} + {VIA_T_SPAN, t_linear}, + {VIA_T_RAID0, t_raid0}, + {VIA_T_RAID1, t_raid1}, + {VIA_T_RAID01, t_raid0}, + {0, t_undef} }; return rd_type(types, (unsigned int) VIA_RAID_TYPE(via)); @@ -116,7 +123,8 @@ #if BYTE_ORDER == LITTLE_ENDIAN # define to_cpu NULL #else -static void to_cpu(void *meta) +static void +to_cpu(void *meta) { struct via *via = meta; unsigned int i = VIA_MAX_DISKS; @@ -134,17 +142,19 @@ #endif /* 8 bit checksum on first 50 bytes of metadata. */ -static uint8_t checksum(struct via *via) +static uint8_t +checksum(struct via *via) { uint8_t i = 50, sum = 0; - + while (i--) - sum += ((uint8_t*) via)[i]; + sum += ((uint8_t *) via)[i]; return sum == via->checksum; } -static int is_via(struct lib_context *lc, struct dev_info *di, void *meta) +static int +is_via(struct lib_context *lc, struct dev_info *di, void *meta) { struct via *via = meta; @@ -157,13 +167,14 @@ if (via->version_number > 1) log_info(lc, "%s: version %u; format handler specified for " "version 0+1 only", handler, via->version_number); - + return 1; } static int setup_rd(struct lib_context *lc, struct raid_dev *rd, struct dev_info *di, void *meta, union read_info *info); -static struct raid_dev *via_read(struct lib_context *lc, struct dev_info *di) +static struct raid_dev * +via_read(struct lib_context *lc, struct dev_info *di) { return read_raid_dev(lc, di, NULL, sizeof(struct via), VIA_CONFIGOFFSET, @@ -171,7 +182,8 @@ } /* Decide about ordering sequence of RAID device. */ -static int dev_sort(struct list_head *pos, struct list_head *new) +static int +dev_sort(struct list_head *pos, struct list_head *new) { struct via *p = META(RD(pos), via); struct via *n = META(RD(new), via); @@ -180,27 +192,30 @@ case VIA_T_RAID1: return VIA_T_RAID1_SOURCE(n); - default: /* span, RAID0 + RAID01 */ + default: /* span, RAID0 + RAID01 */ return VIA_T_RAID_INDEX(n) < VIA_T_RAID_INDEX(p); } } /* Decide about ordering sequence of RAID subset. */ -static int set_sort(struct list_head *pos, struct list_head *new) +static int +set_sort(struct list_head *pos, struct list_head *new) { return _subset(META(RD_RS(RS(new)), via)) < - _subset(META(RD_RS(RS(pos)), via)); + _subset(META(RD_RS(RS(pos)), via)); } -static void super_created(struct raid_set *ss, void *private) +static void +super_created(struct raid_set *ss, void *private) { ss->type = t_raid1; ss->stride = VIA_STRIDE(META(private, via)); } /* FIXME: handle spares in mirrors and check that types are correct. */ -static int group_rd(struct lib_context *lc, struct raid_set *rs, - struct raid_set **ss, struct raid_dev *rd) +static int +group_rd(struct lib_context *lc, struct raid_set *rs, + struct raid_set **ss, struct raid_dev *rd) { struct via *via = META(rd, via); @@ -230,8 +245,8 @@ } /* Add a VIA RAID device to a set */ -static struct raid_set *via_group(struct lib_context *lc, - struct raid_dev *rd) +static struct raid_set * +via_group(struct lib_context *lc, struct raid_dev *rd) { struct raid_set *rs, *ss = NULL; @@ -245,7 +260,8 @@ return NULL; } -static int via_write(struct lib_context *lc, struct raid_dev *rd, int erase) +static int +via_write(struct lib_context *lc, struct raid_dev *rd, int erase) { int ret; #if BYTE_ORDER != LITTLE_ENDIAN @@ -267,15 +283,17 @@ * FIXME: more sanity checks. */ /* Figure total number of disks depending on RAID type. */ -static unsigned int devices(struct raid_dev *rd, void *context) +static unsigned int +devices(struct raid_dev *rd, void *context) { struct via *via = META(rd, via); return VIA_RAID_TYPE(via) == VIA_T_RAID1 ? 2 : VIA_RAID_DISKS(via); } -static int check_rd(struct lib_context *lc, struct raid_set *rs, - struct raid_dev *rd, void *context) +static int +check_rd(struct lib_context *lc, struct raid_set *rs, + struct raid_dev *rd, void *context) { struct via *via = META(rd, via); @@ -291,7 +309,8 @@ return 1; } -static int via_check(struct lib_context *lc, struct raid_set *rs) +static int +via_check(struct lib_context *lc, struct raid_set *rs) { return check_raid_set(lc, rs, devices, NULL, check_rd, NULL, handler); } @@ -299,7 +318,8 @@ /* * IO error event handler. */ -static int event_io(struct lib_context *lc, struct event_io *e_io) +static int +event_io(struct lib_context *lc, struct event_io *e_io) { struct raid_dev *rd = e_io->rd; struct via *via = META(rd, via); @@ -315,7 +335,7 @@ static struct event_handlers via_event_handlers = { .io = event_io, - .rd = NULL, /* FIXME: no device add/remove event handler yet. */ + .rd = NULL, /* FIXME: no device add/remove event handler yet. */ }; @@ -323,7 +343,8 @@ /* * Log native information about the RAID device. */ -static void via_log(struct lib_context *lc, struct raid_dev *rd) +static void +via_log(struct lib_context *lc, struct raid_dev *rd) { unsigned int i; struct via *via = META(rd, via); @@ -337,8 +358,7 @@ via->array.disk.enable_enhanced); P("array.disk.in_disk_array: %u", via, via->array.disk, via->array.disk.in_disk_array); - P("array.disk.raid_type: %u", via, via->array.disk, - VIA_RAID_TYPE(via)); + P("array.disk.raid_type: %u", via, via->array.disk, VIA_RAID_TYPE(via)); P("array.disk.array_index: %u", via, via->array.disk, VIA_ARRAY_INDEX(via)); @@ -366,28 +386,30 @@ #endif static struct dmraid_format via_format = { - .name = HANDLER, - .descr = "VIA Software RAID", - .caps = "S,0,1,10", + .name = HANDLER, + .descr = "VIA Software RAID", + .caps = "S,0,1,10", .format = FMT_RAID, - .read = via_read, - .write = via_write, - .group = via_group, - .check = via_check, - .events = &via_event_handlers, + .read = via_read, + .write = via_write, + .group = via_group, + .check = via_check, + .events = &via_event_handlers, #ifdef DMRAID_NATIVE_LOG - .log = via_log, + .log = via_log, #endif }; /* Register this format handler with the format core. */ -int register_via(struct lib_context *lc) +int +register_via(struct lib_context *lc) { return register_format_handler(lc, &via_format); } -static int setup_rd(struct lib_context *lc, struct raid_dev *rd, - struct dev_info *di, void *meta, union read_info *info) +static int +setup_rd(struct lib_context *lc, struct raid_dev *rd, + struct dev_info *di, void *meta, union read_info *info) { struct via *via = meta; @@ -396,17 +418,17 @@ rd->meta_areas->offset = VIA_CONFIGOFFSET >> 9; rd->meta_areas->size = sizeof(*via); - rd->meta_areas->area = (void*) via; + rd->meta_areas->area = (void *) via; - rd->di = di; + rd->di = di; rd->fmt = &via_format; rd->status = status(via); - rd->type = type(via); + rd->type = type(via); rd->offset = VIA_DATAOFFSET; if (!(rd->sectors = rd->meta_areas->offset)) return log_zero_sectors(lc, di->path, handler); - return (rd->name = name(lc, rd, 1)) ? 1 : 0; + return (rd->name = name(lc, rd, 1)) ? 1 : 0; } --- dmraid/lib/format/ataraid/via.h 2008/02/22 16:57:36 1.1 +++ dmraid/lib/format/ataraid/via.h 2008/06/20 21:52:17 1.2 @@ -19,18 +19,18 @@ #define VIA_MAX_DISKS 8 struct disk { - uint16_t bootable:1; /* BIOS boot */ - uint16_t enable_enhanced:1; /* Unused */ - uint16_t in_disk_array:1; /* Used/Spare */ - uint16_t raid_type:4; + uint16_t bootable:1; /* BIOS boot */ + uint16_t enable_enhanced:1; /* Unused */ + uint16_t in_disk_array:1; /* Used/Spare */ + uint16_t raid_type:4; #define VIA_T_RAID0 0 #define VIA_T_RAID1 1 #define VIA_T_SPAN 8 #define VIA_T_RAID01 9 #define VIA_RAID_TYPE(x) ((x)->array.disk.raid_type) - uint16_t array_index:3; + uint16_t array_index:3; #define VIA_ARRAY_INDEX(x) ((x)->array.disk.array_index) - uint16_t raid_type_info:5; + uint16_t raid_type_info:5; /* SPAN + RAID 0 */ #define VIA_T_RAID_INDEX(x) ((x)->array.disk.raid_type_info & 0x7) @@ -41,33 +41,33 @@ #define VIA_T_RAID1_DIRTY(x) (((x)->array.disk.raid_type_info & 0x4) >> 2) /* RAID 0+1 */ -// #define VIA_T_RAID01_INDEX(x) VIA_T_RAID_INDEX(x) +// #define VIA_T_RAID01_INDEX(x) VIA_T_RAID_INDEX(x) #define VIA_T_RAID01_MIRROR(x) (((x)->array.disk.raid_type_info & 0x8) >> 3) #define VIA_T_RAID01_DIRTY(x) (((x)->array.disk.raid_type_info & 0x10) >> 4) /* SPAN */ #define VIA_T_SPAN_INDEX(x) ((x)->array.disk.raid_type_info & 0x7) - uint16_t tolerance:1; + uint16_t tolerance:1; } __attribute__ ((packed)); struct array { - struct disk disk; - uint8_t disk_array_ex; + struct disk disk; + uint8_t disk_array_ex; #define VIA_RAID_DISKS(x) ((x)->array.disk_array_ex & 0x7) #define VIA_BROKEN(x) (((x)->array.disk_array_ex & 0x8) >> 4) #define VIA_STRIDE(x) (8 << (((x)->array.disk_array_ex & 0xF0) >> 4)) - uint32_t capacity_low; - uint32_t capacity_high; - uint32_t serial_checksum; + uint32_t capacity_low; + uint32_t capacity_high; + uint32_t serial_checksum; } __attribute__ ((packed)); struct via { - uint16_t signature; + uint16_t signature; #define VIA_SIGNATURE 0xAA55 - uint8_t version_number; - struct array array; - uint32_t serial_checksum[8]; - uint8_t checksum; + uint8_t version_number; + struct array array; + uint32_t serial_checksum[8]; + uint8_t checksum; } __attribute__ ((packed)); #endif --- dmraid/lib/format/ddf/ddf1.c 2008/04/02 13:35:31 1.3 +++ dmraid/lib/format/ddf/ddf1.c 2008/06/20 21:52:17 1.4 @@ -4,8 +4,8 @@ * Copyright (C) 2005-2006 IBM, All rights reserved. * Written by Darrick Wong <djwong@xxxxxxxxxx> * - * Copyright (C) 2006 Heinz Mauelshagen, Red Hat GmbH - * All rights reserved. + * Copyright (C) 2006-2008 Heinz Mauelshagen, Red Hat GmbH + * All rights reserved. * * See file LICENSE at the top of this source tree for license information. */ @@ -37,17 +37,19 @@ #define DDF1_DISKS (char*) ".ddf1_disks" /* PCI IDs for Adaptec */ -// #define PCI_VENDOR_ID_ADAPTEC 0x9004 +// #define PCI_VENDOR_ID_ADAPTEC 0x9004 #define PCI_VENDOR_ID_ADAPTEC2 0x9005 /* Map DDF1 disk status to dmraid status */ -static enum status disk_status(struct ddf1_phys_drive *disk) { +static enum status +disk_status(struct ddf1_phys_drive *disk) +{ struct states states[] = { - { 0x72, s_broken }, - { 0x04, s_nosync }, - { 0x08, s_setup }, - { 0x01, s_ok }, - { 0, s_undef }, + {0x72, s_broken}, + {0x04, s_nosync}, + {0x08, s_setup}, + {0x01, s_ok}, + {0, s_undef}, }; return disk ? rd_status(states, disk->state, AND) : s_undef; @@ -60,7 +62,8 @@ * both GUIDs don't have 0xFFFFFFFF in bytes 20-23. Gross. */ /* Find this drive's physical data */ -static struct ddf1_phys_drive *get_phys_drive(struct ddf1 *ddf1) +static struct ddf1_phys_drive * +get_phys_drive(struct ddf1 *ddf1) { unsigned int i = ddf1->pd_header->max_drives; @@ -73,8 +76,8 @@ } /* Find the virtual drive that goes with this config record */ -static struct ddf1_virt_drive *get_virt_drive(struct ddf1 *ddf1, - struct ddf1_config_record *cr) +static struct ddf1_virt_drive * +get_virt_drive(struct ddf1 *ddf1, struct ddf1_config_record *cr) { int i = ddf1->vd_header->num_drives; @@ -89,8 +92,9 @@ /* * Find the index of the VD config record given a physical drive and offset. */ -static int get_config_byoffset(struct ddf1 *ddf1, struct ddf1_phys_drive *pd, - uint64_t offset) +static int +get_config_byoffset(struct ddf1 *ddf1, struct ddf1_phys_drive *pd, + uint64_t offset) { int cfgs = NUM_CONFIG_ENTRIES(ddf1), i; uint32_t *cfg_drive_ids, j; @@ -114,8 +118,8 @@ } /* Find the index of the nth VD config record for this physical drive. */ -static int get_config_index(struct ddf1 *ddf1, struct ddf1_phys_drive *pd, - unsigned int *n) +static int +get_config_index(struct ddf1 *ddf1, struct ddf1_phys_drive *pd, unsigned int *n) { int cfgs = NUM_CONFIG_ENTRIES(ddf1), i, j, nn = *n; uint32_t *ids; @@ -127,7 +131,7 @@ ids = CR_IDS(ddf1, cr); for (j = 0; j < cr->primary_element_count; j++) { if (ids[j] == pd->reference && !nn--) - return i; + return i; } } } @@ -139,18 +143,17 @@ /* * Find the nth VD config record for this physical drive. */ -static inline struct ddf1_config_record *get_config(struct ddf1 *ddf1, - struct ddf1_phys_drive *pd, - unsigned int n) +static inline struct ddf1_config_record * +get_config(struct ddf1 *ddf1, struct ddf1_phys_drive *pd, unsigned int n) { int i = get_config_index(ddf1, pd, &n); return i < 0 ? NULL : CR(ddf1, i); } - + /* Find a config record for this drive, given the offset of the array. */ -static inline struct ddf1_config_record *get_this_config(struct ddf1 *ddf1, - uint64_t offset) +static inline struct ddf1_config_record * +get_this_config(struct ddf1 *ddf1, uint64_t offset) { struct ddf1_phys_drive *pd = get_phys_drive(ddf1); int i = get_config_byoffset(ddf1, pd, offset); @@ -159,8 +162,9 @@ } /* Find the config record disk/offset entry for this config/drive. */ -static int get_offset_entry(struct ddf1 *ddf1, struct ddf1_config_record *cr, - struct ddf1_phys_drive *pd) +static int +get_offset_entry(struct ddf1 *ddf1, struct ddf1_config_record *cr, + struct ddf1_phys_drive *pd) { int i; uint32_t *ids; @@ -177,8 +181,9 @@ } /* Find the offset for this config/drive. */ -static uint64_t get_offset(struct ddf1 *ddf1, struct ddf1_config_record *cr, - struct ddf1_phys_drive *pd) +static uint64_t +get_offset(struct ddf1 *ddf1, struct ddf1_config_record *cr, + struct ddf1_phys_drive *pd) { int i = get_offset_entry(ddf1, cr, pd); @@ -186,33 +191,34 @@ } /* Calculate the stripe size, in sectors */ -static inline unsigned int stride(struct ddf1_config_record *cr) +static inline unsigned int +stride(struct ddf1_config_record *cr) { return to_bytes(1) >> 9 << cr->stripe_size; } /* Map the DDF1 raid type codes into dmraid type codes. */ -static enum type type(struct lib_context *lc, struct ddf1 *ddf1, - struct ddf1_config_record *cr) +static enum type +type(struct lib_context *lc, struct ddf1 *ddf1, struct ddf1_config_record *cr) { unsigned int l; struct types *t; /* Mapping of template types to generic types */ static struct types types[] = { - { DDF1_RAID0, t_raid0 }, - { DDF1_RAID1, t_raid1 }, - { DDF1_RAID4, t_raid4 }, - { DDF1_CONCAT, t_linear }, - { DDF1_JBOD, t_linear }, - { 0, t_undef} + {DDF1_RAID0, t_raid0}, + {DDF1_RAID1, t_raid1}, + {DDF1_RAID4, t_raid4}, + {DDF1_CONCAT, t_linear}, + {DDF1_JBOD, t_linear}, + {0, t_undef} }; /* Seperate array for RAID5 qualifiers */ static struct types qualifier_types[] = { /* FIXME: Is RLQ=0 really right symmetric? */ - { DDF1_RAID5_RS, t_raid5_rs }, - { DDF1_RAID5_LA, t_raid5_la }, - { DDF1_RAID5_LS, t_raid5_ls }, - { 0, t_undef} + {DDF1_RAID5_RS, t_raid5_rs}, + {DDF1_RAID5_LA, t_raid5_la}, + {DDF1_RAID5_LS, t_raid5_ls}, + {0, t_undef} }; if (!cr) @@ -236,8 +242,8 @@ } /* Read the whole metadata chunk at once */ -static uint8_t *read_metadata_chunk(struct lib_context *lc, struct dev_info *di, - uint64_t start) +static uint8_t * +read_metadata_chunk(struct lib_context *lc, struct dev_info *di, uint64_t start) { uint8_t *ret; size_t size = to_bytes(di->sectors - start); @@ -254,26 +260,29 @@ return ret; } -static inline void cond_free(void *p) +static inline void +cond_free(void *p) { if (p) dbg_free(p); } /* Reused error message */ -static inline void *err_drive(struct lib_context *lc, struct dev_info *di, - const char *what) +static inline void * +err_drive(struct lib_context *lc, struct dev_info *di, const char *what) { LOG_ERR(lc, NULL, "%s: cannot find %s drive record on %s", handler, what, di->path); } -static void *err_phys_drive(struct lib_context *lc, struct dev_info *di) +static void * +err_phys_drive(struct lib_context *lc, struct dev_info *di) { return err_drive(lc, di, "physical"); } -static void *err_virt_drive(struct lib_context *lc, struct dev_info *di) +static void * +err_virt_drive(struct lib_context *lc, struct dev_info *di) { return err_drive(lc, di, "virtual"); } @@ -282,8 +291,8 @@ * Read a DDF1 RAID device. Fields are little endian, so * need to convert them if we're on a BE machine (ppc, etc). */ -static int read_extended(struct lib_context *lc, struct dev_info *di, - struct ddf1 *ddf1) +static int +read_extended(struct lib_context *lc, struct dev_info *di, struct ddf1 *ddf1) { int i; uint64_t where; @@ -319,7 +328,7 @@ cond_free(ddf1->primary); ddf1->primary = NULL; }; - + if (sec->signature == DDF1_HEADER) { /* If we encounter an error, we use the secondary table */ if (!ddf1->primary) { @@ -331,8 +340,7 @@ } else { if (sec->signature) log_warn(lc, "%s: bad secondary header signature %x " - "on %s", - handler, sec->signature, di->path); + "on %s", handler, sec->signature, di->path); dbg_free(sec); ddf1->secondary = NULL; @@ -357,7 +365,7 @@ if (ddf1->adapter->signature != DDF1_ADAPTER_DATA) { if (ddf1->adapter->signature) log_warn(lc, "%s: incorrect adapter data signature %x " - "on %s", + "on %s", handler, ddf1->adapter->signature, di->path); dbg_free(ddf1->adapter); ddf1->adapter = NULL; @@ -402,8 +410,8 @@ } /* Now read the physical drive data */ - ddf1->pds = (struct ddf1_phys_drive *)(((uint8_t *)ddf1->pd_header) + - sizeof (*pd)); + ddf1->pds = (struct ddf1_phys_drive *) (((uint8_t *) ddf1->pd_header) + + sizeof(*pd)); for (i = 0; i < pd->num_drives; i++) { ddf1_cvt_phys_drive(ddf1, &ddf1->pds[i]); /* @@ -428,7 +436,7 @@ } /* Now read the virtual drive data */ - ddf1->vds = (struct ddf1_virt_drive*)(((uint8_t*) vd) + sizeof (*pd)); + ddf1->vds = (struct ddf1_virt_drive *) (((uint8_t *) vd) + sizeof(*pd)); for (i = 0; i < vd->num_drives; i++) ddf1_cvt_virt_drive(ddf1, &ddf1->vds[i]); @@ -454,13 +462,12 @@ ddf1->in_cpu_format = 1; /* FIXME: We should verify the checksums for all modes */ - if (ddf1->adaptec_mode && - !(ddf1_check_all_crcs(lc, di, ddf1))) + if (ddf1->adaptec_mode && !(ddf1_check_all_crcs(lc, di, ddf1))) goto bad; return 1; -bad: + bad: ddf1->vds = NULL; ddf1->pds = NULL; cond_free(ddf1->cfg); @@ -473,18 +480,19 @@ } /* Count the number of raid_devs we need to create for this drive */ -static unsigned int num_devs(struct lib_context *lc, void *meta) +static unsigned int +num_devs(struct lib_context *lc, void *meta) { struct ddf1 *ddf1 = meta; unsigned int num_drives = ~0; - + get_config_index(ddf1, get_phys_drive(ddf1), &num_drives); return num_drives; } /* Is this DDF1 metadata? */ -static inline int is_ddf1(struct lib_context *lc, struct dev_info *di, - struct ddf1 *ddf1) +static inline int +is_ddf1(struct lib_context *lc, struct dev_info *di, struct ddf1 *ddf1) { /* * Check our magic numbers and that the version == v2. @@ -493,15 +501,15 @@ /* FIXME: We should examine the version headers... */ return ddf1->anchor.signature == DDF1_HEADER || - ddf1->anchor.signature == DDF1_HEADER_BACKWARDS; + ddf1->anchor.signature == DDF1_HEADER_BACKWARDS; } /* Try to find DDF1 metadata at a given offset (ddf1_sboffset) */ -static struct ddf1 *try_to_find_ddf1(struct lib_context *lc, - struct dev_info *di, - size_t *sz, uint64_t *offset, - union read_info *info, - uint64_t ddf1_sboffset) +static struct ddf1 * +try_to_find_ddf1(struct lib_context *lc, + struct dev_info *di, + size_t * sz, uint64_t * offset, + union read_info *info, uint64_t ddf1_sboffset) { struct ddf1 *ddf1; @@ -515,8 +523,7 @@ goto err; if (!read_file(lc, handler, di->path, &ddf1->anchor, to_bytes(1), - ddf1_sboffset) || - !is_ddf1(lc, di, ddf1)) + ddf1_sboffset) || !is_ddf1(lc, di, ddf1)) goto bad; ddf1->anchor_offset = ddf1_sboffset; @@ -531,9 +538,9 @@ if (read_extended(lc, di, ddf1)) return ddf1; - bad: + bad: dbg_free(ddf1); - err: + err: return NULL; } @@ -543,9 +550,9 @@ * Note that the struct should be fully converted to the correct endianness * by the time this function returns. */ -static void *read_metadata_areas(struct lib_context *lc, struct dev_info *di, - size_t *sz, uint64_t *offset, - union read_info *info) +static void * +read_metadata_areas(struct lib_context *lc, struct dev_info *di, + size_t * sz, uint64_t * offset, union read_info *info) { struct ddf1 *ddf1; @@ -560,8 +567,8 @@ } /* This is all hogwash since file_metadata can only be called once... */ -static void file_metadata_areas(struct lib_context *lc, struct dev_info *di, - void *meta) +static void +file_metadata_areas(struct lib_context *lc, struct dev_info *di, void *meta) { uint8_t *buf; uint64_t start = ddf1_beginning(meta); @@ -571,14 +578,14 @@ file_metadata(lc, handler, di->path, buf, to_bytes(di->sectors - start), to_bytes(start)); dbg_free(buf); - file_dev_size(lc, handler, di); /* Record the device size. */ + file_dev_size(lc, handler, di); /* Record the device size. */ } } static int setup_rd(struct lib_context *lc, struct raid_dev *rd, struct dev_info *di, void *meta, union read_info *info); -static struct raid_dev *ddf1_read(struct lib_context *lc, - struct dev_info *di) +static struct raid_dev * +ddf1_read(struct lib_context *lc, struct dev_info *di) { /* * NOTE: Everything called after read_metadata_areas assumes that @@ -590,7 +597,8 @@ } /* Compose an "identifier" for use as a sort key for raid sets. */ -static inline int compose_id(struct ddf1 *ddf1, struct raid_dev *rd) +static inline int +compose_id(struct ddf1 *ddf1, struct raid_dev *rd) { struct ddf1_phys_drive *pd = get_phys_drive(ddf1); int i = get_config_byoffset(ddf1, pd, rd->offset); @@ -599,24 +607,27 @@ } /* No sort. */ -static int no_sort(struct list_head *pos, struct list_head *new) +static int +no_sort(struct list_head *pos, struct list_head *new) { return 0; } /* Sort DDF1 devices by offset entry within a RAID set. */ -static int dev_sort(struct list_head *pos, struct list_head *new) +static int +dev_sort(struct list_head *pos, struct list_head *new) { struct raid_dev *rd_pos = RD(pos), *rd_new = RD(new); return compose_id(META(GRP_RD(rd_new), ddf1), rd_new) < - compose_id(META(GRP_RD(rd_pos), ddf1), rd_pos); + compose_id(META(GRP_RD(rd_pos), ddf1), rd_pos); } /* * IO error event handler. */ -static int event_io(struct lib_context *lc, struct event_io *e_io) +static int +event_io(struct lib_context *lc, struct event_io *e_io) { log_err(lc, "%s: I/O error on device %s at sector %lu.\n", handler, e_io->rd->di->path, e_io->sector); @@ -626,30 +637,30 @@ #if 0 /* FIXME: This should not use META() directly? */ - struct raid_dev *rd = e_io->rd; - struct ddf1 *ddf1 = META(rd, ddf1); - struct ddf1_raid_configline *cl = this_disk(ddf1); - struct ddf1_raid_configline *fwl = find_logical(ddf1); +struct raid_dev *rd = e_io->rd; +struct ddf1 *ddf1 = META(rd, ddf1); +struct ddf1_raid_configline *cl = this_disk(ddf1); +struct ddf1_raid_configline *fwl = find_logical(ddf1); /* Ignore if we've already marked this disk broken(?) */ - if (rd->status & s_broken) - return 0; - +if (rd->status & s_broken) + return 0; + /* Mark the array as degraded and the disk as failed. */ - rd->status = s_broken; - cl->raidstate = LSU_COMPONENT_STATE_FAILED; - fwl->raidstate = LSU_COMPONENT_STATE_DEGRADED; +rd->status = s_broken; +cl->raidstate = LSU_COMPONENT_STATE_FAILED; +fwl->raidstate = LSU_COMPONENT_STATE_DEGRADED; /* FIXME: Do we have to mark a parent too? */ /* Indicate that this is indeed a failure. */ - return 1; +return 1; } #endif #define NAME_SIZE 64 /* Formulate a RAID set name for this disk. */ -static char *name(struct lib_context *lc, struct ddf1 *ddf1, - struct raid_dev *rd) +static char * +name(struct lib_context *lc, struct ddf1 *ddf1, struct raid_dev *rd) { int i, prefix; char buf[NAME_SIZE]; @@ -661,8 +672,8 @@ return err_phys_drive(lc, rd->di); i = get_config_byoffset(ddf1, pd, rd->offset); - cr = get_config(ddf1, pd, i); - if (i < 0 || !cr) { + cr = get_config(ddf1, pd, i); + if (i < 0 || !cr) { sprintf(buf, DDF1_SPARES); goto out; } @@ -677,29 +688,29 @@ memcpy(buf + prefix, vd->name, 16); i = prefix + 16; while (!isgraph(buf[--i])); - buf[i+1] = 0; + buf[i + 1] = 0; } else { char *b; for (b = buf + prefix, i = 0; i < 24; b += 8, i += 4) sprintf(b, "%02x%02x%02x%02x", - vd->guid[i], vd->guid[i+1], - vd->guid[i+2], vd->guid[i+3]); + vd->guid[i], vd->guid[i + 1], + vd->guid[i + 2], vd->guid[i + 3]); } - out: - return dbg_strdup(buf); /* Only return the needed allocation */ + out: + return dbg_strdup(buf); /* Only return the needed allocation */ } /* Figure out the real size of a disk... */ -static uint64_t get_size(struct lib_context *lc, struct ddf1 *ddf1, - struct ddf1_config_record *cr, - struct ddf1_phys_drive *pd) +static uint64_t +get_size(struct lib_context *lc, struct ddf1 *ddf1, + struct ddf1_config_record *cr, struct ddf1_phys_drive *pd) { if (cr && cr->sectors) /* Some Adaptec controllers need this clamping. */ return type(lc, ddf1, cr) == t_raid0 ? - cr->sectors - cr->sectors % stride(cr) : cr->sectors; + cr->sectors - cr->sectors % stride(cr) : cr->sectors; return pd->size; } @@ -710,9 +721,9 @@ * function is successful, NULL if not. rd_group is the raid device that * represents the entire disk drive. */ -static struct raid_set *group_rd(struct lib_context *lc, - struct raid_set *rs_group, - struct raid_dev *rd_group) +static struct raid_set * +group_rd(struct lib_context *lc, + struct raid_set *rs_group, struct raid_dev *rd_group) { struct ddf1 *ddf1 = META(rd_group, ddf1); struct raid_set *rs = NULL; @@ -721,7 +732,7 @@ struct ddf1_phys_drive *pd; struct ddf1_group_info *gi; unsigned int devs, i; - + if (!(pd = get_phys_drive(ddf1))) return err_phys_drive(lc, rd_group->di); @@ -747,7 +758,7 @@ * If we have a virtual drive config without an entry in the * list of virtual drives, we ignore it. Weird bug seen on * Adaptec 2410SA controller. - */ + */ if (!(rd->name = name(lc, ddf1, rd))) { free_raid_dev(lc, &rd); continue; @@ -789,7 +800,8 @@ * * FIXME: We haven't been able to set up a RAID10 for testing... */ -static struct raid_set *ddf1_group(struct lib_context *lc, struct raid_dev *rd) +static struct raid_set * +ddf1_group(struct lib_context *lc, struct raid_dev *rd) { struct ddf1 *ddf1 = META(rd, ddf1); struct ddf1_phys_drive *pd; @@ -810,8 +822,7 @@ * (Is this really necessary?) */ if (!(rs = find_or_alloc_raid_set(lc, rd->name, FIND_TOP, rd, - LC_RS(lc), NO_CREATE, - NO_CREATE_ARG))) + LC_RS(lc), NO_CREATE, NO_CREATE_ARG))) return NULL; rs->type = t_group; @@ -822,19 +833,20 @@ } /* Write metadata. */ -static int ddf1_write(struct lib_context *lc, struct raid_dev *rd, int erase) +static int +ddf1_write(struct lib_context *lc, struct raid_dev *rd, int erase) { int ret; - struct ddf1 *ddf1 = META(rd, ddf1); + struct ddf1 *ddf1 = META(rd, ddf1); if (ddf1->adaptec_mode) ddf1_update_all_crcs(lc, rd->di, ddf1); - ddf1_cvt_all(lc, ddf1, rd->di); - ret = write_metadata(lc, handler, rd, -1, erase); - ddf1_cvt_all(lc, ddf1, rd->di); + ddf1_cvt_all(lc, ddf1, rd->di); + ret = write_metadata(lc, handler, rd, -1, erase); + ddf1_cvt_all(lc, ddf1, rd->di); - return ret; + return ret; } /* @@ -842,7 +854,8 @@ */ /* Retrieve the number of devices that should be in this set. */ -static unsigned int device_count(struct raid_dev *rd, void *context) +static unsigned int +device_count(struct raid_dev *rd, void *context) { /* Get the logical drive */ struct ddf1_config_record *cr = @@ -852,8 +865,9 @@ } /* Check a RAID device */ -static int check_rd(struct lib_context *lc, struct raid_set *rs, - struct raid_dev *rd, void *context) +static int +check_rd(struct lib_context *lc, struct raid_set *rs, + struct raid_dev *rd, void *context) { /* * FIXME: Should we do more checking for brokenness here? @@ -863,7 +877,8 @@ } /* Start the recursive RAID set check. */ -static int ddf1_check(struct lib_context *lc, struct raid_set *rs) +static int +ddf1_check(struct lib_context *lc, struct raid_set *rs) { return check_raid_set(lc, rs, device_count, NULL, check_rd, NULL, handler); @@ -871,36 +886,38 @@ static struct event_handlers ddf1_event_handlers = { .io = event_io, - .rd = NULL, /* FIXME: no device add/remove event handler yet. */ + .rd = NULL, /* FIXME: no device add/remove event handler yet. */ }; #ifdef DMRAID_NATIVE_LOG /* * Log native information about the RAID device. */ -static void ddf1_log(struct lib_context *lc, struct raid_dev *rd) +static void +ddf1_log(struct lib_context *lc, struct raid_dev *rd) { ddf1_dump_all(lc, rd->di, META(rd, ddf1), handler); } #endif /* #ifdef DMRAID_NATIVE_LOG */ static struct dmraid_format ddf1_format = { - .name = HANDLER, - .descr = "SNIA DDF1", - .caps = "0,1,4,5,linear", + .name = HANDLER, + .descr = "SNIA DDF1", + .caps = "0,1,4,5,linear", .format = FMT_RAID, - .read = ddf1_read, - .write = ddf1_write, - .group = ddf1_group, - .check = ddf1_check, - .events = &ddf1_event_handlers, + .read = ddf1_read, + .write = ddf1_write, + .group = ddf1_group, + .check = ddf1_check, + .events = &ddf1_event_handlers, #ifdef DMRAID_NATIVE_LOG - .log = ddf1_log, + .log = ddf1_log, #endif }; /* Register this format handler with the format core */ -int register_ddf1(struct lib_context *lc) +int +register_ddf1(struct lib_context *lc) { return register_format_handler(lc, &ddf1_format); } @@ -908,8 +925,9 @@ /* * Set up a RAID device from what we've assembled out of the metadata. */ -static int setup_rd(struct lib_context *lc, struct raid_dev *rd, - struct dev_info *di, void *meta, union read_info *info) +static int +setup_rd(struct lib_context *lc, struct raid_dev *rd, + struct dev_info *di, void *meta, union read_info *info) { unsigned int i, ma_count = 5; struct ddf1 *ddf1 = meta; @@ -918,7 +936,7 @@ if (!(pd = get_phys_drive(ddf1))) LOG_ERR(lc, 0, "%s: Cannot find physical drive description " - "on %s!", handler, di->path); + "on %s!", handler, di->path); /* We need multiple metadata areas */ ma_count += ddf1->adapter ? 1 : 0; @@ -969,7 +987,7 @@ ma->area = ddf1->cfg; /* Now set up the rest of the metadata info */ - rd->di = di; + rd->di = di; rd->fmt = &ddf1_format; rd->status = disk_status(pd); rd->type = t_group; --- dmraid/lib/format/ddf/ddf1.h 2008/02/22 17:04:35 1.1 +++ dmraid/lib/format/ddf/ddf1.h 2008/06/20 21:52:17 1.2 @@ -91,160 +91,160 @@ /* The DDF1 header table */ struct ddf1_header { - uint32_t signature; - uint32_t crc; - uint8_t guid[DDF1_GUID_LENGTH]; - uint8_t ddf_rev[DDF1_REV_LENGTH]; - uint32_t seqnum; - uint32_t timestamp; - uint8_t open_flag; - uint8_t foreign_flag; - uint8_t grouping_enforced; - uint8_t reserved2[45]; - uint64_t primary_table_lba; - uint64_t secondary_table_lba; - uint8_t header_type; - uint8_t reserved3[3]; - uint32_t workspace_length; - uint64_t workspace_lba; - uint16_t max_phys_drives; - uint16_t max_virt_drives; - uint16_t max_partitions; - uint16_t vd_config_record_len; - uint16_t max_primary_elements; - uint8_t reserved4[54]; - uint32_t adapter_data_offset; - uint32_t adapter_data_len; - uint32_t phys_drive_offset; - uint32_t phys_drive_len; - uint32_t virt_drive_offset; - uint32_t virt_drive_len; - uint32_t config_record_offset; - uint32_t config_record_len; - uint32_t disk_data_offset; - uint32_t disk_data_len; - uint32_t badblock_offset; - uint32_t badblock_len; - uint32_t diag_offset; - uint32_t diag_len; - uint32_t vendor_offset; - uint32_t vendor_len; - uint8_t reserved5[256]; + uint32_t signature; + uint32_t crc; + uint8_t guid[DDF1_GUID_LENGTH]; + uint8_t ddf_rev[DDF1_REV_LENGTH]; + uint32_t seqnum; + uint32_t timestamp; + uint8_t open_flag; + uint8_t foreign_flag; + uint8_t grouping_enforced; + uint8_t reserved2[45]; + uint64_t primary_table_lba; + uint64_t secondary_table_lba; + uint8_t header_type; + uint8_t reserved3[3]; + uint32_t workspace_length; + uint64_t workspace_lba; + uint16_t max_phys_drives; + uint16_t max_virt_drives; + uint16_t max_partitions; + uint16_t vd_config_record_len; + uint16_t max_primary_elements; + uint8_t reserved4[54]; + uint32_t adapter_data_offset; + uint32_t adapter_data_len; + uint32_t phys_drive_offset; + uint32_t phys_drive_len; + uint32_t virt_drive_offset; + uint32_t virt_drive_len; + uint32_t config_record_offset; + uint32_t config_record_len; + uint32_t disk_data_offset; + uint32_t disk_data_len; + uint32_t badblock_offset; + uint32_t badblock_len; + uint32_t diag_offset; + uint32_t diag_len; + uint32_t vendor_offset; + uint32_t vendor_len; + uint8_t reserved5[256]; } __attribute__ ((packed)); /* The adapter data header */ struct ddf1_adapter { - uint32_t signature; - uint32_t crc; - uint8_t guid[DDF1_GUID_LENGTH]; - uint16_t pci_vendor; - uint16_t pci_device; - uint16_t pci_subvendor; - uint16_t pci_subdevice; - uint8_t reserved2[24]; - uint8_t adapter_data[448]; + uint32_t signature; + uint32_t crc; + uint8_t guid[DDF1_GUID_LENGTH]; + uint16_t pci_vendor; + uint16_t pci_device; + uint16_t pci_subvendor; + uint16_t pci_subdevice; + uint8_t reserved2[24]; + uint8_t adapter_data[448]; } __attribute__ ((packed)); /* Physical drive info */ struct ddf1_disk_data { - uint32_t signature; - uint32_t crc; - uint8_t guid[DDF1_GUID_LENGTH]; - uint32_t reference; - uint8_t forced_ref_flag; - uint8_t forced_guid_flag; - uint8_t scratch[32]; - uint8_t reserved[442]; + uint32_t signature; + uint32_t crc; + uint8_t guid[DDF1_GUID_LENGTH]; + uint32_t reference; + uint8_t forced_ref_flag; + uint8_t forced_guid_flag; + uint8_t scratch[32]; + uint8_t reserved[442]; } __attribute__ ((packed)); /* Physical drive record header */ struct ddf1_phys_drives { - uint32_t signature; - uint32_t crc; - uint16_t num_drives; - uint16_t max_drives; - uint8_t reserved2[52]; + uint32_t signature; + uint32_t crc; + uint16_t num_drives; + uint16_t max_drives; + uint8_t reserved2[52]; /* 64 bytes */ /* Drive records follow */ } __attribute__ ((packed)); /* Physical drive record */ struct ddf1_phys_drive { - uint8_t guid[DDF1_GUID_LENGTH]; - uint32_t reference; - uint16_t type; - uint16_t state; - uint64_t size; - uint8_t path_info[18]; - uint8_t reserved3[6]; + uint8_t guid[DDF1_GUID_LENGTH]; + uint32_t reference; + uint16_t type; + uint16_t state; + uint64_t size; + uint8_t path_info[18]; + uint8_t reserved3[6]; } __attribute__ ((packed)); /* Virtual drive record header */ struct ddf1_virt_drives { - uint32_t signature; - uint32_t crc; - uint16_t num_drives; - uint16_t max_drives; - uint8_t reserved2[52]; + uint32_t signature; + uint32_t crc; + uint16_t num_drives; + uint16_t max_drives; + uint8_t reserved2[52]; /* Drive records follow */ } __attribute__ ((packed)); /* Virtual drive record */ struct ddf1_virt_drive { - uint8_t guid[DDF1_GUID_LENGTH]; - uint16_t vd_num; - uint16_t reserved2; - uint32_t type; - uint8_t state; - uint8_t init_state; - uint8_t reserved3[14]; - uint8_t name[16]; + uint8_t guid[DDF1_GUID_LENGTH]; + uint16_t vd_num; + uint16_t reserved2; + uint32_t type; + uint8_t state; + uint8_t init_state; + uint8_t reserved3[14]; + uint8_t name[16]; } __attribute__ ((packed)); /* Virtual disk configuration record. */ struct ddf1_config_record { - uint32_t signature; - uint32_t crc; - uint8_t guid[DDF1_GUID_LENGTH]; - uint32_t timestamp; - uint32_t seqnum; - uint8_t reserved[24]; - uint16_t primary_element_count; - uint8_t stripe_size; - uint8_t raid_level; - uint8_t raid_qualifier; - uint8_t secondary_element_count; - uint8_t secondary_element_number; - uint8_t secondary_element_raid_level; - uint64_t sectors; - uint64_t size; - uint64_t reserved2; - uint32_t spares[8]; - uint64_t cache_policy; - uint8_t bg_task_rate; + uint32_t signature; + uint32_t crc; + uint8_t guid[DDF1_GUID_LENGTH]; + uint32_t timestamp; + uint32_t seqnum; + uint8_t reserved[24]; + uint16_t primary_element_count; + uint8_t stripe_size; + uint8_t raid_level; + uint8_t raid_qualifier; + uint8_t secondary_element_count; + uint8_t secondary_element_number; + uint8_t secondary_element_raid_level; + uint64_t sectors; + uint64_t size; + uint64_t reserved2; + uint32_t spares[8]; + uint64_t cache_policy; + uint8_t bg_task_rate; /* 137 bytes */ - uint8_t reserved3[3+52+192+32+32+16+16+32]; + uint8_t reserved3[3 + 52 + 192 + 32 + 32 + 16 + 16 + 32]; /* 512 bytes */ } __attribute__ ((packed)); /* Spare disk record */ struct ddf1_spare { - uint8_t guid[DDF1_GUID_LENGTH]; - uint16_t secondary_element; - uint8_t reserved[6]; + uint8_t guid[DDF1_GUID_LENGTH]; + uint16_t secondary_element; + uint8_t reserved[6]; } __attribute__ ((packed)); /* Spare disk assignment record */ struct ddf1_spare_header { - uint32_t signature; - uint32_t crc; - uint32_t timestamp; - uint8_t reserved[7]; - uint8_t type; - uint16_t num_spares; - uint16_t max_spares; - uint8_t reserved2[8]; - struct ddf1_spare spares[0]; + uint32_t signature; + uint32_t crc; + uint32_t timestamp; + uint8_t reserved[7]; + uint8_t type; + uint16_t num_spares; + uint16_t max_spares; + uint8_t reserved2[8]; + struct ddf1_spare spares[0]; } __attribute__ ((packed)); /* Metadata owner */ --- dmraid/lib/format/ddf/ddf1_crc.c 2008/04/02 13:35:31 1.3 +++ dmraid/lib/format/ddf/ddf1_crc.c 2008/06/20 21:52:17 1.4 @@ -4,8 +4,8 @@ * Copyright (C) 2005-2006 IBM, All rights reserved. * Written by James Simshaw <simshawj@xxxxxxxxxx> * - * Copyright (C) 2006 Heinz Mauelshagen, Red Hat GmbH - * All rights reserved. + * Copyright (C) 2006-2008 Heinz Mauelshagen, Red Hat GmbH + * All rights reserved. * * See file LICENSE at the top of this source tree for license information. */ @@ -28,9 +28,10 @@ /* Make the table for a fast CRC. */ #define CRC_TABLE_SIZE 256 -static inline void crc_table_init(uint32_t *crc_table) +static inline void +crc_table_init(uint32_t * crc_table) { - static int new = 1; /* Flag for table not yet computed. */ + static int new = 1; /* Flag for table not yet computed. */ if (new) { uint32_t c, n, k; @@ -49,15 +50,16 @@ * crc() routine below). */ /* Return the CRC of the bytes buf[0..len-1]. */ -static uint32_t crc(uint32_t crc, unsigned char *buf, int len) +static uint32_t +crc(uint32_t crc, unsigned char *buf, int len) { int n; - static uint32_t crc_table[CRC_TABLE_SIZE]; /* CRCs of 8-bit messages. */ + static uint32_t crc_table[CRC_TABLE_SIZE]; /* CRCs of 8-bit messages. */ crc_table_init(crc_table); for (n = 0; n < len; n++) crc = crc_table[(crc ^ buf[n]) & (CRC_TABLE_SIZE - 1)] ^ - (crc >> 8); + (crc >> 8); return crc ^ 0xFFFFFFFFL; } @@ -71,7 +73,8 @@ }; /* Compute the checksum of a table */ -static uint32_t do_crc32(struct lib_context *lc, struct crc_info *ci) +static uint32_t +do_crc32(struct lib_context *lc, struct crc_info *ci) { uint32_t old_csum = *ci->crc, ret = 0xFFFFFFFF; @@ -82,7 +85,8 @@ } /* Return VD record size. */ -static inline size_t record_size(struct ddf1 *ddf1) +static inline size_t +record_size(struct ddf1 *ddf1) { return ddf1->primary->vd_config_record_len * DDF1_BLKSIZE; } @@ -108,8 +112,8 @@ /* Process the configuration records to have their CRCs updated */ -static int update_cfg_crc(struct lib_context *lc, struct dev_info *di, - struct ddf1 *ddf1) +static int +update_cfg_crc(struct lib_context *lc, struct dev_info *di, struct ddf1 *ddf1) { static struct ddf1_record_handler handlers = { .vd = crc32_vd, @@ -121,17 +125,17 @@ } /* Checks the CRC for a particular table */ -static int check_crc(struct lib_context *lc, struct dev_info *di, - struct crc_info *ci) +static int +check_crc(struct lib_context *lc, struct dev_info *di, struct crc_info *ci) { uint32_t crc32; crc32 = do_crc32(lc, ci); if (*ci->crc != crc32) log_print(lc, "%s: %s with CRC %X, expected %X on %s", - HANDLER, ci->text, crc32, *ci->crc, di->path); - - + HANDLER, ci->text, crc32, *ci->crc, di->path); + + return 1; } @@ -155,8 +159,8 @@ #undef CHECK_CRC /* Process the configuration records to have their CRCs checked */ -static int check_cfg_crc(struct lib_context *lc, struct dev_info *di, - struct ddf1 *ddf1) +static int +check_cfg_crc(struct lib_context *lc, struct dev_info *di, struct ddf1 *ddf1) { struct ddf1_record_handler handlers = { .vd = vd_check_crc, @@ -169,27 +173,35 @@ /* Processes all of the DDF1 information for having their CRCs updated*/ enum all_type { CHECK, UPDATE }; -static int all_crcs(struct lib_context *lc, struct dev_info *di, - struct ddf1 *ddf1, enum all_type type) +static int +all_crcs(struct lib_context *lc, struct dev_info *di, + struct ddf1 *ddf1, enum all_type type) { int ret = 1; uint32_t crc; struct crc_info crcs[] = { - { ddf1->primary, &ddf1->primary->crc, - sizeof(*ddf1->primary), "primary header" }, - { ddf1->secondary, &ddf1->secondary->crc, - sizeof(*ddf1->secondary), "secondary header" }, - { ddf1->adapter, &ddf1->adapter->crc, - ddf1->primary->adapter_data_len * DDF1_BLKSIZE, "adapter" }, - { ddf1->disk_data, &ddf1->disk_data->crc, - ddf1->primary->disk_data_len * DDF1_BLKSIZE, "disk data" }, - { ddf1->pd_header, &ddf1->pd_header->crc, - ddf1->primary->phys_drive_len * DDF1_BLKSIZE, - "physical drives" }, - { ddf1->vd_header, &ddf1->vd_header->crc, - ddf1->primary->virt_drive_len * DDF1_BLKSIZE, - "virtual drives" }, - }, *c = ARRAY_END(crcs); + {ddf1->primary, &ddf1->primary->crc, + sizeof(*ddf1->primary), "primary header"} + , + {ddf1->secondary, &ddf1->secondary->crc, + sizeof(*ddf1->secondary), "secondary header"} + , + {ddf1->adapter, &ddf1->adapter->crc, + ddf1->primary->adapter_data_len * DDF1_BLKSIZE, "adapter"} + , + {ddf1->disk_data, &ddf1->disk_data->crc, + ddf1->primary->disk_data_len * DDF1_BLKSIZE, "disk data"} + , + {ddf1->pd_header, &ddf1->pd_header->crc, + ddf1->primary->phys_drive_len * DDF1_BLKSIZE, + "physical drives"} + , + {ddf1->vd_header, &ddf1->vd_header->crc, + ddf1->primary->virt_drive_len * DDF1_BLKSIZE, + "virtual drives"} + , + } + , *c = ARRAY_END(crcs); while (c-- > crcs) { if (c->p) { @@ -203,19 +215,21 @@ } return type == CHECK ? (ret & check_cfg_crc(lc, di, ddf1)) : - update_cfg_crc(lc, di, ddf1); + update_cfg_crc(lc, di, ddf1); } /* Processes the tables to check their CRCs */ -int ddf1_check_all_crcs(struct lib_context *lc, struct dev_info *di, - struct ddf1 *ddf1) +int +ddf1_check_all_crcs(struct lib_context *lc, struct dev_info *di, + struct ddf1 *ddf1) { return all_crcs(lc, di, ddf1, CHECK); } /* Processes all of the DDF1 information for having their CRCs updated */ -void ddf1_update_all_crcs(struct lib_context *lc, struct dev_info *di, - struct ddf1 *ddf1) +void +ddf1_update_all_crcs(struct lib_context *lc, struct dev_info *di, + struct ddf1 *ddf1) { all_crcs(lc, di, ddf1, UPDATE); } --- dmraid/lib/format/ddf/ddf1_cvt.c 2008/02/22 17:04:35 1.1 +++ dmraid/lib/format/ddf/ddf1_cvt.c 2008/06/20 21:52:17 1.2 @@ -20,7 +20,8 @@ #include <datastruct/byteorder.h> /* Convert a DDF header */ -void ddf1_cvt_header(struct ddf1 *ddf1, struct ddf1_header *hdr) +void +ddf1_cvt_header(struct ddf1 *ddf1, struct ddf1_header *hdr) { if (BYTE_ORDER == ddf1->disk_format) return; @@ -57,7 +58,8 @@ } /* Convert DDF adapter data */ -void ddf1_cvt_adapter(struct ddf1 *ddf1, struct ddf1_adapter *hdr) +void +ddf1_cvt_adapter(struct ddf1 *ddf1, struct ddf1_adapter *hdr) { if (BYTE_ORDER == ddf1->disk_format) return; @@ -71,7 +73,8 @@ } /* Convert physical disk data */ -void ddf1_cvt_disk_data(struct ddf1 *ddf1, struct ddf1_disk_data *hdr) +void +ddf1_cvt_disk_data(struct ddf1 *ddf1, struct ddf1_disk_data *hdr) { if (BYTE_ORDER == ddf1->disk_format) return; @@ -82,7 +85,8 @@ } /* Convert physical drive header data */ -void ddf1_cvt_phys_drive_header(struct ddf1 *ddf1, struct ddf1_phys_drives *hdr) +void +ddf1_cvt_phys_drive_header(struct ddf1 *ddf1, struct ddf1_phys_drives *hdr) { if (BYTE_ORDER == ddf1->disk_format) return; @@ -94,7 +98,8 @@ } /* Convert physical drive data */ -void ddf1_cvt_phys_drive(struct ddf1 *ddf1, struct ddf1_phys_drive *hdr) +void +ddf1_cvt_phys_drive(struct ddf1 *ddf1, struct ddf1_phys_drive *hdr) { if (BYTE_ORDER == ddf1->disk_format) return; @@ -106,7 +111,8 @@ } /* Convert virtual drive header data */ -void ddf1_cvt_virt_drive_header(struct ddf1 *ddf1, struct ddf1_virt_drives *hdr) +void +ddf1_cvt_virt_drive_header(struct ddf1 *ddf1, struct ddf1_virt_drives *hdr) { if (BYTE_ORDER == ddf1->disk_format) return; @@ -118,7 +124,8 @@ } /* Convert virtual drive data */ -void ddf1_cvt_virt_drive(struct ddf1 *ddf1, struct ddf1_virt_drive *hdr) +void +ddf1_cvt_virt_drive(struct ddf1 *ddf1, struct ddf1_virt_drive *hdr) { if (BYTE_ORDER == ddf1->disk_format) return; @@ -128,8 +135,9 @@ } /* Convert config record data */ -int ddf1_cvt_config_record(struct lib_context *lc, struct dev_info *di, - struct ddf1 *ddf1, int idx) +int +ddf1_cvt_config_record(struct lib_context *lc, struct dev_info *di, + struct ddf1 *ddf1, int idx) { unsigned int i; uint16_t max_pds; @@ -148,7 +156,8 @@ if (ddf1->primary->signature == DDF1_HEADER_BACKWARDS) CVT32(x); - off = ((uint64_t*) (((uint8_t*) hdr) + sizeof(*hdr) + (x * sizeof(x)))); + off = ((uint64_t *) (((uint8_t *) hdr) + sizeof(*hdr) + + (x * sizeof(x)))); CVT32(hdr->signature); CVT32(hdr->crc); @@ -172,8 +181,9 @@ } /* Convert spare records */ -int ddf1_cvt_spare_record(struct lib_context *lc, struct dev_info *di, - struct ddf1 *ddf1, int idx) +int +ddf1_cvt_spare_record(struct lib_context *lc, struct dev_info *di, + struct ddf1 *ddf1, int idx) { uint16_t x, i; struct ddf1_spare_header *sh = SR(ddf1, idx); @@ -196,7 +206,8 @@ return 1; } -void ddf1_cvt_records(struct lib_context *lc, struct dev_info *di, +void +ddf1_cvt_records(struct lib_context *lc, struct dev_info *di, struct ddf1 *ddf1, int in_cpu_format) { static struct ddf1_record_handler handlers = { @@ -208,8 +219,8 @@ } /* Convert endianness of all metadata */ -void ddf1_cvt_all(struct lib_context *lc, struct ddf1 *ddf1, - struct dev_info *di) +void +ddf1_cvt_all(struct lib_context *lc, struct ddf1 *ddf1, struct dev_info *di) { int i; uint16_t pds = 0, vds = 0; --- dmraid/lib/format/ddf/ddf1_cvt.h 2008/02/22 17:04:35 1.1 +++ dmraid/lib/format/ddf/ddf1_cvt.h 2008/06/20 21:52:17 1.2 @@ -29,7 +29,7 @@ int ddf1_cvt_spare_record(struct lib_context *lc, struct dev_info *di, struct ddf1 *ddf1, int idx); void ddf1_cvt_records(struct lib_context *lc, struct dev_info *di, - struct ddf1 *ddf1, int in_cpu_format); + struct ddf1 *ddf1, int in_cpu_format); void ddf1_cvt_all(struct lib_context *lc, struct ddf1 *ddf1, struct dev_info *di); --- dmraid/lib/format/ddf/ddf1_dump.c 2008/02/22 17:04:35 1.1 +++ dmraid/lib/format/ddf/ddf1_dump.c 2008/06/20 21:52:17 1.2 @@ -28,8 +28,9 @@ _dp_guid(lc, name, P_OFF(x, basevar, x), DDF1_GUID_LENGTH);\ } while (0) -static void _dp_guid(struct lib_context *lc, const char *name, - unsigned int offset, void *data, unsigned int len) +static void +_dp_guid(struct lib_context *lc, const char *name, + unsigned int offset, void *data, unsigned int len) { char *p; int i; @@ -52,17 +53,19 @@ #endif /* Dump top */ -static void dump_top(struct lib_context *lc, struct dev_info *di, - struct ddf1 *ddf1, const char *handler) +static void +dump_top(struct lib_context *lc, struct dev_info *di, + struct ddf1 *ddf1, const char *handler) { log_print(lc, "%s (%s):", di->path, handler); log_print(lc, "DDF1 anchor at %llu with tables in %s-endian format.", ddf1->anchor_offset / DDF1_BLKSIZE, (ddf1->disk_format == LITTLE_ENDIAN ? "little" : "big")); } - + /* Dump DDF tables. */ -static void dump_header(struct lib_context *lc, struct ddf1_header *dh) +static void +dump_header(struct lib_context *lc, struct ddf1_header *dh) { if (!dh) return; @@ -105,7 +108,8 @@ DP("vendor_len:\t%d", dh, dh->vendor_len); } -static void dump_adapter(struct lib_context *lc, struct ddf1_adapter *da) +static void +dump_adapter(struct lib_context *lc, struct ddf1_adapter *da) { if (!da) return; @@ -120,7 +124,8 @@ DP("pci subdevice:\t0x%X", da, da->pci_subdevice); } -static void dump_disk_data(struct lib_context *lc, struct ddf1_disk_data *fg) +static void +dump_disk_data(struct lib_context *lc, struct ddf1_disk_data *fg) { log_print(lc, "Disk Data at %p", fg); DP("signature:\t0x%X", fg, fg->signature); @@ -131,8 +136,8 @@ DP("forced_guid_flag:\t%d", fg, fg->forced_guid_flag); } -static void dump_phys_drive_header(struct lib_context *lc, - struct ddf1_phys_drives *pd) +static void +dump_phys_drive_header(struct lib_context *lc, struct ddf1_phys_drives *pd) { log_print(lc, "Physical Drive Header at %p", pd); DP("signature:\t0x%X", pd, pd->signature); @@ -141,7 +146,8 @@ DP("max drives:\t%d", pd, pd->max_drives); } -static void dump_phys_drive(struct lib_context *lc, struct ddf1_phys_drive *pd) +static void +dump_phys_drive(struct lib_context *lc, struct ddf1_phys_drive *pd) { log_print(lc, "Physical Drive at %p", pd); DP_GUID("guid:\t\t", pd, pd->guid); @@ -152,8 +158,8 @@ DP_BUF("path info:\t", pd, pd->path_info, 18); } -static void dump_virt_drive_header(struct lib_context *lc, - struct ddf1_virt_drives *vd) +static void +dump_virt_drive_header(struct lib_context *lc, struct ddf1_virt_drives *vd) { log_print(lc, "Virtual Drive Header at %p", vd); DP("signature:\t0x%X", vd, vd->signature); @@ -162,7 +168,8 @@ DP("max drives:\t%d", vd, vd->max_drives); } -static void dump_virt_drive(struct lib_context *lc, struct ddf1_virt_drive *vd) +static void +dump_virt_drive(struct lib_context *lc, struct ddf1_virt_drive *vd) { log_print(lc, "Virtual Drive at %p", vd); DP_GUID("guid:\t\t", vd, vd->guid); @@ -173,8 +180,9 @@ DP_BUF("name:\t\t", vd, vd->name, 16); } -static int dump_config_record(struct lib_context *lc, struct dev_info *di, - struct ddf1 *ddf, int idx) +static int +dump_config_record(struct lib_context *lc, struct dev_info *di, + struct ddf1 *ddf, int idx) { int i; uint16_t x; @@ -220,10 +228,11 @@ cfg_drive_offsets[i]); } return 1; -} +} -static int dump_spares(struct lib_context *lc, struct dev_info *di, - struct ddf1 *ddf1, int idx) +static int +dump_spares(struct lib_context *lc, struct dev_info *di, + struct ddf1 *ddf1, int idx) { int i; struct ddf1_spare_header *sh = SR(ddf1, idx); @@ -244,8 +253,9 @@ return 1; } -static void dump_config_records(struct lib_context *lc, struct dev_info *di, - struct ddf1 *ddf1) +static void +dump_config_records(struct lib_context *lc, struct dev_info *di, + struct ddf1 *ddf1) { static struct ddf1_record_handler handlers = { .vd = dump_config_record, @@ -256,8 +266,9 @@ } /* Dump the entire table */ -void ddf1_dump_all(struct lib_context *lc, struct dev_info *di, - struct ddf1 *ddf1, const char *handler) +void +ddf1_dump_all(struct lib_context *lc, struct dev_info *di, + struct ddf1 *ddf1, const char *handler) { int i; --- dmraid/lib/format/ddf/ddf1_lib.c 2008/02/22 17:06:54 1.2 +++ dmraid/lib/format/ddf/ddf1_lib.c 2008/06/20 21:52:17 1.3 @@ -20,9 +20,10 @@ #include <datastruct/byteorder.h> /* Figure out what endian conversions we need */ -int ddf1_endianness(struct lib_context *lc, struct ddf1 *ddf1) +int +ddf1_endianness(struct lib_context *lc, struct ddf1 *ddf1) { - uint8_t *ptr = (uint8_t*) &ddf1->anchor.signature; + uint8_t *ptr = (uint8_t *) & ddf1->anchor.signature; if (ptr[0] == 0xDE && ptr[1] == 0x11) return BIG_ENDIAN; @@ -33,7 +34,8 @@ } /* Find the beginning of all DDF metadata */ -uint64_t ddf1_beginning(struct ddf1 *ddf1) +uint64_t +ddf1_beginning(struct ddf1 *ddf1) { uint64_t start; struct ddf1_header *h = &ddf1->anchor; @@ -52,51 +54,52 @@ } /* Helper for CR_OFF */ -uint16_t ddf1_cr_off_maxpds_helper(struct ddf1 *ddf1) +uint16_t +ddf1_cr_off_maxpds_helper(struct ddf1 * ddf1) { struct ddf1_header *h = ddf1->primary; /* The 0xFFFF nonsense is a weird Adaptec quirk */ -// bz211016 -// return (h->max_primary_elements == 0xFFFF && ddf1->adaptec_mode) ? +// bz211016 +// return (h->max_primary_elements == 0xFFFF && ddf1->adaptec_mode) ? return (h->max_primary_elements == 0xFFFF) ? h->max_phys_drives : h->max_primary_elements; } /* Process DDF1 records depending on type */ -int ddf1_process_records(struct lib_context *lc, struct dev_info *di, - struct ddf1_record_handler *handler, - struct ddf1 *ddf1, int in_cpu_format) +int +ddf1_process_records(struct lib_context *lc, struct dev_info *di, + struct ddf1_record_handler *handler, + struct ddf1 *ddf1, int in_cpu_format) { unsigned int i, cfgs = NUM_CONFIG_ENTRIES(ddf1); uint32_t x; for (i = 0; i < cfgs; i++) { - x = *((uint32_t*) CR(ddf1, i)); - if (!in_cpu_format && - BYTE_ORDER != ddf1->disk_format) + x = *((uint32_t *) CR(ddf1, i)); + if (!in_cpu_format && BYTE_ORDER != ddf1->disk_format) CVT32(x); switch (x) { - case DDF1_VD_CONFIG_REC: - if (!handler->vd(lc, di, ddf1, i)) - return 0; + case DDF1_VD_CONFIG_REC: + if (!handler->vd(lc, di, ddf1, i)) + return 0; - break; + break; - case DDF1_SPARE_REC: - if (!handler->spare(lc, di, ddf1, i)) - return 0; + case DDF1_SPARE_REC: + if (!handler->spare(lc, di, ddf1, i)) + return 0; - break; + break; - case 0: /* Adaptec puts zero in this field??? */ - case DDF1_INVALID: - break; + case 0: /* Adaptec puts zero in this field??? */ + case DDF1_INVALID: + break; - default: - log_warn(lc, "%s: Unknown config record %d.", - di->path, x); + default: + log_warn(lc, "%s: Unknown config record %d.", + di->path, x); } } --- dmraid/lib/format/ddf/ddf1_lib.h 2008/02/22 17:04:35 1.1 +++ dmraid/lib/format/ddf/ddf1_lib.h 2008/06/20 21:52:17 1.2 @@ -14,12 +14,14 @@ #define _DDF1_LIB_H /* Cpmpare two GUIDs */ -static inline uint8_t _and(uint8_t *p) +static inline uint8_t +_and(uint8_t * p) { return p[20] & p[21] & p[22] & p[23]; } -static inline int guidcmp(uint8_t *one, uint8_t *two) +static inline int +guidcmp(uint8_t * one, uint8_t * two) { int x = memcmp(one, two, DDF1_GUID_LENGTH - 4); @@ -30,20 +32,21 @@ } /* Byte offset for sector */ -static inline uint64_t to_bytes(uint64_t sector) +static inline uint64_t +to_bytes(uint64_t sector) { return sector * DDF1_BLKSIZE; } -uint64_t ddf1_beginning(struct ddf1 *ddf1); +uint64_t ddf1_beginning(struct ddf1 * ddf1); uint16_t ddf1_cr_off_maxpds_helper(struct ddf1 *ddf1); int ddf1_endianness(struct lib_context *lc, struct ddf1 *ddf1); struct ddf1_record_handler { - int (*vd)(struct lib_context *lc, struct dev_info *di, - struct ddf1 *ddf1, int idx); - int (*spare)(struct lib_context *lc, struct dev_info *di, - struct ddf1 *ddf1, int idx); + int (*vd) (struct lib_context * lc, struct dev_info * di, + struct ddf1 * ddf1, int idx); + int (*spare) (struct lib_context * lc, struct dev_info * di, + struct ddf1 * ddf1, int idx); }; int ddf1_process_records(struct lib_context *lc, struct dev_info *di, --- dmraid/lib/format/partition/dos.c 2008/04/02 13:35:31 1.3 +++ dmraid/lib/format/partition/dos.c 2008/06/20 21:52:18 1.4 @@ -25,19 +25,19 @@ static const char *handler = HANDLER; /* Make up RAID device name. */ -static size_t _name(struct lib_context *lc, struct raid_dev *rd, - unsigned short partition, char *str, size_t len, - unsigned char type) +static size_t +_name(struct lib_context *lc, struct raid_dev *rd, + unsigned short partition, char *str, size_t len, unsigned char type) { const char *base = get_basename(lc, rd->di->path); return type ? snprintf(str, len, "%s%s%u", base, OPT_STR_PARTCHAR(lc), - partition) : - snprintf(str, len, "%s", base); + partition) : snprintf(str, len, "%s", base); } -static char *name(struct lib_context *lc, struct raid_dev *rd, - unsigned int part, unsigned char type) +static char * +name(struct lib_context *lc, struct raid_dev *rd, + unsigned int part, unsigned char type) { size_t len; char *ret; @@ -57,7 +57,8 @@ #if BYTE_ORDER == LITTLE_ENDIAN # define to_cpu NULL #else -static void to_cpu(void *meta) +static void +to_cpu(void *meta) { struct dos *dos = meta; struct dos_partition *part = dos->partitions; @@ -71,7 +72,8 @@ } #endif -static int is_dos(struct lib_context *lc, struct dev_info *di, void *meta) +static int +is_dos(struct lib_context *lc, struct dev_info *di, void *meta) { struct dos *dos = meta; struct dos_partition *part; @@ -87,8 +89,8 @@ return 1; } -static void dos_file_metadata(struct lib_context *lc, struct dev_info *di, - void *meta) +static void +dos_file_metadata(struct lib_context *lc, struct dev_info *di, void *meta) { if (OPT_DUMP(lc)) log_print(lc, "%s: filing metadata not supported (use fdisk " @@ -98,7 +100,8 @@ /* Allocate a DOS partition sector struct and read the data. */ static int setup_rd(struct lib_context *lc, struct raid_dev *rd, struct dev_info *di, void *meta, union read_info *info); -static struct raid_dev *dos_read(struct lib_context *lc, struct dev_info *di) +static struct raid_dev * +dos_read(struct lib_context *lc, struct dev_info *di) { return read_raid_dev(lc, di, NULL, sizeof(struct dos), DOS_CONFIGOFFSET, @@ -107,23 +110,24 @@ } /* Support functions for dos_group to read the partition table(s). */ -static int part_is_extended (struct dos_partition *part) +static int +part_is_extended(struct dos_partition *part) { return part->type == PARTITION_EXT || - part->type == PARTITION_EXT_LBA || - part->type == PARTITION_LINUX_EXT; + part->type == PARTITION_EXT_LBA || + part->type == PARTITION_LINUX_EXT; } /* Get a partition start offset relative to a base location. */ -static uint64_t get_part_start(const struct dos_partition *raw_part, - uint64_t offset) +static uint64_t +get_part_start(const struct dos_partition *raw_part, uint64_t offset) { return (uint64_t) raw_part->start + offset; } /* RAID set allocation support function. */ -static struct raid_set *_alloc_raid_set(struct lib_context *lc, - struct raid_dev *rd) +static struct raid_set * +_alloc_raid_set(struct lib_context *lc, struct raid_dev *rd) { struct raid_set *rs; @@ -135,9 +139,9 @@ return NULL; rs->status = rd->status; - rs->type = rd->type; + rs->type = rd->type; - if (!(rs->name = dbg_strdup(rd->name))) { + if (!(rs->name = dbg_strdup(rd->name))) { dbg_free(rs); rs = NULL; log_alloc_err(lc, handler); @@ -147,12 +151,12 @@ } /* Check sector vs. RAID device end */ -static int rd_check_end(struct lib_context *lc, - struct raid_dev *rd, uint64_t sector) +static int +rd_check_end(struct lib_context *lc, struct raid_dev *rd, uint64_t sector) { if (sector > rd->di->sectors) LOG_ERR(lc, 1, "%s: partition address past end of RAID device", - handler); + handler); return 0; } @@ -161,9 +165,10 @@ * Allocate a DOS RAID device and a set. * Set the device up and add it to the set. */ -static int _create_rs_and_rd(struct lib_context *lc, struct raid_dev *rd, - struct dos_partition *raw_part, uint64_t sector, - unsigned int part) +static int +_create_rs_and_rd(struct lib_context *lc, struct raid_dev *rd, + struct dos_partition *raw_part, uint64_t sector, + unsigned int part) { struct raid_dev *r; struct raid_set *rs; @@ -174,7 +179,7 @@ if (!(r->di = alloc_dev_info(lc, rd->di->path))) goto free_raid_dev; - if (!(r->name = name(lc, rd, part, 1))) + if (!(r->name = name(lc, rd, part, 1))) goto free_di; r->fmt = rd->fmt; @@ -197,9 +202,9 @@ return 1; - free_di: + free_di: free_dev_info(lc, r->di); - free_raid_dev: + free_raid_dev: free_raid_dev(lc, &r); return 0; @@ -215,14 +220,16 @@ * Partition code inspired by libparted and squeezed for this purpose (lemon). */ /* FIXME: Check for position of partition */ -static int is_partition(struct dos_partition *p, uint64_t start_sector) +static int +is_partition(struct dos_partition *p, uint64_t start_sector) { return p->type != PARTITION_EMPTY && p->length && p->start; } -static int group_rd_extended(struct lib_context *lc, struct raid_dev *rd, - uint64_t start_sector, uint64_t *extended_root, - unsigned int part) +static int +group_rd_extended(struct lib_context *lc, struct raid_dev *rd, + uint64_t start_sector, uint64_t * extended_root, + unsigned int part) { int ret = 0; uint64_t new_start_sector; @@ -240,7 +247,7 @@ #endif if (dos->magic == PARTITION_MAGIC_MAGIC) goto out; - + /* Check magic to see if this is a real partition table. */ if (dos->magic != DOS_MAGIC) goto out; @@ -249,13 +256,13 @@ * Logical partition tables only have two entries, * one for the partition and one for the next partition table. */ - + /* * An entry pointing to the present logical partition. * It is an offset from the present partition table location. */ p1 = dos->partitions; - + /* * An entry pointing to the next logical partition table. * It is an offset from the main extended partition start. @@ -276,25 +283,25 @@ if (!*extended_root) *extended_root = start_sector; new_start_sector = get_part_start(p2, *extended_root); - + if (is_partition(p2, start_sector) && !group_rd_extended(lc, rd, new_start_sector, extended_root, part)) goto out; ret = 1; - out: + out: dbg_free(dos); return ret; } /* Handle primary partitions. */ -static int group_rd(struct lib_context *lc, struct raid_dev *rd, - uint64_t start_sector) +static int +group_rd(struct lib_context *lc, struct raid_dev *rd, uint64_t start_sector) { unsigned int i; uint64_t part_start, part_end, - extended_part_start = 0, extended_root = 0; + extended_part_start = 0, extended_root = 0; struct dos *dos = META(rd, dos); struct dos_partition *raw_table_entry; @@ -314,8 +321,8 @@ * start of drive. */ part_start = get_part_start(raw_table_entry, start_sector); - part_end = part_start + raw_table_entry->length; - + part_end = part_start + raw_table_entry->length; + /* Avoid infinite recursion (mostly). */ if (part_start == start_sector) continue; @@ -336,19 +343,19 @@ start_sector, i + 1)) return 0; } - + /* When we are finished with all the primary partitions, * go do the extended partition if we have one. * It always starts with partition 5. */ return extended_part_start ? - group_rd_extended(lc, rd, extended_part_start, - &extended_root, 5) : 1; + group_rd_extended(lc, rd, extended_part_start, + &extended_root, 5) : 1; } /* Add a DOS RAID device to a set */ -static struct raid_set *dos_group(struct lib_context *lc, - struct raid_dev *rd) +static struct raid_set * +dos_group(struct lib_context *lc, struct raid_dev *rd) { /* * Once we get here, a DOS partition table @@ -363,34 +370,36 @@ * to something else for some strange partitioning scheme because the * code will handle it. */ - return group_rd(lc, rd, 0) ? (struct raid_set*) 1 : NULL; + return group_rd(lc, rd, 0) ? (struct raid_set *) 1 : NULL; } /* * Check integrity of a DOS RAID set. */ -static int dos_check(struct lib_context *lc, struct raid_set *rs) +static int +dos_check(struct lib_context *lc, struct raid_set *rs) { - return 1; /* Nice, eh ? */ + return 1; /* Nice, eh ? */ } static struct dmraid_format dos_format = { - .name = HANDLER, - .descr = "DOS partitions on SW RAIDs", - .caps = NULL, /* Not supported */ + .name = HANDLER, + .descr = "DOS partitions on SW RAIDs", + .caps = NULL, /* Not supported */ .format = FMT_PARTITION, - .read = dos_read, - .write = NULL, /* Not supported */ - .group = dos_group, - .check = dos_check, - .events = NULL, /* Not supported */ + .read = dos_read, + .write = NULL, /* Not supported */ + .group = dos_group, + .check = dos_check, + .events = NULL, /* Not supported */ #ifdef DMRAID_NATIVE_LOG - .log = NULL, /* Not supported; use fdisk and friends */ + .log = NULL, /* Not supported; use fdisk and friends */ #endif }; /* Register this format handler with the format core. */ -int register_dos(struct lib_context *lc) +int +register_dos(struct lib_context *lc) { return register_format_handler(lc, &dos_format); } @@ -401,8 +410,9 @@ * For a DOS partition we essentially just save the * partition table sector and let dos_group do the rest... */ -static int setup_rd(struct lib_context *lc, struct raid_dev *rd, - struct dev_info *di, void *meta, union read_info *info) +static int +setup_rd(struct lib_context *lc, struct raid_dev *rd, + struct dev_info *di, void *meta, union read_info *info) { struct dos *dos = meta; @@ -411,16 +421,16 @@ rd->meta_areas->offset = DOS_CONFIGOFFSET >> 9; rd->meta_areas->size = sizeof(*dos); - rd->meta_areas->area = (void*) dos; + rd->meta_areas->area = (void *) dos; - rd->di = di; + rd->di = di; rd->fmt = &dos_format; - rd->status = s_ok; /* Always :-) */ - rd->type = t_partition; + rd->status = s_ok; /* Always :-) */ + rd->type = t_partition; - rd->offset = DOS_DATAOFFSET; - rd->sectors = di->sectors; + rd->offset = DOS_DATAOFFSET; + rd->sectors = di->sectors; - return (rd->name = name(lc, rd, 0, 0)) ? 1 : 0; + return (rd->name = name(lc, rd, 0, 0)) ? 1 : 0; } --- dmraid/lib/format/partition/dos.h 2008/02/22 16:57:36 1.1 +++ dmraid/lib/format/partition/dos.h 2008/06/20 21:52:18 1.2 @@ -23,29 +23,29 @@ #define DOS_DATAOFFSET 0 struct chs { - uint8_t head; - uint8_t sector; - uint8_t cylinder; + uint8_t head; + uint8_t sector; + uint8_t cylinder; } __attribute__ ((packed)); struct dos_partition { - uint8_t boot_ind; /* 00: 0x80 - active */ - struct chs chs_start; /* 01: */ - uint8_t type; /* 04: partition type */ + uint8_t boot_ind; /* 00: 0x80 - active */ + struct chs chs_start; /* 01: */ + uint8_t type; /* 04: partition type */ #define PARTITION_EMPTY 0x00 #define PARTITION_EXT 0x05 #define PARTITION_EXT_LBA 0x0f #define PARTITION_LINUX_EXT 0x85 #define PARTITION_GPT 0xee - struct chs chs_end; /* 05: */ - uint32_t start; /* 08: starting sector from 0 */ - uint32_t length; /* 0c: nr of sectors in partition */ + struct chs chs_end; /* 05: */ + uint32_t start; /* 08: starting sector from 0 */ + uint32_t length; /* 0c: nr of sectors in partition */ } __attribute__ ((packed)); struct dos { - uint8_t boot_code [446]; - struct dos_partition partitions [4]; - uint16_t magic; + uint8_t boot_code[446]; + struct dos_partition partitions[4]; + uint16_t magic; #define DOS_MAGIC 0xAA55 #define PARTITION_MAGIC_MAGIC 0xF6F6 } __attribute__ ((packed)); --- dmraid/lib/format/template/template.c 2008/02/22 16:57:36 1.1 +++ dmraid/lib/format/template/template.c 2008/06/20 21:52:18 1.2 @@ -24,14 +24,14 @@ /* Make up RAID device name. */ /* CODEME: implement creation of senseful name for the RAID device */ -static size_t _name(struct template *template, char *str, size_t len, - unsigned int subset) +static size_t +_name(struct template *template, char *str, size_t len, unsigned int subset) { return snprintf(str, len, "template"); } -static char *name(struct lib_context *lc, struct raid_dev *rd, - unsigned int subset) +static char * +name(struct lib_context *lc, struct raid_dev *rd, unsigned int subset) { size_t len; char *ret; @@ -40,7 +40,8 @@ if ((ret = dbg_malloc((len = _name(template, NULL, 0, subset) + 1)))) { _name(template, ret, len, subset); mk_alpha(lc, ret + HANDLER_LEN, len - HANDLER_LEN); - } else + } + else log_alloc_err(lc, handler); return ret; @@ -52,13 +53,14 @@ * (see metadata.h for generic ones) */ static struct types types[] = { - { TEMPLATE_T_SPAN, t_linear }, - { TEMPLATE_T_RAID0, t_raid0 }, - { 0, t_undef} + {TEMPLATE_T_SPAN, t_linear}, + {TEMPLATE_T_RAID0, t_raid0}, + {0, t_undef} }; /* Neutralize disk type using generic metadata type mapping function */ -static enum type template_type(struct lib_context *lc, struct raid_dev *rd) +static enum type +template_type(struct lib_context *lc, struct raid_dev *rd) { return rd_type(types, (unsigned int) (META(rd, template))->type); } @@ -70,17 +72,17 @@ #if BYTE_ORDER == LITTLE_ENDIAN # define to_cpu(x) #else -static void to_cpu(struct template *template) +static void +to_cpu(struct template *template) { CVT32(template->something); - ... -} +...} #endif static int setup_rd(struct lib_context *lc, struct raid_dev *rd, struct dev_info *di, void *meta, union read_info *info); -static struct raid_dev *template_read(struct lib_context *lc, - struct dev_info *di) +static struct raid_dev * +template_read(struct lib_context *lc, struct dev_info *di) { return read_raid_dev(lc, di, NULL, sizeof(struct template), TEMPLATE_CONFIGOFFSET, @@ -91,25 +93,27 @@ * Decide about ordering sequence of RAID device. * (Called by list_add_sorted(). */ -static int dev_sort(struct list_head *pos, struct list_head *new) +static int +dev_sort(struct list_head *pos, struct list_head *new) { return (META(RD(new), template))->disk_number < - (META(RD(pos), template))->disk_number; + (META(RD(pos), template))->disk_number; } /* * Decide about ordering sequence of RAID device. * (Called by join_superset(). */ -static int set_sort(struct list_head *pos, struct list_head *new) +static int +set_sort(struct list_head *pos, struct list_head *new) { return _subset(META(RD_RS(RS(new)), via)) < - _subset(META(RD_RS(RS(pos)), via)); + _subset(META(RD_RS(RS(pos)), via)); } /* Add a Template RAID device to a set */ -static struct raid_set *template_group(struct lib_context *lc, - struct raid_dev *rd) +static struct raid_set * +template_group(struct lib_context *lc, struct raid_dev *rd) { if (T_SPARE(rd)) return NULL; @@ -124,8 +128,8 @@ } /* CODEME: Write private RAID metadata to device */ -static int template_write(struct lib_context *lc, - struct raid_dev *rd, int erase) +static int +template_write(struct lib_context *lc, struct raid_dev *rd, int erase) { int ret; #if BYTE_ORDER != LITTLE_ENDIAN @@ -142,7 +146,8 @@ /* * Check integrity of a RAID set. */ -static unsigned int devices(struct raid_dev *rd, void *context) +static unsigned int +devices(struct raid_dev *rd, void *context) { LOG_ERR(lc, 0, "%s: implement RAID device # function", handler); } @@ -153,7 +158,8 @@ LOG_ERR(lc, 0, "%s: implement RAID device integrity checks", handler); } -static int template_check(struct lib_context *lc, struct raid_set *rs) +static int +template_check(struct lib_context *lc, struct raid_set *rs) { /* CODEME: implement */ return check_raid_set(lc, rs, devices, devices_context, @@ -161,15 +167,16 @@ } static struct event_handlers template_event_handlers = { - .io = event_io, /* CODEME: */ - .rd = NULL, /* FIXME: no device add/remove event handler yet. */ + .io = event_io, /* CODEME: */ + .rd = NULL, /* FIXME: no device add/remove event handler yet. */ }; #ifdef DMRAID_NATIVE_LOG /* * Log native information about the RAID device. */ -static void template_log(struct lib_context *lc, struct raid_dev *rd) +static void +template_log(struct lib_context *lc, struct raid_dev *rd) { struct template *template = META(rd, template); @@ -179,29 +186,31 @@ #endif static struct dmraid_format template_format = { - .name = HANDLER, - .descr = "Template RAID", - .caps = "(Insert RAID levels here)", + .name = HANDLER, + .descr = "Template RAID", + .caps = "(Insert RAID levels here)", .format = FMT_RAID, - .read = template_read, - .write = template_write, - .group = template_group, - .check = template_check, - .events = &template_event_handlers, + .read = template_read, + .write = template_write, + .group = template_group, + .check = template_check, + .events = &template_event_handlers, #ifdef DMRAID_NATIVE_LOG - .log = template_log, + .log = template_log, #endif }; /* Register this format handler with the format core */ -int register_template(struct lib_context *lc) +int +register_template(struct lib_context *lc) { return register_format_handler(lc, &template_format); } /* CODEME: Set the RAID device contents up derived from the TEMPLATE ones */ -static int setup_rd(struct lib_context *lc, struct raid_dev *rd, - struct dev_info *di, void *meta, union read_info *info) +static int +setup_rd(struct lib_context *lc, struct raid_dev *rd, + struct dev_info *di, void *meta, union read_info *info) { struct template *template = meta; @@ -210,20 +219,20 @@ rd->meta_areas->offset = TEMPLATE_CONFIGOFFSET >> 9; rd->meta_areas->size = sizeof(*template); - rd->meta_areas->area = (void*) template; + rd->meta_areas->area = (void *) template; - rd->di = di; + rd->di = di; rd->fmt = &template_format; - rd->status = s_ok; /* CODEME: derive from metadata. */ - rd->type = template_type(template); + rd->status = s_ok; /* CODEME: derive from metadata. */ + rd->type = template_type(template); rd->offset = TEMPLATE_DATAOFFSET; /* CODEME: correct sectors. */ rd->sectors = rd->meta_areas->offset; - if ((rd->name = name(lc, rd, 1))) + if ((rd->name = name(lc, rd, 1))) return 1; return 0; --- dmraid/lib/format/template/template.h 2008/02/22 16:57:36 1.1 +++ dmraid/lib/format/template/template.h 2008/06/20 21:52:18 1.2 @@ -25,14 +25,14 @@ uint32_t magic; /* and/or metadata has a 'magic' number ? */ #define TEMPLATE_MAGIC_OK 0xABCDEF - uint8_t type; /* RAID level */ + uint8_t type; /* RAID level */ #define TEMPLATE_T_SPAN 0 #define TEMPLATE_T_RAID0 1 uint8_t disk_number; /* Absolute disk number in set. */ /* etc. */ - ....... /* members for numbers of disks, whatever... */ + ... .... /* members for numbers of disks, whatever... */ } __attribute__ ((packed)); #endif --- dmraid/lib/locking/locking.c 2008/02/22 17:04:36 1.2 +++ dmraid/lib/locking/locking.c 2008/06/20 21:52:18 1.3 @@ -16,7 +16,8 @@ static int lf = -1; /* flock file. */ -static int lock(struct lib_context *lc, struct resource *res) +static int +lock(struct lib_context *lc, struct resource *res) { /* Already locked. */ if (lf > -1) @@ -36,7 +37,8 @@ } /* Unlock file. */ -static void unlock(struct lib_context *lc, struct resource *res) +static void +unlock(struct lib_context *lc, struct resource *res) { /* Not locked! */ if (lf == -1) @@ -55,17 +57,18 @@ /* File base locking interface. */ static struct locking file_locking = { - .name = "file", - .lock = lock, - .unlock = unlock, + .name = "file", + .lock = lock, + .unlock = unlock, }; -static int init_file_locking(struct lib_context *lc) +static int +init_file_locking(struct lib_context *lc) { int ret = 0; char *dir; - if (!(dir = get_dirname(lc, (char*) lock_file))) + if (!(dir = get_dirname(lc, (char *) lock_file))) return 0; if (!mk_dir(lc, dir)) @@ -78,7 +81,7 @@ lc->lock = &file_locking; ret = 1; - out: + out: dbg_free(dir); return ret; @@ -89,7 +92,8 @@ */ /* Initialize locking. */ -int init_locking(struct lib_context *lc) +int +init_locking(struct lib_context *lc) { if (OPT_IGNORELOCKING(lc)) return 1; @@ -101,13 +105,15 @@ } /* Hide locking. */ -int lock_resource(struct lib_context *lc, struct resource *res) +int +lock_resource(struct lib_context *lc, struct resource *res) { return OPT_IGNORELOCKING(lc) ? 1 : lc->lock->lock(lc, res); } /* Hide unlocking. */ -void unlock_resource(struct lib_context *lc, struct resource *res) +void +unlock_resource(struct lib_context *lc, struct resource *res) { return OPT_IGNORELOCKING(lc) ? 1 : lc->lock->unlock(lc, res); } --- dmraid/lib/log/log.c 2008/02/22 16:57:36 1.1 +++ dmraid/lib/log/log.c 2008/06/20 21:52:18 1.2 @@ -18,19 +18,21 @@ "FATAL", }; -static const char *_prefix(int level) +static const char * +_prefix(int level) { return level < ARRAY_SIZE(_prefixes) ? _prefixes[level] : "UNDEF"; } -void plog(struct lib_context *lc, int level, int lf, const char *file, - int line, const char *format, ...) +void +plog(struct lib_context *lc, int level, int lf, const char *file, + int line, const char *format, ...) { int o = LC_VERBOSE, l = level; FILE *f = stdout; va_list ap; - if (level == _PLOG_DEBUG) { + if (level == _PLOG_DEBUG) { o = LC_DEBUG; l -= _PLOG_WARN; } @@ -53,7 +55,8 @@ } /* This is used so often in the metadata format handlers and elsewhere. */ -int log_alloc_err(struct lib_context *lc, const char *who) +int +log_alloc_err(struct lib_context *lc, const char *who) { LOG_ERR(lc, 0, "%s: allocating", who); } --- dmraid/lib/metadata/log_ops.c 2008/02/22 17:04:36 1.1 +++ dmraid/lib/metadata/log_ops.c 2008/06/20 21:52:18 1.2 @@ -9,7 +9,8 @@ */ #include "internal.h" -void end_log(struct lib_context *lc, struct list_head *log) +void +end_log(struct lib_context *lc, struct list_head *log) { struct list_head *pos, *tmp; @@ -19,7 +20,8 @@ } } -int revert_log(struct lib_context *lc, struct list_head *log) +int +revert_log(struct lib_context *lc, struct list_head *log) { int writes_started = 0, ret = 0; struct change *entry; @@ -37,13 +39,14 @@ rd = entry->rd; rd->type = t_spare; list_del_init(&entry->rd->devs); - } else if (entry->type == WRITE_METADATA) { + } + else if (entry->type == WRITE_METADATA) { writes_started = 1; rd = entry->rd; ret = write_dev(lc, rd, 0); if (ret) { log_err(lc, "%s: Error while reverting " - "metadata.", __func__); + "metadata.", __func__); break; } } --- dmraid/lib/metadata/metadata.c 2008/04/02 13:35:31 1.4 +++ dmraid/lib/metadata/metadata.c 2008/06/20 21:52:18 1.5 @@ -1,10 +1,14 @@ /* - * Copyright (C) 2004,2005 Heinz Mauelshagen, Red Hat GmbH. + * Copyright (C) 2004-2008 Heinz Mauelshagen, Red Hat GmbH. * All rights reserved. * + * Copyright (C) 2007 Intel Corporation. All rights reserved. + * November, 2007 - additions for Create, Delete, Rebuild & Raid 10. + * * See file LICENSE at the top of this source tree for license information. */ +#include <getopt.h> #include "internal.h" #include "activate/devmapper.h" @@ -20,24 +24,24 @@ const char *dm_ascii; } ascii_type[] = { /* enum text dm-target id */ - { t_undef, NULL, NULL }, - { t_group, "GROUP", NULL }, - { t_partition, "partition", NULL }, - { t_spare, "spare", NULL }, - { t_linear, "linear", "linear" }, - { t_raid0, "stripe", "striped" }, - { t_raid1, "mirror", "mirror" }, - { t_raid4, "raid4", "raid45" }, - { t_raid5_ls, "raid5_ls", "raid45" }, - { t_raid5_rs, "raid5_rs", "raid45" }, - { t_raid5_la, "raid5_la", "raid45" }, - { t_raid5_ra, "raid5_ra", "raid45" }, - { t_raid6, "raid6", NULL }, + { t_undef, NULL, NULL}, + { t_group, "GROUP", NULL}, + { t_partition, "partition", NULL}, + { t_spare, "spare", NULL}, + { t_linear, "linear", "linear"}, + { t_raid0, "stripe", "striped"}, + { t_raid1, "mirror", "mirror"}, + { t_raid4, "raid4", "raid45"}, + { t_raid5_ls, "raid5_ls", "raid45"}, + { t_raid5_rs, "raid5_rs", "raid45"}, + { t_raid5_la, "raid5_la", "raid45"}, + { t_raid5_ra, "raid5_ra", "raid45"}, + { t_raid6, "raid6", NULL}, }; static const char *stacked_ascii_type[][5] = { - { "raid10", "raid30", "raid40", "raid50", "raid60" }, - { "raid01", "raid03", "raid04", "raid05", "raid06" }, + {"raid10", "raid30", "raid40", "raid50", "raid60"}, + {"raid01", "raid03", "raid04", "raid05", "raid06"}, }; /* @@ -47,16 +51,47 @@ const enum status status; const char *ascii; } ascii_status[] = { - { s_undef, NULL }, - { s_setup, "setup" }, - { s_broken, "broken" }, - { s_inconsistent, "inconsistent" }, - { s_nosync, "nosync" }, - { s_ok, "ok" }, + { + s_undef, NULL}, { + s_setup, "setup"}, { + s_broken, "broken"}, { + s_inconsistent, "inconsistent"}, { + s_nosync, "nosync"}, { +s_ok, "ok"},}; + +/* type of spare set - string definition */ +#define SPARE_TYPE_STRING "8" + +/**************************/ + + +#define ALL_FLAGS ((enum action) -1) + +/* + * Action flag definitions for set_action(). + * + * 'Early' options can be handled directly in set_action() by calling + * the functions registered here (f_set member) handing in arg. + */ +struct actions { + int option; /* Option character/value. */ + enum action action; /* Action flag for this option or UNDEF. */ + enum action needed; /* Mandatory options or UNDEF if alone */ + enum action allowed; /* Allowed flags (ie, other options allowed) */ + + enum args args; /* Arguments allowed ? */ + + /* Function to call on hit or NULL */ + int (*f_set) (struct lib_context * lc, int arg); + int arg; /* Argument for above function call */ }; +/*************************************/ + + /* Fetch the respective ASCII string off the types array. */ -static unsigned int get_type_index(enum type type) +static unsigned int +get_type_index(enum type type) { unsigned int ret = ARRAY_SIZE(ascii_type); @@ -68,36 +103,39 @@ return 0; } -const char *get_type(struct lib_context *lc, enum type type) +const char * +get_type(struct lib_context *lc, enum type type) { return ascii_type[get_type_index(type)].dsp_ascii; } -const char *get_dm_type(struct lib_context *lc, enum type type) +const char * +get_dm_type(struct lib_context *lc, enum type type) { return ascii_type[get_type_index(type)].dm_ascii; } /* Return the RAID type of a stacked RAID set (eg, raid10). */ -static const char *get_stacked_type(void *v) +static const char * +get_stacked_type(void *v) { struct raid_set *rs = v; unsigned int t = (T_RAID0(rs) ? get_type_index((RS_RS(rs))->type) : - get_type_index(rs->type)) - - get_type_index(t_raid1); + get_type_index(rs->type)) - get_type_index(t_raid1); - return stacked_ascii_type[T_RAID0(rs) ? 1 : 0] - [t > t_raid0 ? t_undef : t]; + return stacked_ascii_type[T_RAID0(rs) ? 1:0][t > t_raid0 ? t_undef:t]; } /* Check, if a RAID set is stacked (ie, hierachical). */ -static inline int is_stacked(struct raid_set *rs) +static inline int +is_stacked(struct raid_set *rs) { return !T_GROUP(rs) && SETS(rs); } /* Return the ASCII type for a RAID set. */ -const char *get_set_type(struct lib_context *lc, void *v) +const char * +get_set_type(struct lib_context *lc, void *v) { struct raid_set *rs = v; @@ -106,12 +144,12 @@ } /* Fetch the respective ASCII string off the state array. */ -const char *get_status(struct lib_context *lc, enum status status) +const char * +get_status(struct lib_context *lc, enum status status) { unsigned int i = ARRAY_SIZE(ascii_status); while (i-- && !(status & ascii_status[i].status)); - return ascii_status[i].ascii; } @@ -121,8 +159,8 @@ * * Pay attention to RAID > 0 types. */ -static uint64_t add_sectors(struct raid_set *rs, uint64_t sectors, - uint64_t add) +static uint64_t +add_sectors(struct raid_set *rs, uint64_t sectors, uint64_t add) { add = rs->stride ? round_down(add, rs->stride) : add; @@ -136,7 +174,8 @@ } /* FIXME: proper calculation of unsymetric sets ? */ -static uint64_t smallest_disk(struct raid_set *rs) +static uint64_t +smallest_disk(struct raid_set *rs) { uint64_t ret = ~0; struct raid_dev *rd; @@ -148,26 +187,27 @@ } /* Count subsets of a set. */ -static unsigned int count_subsets(struct lib_context *lc, struct raid_set *rs) +static unsigned int +count_subsets(struct lib_context *lc, struct raid_set *rs) { unsigned ret = 0; struct raid_set *r; - list_for_each_entry(r, &rs->sets, list) - ret++; + list_for_each_entry(r, &rs->sets, list) ret++; return ret; } /* Calculate total sectors of a (hierarchical) RAID set. */ -uint64_t total_sectors(struct lib_context *lc, struct raid_set *rs) +uint64_t +total_sectors(struct lib_context * lc, struct raid_set * rs) { - uint64_t sectors = 0; - struct raid_dev *rd; + uint64_t sectors = 0; + struct raid_dev *rd; /* Stacked RAID sets. */ if (!T_GROUP(rs)) { - struct raid_set *r; + struct raid_set *r; list_for_each_entry(r, &rs->sets, list) sectors = add_sectors(rs, sectors, @@ -186,6 +226,14 @@ } } + /* Size for spare disk set */ + if (T_SPARE(rs)) { + list_for_each_entry(rd, &rs->devs, devs) { + if (T_SPARE(rd)) + sectors = add_sectors(rs, sectors, rd->sectors); + } + } + /* Size correction for higher RAID levels */ if (T_RAID4(rs) || T_RAID5(rs) || T_RAID6(rs)) { unsigned int i = count_subsets(lc, rs); @@ -196,20 +244,21 @@ sectors -= sub; } - return sectors; + return sectors; } /* Check if a RAID device should be counted. */ -static unsigned int _count_dev(struct raid_dev *rd, enum count_type type) +static unsigned int +_count_dev(struct raid_dev *rd, enum count_type type) { return ((type == ct_dev && !T_SPARE(rd)) || - (type == ct_spare && T_SPARE(rd)) || - type == ct_all) ? 1 : 0; + (type == ct_spare && T_SPARE(rd)) || type == ct_all) ? 1 : 0; } /* Count devices in a set recursively. */ -unsigned int count_devs(struct lib_context *lc, struct raid_set *rs, - enum count_type count_type) +unsigned int +count_devs(struct lib_context *lc, struct raid_set *rs, + enum count_type count_type) { unsigned int ret = 0; struct raid_set *r; @@ -233,7 +282,8 @@ * format handlers so far. If life becomes more complex, I might need * one though... */ -static void _free_dev_pointers(struct lib_context *lc, struct raid_dev *rd) +static void +_free_dev_pointers(struct lib_context *lc, struct raid_dev *rd) { int area, i, idx = 0; void **p; @@ -244,7 +294,7 @@ /* Allocate and initialize temporary pointer list. */ if (!(p = dbg_malloc(area * sizeof(*p)))) - LOG_ERR(lc, , "allocating pointer array"); + LOG_ERR(lc,, "failed to allocate pointer array"); /* Add private pointer to list. */ if (rd->private.ptr) @@ -257,7 +307,7 @@ if (p[i] == rd->meta_areas[area].area) break; } - + if (i == idx) p[idx++] = rd->meta_areas[area].area; } @@ -268,12 +318,13 @@ /* Free all RAID device pointers. */ while (idx--) dbg_free(p[idx]); - + dbg_free(p); } /* Allocate dev_info struct and keep the device path */ -struct dev_info *alloc_dev_info(struct lib_context *lc, char *path) +struct dev_info * +alloc_dev_info(struct lib_context *lc, char *path) { struct dev_info *di; @@ -291,7 +342,8 @@ } /* Free dev_info structure */ -static void _free_dev_info(struct lib_context *lc, struct dev_info *di) +static void +_free_dev_info(struct lib_context *lc, struct dev_info *di) { if (di->serial) dbg_free(di->serial); @@ -300,11 +352,15 @@ dbg_free(di); } -static inline void _free_dev_infos(struct lib_context *lc) +static inline void +_free_dev_infos(struct lib_context *lc) { struct list_head *elem, *tmp; list_for_each_safe(elem, tmp, LC_DI(lc)) { + if (!elem) + printf("NULL pointer\n"); + list_del(elem); _free_dev_info(lc, list_entry(elem, struct dev_info, list)); } @@ -314,13 +370,15 @@ * Free dev_info structure or all registered * dev_info structures in case di = NULL. */ -void free_dev_info(struct lib_context *lc, struct dev_info *di) +void +free_dev_info(struct lib_context *lc, struct dev_info *di) { di ? _free_dev_info(lc, di) : _free_dev_infos(lc); } /* Allocate/Free RAID device (member of a RAID set). */ -struct raid_dev *alloc_raid_dev(struct lib_context *lc, const char *who) +struct raid_dev * +alloc_raid_dev(struct lib_context *lc, const char *who) { struct raid_dev *ret; @@ -334,7 +392,8 @@ return ret; } -static void _free_raid_dev(struct lib_context *lc, struct raid_dev **rd) +static void +_free_raid_dev(struct lib_context *lc, struct raid_dev **rd) { struct raid_dev *r = *rd; @@ -348,12 +407,15 @@ */ _free_dev_pointers(lc, r); - dbg_free(r->name); + if (r->name) + dbg_free(r->name); + dbg_free(r); *rd = NULL; } -static inline void _free_raid_devs(struct lib_context *lc) +static inline void +_free_raid_devs(struct lib_context *lc) { struct list_head *elem, *tmp; struct raid_dev *rd; @@ -365,13 +427,15 @@ } /* Free RAID device structure or all registered RAID devices if rd == NULL. */ -void free_raid_dev(struct lib_context *lc, struct raid_dev **rd) +void +free_raid_dev(struct lib_context *lc, struct raid_dev **rd) { rd ? _free_raid_dev(lc, rd) : _free_raid_devs(lc); } /* Allocate/Free RAID set. */ -struct raid_set *alloc_raid_set(struct lib_context *lc, const char *who) +struct raid_set * +alloc_raid_set(struct lib_context *lc, const char *who) { struct raid_set *ret; @@ -380,7 +444,7 @@ INIT_LIST_HEAD(&ret->sets); INIT_LIST_HEAD(&ret->devs); ret->status = s_setup; - ret->type = t_undef; + ret->type = t_undef; } else log_alloc_err(lc, who); @@ -388,7 +452,8 @@ } /* Free a single RAID set structure and its RAID devices. */ -static void _free_raid_set(struct lib_context *lc, struct raid_set *rs) +static void +_free_raid_set(struct lib_context *lc, struct raid_set *rs) { struct raid_dev *rd; struct list_head *elem, *tmp; @@ -399,7 +464,7 @@ rd = RD(elem); log_dbg(lc, "freeing device \"%s\", path \"%s\"", - rd->name, rd->di->path); + rd->name, (rd->di) ? rd->di->path : "?"); /* FIXME: remove partition code in favour of kpartx ? */ /* @@ -425,7 +490,8 @@ } /* Remove a set or all sets (in case rs = NULL) recursively. */ -void free_raid_set(struct lib_context *lc, struct raid_set *rs) +void +free_raid_set(struct lib_context *lc, struct raid_set *rs) { struct list_head *elem, *tmp; @@ -439,21 +505,24 @@ } /* Return != 0 in case of a partitioned RAID set type. */ -int partitioned_set(struct lib_context *lc, void *rs) +int +partitioned_set(struct lib_context *lc, void *rs) { - return T_PARTITION((struct raid_set*) rs); + return T_PARTITION((struct raid_set *) rs); } /* Return != 0 in case of a partitioned base RAID set. */ -int base_partitioned_set(struct lib_context *lc, void *rs) +int +base_partitioned_set(struct lib_context *lc, void *rs) { - return ((struct raid_set*) rs)->flags & f_partitions; + return ((struct raid_set *) rs)->flags & f_partitions; } /* Return RAID set name. */ -const char *get_set_name(struct lib_context *lc, void *rs) +const char * +get_set_name(struct lib_context *lc, void *rs) { - return ((struct raid_set*) rs)->name; + return ((struct raid_set *) rs)->name; } /* @@ -462,9 +531,9 @@ * Search top level RAID set list only if where = FIND_TOP. * Recursive if where = FIND_ALL. */ -static struct raid_set *_find_set(struct lib_context *lc, - struct list_head *list, - const char *name, enum find where) +static struct raid_set * +_find_set(struct lib_context *lc, + struct list_head *list, const char *name, enum find where) { struct raid_set *r, *ret = NULL; @@ -483,26 +552,41 @@ } } - out: + out: log_dbg(lc, "_find_set: %sfound %s", ret ? "" : "not ", name); return ret; } -struct raid_set *find_set(struct lib_context *lc, - struct list_head *list, - const char *name, enum find where) +struct raid_set * +find_set(struct lib_context *lc, + struct list_head *list, const char *name, enum find where) { return _find_set(lc, list ? list : LC_RS(lc), name, where); } -struct raid_set *find_or_alloc_raid_set(struct lib_context *lc, - char *name, enum find where, - struct raid_dev *rd, - struct list_head *list, - void (*f_create) (struct raid_set *super, - void *private), - void *private) +static int set_sort(struct list_head *pos, struct list_head *new); + + +static int +set_sort(struct list_head *pos, struct list_head *new) +{ + struct raid_set *new_rs = list_entry(new, struct raid_set, list); + struct raid_set *pos_rs = list_entry(pos, struct raid_set, list); + + if ((new_rs->name) && (pos_rs->name)) + return (strcmp(new_rs->name, pos_rs->name) < 0); + else + return -1; +} + +struct raid_set * +find_or_alloc_raid_set(struct lib_context *lc, + char *name, enum find where, + struct raid_dev *rd, + struct list_head *list, + void (*f_create) (struct raid_set * + super, void *private), void *private) { struct raid_set *rs; @@ -515,35 +599,34 @@ if (!(rs->name = dbg_strdup(name))) goto err; - if (rd && ((rs->type = rd->type), T_SPARE(rd))) - rs->type = t_undef; + rs->type = rd ? rd->type : t_undef; /* If caller hands a list in, add to it. */ if (list) - list_add_tail(&rs->list, list); + list_add_sorted(lc, list, &rs->list, set_sort); /* Call any create callback. */ if (f_create) f_create(rs, private); - out: + out: return rs; - err: + err: dbg_free(rs); log_alloc_err(lc, __func__); return NULL; } -/* Return # of raid sets build */ -unsigned int count_sets(struct lib_context *lc, struct list_head *list) +/* Return # of RAID sets build */ +unsigned int +count_sets(struct lib_context *lc, struct list_head *list) { int ret = 0; struct list_head *elem; - list_for_each(elem, list) - ret++; + list_for_each(elem, list) ret++; return ret; } @@ -551,44 +634,45 @@ /* * Count devices found */ -static unsigned int _count_devices(struct lib_context *lc, enum dev_type type) +static unsigned int +_count_devices(struct lib_context *lc, enum dev_type type) { unsigned int ret = 0; struct list_head *elem, *list; if (DEVICE & type) list = LC_DI(lc); - else if (((RAID|NATIVE) & type)) + else if (((RAID | NATIVE) & type)) list = LC_RD(lc); else return 0; - - list_for_each(elem, list) - ret++; + + list_for_each(elem, list) ret++; return ret; } -unsigned int count_devices(struct lib_context *lc, enum dev_type type) +unsigned int +count_devices(struct lib_context *lc, enum dev_type type) { return type == SET ? count_sets(lc, LC_RS(lc)) : - _count_devices(lc, type); + _count_devices(lc, type); } /* * Read RAID metadata off a device by trying * all/selected registered format handlers in turn. */ -static int _want_format(struct dmraid_format *fmt, const char *format, - enum fmt_type type) +static int +_want_format(struct dmraid_format *fmt, const char *format, enum fmt_type type) { return fmt->format != type || - (format && strncmp(format, fmt->name, strlen(format))) ? 0 : 1; + (format && strncmp(format, fmt->name, strlen(format))) ? 0 : 1; } -static struct raid_dev *_dmraid_read(struct lib_context *lc, - struct dev_info *di, - struct dmraid_format *fmt) +static struct raid_dev * +_dmraid_read(struct lib_context *lc, + struct dev_info *di, struct dmraid_format *fmt) { struct raid_dev *rd; @@ -602,9 +686,9 @@ return rd; } -static struct raid_dev *dmraid_read(struct lib_context *lc, - struct dev_info *di, char const *format, - enum fmt_type type) +static struct raid_dev * +dmraid_read(struct lib_context *lc, + struct dev_info *di, char const *format, enum fmt_type type) { struct format_list *fl; struct raid_dev *rd = NULL, *rd_tmp; @@ -614,7 +698,8 @@ if (_want_format(fl->fmt, format, type) && (rd_tmp = _dmraid_read(lc, di, fl->fmt))) { if (rd) { - log_print(lc, "%s: \"%s\" and \"%s\" formats " + log_print(lc, + "%s: \"%s\" and \"%s\" formats " "discovered (using %s)!", di->path, rd_tmp->fmt->name, rd->fmt->name, rd->fmt->name); @@ -630,7 +715,8 @@ /* * Write RAID metadata to a device. */ -int write_dev(struct lib_context *lc, struct raid_dev *rd, int erase) +int +write_dev(struct lib_context *lc, struct raid_dev *rd, int erase) { int ret = 0; struct dmraid_format *fmt = rd->fmt; @@ -638,10 +724,10 @@ if (fmt->write) { log_notice(lc, "%sing metadata %s %s", erase ? "Eras" : "Writ", - erase ? "on" : "to", - rd->di->path); + erase ? "on" : "to", rd->di->path); ret = fmt->write(lc, rd, erase); - } else + } + else log_err(lc, "format \"%s\" doesn't support writing metadata", fmt->name); @@ -651,14 +737,15 @@ /* * Group RAID device into a RAID set. */ -static inline struct raid_set *dmraid_group(struct lib_context *lc, - struct raid_dev *rd) +static inline struct raid_set * +dmraid_group(struct lib_context *lc, struct raid_dev *rd) { return rd->fmt->group(lc, rd); } /* Check that device names are members of the devices list. */ -static int _want_device(struct dev_info *di, char **devices) +static int +_want_device(struct dev_info *di, char **devices) { char **dev; @@ -673,8 +760,29 @@ return 0; } +/* Discover RAID devices that are spares */ +void +discover_raid_devices_spares(struct lib_context *lc, const char *format) +{ + struct dev_info *di; + + /* Walk the list of discovered block devices. */ + list_for_each_entry(di, LC_DI(lc), list) { + struct raid_dev *rd; + + if ((rd = dmraid_read(lc, di, format, FMT_RAID))) { + /* FIXME: */ + /*if (T_SPARE(rd)) */ + list_add_tail(&rd->list, LC_RD(lc)); + + } + + } +} + /* Discover RAID devices. */ -void discover_raid_devices(struct lib_context *lc, char **devices) +void +discover_raid_devices(struct lib_context *lc, char **devices) { struct dev_info *di; char *names = NULL; @@ -682,7 +790,7 @@ /* In case we've got format identifiers -> duplicate string for loop. */ if (OPT_FORMAT(lc) && - (!(names = dbg_strdup((char*) OPT_STR_FORMAT(lc))))) { + (!(names = dbg_strdup((char *) OPT_STR_FORMAT(lc))))) { log_alloc_err(lc, __func__); return; } @@ -714,8 +822,8 @@ * * FIXME: remove partition code in favour of kpartx ? */ -static void _discover_partitions(struct lib_context *lc, - struct list_head *rs_list) +static void +_discover_partitions(struct lib_context *lc, struct list_head *rs_list) { char *path; struct dev_info *di; @@ -738,8 +846,7 @@ * Skip all "container" sets, which are not active. */ if (base_partitioned_set(lc, rs) || - partitioned_set(lc, rs) || - !dm_status(lc, rs)) + partitioned_set(lc, rs) || !dm_status(lc, rs)) continue; log_notice(lc, "discovering partitions on \"%s\"", rs->name); @@ -766,7 +873,8 @@ * We don't want to access that 'pointer'! */ if ((r = dmraid_group(lc, rd))) { - log_notice(lc, "created partitioned RAID set(s) for %s", + log_notice(lc, + "created partitioned RAID set(s) for %s", di->path); rs->flags |= f_partitions; } else @@ -781,7 +889,8 @@ } } -void discover_partitions(struct lib_context *lc) +void +discover_partitions(struct lib_context *lc) { _discover_partitions(lc, LC_RS(lc)); } @@ -792,18 +901,25 @@ * name = NULL : build all sets * name = String: build just the one set */ -static void want_set(struct lib_context *lc, struct raid_set *rs, char *name) +static void +want_set(struct lib_context *lc, struct raid_set *rs, char *name) { - if (name) { + struct raid_set *rs_sub, *rs_n; + + if (rs->type == t_group) { + list_for_each_entry_safe(rs_sub, rs_n, &rs->sets, list) + want_set(lc, rs_sub, name); + + if (list_empty(&rs->sets)) + free_raid_set(lc, rs); + } else if (name) { size_t len1 = strlen(rs->name), len2 = strlen(name); - if (len2 > len1 || - strncmp(rs->name, name, min(len1, len2))) { + if (len2 != len1 || strncmp(rs->name, name, min(len1, len2))) { struct dmraid_format *fmt = get_format(rs); - - log_notice(lc, "dropping unwanted RAID set \"%s\"", + log_notice(lc, + "dropping unwanted RAID set \"%s\"", rs->name); - /* * ddf1 carries a private pointer to it's contianing * set which is cleared as part of the check. So we @@ -820,7 +936,8 @@ } /* Get format handler of RAID set. */ -struct dmraid_format *get_format(struct raid_set *rs) +struct dmraid_format * +get_format(struct raid_set *rs) { /* Decend RAID set hierarchy. */ while (SETS(rs)) @@ -830,21 +947,30 @@ } /* Find the set associated with a device */ -struct raid_set *get_raid_set(struct lib_context *lc, struct raid_dev *dev) +struct raid_set * +get_raid_set(struct lib_context *lc, struct raid_dev *dev) { - struct raid_set *rs; - struct raid_dev *rd; + struct raid_set *rs = NULL, *sub_rs = NULL; + struct raid_dev *rd = NULL; - list_for_each_entry(rs, LC_RS(lc), list) - list_for_each_entry(rd, &rs->devs, devs) - if (dev == rd) - return rs; + list_for_each_entry(rs, LC_RS(lc), list) { + list_for_each_entry(rd, &rs->devs, devs) if (dev == rd) + return rs; + if (T_GROUP(rs)) { + list_for_each_entry(sub_rs, &rs->sets, list) { + list_for_each_entry(rd, &rs->devs, devs) + if (dev == rd) + return rs; + } + } + } return NULL; } -/* Check metadata consistency of raid sets. */ -static void check_raid_sets(struct lib_context *lc) +/* Check metadata consistency of RAID sets. */ +static void +check_raid_sets(struct lib_context *lc) { struct list_head *elem, *tmp; struct raid_set *rs; @@ -874,7 +1000,9 @@ return; } -int group_set(struct lib_context *lc, char *name) +/* Build RAID sets from devices on global RD list. */ +static int +build_set(struct lib_context *lc, char *name) { struct raid_dev *rd; struct raid_set *rs; @@ -906,14 +1034,571 @@ /* Check sanity of grouped RAID sets. */ check_raid_sets(lc); + return 1; +} + +struct raid_set_descr { + char *name; + uint64_t size; + char *raid_level; + uint64_t stripe_size; + char *disks; + //uint8_t num_disks; + //struct list_head *disks; +}; + +/* RAID set creation options. */ +static struct option rs_lopts[] = { + { "size", required_argument, NULL, 's'}, + { "type", required_argument, NULL, 'r'}, + { "str", required_argument, NULL, 't'}, + { "stri", required_argument, NULL, 't'}, + { "strip", required_argument, NULL, 't'}, + { "strid", required_argument, NULL, 't'}, + { "disk", required_argument, NULL, 'd'}, + { "disks", required_argument, NULL, 'd'}, + { NULL, no_argument, NULL, 0}, +}; + +#define RAIDLEVEL_INVALID 0xff +#define MAX_STACK 16 +static enum type +check_raid_level(char *raidlevel) +{ + int len, i; + + if (raidlevel == NULL) + return t_undef; + + for (i = 0, len = strlen(raidlevel); i < len; i++) { + if (!isdigit(raidlevel[i])) + return t_undef; + } + + if (i > MAX_STACK) + return t_undef; + + return t_raid0; +} + +static int +check_size(char *size) +{ + int c; + size_t len; + char *pEnd; + + if (!size) + return 0; + + len = strlen(size); + strtod(size, &pEnd); + + /* No unit. */ + if (size + len == pEnd) + return 1; + + /* Check units. */ + c = tolower(size[len - 1]); + if (c == 'b') + len--; + + c = tolower(size[len - 1]); + if (c == 'k' || c == 'm' || c == 'g') + len--; + + return size + len == pEnd ? 1 : 0; +} + +/* + * The unit of a raid size can be byte(b) or block(B)(512 bytes) + * k=1024 and m=1024*1024 or g=1024*1024*1024. + * + * Return size in byte + */ +static uint64_t +get_raid_size(char *rsp) +{ + char *pEnd, *pSizeUnit; + double dRsp; + uint64_t mul = 1; + + if ((dRsp = strtod(rsp, &pEnd)) <= 0) + dRsp = 0; + + if ((pSizeUnit = strpbrk(pEnd, "kKmMgG"))) { + switch (tolower(*pSizeUnit)) { + case 'g': + mul *= 1024; + case 'm': + mul *= 1024; + case 'k': + mul *= 1024; + } + } + + if ((pSizeUnit = strpbrk(pEnd, "bB"))) { + if (*pSizeUnit == 'B') + mul *= 512; + } + + return (uint64_t) (dRsp * mul); +} + +/* Parse RAID set creation arguments. */ +int +parse_rs_args(struct lib_context *lc, char **argv, struct raid_set_descr *rsd) +{ + int o, n, opt_idx; + + optind = 0; + rsd->raid_level = NULL; + rsd->size = 0; + rsd->stripe_size = 0; + rsd->disks = NULL; + + /* set rsd structure for spare disk set */ + if (OPT_HOT_SPARE_SET(lc)) { + rsd->name = (char *) OPT_STR_HOT_SPARE_SET(lc); + rsd->raid_level = (char *) SPARE_TYPE_STRING; + rsd->disks = (char *) OPT_STR_REBUILD_DISK(lc); + } else { + if (!argv[0] || !*argv[0]) + LOG_ERR(lc, 0, + "failed to provide a valid RAID set name"); + + /* Handle the case -Cname. */ + rsd->name = strstr(argv[0], "-C") ? argv[0] + 2 : argv[0]; + + for (n = 0; *(argv + n); n++); + if (n < 4) + LOG_ERR(lc, 0, "too few arguments"); + + while ((o = getopt_long(n, argv, ":", + rs_lopts, &opt_idx)) != -1) { + switch (o) { + case 's': + if (!check_size(optarg)) + LOG_ERR(lc, 0, "failed to config size"); + + if (!rsd->size) + rsd->size = get_raid_size(optarg); + break; + + case 'r': + if (!rsd->raid_level) + rsd->raid_level = optarg; + break; + + case 't': + if (!check_size(optarg)) + LOG_ERR(lc, 0, + "failed to config stripe"); + + if (!rsd->stripe_size) + rsd->stripe_size = + get_raid_size(optarg); + break; + + case 'd': + if (!rsd->disks) + rsd->disks = optarg; + break; + + case '?': + LOG_ERR(lc, 0, "unknown option"); + } + } + } + + return 1; +} + +struct dev_info * +find_disk(struct lib_context *lc, char *dp) +{ + struct dev_info *di; + + if ((dp == NULL) || (*dp == '\0')) + LOG_ERR(lc, 0, "failed to provide an array of disks"); + + + list_for_each_entry(di, LC_DI(lc), list) { + if (!strcmp(di->path, dp)) + return di; + } + + return NULL; +} + +static struct dmraid_format * +find_format(struct lib_context *lc, const char *cp) +{ + struct format_list *fl; + + if (cp == NULL) + LOG_ERR(lc, 0, "format handler string is NULL"); + + + list_for_each_entry(fl, LC_FMT(lc), list) { + if (!(strcmp(fl->fmt->name, cp))) + return fl->fmt; + } + return NULL; +} + +/* + * Remove the first digit and return a raid type according to the + * value of the first digit. + */ +static enum type +get_raid_level(char **rl) +{ + char c; + struct raid_type { + char c; + enum type level; + }; + static struct raid_type rts[] = { + { '0', t_raid0 }, + { '1', t_raid1 }, + { '4', t_raid4 }, + { '5', t_raid5_la }, /* FIXME: other RAID5 algorithms? */ + { '6', t_raid6 }, + { '8', t_spare }, /* FIXME: Intel abuse of raid char. */ + }; + struct raid_type *rt = ARRAY_END(rts); + + if (rl && *rl) { + c = **rl; + (*rl)++; + + while (rt-- > rts) { + if (rt->c == c) + return rt->level; + } + } + + return t_undef; +} + +#define MAX_NAME_LEN 15 +static int +check_rsd(struct lib_context *lc, struct raid_set_descr *rsd) +{ + uint16_t i, len; + + if (!find_format(lc, OPT_STR_FORMAT(lc))) + LOG_ERR(lc, 0, "unknown format type: %s", + lc->options[LC_FORMAT].arg.str); + + if (check_raid_level(rsd->raid_level) == t_undef) + LOG_ERR(lc, 0, "failed to provide a valid RAID type"); + + /* do not check name set, if it is spare set without name */ + if (!((rsd->name == NULL) && + !(strcmp(rsd->raid_level, SPARE_TYPE_STRING)))) { + + if ((len = strlen(rsd->name)) > MAX_NAME_LEN) + LOG_ERR(lc, 0, "name %s is longer than %d chars", + rsd->name, MAX_NAME_LEN); + + if (len == 0) + LOG_ERR(lc, 0, "no RAID set name provided"); + else if (!isalnum(rsd->name[0])) + LOG_ERR(lc, 0, "first character of a name must " + "be an alphanumeric charater"); + + for (i = 1; i < len; i++) { + if ((!isalnum(rsd->name[i])) + && (rsd->name[i] != '_') + && (rsd->name[i] != '-')) + LOG_ERR(lc, 0, "name %s has non-alphanumeric " + "characters", rsd->name); + } + } + + if ((rsd->disks == NULL) || (*(rsd->disks) == 0)) + LOG_ERR(lc, 0, "no hard drives specified"); + + return 1; +} + +static void +free_raidset(struct lib_context *lc, struct raid_set *rs) +{ + struct raid_set *rs1; + + if (SETS(rs)) { + rs1 = list_entry(rs->sets.next, struct raid_set, list); + free_raidset(lc, rs1); + } + if (rs) + _free_raid_set(lc, rs); +} + +struct raid_dev * +find_raiddev(struct lib_context *lc, struct raid_set *rs, struct dev_info *di) +{ + struct raid_dev *rd; + + if (di == NULL) + LOG_ERR(lc, 0, "failed to provide dev info"); + + list_for_each_entry(rd, &rs->devs, devs) { + if (rd->di == di) + return rd; + } + + return NULL; +} + +struct raid_set * +create_raidset(struct lib_context *lc, struct raid_set_descr *rsd) +{ + struct raid_set *rs, *rs_sub, *rs_tmp; + struct dev_info *di; + struct raid_dev *rd; + struct dmraid_format *fmt; + enum type rt; + int n = 0; + char *start, *end; + + if (!check_rsd(lc, rsd)) + return NULL; + + if (!(rs = alloc_raid_set(lc, __func__))) + return NULL; + + /* case if it is spare disk set without name */ + if (!rsd->name + && !(strcmp(rsd->raid_level, SPARE_TYPE_STRING))) { + rs->name = NULL; + } else { + if (!(rs->name = dbg_strdup(rsd->name))) + goto err; + } + + /* the format type has been checked by check_rsd */ + fmt = find_format(lc, OPT_STR_FORMAT(lc)); + /* + * The raid level has been checked at the function check_rsd. + * Use get_raid_level to remove the first digit from the string. + */ + rt = get_raid_level(&rsd->raid_level); + + if (rsd->size) + rs->size = (rsd->size - 1) / 512 + 1; + + if (rsd->stripe_size) + rs->stride = (rsd->stripe_size - 1) / 512 + 1; + + rs->type = rt; + rs->flags = 0; + rs->status = s_init; + end = rsd->disks; + replace_delimiter(end, ',', ' '); + remove_tail_space(end); + + do { + start = end; + /* skip space */ + for (; *start == ' '; start++); + end = remove_delimiter(start, ' '); + + if (!(di = find_disk(lc, start))) { + log_err(lc, "failed to find disk %s", start); + goto err; + } + + /* check if device is not duplicated on the raid dev list */ + if (find_raiddev(lc, rs, di)) { + log_err(lc, "disk %s is duplicated on the disk list", + di->path); + goto err; + } + + if (!(rd = alloc_raid_dev(lc, __func__))) { + log_err(lc, "failed to allocate space for a raid_dev"); + goto err; + } + + rd->name = NULL; + rd->di = di; + rd->fmt = fmt; + rd->status = s_init; + rd->type = t_undef; + rd->offset = 0; + rd->sectors = 0; + list_add_tail(&rd->devs, &rs->devs); + n++; + } while (end++ != '\0'); + + rs->total_devs = rs->found_devs = n; + rs_tmp = rs; + + /* + * If there is a stacked RAID set, all sub sets are + * created and only the type is required to set + */ + while (*rsd->raid_level) { + if ((!(rt = get_raid_level(&rsd->raid_level))) || + !(rs_sub = alloc_raid_set(lc, __func__))) + goto err; + + rs_sub->type = rt; + list_add_tail(&rs_sub->list, &rs_tmp->sets); + rs_tmp = rs_sub; + } + + return rs; + + err: + free_raidset(lc, rs); + return NULL; +} + + +int +rebuild_config_raidset(struct lib_context *lc, struct raid_set *rs) +{ + + struct raid_dev *rd; + struct raid_set *rs1 = NULL; + struct list_head *elem, *tmp; + struct dmraid_format *fmt; + int ret = 0; + + if (!(fmt = (RD_RS(rs)->fmt))) + return 0; + + if (!(fmt->create)) + LOG_ERR(lc, 0, + "metadata creation isn't supported in \"%s\" format", + fmt->name); + + if ((ret = fmt->create(lc, rs)) && (printf("no write_set\n"), 1)) { /* (ret=write_set(lc, rs)) */ + /* free rebuilded RAID set and then reconstr */ + free_raid_set(lc, rs); + list_for_each_safe(elem, tmp, LC_RD(lc)) { + //list_del(elem); + rd = RD(elem); + rd->status = s_ok; + if (!(rs1 = dmraid_group(lc, rd))) + LOG_ERR(lc, 0, + "failed to build the created RAID set"); + want_set(lc, rs1, rs->name); + } + if (rs1) + fmt->check(lc, rs1); + } return 1; } +static int +config_raidset(struct lib_context *lc, struct raid_set *rs) +{ + struct raid_dev *rd; + struct raid_set *rs1 = NULL; + struct list_head *elem, *tmp; + struct dmraid_format *fmt; + int ret = 0; + + if (!(fmt = RD_RS(rs)->fmt)) + return 0; + + if (!fmt->create) + LOG_ERR(lc, 0, + "metadata creation isn't supported in \"%s\" format", + fmt->name); + + if ((ret = fmt->create(lc, rs)) && (ret = write_set(lc, rs))) { + free_raid_set(lc, NULL); + + list_for_each_safe(elem, tmp, &rs->devs) { + list_del(elem); + rd = RD(elem); + rd->status = s_ok; + + if (!(rs1 = dmraid_group(lc, rd))) + LOG_ERR(lc, 0, + "failed to build the created RAID set"); + + want_set(lc, rs1, rs->name); + } + + if (rs1) + fmt->check(lc, rs1); + } + + free_raidset(lc, rs); + return ret; +} + + +int +group_set(struct lib_context *lc, char **argv) +{ + char **sets = argv; + int i = 0; + struct raid_set_descr rsd; + struct raid_set *rs; + + /* This is valid if name of RAID set is required. */ + if (!OPT_HOT_SPARE_SET(lc) && !OPT_STR_HOT_SPARE_SET(lc)) { + if (!build_set(lc, sets[i])) + LOG_ERR(lc, 0, "failed to build a RAID set"); + + /* The required RAID set is found. */ + if (!list_empty(LC_RS(lc))) + return 1; + + /* There is no way for add spare disk to RAID set. */ + if (!OPT_FORMAT(lc) && + OPT_REBUILD_DISK(lc) && OPT_HOT_SPARE_SET(lc)) + return 0; + + /* + * Since there are several arguments required for + * creating a RAID set, we know that the intented command is to list all RAID sets. + */ + if (!sets[0]) + LOG_ERR(lc, 0, "no RAID set found"); + + } + + /* This is not argument for creating spare RAID set. */ + if (!OPT_HOT_SPARE_SET(lc)) { + /* + * Make sure we have min arguments for creating a RAID set: + * a name and an option. + */ + if (!sets[1]) + LOG_ERR(lc, 0, + "either the required RAID set not found or more options required"); + + if (sets[1][0] != '-') + LOG_ERR(lc, 0, + "only one argument allowed for this option"); + } + + if (!parse_rs_args(lc, argv, &rsd)) + return 0; + + if (!build_set(lc, NULL)) + LOG_ERR(lc, 0, "failed to get the existing RAID set info"); + + if (!(rs = create_raidset(lc, &rsd))) + return 0; + + return config_raidset(lc, rs); +} + /* Process function on RAID set(s) */ -static void process_set(struct lib_context *lc, void *rs, - int (*func)(struct lib_context *lc, void *rs, int arg), - int arg) +static void +process_set(struct lib_context *lc, void *rs, + int (*func) (struct lib_context * lc, void *rs, int arg), int arg) { if (!partitioned_set(lc, rs)) func(lc, rs, arg); @@ -922,28 +1607,30 @@ /* FIXME: remove partition code in favour of kpartx ? */ static void process_partitioned_set(struct lib_context *lc, void *rs, - int (*func)(struct lib_context *lc, void *rs, int arg), - int arg) + int (*func) (struct lib_context * lc, void *rs, + int arg), int arg) { if (partitioned_set(lc, rs) && !base_partitioned_set(lc, rs)) func(lc, rs, arg); } -void process_sets(struct lib_context *lc, - int (*func)(struct lib_context *lc, void *rs, int arg), - int arg, enum set_type type) +void +process_sets(struct lib_context *lc, + int (*func) (struct lib_context * lc, void *rs, int arg), + int arg, enum set_type type) { struct raid_set *rs; - void (*p)(struct lib_context *l, void *r, - int (*f)(struct lib_context *lc, void *rs, int arg), int a) = + void (*p) (struct lib_context * l, void *r, + int (*f) (struct lib_context * lc, void *rs, int arg), + int a) = (type == PARTITIONS) ? process_partitioned_set : process_set; - list_for_each_entry(rs, LC_RS(lc), list) - p(lc, rs, func, arg); + list_for_each_entry(rs, LC_RS(lc), list) p(lc, rs, func, arg); } /* Write RAID set metadata to devices. */ -int write_set(struct lib_context *lc, void *v) +int +write_set(struct lib_context *lc, void *v) { int ret = 1; struct raid_set *r, *rs = v; @@ -953,10 +1640,11 @@ list_for_each_entry(r, &rs->sets, list) { /* * FIXME: does it make sense to try the rest of the subset - * in case we fail writing one ? + * in case we fail writing one ? */ - if (!write_set(lc, (void*) r)) - log_err(lc, "writing RAID subset \"%s\", continuing", + if (!write_set(lc, (void *) r)) + log_err(lc, + "writing RAID subset \"%s\", continuing", r->name); } @@ -964,10 +1652,11 @@ list_for_each_entry(rd, &rs->devs, devs) { /* * FIXME: does it make sense to try the rest of the - * devices in case we fail writing one ? + * devices in case we fail writing one ? */ if (!write_dev(lc, rd, 0)) { - log_err(lc, "writing RAID device \"%s\", continuing", + log_err(lc, + "writing RAID device \"%s\", continuing", rd->di->path); ret = 0; } @@ -977,7 +1666,8 @@ } /* Erase ondisk metadata. */ -int erase_metadata(struct lib_context *lc) +int +erase_metadata(struct lib_context *lc) { int ret = 1; struct raid_dev *rd; @@ -1001,7 +1691,8 @@ * * Return neutralized RAID type for given mapping array (linear, raid0, ...) */ -enum type rd_type(struct types *t, unsigned int type) +enum type +rd_type(struct types *t, unsigned int type) { for (; t->unified_type != t_undef && t->type != type; t++); return t->unified_type; @@ -1012,9 +1703,13 @@ * * Return neutralized RAID status for given metadata status */ -enum status rd_status(struct states *s, unsigned int status, enum compare cmp) +enum status +rd_status(struct states *s, unsigned int status, enum compare cmp) { - for (; s->status && (cmp == AND ? !(s->status & status) : (s->status != status)); s++); + for (; + s->status + && (cmp == + AND ? !(s->status & status) : (s->status != status)); s++); return s->unified_status; } @@ -1024,10 +1719,10 @@ * Sort an element into a list by optionally * using a metadata format handler helper function. */ -void list_add_sorted(struct lib_context *lc, - struct list_head *to, struct list_head *new, - int (*f_sort)(struct list_head *pos, - struct list_head *new)) +void +list_add_sorted(struct lib_context *lc, + struct list_head *to, struct list_head *new, + int (*f_sort) (struct list_head * pos, struct list_head * new)) { struct list_head *pos; @@ -1055,14 +1750,16 @@ * File RAID metadata and offset on device for analysis. */ /* FIXME: all files into one directory ? */ -static size_t __name(struct lib_context *lc, char *str, size_t len, - const char *path, const char *suffix) +static size_t +__name(struct lib_context *lc, char *str, size_t len, + const char *path, const char *suffix) { return snprintf(str, len, "%s.%s", - get_basename(lc, (char*) path), suffix) + 1; + get_basename(lc, (char *) path), suffix) + 1; } -static char *_name(struct lib_context *lc, const char *path, const char *suffix) +static char * +_name(struct lib_context *lc, const char *path, const char *suffix) { size_t len; char *ret; @@ -1075,8 +1772,9 @@ return ret; } -static int file_data(struct lib_context *lc, const char *handler, - char *path, void *data, size_t size) +static int +file_data(struct lib_context *lc, const char *handler, + char *path, void *data, size_t size) { int ret = 0; char *name; @@ -1090,21 +1788,23 @@ return ret; } -static void file_number(struct lib_context *lc, const char *handler, - char *path, uint64_t number, const char *suffix) +static void +file_number(struct lib_context *lc, const char *handler, + char *path, uint64_t number, const char *suffix) { char *name, s_number[32]; - + if ((name = _name(lc, path, suffix))) { log_notice(lc, "writing %s to file \"%s\"", suffix, name); - write_file(lc, handler, name, (void*) s_number, - snprintf(s_number, sizeof(s_number), - "%" PRIu64 "\n", number), 0); + write_file(lc, handler, name, (void *) s_number, + snprintf(s_number, sizeof(s_number), + "%" PRIu64 "\n", number), 0); dbg_free(name); } } -static int _chdir(struct lib_context *lc, const char *dir) +static int +_chdir(struct lib_context *lc, const char *dir) { if (chdir(dir)) { log_err(lc, "changing directory to %s", dir); @@ -1114,7 +1814,8 @@ return 0; } -static char *_dir(struct lib_context *lc, const char *handler) +static char * +_dir(struct lib_context *lc, const char *handler) { char *dir = _name(lc, lc->cmd, handler); @@ -1129,7 +1830,7 @@ if (!_chdir(lc, dir)) return dir; - out: + out: dbg_free(dir); return NULL; } @@ -1137,8 +1838,9 @@ /* * File vendor RAID metadata. */ -void file_metadata(struct lib_context *lc, const char *handler, - char *path, void *data, size_t size, uint64_t offset) +void +file_metadata(struct lib_context *lc, const char *handler, + char *path, void *data, size_t size, uint64_t offset) { if (OPT_DUMP(lc)) { char *dir = _dir(lc, handler); @@ -1158,8 +1860,8 @@ /* * File RAID device size. */ -void file_dev_size(struct lib_context *lc, const char *handler, - struct dev_info *di) +void +file_dev_size(struct lib_context *lc, const char *handler, struct dev_info *di) { if (OPT_DUMP(lc)) { char *dir = _dir(lc, handler); @@ -1173,3 +1875,307 @@ _chdir(lc, ".."); } } + +/* Delete RAID set(s) */ +int +delete_raidsets(struct lib_context *lc) +{ + struct raid_set *rs, *rs1; + struct raid_dev *rd; + int n = 0, status; + + if (list_empty(&(lc->lists[LC_RAID_SETS]))) + LOG_ERR(lc, 0, "Cannot find a RAID set to delete"); + + list_for_each_entry(rs, LC_RS(lc), list) { + if (!(rd = list_entry(rs->devs.next, struct raid_dev, devs))) + LOG_ERR(lc, 0, "Failed to locate the raid device"); + + if (rs->type == t_group) { + list_for_each_entry(rs1, &rs->sets, list) { + status = dm_status(lc, rs1); + if (status == 1) + LOG_ERR(lc, 0, + "%s is active and cannot be deleted", + rs1->name); + + n++; + } + if (n > 1) { + printf("\nAbout to delete the raid super-set \"%s\" with the following RAID sets\n", rs->name); + list_for_each_entry(rs1, &rs->sets, list) + printf("%s\n", rs1->name); + } + else if (n == 1) { + rs1 = list_entry(rs->sets.next, + struct raid_set, list); + printf("\nAbout to delete RAID set %s\n", + rs1->name); + } + else + LOG_ERR(lc, 0, "coding error"); + } + else { + printf("\nAbout to delete RAID set %s\n", rs->name); + } + printf("\nWARNING: The metadata stored on the raidset(s) will not be accessible after deletion\n"); + if (!yes_no_prompt(lc, "Do you want to continue")) + return 0; + + if (!rd->fmt->delete) + LOG_ERR(lc, 0, + "Raid set deletion is not supported in \"%s\" format", + rd->fmt->name); + + rd->fmt->delete(lc, rs); + + } + + return 1; +} + +struct raid_set *find_set_inconsistent(struct lib_context *lc, + struct raid_set *rs); + +struct raid_dev *find_spare(struct lib_context *lc, + struct raid_set *rs2rebuild, + struct raid_set **spareRs); + +struct raid_set * +find_set_inconsistent(struct lib_context *lc, struct raid_set *rs) +{ + struct raid_set *r, *rsb; + + list_for_each_entry(r, &rs->sets, list) { + if (T_GROUP(r) && !(rsb = find_set_inconsistent(lc, r))) + return rsb; + } + + return (DEVS(rs) && + (S_BROKEN(rs->status) || S_INCONSISTENT(rs->status))) ? + rs : NULL; + +} + + +/* + * Search for spare drive that can be used to fix given rs. + * + * Returns spare raid_dev and its spare RAID set. + * Based on format configuration searches: + * localy (in RAID set that shall be fixed) + * globaly (any spare drive that can be used to fix rs) + */ +struct raid_dev * +find_spare(struct lib_context *lc, struct raid_set *rs, + struct raid_set **spare_rs) +{ + struct raid_dev *closest = NULL, *spare_rd, *rd = NULL; + struct raid_set *rs_failed = NULL, *tmp_spare_rs = NULL; + struct dmraid_format *fmt = get_format(rs); + + /* Find rd that will be evaluated for replacement. */ + + /* Search the spare sets for eligible disk. */ + if (!(rs_failed = find_set_inconsistent(lc, rs)) || + !(rd = RD_RS(rs_failed))) + LOG_PRINT(lc, NULL, + "no failed subsets or no device in subset found"); + + + /* Local search - based on fmt. */ + if (fmt->scope & t_scope_local) { + struct raid_set *group_rs = find_group(lc, rs); + + if (!group_rs) + return NULL; + + list_for_each_entry(tmp_spare_rs, &group_rs->sets, list) { + if (DEVS(tmp_spare_rs) && T_SPARE(tmp_spare_rs)) { + list_for_each_entry(spare_rd, + &tmp_spare_rs->devs, devs) { + /* Simple check of size */ + if (spare_rd->di->sectors >= + rd->di->sectors && + (!closest || + closest->di->sectors < + rd->di->sectors)) { + if (spare_rd->di->sectors == + rd->di->sectors) { + /* Match */ + closest = spare_rd; + break; + } + + closest = spare_rd; + } + } + } + } + } + + /* Global search - based on fmt */ + if ((fmt->scope & t_scope_global) && !closest) { + struct raid_set *group_rs; + + list_for_each_entry(group_rs, LC_RS(lc), list) { + if (T_GROUP(group_rs) + && (get_format(group_rs) == fmt)) { + list_for_each_entry(tmp_spare_rs, + &group_rs->sets, list) { + if ((DEVS(tmp_spare_rs)) && + T_SPARE(tmp_spare_rs)) { + list_for_each_entry(spare_rd, &tmp_spare_rs->devs, devs) { + /* Simple check of size. */ + if ((spare_rd->di->sectors >= rd->di->sectors) && + (!closest == NULL || + closest->di->sectors < rd->di->sectors)) { + if (spare_rd->di->sectors == rd->di->sectors) { + /* match */ + closest = spare_rd; + break; + } + + closest = spare_rd; + } + } + } + } + } + } + } + + /* Global search. */ + if (closest) { + *spare_rs = get_raid_set(lc, closest); + return closest; + } + + /* spare not found */ + return NULL; +} + + +void +format_error(struct lib_context *lc, const char *error, char **argv) +{ + log_print_nnl(lc, "no raid %s", error); + + if (OPT_FORMAT(lc)) + log_print_nnl(lc, " with format: \"%s\"", OPT_STR_FORMAT(lc)); + + + if (argv && *argv) { + log_print_nnl(lc, " and with names: \""); + + while (*argv) { + log_print_nnl(lc, "%s", *argv++); + if (*argv) + log_print_nnl(lc, "%s", OPT_STR_SEPARATOR(lc)); + else + log_print_nnl(lc, "\""); + } + } + + log_print(lc, ""); +} + +/* Retrieve and build metadata. */ +static int +get_metadata(struct lib_context *lc, enum action action, + struct prepost *p, char **argv) +{ + if (!(M_DEVICE & p->metadata)) + return 1; + + if (!discover_devices(lc, OPT_DEVICES(lc) ? argv : NULL)) + LOG_ERR(lc, 0, "failed to discover devices"); + + if (!count_devices(lc, DEVICE)) { + log_print(lc, "no block devices found"); + return 1; + } + + if (!(M_RAID & p->metadata)) + return 1; + +#ifndef DMRAID_MINI + /* Discover RAID disks and keep RAID metadata (eg, hpt45x) */ + discover_raid_devices(lc, +# ifdef DMRAID_NATIVE_LOG + ((NATIVE_LOG | RAID_DEVICES) & action) ? argv + : NULL); +# else + (RAID_DEVICES & action) ? argv : NULL); +# endif +#else + discover_raid_devices(lc, NULL); +#endif + + if (!OPT_HOT_SPARE_SET(lc) && !OPT_CREATE(lc) + && !count_devices(lc, RAID)) { + format_error(lc, "disks", argv); + return 1; + } + + if (M_SET & p->metadata) { + /* Group RAID sets. */ + group_set(lc, argv); + if (!OPT_HOT_SPARE_SET(lc) && !OPT_CREATE(lc) + && !count_devices(lc, SET)) { + format_error(lc, "sets", argv); + return 0; + } + } + + return 1; +} + + +int +lib_perform(struct lib_context *lc, enum action action, + struct prepost *p, char **argv) +{ + int ret = 0; + + if (ROOT == p->id && geteuid()) + LOG_ERR(lc, 0, "you must be root"); + + /* Lock against parallel runs. Resource NULL for now. */ + if (LOCK == p->lock && !lock_resource(lc, NULL)) + LOG_ERR(lc, 0, "lock failure"); + + if (get_metadata(lc, action, p, argv)) + ret = p->post(lc, p->pre ? p->pre(p->arg) : p->arg); + + if (LOCK == p->lock) + unlock_resource(lc, NULL); + + return ret; +} + +int +dso_get_members(struct lib_context *lc, int arg) +{ + static char disks[100] = "\0"; + const char *vol_name = lc->options[LC_REBUILD_SET].arg.str; + struct raid_set *sub_rs; + struct raid_dev *rd; + + if ((sub_rs = find_set(lc, NULL, vol_name, FIND_ALL))) { + lc->options[LC_REBUILD_SET].opt = 0; + + list_for_each_entry(rd, &sub_rs->devs, devs) { + strcat(disks, rd->di->path); + strcat(disks, " "); + lc->options[LC_REBUILD_SET].opt++; + } + + dbg_free((char *) lc->options[LC_REBUILD_SET].arg.str); + lc->options[LC_REBUILD_SET].arg.str = dbg_strdup(disks); + return 0; + } + else + /* RAID set not found. */ + return 1; +} --- dmraid/lib/metadata/reconfig.c 2008/02/22 17:04:36 1.1 +++ dmraid/lib/metadata/reconfig.c 2008/06/20 21:52:18 1.2 @@ -4,113 +4,354 @@ * James Simshaw <simshawj@xxxxxxxxxx>, and * Adam DiCarlo <bikko@xxxxxxxxxx> * - * Copyright (C) 2006 Heinz Mauelshagen, Red Hat GmbH - * All rights reserved + * Copyright (C) 2006-2008 Heinz Mauelshagen, Red Hat GmbH + * All rights reserved + * + * Copyright (C) 2007 Intel Corporation. All rights reserved. + * November, 2007 - additions for Create, Delete, Rebuild & Raid 10. * * See file LICENSE at the top of this source tree for license information. */ #include "internal.h" +int dso = 0; #define add_to_log(entry, log) \ list_add_tail(&(entry)->changes, &(log)); -static inline int alloc_entry(struct change **entry) +static inline int +alloc_entry(struct change **entry, struct lib_context *lc) { - return (*entry = dbg_malloc(sizeof (*entry))) ? 0 : -ENOMEM; + return (*entry = dbg_malloc(sizeof(*entry))) ? 0 : -ENOMEM; } -static int nuke_spare(struct lib_context *lc, struct raid_dev *rd) +static int +nuke_spare(struct lib_context *lc, struct raid_dev *rd) { printf("Nuking Spare\n"); list_del_init(&rd->devs); return 0; } -/* Add a device to a RAID1 set and start the resync */ -static int add_dev_to_raid1(struct lib_context *lc, struct raid_set *rs, - struct raid_dev *rd) +int +dso_end_rebuild(struct lib_context *lc, int arg) { - int ret; - struct raid_dev *tmp; - struct change *entry; - LIST_HEAD(log); /* playback log */ + struct raid_set *sub_rs; + const char *vol_name = lc->options[LC_REBUILD_SET].arg.str; - /* Add device to the raid set */ - ret = alloc_entry(&entry); - if (ret) - goto err; + sub_rs = find_set(lc, NULL, vol_name, FIND_ALL); + if (sub_rs) { + struct raid_set *rs = NULL; + + rs = find_group(lc, sub_rs); + if ((rs) && S_OK(sub_rs->status)) { + struct raid_dev *check_rd = RD_RS(sub_rs); + enum status state = s_ok; + + if (check_rd->fmt->metadata_handler) + state = check_rd->fmt->metadata_handler(lc, + GET_REBUILD_STATE, + NULL, + (void *) + sub_rs); + + if (state != s_nosync) { + /* cannot rebuild */ + log_print(lc, + "Volume \"%s\" is not in rebuild state (current: %u)\n", + sub_rs->name, state); + return 1; + } + + if (check_rd->fmt->metadata_handler) + check_rd->fmt->metadata_handler(lc, + UPDATE_REBUILD_STATE, + NULL, + (void *) rs); + } else { + log_print(lc, + "Volume \"%s\" is not in rebuild state \n", + vol_name); + return 1; + } + } else + log_print(lc, "raid volume \"%s\" not found\n", vol_name); - entry->type = ADD_TO_SET; - entry->rs = rs; - entry->rd = rd; - add_to_log(entry, log); - list_add_tail(&rd->devs, &rs->devs); - rd->type = t_raid1; + return 0; +} - /* Check that this is a sane configuration */ - list_for_each_entry(tmp, &rs->devs, devs) { - ret = tmp->fmt->check(lc, rs); - if (ret) - goto err; +int rebuild_config_raidset(struct lib_context *lc, struct raid_set *rs); + +void +show_raid_stack(struct lib_context *lc) +{ + struct raid_set *_rs; + log_dbg(lc, "RM: Discovered raid sets:"); + list_for_each_entry(_rs, LC_RS(lc), list) { + struct raid_dev *_rd; + struct raid_set *_rss; + log_dbg(lc, "RM: GROUP name: \"%s\"", _rs->name); + list_for_each_entry(_rd, &_rs->devs, devs) { + log_dbg(lc, "RM: GROUP_DISK name: \"%s\"", + (_rd->di) ? _rd->di->path : "UNKNOWN"); + } + list_for_each_entry(_rss, &_rs->sets, list) { + struct raid_dev *_rsd; + struct raid_set *_rsss; + + log_dbg(lc, "RM: SUPERSET name: \"%s\"", _rss->name); + + list_for_each_entry(_rsd, &_rss->devs, devs) { + log_dbg(lc, "RM: SUPERSET_DISK name: \"%s\"", + (_rsd->di) ? _rsd-> + di->path : "UNKNOWN"); + } + + list_for_each_entry(_rsss, &_rss->sets, list) { + struct raid_dev *_rssd; + log_dbg(lc, "RM: SUBSET name: \"%s\"", + _rsss->name); + list_for_each_entry(_rssd, &_rsss->devs, devs) { + log_dbg(lc, + "RM: SUBSET_DISK name: \"%s\"", + (_rssd->di) ? _rssd-> + di->path : "UNKNOWN"); + } + } + } } +} - /* Write the metadata of the drive we're adding _first_ */ - ret = alloc_entry(&entry); - if (ret) - goto err; +/* Add a device to a RAID1 set and start the resync */ +static int +add_dev_to_raid(struct lib_context *lc, struct raid_set *rs, + struct raid_dev *rd) +{ + int ret = 0; + const char *vol_name = lc->options[LC_REBUILD_SET].arg.str; - entry->type = WRITE_METADATA; - entry->rd = rd; - add_to_log(entry, log); - ret = write_dev(lc, rd, 0); - if (!ret) - goto err; + struct raid_set *sub_rs, *crs; + struct raid_dev *check_rd; - /* Write metadatas of every device in the set */ - list_for_each_entry(tmp, &rs->devs, devs) { - if (tmp != rd) { - ret = alloc_entry(&entry); - if (ret) - goto err; - entry->type = WRITE_METADATA; - entry->rd = tmp; - add_to_log(entry, log); - ret = write_dev(lc, tmp, 0); - if (!ret) + LIST_HEAD(log); /* playback log */ + sub_rs = find_set(lc, NULL, vol_name, FIND_ALL); + check_rd = list_entry(rs->devs.next, typeof(*rd), devs); + + if (rd) { + if (check_rd->fmt->create) { + struct raid_dev *tmp; + if ((ret = check_rd->fmt->create(lc, rs))) { + + list_for_each_entry(tmp, &rs->devs, devs) { + write_dev(lc, tmp, 0); + } + } else { + log_print(lc, "metadata fmt update failed\n"); goto err; + } + } else { + log_print(lc, "create failed fmt handler missing\n"); + goto err; + } + + struct handler_info info; + + if (lc->options[LC_REBUILD_SET].opt) { + if (check_rd->fmt->metadata_handler) { + if (!check_rd-> + fmt->metadata_handler(lc, + GET_REBUILD_DRIVE_NO, + &info, + (void *) sub_rs)) { + LOG_ERR(lc, 0, + "can't get rebuild drive !"); + } + } } + + if (info.data.i32 != -1) { + struct raid_dev *before_rd, *tmp_rd; + int idx = 0; + list_for_each_entry_safe(before_rd, tmp_rd, + &sub_rs->devs, devs) { + if ((idx == info.data.i32) + && (&rd->devs != &before_rd->devs)) { + list_del(&rd->devs) + list_add_tail(&rd->devs, + &before_rd->devs); + break; + } + idx++; + } + } + show_raid_stack(lc); + log_dbg(lc, "RM: REBUILD drivie #: \"%d\"", info.data); + show_raid_stack(lc); } /* Reconfigure device mapper */ // FIXME: is nosync enough? rs->status |= s_inconsistent; - rs->status |= s_nosync; + rs->status = s_ok; + if ((sub_rs = find_set(lc, NULL, vol_name, FIND_ALL))) { + sub_rs->status = s_ok; + + list_for_each_entry(crs, &sub_rs->sets, list) + crs->status = s_ok; + } + change_set(lc, A_ACTIVATE, rs); + rs->status |= s_nosync; + + if ((sub_rs = find_set(lc, NULL, vol_name, FIND_ALL))) { + sub_rs->status |= s_nosync; + list_for_each_entry(crs, &sub_rs->sets, list) { + crs->status |= s_nosync; + } + } + ret = change_set(lc, A_RELOAD, rs); // FIXME: might need this later: change_set(lc, A_DEACTIVATE,rs); if (!ret) goto err; + if (!dso) { +#ifdef DMRAID_LED + struct raid_dev *_rd; + list_for_each_entry(_rd, &sub_rs->devs, devs) + led(strrchr(_rd->di->path, '/') + 1, LED_REBUILD); +#endif + + if (check_rd->fmt->metadata_handler) + check_rd->fmt->metadata_handler(lc, + UPDATE_REBUILD_STATE, + NULL, (void *) rs); + } + /* End transaction */ end_log(lc, &log); return 0; -err: + err: revert_log(lc, &log); return ret; } +struct dev_info *find_disk(struct lib_context *lc, char *dp); + +/* check if disk is under a raid set */ +int +check_busy_disk(struct lib_context *lc, struct raid_dev *check_rd) +{ + struct raid_dev *rd; + + if (!check_rd) + return 0; + + if (!check_rd->di) + return 0; + + list_for_each_entry(rd, LC_RD(lc), list) { + if (rd->di == check_rd->di) + return 0; + } + + return 1; +} + +int +add_dev_to_array(struct lib_context *lc, struct raid_set *rs, + uint build_metadata, struct raid_dev *hot_spare_rd) +{ + const char *set_name = lc->options[LC_REBUILD_SET].arg.str; + struct raid_dev *rd = NULL; + struct raid_set *sub_rs; + + if ((hot_spare_rd) || (build_metadata)) { + struct raid_dev tmp_rd; + struct raid_dev *new_rd = hot_spare_rd; + enum type type = t_raid1; + + sub_rs = find_set(lc, NULL, set_name, FIND_ALL); + if (sub_rs == NULL) { + log_print(lc, "Volume \"%s\" not found\n", set_name); + return 1; + } + + + type = sub_rs->type; + + if (new_rd == NULL) { + const char *disk_name = + lc->options[LC_REBUILD_DISK].arg.str; + + new_rd = &tmp_rd; + /* for non-hot-spare */ + if (!(new_rd->di = find_disk(lc, (char *) disk_name))) + LOG_ERR(lc, 0, "failed to find disk %s", + disk_name); + + /* check if disk is a member of another raid set */ + if (!(check_busy_disk(lc, new_rd))) + LOG_ERR(lc, 0, + "disk %s cannot be used to rebuilding", + disk_name); + + new_rd->fmt = get_format(rs); + } + + /* add a rd to group raid set */ + if ((rd = alloc_raid_dev(lc, "rebuild")) == NULL) + LOG_ERR(lc, 1, + "failed to allocate space for a raid_dev"); + + memset(rd, 0, sizeof(*rd)); + rd->name = NULL; + + rd->di = new_rd->di; + rd->fmt = new_rd->fmt; + + rd->status = s_init; + rd->type = type; + rd->offset = 0; + rd->sectors = 0; + + list_add_tail(&rd->list, LC_RD(lc)); + list_add_tail(&rd->devs, &rs->devs); + + /* add a spare to raid set */ + sub_rs = find_set(lc, NULL, set_name, FIND_ALL); + + if (!(rd = alloc_raid_dev(lc, __func__))) + LOG_ERR(lc, 1, + "failed to allocate space for a raid_dev"); + + rd->name = NULL; + rd->di = new_rd->di; + rd->fmt = new_rd->fmt; + rd->status = s_init; + rd->type = type; + rd->offset = 0; + rd->sectors = 0; + list_add_tail(&rd->devs, &sub_rs->devs); + sub_rs->total_devs++; + } + + add_dev_to_raid(lc, rs, rd); + return 0; +} + /* Remove a disk from a raid1 */ -static int del_dev_in_raid1(struct lib_context *lc, struct raid_set *rs, - struct raid_dev *rd) +static int +del_dev_in_raid1(struct lib_context *lc, struct raid_set *rs, + struct raid_dev *rd) { int ret; struct raid_dev *tmp; struct change *entry; - LIST_HEAD(log); /* Playback log */ + LIST_HEAD(log); /* Playback log */ /* Remove device from the raid set */ - ret = alloc_entry(&entry); + ret = alloc_entry(&entry, lc); if (ret) goto err; @@ -129,7 +370,7 @@ } /* Write the metadata of the drive we're removing _first_ */ - ret = alloc_entry(&entry); + ret = alloc_entry(&entry, lc); if (ret) goto err; @@ -145,7 +386,7 @@ if (tmp == rd) continue; - ret = alloc_entry(&entry); + ret = alloc_entry(&entry, lc); if (ret) goto err; @@ -168,7 +409,7 @@ end_log(lc, &log); return 0; -err: + err: revert_log(lc, &log); return ret; } @@ -176,13 +417,14 @@ /* Corelate type and function to handle addition/removel of RAID device */ struct handler { enum change_type type; - int (*func) (struct lib_context *lc, struct raid_set *rs, - struct raid_dev *rd); + int (*func) (struct lib_context * lc, struct raid_set * rs, + struct raid_dev * rd); }; /* Call the function to handle addition/removal of a RAID device */ -static int handle_dev(struct lib_context *lc, struct handler *h, - struct raid_set *rs, struct raid_dev *rd) +static int +handle_dev(struct lib_context *lc, struct handler *h, + struct raid_set *rs, struct raid_dev *rd) { do { if (h->type == rs->type) @@ -193,11 +435,11 @@ } /* Add a disk to an array. */ -int add_dev_to_set(struct lib_context *lc, struct raid_set *rs, - struct raid_dev *rd) +int +add_dev_to_set(struct lib_context *lc, struct raid_set *rs, struct raid_dev *rd) { struct handler handlers[] = { - {t_raid1, add_dev_to_raid1}, + {t_raid1, add_dev_to_raid}, {t_undef, NULL}, }; @@ -216,8 +458,8 @@ } /* Remove a disk from an array */ -int del_dev_in_set(struct lib_context *lc, struct raid_set *rs, - struct raid_dev *rd) +int +del_dev_in_set(struct lib_context *lc, struct raid_set *rs, struct raid_dev *rd) { struct handler handlers[] = { {t_raid1, del_dev_in_raid1}, @@ -235,3 +477,323 @@ return handle_dev(lc, handlers, rs, rd); } + +/* + * Find group of raid_set to which sub_rs belongs + * Serves one level stacked raids. + */ +struct raid_set * +find_group(struct lib_context *lc, struct raid_set *sub_rs) +{ + struct raid_set *tmp = NULL, *r = NULL, *r2 = NULL; + + list_for_each_entry(tmp, LC_RS(lc), list) { + if (T_GROUP(tmp)) { + list_for_each_entry(r, &tmp->sets, list) { + if (r == sub_rs) + return tmp; + else if (SETS(r)) { + list_for_each_entry(r2, &r->sets, list) { + if (r2 == sub_rs) + return tmp; + } + } + } + } + } + + /* Group not found. */ + return NULL; +} + +struct raid_dev *find_spare(struct lib_context *lc, struct raid_set *sub_rs, + struct raid_set **spare_set); + +int +_rebuild_raidset(struct lib_context *lc, struct raid_set *sub_rs, + char *set_name) +{ + struct raid_set *spare_set = NULL, *rs = NULL; + struct raid_dev *rd = NULL; + int driveRebuild = 1; + + rs = find_group(lc, sub_rs); + + /* raid 0 cannot be rebuild - exit */ + if (T_RAID0(sub_rs) && (!SETS(sub_rs))) { + log_print(lc, "Rebuild: raid0 cannot be rebuild\n"); + return 1; + } + /* FIXME - work-aroud for status reporting */ + if (S_BROKEN(sub_rs->status) || + S_INCONSISTENT(sub_rs->status)) { + if (lc->options[LC_REBUILD_DISK].opt == 0) { + /* find the spare drive */ + if ((rd = find_spare(lc, sub_rs, &spare_set)) == NULL) { + log_print(lc, + "Rebuild: a hot-spare drive not found for a volume: \"%s\"." + " Need a drive to rebuild a volume.\n", + sub_rs->name); + return 1; + } + + } + } else if (S_OK(sub_rs->status)) { + struct raid_dev *check_rd = RD_RS(sub_rs); + enum status state = s_ok; + + if (check_rd && (check_rd->fmt->metadata_handler)) + state = check_rd->fmt->metadata_handler(lc, + GET_REBUILD_STATE, + NULL, (void *) + sub_rs); + + if (state != s_nosync) { + /* cannot rebuild */ + log_print(lc, + "Volume \"%s\" is not in rebuild state (current: %u)", + sub_rs->name, state); + log_print(lc, + "Rebuild: cannot rebuild from current state!\n"); + return 1; + } + driveRebuild = 0; + } else if (!(S_NOSYNC(sub_rs->status))) { + /* cannot rebuild */ + log_print(lc, "Rebuild: cannot rebuild from current state!\n"); + return 1; + } + + + sub_rs->status = s_nosync; + rs->status = s_nosync; + + /* set the name for rebuild set (function down the path are using this variable to + * retrive the raid set that is rebuild + */ + + + dbg_free((char *) lc->options[LC_REBUILD_SET].arg.str); + lc->options[LC_REBUILD_SET].arg.str = + (const char *) dbg_malloc(strlen(sub_rs->name) + 1); + strcpy((char *) lc->options[LC_REBUILD_SET].arg.str, sub_rs->name); + + if (!(add_dev_to_array(lc, rs, + (driveRebuild + && lc->options[LC_REBUILD_DISK].opt) + || rd, rd))) { + log_dbg(lc, "rebuild: raid \"%s\" rebuild finished\n", + set_name); + } else { + /* error - raid failed to be rebuilded */ + log_print(lc, "Rebuild: raid \"%s\" rebuild failed\n", + set_name); + return 1; + } + return 0; +} + + +int +rebuild_raidset(struct lib_context *lc, char *set_name) +{ + struct raid_set *sub_rs = NULL; + int ret = 0; + + sub_rs = find_set(lc, NULL, set_name, FIND_ALL); + if (sub_rs) { + /* for stacked subsets go throu the stack to retrive the subsets that: + - do not contain subsets + - are eligible for rebuild + */ + if (SETS(sub_rs)) { + enum status curr_state = s_ok; + struct raid_set *r = NULL; + + /* check sub-set that are in Ok state */ + curr_state = s_ok; + + /* check for all subsets that have state equal curr_state */ + list_for_each_entry(r, &sub_rs->sets, list) { + if (r->status & curr_state) { + ret |= _rebuild_raidset(lc, r, + set_name); + } + } + + /* TBD change to s_inconsisten when the states are reported in right way */ + curr_state = s_broken | s_inconsistent; + list_for_each_entry(r, &sub_rs->sets, list) { + if (r->status & curr_state) { + ret |= _rebuild_raidset(lc, r, + set_name); + } + } + } else + ret |= _rebuild_raidset(lc, sub_rs, set_name); + + } else + log_print(lc, "raid volume \"%s\" not found\n", set_name); + + return ret; +} + + +int +write_set_spare(struct lib_context *lc, void *v) +{ + int ret = 1; + struct raid_set *r, *rs = v; + struct raid_dev *rd; + + /* Decend hierarchy */ + list_for_each_entry(r, &rs->sets, list) { + /* + * FIXME: does it make sense to try the rest of the subset + * in case we fail writing one ? + */ + if (!write_set_spare(lc, (void *) r)) + log_err(lc, "writing RAID subset \"%s\", continuing", + r->name); + } + + /* Write metadata to the RAID devices of a set */ + list_for_each_entry(rd, &rs->devs, devs) { + /* + * FIXME: does it make sense to try the rest of the + * devices in case we fail writing one ? + */ + if (!(T_GROUP(rs))) { + if (!write_dev(lc, rd, 0)) { + log_err(lc, + "writing RAID device \"%s\", continuing", + rd->di->path); + ret = 0; + } + } + } + + return ret; +} + + + +static int +add_spare_dev_to_raid(struct lib_context *lc, struct raid_set *rs) +{ + int ret = 0; + struct dmraid_format *fmt_hand; + + + /* find format handler */ + fmt_hand = get_format(rs); + + if (!(fmt_hand->create)) { + LOG_ERR(lc, 0, + "metadata creation is not supported in \"%s\" format", + fmt_hand->name); + } else { + if ((ret = fmt_hand->create(lc, rs))) + ret = write_set_spare(lc, rs); + + if (!ret) + log_print(lc, "metadata fmt update failed\n"); + } + + return ret; +} + +int +add_spare_dev_to_array(struct lib_context *lc, struct raid_set *rs) +{ + struct dev_info *di; + struct dmraid_format *fmt_hand; + struct raid_dev *rd; + struct raid_set *rs_sub; + + const char *disk_name = lc->options[LC_REBUILD_DISK].arg.str; + + + /* find format handler */ + fmt_hand = get_format(rs); + + /* add a spare rs to raid set */ + if (!(rs_sub = alloc_raid_set(lc, "rebuild"))) + return 0; + + rs_sub->name = NULL; + rs_sub->size = 0; + rs_sub->stride = 0; + rs_sub->type = t_spare; + rs_sub->flags = 0; + rs_sub->status = s_init; + list_add_tail(&rs_sub->list, &rs->sets); + + /* Find disk by name. */ + if (!(di = find_disk(lc, (char *) disk_name))) + LOG_ERR(lc, 0, "failed to find disk %s", disk_name); + + /* Add a rd to group raid set. */ + if ((rd = alloc_raid_dev(lc, "rebuild")) == NULL) + LOG_ERR(lc, 0, "failed to allocate space for a raid_dev"); + + rd->name = NULL; + rd->di = di; + rd->fmt = fmt_hand; + rd->status = s_init; + rd->type = t_spare; + rd->offset = 0; + rd->sectors = 0; + + /* add dev to lc list and to group rs */ + list_add_tail(&rd->list, LC_RD(lc)); + list_add_tail(&rd->devs, &rs->devs); + + if (!(rd = alloc_raid_dev(lc, "rebuild"))) + LOG_ERR(lc, 0, "failed to allocate space for a raid_dev"); + + rd->name = NULL; + rd->di = di; + rd->fmt = fmt_hand; + rd->status = s_init; + rd->type = t_spare; + rd->offset = 0; + rd->sectors = 0; + list_add_tail(&rd->devs, &rs_sub->devs); + return add_spare_dev_to_raid(lc, rs); +} + + +/* Add a disk to raid set as spare disk. */ +int +hot_spare_add(struct lib_context *lc, struct raid_set *rs) +{ + const char *vol_name = lc->options[LC_HOT_SPARE_SET].arg.str; + int ret_func; + struct dmraid_format *fmt_hand; + + + if (!(!OPT_FORMAT(lc) && + OPT_REBUILD_DISK(lc) && + OPT_HOT_SPARE_SET(lc))) + return 0; + + if (!(fmt_hand = get_format(rs))) + LOG_ERR(lc, 0, "unknown metadata format"); + + if (!(fmt_hand->metadata_handler)) + LOG_ERR(lc, 0, + "metadata_handler() is not supported in \"%s\" format", + fmt_hand->name); + + ret_func = fmt_hand->metadata_handler(lc, CHECK_HOT_SPARE, NULL, + (void *) rs); + + if (!ret_func) + LOG_ERR(lc, 0, + "hot-spare cannot be added to existing raid " + "set \"%s\" in \"%s\" format", + vol_name, fmt_hand->name); + + return add_spare_dev_to_array(lc, rs); +} --- dmraid/lib/misc/file.c 2008/02/22 17:04:36 1.2 +++ dmraid/lib/misc/file.c 2008/06/20 21:52:18 1.3 @@ -8,17 +8,18 @@ #include "internal.h" /* Create directory recusively. */ -static int mk_dir_recursive(struct lib_context *lc, const char *dir) +static int +mk_dir_recursive(struct lib_context *lc, const char *dir) { int ret = 1; - char *orig, *s; + char *orig, *s; const char delim = '/'; - if (!(orig = s = dbg_strdup((char*) dir))) + if (!(orig = s = dbg_strdup((char *) dir))) return log_alloc_err(lc, __func__); - /* Create parent directories */ - log_notice(lc, "creating directory %s", dir); + /* Create parent directories */ + log_notice(lc, "creating directory %s", dir); do { s = remove_delimiter(s + 1, delim); if (mkdir(orig, 0777) && errno != EEXIST) { @@ -32,11 +33,12 @@ dbg_free(orig); - return ret; + return ret; } /* Create directory. */ -int mk_dir(struct lib_context *lc, const char *dir) +int +mk_dir(struct lib_context *lc, const char *dir) { struct stat info; @@ -50,18 +52,19 @@ LOG_ERR(lc, 0, "directory %s not found", dir); } -static int rw_file(struct lib_context *lc, const char *who, int flags, - char *path, void *buffer, size_t size, loff_t offset) +static int +rw_file(struct lib_context *lc, const char *who, int flags, + char *path, void *buffer, size_t size, loff_t offset) { int fd, ret = 0; loff_t o; struct { - ssize_t (*func)(); + ssize_t(*func) (); const char *what; } rw_spec[] = { - { read, "read" }, - { write, "writ" }, - }, *rw = rw_spec + ((flags & O_WRONLY) ? 1 : 0); + { + read, "read"}, { + write, "writ"},}, *rw = rw_spec + ((flags & O_WRONLY) ? 1 : 0); if ((fd = open(path, flags, lc->mode)) == -1) LOG_ERR(lc, 0, "opening \"%s\"", path); @@ -71,7 +74,7 @@ #else #define DMRAID_LSEEK lseek64 #endif - if (offset && (o = DMRAID_LSEEK(fd, offset, SEEK_SET)) == (loff_t) -1) + if (offset && (o = DMRAID_LSEEK(fd, offset, SEEK_SET)) == (loff_t) - 1) log_err(lc, "%s: seeking device \"%s\" to %" PRIu64, who, path, offset); else if (rw->func(fd, buffer, size) != size) @@ -85,16 +88,18 @@ return ret; } -int read_file(struct lib_context *lc, const char *who, char *path, - void *buffer, size_t size, loff_t offset) +int +read_file(struct lib_context *lc, const char *who, char *path, + void *buffer, size_t size, loff_t offset) { return rw_file(lc, who, O_RDONLY, path, buffer, size, offset); } -int write_file(struct lib_context *lc, const char *who, char *path, - void *buffer, size_t size, loff_t offset) +int +write_file(struct lib_context *lc, const char *who, char *path, + void *buffer, size_t size, loff_t offset) { /* O_CREAT|O_TRUNC are noops on a devnode. */ - return rw_file(lc, who, O_WRONLY|O_CREAT|O_TRUNC, path, + return rw_file(lc, who, O_WRONLY | O_CREAT | O_TRUNC, path, buffer, size, offset); } --- dmraid/lib/misc/init.c 2008/02/22 16:57:36 1.1 +++ dmraid/lib/misc/init.c 2008/06/20 21:52:18 1.2 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004,2005 Heinz Mauelshagen, Red Hat GmbH. + * Copyright (C) 2004-2008 Heinz Mauelshagen, Red Hat GmbH. * All rights reserved. * * See file LICENSE at the top of this source tree for license information. @@ -7,11 +7,16 @@ #include "internal.h" +extern int dso; + /* Library initialization. */ -struct lib_context *libdmraid_init(int argc, char **argv) +struct lib_context * +libdmraid_init(int argc, char **argv) { struct lib_context *lc; + dso = (argv[0] && strcmp(argv[0], "dso")) ? 1 : 0; + if ((lc = alloc_lib_context(argv))) { if (!register_format_handlers(lc)) { libdmraid_exit(lc); @@ -25,11 +30,12 @@ } /* Library exit processing. */ -void libdmraid_exit(struct lib_context *lc) +void +libdmraid_exit(struct lib_context *lc) { free_raid_set(lc, NULL); /* Free all RAID sets. */ free_raid_dev(lc, NULL); /* Free all RAID devices. */ free_dev_info(lc, NULL); /* Free all disk infos. */ unregister_format_handlers(lc); /* Unregister all format handlers. */ - free_lib_context(lc); /* Release library context. */ + free_lib_context(lc); /* Release library context. */ } --- dmraid/lib/misc/lib_context.c 2008/04/02 13:35:32 1.2 +++ dmraid/lib/misc/lib_context.c 2008/06/20 21:52:18 1.3 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004,2005 Heinz Mauelshagen, Red Hat GmbH. + * Copyright (C) 2004-2008 Heinz Mauelshagen, Red Hat GmbH. * All rights reserved. * * See file LICENSE at the top of this source tree for license information. @@ -10,34 +10,39 @@ #include "version.h" /* Options access functions. */ -static inline int lc_opt_ok(enum lc_options o) +static inline int +lc_opt_ok(enum lc_options o) { return o < LC_OPTIONS_SIZE; } -int lc_opt(struct lib_context *lc, enum lc_options o) +int +lc_opt(struct lib_context *lc, enum lc_options o) { return lc_opt_ok(o) ? lc->options[o].opt : 0; } -static int _inc_opt(struct lib_context *lc, int o) +static int +_inc_opt(struct lib_context *lc, int o) { - return lc->options[o].opt < UCHAR_MAX ? ++lc->options[o].opt : - lc->options[o].opt; + return lc->options[o].opt < UCHAR_MAX ? + ++lc->options[o].opt : lc->options[o].opt; } -int lc_inc_opt(struct lib_context *lc, int o) +int +lc_inc_opt(struct lib_context *lc, int o) { return lc_opt_ok(o) ? _inc_opt(lc, o) : 0; } -const char *lc_strcat_opt(struct lib_context *lc, enum lc_options o, - char *arg, const char delim) +const char * +lc_strcat_opt(struct lib_context *lc, enum lc_options o, + char *arg, const char delim) { char *ret = NULL; if (lc_opt_ok(o)) { - char *a = (char*) OPT_STR(lc, o); + char *a = (char *) OPT_STR(lc, o); size_t end = (a ? strlen(a) : 0), len = end + strlen(arg) + ((delim && end) ? 1 : 0) + 1; @@ -50,7 +55,7 @@ strcat(ret, arg); OPT_STR(lc, o) = ret; } else { - dbg_free((char*) OPT_STR(lc, o)); + dbg_free((char *) OPT_STR(lc, o)); OPT_STR(lc, o) = ret; log_alloc_err(lc, __func__); } @@ -59,13 +64,13 @@ return ret; } -const char *lc_stralloc_opt(struct lib_context *lc, enum lc_options o, - char *arg) +const char * +lc_stralloc_opt(struct lib_context *lc, enum lc_options o, char *arg) { if (lc_opt_ok(o)) { /* Free any already allocated one. */ if (OPT_STR(lc, o)) - dbg_free((char*) OPT_STR(lc, o)); + dbg_free((char *) OPT_STR(lc, o)); /* Dup new one. */ if ((OPT_STR(lc, o) = dbg_strdup(arg))) @@ -77,12 +82,14 @@ return NULL; } -const char *lc_opt_arg(struct lib_context *lc, enum lc_options o) +const char * +lc_opt_arg(struct lib_context *lc, enum lc_options o) { return lc_opt_ok(o) ? lc->options[o].arg.str : NULL; } -struct list_head *lc_list(struct lib_context *lc, int l) +struct list_head * +lc_list(struct lib_context *lc, int l) { return l < ARRAY_SIZE(lc->lists) ? lc->lists + l : NULL; } @@ -90,21 +97,24 @@ /* * Library context initialization functions. */ -static void init_options(struct lib_context *lc, void *arg) +static void +init_options(struct lib_context *lc, void *arg) { lc_inc_opt(lc, LC_SEPARATOR); - lc->options[LC_SEPARATOR].arg.str = dbg_strdup((char*) ","); + lc->options[LC_SEPARATOR].arg.str = dbg_strdup((char *) ","); lc_inc_opt(lc, LC_PARTCHAR); - lc->options[LC_PARTCHAR].arg.str = dbg_strdup((char*) "p"); + lc->options[LC_PARTCHAR].arg.str = dbg_strdup((char *) "p"); } -static void init_cmd(struct lib_context *lc, void *arg) +static void +init_cmd(struct lib_context *lc, void *arg) { - lc->cmd = get_basename(lc, ((char**) arg)[0]); + lc->cmd = get_basename(lc, ((char **) arg)[0]); } -static void init_lists(struct lib_context *lc, void *arg) +static void +init_lists(struct lib_context *lc, void *arg) { unsigned int i = LC_LISTS_SIZE; @@ -112,40 +122,44 @@ INIT_LIST_HEAD(lc->lists + i); } -static void init_mode(struct lib_context *lc, void *arg) +static void +init_mode(struct lib_context *lc, void *arg) { lc->mode = 0600; } -static void init_paths(struct lib_context *lc, void *arg) +static void +init_paths(struct lib_context *lc, void *arg) { lc->path.error = "/dev/zero"; } /* FIXME: add lib flavour info (e.g., DEBUG). */ -static void init_version(struct lib_context *lc, void *arg) +static void +init_version(struct lib_context *lc, void *arg) { - lc->version.text = DMRAID_LIB_VERSION; - lc->version.date = DMRAID_LIB_DATE; - lc->version.v.major = DMRAID_LIB_MAJOR_VERSION; - lc->version.v.minor = DMRAID_LIB_MINOR_VERSION; - lc->version.v.sub_minor = DMRAID_LIB_SUBMINOR_VERSION; - lc->version.v.suffix = DMRAID_LIB_VERSION_SUFFIX; + lc->version.text = DMRAID_LIB_VERSION; + lc->version.date = DMRAID_LIB_DATE; + lc->version.v.major = DMRAID_LIB_MAJOR_VERSION; + lc->version.v.minor = DMRAID_LIB_MINOR_VERSION; + lc->version.v.sub_minor = DMRAID_LIB_SUBMINOR_VERSION; + lc->version.v.suffix = DMRAID_LIB_VERSION_SUFFIX; } /* Put init functions into an array because of the potentially growing list. */ struct init_fn { - void (*func)(struct lib_context *lc, void *arg); + void (*func) (struct lib_context * lc, void *arg); } init_fn[] = { - { init_options }, - { init_cmd }, - { init_lists }, - { init_mode }, - { init_paths }, - { init_version }, -}; + { + init_options}, { + init_cmd}, { + init_lists}, { + init_mode}, { + init_paths}, { +init_version},}; -struct lib_context *alloc_lib_context(char **argv) +struct lib_context * +alloc_lib_context(char **argv) { struct lib_context *lc; struct init_fn *f; @@ -167,26 +181,29 @@ return lc; } -void free_lib_context(struct lib_context *lc) +void +free_lib_context(struct lib_context *lc) { int o; for (o = 0; o < LC_OPTIONS_SIZE; o++) { if (lc->options[o].arg.str) - dbg_free ((char*) lc->options[o].arg.str); + dbg_free((char *) lc->options[o].arg.str); } dbg_free(lc); } /* Return library date (ASCII). */ -const char *libdmraid_date(struct lib_context *lc) +const char * +libdmraid_date(struct lib_context *lc) { return lc->version.date; } /* Return library version (ASCII). */ -const char *libdmraid_version(struct lib_context *lc) +const char * +libdmraid_version(struct lib_context *lc) { return lc->version.text; } --- dmraid/lib/misc/misc.c 2008/02/22 16:57:36 1.1 +++ dmraid/lib/misc/misc.c 2008/06/20 21:52:18 1.2 @@ -2,6 +2,9 @@ * Copyright (C) 2004,2005 Heinz Mauelshagen, Red Hat GmbH. * All rights reserved. * + * Copyright (C) 2007 Intel Corporation. All rights reserved. + * November, 2007 - additions for Create, Delete, Rebuild & Raid 10. + * * See file LICENSE at the top of this source tree for license information. */ @@ -9,7 +12,8 @@ #include "internal.h" /* Prompt for a yes/no answer */ -int yes_no_prompt(struct lib_context *lc, const char *prompt, ...) +int +yes_no_prompt(struct lib_context *lc, const char *prompt, ...) { int c = '\n'; va_list ap; @@ -31,7 +35,8 @@ } /* Return the basename of a path. */ -char *get_basename(struct lib_context *lc, char *str) +char * +get_basename(struct lib_context *lc, char *str) { char *ret = strrchr(str, '/'); @@ -39,7 +44,8 @@ } /* Return the dirname of a path. */ -char *get_dirname(struct lib_context *lc, char *str) +char * +get_dirname(struct lib_context *lc, char *str) { char *ret = strrchr(str, '/'); size_t len = ret ? ret - str : strlen(str); @@ -51,7 +57,8 @@ } /* Convert a numeric string to alpha. */ -void mk_alpha(struct lib_context *lc, char *str, size_t len) +void +mk_alpha(struct lib_context *lc, char *str, size_t len) { for (; len && *str; len--, str++) { if (isdigit(*str)) @@ -60,7 +67,8 @@ } /* Remove any whitespace from a string. */ -char *remove_white_space(struct lib_context *lc, char *str, size_t size) +char * +remove_white_space(struct lib_context *lc, char *str, size_t size) { int c; char *in = str, *out = str; @@ -70,24 +78,36 @@ if (!isspace(c)) *out++ = c; } - *out = 0; + *out = 0; return str; } +/* Remove any whitespace at the tail of a string */ +void +remove_tail_space(char *str) +{ + char *s = str + strlen(str); + + while (s-- > str && isspace(*s)) + *s = 0; +} + /* Remove/add a delimiter character. */ -char *remove_delimiter(char *ptr, char c) +char * +remove_delimiter(char *ptr, char c) { char *ret = NULL; if (ptr && (ret = strchr(ptr, (int) c))) *ret = 0; - return ret; + return ret; } -void add_delimiter(char **ptr, char c) +void +add_delimiter(char **ptr, char c) { if (ptr && *ptr) { **ptr = c; @@ -95,24 +115,38 @@ } } +char * +replace_delimiter(char *str, char delim, char c) +{ + char *s = str; + + while ((s = remove_delimiter(s, delim))) + add_delimiter(&s, c); + + return str; +} + /* Grow a string. */ -static int grow_string(struct lib_context *lc, char **string, const char *s) +static int +grow_string(struct lib_context *lc, char **string, const char *s) { size_t len; char *tmp = *string; - len = strlen(s) + (tmp ? strlen(tmp) + 1 : 1); + len = strlen(s) + (tmp ? strlen(tmp) + 1 : 1); if ((*string = dbg_realloc(tmp, len))) { if (!tmp) **string = '\0'; - } else if (tmp) + } + else if (tmp) dbg_free(tmp); - + return *string ? 1 : 0; } /* Free a string. */ -void free_string(struct lib_context *lc, char **string) +void +free_string(struct lib_context *lc, char **string) { if (*string) { dbg_free(*string); @@ -121,46 +155,48 @@ } /* Push a string onto the end of another. */ -static int p_str(struct lib_context *lc, char **string, const char *s) +static int +p_str(struct lib_context *lc, char **string, const char *s) { int ret; if ((ret = grow_string(lc, string, s))) - strcat (*string, s); + strcat(*string, s); return ret; } /* Push a string defined by a start and end pointer onto the end of another. */ -static int p_str_str(struct lib_context *lc, char **string, - char *begin, char *end) +static int +p_str_str(struct lib_context *lc, char **string, char *begin, char *end) { if (end == begin) return 1; *end = 0; - return p_str(lc, string, begin); } /* Push an uint64_t in ascii onto the end of a string. */ -static int p_u64(struct lib_context *lc, char **string, const uint64_t u) +static int +p_u64(struct lib_context *lc, char **string, const uint64_t u) { char buffer[22]; sprintf(buffer, "%" PRIu64, u); - return p_str(lc, string, buffer); } /* Push an uint_t in ascii onto the end of a string. */ -static int p_u(struct lib_context *lc, char **string, const unsigned int u) +static int +p_u(struct lib_context *lc, char **string, const unsigned int u) { return p_u64(lc, string, (uint64_t) u); } /* Push an uint_t in ascii onto the end of a string. */ -static int p_d(struct lib_context *lc, char **string, const int d) +static int +p_d(struct lib_context *lc, char **string, const int d) { char buffer[12]; @@ -170,12 +206,13 @@ } /* Push a format string defined list of arguments onto a string. */ -int p_fmt(struct lib_context *lc, char **string, const char *fmt, ...) +int +p_fmt(struct lib_context *lc, char **string, const char *fmt, ...) { int ret = 1; char *b, *f, *f_sav; va_list ap; - + if (!(f = f_sav = dbg_strdup((char *) fmt))) return 0; @@ -198,7 +235,7 @@ case 's': ret = p_str(lc, string, va_arg(ap, char *)); break; - + case 'u': ret = p_u(lc, string, va_arg(ap, unsigned int)); break; @@ -222,3 +259,49 @@ return ret; } + +#ifdef DMRAID_LED +int +led(const char *path, int status) +{ + +#ifdef DMRAID_INTEL_LED + FILE *fd; + int sgpio = 0; + static char com[100]; + + /* Check if sgpio app is installed. */ + if ((fd = popen("which sgpio", "r"))) { + sgpio = fscanf(fd, "%s", com); + close(fd); + } + + if (sgpio != 1) { + printf("sgpio app not found\n"); + return 1; + } + + switch (status) { + case LED_REBUILD: + sprintf(com, "sgpio -d %s -s rebuild", path); + break; + + case LED_OFF: + sprintf(com, "sgpio -d %s -s off", path); + break; + + default: + printf("Unknown LED status\n"); + return 2; + } + + if (system(com) == -1) { + printf("Call to sgpio app (%s) failed\n", com); + return 4; + } +#endif + + return 0; + +} +#endif --- dmraid/lib/misc/workaround.c 2008/02/22 16:57:36 1.1 +++ dmraid/lib/misc/workaround.c 2008/06/20 21:52:18 1.2 @@ -15,22 +15,23 @@ * populate /sys/block in case of IDE module * load because of asynchronuous registration !? */ -void sysfs_workaround(struct lib_context *lc) +void +sysfs_workaround(struct lib_context *lc) { int d, fd; size_t len; char *dev; if (!(dev = dbg_malloc(sizeof(_PATH_DEV) + 4))) - LOG_ERR(lc, , "sysfs workaround"); + LOG_ERR(lc,, "sysfs workaround"); sprintf(dev, "%shd?", _PATH_DEV); for (len = strlen(dev) - 1, d = 'a'; d <= 'z'; d++) { dev[len] = (char) d; if (!removable_device(lc, dev) && - (fd = open (dev, O_RDONLY)) != -1) - close (fd); + (fd = open(dev, O_RDONLY)) != -1) + close(fd); } dbg_free(dev); --- dmraid/lib/mm/dbg_malloc.c 2008/02/22 16:57:37 1.1 +++ dmraid/lib/mm/dbg_malloc.c 2008/06/20 21:52:18 1.2 @@ -12,7 +12,8 @@ #include "dbg_malloc.h" #include "log/log.h" -static void *__dbg_malloc(size_t size, int init) +static void * +__dbg_malloc(size_t size, int init) { void *ret = malloc(size); @@ -24,31 +25,34 @@ #ifdef DEBUG_MALLOC -void *_dbg_malloc(size_t size, struct lib_context *lc, - const char *who, unsigned int line) +void * +_dbg_malloc(size_t size, struct lib_context *lc, + const char *who, unsigned int line) { void *ret = __dbg_malloc(size, 1); log_dbg(lc, "%s: dbg_malloc(%zu) at line %u returned 0x%x", - (char*) who, size, line, (unsigned long) ret); + (char *) who, size, line, (unsigned long) ret); return ret; } -void *_dbg_realloc(void *ptr, size_t size, struct lib_context *lc, - const char *who, unsigned int line) +void * +_dbg_realloc(void *ptr, size_t size, struct lib_context *lc, + const char *who, unsigned int line) { void *ret = realloc(ptr, size); log_dbg(lc, "%s: dbg_realloc(0x%x, %zu) at line %u returned 0x%x", - (char*) who, (unsigned long) ptr, size, line, + (char *) who, (unsigned long) ptr, size, line, (unsigned long) ret); return ret; } -void *_dbg_strndup(void *ptr, size_t len, struct lib_context *lc, - const char *who, unsigned int line) +void * +_dbg_strndup(void *ptr, size_t len, struct lib_context *lc, + const char *who, unsigned int line) { char *ret; @@ -58,40 +62,44 @@ } log_dbg(lc, "%s: dbg_strndup(0x%x) at line %u returned 0x%x", - (char*) who, (unsigned long) ptr, line, (unsigned long) ret); + (char *) who, (unsigned long) ptr, line, (unsigned long) ret); return ret; } -void *_dbg_strdup(void *ptr, struct lib_context *lc, - const char *who, unsigned int line) +void * +_dbg_strdup(void *ptr, struct lib_context *lc, + const char *who, unsigned int line) { return _dbg_strndup(ptr, strlen(ptr), lc, who, line); } -void _dbg_free(void *ptr, struct lib_context *lc, - const char *who, unsigned int line) +void +_dbg_free(void *ptr, struct lib_context *lc, const char *who, unsigned int line) { log_dbg(lc, "%s: dbg_free(0x%x) at line %u", - (char*) who, (unsigned long) ptr, line); + (char *) who, (unsigned long) ptr, line); free(ptr); } #else -void *_dbg_malloc(size_t size) +void * +_dbg_malloc(size_t size) { return __dbg_malloc(size, 1); } -void *_dbg_realloc(void *ptr, size_t size) +void * +_dbg_realloc(void *ptr, size_t size) { return realloc(ptr, size); } -void *_dbg_strndup(void *ptr, size_t len) +void * +_dbg_strndup(void *ptr, size_t len) { char *ret; @@ -103,12 +111,14 @@ return ret; } -void *_dbg_strdup(void *ptr) +void * +_dbg_strdup(void *ptr) { return _dbg_strndup(ptr, strlen(ptr)); } -void _dbg_free(void *ptr) +void +_dbg_free(void *ptr) { free(ptr); } --- dmraid/man/dmraid.8 2008/04/02 13:35:32 1.2 +++ dmraid/man/dmraid.8 2008/06/20 21:52:18 1.3 @@ -1,420 +1,533 @@ -.TH DMRAID 8 "DMRAID TOOL" "Heinz Mauelshagen" \" -*- nroff -*- -.SH NAME -dmraid \- discover and activate software (ATA)RAID -.SH SYNOPSIS -.B dmraid - {-a|--activate} {y|n|yes|no} - [-d|--debug]... [-v|--verbose]... [-i|--ignorelocking] - [-f|--format FORMAT[,FORMAT...]] - [{-P|--partchar} CHAR] - [-p|--no_partitions] - [--separator SEPARATOR] - [-t|--test] - [RAID-set...] - -.B dmraid - {-b|--block_devices} - [-c|--display_columns][FIELD[,FIELD...]]... - [-d|--debug]... [-v|--verbose]... - [--separator SEPARATOR] - [device-path...] - -.B dmraid - {-h|--help} - -.B dmraid - {-l|--list_formats} - [-d|--debug]... [-v|--verbose]... - -.B dmraid - {-n|--native_log} - [-d|--debug]... [-v|--verbose]... [-i|--ignorelocking] - [-f|--format FORMAT[,FORMAT...]] - [--separator SEPARATOR] - [device-path...] - -.B dmraid - {-r|--raid_devices} - [-c|--display_columns][FIELD[,FIELD...]]... - [-d|--debug]... [-v|--verbose]... [-i|--ignorelocking] - [-D|--dump_metadata] - [-f|--format FORMAT[,FORMAT...]] - [--separator SEPARATOR] - [device-path...] - -.B dmraid - {-r|--raid_devices} - [-d|--debug]... [-v|--verbose]... [-i|--ignorelocking] - [-E|--erase_metadata] - [-f|--format FORMAT[,FORMAT...]] - [--separator SEPARATOR] - [device-path...] - -.B dmraid - {-s|--sets}...[a|i|active|inactive] - [-c|--display_columns][FIELD[,FIELD...]]... - [-d|--debug]... [-v|--verbose]... [-i|--ignorelocking] - [-f|--format FORMAT[,FORMAT...]] - [-g|--display_group] - [--separator SEPARATOR] - [RAID-set...] - -.B dmraid - {-V/--version} - -.SH DESCRIPTION -dmraid discovers block and software RAID devices (eg, ATARAID) -by using multiple different metadata format handlers which -support various formats (eg, Highpoint 37x series). -It offers activating RAID sets made up by 2 or more -discovered RAID devices, display properties of devices and sets (see option -.B -l -for supported metadata formats). -Block device access to activated RAID sets occurs via device-mapper nodes -/dev/mapper/RaidSetName. -RaidSetName starts with the format name (see -.B -l -option) which can be used to access all RAID sets of a specific format -easily with certain options (eg, -.B -a -below). - -.SS OPTIONS -.TP -.I \-a, \-\-activate {y|n} [RAID set...] -Activates or deactivates all or particular software RAID set. -In case metadata format handlers are chosen with -.B -f -, only RAID sets with such format(s) can be activated or deactivated. -Useful if devices have multiple metadata signatures. -When activating RAID sets, -.B -p -disables the activation of partitions on them. -RAID set names given on command line don't need to be fully specified -(eg, "dmraid -ay sil" would activate all discovered Silicon Image Medley -RAID sets). - -.TP -.I {-b|--block_devices} [device-path...] -List all or particular discovered block devices with their -properties (size, serial number). -Add -.B -c -to display block device names only and -.B -cc -for CSV column output of block device properties. -See description of -.B -c -below for FIELD identifiers. - -.TP -.I [-d|--debug]... -Enable debugging output. Opion can be given multiple times -increasing the debug output level. - -.TP -.I [-c|--display_columns][FIELD[,FIELD...]]... -Display properties of block devices, RAID sets and devices in column(s). -Optional list specifying which FIELDs to display. -.br -For -.B -b: -.br -d[evpath]|p[ath], sec[tors]|si[ze], ser[ialnumber]. -.br -For -.B -r: -.br -de[vpath]|p[ath], f[ormat], r[aidname], t[ype], st[atus], se[ctors]|si[ze], da[taoffset]|o[ffset]. -.br -For -.B -s: -.br -f[ormat], r[aidname], t[ype], sta[tus], str[ide], se[ctors]|si[ze], su[bsets], d[evices], sp[ares]. -.br -.TP -.I [-f|--format FORMAT[,FORMAT...]] -Use metadata format handler(s) to discover RAID devices. -See -.B -l -for a list of supported format handler names. This is useful to -select particular formats in case multiple metadata signatures are found -on a device. A comma seperated list of format names can be specified which -may not contain white space. - -.TP -.I {-h|--help} -Display help text. - -.TP -.I {-i|--ignorelocking} -Don't take out any locks. Useful in early boot where no read/write -access to /var is available. - -.TP -.I {-l|--list_formats} -List all available metadata format handlers with their names and -descriptions. Supported RAID levels are listed in parenthesis: -.br - -S: Span (concatination) -.br -0: RAID0 (stripe) -.br -1: RAID1 (mirror) -.br -10: RAID10 (mirror on top of stripes) -.br -01: RAID10 (stripe on top of mirrors) - -.TP -.I {-n|--native_log} [device-path...] -Display metadata in native, vendor-specific format. -In case a metadata format handler is chosen with -.B -f -only RAID devices with such format will be displayed in native format. -If device-path(s) is/are given on the command line, native metadata output -is restricted to those listed. - -.TP -.I [{-P|--partchar} CHAR] -Use CHAR as the separator between the device name and the partition number. - -.TP -.I {-r|--raid_devices} [device-path...] -List all discovered RAID devices with format, RAID level, sectors used -and data offset into the device. -In case a metadata format handler is chosen with -.B -f -, only RAID devices with such format can be discovered. Useful if devices -have multiple metadata signatures. -If -.B -D -is added to -.B -r -the RAID metadata gets dumped into a subdirectory named dmraid.format_name -(eg. format_name = isw) in files named devicename.dat. -The byte offset where the metadata is located on the device is written -into files named devicename.offset and the size of the device in sectors -into files named devicename.size. - -If -.B -E -is added to -.B -r -the RAID metadata on the devices gets conditionally erased. -Useful to erase old metadata after new one of different type has been -stored on a device in order to avoid discovering both. If you enter -.B -E -option -.B -D -will be enforced in order to have a fallback in case the wrong metadata -got erased. -Manual copying back onto the device is needed to recover from erasing -the wrong metadata using the dumped files devicename_formatname.dat -and devicename_formatname.offset. -Eg, to restore all *.dat files in the working directory to the respective devices: - -.br -for f in *.dat -.br -do -.br - dd if=$f of=/dev/${f%%.dat} \\ -.br - seek=`cat ${f%%dat}offset` bs=1 -.br -done -.br - -If device-path(s) is/are given on the command line, the above actions -are restricted to those listed. -Add -.B -c -to display RAID device names only and -.B -cc -for CSV column output of RAID device properties. -See description of -.B -c -above for FIELD identifiers. - -.TP -.I --separator SEPARATOR -Use SEPARATOR as a delimiter for all options taking or displaying lists. - -.TP -.I -s... [a|i] [RAID-set...] -Display properties of RAID sets. Multiple RAID set names can be given -on the command line which don't need to be fully specified (eg, "dmraid -s hpt" -would display all discovered Highpoint RAID sets). Enter -.B -s -twice to display RAID subsets too. -Add -.B -c -to display names of RAID sets only, -.B -cc -for CSV column output of RAID set properties and -.B -ccc -for inclusion of block devices in the listing. Doesn't imply -.B -s -s -to show RAID subsets (implied for group sets, e.g. isw). -Add -.B -g -to include information about group RAID sets (as with Intel Software -RAID) in the listing. -See description of -.B -c -above for FIELD identifiers. - -.TP -.I [-v|--verbose]... -Enable verbose runtime information output. Opion can be given multiple times -increasing the verbosity level. - -.SH EXAMPLES -"dmraid -l" lists all supported metadata formats with their names along with -some descriptive information, eg: -.br -hpt37x : (+) Highpoint HPT37X -.br -hpt45x : (+) Highpoint HPT45X -.br -isw : (+) Intel Software RAID -.br -lsi : (0) LSI Logic MegaRAID -.br -nvidia : (+) NVidia RAID -.br -pdc : (+) Promise FastTrack -.br -sil : (+) Silicon Image(tm) Medley(tm) -.br -via : (+) VIA Software RAID -.br -dos : (+) DOS partitions on SW RAIDs -.br -(0): Discover, (+): Discover+Activate - -"dmraid -ay" activates all software RAID sets discovered. - -"dmraid -an" deactivates all active software RAID sets which are not open -(eg, mounted filesystem on them). - -"dmraid -ay -f pdc" (pdc looked up from "dmraid -l") activates all -software RAID sets with Promise format discovered and ignores all other -supported formats. - -"dmraid -r" discovers all software RAID devices supported on your system, eg: -.br -/dev/dm-46: hpt45x, "hpt45x_chidjhaiaa-0", striped, ok, 320172928 sectors, data@ 0 -.br -/dev/dm-50: hpt45x, "hpt45x_chidjhaiaa-0", striped, ok, 320172928 sectors, data@ 0 -.br -/dev/dm-54: hpt45x, "hpt45x_chidjhaiaa-1", striped, ok, 320172928 sectors, data@ 0 -.br -/dev/dm-58: hpt45x, "hpt45x_chidjhaiaa-1", striped, ok, 320172928 sectors, data@ 0 - - -"dmraid -s -s hpt45x_chidjhaiaa" displays properties of -set "hpt45x_chidjhaiaa", eg: -.br -*** Superset -.br -name : hpt45x_chidjhaiaa -.br -size : 640345856 -.br -stride : 128 -.br -type : raid10 -.br -status : ok -.br -subsets: 2 -.br -dev : 4 -.br -spare : 0 -.br ----> Subset -.br -name : hpt45x_chidjhaiaa-0 -.br -size : 640345856 -.br -stride : 128 -.br -type : stripe -.br -status : ok -.br -subsets: 0 -.br -dev : 2 -.br -spare : 0 -.br ----> Subset -.br -name : hpt45x_chidjhaiaa-1 -.br -size : 640345856 -.br -stride : 128 -.br -type : stripe -.br -status : ok -.br -subsets: 0 -.br -dev : 2 -.br -spare : 0 -.br - -"dmraid -s -ccs hpt45" displays properties in column format of all sets -and subsets with hpt45* format, eg: -.br -hpt45x_chidjhaiaa,640345856,128,raid10,ok,4,0 -.br -hpt45x_chidjhaiaa-a,640345856,128,stripe,ok,2,0 -.br -hpt45x_chidjhaiaa-b,640345856,128,stripe,ok,2,0 - -"dmraid -r --sep : -cpath:size" display paths and sizes in sectors for -RAID devices in column format using ':' as a delimiter, eg: -.br -/dev/dm-8:320173055 -.br -/dev/dm-12:320173055 -.br -/dev/dm-22:320173055 -.br -/dev/dm-26:320173055 -.br -/dev/dm-30:586114703 -.br -/dev/dm-34:586114703 -.br -/dev/dm-38:586114703 -.br -/dev/dm-42:586114703 -.br -/dev/dm-46:156301487 -.br -/dev/dm-50:156301487 -.br -/dev/dm-54:390624896 -.br -/dev/dm-58:390624896 -.br -/dev/dm-62:390624896 -.br -/dev/dm-66:390624896 - -.SH DIAGNOSTICS -dmraid returns an exit code of 0 for success or 1 for error. - -.SH AUTHOR -Heinz Mauelshagen <Mauelshagen@xxxxxxxxxx> +.TH DMRAID 8 "DMRAID TOOL" "Heinz Mauelshagen" \" -*- nroff -*- +.SH NAME +dmraid \- discover, configure and activate software (ATA)RAID +.SH SYNOPSIS +.B dmraid + {-a|--activate} {y|n|yes|no} + [-d|--debug]... [-v|--verbose]... [-i|--ignorelocking] + [-f|--format FORMAT[,FORMAT...]] + [{-P|--partchar} CHAR] + [-p|--no_partitions] + [--separator SEPARATOR] + [-t|--test] + [RAID-set...] + +.B dmraid + {-b|--block_devices} + [-c|--display_columns][FIELD[,FIELD...]]... + [-d|--debug]... [-v|--verbose]... + [--separator SEPARATOR] + [device-path...] + +.B dmraid + {-h|--help} + +.B dmraid + {-l|--list_formats} + [-d|--debug]... [-v|--verbose]... + +.B dmraid + {-n|--native_log} + [-d|--debug]... [-v|--verbose]... [-i|--ignorelocking] + [-f|--format FORMAT[,FORMAT...]] + [--separator SEPARATOR] + [device-path...] + +.B dmraid + {-R| --rebuild} + RAID-set + [device-path] + +.B dmraid + {-x| --remove} + [RAID-set] + +.B dmraid + -f FORMAT-handler +{-C| --create} set + --type raidlevel + [--size=setsize --strip stridesize] + --disk "device-path, device-path [, device-path ...]" + +.B dmraid +[ -f|--format FORMAT-handler] +-S|--spare [RAID-set] +-M|--media "device-path" + +.B dmraid + {-r|--raid_devices} + [-c|--display_columns][FIELD[,FIELD...]]... + [-d|--debug]... [-v|--verbose]... [-i|--ignorelocking] + [-D|--dump_metadata] + [-f|--format FORMAT[,FORMAT...]] + [--separator SEPARATOR] + [device-path...] + +.B dmraid + {-r|--raid_devices} + [-d|--debug]... [-v|--verbose]... [-i|--ignorelocking] + [-E|--erase_metadata] + [-f|--format FORMAT[,FORMAT...]] + [--separator SEPARATOR] + [device-path...] + +.B dmraid + {-s|--sets}...[a|i|active|inactive] + [-c|--display_columns][FIELD[,FIELD...]]... + [-d|--debug]... [-v|--verbose]... [-i|--ignorelocking] + [-f|--format FORMAT[,FORMAT...]] + [-g|--display_group] + [--separator SEPARATOR] + [RAID-set...] + +.B dmraid + {-V/--version} + +.SH DESCRIPTION +dmraid discovers block and software RAID devices (eg, ATARAID) +by using multiple different metadata format handlers which +support various formats (eg, Highpoint 37x series). +It offers activating RAID sets made up by 2 or more +discovered RAID devices, display properties of devices and sets (see option +.B -l +for supported metadata formats). +Block device access to activated RAID sets occurs via device-mapper nodes +/dev/mapper/RaidSetName. +RaidSetName starts with the format name (see +.B -l +option) which can be used to access all RAID sets of a specific format +easily with certain options (eg, +.B -a +below). + +.SS OPTIONS +.TP +.I \-a, \-\-activate {y|n} [RAID set...] +Activates or deactivates all or particular software RAID set. +In case metadata format handlers are chosen with +.B -f +, only RAID sets with such format(s) can be activated or deactivated. +Useful if devices have multiple metadata signatures. +When activating RAID sets, +.B -p +disables the activation of partitions on them. +RAID set names given on command line don't need to be fully specified +(eg, "dmraid -ay sil" would activate all discovered Silicon Image Medley +RAID sets). + +.TP +.I {-b|--block_devices} [device-path...] +List all or particular discovered block devices with their +properties (size, serial number). +Add +.B -c +to display block device names only and +.B -cc +for CSV column output of block device properties. +See description of +.B -c +below for FIELD identifiers. + +.TP +.I [-d|--debug]... +Enable debugging output. Opion can be given multiple times +increasing the debug output level. + +.TP +.I [-c|--display_columns][FIELD[,FIELD...]]... +Display properties of block devices, RAID sets and devices in column(s). +Optional list specifying which FIELDs to display. +.br +For +.B -b: +.br +d[evpath]|p[ath], sec[tors]|si[ze], ser[ialnumber]. +.br +For +.B -r: +.br +de[vpath]|p[ath], f[ormat], r[aidname], t[ype], st[atus], se[ctors]|si[ze], da[taoffset]|o[ffset]. +.br +For +.B -s: +.br +f[ormat], r[aidname], t[ype], sta[tus], str[ide], se[ctors]|si[ze], su[bsets], d[evices], sp[ares]. +.br +.TP +.I [-f|--format FORMAT[,FORMAT...]] +Use metadata format handler(s) to discover RAID devices. +See +.B -l +for a list of supported format handler names. This is useful to +select particular formats in case multiple metadata signatures are found +on a device. A comma seperated list of format names can be specified which +may not contain white space. + +.TP +.I {-h|--help} +Display help text. + +.TP +.I {-i|--ignorelocking} +Don't take out any locks. Useful in early boot where no read/write +access to /var is available. + +.TP +.I {-l|--list_formats} +List all available metadata format handlers with their names and +descriptions. Supported RAID levels are listed in parenthesis: +.br + +S: Span (concatination) +.br +0: RAID0 (stripe) +.br +1: RAID1 (mirror) +.br +10: RAID10 (mirror on top of stripes) +.br +01: RAID10 (stripe on top of mirrors) Note: Intel OROM displays this as RAID10 + +.TP +.I {-n|--native_log} [device-path...] +Display metadata in native, vendor-specific format. +In case a metadata format handler is chosen with +.B -f +only RAID devices with such format will be displayed in native format. +If device-path(s) is/are given on the command line, native metadata output +is restricted to those listed. +.TP +.I [{-P|--partchar} CHAR] +Use CHAR as the separator between the device name and the partition number. +.TP +.I {-R| --rebuild} RAID-set [device-path] +Rebuild raid array after a drive has failed and a new drive is added. +For Intel chipset based systems, there are two methods in which a new drive +is added to the system. + +1. Using OROM to identify a new drive + During system reboot, enter OROM and mark the new drive as the rebuild drive. + After booting to the OS, use the dmraid command to rebuild. + + Example: dmraid -R raid_set + +2. Using dmraid to identify a new drive + Boot to the OS and use the dmraid command with the new drive as +the second parameter. + + Example: dmraid -R raid_set /dev/sdc + +3. Using hot spare drive + Mark a drive as hot spare using the "dmraid -f isw -S" command. Then use the dmraid command to start the rebuild. + + Example: dmraid -R raid_set + +.TP +.I {-x|--remove} [RAID-set] +Delete one or all existing software RAID devices from the metadata. + +.TP +.I -f FORMAT-handler {-C|--create} --type raidlevel [--size=setsize --strip stripsize] --disk "device-path, device-path [,device-path]" +Delete one or all existing Configure a software RAID device and store the configuration data in a group of hard drive devices consisting of this array. This command requires the following options: + +-f FORMAT-handler +.br + metadata format (see "dmraid -l") +.br +--type digit[digit...] +.br + specify the raid level of the software RAID set. +.br + 0: raid0 +.br + 1: raid1 +.br + 5: raid5 +.br + 01: raid01 (isw raid10) +.br +--size: [digits[k|K|m|M|g|G][b|B]] +.br + specify the size of the RAID set.The number is an integer followed by [kKmMgG] and/or [bB]. +.br + b: byte (default) +.br + B: block (512 bytes) +.br + K or K: on the base of 1024 +.br + m or M: on the base of 1024*1024 +.br + g or G: on the base of 1024*1024*1024 +.br +If this option is missing, it's set to the default value pre-configured by the vendor. Note that different vendors may apply different constraints on the granularity of the size or the minimal value. +.br +--strip: [digits[k|K|m|M|g|G][b|B]] +.br + specify the strip size of a RAID1, RAID5, and RAID10 RAID set (as above) +.br +--disk: device-path[{,| }device-path...] +.br + specify the array of the hard drives, e.g. /dev/sda. + +.TP +.I -f FORMAT-handler -S -M device-path +.I -S -M device-path + +This command adds hot spare support for one or more RAID sets. + +1. When used with a format handler, which supports hot spare sets (e.g. isw), a hot spare is marked to be used when rebuilding any RAID set of that format. +2. When used when specifying a RAID set, the drive is added to that RAID set and will be used only to rebuild that set. Note: If the specified name does not match an existing RAID-set, a set with the new name will be created. + +.TP +.I {-r|--raid_devices} [device-path...] +List all discovered RAID devices with format, RAID level, sectors used +and data offset into the device. +In case a metadata format handler is chosen with +.B -f +, only RAID devices with such format can be discovered. Useful if devices +have multiple metadata signatures. +If +.B -D +is added to +.B -r +the RAID metadata gets dumped into a subdirectory named dmraid.format_name +(eg. format_name = isw) in files named devicename.dat. +The byte offset where the metadata is located on the device is written +into files named devicename.offset and the size of the device in sectors +into files named devicename.size. + +If +.B -E +is added to +.B -r +the RAID metadata on the devices gets conditionally erased. +Useful to erase old metadata after new one of different type has been +stored on a device in order to avoid discovering both. If you enter +.B -E +option +.B -D +will be enforced in order to have a fallback in case the wrong metadata +got erased. +Manual copying back onto the device is needed to recover from erasing +the wrong metadata using the dumped files devicename_formatname.dat +and devicename_formatname.offset. +Eg, to restore all *.dat files in the working directory to the respective devices: + +.br +for f in *.dat +.br +do +.br + dd if=$f of=/dev/${f%%.dat} \\ +.br + seek=`cat ${f%%dat}offset` bs=1 +.br +done +.br + +If device-path(s) is/are given on the command line, the above actions +are restricted to those listed. +Add +.B -c +to display RAID device names only and +.B -cc +for CSV column output of RAID device properties. +See description of +.B -c +above for FIELD identifiers. + +.TP +.I --separator SEPARATOR +Use SEPARATOR as a delimiter for all options taking or displaying lists. + +.TP +.I -s... [a|i] [RAID-set...] +Display properties of RAID sets. Multiple RAID set names can be given +on the command line which don't need to be fully specified (eg, "dmraid -s hpt" +would display all discovered Highpoint RAID sets). Enter +.B -s +twice to display RAID subsets too. +Add +.B -c +to display names of RAID sets only, +.B -cc +for CSV column output of RAID set properties and +.B -ccc +for inclusion of block devices in the listing. Doesn't imply +.B -s -s +to show RAID subsets (implied for group sets, e.g. isw). +Add +.B -g +to include information about group RAID sets (as with Intel Software +RAID) in the listing. +See description of +.B -c +above for FIELD identifiers. +Note: Size is given in sectors (not bytes). + +.TP +.I [-v|--verbose]... +Enable verbose runtime information output. Opion can be given multiple times +increasing the verbosity level. + +.SH EXAMPLES +"dmraid -l" lists all supported metadata formats with their names along with +some descriptive information, eg: +.br +hpt37x : (+) Highpoint HPT37X +.br +hpt45x : (+) Highpoint HPT45X +.br +isw : (+) Intel Software RAID +.br +lsi : (0) LSI Logic MegaRAID +.br +nvidia : (+) NVidia RAID +.br +pdc : (+) Promise FastTrack +.br +sil : (+) Silicon Image(tm) Medley(tm) +.br +via : (+) VIA Software RAID +.br +dos : (+) DOS partitions on SW RAIDs +.br +(0): Discover, (+): Discover+Activate + +"dmraid -ay" activates all software RAID sets discovered. + +"dmraid -an" deactivates all active software RAID sets which are not open +(eg, mounted filesystem on them). + +"dmraid -ay -f pdc" (pdc looked up from "dmraid -l") activates all +software RAID sets with Promise format discovered and ignores all other +supported formats. + +"dmraid -r" discovers all software RAID devices supported on your system, eg: +.br +/dev/dm-46: hpt45x, "hpt45x_chidjhaiaa-0", striped, ok, 320172928 sectors, data@ 0 +.br +/dev/dm-50: hpt45x, "hpt45x_chidjhaiaa-0", striped, ok, 320172928 sectors, data@ 0 +.br +/dev/dm-54: hpt45x, "hpt45x_chidjhaiaa-1", striped, ok, 320172928 sectors, data@ 0 +.br +/dev/dm-58: hpt45x, "hpt45x_chidjhaiaa-1", striped, ok, 320172928 sectors, data@ 0 + + +"dmraid -s -s hpt45x_chidjhaiaa" displays properties of +set "hpt45x_chidjhaiaa", eg: +.br +*** Superset +.br +name : hpt45x_chidjhaiaa +.br +size : 640345856 +.br +stride : 128 +.br +type : raid10 +.br +status : ok +.br +subsets: 2 +.br +dev : 4 +.br +spare : 0 +.br +---> Subset +.br +name : hpt45x_chidjhaiaa-0 +.br +size : 640345856 +.br +stride : 128 +.br +type : stripe +.br +status : ok +.br +subsets: 0 +.br +dev : 2 +.br +spare : 0 +.br +---> Subset +.br +name : hpt45x_chidjhaiaa-1 +.br +size : 640345856 +.br +stride : 128 +.br +type : stripe +.br +status : ok +.br +subsets: 0 +.br +dev : 2 +.br +spare : 0 +.br + +"dmraid -s -ccs hpt45" displays properties in column format of all sets +and subsets with hpt45* format, eg: +.br +hpt45x_chidjhaiaa,640345856,128,raid10,ok,4,0 +.br +hpt45x_chidjhaiaa-a,640345856,128,stripe,ok,2,0 +.br +hpt45x_chidjhaiaa-b,640345856,128,stripe,ok,2,0 + +"dmraid -r --sep : -cpath:size" display paths and sizes in sectors for +RAID devices in column format using ':' as a delimiter, eg: +.br +/dev/dm-8:320173055 +.br +/dev/dm-12:320173055 +.br +/dev/dm-22:320173055 +.br +/dev/dm-26:320173055 +.br +/dev/dm-30:586114703 +.br +/dev/dm-34:586114703 +.br +/dev/dm-38:586114703 +.br +/dev/dm-42:586114703 +.br +/dev/dm-46:156301487 +.br +/dev/dm-50:156301487 +.br +/dev/dm-54:390624896 +.br +/dev/dm-58:390624896 +.br +/dev/dm-62:390624896 +.br +/dev/dm-66:390624896 + +"dmraid -f isw -C Raid0 --type 0 --strip 8k --size 20g --disk "/dev/sdb /dev/sdc"" creates an ISW volume with +a name of "Raid0", 20Gig bytes in total, and 8kilo bytes strip size on two disks. + +"dmraid -f isw -C Test0 --type 0 --disk "/dev/sdd /dev/sde"" creates an ISW volume with the default size and strip size. + +"dmraid -f isw -C Test10 --type 01 --strip 128B --disk "/dev/sda /dev/sdb /dev/sdc /dev/sdd" creates a stacked +RAID device, RAID10 (isw format), with a name of "Test10", 128 blocks (512bytes) strip size , and the default volume size on +4 disks. + +"dmraid -f isw -S -M /dev/sde" marks the device /dev/sde as a hot spare for rebuild + +"dmraid -R isw_djaggchdde_RAID1 /dev/sde" starts rebuild of the RAID volume on device /dev/sde + +.SH DIAGNOSTICS +dmraid returns an exit code of 0 for success or 1 for error. + +.SH AUTHOR +Heinz Mauelshagen <Mauelshagen@xxxxxxxxxx> --- dmraid/tools/VERSION 2008/04/02 13:35:32 1.5 +++ dmraid/tools/VERSION 2008/06/20 21:52:19 1.6 @@ -1 +1 @@ -1.0.0.rc15 (2008.04.02) +1.0.0.rc15 (2008-06-20) --- dmraid/tools/commands.c 2008/04/02 13:35:32 1.2 +++ dmraid/tools/commands.c 2008/06/20 21:52:19 1.3 @@ -1,7 +1,10 @@ /* - * Copyright (C) 2004,2005 Heinz Mauelshagen, Red Hat GmbH. + * Copyright (C) 2004-2008 Heinz Mauelshagen, Red Hat GmbH. * All rights reserved. * + * Copyright (C) 2007 Intel Corporation. All rights reserved. + * November, 2007 - additions for Create, Delete, Rebuild & Raid 10. + * * See file LICENSE at the top of this source tree for license information. */ @@ -21,18 +24,21 @@ /* Action flags */ enum action action = UNDEF; +int add_dev_to_array(struct lib_context *lc, struct raid_set *rs, + uint build_metadata, struct raid_dev *hot_spare_rd); + /* * Command line options. */ static char const *short_opts = "a:hipP:" #ifndef DMRAID_MINI - "bc::dDEf:gl" + "bc::dDEf:glxM:" #ifdef DMRAID_NATIVE_LOG - "n" + "n" #endif - "rs::tv" + "rR:s::tv" #endif - "V"; + "VC:S::"; #ifdef HAVE_GETOPTLONG static struct option long_opts[] = { @@ -52,16 +58,21 @@ {"ignorelocking", no_argument, NULL, 'i'}, # ifndef DMRAID_MINI {"list_formats", no_argument, NULL, 'l'}, + {"media", required_argument, NULL, 'M'}, # ifdef DMRAID_NATIVE_LOG {"native_log", no_argument, NULL, 'n'}, # endif {"raid_devices", no_argument, NULL, 'r'}, + {"rebuild", required_argument, NULL, 'R'}, {"sets", optional_argument, NULL, 's'}, - {"separator", required_argument, NULL, SEPARATOR}, /* long only. */ + {"remove", no_argument, NULL, 'x'}, + {"separator", required_argument, NULL, SEPARATOR}, /* long only. */ {"test", no_argument, NULL, 't'}, {"verbose", no_argument, NULL, 'v'}, # endif {"version", no_argument, NULL, 'V'}, + {"create", required_argument, NULL, 'C'}, + {"spare", optional_argument, NULL, 'S'}, {NULL, no_argument, NULL, 0} }; #endif /* #ifdef HAVE_GETOPTLONG */ @@ -73,8 +84,8 @@ }; /* Check option argument. */ -static int check_optarg(struct lib_context *lc, const char option, - struct optarg_def *def) +static int +check_optarg(struct lib_context *lc, const char option, struct optarg_def *def) { size_t len; struct optarg_def *d; @@ -91,16 +102,17 @@ } } - LOG_ERR(lc, 0, "Invalid option argument for -%c", option); + LOG_ERR(lc, 0, "invalid option argument for -%c", option); } /* Check activate/deactivate option arguments. */ -static int check_activate(struct lib_context *lc, int arg) +static int +check_activate(struct lib_context *lc, int arg) { struct optarg_def def[] = { - { "yes", ACTIVATE }, - { "no", DEACTIVATE }, - { NULL, UNDEF }, + { "yes", ACTIVATE}, + { "no", DEACTIVATE}, + { NULL, UNDEF}, }; return check_optarg(lc, 'a', def); @@ -108,21 +120,22 @@ #ifndef DMRAID_MINI /* Check active/inactive option arguments. */ -static int check_active(struct lib_context *lc, int arg) +static int +check_active(struct lib_context *lc, int arg) { struct optarg_def def[] = { - { "active", ACTIVE }, - { "inactive", INACTIVE }, - { NULL, UNDEF }, + { "active", ACTIVE}, + { "inactive", INACTIVE}, + { NULL, UNDEF}, }; lc_inc_opt(lc, LC_SETS); - return check_optarg(lc, 's', def); } /* Check and store option arguments. */ -static int check_identifiers(struct lib_context *lc, int o) +static int +check_identifiers(struct lib_context *lc, int o) { if (optarg) { const char delim = *OPT_STR_SEPARATOR(lc); @@ -135,22 +148,48 @@ } lc_inc_opt(lc, o); - return 1; } /* Check and store option argument/output field separator. */ -static int check_separator(struct lib_context *lc, int arg) +static int +check_separator(struct lib_context *lc, int arg) { if (strlen(optarg) != 1) - LOG_ERR(lc, 0, "Invalid separator \"%s\"", optarg); + LOG_ERR(lc, 0, "invalid separator \"%s\"", optarg); return lc_stralloc_opt(lc, LC_SEPARATOR, optarg) ? 1 : 0; } + +/* Check create option arguments. */ +static int +check_create_argument(struct lib_context *lc, int arg) +{ + size_t len; + + len = strlen(optarg); + if (len < 1) + LOG_ERR(lc, 0, "arguments missing"); + + if (*optarg == '-') + LOG_ERR(lc, 0, "the raid set name is missing"); + + lc_inc_opt(lc, arg); + return 1; +} + +/* 'Check' spare option argument. */ +static int +check_spare_argument(struct lib_context *lc, int arg) +{ + lc_inc_opt(lc, arg); + return 1; +} #endif /* Check and store option for partition separator. */ -static int check_part_separator(struct lib_context *lc, int arg) +static int +check_part_separator(struct lib_context *lc, int arg) { /* We're not actually checking that it's only one character... if somebody wants to use more, it shouldn't hurt anything. */ @@ -158,7 +197,8 @@ } /* Display help information */ -static int help(struct lib_context *lc, int arg) +static int +help(struct lib_context *lc, int arg) { char *c = lc->cmd; @@ -169,21 +209,21 @@ "\t[-f|--format FORMAT[,FORMAT...]]\n" "\t[-P|--partchar CHAR]\n" "\t[-p|--no_partitions]\n" - "\t[--separator SEPARATOR]\n" - "\t[RAID-set...]\n", c); + "\t[--separator SEPARATOR]\n" "\t[RAID-set...]\n", c); log_print(lc, "%s\t{-h|--help}\n", c); log_print(lc, "%s\t{-V/--version}\n", c); #else log_print(lc, "%s: Device-Mapper Software RAID tool\n", c); - log_print(lc, "* = [-d|--debug]... [-v|--verbose]... [-i|--ignorelocking]\n"); - log_print(lc, "%s\t{-a|--activate} {y|n|yes|no} *\n" + log_print(lc, + "* = [-d|--debug]... [-v|--verbose]... [-i|--ignorelocking]\n"); + log_print(lc, + "%s\t{-a|--activate} {y|n|yes|no} *\n" "\t[-f|--format FORMAT[,FORMAT...]]\n" - "\t[-P|--partchar CHAR]\n" - "\t[-p|--no_partitions]\n" - "\t[--separator SEPARATOR]\n" - "\t[-t|--test]\n" + "\t[-P|--partchar CHAR]\n" "\t[-p|--no_partitions]\n" + "\t[--separator SEPARATOR]\n" "\t[-t|--test]\n" "\t[RAID-set...]\n", c); - log_print(lc, "%s\t{-b|--block_devices} *\n" + log_print(lc, + "%s\t{-b|--block_devices} *\n" "\t[-c|--display_columns][FIELD[,FIELD...]]...\n" "\t[device-path...]\n", c); log_print(lc, "%s\t{-h|--help}\n", c); @@ -191,29 +231,34 @@ # ifdef DMRAID_NATIVE_LOG log_print(lc, "%s\t{-n|--native_log} *\n" "\t[-f|--format FORMAT[,FORMAT...]]\n" - "\t[--separator SEPARATOR]\n" - "\t[device-path...]\n", c); + "\t[--separator SEPARATOR]\n" "\t[device-path...]\n", c); # endif log_print(lc, "%s\t{-r|--raid_devices} *\n" "\t[-c|--display_columns][FIELD[,FIELD...]]...\n" "\t[-D|--dump_metadata]\n" "\t[-f|--format FORMAT[,FORMAT...]]\n" - "\t[--separator SEPARATOR]\n" - "\t[device-path...]\n", c); + "\t[--separator SEPARATOR]\n" "\t[device-path...]\n", c); log_print(lc, "%s\t{-r|--raid_devices} *\n" "\t{-E|--erase_metadata}\n" "\t[-f|--format FORMAT[,FORMAT...]]\n" - "\t[--separator SEPARATOR]\n" - "\t[device-path...]\n", c); + "\t[--separator SEPARATOR]\n" "\t[device-path...]\n", c); log_print(lc, "%s\t{-s|--sets}...[a|i|active|inactive] *\n" "\t[-c|--display_columns][FIELD[,FIELD...]]...\n" "\t[-f|--format FORMAT[,FORMAT...]]\n" "\t[-g|--display_group]\n" - "\t[--separator SEPARATOR]\n" - "\t[RAID-set...]\n", c); + "\t[--separator SEPARATOR]\n" "\t[RAID-set...]\n", c); + log_print(lc, "%s\t{-f|--format FORMAT}\n \t{-C|--create RAID-set} \n" + "\t{--type RAID-level}\n" + "\t[--size [0-9]...[kKgG][bB]]\n" + "\t[--str[i[de]] [0-9]...[kK][bB]]\n" + "\t{--disk[s] \"device-path[, device-path...\"}\n", c); + log_print(lc, "%s\t{-x|--remove RAID-set} \n"); + log_print(lc, "%s\t{-R|--rebuild} RAID-set [drive_name]\n", c); + log_print(lc, "%s\t[{-f|--format FORMAT}]\n" + "\t{-S|--spare [RAID-set]} \n" + "\t{-M|--media \"device-path\"}\n", c); log_print(lc, "%s\t{-V/--version}\n", c); #endif - return 1; } @@ -225,247 +270,316 @@ */ static struct actions actions[] = { /* [De]activate option. */ - { 'a', - UNDEF, /* Set in check_activate() by mandatory option argument. */ - UNDEF, - ACTIVATE|DEACTIVATE|FORMAT|HELP|IGNORELOCKING|NOPARTITIONS|SEPARATOR + {'a', + UNDEF, /* Set in check_activate() by mandatory option argument. */ + UNDEF, + ACTIVATE | DEACTIVATE | FORMAT | HELP | IGNORELOCKING | NOPARTITIONS | + SEPARATOR #ifndef DMRAID_MINI - |DBG|TEST|VERBOSE + | DBG | TEST | VERBOSE #endif - , ARGS, - check_activate, - 0, - }, + , ARGS, + check_activate, + 0, + }, /* Format option. */ - { 'f', - FORMAT, - ACTIVATE|DEACTIVATE + {'f', + FORMAT, + ACTIVATE | DEACTIVATE #ifndef DMRAID_MINI # ifdef DMRAID_NATIVE_LOG - |NATIVE_LOG + | NATIVE_LOG # endif - |RAID_DEVICES|RAID_SETS, - ACTIVE|INACTIVE|COLUMN|DBG|DUMP|ERASE|GROUP|HELP| - IGNORELOCKING|NOPARTITIONS|SEPARATOR|TEST|VERBOSE + | RAID_DEVICES | RAID_SETS, + ACTIVE | INACTIVE | COLUMN | DBG | DUMP | DMERASE | GROUP | HELP | + IGNORELOCKING | NOPARTITIONS | SEPARATOR | TEST | VERBOSE #else - , UNDEF + , UNDEF #endif - , ARGS, + , ARGS, #ifndef DMRAID_MINI - check_identifiers, + check_identifiers, #else - NULL, + NULL, #endif - LC_FORMAT, - }, + LC_FORMAT, + }, /* Partition separator. */ - { 'P', - PARTCHAR, - ACTIVATE|DEACTIVATE, - FORMAT|HELP|IGNORELOCKING|SEPARATOR + {'P', + PARTCHAR, + ACTIVATE | DEACTIVATE, + FORMAT | HELP | IGNORELOCKING | SEPARATOR #ifndef DMRAID_MINI - |DBG|TEST|VERBOSE + | DBG | TEST | VERBOSE #endif - , ARGS, - check_part_separator, - 0, - }, + , ARGS, + check_part_separator, + 0, + }, /* Partition option. */ - { 'p', - NOPARTITIONS, - ACTIVATE|DEACTIVATE, - FORMAT|HELP|IGNORELOCKING|SEPARATOR + {'p', + NOPARTITIONS, + ACTIVATE | DEACTIVATE, + FORMAT | HELP | IGNORELOCKING | SEPARATOR #ifndef DMRAID_MINI - |DBG|TEST|VERBOSE + | DBG | TEST | VERBOSE #endif - , ARGS, - NULL, - 0, - }, + , ARGS, + NULL, + 0, + }, #ifndef DMRAID_MINI /* Block devices option. */ - { 'b', - BLOCK_DEVICES, - UNDEF, - COLUMN|DBG|HELP|IGNORELOCKING|SEPARATOR|VERBOSE, - ARGS, - lc_inc_opt, - LC_DEVICES, - }, + {'b', + BLOCK_DEVICES, + UNDEF, + COLUMN | DBG | HELP | IGNORELOCKING | SEPARATOR | VERBOSE, + ARGS, + lc_inc_opt, + LC_DEVICES, + }, /* Columns display option. */ - { 'c', - COLUMN, - BLOCK_DEVICES|RAID_DEVICES|RAID_SETS, - ACTIVE|INACTIVE|DBG|DUMP|FORMAT|GROUP|HELP|IGNORELOCKING - |SEPARATOR|VERBOSE, - ARGS, - check_identifiers, - LC_COLUMN, - }, + {'c', + COLUMN, + BLOCK_DEVICES | RAID_DEVICES | RAID_SETS, + ACTIVE | INACTIVE | DBG | DUMP | FORMAT | GROUP | HELP | IGNORELOCKING + | SEPARATOR | VERBOSE, + ARGS, + check_identifiers, + LC_COLUMN, + }, /* Debug option. */ - { 'd', - DBG, - ALL_FLAGS, - ALL_FLAGS, - ARGS, - lc_inc_opt, - LC_DEBUG, - }, + {'d', + DBG, + ALL_FLAGS, + ALL_FLAGS, + ARGS, + lc_inc_opt, + LC_DEBUG, + }, /* Dump metadata option. */ - { 'D', - DUMP, - RAID_DEVICES, - COLUMN|DBG|FORMAT|HELP|IGNORELOCKING|SEPARATOR|VERBOSE, - ARGS, - lc_inc_opt, - LC_DUMP, - }, + {'D', + DUMP, + RAID_DEVICES, + COLUMN | DBG | FORMAT | HELP | IGNORELOCKING | SEPARATOR | VERBOSE, + ARGS, + lc_inc_opt, + LC_DUMP, + }, /* Erase metadata option. */ - { 'E', - ERASE, - RAID_DEVICES, - COLUMN|DBG|FORMAT|HELP|IGNORELOCKING|SEPARATOR|VERBOSE, - ARGS, - NULL, - 0, - }, + {'E', + DMERASE, + RAID_DEVICES, + COLUMN | DBG | FORMAT | HELP | IGNORELOCKING | SEPARATOR | VERBOSE, + ARGS, + NULL, + 0, + }, /* RAID groups option. */ - { 'g', - GROUP, - RAID_SETS, - ACTIVE|INACTIVE|DBG|COLUMN|FORMAT|HELP|IGNORELOCKING - |SEPARATOR|VERBOSE, - ARGS, - lc_inc_opt, - LC_GROUP, - }, + {'g', + GROUP, + RAID_SETS, + ACTIVE | INACTIVE | DBG | COLUMN | FORMAT | HELP | IGNORELOCKING + | SEPARATOR | VERBOSE, + ARGS, + lc_inc_opt, + LC_GROUP, + }, #endif /* Help option. */ - { 'h', - HELP, - UNDEF, - ALL_FLAGS, - ARGS, - help, - 0, - }, + {'h', + HELP, + UNDEF, + ALL_FLAGS, + ARGS, + help, + 0, + }, /* ignorelocking option. */ - { 'i', - IGNORELOCKING, - UNDEF, - ALL_FLAGS, - ARGS, - lc_inc_opt, - LC_IGNORELOCKING, - }, + {'i', + IGNORELOCKING, + UNDEF, + ALL_FLAGS, + ARGS, + lc_inc_opt, + LC_IGNORELOCKING, + }, #ifndef DMRAID_MINI /* List metadata format handlers option. */ - { 'l', - LIST_FORMATS, - UNDEF, - DBG|HELP|IGNORELOCKING|VERBOSE, - NO_ARGS, - NULL, - 0, - }, + {'l', + LIST_FORMATS, + UNDEF, + DBG | HELP | IGNORELOCKING | VERBOSE, + NO_ARGS, + NULL, + 0, + }, + + /* Delete a RAID set option. */ + {'x', + DEL_SETS, + UNDEF, //RAID_SETS, + RAID_SETS | INACTIVE | COLUMN | DBG | FORMAT | GROUP | HELP | + IGNORELOCKING | SEPARATOR | VERBOSE, + ARGS, + NULL, + 0, + }, # ifdef DMRAID_NATIVE_LOG /* Native log option. */ - { 'n', - NATIVE_LOG, - UNDEF, - DBG|FORMAT|HELP|IGNORELOCKING|SEPARATOR|VERBOSE, - ARGS, - NULL, - 0, - }, + {'n', + NATIVE_LOG, + UNDEF, + DBG | FORMAT | HELP | IGNORELOCKING | SEPARATOR | VERBOSE, + ARGS, + NULL, + 0, + }, # endif /* Display RAID devices option. */ - { 'r', - RAID_DEVICES, - UNDEF, - COLUMN|DBG|DUMP|ERASE|FORMAT|HELP|IGNORELOCKING|SEPARATOR|VERBOSE, - ARGS, - NULL, - 0, - }, + {'r', + RAID_DEVICES, + UNDEF, + COLUMN | DBG | DUMP | DMERASE | FORMAT | HELP | IGNORELOCKING | + SEPARATOR | VERBOSE, + ARGS, + NULL, + 0, + }, + + /* rebuild option */ + {'R', + REBUILD, + UNDEF, +#ifdef DMRAID_MINI + HELP, IGNORELOCKING, +#else + DBG | HELP | IGNORELOCKING | VERBOSE, +#endif + ARGS, +#ifndef DMRAID_MINI + check_identifiers, +#else + NULL, +#endif + LC_REBUILD_SET, + }, + + /* Media/drive option */ + {'M', + MEDIA, + UNDEF, +#ifdef DMRAID_MINI + HELP, IGNORELOCKING, +#else + DBG | HELP | IGNORELOCKING | VERBOSE | REBUILD, +#endif + ARGS, +#ifndef DMRAID_MINI + check_identifiers, +#else + NULL, +#endif + LC_REBUILD_DISK, + }, /* Display RAID sets option. */ - { 's', - RAID_SETS, - UNDEF, - ACTIVE|INACTIVE|COLUMN|DBG|FORMAT|GROUP|HELP|IGNORELOCKING - |SEPARATOR|VERBOSE, - ARGS, - check_active, - 0, - }, + {'s', + RAID_SETS, + UNDEF, + ACTIVE | INACTIVE | COLUMN | DBG | FORMAT | GROUP | HELP | + IGNORELOCKING | DEL_SETS | SEPARATOR | VERBOSE, + ARGS, + check_active, + 0, + }, /* Display RAID sets option. */ - { SEPARATOR, - SEPARATOR, - COLUMN|FORMAT, - ALL_FLAGS, - ARGS, - check_separator, - 0, - }, + {SEPARATOR, + SEPARATOR, + COLUMN | FORMAT, + ALL_FLAGS, + ARGS, + check_separator, + 0, + }, /* Test run option. */ - { 't', - TEST, - ACTIVATE|DEACTIVATE, - ACTIVATE|DEACTIVATE|DBG|FORMAT|HELP|IGNORELOCKING| - NOPARTITIONS|VERBOSE, - ARGS, - lc_inc_opt, - LC_TEST, - }, + {'t', + TEST, + ACTIVATE | DEACTIVATE, + ACTIVATE | DEACTIVATE | DBG | FORMAT | HELP | IGNORELOCKING | + NOPARTITIONS | VERBOSE, + ARGS, + lc_inc_opt, + LC_TEST, + }, /* Verbose option. */ - { 'v', - VERBOSE, - ALL_FLAGS, - ALL_FLAGS, - ARGS, - lc_inc_opt, - LC_VERBOSE, - }, + {'v', + VERBOSE, + ALL_FLAGS, + ALL_FLAGS, + ARGS, + lc_inc_opt, + LC_VERBOSE, + }, #endif /* #ifndef DMRAID_MINI */ /* Version option. */ - { 'V', - VERSION, - UNDEF, + {'V', + VERSION, + UNDEF, #ifdef DMRAID_MINI - HELP,IGNORELOCKING, + HELP, IGNORELOCKING, #else - DBG|HELP|IGNORELOCKING|VERBOSE, + DBG | HELP | IGNORELOCKING | VERBOSE, #endif - NO_ARGS, - NULL, - 0, - }, + NO_ARGS, + NULL, + 0, + }, + + /* RAID set creation. */ + {'C', + CREATE, + UNDEF, + DBG | HELP | IGNORELOCKING | VERBOSE, + NO_ARGS, + check_create_argument, + LC_CREATE, + }, + /* Spare disk creation. */ + {'S', + SPARE, + UNDEF, + DBG | HELP | IGNORELOCKING | VERBOSE, + NO_ARGS, + check_spare_argument, + LC_HOT_SPARE_SET, + }, }; /* * Set action flag and call optional function. */ -static int set_action(struct lib_context *lc, int o) +static int +set_action(struct lib_context *lc, int o) { struct actions *a; @@ -474,6 +588,7 @@ action |= a->action; /* Set action flag. */ a->allowed |= a->action;/* Merge to allowed flags. */ a->allowed |= a->needed; + if (a->f_set) /* Optionally call function. */ return a->f_set(lc, a->arg); @@ -485,38 +600,37 @@ } /* Check for invalid option combinations */ -static int check_actions(struct lib_context *lc, char **argv) +static int +check_actions(struct lib_context *lc, char **argv) { struct actions *a; for (a = actions; a < ARRAY_END(actions); a++) { if (a->action & action) { - if (a->needed != UNDEF && - !(a->needed & action)) + if (a->needed != UNDEF && !(a->needed & action)) LOG_ERR(lc, 0, "option missing/invalid option " - "combination with -%c", - a->option); + "combination with -%c", a->option); if (~a->allowed & action) - LOG_ERR(lc, 0, "Invalid option combination" - " (-h for help)"); + LOG_ERR(lc, 0, "invalid option combination" + " (-h for help)"); if (a->args == NO_ARGS && argv[optind]) LOG_ERR(lc, 0, - "No arguments allowed with -%c\n", + "no arguments allowed with -%c\n", a->option); } } if (!action) - LOG_ERR(lc, 0, "Options missing\n"); + LOG_ERR(lc, 0, "options missing\n"); #ifndef DMRAID_MINI - if ((action & (DBG|VERBOSE)) == action) - LOG_ERR(lc, 0, "More options needed with -d/-v"); + if ((action & (DBG | VERBOSE)) == action) + LOG_ERR(lc, 0, "more options needed with -d/-v"); - if (action & ERASE) { + if (action & DMERASE) { action |= DUMP; lc_inc_opt(lc, LC_DUMP); } @@ -526,16 +640,42 @@ } /* Check for invalid option argumengts. */ -static int check_actions_arguments(struct lib_context *lc) +static int +check_actions_arguments(struct lib_context *lc) { if (valid_format(lc, OPT_STR_FORMAT(lc))) return 1; - LOG_ERR(lc, 0, "Invalid format for -f at (see -l)"); + LOG_ERR(lc, 0, "invalid format for -f at (see -l)"); } +int +save_drive_name(struct lib_context *lc, char *drive) +{ + lc->options[LC_REBUILD_DISK].opt++; + return lc_strcat_opt(lc, LC_REBUILD_DISK, drive, ',') ? 1 : 0; +} + +static int +save_spare_name(struct lib_context *lc, char **argv) +{ + char *p = argv[optind]; + + lc->options[LC_HOT_SPARE_SET].arg.str = NULL; + + if (p && strlen(p) && *p != '-') { + lc->options[LC_HOT_SPARE_SET].arg.str = dbg_strdup(p); + if (!lc->options[LC_HOT_SPARE_SET].arg.str) + return log_alloc_err(lc, __func__); + } + + return 1; +} + + /* Parse and handle the command line arguments */ -int handle_args(struct lib_context *lc, int argc, char ***argv) +int +handle_args(struct lib_context *lc, int argc, char ***argv) { int o, ret = 0; #ifdef HAVE_GETOPTLONG @@ -543,7 +683,7 @@ #endif if (argc < 2) - LOG_ERR(lc, 0, "No arguments/options given (-h for help)\n"); + LOG_ERR(lc, 0, "no arguments/options given (-h for help)\n"); #ifdef HAVE_GETOPTLONG /* Walk the options (and option arguments) */ @@ -556,6 +696,29 @@ if ((ret = set_action(lc, o)) && (HELP & action)) return 1; + /* Handle arguments for option -S */ + if (o == 'S') { + if (!save_spare_name(lc, *argv)) + return 0; + } + + /* to create spare disk/set */ + if (o == 'M' && + OPT_HOT_SPARE_SET(lc) && + OPT_REBUILD_DISK(lc)) { + *argv += optind - 3; + return 1; + } + + /* To create a new RAID set; arguments are handled later */ + if (o == 'C') { + *argv += optind - 1; + return 1; + } else if (o == 'R' && argc == 4) { + if (*(*argv + optind)) + save_drive_name(lc, *(*argv + optind)); + } + if (!ret || o == ':' || o == '?') return 0; } @@ -569,107 +732,103 @@ ret = check_actions_arguments(lc); *argv += optind; + if (argc == 4 && lc->options[LC_REBUILD_SET].opt) + *argv += 1; return ret; } -static int version(struct lib_context *lc, int arg) +static int +version(struct lib_context *lc, int arg) { char v[80]; dm_version(lc, v, sizeof(v)); log_print(lc, "%s version:\t\t%s\n" - "%s library version:\t%s %s\n" - "device-mapper version:\t%s", - lc->cmd, DMRAID_VERSION, - lc->cmd, libdmraid_version(lc), libdmraid_date(lc), v); + "%s library version:\t%s %s\n" + "device-mapper version:\t%s", + lc->cmd, DMRAID_VERSION, + lc->cmd, libdmraid_version(lc), libdmraid_date(lc), v); return 1; } +static int +rebuild(struct lib_context *lc, int arg) +{ + return rebuild_raidset(lc, + (char *) lc->options[LC_REBUILD_SET].arg.str); +} + /********************************************************************* * Perform pre/post functions for requested actions. */ /* Post Activate/Deactivate RAID set. */ #ifndef DMRAID_MINI /* Pre and post display_set() functions. */ -static int _display_sets_arg(int arg) +static int +_display_sets_arg(int arg) { return (action & ACTIVE) ? - D_ACTIVE : ((action & INACTIVE) ? D_INACTIVE : D_ALL); + D_ACTIVE : ((action & INACTIVE) ? D_INACTIVE : D_ALL); } -static int _display_set(struct lib_context *lc, void *rs, int type) +static int +_display_set(struct lib_context *lc, void *rs, int type) { display_set(lc, rs, type, 0); - return 1; } -static int _display_sets(struct lib_context *lc, int type) +static int +_display_sets(struct lib_context *lc, int type) { process_sets(lc, _display_set, type, SETS); + return 1; +} +static int +_delete_sets(struct lib_context *lc, int arg) +{ + delete_raidsets(lc); return 1; } -static int _display_devices(struct lib_context *lc, int type) +static int +_create_sets(struct lib_context *lc, int arg) { - display_devices(lc, type); + return 1; +} +static int +_display_devices(struct lib_context *lc, int type) +{ + display_devices(lc, type); return 1; } -static int _erase(struct lib_context *lc, int arg) +static int +_erase(struct lib_context *lc, int arg) { return erase_metadata(lc); } -#endif -/* Retrieve and build metadata. */ -static int get_metadata(struct lib_context *lc, struct prepost *p, char **argv) +/* Post hot_spare_add function */ +static int +_hot_spare_add_set(struct lib_context *lc, void *r, int type) { - if (!(M_DEVICE & p->metadata)) - return 1; - - if (!discover_devices(lc, OPT_DEVICES(lc) ? argv : NULL)) - LOG_ERR(lc, 0, "failed to discover devices"); - - if(!count_devices(lc, DEVICE)) { - log_print(lc, "no block devices found"); - return 1; - } + return hot_spare_add(lc, (struct raid_set*) r); +} - if (!(M_RAID & p->metadata)) - return 1; +static int +_hot_spare_add(struct lib_context *lc, int type) +{ + process_sets(lc, _hot_spare_add_set, type, SETS); + return 1; +} -#ifndef DMRAID_MINI - /* Discover RAID disks and keep RAID metadata (eg, hpt45x) */ - discover_raid_devices(lc, -# ifdef DMRAID_NATIVE_LOG - ((NATIVE_LOG|RAID_DEVICES) & action) ? argv : NULL); -# else - (RAID_DEVICES & action) ? argv : NULL); -# endif -#else - discover_raid_devices(lc, NULL); #endif - if (!count_devices(lc, RAID)) { - format_error(lc, "disks", argv); - return 1; - } - if (M_SET & p->metadata) { - /* Group RAID sets. */ - build_sets(lc, argv); - if (!count_devices(lc, SET)) { - format_error(lc, "sets", argv); - return 0; - } - } - - return 1; -} /* * Function abstraction which takes pre- and post-function calls @@ -692,112 +851,136 @@ */ struct prepost prepost[] = { /* (De)activate RAID set. */ - { ACTIVATE|DEACTIVATE, - M_DEVICE|M_RAID|M_SET, - ROOT, - LOCK, - NULL, - 0, - activate_or_deactivate_sets, - }, + {ACTIVATE | DEACTIVATE, + M_DEVICE | M_RAID | M_SET, + ROOT, + LOCK, + NULL, + 0, + activate_or_deactivate_sets, + }, #ifndef DMRAID_MINI /* Display block devices. */ - { BLOCK_DEVICES, - M_DEVICE, - ROOT, - NO_LOCK, - NULL, - DEVICE, - _display_devices, - }, + {BLOCK_DEVICES, + M_DEVICE, + ROOT, + NO_LOCK, + NULL, + DEVICE, + _display_devices, + }, /* Erase metadata. */ - { ERASE, - M_DEVICE|M_RAID, - ROOT, - LOCK, - NULL, - 0, - _erase, - }, + {DMERASE, + M_DEVICE | M_RAID, + ROOT, + LOCK, + NULL, + 0, + _erase, + }, /* List metadata format handlers. */ - { LIST_FORMATS, - M_NONE, - ANY_ID, - NO_LOCK, - NULL, - 0, - list_formats, - }, + {LIST_FORMATS, + M_NONE, + ANY_ID, + NO_LOCK, + NULL, + 0, + list_formats, + }, # ifdef DMRAID_NATIVE_LOG /* Native metadata log. */ - { NATIVE_LOG, - M_DEVICE|M_RAID, - ROOT, - LOCK, - NULL, - NATIVE, - _display_devices, - }, + {NATIVE_LOG, + M_DEVICE | M_RAID, + ROOT, + LOCK, + NULL, + NATIVE, + _display_devices, + }, # endif /* Display RAID devices. */ - { RAID_DEVICES, - M_DEVICE|M_RAID, - ROOT, - LOCK, - NULL, - RAID, - _display_devices, - }, + {RAID_DEVICES, + M_DEVICE | M_RAID, + ROOT, + LOCK, + NULL, + RAID, + _display_devices, + }, + + /* Delete RAID sets. */ + {DEL_SETS, + M_DEVICE | M_RAID | M_SET, + ROOT, + LOCK, + NULL, + 0, + _delete_sets, + }, /* Display RAID sets. */ - { RAID_SETS, - M_DEVICE|M_RAID|M_SET, - ROOT, - LOCK, - _display_sets_arg, - 0, - _display_sets, - }, + {RAID_SETS, + M_DEVICE | M_RAID | M_SET, + ROOT, + LOCK, + _display_sets_arg, + 0, + _display_sets, + }, + #endif /* Display version. */ - { VERSION, - M_NONE, - ANY_ID, - NO_LOCK, - NULL, - 0, - version, - }, -}; + {VERSION, + M_NONE, + ANY_ID, + NO_LOCK, + NULL, + 0, + version, + }, + + /* Create a RAID set. */ + {CREATE, + M_DEVICE | M_RAID | M_SET, + ROOT, + LOCK, + NULL, + 0, + _create_sets, + }, + + /* Add spare disk to a RAID set. */ + {SPARE, + M_DEVICE | M_RAID | M_SET, + ROOT, + LOCK, + NULL, + 0, + _hot_spare_add, + }, + + + /* Rebuild */ + {REBUILD, + M_DEVICE | M_RAID | M_SET, + ROOT, + LOCK, + NULL, + 0, + rebuild, + }, -static int _perform(struct lib_context *lc, struct prepost *p, - char **argv) -{ - int ret = 0; - - if (ROOT == p->id && geteuid()) - LOG_ERR(lc, 0, "you must be root"); - - /* Lock against parallel runs. Resource NULL for now. */ - if (LOCK == p->lock && !lock_resource(lc, NULL)) - LOG_ERR(lc, 0, "lock failure"); - - if (get_metadata(lc, p, argv)) - ret = p->post(lc, p->pre ? p->pre(p->arg) : p->arg); - - if (LOCK == p->lock) - unlock_resource(lc, NULL); - - return ret; -} +}; -int perform(struct lib_context *lc, char **argv) +/* Perform pre/post actions for options. */ +int +perform(struct lib_context *lc, char **argv) { struct prepost *p; @@ -808,7 +991,8 @@ /* Find appropriate action. */ for (p = prepost; p < ARRAY_END(prepost); p++) { if (p->action & action) - return _perform(lc, p, argv); + return lib_perform(lc, action, p, argv); + } return 0; --- dmraid/tools/commands.h 2008/04/02 13:35:32 1.2 +++ dmraid/tools/commands.h 2008/06/20 21:52:19 1.3 @@ -2,6 +2,9 @@ * Copyright (C) 2004,2005 Heinz Mauelshagen, Red Hat GmbH. * All rights reserved. * + * Copyright (C) 2007 Intel Corporation. All rights reserved. + * November, 2007 - additions for Create, Delete, Rebuild & Raid 10. + * * See file LICENSE at the top of this source tree for license information. */ @@ -13,50 +16,8 @@ #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*a)) #define ARRAY_END(a) (a + ARRAY_SIZE(a)) -/* Options actions dmraid performs. */ -enum action { - UNDEF = 0x0, - ACTIVATE = 0x1, - DEACTIVATE = 0x2, - FORMAT = 0x4, -#ifndef DMRAID_MINI - BLOCK_DEVICES = 0x8, - COLUMN = 0x10, - DBG = 0x20, - DUMP = 0x40, - ERASE = 0x80, - GROUP = 0x100, -#endif - HELP = 0x200, -#ifndef DMRAID_MINI - LIST_FORMATS = 0x400, -# ifdef DMRAID_NATIVE_LOG - NATIVE_LOG = 0x800, -# endif -#endif - NOPARTITIONS = 0x1000, -#ifndef DMRAID_MINI - RAID_DEVICES = 0x2000, - RAID_SETS = 0x4000, - TEST = 0x8000, - VERBOSE = 0x10000, - ACTIVE = 0x20000, - INACTIVE = 0x40000, - SEPARATOR = 0x80000, -#endif - VERSION = 0x100000, - IGNORELOCKING = 0x200000, - PARTCHAR = 0x400000, -}; - #define ALL_FLAGS ((enum action) -1) -/* Arguments allowed ? */ -enum args { - NO_ARGS, - ARGS, -}; - /* * Action flag definitions for set_action(). * @@ -72,41 +33,10 @@ enum args args; /* Arguments allowed ? */ /* Function to call on hit or NULL */ - int (*f_set)(struct lib_context *lc, int arg); + int (*f_set) (struct lib_context * lc, int arg); int arg; /* Argument for above function call */ }; -/* Define which metadata is needed before we can call post functions. */ -enum metadata_need { - M_NONE = 0x00, - M_DEVICE = 0x01, - M_RAID = 0x02, - M_SET = 0x04, -}; - -enum id { - ROOT, - ANY_ID, -}; - -enum lock { - LOCK, - NO_LOCK, -}; - -/* - * Pre and Post functions to perform for an option. - */ -struct prepost { - enum action action; - enum metadata_need metadata; - enum id id; - enum lock lock; - int (*pre)(int arg); - int arg; - int (*post)(struct lib_context *lc, int arg); -}; - int handle_args(struct lib_context *lc, int argc, char ***argv); int perform(struct lib_context *lc, char **argv); --- dmraid/tools/dmraid.c 2008/02/22 16:57:37 1.1 +++ dmraid/tools/dmraid.c 2008/06/20 21:52:19 1.2 @@ -14,7 +14,8 @@ #include "toollib.h" #include "version.h" -int main(int argc, char **argv) +int +main(int argc, char **argv) { int ret = 0; struct lib_context *lc; @@ -32,13 +33,12 @@ * If both are ok -> perform the required action. */ ret = handle_args(lc, argc, &argv) && - init_locking(lc) && - perform(lc, argv); + init_locking(lc) && perform(lc, argv); /* Cleanup the library context. */ libdmraid_exit(lc); } /* Set standard exit code. */ - exit (ret ? EXIT_SUCCESS : EXIT_FAILURE); + exit(ret ? EXIT_SUCCESS : EXIT_FAILURE); } --- dmraid/tools/toollib.c 2008/02/22 16:57:37 1.1 +++ dmraid/tools/toollib.c 2008/06/20 21:52:19 1.2 @@ -1,7 +1,10 @@ /* - * Copyright (C) 2004,2005 Heinz Mauelshagen, Red Hat GmbH. + * Copyright (C) 2004-2008 Heinz Mauelshagen, Red Hat GmbH. * All rights reserved. * + * Copyright (C) 2007 Intel Corporation. All rights reserved. + * November, 2007 - additions for Create, Delete, Rebuild & Raid 10. + * * See file LICENSE at the top of this source tree for license information. */ @@ -23,13 +26,13 @@ #include "toollib.h" /* [De]activate a RAID set. */ -static int _change_set(struct lib_context *lc, void *rs, int arg) +static int +_change_set(struct lib_context *lc, void *rs, int arg) { - if (change_set(lc, - (ACTIVATE & action) ? A_ACTIVATE : A_DEACTIVATE, + if (change_set(lc, (ACTIVATE & action) ? A_ACTIVATE : A_DEACTIVATE, rs)) { - log_info(lc, "%sctivating %s RAID set \"%s\"", - action & ACTIVATE ? "A": "Dea", + log_info(lc, "%sctivating %s raid set \"%s\"", + action & ACTIVATE ? "A" : "Dea", get_set_type(lc, rs), get_set_name(lc, rs)); return 1; } @@ -39,13 +42,15 @@ /* [De]activate RAID sets. */ /* FIXME: remove partition code in favour of kpartx ? */ -static void process_partitions(struct lib_context *lc) +static void +process_partitions(struct lib_context *lc) { discover_partitions(lc); process_sets(lc, _change_set, 0, PARTITIONS); } -int activate_or_deactivate_sets(struct lib_context *lc, int arg) +int +activate_or_deactivate_sets(struct lib_context *lc, int arg) { /* Discover partitions to deactivate RAID sets for and work on them. */ if (DEACTIVATE & action) @@ -61,21 +66,15 @@ } /* Build all sets or the ones given. */ -void build_sets(struct lib_context *lc, char **sets) +void +build_sets(struct lib_context *lc, char **sets) { - int o = 0; - - do { - if (!group_set(lc, sets[o])) - log_err(lc, "building set"); - - if (!sets[o]) - break; - } while (sets[++o]); + group_set(lc, sets); } /* Convert a character string to lower case. */ -void str_tolower(char *s) +void +str_tolower(char *s) { for (; *s; s++) *s = tolower(*s); @@ -85,8 +84,9 @@ * Check if selected or all formats shall be used to read the metadata. */ /* Collapse a delimiter into one. */ -char *collapse_delimiter(struct lib_context *lc, char *str, - size_t size, const char delim) +char * +collapse_delimiter(struct lib_context *lc, char *str, + size_t size, const char delim) { size_t len; char *p = str; @@ -101,13 +101,14 @@ return str; } -int valid_format(struct lib_context *lc, const char *fmt) +int +valid_format(struct lib_context *lc, const char *fmt) { int ret = 1; char *p, *p_sav, *sep; const char delim = *OPT_STR_SEPARATOR(lc); - if (!(p_sav = dbg_strdup((char*) fmt))) + if (!(p_sav = dbg_strdup((char *) fmt))) return log_alloc_err(lc, __func__); sep = p_sav; @@ -122,29 +123,5 @@ } while (sep); dbg_free(p_sav); - return ret; } - -void format_error(struct lib_context *lc, const char *error, char **argv) -{ - log_print_nnl(lc, "No RAID %s", error); - - if (OPT_FORMAT(lc)) - log_print_nnl(lc, " with format: \"%s\"", - OPT_STR_FORMAT(lc)); - - - if (argv && *argv) { - log_print_nnl(lc, " and with names: \""); - while (*argv) { - log_print_nnl(lc, "%s", *argv++); - if (*argv) - log_print_nnl(lc, "%s", OPT_STR_SEPARATOR(lc)); - else - log_print_nnl(lc, "\""); - } - } - - log_print(lc, ""); -} --- dmraid/tools/toollib.h 2008/02/22 16:57:37 1.1 +++ dmraid/tools/toollib.h 2008/06/20 21:52:19 1.2 @@ -10,12 +10,12 @@ extern enum action action; -int activate_or_deactivate_sets(struct lib_context *lc, int arg); +int activate_or_deactivate_sets(struct lib_context *lc, int arg); void build_sets(struct lib_context *lc, char **sets); void format_error(struct lib_context *lc, const char *error, char **argv); void str_tolower(char *s); char *collapse_delimiter(struct lib_context *lc, char *str, size_t size, const char delim); -int valid_format(struct lib_context *lc, const char *fmt); +int valid_format(struct lib_context *lc, const char *fmt); #endif -- dm-devel mailing list dm-devel@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/dm-devel