diff options
author | James Hall <James.Hall@Sun.COM> | 2010-06-23 10:37:46 +0100 |
---|---|---|
committer | James Hall <James.Hall@Sun.COM> | 2010-06-23 10:37:46 +0100 |
commit | 32c22d57860198538fb6b8f261cb76ab26318d34 (patch) | |
tree | ad634452f7d5849ffdfb3028f6751d3ddfb959c5 /usr/src | |
parent | bbbbacb4bedf3d3959b4c3ec8ba1e07c8c10251d (diff) | |
download | illumos-gate-32c22d57860198538fb6b8f261cb76ab26318d34.tar.gz |
6569362 metaimport can corrupt shared namespace
6865676 SDS metaimport fail for 3rd Party LUNs
6861151 Recreate soft partition on >1TB stripe fails with "overlapping extent specificed"
6883934 Host added to imported metaset panics accessing soft partition
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/lib/lvm/libmeta/common/meta_devadm.c | 6 | ||||
-rw-r--r-- | usr/src/lib/lvm/libmeta/common/meta_nameinfo.c | 50 | ||||
-rw-r--r-- | usr/src/uts/common/io/lvm/md/md.c | 7 | ||||
-rw-r--r-- | usr/src/uts/common/io/lvm/md/md_ioctl.c | 5 | ||||
-rw-r--r-- | usr/src/uts/common/io/lvm/md/md_mddb.c | 59 | ||||
-rw-r--r-- | usr/src/uts/common/io/lvm/md/md_names.c | 306 | ||||
-rw-r--r-- | usr/src/uts/common/sys/lvm/md_names.h | 11 | ||||
-rw-r--r-- | usr/src/uts/common/sys/lvm/mdvar.h | 7 |
8 files changed, 169 insertions, 282 deletions
diff --git a/usr/src/lib/lvm/libmeta/common/meta_devadm.c b/usr/src/lib/lvm/libmeta/common/meta_devadm.c index 411da72b60..0d90d2f802 100644 --- a/usr/src/lib/lvm/libmeta/common/meta_devadm.c +++ b/usr/src/lib/lvm/libmeta/common/meta_devadm.c @@ -19,12 +19,9 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <stdio.h> #include <stdarg.h> #include <ctype.h> @@ -292,6 +289,7 @@ meta_update_namespace( nm.devname = (uintptr_t)devname; nm.devname_len = strlen(devname); nm.mnum = meta_getminor(dev); + nm.major = meta_getmajor(dev); nm.key = key; nm.pathname = (uintptr_t)pname; nm.pathname_len = strlen(pname); diff --git a/usr/src/lib/lvm/libmeta/common/meta_nameinfo.c b/usr/src/lib/lvm/libmeta/common/meta_nameinfo.c index f2e6104300..f353af9a0d 100644 --- a/usr/src/lib/lvm/libmeta/common/meta_nameinfo.c +++ b/usr/src/lib/lvm/libmeta/common/meta_nameinfo.c @@ -20,8 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved. */ #include <dlfcn.h> @@ -96,13 +95,28 @@ meta_geom_to_md( * convert efi to md types */ static void -meta_efi_to_mdgeom(struct dk_gpt *gpt, mdgeom_t *mdgp) +meta_efi_to_mdgeom(md_unit_t *mdev, struct dk_gpt *gpt, mdgeom_t *mdgp) { (void) memset(mdgp, '\0', sizeof (*mdgp)); - mdgp->ncyl = (gpt->efi_last_u_lba - gpt->efi_first_u_lba) / - (MD_EFI_FG_HEADS * MD_EFI_FG_SECTORS); - mdgp->nhead = MD_EFI_FG_HEADS; - mdgp->nsect = MD_EFI_FG_SECTORS; + + /* + * Should always get geom from metadevice unit if metadevice. + * If metadevice is built on top of efi disks then it will + * have MD_EFI_FG_ values, otherwise it will have geom from + * the first component. + */ + if (mdev) { + mdgp->ncyl = (mdev->c.un_total_blocks) / + (mdev->c.un_nhead * mdev->c.un_nsect); + mdgp->nhead = mdev->c.un_nhead; + mdgp->nsect = mdev->c.un_nsect; + } else { + mdgp->ncyl = (gpt->efi_last_u_lba - gpt->efi_first_u_lba) + / (MD_EFI_FG_HEADS * MD_EFI_FG_SECTORS); + mdgp->nhead = MD_EFI_FG_HEADS; + mdgp->nsect = MD_EFI_FG_SECTORS; + } + mdgp->rpm = MD_EFI_FG_RPM; mdgp->write_reinstruct = MD_EFI_FG_WRI; mdgp->read_reinstruct = MD_EFI_FG_RRI; @@ -589,6 +603,8 @@ metagetvtoc( /* DKIOCGGEOM yielded ENOTSUP => try efi_alloc_and_read */ struct dk_gpt *gpt; int save_errno; + md_unit_t *mdev = NULL; + mdsetname_t *sp = NULL; /* this also sets errno */ partno = efi_alloc_and_read(fd, &gpt); @@ -610,6 +626,7 @@ metagetvtoc( metafreevtoc(&dnp->vtoc); meta_efi_to_mdvtoc(gpt, &dnp->vtoc); if (dnp->vtoc.nparts > MD_MAX_PARTS) { + efi_free(gpt); (void) mddeverror(ep, MDE_TOO_MANY_PARTS, NODEV64, rname); return (NULL); @@ -623,7 +640,24 @@ metagetvtoc( if (dnp->vtoc.nparts < V_NUMPAR) { dnp->vtoc.nparts = V_NUMPAR; } - meta_efi_to_mdgeom(gpt, &dnp->geom); + + /* + * Is np a metadevice? + */ + if (metaismeta(np)) { + sp = metasetnosetname(MD_MIN2SET(meta_getminor + (np->dev)), ep); + if (!sp || (mdev = meta_get_mdunit(sp, np, ep)) == + NULL) { + efi_free(gpt); + (void) mddeverror(ep, MDE_NOT_META, + NODEV64, rname); + return (NULL); + } + } + + meta_efi_to_mdgeom(mdev, gpt, &dnp->geom); + Free(mdev); efi_free(gpt); } else { /* no error on DKIOCGGEOM, try meta_getvtoc */ diff --git a/usr/src/uts/common/io/lvm/md/md.c b/usr/src/uts/common/io/lvm/md/md.c index 2196d9f5e0..89a329e1b9 100644 --- a/usr/src/uts/common/io/lvm/md/md.c +++ b/usr/src/uts/common/io/lvm/md/md.c @@ -20,8 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -274,11 +273,7 @@ extern void med_fini(void); extern void md_devid_cleanup(set_t, uint_t); /* md_names.c */ -extern void *lookup_entry(struct nm_next_hdr *, set_t, - side_t, mdkey_t, md_dev64_t, int); extern struct nm_next_hdr *get_first_record(set_t, int, int); -extern int remove_entry(struct nm_next_hdr *, - side_t, mdkey_t, int); int md_maxphys = 0; /* maximum io size in bytes */ #define MD_MAXBCOUNT (1024 * 1024) diff --git a/usr/src/uts/common/io/lvm/md/md_ioctl.c b/usr/src/uts/common/io/lvm/md/md_ioctl.c index fc13ea95c3..55ed85e224 100644 --- a/usr/src/uts/common/io/lvm/md/md_ioctl.c +++ b/usr/src/uts/common/io/lvm/md/md_ioctl.c @@ -20,8 +20,7 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -714,7 +713,7 @@ update_namespace_ioctl( side = nm->side; return (md_update_namespace(nm->setno, side, nm->key, - dname, pname, nm->mnum)); + dname, pname, nm->major, nm->mnum)); } diff --git a/usr/src/uts/common/io/lvm/md/md_mddb.c b/usr/src/uts/common/io/lvm/md/md_mddb.c index 8abcf4837d..fd373a8752 100644 --- a/usr/src/uts/common/io/lvm/md/md_mddb.c +++ b/usr/src/uts/common/io/lvm/md/md_mddb.c @@ -20,8 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved. */ #include <sys/types.h> @@ -12272,6 +12271,7 @@ md_update_minor( struct nm_name *n; char *shn; int retval = 1; + side_t s; /* * Load the devid name space if it exists @@ -12295,18 +12295,26 @@ md_update_minor( /* * Look up the key */ - if ((n = lookup_entry(nh, setno, side, key, NODEV64, 0L)) != NULL) { + for (s = 0; s < MD_MAXSIDES; s++) { /* - * Find the entry, update its n_minor if metadevice + * For side other than the import 'side', cleanup its entry */ - if ((shn = (char *)getshared_name(setno, n->n_drv_key, 0L)) - == NULL) { - retval = 0; - goto out; - } - - if (strcmp(shn, "md") == 0) { - n->n_minor = MD_MKMIN(setno, MD_MIN2UNIT(n->n_minor)); + if ((n = lookup_entry(nh, setno, s, key, NODEV64, 0L)) != + NULL) { + if (n->n_side == side) { + /* + * Update its n_minor if metadevice + */ + if (((shn = (char *)getshared_name(setno, + n->n_drv_key, 0L)) != NULL) && + (strcmp(shn, "md") == 0)) { + n->n_minor = MD_MKMIN(setno, + MD_MIN2UNIT(n->n_minor)); + } + } else { + /* We are not the import side, cleanup */ + (void) remove_entry(nh, n->n_side, key, 0L); + } } } @@ -12542,7 +12550,7 @@ update_setname( o_data = shn->sn_data; if (remove_shared_entry(nh, o_key, NULL, 0L | NM_IMP_SHARED | - NM_NOCOMMIT)) { + NM_NOCOMMIT | NM_KEY_RECYCLE)) { err = MDDB_E_NORECORD; goto out; } @@ -12729,11 +12737,8 @@ md_update_namespace_rr_did( mdkey_t ent_did_key; uint32_t ent_did_count; uint32_t ent_did_data; - size_t ent_size, size; ddi_devid_t devid = NULL; struct did_shr_name *shn; - size_t offset; - struct nm_next_hdr *this_did_shr_nh; void *old_devid, *new_devid; if (!(md_get_setstatus(setno) & MD_SET_NM_LOADED)) @@ -12745,7 +12750,6 @@ md_update_namespace_rr_did( /* * It is okay if we dont have any configuration */ - offset = (sizeof (struct devid_shr_rec) - sizeof (struct did_shr_name)); if ((nh = get_first_record(setno, 0, NM_DEVID | NM_NOTSHARED)) == NULL) { return (0); @@ -12761,7 +12765,7 @@ md_update_namespace_rr_did( if (did_shr_nh == NULL) { return (ENOENT); } - this_did_shr_nh = did_shr_nh->nmn_nextp; + shr_n = (struct did_shr_name *)lookup_shared_entry( did_shr_nh, n->min_devid_key, (char *)0, &recids[0], NM_DEVID); @@ -12780,21 +12784,10 @@ md_update_namespace_rr_did( ent_did_key = shr_n ->did_key; ent_did_count = shr_n->did_count; ent_did_data = shr_n->did_data; - ent_size = DID_SHR_NAMSIZ(shr_n); - size = ((struct nm_rec_hdr *) - this_did_shr_nh->nmn_record)-> - r_used_size - offset - ent_size; - if (size == 0) { - (void) bzero(shr_n, ent_size); - } else { - (void) ovbcopy((caddr_t)shr_n + - ent_size, shr_n, size); - (void) bzero((caddr_t)shr_n + - size, ent_size); - } - ((struct nm_rec_hdr *)this_did_shr_nh-> - nmn_record)->r_used_size -= - ent_size; + (void) remove_shared_entry(did_shr_nh, + shr_n->did_key, NULL, NM_DEVID | + NM_IMP_SHARED | NM_KEY_RECYCLE); + /* add in new devid info */ if ((shn = (struct did_shr_name *) alloc_entry(did_shr_nh, diff --git a/usr/src/uts/common/io/lvm/md/md_names.c b/usr/src/uts/common/io/lvm/md/md_names.c index 9c60111294..8a716e5730 100644 --- a/usr/src/uts/common/io/lvm/md/md_names.c +++ b/usr/src/uts/common/io/lvm/md/md_names.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved. */ #include <sys/errno.h> @@ -39,19 +38,8 @@ extern md_set_t md_set[]; extern int *md_nm_snarfed; void *lookup_entry(struct nm_next_hdr *, set_t, side_t, mdkey_t, md_dev64_t, int); -void *lookup_entry_common(struct nm_next_hdr *, set_t, - side_t, mdkey_t, md_dev64_t, int, void **, size_t *); -void *lookup_entry_record_offset(struct nm_next_hdr *, set_t, - side_t, mdkey_t, md_dev64_t, int, void *, size_t *); - void *lookup_shared_entry(struct nm_next_hdr *, mdkey_t, char *, mddb_recid_t *, int); -void *lookup_shared_entry_common(struct nm_next_hdr *, - mdkey_t, char *, mddb_recid_t *, int, void **, - size_t *); -void *lookup_shared_entry_record_offset(struct nm_next_hdr *, - mdkey_t, char *, mddb_recid_t *, int, void *, size_t *); - static void add_to_devid_list(ddi_devid_t did); static int devid_is_unique(ddi_devid_t did); static size_t free_devid_list(int *count); @@ -159,6 +147,14 @@ destroy_key(struct nm_next_hdr *nh, int shared, mdkey_t key) if ((key + 1) != rh->r_next_key) return; + /* + * Here the key is the highest allocated key. + * Check to see if this key is recycled or not and if yes, + * then keep r_next_key intact. + */ + if (shared & NM_KEY_RECYCLE) + return; + while (unused_key(nh, shared, key)) key--; rh->r_next_key = key + 1; @@ -562,7 +558,7 @@ rem_entry( void *ent, /* address of entry to be removed */ size_t ent_size, /* size of entry to be removed */ size_t offset, /* offset of entry within record */ - int devid_nm) /* which name space? 0 - primary */ + int devid_nm) /* bitwise of NM_DEVID, NM_KEY_RECYCLE */ { struct nm_next_hdr *first_nh; mddb_recid_t recids[3]; @@ -597,8 +593,8 @@ rem_entry( /* * We don't keep track of keys in the device id nonshared namespace */ - if (!devid_nm) - destroy_key(first_nh, NM_NOTSHARED, ent_key); + if (!(devid_nm & NM_DEVID)) + destroy_key(first_nh, devid_nm | NM_NOTSHARED, ent_key); mddb_commitrecs_wrapper(recids); return (0); @@ -611,7 +607,8 @@ rem_shr_entry( void *ent, /* address of entry to be removed */ size_t ent_size, /* size of entry to be removed */ size_t offset, /* offset of entry within record */ - int devid_nm) /* which name space? 0 - primary */ + int devid_nm) /* bitwise of NM_DEVID, NM_IMP_SHARED, */ + /* NM_NOCOMMIT, NM_KEY_RECYCLE */ { struct nm_next_hdr *first_nh; mddb_recid_t recids[3]; @@ -895,10 +892,10 @@ update_entry( int remove_entry( - struct nm_next_hdr *nh, /* head record header */ - side_t side, /* (key 1) side number */ - mdkey_t key, /* (key 2) via md_setdevname */ - int devid_nm) /* which name space? */ + struct nm_next_hdr *nh, /* head record header */ + side_t side, /* (key 1) side number */ + mdkey_t key, /* (key 2) via md_setdevname */ + int devid_nm) /* bitwise of NM_DEVID, NM_KEY_RECYCLE */ { struct nm_rec_hdr *rh = (struct nm_rec_hdr *)nh->nmn_record; struct nm_next_hdr *this_nh = nh->nmn_nextp; @@ -967,10 +964,11 @@ remove_entry( int remove_shared_entry( - struct nm_next_hdr *nh, /* First record header to start lookup */ - mdkey_t key, /* Shared key, used as key if nm is NULL */ - char *nm, /* Shared name, used as key if non-NULL */ - int devid_nm) /* which name space? */ + struct nm_next_hdr *nh, /* first record header to start lookup */ + mdkey_t key, /* shared key, used as key if nm is NULL */ + char *nm, /* shared name, used as key if non-NULL */ + int devid_nm) /* bitwise of NM_DEVID, NM_IMP_SHARED, */ + /* NM_NOCOMMIT, NM_KEY_RECYCLE */ { struct nm_rec_hdr *rh = (struct nm_rec_hdr *)nh->nmn_record; struct nm_next_hdr *this_nh = nh->nmn_nextp; @@ -1027,7 +1025,7 @@ remove_shared_entry( shn_size, offset, devid_nm)); if (nm_len == shn_namlen) { - if (!devid_nm) { + if (!(devid_nm & NM_DEVID)) { if (strcmp(nm, ((struct nm_shared_name *) shn)->sn_name) == 0) return (rem_shr_entry(this_nh, recid, @@ -1100,45 +1098,13 @@ build_device_number(set_t setno, struct nm_name *n) } void * -lookup_entry_record_offset( -struct nm_next_hdr *nh, /* head record header */ - set_t setno, /* set to lookup in */ - side_t side, /* (key 1) side number */ - mdkey_t key, /* (key 2) from md_setdevname */ - md_dev64_t dev, /* (alt. key 2) use if key == KEYWILD */ - int devid_nm, /* Which name space? */ - void *recp, /* pointer to the record containing the result */ - size_t *offsetp /* offset in the above record of result */ -) -{ - return (lookup_entry_common(nh, setno, side, key, dev, devid_nm, - &recp, offsetp)); -} - -void * lookup_entry( struct nm_next_hdr *nh, /* head record header */ set_t setno, /* set to lookup in */ side_t side, /* (key 1) side number */ mdkey_t key, /* (key 2) from md_setdevname */ md_dev64_t dev, /* (alt. key 2) use if key == KEYWILD */ - int devid_nm /* Which name space? */ -) -{ - return (lookup_entry_common(nh, setno, side, key, dev, devid_nm, - NULL, NULL)); -} - -void * -lookup_entry_common( - struct nm_next_hdr *nh, /* head record header */ - set_t setno, /* set to lookup in */ - side_t side, /* (key 1) side number */ - mdkey_t key, /* (key 2) from md_setdevname */ - md_dev64_t dev, /* (alt. key 2) use if key == KEYWILD */ - int devid_nm, /* Which name space? */ - void **recp, /* record containing the result */ - size_t *offsetp /* offset in the record of result */ + int devid_nm /* Which name space? */ ) { struct nm_next_hdr *this_nh = nh->nmn_nextp; @@ -1199,23 +1165,13 @@ lookup_entry_common( if ((side == n_side) || (side == MD_SIDEWILD)) { - if ((key != MD_KEYWILD) && (key == n_key)) { - if (recp) - *recp = record; - if (offsetp) - *offsetp = offset; + if ((key != MD_KEYWILD) && (key == n_key)) return ((void *)n); - } if ((key == MD_KEYWILD) && !devid_nm && (dev == build_device_number(setno, - (struct nm_name *)n))) { - if (recp) - *recp = record; - if (offsetp) - *offsetp = offset; + (struct nm_name *)n))) return ((void *)n); - } } @@ -1419,41 +1375,12 @@ lookup_deventry( } void * -lookup_shared_entry_record_offset( - struct nm_next_hdr *nh, /* First record header to start lookup */ - mdkey_t key, /* Shared key, used as key if nm is NULL */ - char *nm, /* Shared name, used as key if non-NULL */ - mddb_recid_t *id, /* mddb record id of record entry is found in */ - int devid_nm, /* which name space? */ - void *recp, /* pointer to record containing the result */ - size_t *offset_p /* offest in the above record of the result */ -) -{ - return (lookup_shared_entry_common(nh, key, nm, id, devid_nm, &recp, - offset_p)); -} - -void * lookup_shared_entry( - struct nm_next_hdr *nh, /* First record header to start lookup */ - mdkey_t key, /* Shared key, used as key if nm is NULL */ - char *nm, /* Shared name, used as key if non-NULL */ - mddb_recid_t *id, /* mddb record id of record entry is found in */ - int devid_nm) /* which name space? */ -{ - return (lookup_shared_entry_common(nh, key, nm, id, devid_nm, NULL, - NULL)); -} - -void * -lookup_shared_entry_common( struct nm_next_hdr *nh, /* First record header to start lookup */ mdkey_t key, /* Shared key, used as key if nm is NULL */ char *nm, /* Shared name, used as key if non-NULL */ mddb_recid_t *id, /* mddb record id of record entry is found in */ - int devid_nm, /* which name space? */ - void **recp, /* pointer to record containing the result */ - size_t *offsetp /* offest in the above record of the result */ + int devid_nm /* which name space? */ ) { @@ -1523,13 +1450,8 @@ lookup_shared_entry_common( shn_size = SHR_NAMSIZ((struct nm_shared_name *)shn); } - if ((key != 0) && (key == shn_key)) { - if (recp) - *recp = record; - if (offsetp) - *offsetp = offset; + if ((key != 0) && (key == shn_key)) return ((void *)shn); - } /* Lookup by name */ if (nm != NULL) { @@ -1539,35 +1461,20 @@ lookup_shared_entry_common( * and we want to do a partial match on that. */ if (strncmp(nm, ((struct nm_shared_name *)shn)->sn_name, - strlen(nm)) == 0) { - if (recp) - *recp = record; - if (offsetp) - *offsetp = offset; + strlen(nm)) == 0) return ((void *)shn); - } } else if (nm_len == shn_namlen) { - if (devid_nm & NM_DEVID) { + if (devid_nm & NM_DEVID) { if (ddi_devid_compare((ddi_devid_t)nm, (ddi_devid_t)(((struct did_shr_name *)shn)-> - did_devid)) == 0) { - if (recp) - *recp = record; - if (offsetp) - *offsetp = offset; + did_devid)) == 0) return ((void *)shn); - } - } else { + } else { if (strcmp(nm, ((struct nm_shared_name *) - shn)->sn_name) == 0) { - if (recp) - *recp = record; - if (offsetp) - *offsetp = offset; + shn)->sn_name) == 0) return ((void *)shn); } } - } } shn = (caddr_t)get_next_entry(this_nh, @@ -3308,16 +3215,11 @@ md_update_namespace_did( mdkey_t ent_did_key; uint32_t ent_did_count; uint32_t ent_did_data; - void *record, *n_record; - size_t offset; struct did_shr_name *shn; mddb_recid_t recids[3]; - struct nm_next_hdr *nh; - struct nm_next_hdr *this_did_nh; + struct nm_next_hdr *did_nh; struct did_min_name *n; struct did_shr_name *shr_n; - mdkey_t devid_key; - size_t ent_size, size; (void) md_load_namespace(setno, NULL, NM_DEVID); if (!md_load_namespace(setno, NULL, 0L)) { @@ -3326,34 +3228,20 @@ md_update_namespace_did( } rw_enter(&nm_lock.lock, RW_WRITER); - offset = (sizeof (struct devid_shr_rec) - sizeof (struct did_shr_name)); - if ((nh = get_first_record(setno, 0, NM_DEVID | NM_NOTSHARED)) == + if ((did_nh = get_first_record(setno, 0, NM_DEVID | NM_NOTSHARED)) == NULL) { rw_exit(&nm_lock.lock); return (ENOENT); } - this_did_nh = nh->nmn_nextp; - if (this_did_nh == NULL) { - rw_exit(&nm_lock.lock); - return (ENOENT); - } - record = this_did_nh->nmn_record; - if (record == NULL) { - rw_exit(&nm_lock.lock); - return (ENOENT); - } - - if ((n = (struct did_min_name *)lookup_entry(nh, setno, side, key, + if ((n = (struct did_min_name *)lookup_entry(did_nh, setno, side, key, NODEV64, NM_DEVID)) == NULL) { rw_exit(&nm_lock.lock); return (ENOENT); } - devid_key = n->min_devid_key; - rw_exit(&nm_lock.lock); - devt = md_dev64_to_dev( - md_getdevnum(setno, side, key, MD_TRUST_DEVT)); + rw_exit(&nm_lock.lock); + devt = md_dev64_to_dev(md_getdevnum(setno, side, key, MD_TRUST_DEVT)); rw_enter(&nm_lock.lock, RW_WRITER); if (ddi_lyr_get_devid(devt, &rtn_devid) == DDI_SUCCESS) { @@ -3364,12 +3252,9 @@ md_update_namespace_did( return ((int)NODEV64); } - n_record = did_shr_nh->nmn_nextp->nmn_record; - - shr_n = (struct did_shr_name *) - lookup_shared_entry_record_offset(did_shr_nh, devid_key, - (char *)0, &recids[0], NM_DEVID, n_record, &offset); - + shr_n = (struct did_shr_name *)lookup_shared_entry( + did_shr_nh, n->min_devid_key, (char *)0, + &recids[0], NM_DEVID); if (shr_n == NULL) { ddi_devid_free(rtn_devid); rw_exit(&nm_lock.lock); @@ -3382,29 +3267,10 @@ md_update_namespace_did( ent_did_key = shr_n->did_key; ent_did_count = shr_n->did_count; ent_did_data = shr_n->did_data; - ent_size = DID_SHR_NAMSIZ(shr_n); - - /* - * So we're going to overwrite this record; if it's the - * last entry, just bzero() it. If it's not, then copy - * the remaining entries back to the start of our entry - */ - - size = ((struct nm_rec_hdr *)n_record)->r_used_size - - offset - ent_size; - - ASSERT(size + offset <= ((struct nm_rec_hdr *) - n_record)->r_used_size); + (void) remove_shared_entry(did_shr_nh, + shr_n->did_key, NULL, NM_DEVID | + NM_KEY_RECYCLE); - if (size == 0) { - (void) bzero(shr_n, ent_size); - } else { - (void) ovbcopy((caddr_t)shr_n + ent_size, shr_n, - size); - (void) bzero((caddr_t)shr_n + size, ent_size); - } - ((struct nm_rec_hdr *)n_record)->r_used_size -= - ent_size; /* add in new devid info */ if ((shn = (struct did_shr_name *)alloc_entry( did_shr_nh, md_set[setno].s_did_nmid, @@ -3449,6 +3315,7 @@ md_update_namespace( mdkey_t key, /* (key 2) key provided by md_setdevname() */ char *devname, /* device name */ char *pathname, /* pathname to device */ + major_t major, /* major number */ minor_t mnum /* minor numer */ ) { @@ -3456,15 +3323,12 @@ md_update_namespace( struct nm_name *n; struct nm_next_hdr *snh; struct nm_shared_name *shn; - void *n_record; mddb_recid_t recids[3]; - size_t size; - mdkey_t ent_key, ent_drv_key, ent_dir_key, new_dir_key; + mdkey_t ent_key, ent_drv_key, ent_dir_key; uint32_t ent_count; side_t ent_side; - size_t offset; - char *old_pathname; - int ent_size; + char *old_pathname, *old_drvnm; + char *drvnm; if (!md_load_namespace(setno, NULL, 0L)) { return (ENOENT); @@ -3472,65 +3336,73 @@ md_update_namespace( rw_enter(&nm_lock.lock, RW_WRITER); - offset = sizeof (struct nm_rec) - sizeof (struct nm_name); - if ((nh = get_first_record(setno, 0, NM_NOTSHARED)) == NULL) { + if ((nh = get_first_record(setno, 0, NM_NOTSHARED)) == NULL || + (snh = get_first_record(setno, 0, NM_SHARED)) == NULL) { rw_exit(&nm_lock.lock); return (ENOENT); } - n_record = nh->nmn_nextp->nmn_record; - - if ((n = (struct nm_name *)lookup_entry_record_offset(nh, setno, side, - key, NODEV64, 0L, n_record, &offset)) == NULL) { + if ((n = (struct nm_name *)lookup_entry(nh, setno, side, key, NODEV64, + 0L)) == NULL) { rw_exit(&nm_lock.lock); return (ENOENT); } - /* save the values from the old record */ + /* Save the values from the old record */ ent_side = n->n_side; ent_key = n->n_key; ent_count = n->n_count; + + /* + * These can be overwritten + */ ent_drv_key = n->n_drv_key; ent_dir_key = n->n_dir_key; - ent_size = NAMSIZ(n); /* - * So we're going to overwrite this record; if it's the last - * entry, just bzero() it. If it's not, then copy the - * remaining entries back to the start of our entry + * Now can safely remove the entry + * If the entry is there it will be removed, + * otherwise nothing will happen to mddb */ - - size = ((struct nm_rec_hdr *)n_record)->r_used_size - offset - ent_size; - - ASSERT(offset + size <= ((struct nm_rec_hdr *)n_record)->r_alloc_size); - - if (size == 0) { - (void) bzero(n, ent_size); /* last entry */ - } else { - (void) ovbcopy((caddr_t)n + ent_size, n, size); - (void) bzero((caddr_t)n + size, ent_size); - } - ((struct nm_rec_hdr *)n_record)->r_used_size -= ent_size; + (void) remove_entry(nh, n->n_side, n->n_key, 0L | NM_KEY_RECYCLE); rw_exit(&nm_lock.lock); - /* check to see if we have a new pathname */ + /* The old path and drvnm has to be there */ old_pathname = md_getshared_name(setno, ent_dir_key); + old_drvnm = md_getshared_name(setno, ent_drv_key); + if (!old_pathname || !old_drvnm) { + return (ENOENT); + } + + /* Check to see if we have a new pathname */ if (strcmp(old_pathname, pathname)) { /* now see if the new pathname actually exists in our nsp */ - if ((snh = get_first_record(setno, 0, NM_SHARED)) == NULL) - return (ENOENT); shn = (struct nm_shared_name *)lookup_shared_entry( snh, NULL, pathname, &recids[0], 0L); if (shn) { /* pathname exists so get it's key */ - new_dir_key = shn->sn_key; + ent_dir_key = shn->sn_key; } else { /* pathname doesn't exist so create it */ - new_dir_key = + ent_dir_key = md_setshared_name(setno, pathname, NM_NOCOMMIT); } - /* update dir key */ - ent_dir_key = new_dir_key; + } + + /* + * Check and update n_drv_key as well since we can't + * blindly use the old one for the new drvnm + */ + drvnm = ddi_major_to_name(major); + if (strcmp(old_drvnm, drvnm)) { + shn = (struct nm_shared_name *)lookup_shared_entry( + snh, NULL, drvnm, &recids[0], 0L); + if (shn) { + ent_drv_key = shn->sn_key; + } else { + ent_drv_key = + md_setshared_name(setno, drvnm, NM_NOCOMMIT); + } } rw_enter(&nm_lock.lock, RW_WRITER); @@ -3548,14 +3420,12 @@ md_update_namespace( n->n_key = ent_key; n->n_count = ent_count; n->n_drv_key = ent_drv_key; + n->n_dir_key = ent_dir_key; /* fill-in filename */ (void) strcpy(n->n_name, devname); n->n_namlen = (ushort_t)(strlen(devname) + 1); - /* directory name */ - n->n_dir_key = ent_dir_key; - recids[1] = md_set[setno].s_nmid; recids[2] = 0; diff --git a/usr/src/uts/common/sys/lvm/md_names.h b/usr/src/uts/common/sys/lvm/md_names.h index 23a19c74cf..20b6d494d4 100644 --- a/usr/src/uts/common/sys/lvm/md_names.h +++ b/usr/src/uts/common/sys/lvm/md_names.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,15 +19,12 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved. */ #ifndef _SYS_MD_NAMES_H #define _SYS_MD_NAMES_H -#pragma ident "%Z%%M% %I% %E% SMI" - #ifdef __cplusplus extern "C" { #endif @@ -41,6 +37,7 @@ extern "C" { #define NM_NOTSHARED 0 #define NM_DEVID 0x0010 #define NM_IMP_SHARED 0x0020 +#define NM_KEY_RECYCLE 0x0040 #define NM_DEVID_VALID 1 #define NM_DEVID_INVALID 0 diff --git a/usr/src/uts/common/sys/lvm/mdvar.h b/usr/src/uts/common/sys/lvm/mdvar.h index 8f70a29e8b..3eff20c242 100644 --- a/usr/src/uts/common/sys/lvm/mdvar.h +++ b/usr/src/uts/common/sys/lvm/mdvar.h @@ -20,8 +20,7 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved. */ #ifndef _SYS_MDVAR_H @@ -810,7 +809,8 @@ extern int md_getdevid(set_t setno, side_t side, mdkey_t key, extern int md_getdevidminor(set_t setno, side_t side, mdkey_t key, char *minorname, size_t minorname_len); extern int md_update_namespace(set_t setno, side_t side, mdkey_t key, - caddr_t devname, caddr_t pathname, minor_t mnum); + caddr_t devname, caddr_t pathname, major_t major, + minor_t mnum); extern int md_update_locator_namespace(set_t setno, side_t side, caddr_t devname, caddr_t pathname, md_dev64_t devt); extern int md_update_namespace_did(set_t setno, side_t side, mdkey_t key, @@ -843,6 +843,7 @@ extern void *lookup_shared_entry(struct nm_next_hdr *, mdkey_t key, char *, mddb_recid_t *, int); extern int remove_shared_entry(struct nm_next_hdr *, mdkey_t key, char *, int); +extern int remove_entry(struct nm_next_hdr *, side_t, mdkey_t, int); extern void *alloc_entry(struct nm_next_hdr *, mddb_recid_t, size_t, int, mddb_recid_t *); extern void *getshared_name(set_t, mdkey_t, int); |