summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorJames Hall <James.Hall@Sun.COM>2010-06-23 10:37:46 +0100
committerJames Hall <James.Hall@Sun.COM>2010-06-23 10:37:46 +0100
commit32c22d57860198538fb6b8f261cb76ab26318d34 (patch)
treead634452f7d5849ffdfb3028f6751d3ddfb959c5 /usr/src
parentbbbbacb4bedf3d3959b4c3ec8ba1e07c8c10251d (diff)
downloadillumos-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.c6
-rw-r--r--usr/src/lib/lvm/libmeta/common/meta_nameinfo.c50
-rw-r--r--usr/src/uts/common/io/lvm/md/md.c7
-rw-r--r--usr/src/uts/common/io/lvm/md/md_ioctl.c5
-rw-r--r--usr/src/uts/common/io/lvm/md/md_mddb.c59
-rw-r--r--usr/src/uts/common/io/lvm/md/md_names.c306
-rw-r--r--usr/src/uts/common/sys/lvm/md_names.h11
-rw-r--r--usr/src/uts/common/sys/lvm/mdvar.h7
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);