Intel(R) Smart Response Technology mdadm enumeration/assembly
cover Intel(R) Smart Response Technology mdadm enumeration/assembly
As mentioned in the kernel enabling [1] these cache volumes augment the existing imsm model in that cache legs each imply a container. In the standard cache configuration two single-drive-raid0 volumes (from separate containers) are associated into a cached volume. The diagram below attempts to make this clearer.
+-----------------------+ +----------------------+
| sda | SSD | sdb | HDD
| +-------------------+ | | +------------------+ |
| | /dev/md/imsm0 | | Container0 | | /dev/md/imsm1 | | Container1
| | +---------------+ | | | | +--------------+ | |
| | | /dev/md/vol0 | | | RAID Volume0 | | | /dev/md/vol1 | | | RAID Volume1
| | | +---------+ | | | | | | +----------+ | | |
| | | |SRT Cache| | | | | | | |SRT Target| | | |
+-+-+--+----+----+--+-+-+ +-+-+-+----+-----+-+-+-+
| |
| |
| HDD Cached by SSD |
| +--------------+ |
+-----------+ /dev/md/isrt +----------+
+--------------+ In support of the standard mdadm volume discovery model a uuid a synthesized from the combination of the two container-family-numbers and immutable volume-ids. Examine_brief is modified to aggregate cache legs across containers.
Create support is not included, but existing volumes can be auto-assembled:
mdadm -Ebs > conf
mdadm -Asc conf
To facilitate testing the patches are also available on github, but note that this branch will rebase according to review feedback.
git://github.com/djbw/mdadm isrt
[1]: http://marc.info/?l=linux-raid&m=139832034826379&w=2
---
Dan Williams (11):
sysfs: fix sysfs_set_array() to accept valid negative array levels make must_be_container() more selective
Assemble: show the uuid in the verbose case
Assemble: teardown partially assembled arrays
Examine: support for coalescing "cache legs"
imsm: immutable volume id
imsm: cache metadata definitions
imsm: read cache metadata
imsm: examine cache configurations
imsm: assemble cache volumes
imsm: support cache enabled arrays
Assemble.c | 27 ++- Examine.c | 92 +++++++++- Makefile | 2 isrt-intel.h | 270 ++++++++++++++++++++++++++++++ maps.c | 1 mdadm.h | 4 super-intel.c | 516 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- sysfs.c | 13 + util.c | 18 +- 9 files changed, 865 insertions(+), 78 deletions(-) create mode 100644 isrt-intel.h
RFC PATCH 1/11 sysfs: fix sysfs_set_array() to accept valid negative array levels
From: Dan Williams <[email protected]>
Assume this FIXME was to prevent loading a personality for containers. Fix it up to accept the values that correlate with the actual md kernel personalities.
--- sysfs.c | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-)
sysfs.c +3 -2
@@ -628,8 +628,9 @@ int sysfs_set_array(struct mdinfo *info, int vers)return 1 ; } } -if (info->array.level <0 ) -return 0 ;/* FIXME */ +/* containers have no personality, they're rather bland */ +if (info->array.level <=LEVEL_CONTAINER ) +return 0 ; rv |=sysfs_set_str (info,NULL ,"level" ,map_num (pers, info->array.level));if (info->reshape_active && info->delta_disks != UnSet)
RFC PATCH 2/11 make must_be_container() more selective
In reply to Dan WilliamsCache configurations in mid-assembly may appear to be a "container" as they are 0-sized and external. Teach must_be_container() to look for "external:<metadata name>" as the container identfier from <sysfs>/md/metadata_version.
--- util.c | 17 +++++++++-------- 1 files changed, 9 insertions(+), 8 deletions(-)
util.c +9 -8
@@ -1176,18 +1176,19 @@ int get_dev_size(int fd, char *dname, unsigned long long *sizep) }/* Return true if this can only be a container, not a member device. -* i.e. is and md device and size is zero +* i.e. is and md device and the text_version matches an external +* metadata format */ int must_be_container (int fd) { -unsigned long long size; -if (md_get_version (fd) <0 ) +struct mdinfo *sra =sysfs_read (fd,NULL ,GET_VERSION ); +struct superswitch *ss; + +if (!sra)return 0 ; -if (get_dev_size (fd,NULL , &size) ==0 ) -return 1 ; -if (size ==0 ) -return 1 ; -return 0 ; + ss =version_to_superswitch (sra->text_version); +sysfs_free (sra); +return ss ? ss->external :0 ; }/* Sets endofpart parameter to the last block used by the last GPT partition on the device.
RFC PATCH 3/11 Assemble: show the uuid in the verbose case
In reply to Dan WilliamsMake the verbose output more usable when the array name is not given.
--- Assemble.c | 18 +++++++++++++++--- 1 files changed, 15 insertions(+), 3 deletions(-)
Assemble.c +15 -3
@@ -1288,9 +1288,21 @@ try_again:*/ if (!st && ident->st) st = ident->st; -if (c->verbose>0 ) -pr_err ("looking for devices for %s\n" , - mddev ? mddev :"further assembly" ); + +if (c->verbose >0 ) { +char uuid[64 ], *id; + +if (mddev) + id = mddev; +else if (ident->uuid_set) { +__fname_from_uuid (ident->uuid, + st ? st->ss->swapuuid :0 , + uuid,':' ); + id = uuid +5 ; + }else + id ="further assembly" ; +pr_err ("looking for devices for %s\n" , id); + } content = &info;if (st)
RFC PATCH 4/11 Assemble: teardown partially assembled arrays
In reply to Dan WilliamsIn the scenario of assembling composite md arrays, e.g. /dev/md2 with /dev/md1 and /dev/md0 as components, we want /dev/md2 assembly to be delayed until the components are available. If we attempt to assemble /dev/md2 when only /dev/md0 is available /dev/md2 will not be fully initialized, and /dev/md1 will be assembled to an equally defunct /dev/md3.
So teardown the early /dev/md2 on the expectation that more devices will arrive in a later assembly pass.
--- Assemble.c | 9 +++++---- 1 files changed, 5 insertions(+), 4 deletions(-)
Assemble.c +5 -4
@@ -1147,16 +1147,17 @@ static int start_array(int mdfd,if (sparecnt)fprintf (stderr," and %d spare%s" , sparecnt, sparecnt==1 ?"" :"s" );if (!enough (content->array.level, content->array.raid_disks, - content->array.layout,1 , avail)) + content->array.layout,1 , avail)) {fprintf (stderr," - not enough to start the array.\n" ); -else if (!enough (content->array.level, +ioctl (mdfd,STOP_ARRAY ,NULL ); + }else if (!enough (content->array.level, content->array.raid_disks, content->array.layout, clean, - avail)) + avail)) {fprintf (stderr," - not enough to start the " "array while not clean - consider " "--force.\n" ); -else { + }else {if (req_cnt == (unsigned )content->array.raid_disks)fprintf (stderr," - need all %d to start it" , req_cnt);else
RFC PATCH 5/11 Examine: support for coalescing "cache legs"
In reply to Dan Williams'isrt' volumes introduce a new category of a array. They have components that are subarrays from separate containers (likely thanks to the constraint that all active members in an imsm container must be members of all subarrays). We want '-Eb' to identify the composite volume uuid, but the default coalescing (by container) results in duplicated output of the cache volume uuid.
Instead, introduce infrastructure to handle this directly.
1/ add ->cache_legs to struct mdinfo to indicate how many subarrays in a given
container are components (legs) of a cache association.
2/ add ->cache_leg to struct supertype to indicate a cache leg to
enumerate via ->getinfo_super()
3/ teach Examine to coalesce cache volumes across containers by uuid and
dump their details via ->brief_examine_cache() extension to struct superswitch.
--- Examine.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++-------- mdadm.h | 3 ++ 2 files changed, 83 insertions(+), 12 deletions(-)
Examine.c +80 -12
@@ -30,6 +30,73 @@#endif #include "md_u.h" #include "md_p.h" + +struct array { +struct supertype *st; +struct mdinfo info; +void *devs; +struct array *next; +int spares; +int cache_leg; +}; + +static struct array *add_cache_legs (struct array *caches,struct supertype *st, +struct mdinfo *info,struct array *arrays) +{ +struct mdinfo cache_info; +struct array *ap; +int i; + +for (i =1 ; i <= info->cache_legs; i++) { +/* in the case where the cache leg is assembled its uuid +* may appear in the arrays list, so we need to check +* both the caches list and the arrays list for +* duplicates +*/ +struct array *lists[] = { caches, arrays }; +int j; + + st->cache_leg = i; + st->ss->getinfo_super (st, &cache_info,NULL ); + st->cache_leg =0 ; +for (j =0 ; j <2 ; j++) { +for (ap = lists[j]; ap; ap = ap->next) { +if (st->ss == ap->st->ss + &&same_uuid (ap->info.uuid, cache_info.uuid, + st->ss->swapuuid)) +break ; + } +if (ap) +break ; + } +if (!ap) { + ap =xcalloc (1 ,sizeof (*ap)); + ap->devs =dl_head (); + ap->next = caches; + ap->st = st; + ap->cache_leg = i; + caches = ap; +memcpy (&ap->info, &cache_info,sizeof (cache_info)); + } + } + +return caches; +} + +static void free_arrays (struct array *arrays) +{ +struct array *ap; + +while (arrays) { + ap = arrays; + arrays = ap->next; + + ap->st->ss->free_super (ap->st); +free (ap); + } +} + +int Examine (struct mddev_dev *devlist,struct context *c,struct supertype *forcest)
@@ -54,14 +121,7 @@ int Examine(struct mddev_dev *devlist,int fd;int rv =0 ;int err =0 ; - -struct array { -struct supertype *st; -struct mdinfo info; -void *devs; -struct array *next; -int spares; - } *arrays =NULL ; +struct array *arrays =NULL , *caches =NULL ;for (; devlist ; devlist = devlist->next) {struct supertype *st;
@@ -131,13 +191,14 @@ int Examine(struct mddev_dev *devlist,break ; }if (!ap) { - ap =xmalloc (sizeof (*ap)); + ap =xcalloc (1 ,sizeof (*ap)); ap->devs =dl_head (); ap->next = arrays; - ap->spares =0 ; ap->st = st; arrays = ap; st->ss->getinfo_super (st, &ap->info,NULL ); + caches =add_cache_legs (caches, st, &ap->info, + arrays); }else st->ss->getinfo_super (st, &ap->info,NULL ); if (!have_container &&
@@ -179,11 +240,18 @@ int Examine(struct mddev_dev *devlist,printf ("\n" ); ap->st->ss->brief_examine_subarrays (ap->st, c->verbose); } - ap->st->ss->free_super (ap->st); -/* FIXME free ap */ if (ap->spares || c->verbose >0 )printf ("\n" ); } +/* list container caches after their parent containers +* and subarrays +*/ +for (ap = caches; ap; ap = ap->next) +if (ap->st->ss->brief_examine_cache) + ap->st->ss->brief_examine_cache (ap->st, ap->cache_leg); +free_arrays (arrays); +free_arrays (caches); + }return rv; }
mdadm.h +3 -0
@@ -233,6 +233,7 @@ struct mdinfo {int container_enough;/* flag external handlers can set to * indicate that subarrays have not enough (-1), * enough to start (0), or all expected disks (1) */ +int cache_legs;/* number of cross-container cache members in this 'array' */ char sys_name[20 ];struct mdinfo *devs;struct mdinfo *next;
@@ -684,6 +685,7 @@ extern struct superswitch {void (*examine_super)(struct supertype *st,char *homehost);void (*brief_examine_super)(struct supertype *st,int verbose);void (*brief_examine_subarrays)(struct supertype *st,int verbose); +void (*brief_examine_cache)(struct supertype *st,int cache);void (*export_examine_super)(struct supertype *st);int (*examine_badblocks)(struct supertype *st,int fd,char *devname);int (*copy_metadata)(struct supertype *st,int from,int to);
@@ -1006,6 +1008,7 @@ struct supertype {Used when examining metadata to display content of disk when user has no hw/firmare compatible system. */ +int cache_leg;/* hack to interrogate cache legs within containers */ struct metadata_update *updates;struct metadata_update **update_tail;
RFC PATCH 6/11 imsm: immutable volume id
In reply to Dan WilliamsSupport the new extensions to have a volume-id that is immutable and unique for the life of the container. Prior to this change deleting and recreating a volume would result in it having the same uuid as the previous volume in that position. Now, every time a volume is created a container generation count is incremented allowing the volume-ids to include container generation salt.
TODO update kill_subarray_imsm() and update_subarray_imsm() to allow deletion and renaming (respectively) of arrays with an immutable id.
--- super-intel.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 files changed, 65 insertions(+), 12 deletions(-)
super-intel.c +65 -12
@@ -188,8 +188,9 @@ struct imsm_dev {__u16 cache_policy;__u8 cng_state;__u8 cng_sub_state; -#define IMSM_DEV_FILLERS 10 -__u32 filler[IMSM_DEV_FILLERS ]; +__u16 dev_id; +__u16 fill; +__u32 filler[9 ];struct imsm_vol vol; } __attribute__ ((packed));
@@ -209,8 +210,9 @@ struct imsm_super {__u32 orig_family_num;/* 0x40 - 0x43 original family num */ __u32 pwr_cycle_count;/* 0x44 - 0x47 simulated power cycle count for array */ __u32 bbm_log_size;/* 0x48 - 0x4B - size of bad Block Mgmt Log in bytes */ -#define IMSM_FILLERS 35 -__u32 filler[IMSM_FILLERS ];/* 0x4C - 0xD7 RAID_MPB_FILLERS */ +__u16 create_events;/* counter for generating unique ids */ +__u16 fill1; +__u32 filler[34 ];struct imsm_disk disk[1 ];/* 0xD8 diskTbl[numDisks] */ /* here comes imsm_dev[num_raid_devs] */ /* here comes BBM logs */
@@ -1984,6 +1986,30 @@ static int match_home_imsm(struct supertype *st, char *homehost)return -1 ; } +static void volume_uuid_from_super (struct intel_super *super,struct sha1_ctx *ctx) +{ +struct imsm_dev *dev =NULL ; + +if (super->current_vol >=0 ) + dev =get_imsm_dev (super, super->current_vol); + +if (!dev) +return ; + +/* if the container is tracking creation events then dev_id is +* valid and we can advertise an immutable uuid, otherwise use the +* old volume-position/name method +*/ +if (super->anchor->create_events) { +sha1_process_bytes (&dev->dev_id,sizeof (dev->dev_id), ctx); + }else { +__u32 vol = super->current_vol; + +sha1_process_bytes (&vol,sizeof (vol), ctx); +sha1_process_bytes (dev->volume,MAX_RAID_SERIAL_LEN , ctx); + } +} +static void uuid_from_super_imsm (struct supertype *st,int uuid[4 ]) {/* The uuid returned here is used for:
@@ -2012,7 +2038,6 @@ static void uuid_from_super_imsm(struct supertype *st, int uuid[4])char buf[20 ];struct sha1_ctx ctx; -struct imsm_dev *dev =NULL ;__u32 family_num;/* some mdadm versions failed to set ->orig_family_num, in which
@@ -2025,13 +2050,7 @@ static void uuid_from_super_imsm(struct supertype *st, int uuid[4])sha1_init_ctx (&ctx);sha1_process_bytes (super->anchor->sig,MPB_SIG_LEN , &ctx);sha1_process_bytes (&family_num,sizeof (__u32), &ctx); -if (super->current_vol >=0 ) - dev =get_imsm_dev (super, super->current_vol); -if (dev) { -__u32 vol = super->current_vol; -sha1_process_bytes (&vol,sizeof (vol), &ctx); -sha1_process_bytes (dev->volume,MAX_RAID_SERIAL_LEN , &ctx); - } +volume_uuid_from_super (super, &ctx);sha1_finish_ctx (&ctx, buf);memcpy (uuid, buf,4 *4 ); }
@@ -4562,6 +4581,39 @@ static int check_name(struct intel_super *super, char *name, int quiet)return !reason; } +static void new_dev_id (struct intel_super *super,struct imsm_dev *new_dev) +{ +struct imsm_super *mpb = super->anchor; +__u16 create_events, i; + +/* only turn on create_events tracking for newly born +* containers, lest we change the uuid of live volumes (see +* volume_uuid_from_super()) +*/ + create_events =__le16_to_cpu (mpb->create_events); +if (super->current_vol >0 && !create_events) +return ; + +/* catch the case of create_events wrapping to an existing id in +* the mpb +*/ +do { + create_events++; +/* wrap to 1, because zero means no dev_id support */ +if (create_events ==0 ) + create_events =1 ; +for (i =0 ; i < mpb->num_raid_devs; i++) { +struct imsm_dev *dev =__get_imsm_dev (mpb, i); + +if (dev->dev_id ==__cpu_to_le16 (create_events)) +break ; + } + }while (i < mpb->num_raid_devs); + + new_dev->dev_id =__cpu_to_le16 (create_events); + mpb->create_events =__cpu_to_le16 (create_events); +} + static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info, unsigned long long size, char *name, char *homehost, int *uuid,
@@ -4655,6 +4707,7 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,return 0 ; dv =xmalloc (sizeof (*dv)); dev =xcalloc (1 ,sizeof (*dev) +sizeof (__u32) * (info->raid_disks -1 )); +new_dev_id (super, dev);strncpy ((char *) dev->volume, name,MAX_RAID_SERIAL_LEN ); array_blocks = calc_array_size(info->level, info->raid_disks, info->layout, info->chunk_size,
RFC PATCH 7/11 imsm: cache metadata definitions
In reply to Dan Williams--- Makefile | 2 isrt-intel.h | 256 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ super-intel.c | 16 +++- 3 files changed, 271 insertions(+), 3 deletions(-) create mode 100644 isrt-intel.h
Makefile +1 -1
@@ -127,7 +127,7 @@ CHECK_OBJS = restripe.o sysfs.o maps.o lib.o xmalloc.o dlink.o SRCS = $(patsubst %.o,%.c,$(OBJS)) -INCL = mdadm.h part.h bitmap.h +INCL = mdadm.h part.h bitmap.h isrt-intel.h platform-intel.h MON_OBJS = mdmon.o monitor.o managemon.o util.o maps.o mdstat.o sysfs.o \ policy.o lib.o \
isrt-intel.h new file +256 -0
256 lines not on this page · raw message
super-intel.c +14 -2
@@ -22,6 +22,7 @@#include "mdmon.h" #include "sha1.h" #include "platform-intel.h" +#include "isrt-intel.h" #include <values.h> #include <scsi/sg.h> #include <ctype.h>
@@ -39,7 +40,6 @@#define MPB_VERSION_CNG "1.2.06"#define MPB_VERSION_ATTRIBS "1.3.00"#define MAX_SIGNATURE_LENGTH 32 -#define MAX_RAID_SERIAL_LEN 16/* supports RAID0 */ #define MPB_ATTRIB_RAID0 __cpu_to_le32(0x00000001)
@@ -179,6 +179,8 @@ struct imsm_dev {#define DEV_CLONE_N_GO __cpu_to_le32(0x400)#define DEV_CLONE_MAN_SYNC __cpu_to_le32(0x800)#define DEV_CNG_MASTER_DISK_NUM __cpu_to_le32(0x1000) +/* Volume is being used as NvCache for an accelerated volume */ +#define DEV_NVC_VOLUME __cpu_to_le32(0x4000)__u32 status;/* Persistent RaidDev status */ __u32 reserved_blocks;/* Reserved blocks at beginning of volume */ __u8 migr_priority;
@@ -189,8 +191,18 @@ struct imsm_dev {__u8 cng_state;__u8 cng_sub_state;__u16 dev_id; +__u8 nv_cache_mode; +#define DEV_NVC_CLEAN (0) +#define DEV_NVC_DIRTY (1) +#define DEV_NVC_HEALTH_GOOD (0 << 1) +#define DEV_NVC_HEALTH_FAILED (1 << 1) +#define DEV_NVC_HEALTH_READONLY (2 << 1) +#define DEV_NVC_HEALTH_BACKUP (3 << 1) +__u8 nv_cache_flags; +__u32 nvc_orig_family_num;/* Unique Volume Id of the cache */ +__u16 nvc_dev_id;/* volume associated with this volume */ __u16 fill; -__u32 filler[9 ]; +__u32 filler[7 ];struct imsm_vol vol; } __attribute__ ((packed));
RFC PATCH 8/11 imsm: read cache metadata
In reply to Dan WilliamsAdd support for identifying cache volumes and retrieving the associated cache mpb located at the start of the volume marked with a DEV_NVC_VOLUME flag.
--- super-intel.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++-------- 1 files changed, 47 insertions(+), 8 deletions(-)
super-intel.c +47 -8
@@ -345,6 +345,7 @@ static unsigned int mpb_sectors(struct imsm_super *mpb)struct intel_dev {struct imsm_dev *dev;struct intel_dev *next; +struct nv_cache_control_data *nvc;unsigned index; };
@@ -3086,6 +3087,7 @@ static void free_devlist(struct intel_super *super)while (super->devlist) { dv = super->devlist->next; +free (super->devlist->nvc);free (super->devlist->dev);free (super->devlist); super->devlist = dv;
@@ -3467,9 +3469,34 @@ static void end_migration(struct imsm_dev *dev, struct intel_super *super, }#endif -static int parse_raid_devices (struct intel_super *super) +static int load_cache (int fd,struct intel_dev *dv) { -int i; +struct imsm_dev *dev = dv->dev; +struct imsm_map *map =get_imsm_map (dev,MAP_X ); +off_t offset =pba_of_lba0 (map) <<9 ; +ssize_t size = (sizeof (*dv->nvc) +511 ) & ~511 ; +int ret; + +if (posix_memalign ((void **) &dv->nvc,512 , size) !=0 ) { +pr_err ("Failed to allocate cache anchor buffer" +" for %.16s\n" , dev->volume); +return 1 ; + } + + ret =pread (fd, dv->nvc, size, offset); +if (ret != size) { +pr_err ("Failed to read cache metadata for %.16s: %s\n" , + dev->volume,strerror (errno)); +free (dv->nvc); + dv->nvc =NULL ; + } + +return ret != size; +} + +static int load_raid_devices (int fd,struct intel_super *super) +{ +int i, err;struct imsm_dev *dev_new;size_t len, len_migr;size_t max_len =0 ;
@@ -3496,6 +3523,16 @@ static int parse_raid_devices(struct intel_super *super) dv->index = i; dv->next = super->devlist; super->devlist = dv; + +/* volumes that serve as caches have metadata at offset-0 from +* the start of the volume +*/ +if (dv->dev->status &DEV_NVC_VOLUME ) { + err =load_cache (fd, dv); +if (err) +return err; + }else + dv->nvc =NULL ; }/* ensure that super->buf is large enough when all raid devices
@@ -3718,8 +3755,7 @@ static void clear_hi(struct intel_super *super) } } -static int -load_and_parse_mpb (int fd,struct intel_super *super,char *devname,int keep_fd) +static int load_mpb (int fd,struct intel_super *super,char *devname,int keep_fd) {int err;
@@ -3729,7 +3765,10 @@ load_and_parse_mpb(int fd, struct intel_super *super, char *devname, int keep_fd err =load_imsm_disk (fd, super, devname, keep_fd);if (err)return err; - err =parse_raid_devices (super); + err =load_raid_devices (fd, super); +if (err) +return err; +clear_hi (super);return err; }
@@ -4384,13 +4423,13 @@ static int get_super_block(struct intel_super **super_list, char *devnm, char *d }find_intel_hba_capability (dfd, s, devname); - err =load_and_parse_mpb (dfd, s,NULL , keep_fd); + err =load_mpb (dfd, s,NULL , keep_fd);/* retry the load if we might have raced against mdmon */ if (err ==3 && devnm &&mdmon_running (devnm))for (retry =0 ; retry <3 ; retry++) {usleep (3000 ); - err =load_and_parse_mpb (dfd, s,NULL , keep_fd); + err =load_mpb (dfd, s,NULL , keep_fd);if (err !=3 )break ; }
@@ -4473,7 +4512,7 @@ static int load_super_imsm(struct supertype *st, int fd, char *devname)free_imsm (super);return 2 ; } - rv =load_and_parse_mpb (fd, super, devname,0 ); + rv =load_mpb (fd, super, devname,0 );if (rv) {if (devname)
RFC PATCH 9/11 imsm: examine cache configurations
In reply to Dan WilliamsAllow -E to show the cache associations of volumes. The UUIDs are calculated from the stored "orig_family_num" and "dev_id" in the cache metadata.
For -Eb a UUID is synthesized from the union of the <cache>:<cache-target> tuple for the purposes of identifying the complete volume.
The proposed assembly hierarchy is:
1/ (2) containers (one for the cache "array", one for the cache-target
"array")
2/ (2) subarrays (one for the cache "volume", one for the cache-target
"volume")
3/ (1) stacked array with the subarray from 2/ as component members
...where "array" and "volume" are the imsm terminology for a mdadm container and subarray.
TODO: what to do about the name of the composite volume? Leave it dynamically assigned for now, we could have it takeover the cache-target name, but that name is not available when examinig the cache device...
--- isrt-intel.h | 12 ++++ super-intel.c | 184 ++++++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 172 insertions(+), 24 deletions(-)
isrt-intel.h +12 -0
@@ -43,6 +43,18 @@ enum { NV_CACHE_MODE_DIS_SAFE = 11, /* volume or NV cache not associated */ }; +static inline int nvc_enabled (__u8 mode) +{ +switch (mode) { +case NV_CACHE_MODE_OFF : +case NV_CACHE_MODE_DIS_PERF : +case NV_CACHE_MODE_DIS_SAFE : +return 0 ; +default : +return 1 ; + } +} +struct segment_index_pair {__u32 segment;__u32 index;
super-intel.c +160 -24
288 lines not on this page · raw message
RFC PATCH 10/11 imsm: assemble cache volumes
In reply to Dan WilliamsTeach load_super to examine the passed in fd and determine if it is a cache or cache-target md device.
Generate info to allow the two halves of the cache to be assembled.
XXX: what are the rules we need for compare_super to determine stale cache associations?
Create a LEVEL_ISRT md device.
--- isrt-intel.h | 2 + maps.c | 1 mdadm.h | 1 super-intel.c | 191 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- sysfs.c | 8 ++ util.c | 1 6 files changed, 198 insertions(+), 6 deletions(-)
isrt-intel.h +2 -0
@@ -28,6 +28,8 @@ enum {NVC_SIG_LEN =32 ,ISRT_DEV_IDX =0 ,ISRT_TARGET_DEV_IDX =1 , +ISRT_ROLE_CACHE =0 , +ISRT_ROLE_TARGET =1 ,NV_CACHE_MODE_OFF =0 , NV_CACHE_MODE_OFF_TO_SAFE = 1, /* powerfail recovery state */
maps.c +1 -0
@@ -93,6 +93,7 @@ mapping_t pers[] = { { "10", 10}, { "faulty", LEVEL_FAULTY}, { "container", LEVEL_CONTAINER}, + { "isrt", LEVEL_ISRT }, { NULL, 0} };
mdadm.h +1 -0
@@ -1457,6 +1457,7 @@ char *xstrdup(const char *str);#define LEVEL_MULTIPATH (-4)#define LEVEL_LINEAR (-1)#define LEVEL_FAULTY (-5) +#define LEVEL_ISRT (-12)/* kernel module doesn't know about these */ #define LEVEL_CONTAINER (-100)
super-intel.c +186 -5
274 lines not on this page · raw message
sysfs.c +7 -1
@@ -638,7 +638,13 @@ int sysfs_set_array(struct mdinfo *info, int vers) rv |=sysfs_set_num (info,NULL ,"raid_disks" , raid_disks); rv |=sysfs_set_num (info,NULL ,"chunk_size" , info->array.chunk_size); rv |=sysfs_set_num (info,NULL ,"layout" , info->array.layout); - rv |=sysfs_set_num (info,NULL ,"component_size" , info->component_size/2 ); +if (info->array.level ==LEVEL_ISRT ) { +/* FIXME: how do we support asymmetric component sizes for +* external metadata? +*/ + rv |=sysfs_set_num (info,NULL ,"component_size" ,0 ); + }else + rv |=sysfs_set_num (info,NULL ,"component_size" , info->component_size/2 );if (info->custom_array_size) {int rc;
util.c +1 -0
@@ -362,6 +362,7 @@ int enough(int level, int raid_disks, int layout, int clean, char *avail)case LEVEL_MULTIPATH :return avail_disks>=1 ; +case LEVEL_ISRT :case LEVEL_LINEAR :case 0 :return avail_disks == raid_disks;
RFC PATCH 11/11 imsm: support cache enabled arrays
In reply to Dan WilliamsTurn on attribute support for caching.
--- super-intel.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-)
super-intel.c +2 -1
@@ -81,7 +81,8 @@ MPB_ATTRIB_RAID1 | \ MPB_ATTRIB_RAID10 | \ MPB_ATTRIB_RAID5 | \ - MPB_ATTRIB_EXP_STRIPE_SIZE) + MPB_ATTRIB_EXP_STRIPE_SIZE | \ + MPB_ATTRIB_NVM)/* Define attributes that are unused but not harmful */ #define MPB_ATTRIB_IGNORED (MPB_ATTRIB_NEVER_USE)