Mercurial > illumos > illumos-gate
changeset 1623:7bac4a816ebe
PSARC/2005/153 Bunnahabhain: Descriptive Name Support in SVM
4521995 Allow descriptive names for metadevices and hot spare pools
6396962 metareplace -c is obsolete and no longer needed.
line wrap: on
line diff
--- a/usr/src/cmd/devfsadm/Makefile.com Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/cmd/devfsadm/Makefile.com Tue Mar 14 14:53:36 2006 -0800 @@ -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. @@ -19,8 +18,9 @@ # # CDDL HEADER END # + # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -192,7 +192,7 @@ $(RM) $@; cat $(POFILES) > $@ $(DEVFSADM_MOD): $(DEVFSADM_OBJ) - $(LINK.c) -o $@ $< $(DEVFSADM_OBJ) $(LDLIBS) + $(LINK.c) -o $@ $< $(DEVFSADM_OBJ) $(LDLIBS) -lmeta $(POST_PROCESS) SUNW_%.so: %.o
--- a/usr/src/cmd/devfsadm/md_link.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/cmd/devfsadm/md_link.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,12 +19,13 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" +#include <meta.h> #include <regex.h> #include <devfsadm.h> #include <stdio.h> @@ -34,8 +34,8 @@ #include <limits.h> #include <sys/mkdev.h> -#define MD_LINK_RE_DEVICES "^md/r?dsk/d[0-9]+$" -#define MD_LINK_RE_SHARED "^md/shared/[0-9]+/r?dsk/d[0-9]+$" +#define MD_LINK_RE_DEVICES "^md/r?dsk/.+$" +#define MD_LINK_RE_SHARED "^md/shared/[0-9]+/r?dsk/.+$" #define MD_LINK_RE_ADMIN "^md/admin" /* @@ -77,19 +77,25 @@ * For the admin device: * /dev/md/admin -> /devices/pseudo/md@0:admin * - * For each other device - * /dev/md/dsk/dN -> /devices/pseudo/md@0:0,N,blk - * /dev/md/rdsk/dN -> /devices/pseudo/md@0:0,N,raw - * /dev/md/shared/M/dsk/dN /devices/pseudo/md@0:M,N,blk - * /dev/md/shared/M/rdsk/dN /devices/pseudo/md@0:M,N,raw + * For metadevice: + * /dev/md/dsk/foobar --> /devices/pseudo/md@0:0,100,blk + * /dev/md/rdsk/foobar --> /devices/pseudo/md@0:0,100,raw + * + * Where 'foobar' is user specified arbitrary name and '100' + * is the minor number returned by MD_IOCMAKE_DEV ioctl + * */ static int md_create(di_minor_t minor, di_node_t node) { char mn[MAXNAMELEN + 1]; char path[PATH_MAX + 1]; - int set = -1, mdev = -1, ret; + int set = -1, ret; char *type, *dir; + char *device_name; + dev_t minor_devt = di_minor_devt(minor); + int key; + md_error_t ep; (void) strcpy(mn, di_minor_name(minor)); @@ -115,26 +121,38 @@ * under the "shared" directory entry instead of linking * into the top level dsk/rdsk directories. */ - ret = sscanf(mn, "%d,%d,", &set, &mdev); - if (ret == 2 && (type = strrchr(mn, ',')) != NULL) { - type ++; + ret = sscanf(mn, "%d,", &set); + if (ret == 1 && (type = strrchr(mn, ',')) != NULL) { + type++; if (strcmp(type, "blk") == 0) { dir = "dsk"; } else { dir = "rdsk"; } + + (void) memset(&ep, '\0', sizeof (ep)); + if ((device_name = meta_getnmentbydev(set, + MD_SIDEWILD, minor_devt, NULL, NULL, + &key, &ep)) == NULL) { + (void) close_admin(&ep); + return (DEVFSADM_CONTINUE); + } + if (set == 0) { /* this is a simple md */ (void) snprintf(path, sizeof (path), - "md/%s/d%d", dir, mdev); + "md/%s/%s", dir, basename(device_name)); } else { /* this is a shared md */ (void) snprintf(path, sizeof (path), - "md/shared/%d/%s/d%d", - set, dir, mdev); + "md/shared/%d/%s/%s", set, dir, + basename(device_name)); } (void) devfsadm_mklink(path, node, minor, 0); + Free(device_name); } } + + (void) close_admin(&ep); return (DEVFSADM_CONTINUE); }
--- a/usr/src/cmd/lvm/metassist/layout/layout_svm_util.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/cmd/lvm/metassist/layout/layout_svm_util.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -1672,7 +1671,7 @@ mdname_t *mdn; md_raid_t *raid; - mdn = metaname(&sp, nlp->namep->cname, &error); + mdn = metaname(&sp, nlp->namep->cname, META_DEVICE, &error); mdclrerror(&error); if (mdn == NULL) { continue; @@ -1704,7 +1703,7 @@ mdname_t *mdn; md_stripe_t *stripe; - mdn = metaname(&sp, nlp->namep->cname, &error); + mdn = metaname(&sp, nlp->namep->cname, META_DEVICE, &error); mdclrerror(&error); if (mdn == NULL) { continue; @@ -1745,7 +1744,7 @@ mdname_t *mdn; md_sp_t *soft_part; - mdn = metaname(&sp, nlp->namep->cname, &error); + mdn = metaname(&sp, nlp->namep->cname, META_DEVICE, &error); mdclrerror(&error); if (mdn == NULL) { continue; @@ -1901,8 +1900,13 @@ { mdname_t *mdn; md_error_t error = mdnullerror; + meta_device_type_t uname_type = UNKNOWN; - mdn = metaname(&sp, slice_name, &error); + /* Determine the appropriate uname type for metaname */ + if (type == SVM_MDB || type == SVM_DRIVE || type == SVM_TRANS) + uname_type = LOGICAL_DEVICE; + + mdn = metaname(&sp, slice_name, uname_type, &error); if (!mdisok(&error)) { mdn = NULL; }
--- a/usr/src/cmd/lvm/rpc.metad/metad_svc_subr.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/cmd/lvm/rpc.metad/metad_svc_subr.c Tue Mar 14 14:53:36 2006 -0800 @@ -2140,7 +2140,7 @@ if ((np = metaslicename(dp, MD_SLICE0, ep)) == NULL) return; - if ((real_np = metaname(&sp, np->bname, ep)) == NULL) + if ((real_np = metaname(&sp, np->bname, LOGICAL_DEVICE, ep)) == NULL) return; res->dev = real_np->dev; @@ -2262,7 +2262,7 @@ if ((np = metaslicename(dp, MD_SLICE0, ep)) == NULL) return; - if (metaname(&sp, np->bname, ep) == NULL) + if (metaname(&sp, np->bname, LOGICAL_DEVICE, ep) == NULL) return; res->enc_devid = meta_get_devid(np->rname); @@ -2381,7 +2381,7 @@ return (TRUE); } - np = metaname(&sp, disklist[0].devname, ep); + np = metaname(&sp, disklist[0].devname, LOGICAL_DEVICE, ep); if (np != NULL) { mdcinfo_t *cinfo; if ((cinfo = metagetcinfo(np, ep)) != NULL) { @@ -2493,7 +2493,7 @@ if (disklist[i].dev == NODEV) i = 0; - np = metaname(&sp, disklist[i].devname, ep); + np = metaname(&sp, disklist[i].devname, LOGICAL_DEVICE, ep); if (np != NULL) { mdcinfo_t *cinfo; if ((cinfo = metagetcinfo(np, ep)) != NULL) { @@ -5138,9 +5138,9 @@ if (metaioctl(MD_MN_GET_MM_OWNER, ownpar, ep, "MD_MN_GET_MM_OWNER") != 0) { mde_perror(ep, gettext( - "Unable to get mirror owner for %s/d%u"), + "Unable to get mirror owner for %s/%s"), local_sp->setname, - (unsigned)MD_MIN2UNIT(ownpar->d.mnum)); + get_mdname(local_sp, ownpar->d.mnum)); goto out; } @@ -5160,9 +5160,9 @@ MD_MN_MM_ALLOW_CHANGE) == -1) { mde_perror(ep, gettext( "Unable to reset mirror owner for" - " %s/d%u"), local_sp->setname, - (unsigned)MD_MIN2UNIT( - ownpar->d.mnum)); + " %s/%s"), local_sp->setname, + get_mdname(local_sp, + ownpar->d.mnum)); goto out; } break;
--- a/usr/src/cmd/lvm/util/metaclear.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/cmd/lvm/util/metaclear.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -47,7 +46,7 @@ { /* clear hotspare pool */ - if (is_hspname(uname)) { + if (is_existing_hsp(*spp, uname)) { mdhspname_t *hspnp; /* get hotspare pool name */ @@ -71,8 +70,12 @@ else { mdname_t *np; + /* check for ownership */ + if (meta_check_ownership(*spp, ep) != 0) + return (-1); + /* get metadevice name */ - if (((np = metaname(spp, uname, ep)) == NULL) || + if (((np = metaname(spp, uname, META_DEVICE, ep)) == NULL) || (metachkmeta(np, ep) != 0)) { return (-1); } @@ -82,10 +85,6 @@ if (meta_lock(*spp, TRUE, ep)) return (-1); - /* check for ownership */ - if (meta_check_ownership(*spp, ep) != 0) - return (-1); - /* clear metadevice */ return (meta_reset_by_name(*spp, np, options, ep)); } @@ -119,10 +118,11 @@ char *argv[] ) { - char *sname = NULL; + char *sname = MD_LOCAL_NAME; mdsetname_t *sp = NULL; int aflag = 0; int pflag = 0; + int set_flag = 0; mdcmdopts_t options = (MDCMD_PRINT|MDCMD_DOIT); int c; md_error_t status = mdnullerror; @@ -172,6 +172,7 @@ case 's': sname = optarg; + set_flag++; break; case 'a': @@ -201,30 +202,20 @@ argc -= optind; argv += optind; - if (sname != NULL && (sp = metasetname(sname, ep)) == NULL) { - goto errout; + /* with mn sets if -a, set name must have been specified by -s */ + if (called_thru_rpc && aflag && !set_flag) { + md_eprintf(gettext( + "-a parameter requires the use of -s in multi-node sets")); + md_exit(sp, 1); + } + + /* get set context */ + if ((sp = metasetname(sname, ep)) == NULL) { + mde_perror(ep, ""); + md_exit(sp, 1); } if (called_thru_rpc) { - - if (aflag) { - /* if -a, set name must have been specified by -s */ - if ((sp == NULL) || - (metaget_setdesc(sp, ep) == NULL)) - goto errout; - } else { - /* - * setname may be defined by setname in first arg - * if sp is NULL, meta_is_mn_name() derives sp from - * argv[0], eg from set/d10 - */ - if (meta_is_mn_name(&sp, argv[0], ep)) { - if (metaget_setdesc(sp, ep) == NULL) - goto errout; - } else - goto errout; - } - /* Check if the device is open on all nodes */ options |= MDCMD_MN_OPEN_CHECK; } @@ -233,12 +224,6 @@ if (argc != 0) usage(sp, 1); - if (sp == NULL) { - /* Get sp for local set */ - if ((sp = metasetname(MD_LOCAL_NAME, ep)) == NULL) - goto errout; - } - /* * If a MN set, we will generate a series of individual * metaclear commands which will each grab the set lock. @@ -271,13 +256,12 @@ */ if (argc <= 0) usage(sp, 1); + if (meta_is_mn_name(&sp, argv[0], ep)) mnset = TRUE; eval = 0; for (; (argc > 0); --argc, ++argv) { - mdhspname_t *hspnp; - mdname_t *np; char *cname; /* @@ -287,45 +271,32 @@ * deal with it. */ if (!called_thru_rpc && mnset) { + /* get the canonical name */ if (pflag) { /* * If -p, set cname to the device * argument. */ - cname = argv[0]; + cname = Strdup(argv[0]); } else { /* * For hotspares and metadevices, set * cname to the full name, * setname/hspxxx or setname/dxxx */ - if (is_hspname(argv[0])) { - /* get hotspare pool name */ - if ((hspnp = metahspname(&sp, - argv[0], ep)) == NULL) { - mde_perror(ep, ""); - eval = 1; - continue; - } - cname = hspnp->hspname; - } else { - /* get metadevice name */ - if (((np = metaname(&sp, - argv[0], ep)) == NULL) || - (metachkmeta(np, ep) - != 0)) { - mde_perror(ep, ""); - eval = 1; - continue; - } - cname = np->cname; + cname = meta_name_getname(&sp, + argv[0], META_DEVICE, ep); + if (cname == NULL) { + mde_perror(ep, ""); + eval = 1; + continue; } } if (meta_mn_send_metaclear_command(sp, cname, options, pflag, ep) != 0) { eval = 1; - continue; } + Free(cname); } else { if (pflag) { /* @@ -339,24 +310,34 @@ continue; } } else { - /* clear named devices */ - if (clear_name(&sp, argv[0], - options, ep) != 0) { + /* + * get the canonical name and + * setup sp if it has been + * specified as part of the + * metadevice/hsp name param + */ + cname = meta_name_getname(&sp, + argv[0], META_DEVICE, ep); + if (cname == NULL) { mde_perror(ep, ""); eval = 1; continue; } + + /* clear named devices */ + if (clear_name(&sp, cname, + options, ep) != 0) { + mde_perror(ep, ""); + eval = 1; + Free(cname); + continue; + } + Free(cname); } } } } /* update md.cf */ - if (sp == NULL) { - /* Get sp for local set */ - if ((sp = metasetname(MD_LOCAL_NAME, ep)) == NULL) - goto errout; - } - if (meta_update_md_cf(sp, ep) != 0) { mde_perror(ep, ""); eval = 1;
--- a/usr/src/cmd/lvm/util/metaclust.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/cmd/lvm/util/metaclust.c Tue Mar 14 14:53:36 2006 -0800 @@ -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. @@ -21,7 +20,7 @@ */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -238,19 +237,25 @@ compose_path(mdsetname_t *sp, int mnum, char *pathname, int pathlen) { int rtn; + mdname_t *np; + md_error_t status = mdnullerror; if (MD_MIN2SET(mnum) != sp->setno) { md_eprintf(gettext("minor number 0x%x invalid for set %d\n"), mnum, sp->setno); return (-1); } - rtn = snprintf(pathname, pathlen, "/dev/md/%s/rdsk/d%u", - sp->setname, (unsigned)MD_MIN2UNIT(mnum)); + + if ((np = metamnumname(&sp, mnum, 0, &status)) == NULL) { + return (-1); + } + + rtn = snprintf(pathname, pathlen, "%s", np->rname); if ((pathname[0] == '\0') || (rtn >= pathlen)) { md_eprintf(gettext( - "Could not create path for device %s/d%u\n"), - sp->setname, (unsigned)MD_MIN2UNIT(mnum)); + "Could not create path for device %s\n"), + get_mdname(sp, mnum)); return (-1); } return (0); @@ -328,15 +333,14 @@ mir_state->mnum = meta_getminor(devnp->dev); MD_SETDRIVERNAME(mir_state, MD_MIRROR, sp->setno); meta_mc_log(MC_LOG4, gettext("Getting mirror state" - " for %s/d%u: %s"), sp->setname, - (unsigned)MD_MIN2UNIT(mir_state->mnum), + " for %s: %s"), get_mdname(sp, mir_state->mnum), meta_print_hrtime(gethrtime() - start_time)); if (metaioctl(MD_MN_GET_MIRROR_STATE, mir_state, ep, "MD_MN_GET_MIRROR_STATE") != 0) { mde_perror(ep, gettext("Unable to get " - "mirror state for %s/d%u"), sp->setname, - (unsigned)MD_MIN2UNIT(mir_state->mnum)); + "mirror state for %s"), + get_mdname(sp, mir_state->mnum)); goto out; } else { continue; @@ -372,16 +376,15 @@ MD_SETDRIVERNAME(ownpar, MD_MIRROR, sp->setno); meta_mc_log(MC_LOG4, gettext("Setting owner " - "for %s/d%u: %s"), sp->setname, - (unsigned)MD_MIN2UNIT(ownpar->d.mnum), + "for %s: %s"), get_mdname(sp, ownpar->d.mnum), meta_print_hrtime(gethrtime() - start_time)); /* get the current owner id */ if (metaioctl(MD_MN_GET_MM_OWNER, ownpar, ep, "MD_MN_GET_MM_OWNER") != 0) { mde_perror(ep, gettext("Unable to get " - "mirror owner for %s/d%u"), sp->setname, - (unsigned)MD_MIN2UNIT(ownpar->d.mnum)); + "mirror owner for %s"), + get_mdname(sp, ownpar->d.mnum)); goto out; } } @@ -407,18 +410,16 @@ MD_MN_MM_ALLOW_CHANGE) == -1) { md_eprintf(gettext( "Unable to reset mirror owner " - "for %s/d%u\n"), sp->setname, - (unsigned)MD_MIN2UNIT( - ownpar->d.mnum)); + "for %s\n"), + get_mdname(sp, ownpar->d.mnum)); goto out; } if (meta_mirror_resync(sp, devnp, 0, ep, MD_RESYNC_KILL_NO_WAIT) != 0) { md_eprintf(gettext( "Unable to kill resync for" - " %s/d%u\n"), sp->setname, - (unsigned)MD_MIN2UNIT( - ownpar->d.mnum)); + " %s\n"), + get_mdname(sp, ownpar->d.mnum)); goto out; } } @@ -441,8 +442,8 @@ ownpar->d.mnum, ownpar->d.owner, MD_MN_MM_CHOOSE_OWNER) == -1) { md_eprintf(gettext("Unable to choose " - "mirror owner for %s/d%u\n"), sp->setname, - (unsigned)MD_MIN2UNIT(ownpar->d.mnum)); + "mirror owner for %s\n"), + get_mdname(sp, ownpar->d.mnum)); goto out; } } @@ -465,7 +466,7 @@ * cluster, ABR will be cleared on all nodes. */ char *miscname; - char name[MD_MAX_CTDLEN]; + char name[MAXPATHLEN]; int mnum, fd; name[0] = '\0'; @@ -483,8 +484,7 @@ continue; meta_mc_log(MC_LOG4, gettext("Re-setting ABR state " - "for %s/d%u: %s"), sp->setname, - (unsigned)MD_MIN2UNIT(mnum), + "for %s: %s"), get_mdname(sp, mnum), meta_print_hrtime(gethrtime() - start_time)); /* compose the absolute device path and open it */ @@ -507,7 +507,7 @@ */ char *miscname; - char name[MD_MAX_CTDLEN]; + char name[MAXPATHLEN]; int mnum, fd; volcap_t vc; uint_t tstate; @@ -535,8 +535,7 @@ continue; meta_mc_log(MC_LOG4, gettext("Updating ABR state " - "for %s/d%u: %s"), sp->setname, - (unsigned)MD_MIN2UNIT(mnum), + "for %s: %s"), get_mdname(sp, mnum), meta_print_hrtime(gethrtime() - start_time)); /* compose the absolute device path and open it */
--- a/usr/src/cmd/lvm/util/metadb.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/cmd/lvm/util/metadb.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -75,7 +74,7 @@ { mdname_t *np; - if ((np = metaname(&sp, name, ep)) == NULL) + if ((np = metaname(&sp, name, LOGICAL_DEVICE, ep)) == NULL) return (NULL); return (metanamelist_append(nlp, np));
--- a/usr/src/cmd/lvm/util/metadetach.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/cmd/lvm/util/metadetach.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -90,7 +89,7 @@ usage(*spp, 1); /* get submirror */ - if ((submirnp = metaname(spp, argv[1], ep)) == NULL) + if ((submirnp = metaname(spp, argv[1], META_DEVICE, ep)) == NULL) return (-1); /* detach submirror */ @@ -238,7 +237,7 @@ } /* Get metadevice name */ - if (((np = metaname(&sp, argv[optind], ep)) == NULL) || + if (((np = metaname(&sp, argv[optind], META_DEVICE, ep)) == NULL) || (metachkmeta(np, ep) != 0)) { mde_perror(ep, ""); md_exit(sp, 1);
--- a/usr/src/cmd/lvm/util/metahs.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/cmd/lvm/util/metahs.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -60,7 +59,7 @@ /* must have set */ assert(sp != NULL); - assert(sp->setno == HSP_SET(hspnp->hsp)); + assert(hspnp->hsp == MD_HSP_NONE || sp->setno == HSP_SET(hspnp->hsp)); /* print status */ if (meta_hsp_print(sp, hspnp, &nlp, NULL, stdout, options, ep) != 0) @@ -93,18 +92,6 @@ } /* - * check for "all" - */ -static int -is_all(char *s) -{ - if ((strcoll(s, gettext("all")) == 0) || - (strcoll(s, gettext("ALL")) == 0)) - return (1); - return (0); -} - -/* * parse args and add hotspares */ static int @@ -125,11 +112,7 @@ /* get hotspare pool name(s) */ if (argc < 1) usage(*spp, 1); - if ((argc > 1) && is_all(argv[0])) { - if ((*spp == NULL) && - ((*spp = metasetname(MD_LOCAL_NAME, ep)) == NULL)) { - return (-1); - } + if ((argc > 1) && meta_is_all(argv[0])) { /* check for ownership */ assert(*spp != NULL); if (meta_check_ownership(*spp, ep) != 0) @@ -140,9 +123,12 @@ } else if (cnt == 0) { return (mderror(ep, MDE_NO_HSPS, NULL)); } - } else if ((cnt = metahspnamelist(spp, &hspnlp, 1, &argv[0], - ep)) < 0) { - return (-1); + } else { /* create the hsp nmlist from the specified hsp name */ + if (!is_hspname(argv[0])) + return (mderror(ep, MDE_NAME_ILLEGAL, argv[0])); + + if ((cnt = metahspnamelist(spp, &hspnlp, 1, &argv[0], ep)) < 0) + return (-1); } assert(cnt > 0); --argc, ++argv; @@ -158,7 +144,8 @@ return (-1); /* get hotspares */ - if (metanamelist(spp, &nlp, argc, argv, ep) < 0) { + if (metanamelist(spp, &nlp, argc, argv, + LOGICAL_DEVICE, ep) < 0) { goto out; } @@ -201,11 +188,7 @@ /* get hotspare pool name(s) */ if (argc < 1) usage(*spp, 1); - if ((argc > 1) && is_all(argv[0])) { - if ((*spp == NULL) && - ((*spp = metasetname(MD_LOCAL_NAME, ep)) == NULL)) { - return (-1); - } + if ((argc > 1) && meta_is_all(argv[0])) { /* check for ownership */ assert(*spp != NULL); if (meta_check_ownership(*spp, ep) != 0) @@ -234,7 +217,8 @@ return (-1); /* get hotspares */ - if (metanamelist(spp, &nlp, argc, argv, ep) < 0) { + if (metanamelist(spp, &nlp, argc, argv, + LOGICAL_DEVICE, ep) < 0) { goto out; } @@ -292,7 +276,8 @@ usage(*spp, 1); /* get list of hotspares */ - if (metanamelist(spp, &nlp, argc, argv, ep) < 0) + if (metanamelist(spp, &nlp, argc, argv, + LOGICAL_DEVICE, ep) < 0) goto out; assert(nlp != NULL); @@ -337,11 +322,7 @@ /* get hotspare pool name(s) */ if (argc != 3) usage(*spp, 1); - if (is_all(argv[0])) { - if ((*spp == NULL) && - ((*spp = metasetname(MD_LOCAL_NAME, ep)) == NULL)) { - return (-1); - } + if (meta_is_all(argv[0])) { /* check for ownership */ assert(*spp != NULL); if (meta_check_ownership(*spp, ep) != 0) @@ -369,11 +350,11 @@ return (-1); /* get old component */ - if ((oldnp = metaname(spp, argv[1], ep)) == NULL) + if ((oldnp = metaname(spp, argv[1], LOGICAL_DEVICE, ep)) == NULL) goto out; /* get new component */ - if ((newnp = metaname(spp, argv[2], ep)) == NULL) + if ((newnp = metaname(spp, argv[2], LOGICAL_DEVICE, ep)) == NULL) goto out; /* replace hotspares */ @@ -480,10 +461,6 @@ /* get hotspare pool name(s) */ if (argc == 0) { - if ((*spp == NULL) && - ((*spp = metasetname(MD_LOCAL_NAME, ep)) == NULL)) { - return (-1); - } /* check for ownership */ assert(*spp != NULL); if (meta_check_ownership(*spp, ep) != 0) @@ -696,6 +673,24 @@ if (which_op == NONE) usage(sp, 1); + /* + * if a hot spare pool was specified by name then + * get the canonical form of the name and set up + * sp if the name was specified in the form 'set/hsp' + * unless 'all' is specified or the request is made to + * enable a hs which means that argv[0] will be a component + */ + if (argc > 0 && !meta_is_all(argv[0]) && which_op != ENABLE_A_HS) { + char *cname = NULL; + + cname = meta_name_getname(&sp, argv[0], HSP_DEVICE, ep); + if (cname == NULL) { + mde_perror(ep, ""); + md_exit(sp, 1); + } + Free(cname); + } + if (which_op == STATUS_A_HSP) { if (status_hotspares(&sp, argc, argv, ep) != 0) { mde_perror(ep, "");
--- a/usr/src/cmd/lvm/util/metainit.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/cmd/lvm/util/metainit.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -128,14 +127,18 @@ /* for all matching entries, which haven't already been done */ for (line = 0; (line < tabp->nlines); ++line) { md_tab_line_t *linep = &tabp->lines[line]; + char *uname = linep->argv[0]; /* see if already done */ if (linep->flags != DO_AGAIN) continue; + /* clear the metadev/hsp caches between inits */ + metaflushmetanames(); + /* try it */ if ((called_thru_rpc == FALSE) && - meta_is_mn_name(spp, linep->argv[0], ep)) { + meta_is_mn_name(spp, uname, ep)) { /* * MN set, send command to all nodes * Note that is sp is NULL, meta_is_mn_name() derives @@ -144,15 +147,26 @@ ret = mn_send_command(spp, linep->argc, linep->argv, options, flags, linep->context, ep); } else { - ret = meta_init_name(spp, linep->argc, linep->argv, - options, ep); - if (ret != 0) { - if (!(flags & MD_IGNORE_STDERR)) { - mderrorextra(ep, linep->context); - mde_perror(ep, ""); - rval = -1; + char *cname = NULL; + + cname = meta_name_getname(spp, uname, META_DEVICE, ep); + if (cname == NULL) { + mde_perror(ep, ""); + mdclrerror(ep); + } else { + + ret = meta_init_name(spp, linep->argc, + linep->argv, cname, options, ep); + Free(cname); + + if (ret != 0) { + if (!(flags & MD_IGNORE_STDERR)) { + mderrorextra(ep, linep->context); + mde_perror(ep, ""); + rval = -1; + } + mdclrerror(ep); } - mdclrerror(ep); } } if (ret == 0) { @@ -184,16 +198,6 @@ int done; int eval = -1; - /* create local set, if necessary */ - if (*spp == NULL) { - if ((*spp = metasetname(MD_LOCAL_NAME, ep)) == NULL) { - mde_perror(ep, ""); - mdclrerror(ep); - return (eval); - } - } - setlen = strlen((*spp)->setname); - /* * Only take the lock if this is not a MN set * We can only enter this code for a MN set if we are the initiator @@ -225,6 +229,7 @@ return (eval); } + setlen = strlen((*spp)->setname); for (more = 0; (more < tabp->nlines); ++more) { md_tab_line_t *linep = &tabp->lines[more]; char *cname = linep->cname; @@ -290,11 +295,10 @@ md_tab_line_t *linep = NULL; int rval = -1; int ret; + char *uname = argv[0]; /* look in md.tab */ if (argc == 1) { - char *name = argv[0]; - /* get md.tab entries */ if ((tabp = meta_tab_parse(NULL, ep)) == NULL) { if (! mdissyserror(ep, ENOENT)) @@ -302,7 +306,7 @@ } /* look in md.tab */ - if ((linep = meta_tab_find(*spp, tabp, name, TAB_MD_HSP)) + if ((linep = meta_tab_find(*spp, tabp, uname, TAB_MD_HSP)) != NULL) { argc = linep->argc; argv = linep->argv; @@ -310,14 +314,29 @@ } if ((called_thru_rpc == FALSE) && - meta_is_mn_name(spp, argv[0], ep)) { + meta_is_mn_name(spp, uname, ep)) { /* * MN set, send command to all nodes */ ret = mn_send_command(spp, argc, argv, options, MD_DISP_STDERR, NO_CONTEXT_STRING, ep); - } else - ret = meta_init_name(spp, argc, argv, options, ep); + } else { + char *cname = NULL; + + cname = meta_name_getname(spp, uname, META_DEVICE, ep); + if (cname == NULL) { + goto out; + } + + /* check for ownership */ + if (meta_check_ownership(*spp, ep) != 0) { + Free(cname); + goto out; + } + + ret = meta_init_name(spp, argc, argv, cname, options, ep); + Free(cname); + } if (ret != 0) { if (linep != NULL) @@ -687,7 +706,7 @@ char *argv[] ) { - char *sname = NULL; + char *sname = MD_LOCAL_NAME; mdsetname_t *sp = NULL; enum action { NONE, @@ -784,12 +803,12 @@ } } - if (sname != NULL) { - if ((sp = metasetname(sname, ep)) == NULL) { - mde_perror(ep, ""); - md_exit(sp, 1); - } + /* sname is MD_LOCAL_NAME if not specified on the command line */ + if ((sp = metasetname(sname, ep)) == NULL) { + mde_perror(ep, ""); + md_exit(sp, 1); } + argc -= optind; argv += optind; if (todo == NONE) {
--- a/usr/src/cmd/lvm/util/metaoffline.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/cmd/lvm/util/metaoffline.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -139,8 +138,8 @@ } /* get names */ - if (((mirnp = metaname(&sp, argv[0], ep)) == NULL) || - ((submirnp = metaname(&sp, argv[1], ep)) == NULL)) { + if (((mirnp = metaname(&sp, argv[0], META_DEVICE, ep)) == NULL) || + ((submirnp = metaname(&sp, argv[1], META_DEVICE, ep)) == NULL)) { mde_perror(ep, ""); md_exit(sp, 1); }
--- a/usr/src/cmd/lvm/util/metaonline.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/cmd/lvm/util/metaonline.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -135,8 +134,8 @@ } /* get names */ - if (((mirnp = metaname(&sp, argv[0], ep)) == NULL) || - ((submirnp = metaname(&sp, argv[1], ep)) == NULL)) { + if (((mirnp = metaname(&sp, argv[0], META_DEVICE, ep)) == NULL) || + ((submirnp = metaname(&sp, argv[1], META_DEVICE, ep)) == NULL)) { mde_perror(ep, ""); md_exit(sp, 1); }
--- a/usr/src/cmd/lvm/util/metaparam.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/cmd/lvm/util/metaparam.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -35,18 +34,6 @@ #include <sdssc.h> /* - * check for "none" - */ -static int -is_none(char *s) -{ - if ((strcoll(s, gettext("none")) == 0) || - (strcoll(s, gettext("NONE")) == 0)) - return (1); - return (0); -} - -/* * print usage message */ static void @@ -202,7 +189,7 @@ break; case 'h': - if (is_none(optarg)) { + if (meta_is_none(optarg)) { msp.hsp_id = MD_HSP_NONE; } else if ((hspnp = metahspname(&sp, optarg, ep)) == NULL) { @@ -289,7 +276,7 @@ break; case 'h': - if (is_none(optarg)) { + if (meta_is_none(optarg)) { msp.hsp_id = MD_HSP_NONE; } else if ((hspnp = metahspname(&sp, optarg, ep)) == NULL) { @@ -442,7 +429,7 @@ md_exit(sp, result); } - if ((np = metaname(&sp, argv[optind], ep)) == NULL) { + if ((np = metaname(&sp, argv[optind], META_DEVICE, ep)) == NULL) { mde_perror(ep, ""); md_exit(sp, 1); }
--- a/usr/src/cmd/lvm/util/metarecover.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/cmd/lvm/util/metarecover.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -142,7 +141,7 @@ argv++; argc--; - if ((namep = metaname(&sp, devname, ep)) == NULL) { + if ((namep = metaname(&sp, devname, UNKNOWN, ep)) == NULL) { mde_perror(ep, ""); md_exit(sp, 1); }
--- a/usr/src/cmd/lvm/util/metarename.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/cmd/lvm/util/metarename.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -221,13 +220,14 @@ } if (i == 1 && !xflag) { /* rename, create dest metadevice name */ - if (meta_init_make_device(&sp, argv[i], ep) != 0) { + if (meta_init_make_device(&sp, argv[i], ep) <= 0) { mde_perror(ep, argv[i]); md_exit(sp, 1); } } - if (NULL == (mdnms[i] = metaname(&sp, argv[i], ep))) { + if ((mdnms[i] = metaname(&sp, argv[i], + META_DEVICE, ep)) == NULL) { mde_perror(ep, argv[i]); md_exit(sp, 1); }
--- a/usr/src/cmd/lvm/util/metareplace.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/cmd/lvm/util/metareplace.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -47,9 +46,8 @@ usage: %s [-s setname] mirror component-old component-new\n\ %s [-s setname] -e mirror component\n\ %s [-s setname] [-f] RAID component-old component-new\n\ - %s [-s setname] [-f] -e RAID component\n\ - %s [-s setname] -c metadevice component-old component-new\n"), - myname, myname, myname, myname, myname); + %s [-s setname] [-f] -e RAID component\n"), + myname, myname, myname, myname); md_exit(sp, eval); } @@ -67,7 +65,6 @@ mdcmdopts_t options = (MDCMD_PRINT|MDCMD_DOIT); mdname_t *namep; int eflag = 0; - int cflag = 0; int c; md_error_t status = mdnullerror; md_error_t *ep = &status; @@ -111,7 +108,7 @@ /* parse arguments */ optind = 1; opterr = 1; - while ((c = getopt(argc, argv, "hs:cefn?")) != -1) { + while ((c = getopt(argc, argv, "hs:efn?")) != -1) { switch (c) { case 'h': usage(sp, 0); @@ -137,11 +134,6 @@ } break; - case 'c': - options |= MDCMD_CLUSTER_REPLACE; - ++cflag; - break; - case '?': if (optopt == '?') usage(sp, 0); @@ -167,30 +159,14 @@ uname = argv[0]; - if (((namep = metaname(&sp, argv[0], ep)) == NULL)) { + if (((namep = metaname(&sp, uname, META_DEVICE, ep)) == NULL)) { mde_perror(ep, ""); md_exit(sp, 1); } - /* - * This 'if' statement might look a little strange so I'll 'splain - * a few things. - * - * If 'cflag' is not set then always do the metachkmeta. - * This is the normal behavior and you're not allowed to run - * metarplace on a hotspare. metachkmeta will barf. - * - * If 'cflag' and uname is not a hotspare do metachkmeta - * Still need to check out the metadevice as long as it's not - * a hotspare. - * - * Else we've got a hotspare so we can't call metachkmeta - */ - if ((!cflag) || (cflag && (!is_hspname(uname)))) { - if (metachkmeta(namep, ep) != 0) { - mde_perror(ep, ""); - md_exit(sp, 1); - } + if (metachkmeta(namep, ep) != 0) { + mde_perror(ep, ""); + md_exit(sp, 1); } assert(sp != NULL); @@ -274,7 +250,7 @@ if (argc != 1) usage(sp, 1); - if ((compnp = metaname(&sp, argv[0], ep)) == NULL) { + if ((compnp = metaname(&sp, argv[0], UNKNOWN, ep)) == NULL) { mde_perror(ep, ""); md_exit(sp, 1); } @@ -290,26 +266,18 @@ if (argc != 2) usage(sp, 1); - if ((oldnp = metaname(&sp, argv[0], ep)) == NULL) { - mde_perror(ep, ""); - md_exit(sp, 1); - } - if ((newnp = metaname(&sp, argv[1], ep)) == NULL) { + if ((oldnp = metaname(&sp, argv[0], UNKNOWN, ep)) == NULL) { mde_perror(ep, ""); md_exit(sp, 1); } - if (cflag) { /* new replace stuff */ - if (meta_replace(sp, namep, oldnp, newnp, uname, - options, ep) != 0) { - mde_perror(ep, ""); - md_exit(sp, 1); - } - } else { - if (meta_replace_byname(sp, namep, oldnp, newnp, - options, ep) != 0) { - mde_perror(ep, ""); - md_exit(sp, 1); - } + if ((newnp = metaname(&sp, argv[1], UNKNOWN, ep)) == NULL) { + mde_perror(ep, ""); + md_exit(sp, 1); + } + if (meta_replace_byname(sp, namep, oldnp, newnp, + options, ep) != 0) { + mde_perror(ep, ""); + md_exit(sp, 1); } }
--- a/usr/src/cmd/lvm/util/metaroot.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/cmd/lvm/util/metaroot.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 1992-2003 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -251,7 +250,7 @@ mde_perror(ep, ""); return (METAROOT_ERR); } - if ((rootnp = metaname(&sp, curroot, ep)) == NULL) { + if ((rootnp = metaname(&sp, curroot, UNKNOWN, ep)) == NULL) { mde_perror(ep, ""); return (METAROOT_ERR); } @@ -412,7 +411,7 @@ } /* get device name */ - if ((rootnp = metaname(&sp, argv[0], ep)) == NULL) { + if ((rootnp = metaname(&sp, argv[0], UNKNOWN, ep)) == NULL) { mde_perror(ep, ""); md_exit(sp, 1); } @@ -425,7 +424,7 @@ * mounted as happens if this command is part of the install * process, currootnp will be set to NULL. */ - currootnp = metaname(&sp, curroot, ep); + currootnp = metaname(&sp, curroot, UNKNOWN, ep); /* * If the argument is the name of the current root filesystem, then * the command is allowed, otherwise check that the argument is
--- a/usr/src/cmd/lvm/util/metastat.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/cmd/lvm/util/metastat.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -110,7 +109,7 @@ options |= PRINT_SUBDEVS; /* hotspare pool */ - if (is_hspname(uname)) { + if (is_existing_hsp(*spp, uname)) { mdhspname_t *hspnamep; /* get hotsparepool */ @@ -128,7 +127,7 @@ } /* get metadevice */ - if (((namep = metaname(spp, uname, ep)) == NULL) || + if (((namep = metaname(spp, uname, META_DEVICE, ep)) == NULL) || (metachkmeta(namep, ep) != 0)) return (-1); @@ -162,20 +161,20 @@ ) { int rval = -1; + char *cname = NULL; char *cp = NULL; md_gs_stat_parm_t gsp; - /* create local set, if necessary */ - if (*spp == NULL) { - if (fname != NULL && (cp = strchr(fname, '/')) != NULL) - *cp = '\0'; - if (fname != NULL && (*spp = metasetname(fname, ep)) != NULL) { - *cp = '/'; - } else { - if ((*spp = metasetname(MD_LOCAL_NAME, ep)) == NULL) - return (rval); + if (fname != NULL && strchr(fname, '/') != NULL) { + /* get the canonical name */ + cname = meta_name_getname(spp, fname, META_DEVICE, ep); + if (cname == NULL) { + mde_perror(ep, ""); + mdclrerror(ep); + return (-1); } + Free(cname); } if ((cp = getenv("MD_DEBUG")) == NULL) @@ -264,7 +263,7 @@ ) { (void) fprintf(stderr, gettext("\ -usage: %s [-s setname] [-a][-c][-B][-r][-i][-p] [-t] [metadevice...]\n"), +usage: %s [-s setname] [-a][-c][-B][-D][-r][-i][-p] [-t] [metadevice...]\n"), myname); md_exit(sp, eval); } @@ -278,7 +277,7 @@ char *argv[] ) { - char *sname = NULL; + char *sname = MD_LOCAL_NAME; mdsetname_t *sp = NULL; mdprtopts_t options = PRINT_HEADER | PRINT_DEVID | PRINT_FAST; int c; @@ -288,6 +287,7 @@ int eval = 0; int inquire = 0; int quiet_flg = 0; + int set_flg = 0; int error; int all_sets_flag = 0; int concise_flag = 0; @@ -324,7 +324,7 @@ /* parse arguments */ optind = 1; opterr = 1; - while ((c = getopt(argc, argv, "acSs:hpBrtiq?")) != -1) { + while ((c = getopt(argc, argv, "acSs:hpBDrtiq?")) != -1) { switch (c) { case 'a': all_sets_flag++; @@ -341,6 +341,7 @@ case 's': sname = optarg; + set_flg++; break; case 'h': @@ -363,6 +364,9 @@ case 'B': options |= PRINT_LARGEDEVICES; break; + case 'D': + options |= PRINT_FN; + break; case 'r': /* defunct option */ break; case 'q': @@ -380,23 +384,16 @@ argc -= optind; argv += optind; - if (sname != NULL) { - - if (all_sets_flag) { - fprintf(stderr, gettext("metastat: " - "incompatible options: -a and -s\n")); - usage(sp, 1); - } + if (all_sets_flag && set_flg) { + fprintf(stderr, gettext("metastat: " + "incompatible options: -a and -s\n")); + usage(sp, 1); + } - if ((sp = metasetname(sname, ep)) == NULL) { - mde_perror(ep, ""); - md_exit(sp, 1); - } - } else { - if ((sp = metasetname(MD_LOCAL_NAME, ep)) == NULL) { - mde_perror(ep, ""); - md_exit(sp, 1); - } + /* get set context */ + if ((sp = metasetname(sname, ep)) == NULL) { + mde_perror(ep, ""); + md_exit(sp, 1); } /* make sure that the mddb is not stale. Else print a warning */ @@ -453,26 +450,39 @@ /* print named device types */ while (devcnt < argc) { char *uname = argv[devcnt]; + char *cname = NULL; + + /* get the canonical name */ + cname = meta_name_getname(&sp, uname, META_DEVICE, ep); + if (cname == NULL) { + /* already printed the error */ + mdclrerror(ep); + eval = 1; + ++devcnt; + continue; + } if (concise_flag) { mdname_t *np; - np = metaname(&sp, uname, ep); + np = metaname(&sp, cname, META_DEVICE, ep); if (np == NULL) { mde_perror(ep, ""); mdclrerror(ep); + eval = 1; } else { print_concise_md(0, sp, np); } } else { - if (print_name(&sp, uname, &nlistp, NULL, stdout, options, + if (print_name(&sp, cname, &nlistp, NULL, stdout, options, &meta_print_trans_msg, &lognlp, ep) != 0) { mde_perror(ep, ""); mdclrerror(ep); eval = 1; } } + Free(cname); ++devcnt; } @@ -482,14 +492,24 @@ while (devcnt < argc) { char *uname = argv[devcnt]; + char *cname = NULL; + + /* get the canonical name */ + cname = meta_name_getname(&sp, uname, META_DEVICE, ep); + if (cname == NULL) { + mde_perror(ep, ""); + mdclrerror(ep); + ++devcnt; + continue; + } /* hotspare pools */ - if (is_hspname(uname)) { + if (is_existing_hsp(sp, cname)) { mdhspname_t *hspnamep; md_hsp_t *hsp; /* get hotsparepool */ - if ((hspnamep = metahspname(&sp, uname, + if ((hspnamep = metahspname(&sp, cname, ep)) == NULL) eval = 1; @@ -504,7 +524,8 @@ namep = hsp->hotspares. hotspares_val[hsi].hsnamep; - if (!(options & PRINT_LARGEDEVICES)) { + if (!(options & + (PRINT_LARGEDEVICES | PRINT_FN))) { /* meta_getdevs populates the */ /* nlistp structure for use */ if (meta_getdevs(sp, namep, @@ -517,12 +538,13 @@ } else { /* get metadevice */ - if (((namep = metaname(&sp, uname, - ep)) == NULL) || + if (((namep = metaname(&sp, cname, + META_DEVICE, ep)) == NULL) || (metachkmeta(namep, ep) != 0)) eval = 1; - if (!(options & PRINT_LARGEDEVICES)) { + if (!(options & + (PRINT_LARGEDEVICES | PRINT_FN))) { /* meta_getdevs populates the */ /* nlistp structure for use */ if (meta_getdevs(sp, namep, &nlistp, ep) @@ -530,7 +552,7 @@ eval = 1; } } - + Free(cname); ++devcnt; } if (print_devid(sp, nlistp, stdout, ep) != 0) @@ -602,12 +624,6 @@ md_error_t *ep = &status; int meta_print_trans_msg = 0; - /* default to local set */ - if ((sp == NULL) && ((sp = metasetname(MD_LOCAL_NAME, ep)) == NULL)) { - mde_perror(ep, ""); - md_exit(sp, 1); - } - /* check for ownership */ assert(sp != NULL); if (meta_check_ownership(sp, ep) != 0) { @@ -638,7 +654,7 @@ * upgrade. Even if meta_getalldevs fails, the * data in nlistp is still valid. */ - if (!(options & PRINT_LARGEDEVICES)) { + if (!(options & (PRINT_LARGEDEVICES | PRINT_FN))) { (void) meta_getalldevs(sp, &nlistp, 0, ep); } if (nlistp != NULL) { @@ -1164,7 +1180,7 @@ md_sp_t *soft_part; mdnamelist_t *tnlp; - mdn = metaname(&sp, nlp->namep->cname, &error); + mdn = metaname(&sp, nlp->namep->cname, META_DEVICE, &error); mdclrerror(&error); if (mdn == NULL) { print_concise_entry(0, nlp->namep->cname, 0, 'p'); @@ -1195,7 +1211,9 @@ for (tnlp = nlp->next; tnlp != NULL; tnlp = tnlp->next) { md_sp_t *part; - mdn = metaname(&sp, tnlp->namep->cname, &error); + mdn = metaname(&sp, tnlp->namep->cname, + META_DEVICE, &error); + mdclrerror(&error); if (mdn == NULL) continue; @@ -1287,7 +1305,7 @@ mdname_t *mdn; md_common_t *u; - mdn = metaname(&sp, nlp->namep->cname, &error); + mdn = metaname(&sp, nlp->namep->cname, META_DEVICE, &error); mdclrerror(&error); if (mdn == NULL) { print_concise_entry(0, nlp->namep->cname, 0, mtype); @@ -1672,7 +1690,7 @@ if (mirror_status & MD_UN_RESYNC_ACTIVE) { - if (mirror->common.revision == MD_64BIT_META_DEV) { + if (mirror->common.revision & MD_64BIT_META_DEV) { (void) snprintf(buf, sizeof (buf), gettext("resync-%2d.%1d%%"), mirror->percent_done / 10,
--- a/usr/src/cmd/lvm/util/metasync.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/cmd/lvm/util/metasync.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -236,7 +235,7 @@ int result; /* get device */ - if ((np = metaname(&sp, argv[0], ep)) == NULL) { + if ((np = metaname(&sp, argv[0], META_DEVICE, ep)) == NULL) { mde_perror(ep, ""); rval = -1; continue;
--- a/usr/src/cmd/lvm/util/metattach.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/cmd/lvm/util/metattach.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -163,7 +162,8 @@ usage(*spp, 1); /* get list of components */ - if (metanamelist(spp, &compnlp, argc, argv, ep) < 0) + if (metanamelist(spp, &compnlp, argc, argv, + UNKNOWN, ep) < 0) return (-1); assert(compnlp != NULL); for (p = compnlp; (p != NULL); p = p->next) { @@ -256,7 +256,8 @@ usage(*spp, 1); /* get list of components */ - if (metanamelist(spp, &compnlp, argc, argv, ep) < 0) + if (metanamelist(spp, &compnlp, argc, argv, + UNKNOWN, ep) < 0) return (-1); assert(compnlp != NULL); for (p = compnlp; (p != NULL); p = p->next) { @@ -318,7 +319,8 @@ /* get submirror */ if (argc == 1) { - if (((submirnp = metaname(spp, argv[0], ep)) == NULL) || + if (((submirnp = metaname(spp, argv[0], META_DEVICE, + ep)) == NULL) || (metachkmeta(submirnp, ep) != 0)) { return (-1); } @@ -427,7 +429,7 @@ } } - if (((np = metaname(&sp, argv[optind], ep)) == NULL) || + if (((np = metaname(&sp, argv[optind], META_DEVICE, ep)) == NULL) || (metachkmeta(np, ep) != 0)) { mde_perror(ep, ""); md_exit(sp, 1);
--- a/usr/src/cmd/rcm_daemon/common/svm_rcm.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/cmd/rcm_daemon/common/svm_rcm.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -72,6 +71,7 @@ */ #define MSG_UNRECOGNIZED gettext("SVM: \"%s\" is not a SVM resource") #define MSG_NODEPS gettext("SVM: can't find dependents") +#define MSG_NORECACHE gettext("SVM: WARNING: couldn't re-cache.") #define MSG_OPENERR gettext("SVM: can't open \"%s\"") #define MSG_CACHEFAIL gettext("SVM: can't malloc cache") @@ -120,7 +120,8 @@ struct deventry *next; /* next entry with same hash */ svm_type_t devtype; /* device type */ dev_t devkey; /* key */ - char *devname; /* name */ + char *devname; /* name in /dev */ + char *devicesname; /* name in /devices */ struct deventry *dependent; /* 1st dependent */ struct deventry *next_dep; /* next dependent */ struct deventry *antecedent; /* antecedent */ @@ -157,6 +158,7 @@ static int svm_register(rcm_handle_t *hd); static int svm_unregister(rcm_handle_t *hd); +static int svm_unregister_device(rcm_handle_t *hd, deventry_t *d); static deventry_t *cache_dependent(cache_t *cache, char *devname, int devflags, deventry_t *dependents); static deventry_t *cache_device(cache_t *cache, char *devname, @@ -185,7 +187,7 @@ static void free_cache(cache_t **cache); static void free_deventry(deventry_t **deventry); static uint32_t hash(uint32_t h, char *s); -static void register_device(rcm_handle_t *hd, char *devname); +static void svm_register_device(rcm_handle_t *hd, char *devname); static int add_dep(int *ndeps, char ***depsp, deventry_t *deventry); static int get_dependents(deventry_t *deventry, char *** dependentsp); char *add_to_usage(char ** usagep, char *string); @@ -341,7 +343,7 @@ /* If not, register the whole cache and mark it as registered. */ while ((devicename = cache_walk(svm_cache, &i, &l)) != NULL) { - register_device(hd, devicename); + svm_register_device(hd, devicename); } svm_cache->registered = 1; @@ -369,7 +371,6 @@ { deventry_t *l = NULL; uint32_t i = 0; - char *devicename; rcm_log_message(RCM_TRACE1, "SVM: unregister\n"); /* Guard against bad arguments */ @@ -378,8 +379,8 @@ /* Walk the cache, unregistering everything */ (void) mutex_lock(&svm_cache_lock); if (svm_cache != NULL) { - while ((devicename = cache_walk(svm_cache, &i, &l)) != NULL) { - (void) rcm_unregister_interest(hd, devicename, 0); + while (cache_walk(svm_cache, &i, &l) != NULL) { + (void) svm_unregister_device(hd, l); } svm_cache->registered = 0; } @@ -1599,7 +1600,8 @@ mdname_t *mdn; md_trans_t *trans; - mdn = metaname(&sp, nlp->namep->cname, &error); + mdn = metaname(&sp, nlp->namep->cname, META_DEVICE, + &error); if (mdn == NULL) { continue; } @@ -1622,7 +1624,8 @@ mdname_t *mdn; md_mirror_t *mirror; - mdn = metaname(&sp, nlp->namep->cname, &error); + mdn = metaname(&sp, nlp->namep->cname, META_DEVICE, + &error); if (mdn == NULL) { continue; } @@ -1645,7 +1648,8 @@ mdname_t *mdn; md_raid_t *raid; - mdn = metaname(&sp, nlp->namep->cname, &error); + mdn = metaname(&sp, nlp->namep->cname, META_DEVICE, + &error); if (mdn == NULL) { continue; } @@ -1668,7 +1672,8 @@ mdname_t *mdn; md_stripe_t *stripe; - mdn = metaname(&sp, nlp->namep->cname, &error); + mdn = metaname(&sp, nlp->namep->cname, META_DEVICE, + &error); if (mdn == NULL) { continue; } @@ -1691,7 +1696,8 @@ mdname_t *mdn; md_sp_t *soft_part; - mdn = metaname(&sp, nlp->namep->cname, &error); + mdn = metaname(&sp, nlp->namep->cname, META_DEVICE, + &error); if (mdn == NULL) { continue; } @@ -1844,14 +1850,16 @@ create_deventry(char *devname, svm_type_t devtype, md_dev64_t devkey, int devflags) { - deventry_t *newdeventry; - char *newdevname; + const char *devprefix = "/dev/"; + deventry_t *newdeventry = NULL; + char *newdevname = NULL; + char *devicesname = NULL; newdeventry = (deventry_t *)malloc(sizeof (*newdeventry)); if (newdeventry == NULL) { rcm_log_message(RCM_ERROR, gettext("SVM: can't malloc deventrys")); - return (NULL); + goto errout; } (void) memset((char *)newdeventry, 0, sizeof (*newdeventry)); @@ -1859,16 +1867,55 @@ if (newdevname == NULL) { rcm_log_message(RCM_ERROR, gettext("SVM: can't malloc devname")); - free(newdeventry); - return (NULL); + goto errout; + } + + /* + * When we register interest in a name starting with /dev/, RCM + * will use realpath to convert the name to a /devices name before + * storing it. metaclear removes both the /dev and the /devices + * form of the name of a metadevice from the file system. Thus, + * when we later call rcm_unregister_interest to get rid of a + * metacleared device, RCM will not be able to derive the /devices + * name for the /dev name. Thus, to unregister we will need to use + * the /devices name. We will save it now, so that we have it when + * it comes time to unregister. + */ + if (strncmp(devname, devprefix, strlen(devprefix)) == 0) { + devicesname = (char *)malloc(PATH_MAX); + if (devicesname == NULL) { + rcm_log_message(RCM_ERROR, + gettext("SVM: can't malloc PATH_MAX bytes")); + goto errout; + } + if (realpath(devname, devicesname) == NULL) { + free(devicesname); + devicesname = NULL; + } } newdeventry->devname = newdevname; + newdeventry->devicesname = devicesname; newdeventry->devtype = devtype; newdeventry->devkey = meta_cmpldev(devkey); newdeventry->flags = devflags; - rcm_log_message(RCM_TRACE1, - "SVM created deventry for %s\n", newdeventry->devname); + if (newdeventry->devicesname == NULL) { + rcm_log_message(RCM_TRACE1, + "SVM created deventry for %s\n", newdeventry->devname); + } else { + rcm_log_message(RCM_TRACE1, + "SVM created deventry for %s (%s)\n", + newdeventry->devname, newdeventry->devicesname); + } return (newdeventry); + +errout: + if (devicesname != NULL) + free(devicesname); + if (newdevname != NULL) + free(newdevname); + if (newdeventry != NULL) + free(newdeventry); + return (NULL); } /* @@ -1991,7 +2038,40 @@ /* * cache_sync() * - * Resync cache with the svm database + * Resync cache with the svm database. First a new cache is created + * that represents the current state of the SVM database. The + * function walks the new cache to look for new entries that must be + * registered. The new entries are kept in a list, because we cannot + * register them at this point. Entries that appear in both caches + * are removed from the old cache. Because of this at the end of the + * walk, the old cache will only contain devices that have been + * removed and need to be unregistered. + * + * Next the old cache is walked, so that we can unregister the devices + * that are no longer present. + * + * Finally, we process the list of new devices that must be + * registered. There is a reason why we must unregister the removed + * (metacleared) devices before registering the new ones. It has to + * do with the fact that rcm_register_interest calls realpath(3C) to + * convert a /dev name to a /devices name. It uses the /devices name + * for storing the device information. + * + * It can happen that between cache_syncs that the administrator + * metaclears one metadevice and metacreates a new one. For example, + * + * metaclear acct + * metainit engr 1 1 c1t12d0s0 + * + * The metaclear operation frees up the minor number that was being + * used by acct. The metainit operation can then reuse the minor + * number. This means that both metadevices would have the same + * /devices name even though they had different /dev names. Since + * rcm_register_interest uses /devices names for storing records, we + * need to unregister acct before registering engr. Otherwise we + * would get an EALREADY errno and a failed registration. This is why + * cache_sync creates a list of devices to be registered after all the + * removed devices have been unregistered. * * Input: * rcm_handle_t *hd rcm handle @@ -2009,17 +2089,24 @@ cache_t *new_cache; cache_t *old_cache = *cachep; deventry_t *hashline = NULL; + deventry_t **register_list = NULL; + deventry_t *register_this; + uint32_t register_count = 0; /* # entrys in register_list */ + uint32_t allocated = 0; /* # entrys allocated in */ + /* register_list */ + uint32_t allocate_incr = 16; uint32_t i = 0; /* Get a new cache */ if ((new_cache = create_cache()) == NULL) { - rcm_log_message(RCM_WARNING, - gettext("SVM: WARNING: couldn't re-cache.")); + rcm_log_message(RCM_WARNING, MSG_NORECACHE); return; } /* For every entry in the new cache... */ while ((devicename = cache_walk(new_cache, &i, &hashline)) != NULL) { + register_this = NULL; + /* Look for this entry in the old cache */ deventry = cache_lookup(old_cache, devicename); /* @@ -2028,12 +2115,32 @@ * again and remove it from the old cache */ if (deventry == NULL) { - register_device(hd, hashline->devname); + register_this = hashline; } else { if (deventry->flags&REMOVED) - register_device(hd, hashline->devname); + register_this = hashline; cache_remove(old_cache, deventry); } + + /* Save this entry if we need to register it later. */ + if (register_this) { + if (register_count >= allocated) { + /* Need to extend our array */ + allocated += allocate_incr; + register_list = + (deventry_t **)realloc(register_list, + allocated * sizeof (*register_list)); + if (register_list == NULL) { + /* Out of memory. Give up. */ + rcm_log_message(RCM_WARNING, + MSG_NORECACHE); + free(new_cache); + return; + } + } + *(register_list + register_count) = register_this; + register_count++; + } } /* @@ -2044,10 +2151,18 @@ hashline = NULL; while ((devicename = cache_walk(old_cache, &i, &hashline)) != NULL) { if (!(hashline->flags&REMOVED)) { - (void) rcm_unregister_interest(hd, devicename, 0); + (void) svm_unregister_device(hd, hashline); } } + /* Register the new devices. */ + for (i = 0; i < register_count; i++) { + deventry = *(register_list + i); + svm_register_device(hd, deventry->devname); + } + if (register_list) + free(register_list); + /* Swap pointers */ *cachep = new_cache; @@ -2204,6 +2319,8 @@ free(oldhspentry); } } + if ((*deventry)->devicesname) + free((*deventry)->devicesname); free((*deventry)->devname); free (*deventry); *deventry = olddeventry; @@ -2240,7 +2357,7 @@ } /* - * register_device() + * svm_register_device() * * Register a device * @@ -2251,7 +2368,7 @@ * Locking: None */ static void -register_device(rcm_handle_t *hd, char *devname) +svm_register_device(rcm_handle_t *hd, char *devname) { /* Sanity check */ if (devname == NULL) @@ -2840,7 +2957,6 @@ mdsetname_t *sp; md_error_t error = mdnullerror; char sname[BUFSIZ+1]; - uint32_t d; mdname_t *np; deventry_t *dependent; int rval = NOTREDUNDANT; @@ -2871,10 +2987,10 @@ * it contains a setname. */ ret = sscanf(dependent->devname, - "/dev/md/%" VAL2STR(BUFSIZ) "[^/]/dsk/d%u", - sname, &d); + "/dev/md/%" VAL2STR(BUFSIZ) "[^/]/dsk/", + sname); - if (ret != 2) + if (ret != 1) (void) strcpy(sname, MD_LOCAL_NAME); if ((sp = metasetname(sname, &error)) == NULL) { @@ -2887,7 +3003,7 @@ rcm_log_message(RCM_TRACE1, "SVM: processing: %s\n", dependent->devname); - np = metaname(&sp, dependent->devname, &error); + np = metaname(&sp, dependent->devname, META_DEVICE, &error); switch (dependent->devtype) { case SVM_TRANS: @@ -2943,3 +3059,66 @@ rcm_log_message(RCM_TRACE1, "SVM: check_device return %d\n", rval); return (rval); } + +/* + * svm_unregister_device + * + * Unregister the device specified by the deventry + * + * Input: + * rcm_handle_t * information for RCM + * deventry_t * description of the device to be + * unregistered + * + * Return: + * int 0 - successfully unregistered + * != 0 - failed to unregister + * + * Locking: + * None + * + * If the deventry_t has a devicesname, we will first attempt to unregister + * using that name. If that fails then we'll attempt to unregister using + * devname. The reason for this strategy has to do with the way that + * rcm_register_interest works. If passed a /dev/ name, + * rcm_register_interest uses realpath() to convert it to a /devices name. + * Thus, we are more likely to succeed if we use devicesname first. + */ + +static int +svm_unregister_device(rcm_handle_t *hd, deventry_t *d) +{ + int deleted; + + if (d->devicesname) { + rcm_log_message(RCM_TRACE1, "SVM: unregister_device %s (%s)\n", + d->devname, d->devicesname); + } else { + rcm_log_message(RCM_TRACE1, "SVM: unregister_device %s\n", + d->devname); + } + deleted = -1; + if (d->devicesname != NULL) { + /* + * Try to unregister via the /devices entry first. RCM + * converts /dev/ entries to /devices entries before + * storing them. Thus, if this item has a /devices name + * available, we should use it for unregistering. + */ + deleted = rcm_unregister_interest(hd, + d->devicesname, 0); + } + if (deleted != 0) { + /* + * Either we did not have a /devices name or the attempt to + * unregister using the /devices name failed. Either way + * we'll now try to unregister using the conventional name. + */ + deleted = rcm_unregister_interest(hd, d->devname, 0); + } + if (deleted != 0) { + rcm_log_message(RCM_TRACE1, "SVM: unregister_device failed " + "for %s\n", d->devname); + } + return (deleted); +}
--- a/usr/src/head/meta.h Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/head/meta.h Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -154,6 +153,7 @@ #define PRINT_FAST 0x00000080 #define PRINT_DEVID 0x00000100 #define PRINT_LARGEDEVICES 0x00000200 +#define PRINT_FN 0x00000400 /* * for meta_devadm options @@ -218,7 +218,6 @@ #define MDCMD_INIT 0x0010 /* init operation */ #define MDCMD_UPDATE 0x0020 /* update sizes used w/o DOIT mostly */ #define MDCMD_NOLOCK 0x0040 /* lock already held, DONT acquire */ -#define MDCMD_CLUSTER_REPLACE 0x0080 /* don't resync raid */ #define MDCMD_VERBOSE 0x0100 /* be verbose */ #define MDCMD_USE_WHOLE_DISK 0x0200 /* repartition disk */ #define MDCMD_DIRECT 0x0400 /* extents specified directly */ @@ -775,8 +774,8 @@ extern int meta_adjust_geom(md_unit_t *md, mdname_t *np, uint_t write_reinstruct, uint_t read_reinstruct, uint_t round_cyl, md_error_t *ep); -extern int meta_init_name(mdsetname_t **spp, - int argc, char *argv[], mdcmdopts_t options, +extern int meta_init_name(mdsetname_t **spp, int argc, + char *argv[], char *cname, mdcmdopts_t options, md_error_t *ep); extern int meta_check_devicesize(diskaddr_t total_blocks); extern int meta_init_make_device(mdsetname_t **spp, char *uname, @@ -1103,9 +1102,16 @@ /* meta_name.c */ extern char *meta_name_getname(mdsetname_t **spp, char *uname, - md_error_t *ep); + meta_device_type_t uname_type, md_error_t *ep); extern char *meta_canonicalize(mdsetname_t *sp, char *uname); +extern char *meta_canonicalize_check_set(mdsetname_t **sp, + char *uname, md_error_t *ep); +extern int meta_is_all(char *uname); +extern int is_existing_metadevice(mdsetname_t *sp, char *uname); +extern int is_existing_hsp(mdsetname_t *sp, char *uname); +extern int is_existing_meta_hsp(mdsetname_t *sp, char *uname); extern int is_metaname(char *uname); +extern int meta_is_none(char *uname); extern int is_hspname(char *uname); extern int parse_ctd(char *uname, uint_t *slice); extern md_set_desc *sr2setdesc(md_set_record *sr); @@ -1135,19 +1141,20 @@ extern int meta_getdev(mdsetname_t *sp, mdname_t *np, md_error_t *ep); extern mdname_t *metaname_fast(mdsetname_t **spp, char *uname, - md_error_t *ep); + meta_device_type_t uname_type, md_error_t *ep); extern mdname_t *metaname(mdsetname_t **spp, char *uname, - md_error_t *ep); + meta_device_type_t uname_type, md_error_t *ep); extern mdname_t *metamnumname(mdsetname_t **spp, minor_t mnum, int fast, md_error_t *ep); -extern char *get_mdname(minor_t mnum); +extern char *get_mdname(mdsetname_t *sp, minor_t mnum); extern int metaismeta(mdname_t *np); extern int metachkmeta(mdname_t *np, md_error_t *ep); extern int metachkdisk(mdname_t *np, md_error_t *ep); extern int metachkcomp(mdname_t *np, md_error_t *ep); extern void metafreenamelist(mdnamelist_t *nlp); extern int metanamelist(mdsetname_t **spp, mdnamelist_t **nlpp, - int argc, char *argv[], md_error_t *ep); + int argc, char *argv[], meta_device_type_t type, + md_error_t *ep); extern mdname_t *metanamelist_append(mdnamelist_t **nlpp, mdname_t *np); extern mdnamelist_t **meta_namelist_append_wrapper(mdnamelist_t **nlpp, @@ -1156,7 +1163,7 @@ char *uname, md_error_t *ep); extern mdhspname_t *metahsphspname(mdsetname_t **spp, hsp_t hsp, md_error_t *ep); -extern char *get_hspname(hsp_t mnum); +extern char *get_hspname(mdsetname_t *sp, hsp_t mnum); extern void metafreehspnamelist(mdhspnamelist_t *hspnlp); extern int metahspnamelist(mdsetname_t **spp, mdhspnamelist_t **hspnlpp, @@ -1168,6 +1175,7 @@ extern char *get_devname(set_t setno, md_dev64_t dev); extern mdname_t *metakeyname(mdsetname_t **spp, mdkey_t key, int fast, md_error_t *ep); +extern void metaflushmetanames(void); extern void metaflushnames(int flush_sr_cache); extern int meta_get_hotspare_names(mdsetname_t *sp, mdnamelist_t **nlpp, int options, md_error_t *ep); @@ -1213,6 +1221,10 @@ extern char *meta_getnmentbydev(set_t setno, side_t sideno, md_dev64_t dev, char **drvnm, minor_t *mnum, mdkey_t *key, md_error_t *ep); +extern char *meta_gethspnmentbyid(set_t setno, side_t sideno, + hsp_t hspid, md_error_t *ep); +extern hsp_t meta_gethspnmentbyname(set_t setno, side_t sideno, + char *hspname, md_error_t *ep); extern char *meta_getdidminorbykey(set_t setno, side_t sideno, mdkey_t key, md_error_t *ep); extern ddi_devid_t meta_getdidbykey(set_t setno, side_t sideno, @@ -1230,6 +1242,10 @@ md_error_t *ep); extern int del_key_names(mdsetname_t *sp, mdnamelist_t *nlp, md_error_t *ep); +extern mdkey_t add_self_name(mdsetname_t *, char *, + md_mkdev_params_t *, md_error_t *); +extern int del_self_name(mdsetname_t *, mdkey_t, + md_error_t *); /* meta_patch.c */ extern int meta_patch_vfstab(char *cmpname, mdname_t *fsnp, @@ -1329,10 +1345,6 @@ uint_t *slicep, md_error_t *ep); /* meta_replace.c */ -extern int meta_replace(mdsetname_t *sp, mdname_t *metanp, - mdname_t *oldnp, - mdname_t *newnp, char *uname, mdcmdopts_t options, - md_error_t *ep); extern int meta_replace_byname(mdsetname_t *sp, mdname_t *namep, mdname_t *oldnp, mdname_t *newnp, mdcmdopts_t options, md_error_t *ep);
--- a/usr/src/lib/libdiskmgt/common/inuse_svm.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/lib/libdiskmgt/common/inuse_svm.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -87,7 +86,7 @@ static md_drive_desc *(*mdl_metaget_drivedesc)(mdsetname_t *sp, int flags, md_error_t *ep); static mdname_t *(*mdl_metaname)(mdsetname_t **spp, char *uname, - md_error_t *ep); + meta_device_type_t uname_type, md_error_t *ep); static int (*mdl_metareplicalist)(mdsetname_t *sp, int flags, md_replicalist_t **rlpp, md_error_t *ep); static mdsetname_t *(*mdl_metasetnosetname)(set_t setno, md_error_t *ep); @@ -303,7 +302,8 @@ mdname_t *mdn; md_raid_t *raid; - mdn = (mdl_metaname)(&sp, nlp->namep->cname, &error); + mdn = (mdl_metaname)(&sp, nlp->namep->cname, + META_DEVICE, &error); (mdl_mdclrerror)(&error); if (mdn == NULL) { continue; @@ -336,7 +336,8 @@ mdname_t *mdn; md_stripe_t *stripe; - mdn = (mdl_metaname)(&sp, nlp->namep->cname, &error); + mdn = (mdl_metaname)(&sp, nlp->namep->cname, + META_DEVICE, &error); (mdl_mdclrerror)(&error); if (mdn == NULL) { continue; @@ -379,7 +380,8 @@ mdname_t *mdn; md_sp_t *soft_part; - mdn = (mdl_metaname)(&sp, nlp->namep->cname, &error); + mdn = (mdl_metaname)(&sp, nlp->namep->cname, + META_DEVICE, &error); (mdl_mdclrerror)(&error); if (mdn == NULL) { continue; @@ -539,8 +541,8 @@ mdl_metaget_drivedesc = (md_drive_desc *(*)(mdsetname_t *, int, md_error_t *))dlsym(lh, "metaget_drivedesc"); - mdl_metaname = (mdname_t *(*)(mdsetname_t **, char *, md_error_t *)) - dlsym(lh, "metaname"); + mdl_metaname = (mdname_t *(*)(mdsetname_t **, char *, + meta_device_type_t, md_error_t *))dlsym(lh, "metaname"); mdl_metareplicalist = (int (*)(mdsetname_t *, int, md_replicalist_t **, md_error_t *))dlsym(lh, "metareplicalist"); @@ -650,7 +652,7 @@ mdname_t *mdn; md_error_t error = *mdl_mdnullerror; - mdn = (mdl_metaname)(&sp, sname, &error); + mdn = (mdl_metaname)(&sp, sname, UNKNOWN, &error); if (!mdisok(&error)) { (mdl_mdclrerror)(&error); return (0);
--- a/usr/src/lib/lvm/libmeta/common/meta_attach.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/lib/lvm/libmeta/common/meta_attach.c Tue Mar 14 14:53:36 2006 -0800 @@ -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. @@ -21,13 +20,12 @@ */ /* - * Copyright 1992-2002 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" - /* * attach operations */ @@ -58,7 +56,7 @@ /* grow device */ (void) memset(&mgp, 0, sizeof (mgp)); - if (big_or_little == MD_64BIT_META_DEV) + if (big_or_little & MD_64BIT_META_DEV) mgp.options = MD_CRO_64BIT; else mgp.options = MD_CRO_32BIT;
--- a/usr/src/lib/lvm/libmeta/common/meta_check.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/lib/lvm/libmeta/common/meta_check.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -152,7 +151,7 @@ mdname_t *snp; if ((snp = metaname(&sp, swtp->swt_ent[i].ste_path, - ep)) == NULL) { + UNKNOWN, ep)) == NULL) { mdclrerror(ep); continue; } @@ -201,7 +200,7 @@ mdname_t *snp; if ((snp = metaname(&sp, swtp->swt_ent[i].ste_path, - ep)) == NULL) { + LOGICAL_DEVICE, ep)) == NULL) { mdclrerror(ep); continue; } @@ -238,7 +237,7 @@ if (ioctl(dump_fd, DIOCGETDEV, device) != -1) { mdname_t *dump_np; - if ((dump_np = metaname(&sp, device, ep)) == NULL) { + if ((dump_np = metaname(&sp, device, UNKNOWN, ep)) == NULL) { mdclrerror(ep); (void) close(dump_fd); return (0); @@ -306,7 +305,7 @@ (void) strcpy(mountp, m.mnt_mountp); (void) strcpy(mnt_special, m.mnt_special); - if ((mnp = metaname(&sp, mnt_special, ep)) == NULL) { + if ((mnp = metaname(&sp, mnt_special, UNKNOWN, ep)) == NULL) { mdclrerror(ep); continue; } @@ -372,7 +371,8 @@ (void) strcpy(mountp, m.mnt_mountp); (void) strcpy(mnt_special, m.mnt_special); - if ((mnp = metaname(&sp, mnt_special, ep)) == NULL) { + if ((mnp = metaname(&sp, mnt_special, + LOGICAL_DEVICE, ep)) == NULL) { mdclrerror(ep); continue; } @@ -525,15 +525,12 @@ * * Case 1 - The filenames are identical * - * Case 2 - Either name is a metadevice name. If so then they - * are not the same drive. - * - * Case 3 - Both devices have a devid + * Case 2 - Both devices have a devid * get and compare the devids for the devices. If both * devices have a devid then the compare will is all * that is needed we are done. * - * Case 4 - One or more devices does not have a devid + * Case 3 - One or more devices does not have a devid * start by doing a simple compare of the name, if they * are the same just return. *
--- a/usr/src/lib/lvm/libmeta/common/meta_db.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/lib/lvm/libmeta/common/meta_db.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -2076,13 +2075,15 @@ /* get device name */ devname = splicename(&c->c_devname); if (flags & PRINT_FAST) { - if ((rp->r_namep = metaname_fast(&sp, devname, ep)) == NULL) { + if ((rp->r_namep = metaname_fast(&sp, devname, + LOGICAL_DEVICE, ep)) == NULL) { Free(devname); Free(rp); return (NULL); } } else { - if ((rp->r_namep = metaname(&sp, devname, ep)) == NULL) { + if ((rp->r_namep = metaname(&sp, devname, + LOGICAL_DEVICE, ep)) == NULL) { Free(devname); Free(rp); return (NULL);
--- a/usr/src/lib/lvm/libmeta/common/meta_error.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/lib/lvm/libmeta/common/meta_error.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -71,10 +70,10 @@ char *name; /* get name, or fake it */ - if ((name = get_mdname(mnum)) == NULL) { + if ((name = get_mdname(NULL, mnum)) == NULL) { char buf[40]; - (void) sprintf(buf, "%lu/d%lu", MD_MIN2SET(mnum), + (void) sprintf(buf, "%lu/%lu", MD_MIN2SET(mnum), MD_MIN2UNIT(mnum)); return (Strdup(buf)); } @@ -109,10 +108,10 @@ { char *name; - if ((name = get_hspname(hsp)) == NULL) { + if ((name = get_hspname(NULL, hsp)) == NULL) { char buf[40]; - (void) sprintf(buf, "%u/hsp%03u", HSP_SET(hsp), HSP_ID(hsp)); + (void) sprintf(buf, "%u/%u", HSP_SET(hsp), HSP_ID(hsp)); return (Strdup(buf)); } return (Strdup(name)); @@ -878,6 +877,18 @@ (void) snprintf(p, psize, dgettext(TEXT_DOMAIN, "service(s) not online in SMF")); break; + case MDE_AMBIGUOUS_DEV: + (void) snprintf(p, psize, dgettext(TEXT_DOMAIN, + "Specify complete path to avoid ambiguity.")); + break; + case MDE_NAME_IN_USE: + (void) snprintf(p, psize, dgettext(TEXT_DOMAIN, + "Name already in use for metadevice or hot spare pool.")); + break; + case MDE_NAME_ILLEGAL: + (void) snprintf(p, psize, dgettext(TEXT_DOMAIN, + "Invalid name for metadevice or hot spare pool.")); + break; case MDE_ZONE_ADMIN: (void) snprintf(p, psize, dgettext(TEXT_DOMAIN, "Volume administration unavailable within non-global zones."));
--- a/usr/src/lib/lvm/libmeta/common/meta_getdevs.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/lib/lvm/libmeta/common/meta_getdevs.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -129,6 +128,10 @@ /* must have local set */ assert(sp != NULL); + /* if no valid name then return an error */ + if (namep == NULL) + return (-1); + /* just add regular devices */ if (! metaismeta(namep)) { mdnamelist_t *p;
--- a/usr/src/lib/lvm/libmeta/common/meta_hotspares.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/lib/lvm/libmeta/common/meta_hotspares.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -42,7 +41,6 @@ #include <sys/lvm/md_hotspares.h> #include <sys/lvm/md_convert.h> - /* * FUNCTION: meta_get_hsp_names() * INPUT: sp - the set name to get hotspares from @@ -137,7 +135,7 @@ /* should have a set */ assert(sp != NULL); - assert(sp->setno == HSP_SET(hspnp->hsp)); + assert(hspnp->hsp == MD_HSP_NONE || sp->setno == HSP_SET(hspnp->hsp)); /* get size of unit structure */ (void) memset(&mig, 0, sizeof (mig)); @@ -191,7 +189,7 @@ /* must have set */ assert(sp != NULL); - assert(sp->setno == HSP_SET(hspnp->hsp)); + assert(hspnp->hsp == MD_HSP_NONE || sp->setno == HSP_SET(hspnp->hsp)); /* short circuit */ if (hspnp->unitp != NULL) @@ -285,7 +283,7 @@ /* should be in the same set */ assert(sp != NULL); - assert(sp->setno == HSP_SET(hspnp->hsp)); + assert(hspnp->hsp == MD_HSP_NONE || sp->setno == HSP_SET(hspnp->hsp)); /* get unit */ if ((hspp = meta_get_hsp(sp, hspnp, ep)) == NULL) @@ -482,11 +480,12 @@ mdname_t *didnp = NULL; uint_t len; int large_hs_dev_cnt = 0; + int fn_hs_dev_cnt = 0; if (options & PRINT_LARGEDEVICES) { for (hsi = 0; (hsi < hspp->hotspares.hotspares_len); ++hsi) { md_hs_t *hsp = &hspp->hotspares.hotspares_val[hsi]; - if (hsp->revision == MD_64BIT_META_DEV) { + if (hsp->revision & MD_64BIT_META_DEV) { large_hs_dev_cnt += 1; if (meta_getdevs(sp, hsp->hsnamep, nlpp, ep) != 0) @@ -499,6 +498,21 @@ goto out; } } + + if (options & PRINT_FN) { + if (!HSP_ID_IS_FN(hspp->hspnamep->hsp)) { + rval = 0; + goto out; + } + for (hsi = 0; (hsi < hspp->hotspares.hotspares_len); ++hsi) { + md_hs_t *hsp = &hspp->hotspares.hotspares_val[hsi]; + fn_hs_dev_cnt += 1; + if (meta_getdevs(sp, hsp->hsnamep, nlpp, ep) + != 0) + goto out; + } + } + /* print header */ if (hspp->hotspares.hotspares_len == 0) { if (fprintf(fp, dgettext(TEXT_DOMAIN, "%s: is empty\n"), @@ -597,7 +611,7 @@ } if (options & PRINT_LARGEDEVICES) { - if (hsp->revision != MD_64BIT_META_DEV) + if ((hsp->revision & MD_64BIT_META_DEV) == 0) continue; } /* determine if devid does NOT exist */ @@ -668,7 +682,8 @@ /* should have same set */ assert(sp != NULL); - assert((hspnp == NULL) || (sp->setno == HSP_SET(hspnp->hsp))); + assert(hspnp == NULL || hspnp->hsp == MD_HSP_NONE || + sp->setno == HSP_SET(hspnp->hsp)); /* print all hsps */ if (hspnp == NULL) { @@ -743,6 +758,309 @@ } /* + * FUNCTION: del_hsp_name_mn_sides() + * INPUT: sp - set name + * curside - side of this node + * key - key of records to delete + * OUTPUT: ep - error information + * RETURNS: none. + * PURPOSE: There are name records for each side in a set. This + * function deletes the records associated with the specified + * key for all sides except curside. This function is used + * when the set is a multinode set. + */ +static void +del_hsp_name_mn_sides( + mdsetname_t *sp, + md_set_desc *sd, + side_t curside, + mdkey_t key, + md_error_t *ep +) +{ + md_error_t first_error = MDNULLERROR; + int error_seen = FALSE; + md_mnnode_desc *nd; + + for (nd = sd->sd_nodelist; nd; nd = nd->nd_next) { + if (nd->nd_nodeid == curside) + continue; + if (del_name(sp, nd->nd_nodeid, key, &first_error) == -1) { + if (error_seen == FALSE) { + error_seen = TRUE; + (void) mdstealerror(ep, &first_error); + } + } + } +} + +/* + * FUNCTION: del_hsp_name_trad_sides() + * INPUT: sp - set name + * curside - side of this node + * key - key of records to delete + * OUTPUT: ep - error information + * RETURNS: none. + * PURPOSE: There are name records for each side in a set. This + * function deletes the records associated with the specified + * key for all sides except curside. This function is used + * when the set is a traditional set. + */ +static void +del_hsp_name_trad_sides( + mdsetname_t *sp, + md_set_desc *sd, + side_t curside, + mdkey_t key, + md_error_t *ep +) +{ + int error_seen = FALSE; + md_error_t first_error = MDNULLERROR; + int i; + + for (i = 0; i < MD_MAXSIDES; i++) { + if (i == curside) + continue; + if (sd->sd_nodes[i][0] != '\0') { + if (del_name(sp, i, key, &first_error) == -1) { + if (error_seen == FALSE) { + error_seen = TRUE; + (void) mdstealerror(ep, &first_error); + } + } + } + } +} + +/* + * FUNCTION: del_hsp_keys() + * INPUT: sp - set name + * hspid - ID of records to delete + * OUTPUT: ep - error information + * RETURNS: 0 - success + * -1 - error + * PURPOSE: Remove the NM records associated with hspid from all sides + * of the set. Missing records are not considered to be an + * error. The key associated with the current side is removed + * last. + * + * This function is very similar to del_key_name(), except it + * does not require any device look up. This is because the + * hot spare pool is not a device. + */ +static int +del_hsp_keys(mdsetname_t *sp, hsp_t hspid, md_error_t *ep) +{ + md_error_t first_error = MDNULLERROR; + mdkey_t key = HSP_ID_TO_KEY(hspid); + md_set_desc *sd; + side_t thisside; /* Side # of this node. */ + + /* + * If there is no key, this means that the hot spare was created + * before the introduction of friendly names. Thus, the is no NM + * record and nothing for us to do in this function. + */ + if (key == MD_KEYBAD) + return (0); + + /* Find our current side */ + mdclrerror(ep); + thisside = getmyside(sp, ep); + if (! mdisok(ep)) + return (-1); + + /* + * If not the local set, we need to process the non-local sides + * first. + */ + if (!metaislocalset(sp)) { + if ((sd = metaget_setdesc(sp, ep)) == NULL) + return (-1); + if (MD_MNSET_DESC(sd)) { + /* Multinode set. Sides are in a linked list. */ + del_hsp_name_mn_sides(sp, sd, thisside, key, + &first_error); + } else { + /* Sides are in an array. */ + del_hsp_name_trad_sides(sp, sd, thisside, key, + &first_error); + } + } + + /* Now delete the name for the current side. */ + (void) del_name(sp, thisside, key, ep); + if (! mdisok(&first_error)) + (void) mdstealerror(ep, &first_error); + return (mdisok(ep) ? 0 : -1); +} + +/* + * FUNCTION: add_hsp_name_mn_sides() + * INPUT: sp - set name + * curside - side number for this node + * key - key to use for the name record + * hsp_name - name of the hot spare + * OUTPUT: ep - error information + * RETURNS: 0 indicates success, and -1 indicates failure. + * PURPOSE: Once the name record has been added for the current side, + * this function adds the record to the remaining sides. This + * function is to be used when the set is a multinode set. + * The side designated by curside will be ignored when adding + * records. + */ +static int +add_hsp_name_mn_sides( + mdsetname_t *sp, + md_set_desc *sd, + side_t curside, + mdkey_t key, + char *hsp_name, + md_error_t *ep +) +{ + md_mnnode_desc *nd; + + for (nd = sd->sd_nodelist; nd; nd = nd->nd_next) { + if (nd->nd_nodeid == curside) + continue; + if (add_name(sp, nd->nd_nodeid, key, MD_HOTSPARES, + minor(NODEV), hsp_name, ep) == -1) { + return (-1); + } + } + return (0); +} + +/* + * FUNCTION: add_hsp_name_trad_sides() + * INPUT: sp - set name + * curside - side number for this node + * key - key to use for the name record + * hsp_name - name of the hot spare + * OUTPUT: ep - error information + * RETURNS: 0 indicates success, and -1 indicates failure. + * PURPOSE: Once the name record has been added for the current side, + * this function adds the record to the remaining sides. This + * function is to be used when the set is a traditional set. + * The side designated by curside will be ignored when adding + * records. + */ +static int +add_hsp_name_trad_sides( + mdsetname_t *sp, + md_set_desc *sd, + side_t curside, + mdkey_t key, + char *hsp_name, + md_error_t *ep +) +{ + int i; + + for (i = 0; i < MD_MAXSIDES; i++) { + if (i == curside) + continue; + if (sd->sd_nodes[i][0] != '\0') { + if (add_name(sp, i, key, MD_HOTSPARES, minor(NODEV), + hsp_name, ep) == -1) { + return (-1); + } + } + } + return (0); +} + +/* + * FUNCTION: add_hsp_name() + * INPUT: sp - Name of the set containing the hsp + * hsp_name - Hot spare pool name to be added + * OUTPUT: ep - Error information + * RETURNS: If successful the key of the newly added record is + * returned. MD_KEYBAD is returned to indicate a failure. + * PURPOSE: This function creates a new NM record containing the name + * of the hotspare pool. A record containing the name is + * added to each active side, but the record is added first to + * the current side. This function is modeled on + * add_key_name() in meta_namespace. The difference is that + * there is no device associated with a hot spare pool + */ +static hsp_t +add_hsp_name( + mdsetname_t *sp, + char *hsp_name, + md_error_t *ep +) +{ + md_error_t ignore_error = MDNULLERROR; + mdkey_t key; + md_set_desc *sd; + side_t thisside; /* Side # of this node. */ + + if (sp == NULL) { + (void) mderror(ep, MDE_NO_SET, NULL); + return (MD_KEYBAD); + } + if (hsp_name == NULL) { + (void) mderror(ep, MDE_INVAL_HSOP, NULL); + return (MD_KEYBAD); + } + + mdclrerror(ep); + thisside = getmyside(sp, ep); + if (! mdisok(ep)) + return (MD_HSPID_WILD); + + /* First add the record for the side of the current node. */ + key = add_name(sp, thisside, MD_KEYWILD, MD_HOTSPARES, minor(NODEV), + hsp_name, ep); + if (key == -1) { + goto cleanup; + } + + /* Make sure that we can use the key */ + if (!HSP_KEY_OK(key)) { + (void) mdhsperror(ep, MDE_HSP_CREATE_FAILURE, MD_HSPID_WILD, + hsp_name); + goto cleanup; + } + + /* + * Now that we have a key, we will use it to add a record to the + * rest of the sides in the set. For multinode sets, the sides are + * in a linked list that is anchored on the set descriptor. For + * traditional sets the side information is in an array in the set + * descriptor. + */ + if (!metaislocalset(sp)) { + if ((sd = metaget_setdesc(sp, ep)) == NULL) { + goto cleanup; + } + if (MD_MNSET_DESC(sd)) { + /* Multinode set. Sides are in linked list. */ + if (add_hsp_name_mn_sides(sp, sd, thisside, key, + hsp_name, ep) == -1) { + goto cleanup; + } + } else { + /* Traditional set. Sides are in an array. */ + if (add_hsp_name_trad_sides(sp, sd, thisside, key, + hsp_name, ep) == -1) { + goto cleanup; + } + } + } + + return (KEY_TO_HSP_ID(sp->setno, key)); + +cleanup: + /* Get rid records that we added. */ + (void) del_hsp_keys(sp, KEY_TO_HSP_ID(sp->setno, key), &ignore_error); + return (MD_HSPID_WILD); +} + +/* * add hotspares and/or hotspare pool */ int @@ -754,12 +1072,14 @@ md_error_t *ep ) { + md_error_t ignore_error = MDNULLERROR; mdnamelist_t *p; set_hs_params_t shs; + side_t thisside; /* should have a set */ assert(sp != NULL); - assert(sp->setno == HSP_SET(hspnp->hsp)); + assert(hspnp->hsp == MD_HSP_NONE || sp->setno == HSP_SET(hspnp->hsp)); /* clear cache */ meta_invalidate_hsp(hspnp); @@ -767,9 +1087,39 @@ /* setup hotspare pool info */ (void) memset(&shs, 0, sizeof (shs)); shs.shs_cmd = ADD_HOT_SPARE; - shs.shs_hot_spare_pool = hspnp->hsp; MD_SETDRIVERNAME(&shs, MD_HOTSPARES, sp->setno); + /* Get key for hot spare pool name record. */ + if (options & MDCMD_DOIT) { + /* First see if the name record already exists. */ + mdclrerror(ep); + thisside = getmyside(sp, ep); + if (! mdisok(ep)) + return (-1); + shs.shs_hot_spare_pool = + meta_gethspnmentbyname(sp->setno, thisside, + hspnp->hspname, ep); + if (! mdisok(ep)) { + /* + * If the error is ENOENT, then we will create a + * hot spare pool name records. For other types of + * errors, however, we'll bail out. + */ + if (! mdissyserror(ep, ENOENT)) + return (-1); + mdclrerror(ep); + /* make sure that the name isn't already in use */ + if (is_existing_metadevice(sp, hspnp->hspname)) + return (mderror(ep, MDE_NAME_IN_USE, + hspnp->hspname)); + if ((shs.shs_hot_spare_pool = + add_hsp_name(sp, hspnp->hspname, ep)) == + MD_HSPID_WILD) { + return (-1); + } + } + } + /* add empty hotspare pool */ if (hsnlp == NULL) { shs.shs_options = HS_OPT_POOL; @@ -778,8 +1128,14 @@ shs.shs_options |= HS_OPT_DRYRUN; } if (metaioctl(MD_IOCSET_HS, &shs, &shs.mde, - hspnp->hspname) != 0) + hspnp->hspname) != 0) { + if (options & MDCMD_DOIT) { + (void) del_hsp_keys(sp, + shs.shs_hot_spare_pool, + &ignore_error); + } return (mdstealerror(ep, &shs.mde)); + } goto success; } @@ -794,7 +1150,8 @@ diskaddr_t size, label, start_blk; /* should be in same set */ - assert(sp->setno == HSP_SET(hspnp->hsp)); + assert(hspnp->hsp == MD_HSP_NONE || + sp->setno == HSP_SET(hspnp->hsp)); /* check it out */ if (meta_check_hotspare(sp, hsnp, ep) != 0) @@ -857,6 +1214,49 @@ } /* + * FUNCTION: meta_hsp_delete() + * INPUT: sp - Name of the set containing the hsp + * hspnp - Hot spare pool name information + * options - Options from command line + * OUTPUT: ep - Error information + * RETURNS: 0 on success and -1 on failure. + * PURPOSE: Common code to delete an empty hot spare pool. + */ +static int +meta_hsp_delete( + mdsetname_t *sp, + mdhspname_t *hspnp, + mdcmdopts_t options, + md_error_t *ep +) +{ + set_hs_params_t shs; + + /* setup hotspare pool info */ + (void) memset(&shs, 0, sizeof (shs)); + shs.shs_hot_spare_pool = hspnp->hsp; + MD_SETDRIVERNAME(&shs, MD_HOTSPARES, sp->setno); + shs.shs_cmd = DELETE_HOT_SPARE; + shs.shs_options = HS_OPT_POOL; + /* If DOIT is not set, it's a dryrun */ + if ((options & MDCMD_DOIT) == 0) { + shs.shs_options |= HS_OPT_DRYRUN; + } + + /* Remove hsp record. */ + if (metaioctl(MD_IOCSET_HS, &shs, &shs.mde, + hspnp->hspname) != 0) + return (mdstealerror(ep, &shs.mde)); + + /* Get rid of hsp NM records */ + if ((options & MDCMD_DOIT) && + (del_hsp_keys(sp, hspnp->hsp, ep) == -1)) { + return (-1); + } + return (0); +} + +/* * delete hotspares from pool */ int @@ -873,7 +1273,7 @@ /* should have a set */ assert(sp != NULL); - assert(sp->setno == HSP_SET(hspnp->hsp)); + assert(hspnp->hsp == MD_HSP_NONE || sp->setno == HSP_SET(hspnp->hsp)); /* clear cache */ meta_invalidate_hsp(hspnp); @@ -886,14 +1286,8 @@ /* delete empty hotspare pool */ if (hsnlp == NULL) { - shs.shs_options = HS_OPT_POOL; - /* If DOIT is not set, it's a dryrun */ - if ((options & MDCMD_DOIT) == 0) { - shs.shs_options |= HS_OPT_DRYRUN; - } - if (metaioctl(MD_IOCSET_HS, &shs, &shs.mde, - hspnp->hspname) != 0) - return (mdstealerror(ep, &shs.mde)); + if (meta_hsp_delete(sp, hspnp, options, ep) != 0) + return (-1); goto success; } @@ -907,7 +1301,8 @@ mdname_t *hsnp = p->namep; /* should be in same set */ - assert(sp->setno == HSP_SET(hspnp->hsp)); + assert(hspnp->hsp == MD_HSP_NONE || + sp->setno == HSP_SET(hspnp->hsp)); /* delete hotspare */ shs.shs_component_old = hsnp->dev; @@ -963,7 +1358,7 @@ /* should be in same set */ assert(sp != NULL); - assert(sp->setno == HSP_SET(hspnp->hsp)); + assert(hspnp->hsp == MD_HSP_NONE || sp->setno == HSP_SET(hspnp->hsp)); /* save new binding incase this is a rebind where oldnp==newnp */ new_dev = newnp->dev; @@ -1436,7 +1831,8 @@ /* see if it exists already */ if (meta_get_hsp(*spp, hspnp, ep) != NULL) { - (void) mdhsperror(ep, MDE_HSP_ALREADY_SETUP, hspnp->hsp, uname); + (void) mdhsperror(ep, MDE_HSP_ALREADY_SETUP, + hspnp->hsp, uname); goto out; } else if (! mdishsperror(ep, MDE_INVAL_HSP)) { goto out; @@ -1469,7 +1865,8 @@ mdname_t *hsnamep; /* parse hotspare name */ - if ((hsnamep = metaname(spp, argv[0], ep)) == NULL) + if ((hsnamep = metaname(spp, argv[0], + LOGICAL_DEVICE, ep)) == NULL) goto out; hsp->hsnamep = hsnamep; --argc, ++argv; @@ -1520,7 +1917,8 @@ /* should have the same set */ assert(sp != NULL); - assert((hspnp == NULL) || (sp->setno == HSP_SET(hspnp->hsp))); + assert(hspnp == NULL || hspnp->hsp == MD_HSP_NONE || + sp->setno == HSP_SET(hspnp->hsp)); /* reset all hotspares */ if (hspnp == NULL) { @@ -1595,15 +1993,8 @@ } /* clear hotspare pool */ - shs.shs_options = HS_OPT_POOL; - /* If DOIT is not set, it's a dryrun */ - if ((options & MDCMD_DOIT) == 0) { - shs.shs_options |= HS_OPT_DRYRUN; - } - if (metaioctl(MD_IOCSET_HS, &shs, &shs.mde, hspnp->hspname) != 0) { - (void) mdstealerror(ep, &shs.mde); + if (meta_hsp_delete(sp, hspnp, options, ep) != 0) goto out; - } rval = 0; /* success */ /* let em know */
--- a/usr/src/lib/lvm/libmeta/common/meta_init.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/lib/lvm/libmeta/common/meta_init.c Tue Mar 14 14:53:36 2006 -0800 @@ -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. @@ -21,7 +20,7 @@ */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -32,6 +31,7 @@ */ #include <meta.h> +#include <sys/lvm/mdio.h> #include <libdevinfo.h> @@ -209,10 +209,10 @@ * Input: spp set structure * uname unit-name (fully qualified or relative) * Output: ep error return structure - * Returns: 0 success + * Returns: > 0 success and return 'key' * -1 Error. <ep> contains error reason */ -int +mdkey_t meta_init_make_device( mdsetname_t **spp, char *uname, @@ -221,47 +221,29 @@ { di_devlink_handle_t hdl; md_mkdev_params_t params; - int rval = 0; - char *p, *e = uname; - size_t len = strlen(uname); + mdkey_t rval = 0; + char *p; + int len = strlen(uname); - e += len; (void) memset(¶ms, 0, sizeof (params)); MD_SETDRIVERNAME(¶ms, "md", (*spp)->setno); /* - * Find the start of the unit within <uname>. + * This ioctl call causes kernel to allocate a unit number + * and populate /devices for the named metadevice */ - p = strrchr(uname, '/'); - if (p == NULL) { - /* Relative name (e.g. d80) */ - p = &uname[1]; - } else { - /* qualified name (e.g. /dev/md/dsk/d80) */ - p += 2; - if (p >= e) { - /* Invalid drive name */ - p = Malloc(len + 3); - (void) snprintf(p, len + 3, "\"%s\"", uname); - rval = mderror(ep, MDE_NOT_DRIVENAME, p); - Free(p); - return (rval); - } - } - e = NULL; - params.mnum = strtoul(p, &e, 10); - if (e == p) { - /* Invalid drive name */ - p = Malloc(len + 3); - (void) snprintf(p, len + 3, "\"%s\"", uname); - rval = mderror(ep, MDE_NOT_DRIVENAME, p); - Free(p); - return (rval); - } - if (metaioctl(MD_IOCMAKE_DEV, ¶ms, ¶ms.mde, NULL) != 0) { return (mdstealerror(ep, ¶ms.mde)); } + + /* + * Now we have minor number so add it to the namespace + * and return the key + */ + if ((rval = add_self_name(*spp, uname, ¶ms, ep)) <= 0) { + return (mderror(ep, MDE_UNIT_NOT_FOUND, NULL)); + } + /* * Wait until device appears in namespace. di_devlink_init() returns * once the /dev links have been created. If NULL is returned the @@ -274,6 +256,10 @@ if (hdl != NULL) { (void) di_devlink_fini(&hdl); } else { + /* + * Delete name entry we just created + */ + (void) del_self_name(*spp, rval, ep); p = Malloc(len + 3); (void) snprintf(p, len + 3, "\"%s\"", uname); rval = mderror(ep, MDE_UNIT_NOT_FOUND, p); @@ -382,6 +368,7 @@ mdsetname_t **spp, int argc, char *argv[], + char *cname, /* canonical name */ mdcmdopts_t options, md_error_t *ep ) @@ -390,56 +377,98 @@ char *p; int rval; char *uname = argv[0]; + mdkey_t key = MD_KEYWILD; + minor_t mnum; + md_error_t t_e = mdnullerror; assert(argc > 0); + assert(*spp != NULL); /* determine type of metadevice or hot spare pool being created */ init_type = meta_get_init_type(argc, argv); + /* + * Metatrans is eof + */ + if (init_type == TAB_TRANS) + return (mderror(ep, MDE_EOF_TRANS, NULL)); + /* hotspare pool */ if (init_type == TAB_HSP) return (meta_init_hsp(spp, argc, argv, options, ep)); + /* + * We are creating metadevice so make sure the name + * has not been used + */ + if (is_existing_meta_hsp(*spp, cname)) { + /* + * The name has been used by hsp + */ + if (is_existing_hsp(*spp, cname)) { + return (mderror(ep, MDE_NAME_IN_USE, cname)); + } + + /* + * If path exists but unit is not created + * then meta_init_make_device will correct + * that. If unit also exists then it + * will return a conflict error + */ + if (init_type != TAB_UNKNOWN) { + /* Create device node */ + if ((key = meta_init_make_device(spp, uname, + &t_e)) <= 0) { + return (mdstealerror(ep, &t_e)); + } + } + } + /* metadevice */ if (argc >= 2 && init_type != TAB_UNKNOWN) { - md_error_t t_e = mdnullerror; - char *cname; - /* * We need to create the device node if the specified metadevice * does not already exist in the database. The actual creation * is undertaken by the md driver and the links propagated by * devfsadm. */ - - /* initialize the spp properly */ - if ((cname = meta_name_getname(spp, uname, &t_e)) != NULL) - Free(cname); - if (! mdisok(&t_e)) - return (mdstealerror(ep, &t_e)); - - /* Create device node */ - if (meta_init_make_device(spp, uname, &t_e) != 0) { - return (mdstealerror(ep, &t_e)); + if (key == MD_KEYWILD) { + if ((key = meta_init_make_device(spp, uname, + &t_e)) <= 0) + return (mdstealerror(ep, &t_e)); } switch (init_type) { case TAB_MIRROR: - return (meta_init_mirror(spp, argc, argv, options, ep)); + rval = meta_init_mirror(spp, argc, argv, options, ep); break; case TAB_RAID: - return (meta_init_raid(spp, argc, argv, options, ep)); + rval = meta_init_raid(spp, argc, argv, options, ep); break; case TAB_SP: - return (meta_init_sp(spp, argc, argv, options, ep)); - break; - case TAB_TRANS: - return (mderror(ep, MDE_EOF_TRANS, NULL)); + rval = meta_init_sp(spp, argc, argv, options, ep); break; case TAB_STRIPE: - return (meta_init_stripe(spp, argc, argv, options, ep)); + rval = meta_init_stripe(spp, argc, argv, options, ep); break; } + + if (rval == -1 || !(options & MDCMD_DOIT)) { + /* + * Remove the device node created before + */ + if ((meta_getnmentbykey((*spp)->setno, MD_SIDEWILD, + key, NULL, &mnum, NULL, ep) != NULL) && + MD_MIN2UNIT(mnum) < MD_MAXUNITS) { + (void) metaioctl(MD_IOCREM_DEV, &mnum, &t_e, NULL); + } + + /* + * Del what we added before + */ + (void) del_self_name(*spp, key, &t_e); + } + return (rval); } /* unknown type */
--- a/usr/src/lib/lvm/libmeta/common/meta_mirror.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/lib/lvm/libmeta/common/meta_mirror.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -314,14 +313,19 @@ * is net mounted as happens if we're part of the * install process, rootnp will be set to NULL and we * return success. + * + * Since curroot should be a complete path, we only + * need to check whether the device is a logical device. + * The metaname below returns NULL if curroot is not a logical + * device. */ - if ((rootnp = metaname(&sp, curroot, ep)) == NULL) + if ((rootnp = metaname(&sp, curroot, LOGICAL_DEVICE, ep)) == NULL) return (0); /* - * If the currently mounted root slice is not a - * ctds, we don't bother checking + * If we're here, the curroot is a mounted on a logical device. + * Make sure this mirror is not on the root logical device. */ - if ((!metaismeta(rootnp)) && metaismeta(mirnp)) { + if (metaismeta(mirnp)) { if ((mirrorp = meta_get_mirror(sp, mirnp, ep)) == NULL) return (-1); @@ -597,7 +601,14 @@ if (options & PRINT_LARGEDEVICES) { - if (mirrorp->common.revision != MD_64BIT_META_DEV) { + if ((mirrorp->common.revision & MD_64BIT_META_DEV) == 0) { + rval = 0; + goto out; + } + } + + if (options & PRINT_FN) { + if ((mirrorp->common.revision & MD_FN_META_DEV) == 0) { rval = 0; goto out; } @@ -619,7 +630,7 @@ } /* print submirror */ - if (fprintf(fp, " %s", submirnamep->cname) == EOF) + if (fprintf(fp, " %s", submirnamep->rname) == EOF) goto out; } @@ -908,7 +919,40 @@ * level and print there if appropriate. */ if (options & PRINT_LARGEDEVICES) { - if (mirrorp->common.revision != MD_64BIT_META_DEV) { + if ((mirrorp->common.revision & MD_64BIT_META_DEV) == 0) { + for (smi = 0; (smi < NMIRROR); ++smi) { + md_submirror_t *mdsp = + &mirrorp->submirrors[smi]; + mdname_t *submirnamep = + mdsp->submirnamep; + if (submirnamep == NULL) { + continue; + } + if ((metaismeta(submirnamep)) && + (meta_print_name(sp, submirnamep, nlpp, + fname, fp, options | PRINT_SUBDEVS, NULL, + ep) != 0)) { + return (-1); + } + } + rval = 0; + goto out; + } else { + if (meta_getdevs(sp, mirrorp->common.namep, + nlpp, ep) != 0) + goto out; + } + } + + /* + * check for the -D option. If -D and the name is + * a descriptive name, get the dev for relocation information + * printout. If not a descriptive name, don't print this + * information out but you need to go down to the subdevice + * level and print there if appropriate. + */ + if (options & PRINT_FN) { + if ((mirrorp->common.revision & MD_FN_META_DEV) == 0) { for (smi = 0; (smi < NMIRROR); ++smi) { md_submirror_t *mdsp = &mirrorp->submirrors[smi]; @@ -987,7 +1031,7 @@ /* print resync status */ if (status & MD_UN_RESYNC_CANCEL) { /* Resync was cancelled but is restartable */ - if (mirrorp->common.revision == MD_64BIT_META_DEV) { + if (mirrorp->common.revision & MD_64BIT_META_DEV) { if (fprintf(fp, dgettext(TEXT_DOMAIN, " Resync cancelled: %2d.%1d %% done\n"), mirrorp->percent_done/10, @@ -1002,7 +1046,7 @@ } } } else if (status & MD_UN_RESYNC_ACTIVE) { - if (mirrorp->common.revision == MD_64BIT_META_DEV) { + if (mirrorp->common.revision & MD_64BIT_META_DEV) { if (fprintf(fp, dgettext(TEXT_DOMAIN, " Resync in progress: %2d.%1d %% done\n"), mirrorp->percent_done/10, @@ -1136,6 +1180,7 @@ char *sm_state; md_timeval32_t tv; char *timep; + md_stripe_t *stripep; /* skip unused submirrors */ if (submirnamep == NULL) { @@ -1143,6 +1188,17 @@ continue; } + if (options & PRINT_FN) { + /* get unit structure */ + if ((stripep = meta_get_stripe_common(sp, submirnamep, + ((options & PRINT_FAST) ? 1 : 0), ep)) == NULL) + goto out; + + if ((stripep->common.revision & MD_FN_META_DEV) + == 0) + continue; + } + /* add extra line */ if (fprintf(fp, "\n") == EOF) goto out; @@ -2384,10 +2440,10 @@ /* did the user tell us to generate a large device? */ create_flag = meta_check_devicesize(mm->c.un_total_blocks); if (create_flag == MD_CRO_64BIT) { - mm->c.un_revision = MD_64BIT_META_DEV; + mm->c.un_revision |= MD_64BIT_META_DEV; set_params.options = MD_CRO_64BIT; } else { - mm->c.un_revision = MD_32BIT_META_DEV; + mm->c.un_revision &= ~MD_64BIT_META_DEV; set_params.options = MD_CRO_32BIT; } set_params.mnum = MD_SID(mm); @@ -2441,7 +2497,7 @@ assert(argc > 0); if (argc < 1) goto syntax; - if ((mirnp = metaname(spp, uname, ep)) == NULL) + if ((mirnp = metaname(spp, uname, META_DEVICE, ep)) == NULL) goto out; assert(*spp != NULL); uname = mirnp->cname; @@ -2504,7 +2560,8 @@ } /* parse submirror name */ - if ((submirnamep = metaname(spp, argv[0], ep)) == NULL) + if ((submirnamep = metaname(spp, argv[0], + META_DEVICE, ep)) == NULL) goto out; mdsm->submirnamep = submirnamep; --argc, ++argv;
--- a/usr/src/lib/lvm/libmeta/common/meta_mn_handlers.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/lib/lvm/libmeta/common/meta_mn_handlers.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -1149,8 +1148,9 @@ } name = splicename(&d->msg_splitname); - if ((np = metaname(&sp, name, &ep)) == NULL) { - Free(name); + np = metaname(&sp, name, LOGICAL_DEVICE, &ep); + Free(name); + if (np == NULL) { (void) mdstealerror(&(resp->mmr_ep), &ep); resp->mmr_exitval = -1; return; @@ -1192,7 +1192,7 @@ } } add_name = splicename(&d->msg_splitname); - if ((np = metaname(&sp, add_name, &ep)) != NULL) { + if ((np = metaname(&sp, add_name, LOGICAL_DEVICE, &ep)) != NULL) { meta_invalidate_name(np); } else { ret = -1; @@ -1268,7 +1268,7 @@ } /* Not incrementing "i" intentionally (dbcnt is changed) */ } - if ((np = metaname(&sp, del_name, &ep)) != NULL) { + if ((np = metaname(&sp, del_name, LOGICAL_DEVICE, &ep)) != NULL) { meta_invalidate_name(np); } else { ret = -1; @@ -1673,6 +1673,9 @@ return; } + /* + * Device should be in the namespace already + */ if ((np = metamnumname(&sp, d->iocset_params.mnum, 1, &mde)) == NULL) { syslog(LOG_ERR, dgettext(TEXT_DOMAIN, "MD_MN_MSG_IOCSET: Invalid mnum %d\n"), @@ -1681,14 +1684,9 @@ return; } - if (meta_init_make_device(&sp, np->cname, &mde) == -1) { - syslog(LOG_ERR, dgettext(TEXT_DOMAIN, - "MD_MN_MSG_IOCSET: Invalid metadevice name %s\n"), - np->cname); - resp->mmr_exitval = 1; - return; - } - + /* + * Create unit structure + */ d->iocset_params.mdp = (uintptr_t)&d->unit; /* set pointer to unit */ ret = metaioctl(MD_IOCSET, &(d->iocset_params), &mde, np->cname); resp->mmr_exitval = ret; @@ -1757,7 +1755,7 @@ return; } - compnp = metaname(&sp, d->addkeyname_name, &mde); + compnp = metaname(&sp, d->addkeyname_name, UNKNOWN, &mde); if (compnp != NULL) { ret = add_key_name(sp, compnp, NULL, &mde); if (ret < 0) @@ -1955,3 +1953,69 @@ resp->mmr_exitval = metaioctl(MD_MN_POKE_HOTSPARES, &pokehsp, &pokehsp.mde, NULL); } + +/* + * Called to create a softpart during a metarecover operation + */ +/*ARGSUSED*/ +void +mdmn_do_addmdname(md_mn_msg_t *msg, uint_t flags, md_mn_result_t *resp) +{ + md_mn_msg_addmdname_t *d; + md_error_t mde = mdnullerror; + mdsetname_t *sp; + int init = 0; + mdkey_t key; + minor_t mnum; + + resp->mmr_comm_state = MDMNE_ACK; /* Ok state */; + resp->mmr_out_size = 0; + resp->mmr_err_size = 0; + resp->mmr_out = NULL; + resp->mmr_err = NULL; + d = (md_mn_msg_addmdname_t *)(void *)msg->msg_event_data; + + if ((sp = metasetnosetname(d->addmdname_setno, &mde)) == NULL) { + syslog(LOG_ERR, dgettext(TEXT_DOMAIN, + "MD_MN_MSG_ADDMDNAME: Invalid setno %d\n"), + d->addmdname_setno); + resp->mmr_exitval = 1; + return; + } + + /* + * If device node does not exist then init it + */ + if (!is_existing_meta_hsp(sp, d->addmdname_name)) { + if ((key = meta_init_make_device(&sp, d->addmdname_name, + &mde)) <= 0) { + syslog(LOG_ERR, dgettext(TEXT_DOMAIN, + "MD_MN_MSG_ADDMDNAME: Invalid name %s\n"), + d->addmdname_name); + resp->mmr_exitval = 1; + return; + } + + init = 1; + } + + /* + * We should have it + */ + if (metaname(&sp, d->addmdname_name, META_DEVICE, &mde) == NULL) { + + if (init) { + if (meta_getnmentbykey(sp->setno, MD_SIDEWILD, + key, NULL, &mnum, NULL, &mde) != NULL) { + (void) metaioctl(MD_IOCREM_DEV, &mnum, + &mde, NULL); + } + (void) del_self_name(sp, key, &mde); + } + + resp->mmr_exitval = 1; + return; + } + + resp->mmr_exitval = 0; +}
--- a/usr/src/lib/lvm/libmeta/common/meta_mn_msg_table.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/lib/lvm/libmeta/common/meta_mn_msg_table.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -56,6 +55,7 @@ extern void mdmn_do_delkeyname(HANDLER_PARMS); extern void mdmn_do_get_tstate(HANDLER_PARMS); extern void mdmn_do_get_mirstate(HANDLER_PARMS); +extern void mdmn_do_addmdname(HANDLER_PARMS); extern int mdmn_smgen_test6(SMGEN_PARMS); extern int mdmn_smgen_state_upd(SMGEN_PARMS); @@ -687,4 +687,16 @@ UINT_MAX, 100 /* comm fail retry / time delta */ }, + { + /* + * MD_MN_MSG_ADDMDNAME + * Add metadevice name into replica + */ + MD_MSG_CLASS1, /* message class */ + mdmn_do_addmdname, /* add ,etadevice name */ + NULL, /* submessage generator */ + 90, /* times out in 90 secs */ + 10000, 2, /* class busy retry / time delta */ + 10, 1000 /* comm fail retry / time delta */ + }, };
--- a/usr/src/lib/lvm/libmeta/common/meta_mn_subr.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/lib/lvm/libmeta/common/meta_mn_subr.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -76,7 +75,7 @@ * FUNCTION: meta_is_mn_name() * INPUT: spp - ptr to the set name, if NULL the setname is derived * from the metadevice name (eg set/d10 ) - * name - the metadevice name + * name - the metadevice/hsp name * OUTPUT: ep - return error pointer * RETURNS: int - 1 if MultiNode set else 0 * PURPOSE: checks if the metadevice is in a MultiNode set @@ -88,23 +87,23 @@ md_error_t *ep ) { - md_error_t t_e = mdnullerror; - char *cname; + if (*spp == NULL) { + char *cname; - if (*spp == NULL) { - if (is_hspname(name)) { - if (metahspname(spp, name, ep) == NULL) - return (0); - } else if (is_metaname(name)) { - /* Will fill in *spp based on name */ - if ((cname = meta_name_getname(spp, name, &t_e)) - != NULL) - Free(cname); - if (! mdisok(&t_e)) { - (void) mdstealerror(ep, &t_e); - return (0); - } - } else return (0); + /* + * if the setname is specified in uname and *spp is + * not set, then it is setup using that set name value. + * If *spp is set and a setname specified in uname and + * the set names don't agree then cname will be + * returned as NULL + */ + cname = meta_canonicalize_check_set(spp, name, ep); + if (cname == NULL) { + mdclrerror(ep); + return (0); + } + + Free(cname); } if ((strcmp((*spp)->setname, MD_LOCAL_NAME) != 0) &&
--- a/usr/src/lib/lvm/libmeta/common/meta_mount.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/lib/lvm/libmeta/common/meta_mount.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -82,7 +81,7 @@ (void) strcpy(mnt_mountp, m.mnt_mountp); (void) strcpy(mnt_special, m.mnt_special); - if ((mnp = metaname(&sp, mnt_special, ep)) == NULL) { + if ((mnp = metaname(&sp, mnt_special, UNKNOWN, ep)) == NULL) { mdclrerror(ep); continue; }
--- a/usr/src/lib/lvm/libmeta/common/meta_name.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/lib/lvm/libmeta/common/meta_name.c Tue Mar 14 14:53:36 2006 -0800 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -30,6 +30,7 @@ #include <ctype.h> #include <string.h> +#include <sys/fs/ufs_fsdir.h> /* * Just in case we're not in a build environment, make sure that @@ -60,6 +61,11 @@ static mdhspnamelist_t *hsplistp = NULL; /* + * Static definitions + */ +static int chksetname(mdsetname_t **spp, char *sname, md_error_t *ep); + +/* * leak proof name conversion */ static char * @@ -122,102 +128,15 @@ } /* - * parse up metadevice name - */ -static int -parse_metadevice( - char *uname, - char **snamep, - unit_t *unitp -) -{ - char *sname = Malloc(strlen(uname) + 1); - char *tname = Malloc(strlen(uname) + 1); - - unit_t unit; - int len; - char *up; - char *tp; - int lcws; /* last character was slash */ - - /* handle dont cares */ - if (unitp == NULL) - unitp = &unit; - - /* Now copy uname to tname by throwing away any duplicate '/' */ - for (lcws = 0, tp = tname, up = uname; *up; up++) { - if (lcws) { - if (*up == '/') { - continue; - } else { - lcws = 0; - } - } - if (*up == '/') { - lcws = 1; - } - *tp++ = *up; /* ++ is done by for loop */ - } - *tp = '\0'; - - /* without set */ - if ((sscanf(tname, "d%lu%n", unitp, &len) == 1) && - (strlen(tname) == len) && ((long)*unitp >= 0)) { - if (snamep != NULL) - *snamep = NULL; - Free(sname); - Free(tname); - return (0); - } - - /* fully-qualified without set */ - if (((sscanf(tname, "/dev/md/dsk/d%lu%n", unitp, &len) == 1) && - (strlen(tname) == len) && ((long)*unitp >= 0)) || - ((sscanf(tname, "/dev/md/rdsk/d%lu%n", unitp, &len) == 1) && - (strlen(tname) == len) && ((long)*unitp >= 0))) { - if (snamep != NULL) - *snamep = Strdup(MD_LOCAL_NAME); - Free(sname); - Free(tname); - return (0); - } - - /* with set */ - if (((sscanf(tname, "%[^/]/d%lu%n", sname, unitp, &len) == 2) && - (strlen(tname) == len) && ((long)*unitp >= 0)) || - ((sscanf(tname, "/dev/md/%[^/]/dsk/d%lu%n", sname, - unitp, &len) == 2) && - (strlen(tname) == len) && ((long)*unitp >= 0)) || - ((sscanf(tname, "/dev/md/%[^/]/rdsk/d%lu%n", sname, - unitp, &len) == 2) && - (strlen(tname) == len) && ((long)*unitp >= 0))) { - if (snamep != NULL) { - *snamep = sname; - } else { - Free(sname); - } - Free(tname); - return (0); - } - - /* no match */ - if (snamep != NULL) - *snamep = NULL; - Free(sname); - Free(tname); - return (-1); -} - -/* * FUNCTION: parse_device() * INPUT: sp - pointer to setname struct * uname - Name of either a hotspare pool or metadevice * This can either be a fully qualified path or * in the form [set name/]device - * OUTPUT: setnamep - name of the set that uname is in - * uname - name of the hotspare pools or metadevice - * only contains the name of the device with all - * other path information stripped off. + * OUTPUT: snamep - name of the set that uname is in + * fnamep - metadevice or hsp with path and set name info stripped + * This parameter is dynamically allocated and must be + * freed by the calling function. * PURPOSE: Parse uname and sp into the set name and device name strings. * If the set name is specified as part of uname then use that * otherwise attempt to get the set name from sp. @@ -226,10 +145,12 @@ parse_device( mdsetname_t *sp, char *uname, - char **setnamep /* dynamically alloced - caller must free */ + char **fnamep, /* dynamically alloced - caller must free */ + char **snamep /* dynamically alloced - caller must free */ ) { char setname[FILENAME_MAX+1]; + char devname[FILENAME_MAX+1]; char *tname = Malloc(strlen(uname) + 1); int len; @@ -255,139 +176,94 @@ /* fully-qualified - local set */ if (((sscanf(tname, "/dev/md/dsk/%" VAL2STR(FILENAME_MAX) "s%n", - uname, &len) == 1) && (strlen(tname) == len)) || + devname, &len) == 1) && (strlen(tname) == len)) || ((sscanf(tname, "/dev/md/rdsk/%" VAL2STR(FILENAME_MAX) "s%n", - uname, &len) == 1) && (strlen(tname) == len))) { - if (setnamep != NULL) - *setnamep = NULL; + devname, &len) == 1) && (strlen(tname) == len))) { + *snamep = Strdup(MD_LOCAL_NAME); + *fnamep = Strdup(devname); Free(tname); return; } /* with setname specified - either fully qualified and relative spec */ - if (((sscanf(tname, "%" VAL2STR(FILENAME_MAX) "s/%" - VAL2STR(FILENAME_MAX) "s%n", setname, uname, &len) == 2) && - (strlen(tname) == len)) || + if (((sscanf(tname, "%[^/]/%" VAL2STR(FILENAME_MAX) "s%n", + setname, devname, &len) == 2) && (strlen(tname) == len)) || ((sscanf(tname, "/dev/md/%[^/]/dsk/%" VAL2STR(FILENAME_MAX) "s%n", - setname, uname, &len) == 2) && (strlen(tname) == len)) || + setname, devname, &len) == 2) && (strlen(tname) == len)) || ((sscanf(tname, "/dev/md/%[^/]/rdsk/%" VAL2STR(FILENAME_MAX) "s%n", - setname, uname, &len) == 2) && (strlen(tname) == len))) { - - if (setnamep != NULL) { - *setnamep = Strdup(setname); - } + setname, devname, &len) == 2) && (strlen(tname) == len))) { + + *snamep = Strdup(setname); + *fnamep = Strdup(devname); Free(tname); return; } /* without setname specified */ - (void) strcpy(uname, tname); - if (setnamep != NULL) { - if (sp != NULL && !metaislocalset(sp)) - *setnamep = Strdup(sp->setname); - else - *setnamep = NULL; - } - Free(tname); + *fnamep = tname; + if (sp != NULL && !metaislocalset(sp)) + *snamep = Strdup(sp->setname); + else + *snamep = NULL; +} + +/* + * check for "all" + */ +int +meta_is_all(char *s) +{ + if ((strcoll(s, gettext("all")) == 0) || + (strcoll(s, gettext("ALL")) == 0)) + return (1); + return (0); } /* - * parse up hotspare pool name + * check for "none" */ +int +meta_is_none(char *s) +{ + if ((strcoll(s, gettext("none")) == 0) || + (strcoll(s, gettext("NONE")) == 0)) + return (1); + return (0); +} + static int -parse_hsp( - char *uname, - char **snamep, - hsp_t *hspp -) +valid_name_syntax(char *uname) { - char *sname = Malloc(strlen(uname) + 1); - hsp_t hsp; - int len; - - /* handle dont cares */ - if (hspp == NULL) - hspp = &hsp; - - /* without set */ - if ((sscanf(uname, "hsp%03u%n", hspp, &len) == 1) && - (strlen(uname) == len) && ((long)*hspp >= 0)) { - if (snamep != NULL) - *snamep = NULL; - Free(sname); + int i; + int uname_len; + + if (uname == NULL || !isalpha(uname[0])) + return (0); + + uname_len = strlen(uname); + if (uname_len > MAXNAMLEN) return (0); + + /* 'all' and 'none' are reserved */ + if (meta_is_all(uname) || meta_is_none(uname)) + return (0); + + for (i = 1; i < uname_len; i++) { + if ((isalnum(uname[i]) || uname[i] == '-' || + uname[i] == '_' || uname[i] == '.')) + continue; + break; } - /* with set */ - if ((sscanf(uname, "%[^/]/hsp%03u%n", sname, - hspp, &len) == 2) && - (strlen(uname) == len) && ((long)*hspp >= 0)) { - if (snamep != NULL) { - *snamep = sname; - } else { - Free(sname); - } + if (i < uname_len) return (0); - } - - /* no match */ - Free(sname); - return (-1); + + return (1); + } /* - * canonicalize metadevice name - */ -static char * -canon_metadevice( - char *sname, - unit_t unit -) -{ - char *cname; - size_t len; - - if ((sname == NULL) || (strcmp(sname, MD_LOCAL_NAME) == 0)) { - len = strlen("d") + 20 + 1; - cname = Malloc(len); - (void) snprintf(cname, len, "d%lu", unit); - } else { - len = strlen(sname) + strlen("/d") + 20 + 1; - cname = Malloc(len); - (void) snprintf(cname, len, "%s/d%lu", sname, unit); - } - - return (cname); -} - -/* - * canonicalize hotspare pool name - */ -static char * -canon_hsp( - char *sname, - hsp_t hsp -) -{ - char *cname; - size_t len; - - if ((sname == NULL) || (strcmp(sname, MD_LOCAL_NAME) == 0)) { - cname = Malloc(strlen("hsp000") + 1); - (void) sprintf(cname, "hsp%03u", hsp); - } else { - len = strlen(sname) + strlen("/hsp000") + 1; - cname = Malloc(len); - (void) snprintf(cname, len, "%s/hsp%03lu", sname, hsp); - } - - return (cname); -} - -/* - * canonicalize name, return type - * - * NOTE: this is really only for use by meta_tab* + * canonicalize name */ char * meta_canonicalize( @@ -396,23 +272,106 @@ ) { char *sname = NULL; + char *tname = NULL; char *cname; - /* return the set name and dev name */ - parse_device(sp, uname, &sname); - - if (sname == NULL) - cname = Strdup(uname); + /* return the dev name and set name */ + parse_device(sp, uname, &tname, &sname); + + if (!valid_name_syntax(tname)) { + Free(tname); + if (sname != NULL) + Free(sname); + return (NULL); + } + + if ((sname == NULL) || (strcmp(sname, MD_LOCAL_NAME) == 0)) + cname = tname; else { size_t cname_len; - cname_len = strlen(uname) + strlen(sname) + 2; + cname_len = strlen(tname) + strlen(sname) + 2; cname = Malloc(cname_len); (void) snprintf( - cname, cname_len, "%s/%s", sname, uname); + cname, cname_len, "%s/%s", sname, tname); + Free(tname); + } + + if (sname != NULL) + Free(sname); + + return (cname); +} + +/* + * canonicalize name and check the set + */ +char * +meta_canonicalize_check_set( + mdsetname_t **spp, + char *uname, + md_error_t *ep +) +{ + char *sname = NULL; + char *tname = NULL; + char *cname; + + /* return the dev name and set name */ + parse_device(*spp, uname, &tname, &sname); + + if (!valid_name_syntax(tname)) { + (void) mderror(ep, MDE_NAME_ILLEGAL, tname); + if (sname != NULL) + Free(sname); + Free(tname); + return (NULL); + } + + /* check the set name returned from the name for validity */ + if (chksetname(spp, sname, ep) != 0) { + Free(tname); + if (sname != NULL) + Free(sname); + return (NULL); + } + + if ((sname == NULL) || (strcmp(sname, MD_LOCAL_NAME) == 0)) + cname = tname; + else { + size_t cname_len; + + cname_len = strlen(tname) + strlen(sname) + 2; + cname = Malloc(cname_len); + (void) snprintf( + cname, cname_len, "%s/%s", sname, tname); + Free(tname); + } + + if (sname != NULL) + Free(sname); + + return (cname); +} + +/* + * Verify that the name is a valid hsp/metadevice name + */ +static int +parse_meta_hsp_name(char *uname) +{ + char *sname = NULL; + char *tname = NULL; + int ret; + + /* return the dev name and set name */ + parse_device(NULL, uname, &tname, &sname); + + ret = valid_name_syntax(tname); + if (sname != NULL) Free(sname); - } - return (cname); + Free(tname); + return (ret); } /* @@ -423,10 +382,7 @@ char *uname ) { - if (parse_metadevice(uname, NULL, NULL) == 0) - return (1); - else - return (0); + return (parse_meta_hsp_name(uname)); } /* @@ -437,10 +393,108 @@ char *uname ) { - if (parse_hsp(uname, NULL, NULL) == 0) + return (parse_meta_hsp_name(uname)); +} + +/* + * check to verify that name is an existing metadevice + */ +int +is_existing_metadevice( + mdsetname_t *sp, + char *uname +) +{ + char *raw_name; + char *set_name; + char *full_path; + char *fname = NULL; + int pathlen; + int retval = 0; + + assert(uname != NULL); + /* + * If it is an absolute name of a metadevice, then just call rawname + * on the input + */ + if (uname[0] == '/') { + if (strncmp("/dev/md", uname, strlen("/dev/md")) == 0 && + (raw_name = rawname(uname)) != NULL) { + Free(raw_name); + return (1); + } + return (0); + } + + /* create a fully specified path from the parsed string */ + parse_device(sp, uname, &fname, &set_name); + + if ((set_name == NULL) || (strcmp(set_name, MD_LOCAL_NAME) == 0)) { + pathlen = strlen("/dev/md/rdsk/") + strlen(fname) + 1; + full_path = Zalloc(pathlen); + (void) snprintf(full_path, pathlen, "/dev/md/rdsk/%s", fname); + } else { + pathlen = strlen("/dev/md//rdsk/") + strlen(fname) + + strlen(set_name) + 1; + full_path = Zalloc(pathlen); + (void) snprintf(full_path, pathlen, "/dev/md/%s/rdsk/%s", + set_name, fname); + } + + if ((raw_name = rawname(full_path)) != NULL) { + Free(raw_name); + retval = 1; + } + + if (set_name != NULL) + Free(set_name); + + Free(fname); + Free(full_path); + return (retval); +} + +/* + * check to verify that name is an existing hsp + */ +int +is_existing_hsp( + mdsetname_t *sp, + char *uname +) +{ + md_error_t status = mdnullerror; + hsp_t hsp; + set_t cur_set; + + if (sp != NULL) + cur_set = sp->setno; + else + cur_set = 0; + + hsp = meta_gethspnmentbyname(cur_set, MD_SIDEWILD, uname, &status); + + if (hsp == MD_HSP_NONE) { + mdclrerror(&status); + return (0); + } + return (1); +} + +/* + * check to verify that name is an existing metadevice or hotspare pool + */ +int +is_existing_meta_hsp( + mdsetname_t *sp, + char *uname +) +{ + if (is_existing_metadevice(sp, uname) || + is_existing_hsp(sp, uname)) return (1); - else - return (0); + + return (0); } /* @@ -851,7 +905,7 @@ ) { /* if we already have a set, make sure it's the same */ - if (*spp != NULL) { + if (*spp != NULL && !metaislocalset(*spp)) { if ((*spp)->setname != sname && strcmp((*spp)->setname, sname) != 0) { return (mderror(ep, MDE_SET_DIFF, sname)); @@ -881,7 +935,7 @@ /* default to *spp's setname, or if that is NULL to MD_LOCAL_NAME */ if (sname == NULL) { if (*spp) { - sname = (*spp)->setname; + return (0); } else { sname = MD_LOCAL_NAME; } @@ -1044,9 +1098,6 @@ int l = 0; int cl = strlen(name); - if (is_metaname(name)) - return (Strdup(name)); - /* * Handle old style names, which are of the form /dev/rXXNN[a-h]. */ @@ -1193,40 +1244,42 @@ /* * check set and get comparison name + * + * NOTE: This function has a side effect of setting *spp if the setname + * has been specified and *spp is not already set. */ char * meta_name_getname( - mdsetname_t **spp, - char *uname, - md_error_t *ep + mdsetname_t **spp, + char *uname, + meta_device_type_t uname_type, + md_error_t *ep ) { - char *sname = NULL; - int ismeta = 0; - unit_t unit; - - /* check set name */ - if (parse_metadevice(uname, &sname, &unit) == 0) - ismeta = 1; - if (chksetname(spp, sname, ep) != 0) { - if (sname != NULL) - Free(sname); + if (uname_type == META_DEVICE || uname_type == HSP_DEVICE || + (uname_type == UNKNOWN && is_existing_metadevice(*spp, uname))) { + + /* + * if the setname is specified in uname, *spp is set, + * and the set names don't agree then canonical name will be + * returned as NULL + */ + return (meta_canonicalize_check_set(spp, uname, ep)); + } + + /* if it is not a meta/hsp and *spp is not set then set it to local */ + if (chksetname(spp, NULL, ep) != 0) return (NULL); - } - if (sname != NULL) - Free(sname); - - /* return comparison name */ - if (ismeta) - return (canon_metadevice((*spp)->setname, unit)); - else - return (Strdup(uname)); + + /* if it is not a meta/hsp name then just return uname */ + return (Strdup(uname)); } /* * FUNCTION: getrname() * INPUT: spp - the setname struct * uname - the possibly unqualified device name + * type - ptr to the device type of uname * OUTPUT: ep - return error pointer * RETURNS: char* - character string containing the fully * qualified raw device name @@ -1234,20 +1287,44 @@ * unqualified device name. If uname is an absolute * path the raw name is derived from the input string. * Otherwise, an attempt is made to get the rawname by - * catting "/dev/md/rdsk" and "/dev/rdsk". + * catting "/dev/md/rdsk" and "/dev/rdsk". If the input + * value of type is UNKNOWN and it can be successfully + * determined then update type to the correct value. */ -static char * -getrname(mdsetname_t **spp, char *uname, md_error_t *ep) +static char * +getrname(mdsetname_t **spp, char *uname, + meta_device_type_t *type, md_error_t *ep) { - char *rname, - *fname; - int constructed = 0; + char *rname, + *fname; + int i; + int rname_cnt = 0; + char *rname_list[3]; + meta_device_type_t tmp_type; assert(uname != NULL); /* if it is an absolute name then just call rawname on the input */ if (uname[0] == '/') { - if ((rname = rawname(uname)) != NULL) + if ((rname = rawname(uname)) != NULL) { + /* + * If the returned rname does not match with + * the specified uname type, we'll return null. + */ + if (strncmp(rname, "/dev/md", strlen("/dev/md")) == 0) { + if (*type == LOGICAL_DEVICE) { + (void) mdsyserror(ep, ENOENT, uname); + return (NULL); + } + *type = META_DEVICE; + } else { + if (*type == META_DEVICE) { + (void) mdsyserror(ep, ENOENT, uname); + return (NULL); + } + *type = LOGICAL_DEVICE; + } return (rname); + } /* out of luck */ (void) mdsyserror(ep, ENOENT, uname); @@ -1255,57 +1332,84 @@ } /* + * Get device that matches the requested type. If + * a match is found, return immediately. If type is + * UNKNOWN, save all the found devices in rname_list + * so we can determine later whether the input uname + * is ambiguous. + * * Check for metadevice before physical device. * With the introduction of softpartitions it is more * likely to be a metadevice. */ /* metadevice short form */ - if (metaislocalset(*spp)) { - fname = Malloc(strlen(uname) + strlen("/dev/md/rdsk/") + 1); - (void) strcpy(fname, "/dev/md/rdsk/"); - (void) strcat(fname, uname); - if (*uname == 'd') - constructed = 1; - } else { - char *p; - size_t len; - - if ((p = strchr(uname, '/')) != NULL) { - ++p; + if (*type == META_DEVICE || *type == UNKNOWN) { + if (metaislocalset(*spp)) { + fname = Malloc(strlen(uname) + + strlen("/dev/md/rdsk/") + 1); + (void) strcpy(fname, "/dev/md/rdsk/"); + (void) strcat(fname, uname); } else { - p = uname; + char *p; + size_t len; + + if ((p = strchr(uname, '/')) != NULL) { + ++p; + } else { + p = uname; + } + len = strlen((*spp)->setname) + strlen(p) + + strlen("/dev/md//rdsk/") + 1; + fname = Malloc(len); + (void) snprintf(fname, len, "/dev/md/%s/rdsk/%s", + (*spp)->setname, p); } - len = strlen((*spp)->setname) + strlen(p) + - strlen("/dev/md//rdsk/") + 1; - fname = Malloc(len); - (void) snprintf(fname, len, "/dev/md/%s/rdsk/%s", - (*spp)->setname, p); - if (*p == 'd') - constructed = 1; + rname = rawname(fname); + + if (*type == META_DEVICE) { + /* + * Handle the case where we have a new metadevice + * that does not yet exist in the name-space(e.g + * metarecover in MN sets where /dev/md entry is + * not yet created in the non-master nodes). In + * this case we return the constructed metadevice + * name as that will exist after the metainit call + * has created it. + */ + if (rname == NULL) { + rname = Strdup(fname); + } + + Free(fname); + return (rname); + } + + Free(fname); + if ((rname != NULL) && (*type == UNKNOWN)) { + /* Save this result */ + rname_list[rname_cnt] = rname; + rname_cnt ++; + } } - rname = rawname(fname); - - /* - * Handle the case where we have a new metadevice that does not yet - * exist in the name-space. In this case we return the constructed - * metadevice name as that will exist after the metainit call has - * created it. - */ - if ((rname == NULL) && constructed) { - rname = Strdup(fname); + + if (*type == LOGICAL_DEVICE || *type == UNKNOWN) { + fname = Malloc(strlen(uname) + strlen("/dev/rdsk/") + 1); + (void) strcpy(fname, "/dev/rdsk/"); + (void) strcat(fname, uname); + rname = rawname(fname); + + Free(fname); + if (rname != NULL) { + /* Simply return if a logical device was requested */ + if (*type == LOGICAL_DEVICE) { + return (rname); + } else { + rname_list[rname_cnt] = rname; + rname_cnt ++; + } + } } - Free(fname); - if (rname != NULL) - return (rname); - - fname = Malloc(strlen(uname) + strlen("/dev/rdsk/") + 1); - (void) strcpy(fname, "/dev/rdsk/"); - (void) strcat(fname, uname); - rname = rawname(fname); - Free(fname); - if (rname != NULL) - return (rname); /* * If all else fails try the straight uname. @@ -1317,19 +1421,93 @@ * fubar/d10 -m fubar/d0 fubar/d1 * mount /dev/md/fubar/dsk/d10 /fubar * - * When the system was booted DiskSuite would try to take ownership + * When the system was booted SVM would try to take ownership * of diskset fubar. This would cause rawname("fubar/d10") to be * called. rawname() stats the string which caused the cluster * reservation code to try and take ownership which it was already * doing and a deadlock would occur. By moving this final attempt * at resolving the rawname to the end we avoid this deadlock. */ - if (rname = rawname(uname)) + if (rname = rawname(uname)) { + /* + * It's only possible to get a logical device from this + * rawname call since a metadevice would have been + * detected earlier. + */ + if (*type == LOGICAL_DEVICE && + (strncmp(rname, "/dev/md/", strlen("/dev/md"))) != 1) + return (rname); + else { + rname_list[rname_cnt] = rname; + rname_cnt++; + } + } + + /* + * At this point, we've searched /dev/md/rdsk, /dev/rdsk and + * ./ for the specified device. rname_list contains all + * the matches we've found and rname_cnt is the number of + * matches. + * + * We know that either we don't have a match if a specific + * type was given, in which case we simply return NULL or + * we have an UNKNOWN device with 1-3 entries in rname_list. + * + * If we get 3 entries, rname_cnt == 3, it's ambiguous. + * If we only get 1 entry, rname_cnt == 1, return rname_list[0]. + * If we get 2 entries that are not the same, it's ambigous. + */ + rname = NULL; + if (rname_cnt == 0 || *type != UNKNOWN) { + /* out of luck */ + (void) mdsyserror(ep, ENOENT, uname); + return (NULL); + } else { + if (rname_cnt == 3) { + (void) mderror(ep, MDE_AMBIGUOUS_DEV, uname); + (void) printf(dgettext(TEXT_DOMAIN, + "Error: ambiguous device name.\n%s %s %s\n\n"), + rname_list[0], rname_list[1], rname_list[2]); + rname = NULL; + } + + /* grab the type in case it is not ambiguous */ + if (strncmp(rname_list[0], "/dev/md", strlen("/dev/md")) == 0) + tmp_type = META_DEVICE; + else + tmp_type = LOGICAL_DEVICE; + + if (rname_cnt == 1) { + rname = Strdup(rname_list[0]); + *type = tmp_type; + } else { + /* + * Prevent the case where the command is run in + * either /dev/md/rdsk or /dev/rdsk so the both + * rname_list[0] and rname_list[1] are the same. + */ + if (strcmp(rname_list[0], rname_list[1]) != 0) { + (void) mderror(ep, MDE_AMBIGUOUS_DEV, uname); + if (rname_cnt != 3) { + /* + * For the rname_cnt == 3 case, the + * error was printed above. + */ + (void) printf(dgettext(TEXT_DOMAIN, + "Error: ambiguous device " + "name.\n%s %s\n\n"), + rname_list[0], rname_list[1]); + } + rname = NULL; + } else { + rname = Strdup(rname_list[0]); + *type = tmp_type; + } + } + for (i = 0; i < rname_cnt; i++) + Free(rname_list[i]); return (rname); - - /* out of luck */ - (void) mdsyserror(ep, ENOENT, uname); - return (NULL); + } } /* @@ -1337,20 +1515,26 @@ */ static char * getrawnames( - mdsetname_t **spp, - char *uname, - char **dnamep, - md_error_t *ep + mdsetname_t **spp, + char *uname, + char **dnamep, + meta_device_type_t *uname_type, + md_error_t *ep ) { - char *rname; + char *rname = NULL; size_t len; + /* + * Incorrect code path if type is HSP_DEVICE + */ + assert(*uname_type != HSP_DEVICE); + /* initialize */ *dnamep = NULL; /* get slice name */ - if ((rname = getrname(spp, uname, ep)) != NULL) { + if ((rname = getrname(spp, uname, uname_type, ep)) != NULL) { *dnamep = metadiskname(rname); return (rname); } @@ -1358,9 +1542,11 @@ /* * If name cannot be found, if may be because is is not accessible. * If it is an absolute name, try all possible disk name formats and - * if it is device name, assume it is /dev/rdsk/... + * if it is device name, assume it is /dev/rdsk/.. + * Since the code below assumes logical devices, if the given + * uname_type is META_DEVICE, there's nothing to do. */ - if (mdissyserror(ep, ENOENT)) { + if (mdissyserror(ep, ENOENT) && *uname_type != META_DEVICE) { if (uname[0] == '/') { /* Absolute name */ char *p; @@ -1378,6 +1564,7 @@ mdclrerror(ep); rname = Strdup(uname); *dnamep = metadiskname(rname); + *uname_type = LOGICAL_DEVICE; return (rname); } @@ -1393,6 +1580,7 @@ (void) snprintf(rname, len, "/dev/r%s%u%s", onmb, d, snm); *dnamep = metadiskname(rname); + *uname_type = LOGICAL_DEVICE; return (rname); } @@ -1405,6 +1593,7 @@ rname[(p - uname)] = 'r'; (void) strcpy(&rname[(p - uname) + 1], p); *dnamep = metadiskname(rname); + *uname_type = LOGICAL_DEVICE; return (rname); } @@ -1413,6 +1602,7 @@ mdclrerror(ep); rname = Strdup(uname); *dnamep = metadiskname(rname); + *uname_type = LOGICAL_DEVICE; return (rname); } } else { @@ -1427,12 +1617,15 @@ (void) snprintf(rname, len, "/dev/rdsk/%s", uname); *dnamep = metadiskname(rname); + *uname_type = LOGICAL_DEVICE; return (rname); } } } /* out of luck */ + if (!mdiserror(ep, MDE_AMBIGUOUS_DEV)) + (void) mderror(ep, MDE_UNIT_NOT_FOUND, uname); return (NULL); } @@ -1575,9 +1768,10 @@ */ static int uname2sliceno( - char *uname, - uint_t *slicep, - md_error_t *ep + char *uname, + meta_device_type_t uname_type, + uint_t *slicep, + md_error_t *ep ) { uint_t c = 0, t = 0, d = 0; @@ -1587,7 +1781,8 @@ char *p; char *rname = NULL; - if (is_metaname(uname)) + + if (uname_type == META_DEVICE) return (*slicep = 0); if ((p = strrchr(uname, '/')) != NULL) @@ -1645,12 +1840,13 @@ */ static int getparts( - mddrivename_t *dnp, - char *rname, - char *dname, - uint_t *npartsp, - uint_t *partnop, - md_error_t *ep + mddrivename_t *dnp, + char *rname, + char *dname, + meta_device_type_t uname_type, + uint_t *npartsp, + uint_t *partnop, + md_error_t *ep ) { int nparts; @@ -1659,7 +1855,7 @@ mdvtoc_t *vtocp; /* metadevice */ - if (is_metaname(rname)) { + if (uname_type == META_DEVICE) { dnp->type = MDT_META; nparts = 1; partno = 0; @@ -1713,7 +1909,7 @@ mdclrerror(ep); nparts = V_NUMPAR; - if (uname2sliceno(rname, &partno, ep) < 0) { + if (uname2sliceno(rname, uname_type, &partno, ep) < 0) { mdclrerror(ep); partno = 0; } @@ -1925,17 +2121,18 @@ static mdname_t * setup_slice( - mdsetname_t *sp, - mddrivename_t *dnp, - char *uname, - char *rname, - char *dname, - uint_t partno, - md_error_t *ep + mdsetname_t *sp, + meta_device_type_t uname_type, + mddrivename_t *dnp, + char *uname, + char *rname, + char *dname, + uint_t partno, + md_error_t *ep ) { - char *srname = NULL; - mdname_t *np; + char *srname = NULL; + mdname_t *np; /* must have a set */ assert(sp != NULL); @@ -1946,7 +2143,7 @@ if (rname) srname = rname; - else if (is_metaname(dname)) + else if (uname_type == META_DEVICE) srname = dname; else { char onmb[BUFSIZ+1]; @@ -2072,9 +2269,8 @@ } fastnmlp = NULL; } - static char * -getrname_fast(char *unm, md_error_t *ep) +getrname_fast(char *unm, meta_device_type_t uname_type, md_error_t *ep) { uint_t d = 0; int l = 0; @@ -2084,36 +2280,62 @@ char *p; size_t len; - if (is_metaname(unm)) { - /* without set */ - if (sscanf(unm, "d%u%n", &d, &l) == 1 && cl == l) { - rnm = Zalloc(14 + cl + 1); - (void) sprintf(rnm, "/dev/md/rdsk/d%u", d); + if (uname_type == META_DEVICE) { + /* fully qualified - local set */ + if (((sscanf(unm, "/dev/md/dsk/%" VAL2STR(BUFSIZ) "s%n", + onmb, &len) == 1) && (cl == len)) || + ((sscanf(unm, "/dev/md/rdsk/%" VAL2STR(BUFSIZ) "s%n", + onmb, &len) == 1) && (cl == len))) { + len = strlen("/dev/md/rdsk/") + strlen(onmb) + 1; + rnm = Zalloc(len); + (void) snprintf(rnm, len, "/dev/md/rdsk/%s", onmb); + return (rnm); + } + + /* fully qualified - setname specified */ + if (((sscanf(unm, "/dev/md/%[^/]/dsk/%" + VAL2STR(BUFSIZ) "s%n", + snm, onmb, &len) == 2) && (cl == len)) || + ((sscanf(unm, "/dev/md/%[^/]/rdsk/%" + VAL2STR(BUFSIZ) "s%n", + snm, onmb, &len) == 2) && (cl == len))) { + + len = strlen("/dev/md//rdsk/") + strlen(snm) + + strlen(onmb) + 1; + rnm = Zalloc(len); + (void) snprintf(rnm, len, "/dev/md/%s/rdsk/%s", + snm, onmb); return (rnm); } - /* fully-qualified without set */ - if ((sscanf(unm, "/dev/md/dsk/d%u%n", &d, &l) == 1 || - sscanf(unm, "/dev/md/rdsk/d%u%n", &d, &l) == 1) && - cl == l) { - rnm = Zalloc(14 + cl + 1); - (void) sprintf(rnm, "/dev/md/rdsk/d%u", d); + /* Fully qualified path - error */ + if (unm[0] == '/') { + (void) mdsyserror(ep, EINVAL, unm); + return (NULL); + } + + /* setname specified <setname>/<metadev> */ + if (((sscanf(unm, "%[^/]/%" VAL2STR(BUFSIZ) "s%n", + snm, onmb, &len) == 2) && (cl == len))) { + /* Not <setname>/<metadev> - error */ + if (strchr(onmb, '/') != NULL) { + (void) mdsyserror(ep, EINVAL, unm); + return (NULL); + } + + len = strlen("/dev/md//rdsk/") + strlen(snm) + + strlen(onmb) + 1; + rnm = Zalloc(len); + (void) snprintf(rnm, len, "/dev/md/%s/rdsk/%s", + snm, onmb); return (rnm); } - /* with set */ - if ((sscanf(unm, - "%" VAL2STR(BUFSIZ) "[^/]/d%u%n", snm, &d, &l) == 2 || - sscanf(unm, "/dev/md/%" VAL2STR(BUFSIZ) "[^/]/dsk/d%u%n", - snm, &d, &l) == 2 || - sscanf(unm, "/dev/md/%" VAL2STR(BUFSIZ) "[^/]/rdsk/d%u%n", - snm, &d, &l) == 2) && cl == l) { - len = 14 + cl + strlen(snm) + 1; - rnm = Zalloc(len); - (void) snprintf(rnm, len, "/dev/md/%s/rdsk/d%u", - snm, d); - return (rnm); - } + /* Must be simple metaname/hsp pool name */ + len = strlen("/dev/md/rdsk/") + strlen(unm) + 1; + rnm = Zalloc(len); + (void) snprintf(rnm, len, "/dev/md/rdsk/%s", unm); + return (rnm); } /* NOT Fully qualified path, done */ @@ -2161,9 +2383,10 @@ static mdname_t * metainitfastname( - mdsetname_t *sp, - char *uname, - md_error_t *ep + mdsetname_t *sp, + char *uname, + meta_device_type_t uname_type, + md_error_t *ep ) { uint_t c = 0, t = 0, d = 0, s = 0; @@ -2171,6 +2394,7 @@ mddrivename_t *dnp; mdname_t *np; mdnamelist_t **fnlpp; + char *cname; for (fnlpp = &fastnmlp; (*fnlpp != NULL); fnlpp = &(*fnlpp)->next) { np = (*fnlpp)->namep; @@ -2187,27 +2411,10 @@ /* Metadevices */ - if (is_metaname(uname)) { - char *p; - size_t len; - - if ((p = strrchr(uname, '/')) != NULL) - ++p; - else - p = uname; - - if (metaislocalset(sp)) { - if (np->cname) - Free(np->cname); - np->cname = Strdup(p); - } else { - if (np->cname) - Free(np->cname); - len = strlen(sp->setname) + 1 + strlen(p) + 1; - np->cname = Zalloc(len); - (void) snprintf(np->cname, len, "%s/%s", - sp->setname, p); - } + if (uname_type == META_DEVICE && + (cname = meta_canonicalize(sp, uname)) != NULL) { + + np->cname = cname; dnp->type = MDT_FAST_META; goto done; } @@ -2252,7 +2459,7 @@ if ((dnp->cname = metadiskname(np->cname)) == NULL) dnp->cname = Strdup(np->cname); - if ((np->rname = getrname_fast(uname, ep)) != NULL) { + if ((np->rname = getrname_fast(uname, uname_type, ep)) != NULL) { if ((dnp->rname = metadiskname(np->rname)) == NULL) dnp->rname = Strdup(np->rname); } else { @@ -2274,6 +2481,7 @@ mdsetname_t **spp, char *uname, int fast, + meta_device_type_t uname_type, md_error_t *ep ) { @@ -2289,17 +2497,20 @@ assert(uname != NULL); /* check setname */ - if ((cname = meta_name_getname(spp, uname, ep)) == NULL) + if ((cname = meta_name_getname(spp, uname, uname_type, ep)) == NULL) return (NULL); assert(*spp != NULL); Free(cname); /* get raw name (rname) of the slice and drive (dname) we have */ - if ((rname = getrawnames(spp, uname, &dname, ep)) == NULL) { + if ((rname = getrawnames(spp, uname, + &dname, &uname_type, ep)) == NULL) { return (NULL); } + assert(uname_type != UNKNOWN); + /* look in cache first */ for (tail = &drivelistp; (*tail != NULL); tail = &(*tail)->next) { dnp = (*tail)->drivenamep; @@ -2311,7 +2522,7 @@ if (dname != NULL) Free(dname); - if (uname2sliceno(uname, &partno, ep) < 0) + if (uname2sliceno(uname, uname_type, &partno, ep) < 0) return (NULL); return (metaslicename(dnp, partno, ep)); @@ -2326,7 +2537,7 @@ if (dname != NULL) Free(dname); - return (metainitfastname(*spp, uname, ep)); + return (metainitfastname(*spp, uname, uname_type, ep)); } /* allocate new list element and drive */ @@ -2336,7 +2547,7 @@ metainitdrivename(dnp); /* get parts info */ - if (getparts(dnp, rname, dname, &nparts, &partno, ep) != 0) + if (getparts(dnp, rname, dname, uname_type, &nparts, &partno, ep) != 0) goto out; /* @@ -2359,8 +2570,8 @@ } /* setup name_t (or slice) wanted */ - if ((np = setup_slice(*spp, dnp, uname, rname, dname, partno, ep)) - == NULL) + if ((np = setup_slice(*spp, uname_type, dnp, uname, rname, + dname, partno, ep)) == NULL) goto out; /* canonical disk name */ @@ -2393,20 +2604,22 @@ metaname( mdsetname_t **spp, char *uname, + meta_device_type_t uname_type, md_error_t *ep ) { - return (metaname_common(spp, uname, 0, ep)); + return (metaname_common(spp, uname, 0, uname_type, ep)); } mdname_t * metaname_fast( mdsetname_t **spp, char *uname, + meta_device_type_t uname_type, md_error_t *ep ) { - return (metaname_common(spp, uname, 1, ep)); + return (metaname_common(spp, uname, 1, uname_type, ep)); } /* @@ -2414,15 +2627,14 @@ */ mddrivename_t * metadrivename( - mdsetname_t **spp, - char *uname, - md_error_t *ep + mdsetname_t **spp, + char *uname, + md_error_t *ep ) { char *slicename; mdname_t *np; - char *cname; mddrivenamelist_t **tail; mddrivename_t *dnp; char *dname; @@ -2430,21 +2642,13 @@ int mplen; size_t len; - /* check setname, get comparison name */ assert(uname != NULL); - if ((cname = meta_name_getname(spp, uname, ep)) == NULL) { + + if ((dname = metadiskname(uname)) == NULL) { (void) mdsyserror(ep, ENOENT, uname); return (NULL); } - assert(*spp != NULL); - - if ((dname = metadiskname(cname)) == NULL) { - (void) mdsyserror(ep, ENOENT, cname); - Free(cname); - return (NULL); - } - /* look in cache first */ for (tail = &drivelistp; (*tail != NULL); tail = &(*tail)->next) { dnp = (*tail)->drivenamep; @@ -2452,11 +2656,11 @@ (strcmp(dnp->cname, dname) == 0)) || (dnp->rname != NULL && (strcmp(dnp->rname, dname) == 0))) { - Free(cname); Free(dname); return (dnp); } } + Free(dname); /* Check each possible slice name based on MD_MAX_PARTS. */ @@ -2473,14 +2677,12 @@ /* Check for each slice in turn until we find one */ for (np = NULL, i = 0; ((np == NULL) && (i < MD_MAX_PARTS)); ++i) { (void) snprintf(slicename, len, "%ss%d", uname, i); - np = metaname(spp, slicename, ep); + np = metaname(spp, slicename, LOGICAL_DEVICE, ep); } Free(slicename); if (np == NULL) { - char *dname; - - if ((mdissyserror(ep, ENOENT)) && + if ((mdiserror(ep, MDE_UNIT_NOT_FOUND)) && ((dname = metadiskname(uname)) != NULL)) { Free(dname); (void) mderror(ep, MDE_NOT_DRIVENAME, uname); @@ -2491,6 +2693,58 @@ } /* + * FUNCTION: metaslicename_type() + * INPUT: dnp - the drivename structure + * sliceno - the slice on the drive to return + * type - LOGICAL_DEVICE or META_DEVICE + * OUTPUT: ep - return error pointer + * RETURNS: mdname_t- pointer the the slice name structure + * PURPOSE: interface to the parts struct in the drive name struct + * Since there is no guarantee that the slice name + * structures are populated users should call this + * function rather than accessing the structure directly + * since it will populate the structure values if they + * haven't already been populated before returning. + */ +mdname_t * +metaslicename_type( + mddrivename_t *dnp, + uint_t sliceno, + meta_device_type_t uname_type, + md_error_t *ep +) +{ + mdsetname_t *sp = NULL; + char *namep = NULL; + mdname_t *np; + + assert(dnp->type != MDT_FAST_COMP && dnp->type != MDT_FAST_META); + + if (sliceno >= dnp->parts.parts_len) { + (void) mderror(ep, MDE_NOSLICE, dnp->cname); + return (NULL); + } + + np = &dnp->parts.parts_val[sliceno]; + + /* check to see if the struct is already populated */ + if (np->cname) { + return (np); + } + + if ((namep = meta_name_getname(&sp, dnp->cname, + uname_type, ep)) == NULL) + return (NULL); + + np = setup_slice(sp, uname_type, dnp, NULL, NULL, dnp->rname, + sliceno, ep); + + Free(namep); + + return (np); +} + +/* * FUNCTION: metaslicename() * INPUT: dnp - the drivename structure * sliceno - the slice on the drive to return @@ -2510,32 +2764,7 @@ md_error_t *ep ) { - mdsetname_t *sp = NULL; - char *namep = NULL; - mdname_t *np; - - assert(dnp->type != MDT_FAST_COMP && dnp->type != MDT_FAST_META); - - if (sliceno >= dnp->parts.parts_len) { - (void) mderror(ep, MDE_NOSLICE, dnp->cname); - return (NULL); - } - - np = &dnp->parts.parts_val[sliceno]; - - /* check to see if the struct is already populated */ - if (np->cname) { - return (np); - } - - if ((namep = meta_name_getname(&sp, dnp->cname, ep)) == NULL) - return (NULL); - - np = setup_slice(sp, dnp, NULL, NULL, dnp->rname, sliceno, ep); - - Free(namep); - - return (np); + return (metaslicename_type(dnp, sliceno, LOGICAL_DEVICE, ep)); } /* @@ -2553,7 +2782,8 @@ mdsetname_t *sp = NULL; char *uname; mdname_t *np; - size_t len; + md_dev64_t dev; + mdkey_t key; /* check set first */ if (spp == NULL) @@ -2563,23 +2793,21 @@ assert(*spp != NULL); sp = *spp; - /* build corresponding device name */ - if (metaislocalset(sp)) { - uname = Malloc(20); - (void) sprintf(uname, "d%lu", MD_MIN2UNIT(mnum)); - } else { - len = strlen(sp->setname) + 1 + 20; - uname = Malloc(len); - (void) snprintf(uname, len, "%s/d%lu", sp->setname, - MD_MIN2UNIT(mnum)); - } + /* get corresponding device name */ + dev = metamakedev(mnum); + if ((uname = meta_getnmentbydev(sp->setno, MD_SIDEWILD, dev, + NULL, NULL, &key, ep)) == NULL) + return (NULL); /* setup name */ if (fast) { - np = metaname_fast(spp, uname, ep); - np->dev = metamakedev(mnum); + np = metaname_fast(spp, uname, META_DEVICE, ep); + if (np) { + np->dev = dev; + np->key = key; + } } else - np = metaname(spp, uname, ep); + np = metaname(spp, uname, META_DEVICE, ep); Free(uname); return (np); @@ -2590,15 +2818,19 @@ */ char * get_mdname( + mdsetname_t *sp, minor_t mnum ) { mdname_t *np; md_error_t status = mdnullerror; + mdsetname_t **spp = NULL; + + if (sp != NULL) + spp = &sp; /* get name */ - if ((np = metamnumname(NULL, mnum, 0, &status)) == NULL) { - mdclrerror(&status); + if ((np = metamnumname(spp, mnum, 0, &status)) == NULL) { return (NULL); } assert(meta_getminor(np->dev) == mnum); @@ -2694,6 +2926,7 @@ mdnamelist_t **nlpp, int argc, char *argv[], + meta_device_type_t type, md_error_t *ep ) { @@ -2703,7 +2936,8 @@ for (*nlpp = NULL; (argc > 0); ++count, --argc, ++argv) { mdnamelist_t *nlp = Zalloc(sizeof (*nlp)); - if ((nlp->namep = metaname(spp, argv[0], ep)) == NULL) { + if ((nlp->namep = metaname(spp, argv[0], + type, ep)) == NULL) { metafreenamelist(*nlpp); *nlpp = NULL; return (-1); @@ -2820,28 +3054,82 @@ gethspname( mdsetname_t **spp, char *uname, - hsp_t *hspp, md_error_t *ep ) { - char *sname = NULL; + char *cname = NULL; + + cname = meta_canonicalize(*spp, uname); + /* if it is not a meta/hsp name then flag an error */ + if (cname == NULL) { + (void) mdsyserror(ep, ENOENT, uname); + return (NULL); + } + return (cname); +} + +/* + * set up a hotspare pool name structure using both the name + * and the self id + */ +static mdhspname_t * +metahspname_hsp( + mdsetname_t **spp, + char *uname, + hsp_t hsp, + md_error_t *ep +) +{ + char *cname; + mdhspnamelist_t **tail; + mdhspname_t *hspnp; /* check setname */ assert(uname != NULL); - if (parse_hsp(uname, &sname, hspp) != 0) { - (void) mdsyserror(ep, ENOENT, uname); + if ((cname = gethspname(spp, uname, ep)) == NULL) return (NULL); + assert(*spp != NULL); + + /* look in cache first */ + for (tail = &hsplistp; (*tail != NULL); tail = &(*tail)->next) { + hspnp = (*tail)->hspnamep; + if (strcmp(hspnp->hspname, cname) == 0) { + Free(cname); + /* if the hsp value has not been set then set it now */ + if (hspnp->hsp == MD_HSP_NONE) + hspnp->hsp = hsp; + return (hspnp); + } } - if (chksetname(spp, sname, ep) != 0) { - if (sname != NULL) - Free(sname); - return (NULL); + + /* if the hsp number isn't specified then attempt to get it */ + if (hsp == MD_HSP_NONE && (hsp = meta_gethspnmentbyname((*spp)->setno, + MD_SIDEWILD, cname, ep)) == MD_HSP_NONE) { + if (! mdisok(ep)) { + /* + * If the error is ENOENT, then we will continue on, + * because the device does not yet exist. + * For other types of errors, however, we'll bail out. + */ + if (! mdissyserror(ep, ENOENT)) { + Free(cname); + return (NULL); + } + mdclrerror(ep); + } } - if (sname != NULL) - Free(sname); - - /* return comparison name */ - return (canon_hsp((*spp)->setname, *hspp)); + + /* allocate new list element and hspname */ + *tail = Zalloc(sizeof (**tail)); + hspnp = (*tail)->hspnamep = Zalloc(sizeof (*hspnp)); + metainithspname(hspnp); + + /* save hspname and number */ + hspnp->hspname = cname; + hspnp->hsp = hsp; + + /* success */ + return (hspnp); } /* @@ -2854,51 +3142,11 @@ md_error_t *ep ) { - char *cname; - hsp_t hsp; - mdhspnamelist_t **tail; - mdhspname_t *hspnp; - - /* check setname */ - assert(uname != NULL); - if ((cname = gethspname(spp, uname, &hsp, ep)) == NULL) - return (NULL); - assert(*spp != NULL); - - /* look in cache first */ - for (tail = &hsplistp; (*tail != NULL); tail = &(*tail)->next) { - hspnp = (*tail)->hspnamep; - if (strcmp(hspnp->hspname, cname) == 0) { - Free(cname); - return (hspnp); - } - } - - /* allocate new list element and hspname */ - *tail = Zalloc(sizeof (**tail)); - hspnp = (*tail)->hspnamep = Zalloc(sizeof (*hspnp)); - metainithspname(hspnp); - - /* save hspname and number */ - hspnp->hspname = cname; - hspnp->hsp = MAKE_HSP_ID((*spp)->setno, hsp); - - /* success */ - return (hspnp); - - /* cleanup, return error */ -out: - metafreehspname(hspnp); - Free(hspnp); - Free(*tail); - *tail = NULL; - return (NULL); - - + return (metahspname_hsp(spp, uname, MD_HSP_NONE, ep)); } /* - * set up hotspare pool name from id + * set up hotspare pool name from key */ mdhspname_t * metahsphspname( @@ -2911,7 +3159,6 @@ mdsetname_t *sp = NULL; char *uname; mdhspname_t *hspnp; - size_t len; /* check set first */ if (spp == NULL) @@ -2921,19 +3168,13 @@ assert(*spp != NULL); sp = *spp; - /* build corresponding hotspare pool name */ - if (metaislocalset(sp)) { - uname = Malloc(20); - (void) sprintf(uname, "hsp%03u", HSP_ID(hsp)); - } else { - len = strlen(sp->setname) + 1 + 20; - uname = Malloc(len); - (void) snprintf(uname, len, "%s/hsp%03lu", sp->setname, - HSP_ID(hsp)); - } + /* get corresponding hotspare pool name */ + if ((uname = meta_gethspnmentbyid(sp->setno, + MD_SIDEWILD, hsp, ep)) == NULL) + return (NULL); /* setup name */ - hspnp = metahspname(spp, uname, ep); + hspnp = metahspname_hsp(spp, uname, hsp, ep); Free(uname); return (hspnp); } @@ -2942,13 +3183,17 @@ * return hotspare pool name */ char * -get_hspname(hsp_t hsp) +get_hspname(mdsetname_t *sp, hsp_t hsp) { mdhspname_t *hspnp; md_error_t status = mdnullerror; + mdsetname_t **spp = NULL; + + if (sp != NULL) + spp = &sp; /* get name */ - if ((hspnp = metahsphspname(NULL, hsp, &status)) == NULL) { + if ((hspnp = metahsphspname(spp, hsp, &status)) == NULL) { mdclrerror(&status); return (NULL); } @@ -3050,7 +3295,7 @@ dev, NULL, NULL, &key, ep)) == NULL) { return (NULL); } - namep = metaname_fast(spp, device_name, ep); + namep = metaname_fast(spp, device_name, LOGICAL_DEVICE, ep); if (namep != NULL) namep->key = key; @@ -3136,9 +3381,9 @@ return (NULL); } if (fast) - namep = metaname_fast(spp, device_name, ep); + namep = metaname_fast(spp, device_name, UNKNOWN, ep); else - namep = metaname(spp, device_name, ep); + namep = metaname(spp, device_name, UNKNOWN, ep); assert(dev != NODEV64); if (namep) @@ -3148,6 +3393,18 @@ } /* + * completely flush metadev/hsp caches + */ +void +metaflushmetanames() +{ + metaflushhspnames(); + metaflushdrivenames(); + metaflushfastnames(); + metaflushstatcache(); +} + +/* * completely flush the caches */ void
--- a/usr/src/lib/lvm/libmeta/common/meta_namespace.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/lib/lvm/libmeta/common/meta_namespace.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -84,6 +83,93 @@ } /* + * Ask the driver for the hsp name, driver name, and minor number; + * which has been stored in the metadevice state database + * (on behalf of the utilities). + * (by key) + */ +char * +meta_gethspnmentbyid( + set_t setno, + side_t sideno, + hsp_t hspid, + md_error_t *ep +) +{ + struct mdhspnm_params nm; + char *device_name; + + device_name = Malloc(MAXPATHLEN); + device_name[0] = '\0'; + + (void) memset(&nm, '\0', sizeof (nm)); + nm.setno = setno; + nm.side = sideno; + nm.hspid = hspid; + nm.ret_hspid = MD_HSPID_WILD; + nm.hspname_len = MAXPATHLEN; + nm.hspname = (uint64_t)device_name; + + if (metaioctl(MD_IOCGET_HSP_NM, &nm, &nm.mde, NULL) != 0) { + (void) mdstealerror(ep, &nm.mde); + Free(device_name); + return (NULL); + } + + return (device_name); +} + +/* + * Ask the driver for the hsp_self_id; + * which has been stored in the metadevice state database + * (on behalf of the utilities). + * (by hsp name) + */ +hsp_t +meta_gethspnmentbyname( + set_t setno, + side_t sideno, + char *hspname, + md_error_t *ep +) +{ + struct mdhspnm_params nm; + char *device_name; + + /* must have a hsp name */ + assert(hspname != NULL); + + device_name = Malloc(MAXPATHLEN); + (void) strcpy(device_name, hspname); + + (void) memset(&nm, '\0', sizeof (nm)); + nm.setno = setno; + nm.side = sideno; + nm.hspid = MD_HSPID_WILD; + nm.ret_hspid = MD_HSPID_WILD; + nm.hspname_len = strlen(device_name) + 1; + nm.hspname = (uint64_t)device_name; + + /* + * The ioctl expects the a hsp name and return its hsp_self_id. + */ + if (metaioctl(MD_IOCGET_HSP_NM, &nm, &nm.mde, NULL) != 0) { + (void) mdstealerror(ep, &nm.mde); + Free(device_name); + return (MD_HSP_NONE); + } + + if (nm.ret_hspid == MD_HSPID_WILD) { + Free(device_name); + return (MD_HSP_NONE); + } + + Free(device_name); + return (nm.ret_hspid); +} + + +/* * Ask the driver for the minor name which has been stored in the * metadevice state database. * (by key) @@ -277,6 +363,24 @@ return (NULL); } + /* + * With the friendly name work, each metadevice will have + * an NM entry. However, to allow backward compatibility, + * systems upgraded to a friendly name release won't have + * NM entries for the pre-existing top level metadevices. This + * implementation allows users to downgrade to a pre-friendly + * name release since the configuration information (mddb) is + * not modified. + * + * meta_getnmentbydev is called to get nm entry for all metadevices + * and expects the minor and major number and returns a key and + * name. For upgraded systems with pre-existing metadevices, + * the only returning value will be the name since there's no nm + * entry for pre-friendly name top level metadevices. So a return + * key for the device will not be available and will be NULL. + * Thus, the caller is responsible for making sure the returned key + * is valid, not NULL. + */ if (drvnm != NULL) *drvnm = Strdup(nm.drvnm); if (mnum != NULL) @@ -599,3 +703,172 @@ mdclrerror(&status); return (rval); } + + +/* + * This routine when is called will store the metadevice name + * when it is first created + */ +mdkey_t +add_self_name( + mdsetname_t *sp, + char *uname, + md_mkdev_params_t *params, + md_error_t *ep +) +{ + char *p, *devname; + side_t myside, side; + mdkey_t key; + md_set_desc *sd; + int len; + char *drvname = params->md_driver.md_drivername; + minor_t minor = MD_MKMIN(sp->setno, params->un); + md_mnnode_desc *mnside; + + p = strrchr(uname, '/'); + p = (p == NULL? uname : ++p); + + /* + * The valid qualified name + */ + if (metaislocalset(sp)) { + len = strlen(p) + strlen("/dev/md/dsk/") + 1; + devname = Malloc(len); + (void) strcpy(devname, "/dev/md/dsk/"); + (void) strcat(devname, p); + } else { + len = strlen(sp->setname) + strlen(p) + + strlen("/dev/md//dsk/") + 1; + devname = Malloc(len); + (void) snprintf(devname, len, "/dev/md/%s/dsk/%s", + sp->setname, p); + } + + /* + * Add self to the namespace + */ + if ((myside = getmyside(sp, ep)) == MD_SIDEWILD) { + Free(devname); + return (-1); + } + + if (metaislocalset(sp)) { + if ((key = add_name(sp, myside, MD_KEYWILD, drvname, + minor, devname, ep)) == MD_KEYBAD) { + Free(devname); + return (-1); + } + } else { + /* + * Add myside first and use the returned key to add other sides + */ + if ((key = add_name(sp, myside, MD_KEYWILD, drvname, + minor, devname, ep)) == MD_KEYBAD) { + Free(devname); + return (-1); + } + + /* + * Add for all other sides + */ + if ((sd = metaget_setdesc(sp, ep)) == NULL) { + Free(devname); + return (-1); + } + + if (MD_MNSET_DESC(sd)) { + for (mnside = sd->sd_nodelist; mnside != NULL; + mnside = mnside->nd_next) { + if (mnside->nd_nodeid == myside) + continue; + if (add_name(sp, mnside->nd_nodeid, key, drvname, + minor, devname, ep) == -1) { + Free(devname); + return (-1); + } + } + } else { + for (side = 0; side < MD_MAXSIDES; side++) { + if (sd->sd_nodes[side][0] == '\0') + continue; + if (side == myside) + continue; + if (add_name(sp, side, key, drvname, minor, devname, + ep) == -1) { + Free(devname); + return (-1); + } + } + } + } + + Free(devname); + return (key); +} + + +/* + * This routine when is called will remove the metadevice name + * from the namespace and it is the last thing to do in the + * metaclear operation + */ +int +del_self_name( + mdsetname_t *sp, + mdkey_t key, + md_error_t *ep +) +{ + side_t myside; + int rval = 0; + side_t side; + md_set_desc *sd; + md_mnnode_desc *mnside; + + assert(key != MD_KEYBAD); + + if ((myside = getmyside(sp, ep)) == MD_SIDEWILD) + return (-1); + + if (metaislocalset(sp)) { + rval = del_name(sp, myside, key, ep); + } else { + /* + * Remove all other sides first + */ + if ((sd = metaget_setdesc(sp, ep)) == NULL) { + return (-1); + } + + if (MD_MNSET_DESC(sd)) { + for (mnside = sd->sd_nodelist; mnside != NULL; + mnside = mnside->nd_next) { + if (mnside->nd_nodeid == myside) + continue; + if ((rval = del_name(sp, mnside->nd_nodeid, key, + ep)) == -1) { + goto out; + } + } + } else { + for (side = 0; side < MD_MAXSIDES; side++) { + if (sd->sd_nodes[side][0] == '\0') + continue; + if (side == myside) + continue; + if ((rval = del_name(sp, side, key, ep)) == -1) { + goto out; + } + } + } + + /* + * del myside + */ + rval = del_name(sp, myside, key, ep); + } + +out: + return (rval); +}
--- a/usr/src/lib/lvm/libmeta/common/meta_raid.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/lib/lvm/libmeta/common/meta_raid.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -393,7 +392,14 @@ if (options & PRINT_LARGEDEVICES) { - if (raidp->common.revision != MD_64BIT_META_DEV) { + if ((raidp->common.revision & MD_64BIT_META_DEV) == 0) { + rval = 0; + goto out; + } + } + + if (options & PRINT_FN) { + if ((raidp->common.revision & MD_FN_META_DEV) == 0) { rval = 0; goto out; } @@ -403,28 +409,14 @@ if (fprintf(fp, "%s -r", raidp->common.namep->cname) == EOF) goto out; - /* print columns */ + /* + * Print columns. Always print the full path. + */ for (col = 0; (col < raidp->cols.cols_len); ++col) { md_raidcol_t *mdrcp = &raidp->cols.cols_val[col]; - /* print column */ - /* - * If the path is our standard /dev/rdsk or /dev/md/rdsk - * then just print out the cxtxdxsx or the dx, metainit - * will assume the default, otherwise we need the full - * pathname to make sure this works as we intend. - */ - if ((strstr(mdrcp->colnamep->rname, "/dev/rdsk") == NULL) && - (strstr(mdrcp->colnamep->rname, "/dev/md/rdsk") == NULL) && - (strstr(mdrcp->colnamep->rname, "/dev/td/") == NULL)) { - /* not standard path, print full pathname */ - if (fprintf(fp, " %s", mdrcp->colnamep->rname) == EOF) - goto out; - } else { - /* standard path so print ctd or d number */ - if (fprintf(fp, " %s", mdrcp->colnamep->cname) == EOF) - goto out; - } + if (fprintf(fp, " %s", mdrcp->colnamep->rname) == EOF) + goto out; } if (fprintf(fp, " -k") == EOF) @@ -806,7 +798,14 @@ uint_t tstate = 0; if (options & PRINT_LARGEDEVICES) { - if (raidp->common.revision != MD_64BIT_META_DEV) { + if ((raidp->common.revision & MD_64BIT_META_DEV) == 0) { + rval = 0; + goto out; + } + } + + if (options & PRINT_FN) { + if ((raidp->common.revision & MD_FN_META_DEV) == 0) { rval = 0; goto out; } @@ -1390,10 +1389,10 @@ if (create_flag == MD_CRO_32BIT) { mgp.options = MD_CRO_32BIT; - new_mr->c.un_revision = MD_32BIT_META_DEV; + new_mr->c.un_revision &= ~MD_64BIT_META_DEV; } else { mgp.options = MD_CRO_64BIT; - new_mr->c.un_revision = MD_64BIT_META_DEV; + new_mr->c.un_revision |= MD_64BIT_META_DEV; } if (metaioctl(MD_IOCGROW, &mgp, &mgp.mde, NULL) != 0) { (void) mdstealerror(ep, &mgp.mde); @@ -1583,7 +1582,6 @@ md_dev64_t old_dev, new_dev; diskaddr_t new_start_blk, new_end_blk; int rebind; - mr_unit_t *mr; char *new_devidp = NULL; md_error_t xep = mdnullerror; int ret; @@ -1629,67 +1627,53 @@ params.old_dev = old_dev; params.cmd = force ? FORCE_REPLACE_COMP : REPLACE_COMP; - if (options & MDCMD_CLUSTER_REPLACE) { - if ((mr = (mr_unit_t *)meta_get_mdunit(sp, raidnp, ep)) == NULL) - return (NULL); - Free(mr); - params.options = MDIOCTL_NO_RESYNC_RAID; - params.number_blks = metagetsize(newnp, ep); - if ((metagetlabel(newnp, ep) == MD_DISKADDR_ERROR) || - (metagetlabel(newnp, ep) == 0)) - params.has_label = 0; - else - params.has_label = 1; - params.start_blk = metagetstart(sp, newnp, ep); + if ((strcmp(oldnp->rname, newnp->rname) == 0) && + (old_dev != new_dev)) { + rebind = 1; } else { - if ((strcmp(oldnp->rname, newnp->rname) == 0) && - (old_dev != new_dev)) { - rebind = 1; - } else { - rebind = 0; - } - if (rebind) { - newnp->dev = new_dev; - newnp->start_blk = new_start_blk; - newnp->end_blk = new_end_blk; - } + rebind = 0; + } + if (rebind) { + newnp->dev = new_dev; + newnp->start_blk = new_start_blk; + newnp->end_blk = new_end_blk; + } + + /* + * Save a copy of the devid associated with the new disk, the + * reason is that the checks for the column (meta_check_column) + * via validate_new_raid(), could cause the disk's devid to be + * changed to that of the devid that is currently stored in the + * replica namespace for the disk in question. This devid could + * be stale if we are replacing the disk. The actual function + * that overwrites the devid is dr2drivedesc(). + */ - /* - * Save a copy of the devid associated with the new disk, the - * reason is that the checks for the column (meta_check_column) - * via validate_new_raid(), could cause the disk's devid to be - * changed to that of the devid that is currently stored in the - * replica namespace for the disk in question. This devid could - * be stale if we are replacing the disk. The actual function - * that overwrites the devid is dr2drivedesc(). - */ + /* don't setup new_devid if no devid's or MN diskset */ + if (newnp->drivenamep->devid != NULL) + new_devidp = Strdup(newnp->drivenamep->devid); - /* don't setup new_devid if no devid's or MN diskset */ - if (newnp->drivenamep->devid != NULL) - new_devidp = Strdup(newnp->drivenamep->devid); + if (!metaislocalset(sp)) { + if ((sd = metaget_setdesc(sp, ep)) == NULL) + return (-1); + if (MD_MNSET_DESC(sd)) + new_devidp = NULL; + } - if (!metaislocalset(sp)) { - if ((sd = metaget_setdesc(sp, ep)) == NULL) - return (-1); - if (MD_MNSET_DESC(sd)) - new_devidp = NULL; - } + /* check out new (sets up start_blk, has_label, number_blks) */ + if (validate_new_raid(sp, raidnp, newnp, ¶ms, rebind, + ep) != 0) { + Free(new_devidp); + return (-1); + } - /* check out new (sets up start_blk, has_label, number_blks) */ - if (validate_new_raid(sp, raidnp, newnp, ¶ms, rebind, - ep) != 0) { - Free(new_devidp); - return (-1); - } - - /* - * Copy back the saved devid. - */ - Free(newnp->drivenamep->devid); - if (new_devidp) { - newnp->drivenamep->devid = Strdup(new_devidp); - Free(new_devidp); - } + /* + * Copy back the saved devid. + */ + Free(newnp->drivenamep->devid); + if (new_devidp) { + newnp->drivenamep->devid = Strdup(new_devidp); + Free(new_devidp); } /* store name in namespace, allocate new key */ @@ -2106,7 +2090,7 @@ * Otherwise it's of type raid_pwhdr32_od_t and has to * be converted. */ - if (mr->c.un_revision == MD_64BIT_META_DEV) { + if (mr->c.un_revision & MD_64BIT_META_DEV) { rpw = (raid_pwhdr_t *)buf; } else { RAID_CONVERT_RPW((raid_pwhdr32_od_t *)buf, rpw); @@ -2386,10 +2370,10 @@ (void) memset(&set_params, 0, sizeof (set_params)); /* did the user tell us to generate a large device? */ if (create_flag == MD_CRO_64BIT) { - mr->c.un_revision = MD_64BIT_META_DEV; + mr->c.un_revision |= MD_64BIT_META_DEV; set_params.options = MD_CRO_64BIT; } else { - mr->c.un_revision = MD_32BIT_META_DEV; + mr->c.un_revision &= ~MD_64BIT_META_DEV; set_params.options = MD_CRO_32BIT; } set_params.mnum = MD_SID(mr); @@ -2444,7 +2428,7 @@ assert(argc > 0); if (argc < 1) goto syntax; - if ((raidnp = metaname(spp, uname, ep)) == NULL) + if ((raidnp = metaname(spp, uname, META_DEVICE, ep)) == NULL) goto out; assert(*spp != NULL); @@ -2518,7 +2502,7 @@ mdname_t *colnp; /* parse column name */ - if ((colnp = metaname(spp, argv[0], ep)) == NULL) + if ((colnp = metaname(spp, argv[0], UNKNOWN, ep)) == NULL) goto out; /* check for soft partitions */ if (meta_sp_issp(*spp, colnp, ep) != 0) {
--- a/usr/src/lib/lvm/libmeta/common/meta_rename.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/lib/lvm/libmeta/common/meta_rename.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -101,6 +100,19 @@ md_rename_t txn; int from_add_flag = 0; int to_add_flag = 0; + int from_is_fn, to_is_fn; + bool_t from_has_parent, to_has_parent; + + /* + * What types of devices we have here? + * For MDRNOP_RENAME to_mdp is NULL + */ + from_is_fn = (from_mdp->revision & MD_FN_META_DEV); + from_has_parent = MD_HAS_PARENT(from_mdp->parent); + if (to_mdp) { + to_is_fn = (to_mdp->revision & MD_FN_META_DEV); + to_has_parent = MD_HAS_PARENT(to_mdp->parent); + } /* * If the device exists a key may already exist so need to find it @@ -119,13 +131,18 @@ if ((from_np->key == MD_KEYWILD) || (from_np->key == MD_KEYBAD)) { /* - * If from does not have key and it is a component device - * then something really goes wrong + * If we are top and revision indicates that we + * should have key but we don't then something + * really goes wrong */ - assert(!MD_HAS_PARENT(from_mdp->parent)); + assert(!from_has_parent && !from_is_fn); + + if (from_has_parent || from_is_fn) { + return (-1); + } /* - * So only add the entry if from is a top device + * So only add the entry if necessary */ if (add_key_name(sp, from_np, NULL, ep) != 0) { assert(!mdisok(ep)); @@ -145,13 +162,18 @@ if ((to_np->key == MD_KEYWILD) || (to_np->key == MD_KEYBAD)) { /* - * If to does not have key and is not a top device - * then something really goes wrong + * If we are top and revision indicates that we + * should have key but we don't then something + * really goes wrong */ - assert(!MD_HAS_PARENT(to_mdp->parent)); + assert(!to_has_parent && !to_is_fn); + + if (to_has_parent || to_is_fn) { + return (-1); + } /* - * Add entry + * So only add the entry if necessary */ if (add_key_name(sp, to_np, NULL, ep) != 0) { assert(!mdisok(ep)); @@ -180,19 +202,41 @@ if (metaioctl(MD_IOCRENAME, &txn, &txn.mde, from_np->cname) != 0) { if (from_add_flag) { (void) del_key_name(sp, from_np, ep); + /* + * Attempt removal of device node + */ + (void) metaioctl(MD_IOCREM_DEV, &txn.from.mnum, + ep, NULL); } if (op == MDRNOP_RENAME || to_add_flag) { (void) del_key_name(sp, to_np, ep); + /* + * Attempt removal of device node + */ + (void) metaioctl(MD_IOCREM_DEV, &txn.to.mnum, + ep, NULL); } + return (mdstealerror(ep, &txn.mde)); } /* - * If top device + * Since now the metadevice can be ref'd in the namespace + * by self and by the top device so upon the successful + * rename/xchange, we need to check the type and make + * necessary adjustment for the device's n_cnt in the namespace + * by calling add_key_name/del_key_name to do the tricks */ - if (op == MDRNOP_RENAME && !MD_HAS_PARENT(from_mdp->parent)) { - (void) del_key_name(sp, to_np, ep); + if (op == MDRNOP_RENAME && from_has_parent) { + (void) add_key_name(sp, to_np, NULL, ep); + if (from_is_fn) + (void) del_key_name(sp, from_np, ep); + (void) del_self_name(sp, from_np->key, ep); + } + + if (op == MDRNOP_EXCHANGE && from_is_fn) { + (void) add_key_name(sp, from_np, NULL, ep); } /* force the name cache to re-read device state */ @@ -216,14 +260,11 @@ { int flags = (options & MDCMD_FORCE)? FORCE: 0; int rc = 0; - mdcinfo_t *cinfop; char *p; - md_set_desc *sd; - mdkey_t side_key = MD_KEYWILD; - md_error_t dummy_ep = mdnullerror; - int i, j; - md_mnnode_desc *nd, *nd_del; md_common_t *from_mdp; + minor_t to_minor = meta_getminor(to_np->dev); + md_error_t status = mdnullerror; + md_error_t *t_ep = &status; /* must have a set */ assert(sp != NULL); @@ -263,130 +304,36 @@ } mdclrerror(ep); + /* + * The dest device name has been added early on + * by meta_init_make_device call so get the entry from + * the namespace + */ + if (meta_getnmentbydev(sp->setno, MD_SIDEWILD, to_np->dev, + NULL, NULL, &to_np->key, ep) == NULL) { + return (-1); + } + /* If FORCE is not set, check if metadevice is open */ if (!(flags & FORCE)) { - if (check_open(sp, from_np, ep) != 0) { - return (-1); - } + if (check_open(sp, from_np, ep) != 0) { + (void) del_key_name(sp, to_np, t_ep); + (void) metaioctl(MD_IOCREM_DEV, &to_minor, t_ep, NULL); + return (-1); + } } /* * All checks are done, now we do the real work. - * If we are in dryrun mode, we're done. + * If we are in dryrun mode, clear the deivce node + * and we are done. */ if (flags & DRYRUN) { + (void) del_key_name(sp, to_np, t_ep); + (void) metaioctl(MD_IOCREM_DEV, &to_minor, t_ep, NULL); return (0); /* success */ } - /* - * add key for new name to the namespace - */ - if ((cinfop = metagetcinfo(from_np, ep)) == NULL) { - assert(!mdisok(ep)); - return (-1); - } - - if (metaislocalset(sp)) { - to_np->key = add_name(sp, MD_SIDEWILD, MD_KEYWILD, - cinfop->dname, meta_getminor(to_np->dev), to_np->bname, ep); - } else { - /* - * As this is not the local set we have to create a namespace - * record for each side (host) in the set. We cannot use - * add_key_names() because the destination device (to_np) - * should not exist and so the subsequent metagetcinfo() - * call will fail when it tries to open the device, so we - * have to use the information from the source device (from_np) - */ - if ((sd = metaget_setdesc(sp, ep)) == (md_set_desc *)NULL) { - return (-1); - } - to_np->key = MD_KEYWILD; - - if (MD_MNSET_DESC(sd)) { - nd = sd->sd_nodelist; - while (nd) { - side_key = add_name(sp, (side_t)nd->nd_nodeid, - to_np->key, cinfop->dname, - meta_getminor(to_np->dev), - to_np->bname, ep); - /* - * Break out if failed to add the key, - * but delete any name space records that - * were added. - */ - if (side_key == MD_KEYBAD || - side_key == MD_KEYWILD) { - /* - * If we have a valid to_np->key then - * a record was added correctly but - * we do not know for which side, so - * we need to try to delete all of them. - */ - - if (to_np->key != MD_KEYBAD && - to_np->key != MD_KEYWILD) { - nd_del = sd->sd_nodelist; - while ((nd_del != nd) && - (nd_del != NULL)) { - (void) del_name(sp, - (side_t)nd_del->nd_nodeid, - to_np->key, &dummy_ep); - nd_del = nd_del->nd_next; - } - /* preserve error key state */ - to_np->key = side_key; - } - break; - } - to_np->key = side_key; - nd = nd->nd_next; - } - } else { - for (i = 0; i < MD_MAXSIDES; i++) { - if (sd->sd_nodes[i][0] != '\0') { - side_key = add_name(sp, (side_t)i, - to_np->key, cinfop->dname, - meta_getminor(to_np->dev), - to_np->bname, ep); - /* - * Break out if failed to add the key, - * but delete any name space records - * that were added. - */ - if (side_key == MD_KEYBAD || - side_key == MD_KEYWILD) { - /* - * If we have a valid - * to_np->key then a record was - * added correctly but we do - * not know for which side, so - * we need to try to delete - * all of them. - */ - if (to_np->key != MD_KEYBAD && - to_np->key != MD_KEYWILD) { - for (j = 0; j < i; - j++) { - (void) del_name(sp, - (side_t)j, - to_np->key, - &dummy_ep); - } - /* - * preserve err - * key state - */ - to_np->key = side_key; - } - break; - } - to_np->key = side_key; - } - } - } - } - if (to_np->key == MD_KEYBAD || to_np->key == MD_KEYWILD) { assert(!mdisok(ep)); return (-1);
--- a/usr/src/lib/lvm/libmeta/common/meta_replace.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/lib/lvm/libmeta/common/meta_replace.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -33,45 +32,6 @@ #include <meta.h> #include <sys/lvm/md_stripe.h> -int -meta_replace(mdsetname_t *sp, mdname_t *metanp, mdname_t *oldnp, - mdname_t *newnp, char *uname, mdcmdopts_t options, md_error_t *ep) -{ - char *miscname; - - assert(sp != NULL); - - if (is_hspname(uname)) { - mdhspname_t *hspnp; - - if ((hspnp = metahspname(&sp, uname, ep)) == NULL) - return (-1); - assert(sp != NULL); - (void) meta_hs_replace(sp, hspnp, oldnp, newnp, options, ep); - return (0); - } - assert(sp->setno == MD_MIN2SET(meta_getminor(metanp->dev))); - if (metachkmeta(metanp, ep) != 0) - return (-1); - - - if ((miscname = metagetmiscname(metanp, ep)) == NULL) - return (-1); - - if (strcmp(miscname, MD_RAID) == 0) { - return (meta_raid_replace(sp, metanp, oldnp, newnp, - options, ep)); - } else if (strcmp(miscname, MD_TRANS) == 0) { - return (meta_trans_replace(sp, metanp, oldnp, newnp, - options, ep)); - } else if (strcmp(miscname, MD_STRIPE) == 0) { - return (meta_stripe_replace(sp, metanp, oldnp, newnp, - options, ep)); - } - - return (mdmderror(ep, MDE_UNKNOWN_TYPE, meta_getminor(metanp->dev), - metanp->cname)); -} /* * replace named device */
--- a/usr/src/lib/lvm/libmeta/common/meta_se_notify.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/lib/lvm/libmeta/common/meta_se_notify.c Tue Mar 14 14:53:36 2006 -0800 @@ -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. @@ -21,7 +20,7 @@ */ /* - * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -39,6 +38,7 @@ obj2devname(uint32_t tag, set_t setno, md_dev64_t dev) { char *setname; + char *uname; char name[MD_MAX_CTDLEN]; mdsetname_t *sp; md_error_t status = mdnullerror; @@ -60,22 +60,18 @@ case SVM_TAG_RAID5: case SVM_TAG_STRIPE: case SVM_TAG_TRANS: - if (setno == 0) { - rtn = snprintf(name, sizeof (name), "d%u", - (unsigned)MD_MIN2UNIT(mnum)); - } else if (setname != NULL) { - rtn = snprintf(name, sizeof (name), "%s/d%u", setname, - (unsigned)MD_MIN2UNIT(mnum)); - } + uname = get_mdname(sp, mnum); + if (uname == NULL) + return (NULL); + + (void) strcpy(name, uname); break; case SVM_TAG_HSP: - if (setno == 0) { - rtn = snprintf(name, sizeof (name), "hsp%u", - (unsigned)MD_MIN2UNIT(mnum)); - } else if (setname != NULL) { - rtn = snprintf(name, sizeof (name), "%s/hsp%u", - setname, (unsigned)MD_MIN2UNIT(mnum)); - } + uname = get_hspname(sp, mnum); + if (uname == NULL) + return (NULL); + + (void) strcpy(name, uname); break; case SVM_TAG_DRIVE: (void) sprintf(name, "drive");
--- a/usr/src/lib/lvm/libmeta/common/meta_set.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/lib/lvm/libmeta/common/meta_set.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -607,7 +606,7 @@ *ret_mnum = NODEV32; - if ((np = metaname(&sp, bname, ep)) == NULL) + if ((np = metaname(&sp, bname, LOGICAL_DEVICE, ep)) == NULL) return (-1); /* @@ -742,7 +741,7 @@ * Need to pass the node the devid of the disk and get it to * send back the details of the disk from that side. */ - if ((np = metaname(&sp, bname, ep)) == NULL) + if ((np = metaname(&sp, bname, UNKNOWN, ep)) == NULL) return (-1); dnp = np->drivenamep; @@ -1783,12 +1782,12 @@ /* get device name */ if (flags & PRINT_FAST) { - if ((np = metaname_fast(&sp, nm, ep)) == NULL) { + if ((np = metaname_fast(&sp, nm, LOGICAL_DEVICE, ep)) == NULL) { Free(nm); return (NULL); } } else { - if ((np = metaname(&sp, nm, ep)) == NULL) { + if ((np = metaname(&sp, nm, LOGICAL_DEVICE, ep)) == NULL) { Free(nm); return (NULL); }
--- a/usr/src/lib/lvm/libmeta/common/meta_set_prv.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/lib/lvm/libmeta/common/meta_set_prv.c Tue Mar 14 14:53:36 2006 -0800 @@ -149,7 +149,8 @@ */ if (strcmp(np->rname, rname) != 0) { /* different rname */ - remote_np = metaname_fast(&sp, rname, ep); + remote_np = metaname_fast(&sp, rname, + LOGICAL_DEVICE, ep); if (remote_np != NULL) { remote_dnp = remote_np->drivenamep; }
--- a/usr/src/lib/lvm/libmeta/common/meta_sp.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/lib/lvm/libmeta/common/meta_sp.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -777,8 +776,15 @@ /* check set pointer */ assert(sp != NULL); + /* + * Get a list of the soft partitions that currently reside on + * the component. We should ALWAYS force reload the cache, + * because if we're using the md.tab, we must rebuild + * the list because it won't contain the previous (if any) + * soft partition. + */ /* find all soft partitions on the component */ - count = meta_sp_get_by_component(sp, np, &spnlp, 0, ep); + count = meta_sp_get_by_component(sp, np, &spnlp, 1, ep); if (count == -1) { rval = -1; @@ -1841,6 +1847,15 @@ mdname_t *np = NULL; mdsetname_t *spsetp = NULL; sp_ext_offset_t cur_off; + md_set_desc *sd; + int init = 0; + mdkey_t key; + minor_t mnum; + + if (!metaislocalset(sp)) { + if ((sd = metaget_setdesc(sp, ep)) == NULL) + return (-1); + } if ((cur_off = meta_sp_get_start(sp, compnp, ep)) == MD_DISKADDR_ERROR) return (-1); @@ -1857,13 +1872,67 @@ } } + /* + * For the MN set, meta_init_make_device needs to + * be run on all the nodes so the entries for the + * softpart device name and its comp can be created + * in the same order in the replica namespace. If + * we have it run on mdmn_do_iocset then the mddbs + * will be out of sync between master node and slave + * nodes. + */ if (strcmp(wm.wm_mdname, MD_SP_FREEWMNAME) != 0) { - if (meta_init_make_device(&sp, wm.wm_mdname, ep) != 0) + + if (!metaislocalset(sp) && MD_MNSET_DESC(sd)) { + md_mn_msg_addmdname_t *send_params; + int result; + md_mn_result_t *resp = NULL; + int message_size; + + message_size = sizeof (*send_params) + + strlen(wm.wm_mdname) + 1; + send_params = Zalloc(message_size); + send_params->addmdname_setno = sp->setno; + (void) strcpy(&send_params->addmdname_name[0], + wm.wm_mdname); + result = mdmn_send_message(sp->setno, + MD_MN_MSG_ADDMDNAME, + MD_MSGF_PANIC_WHEN_INCONSISTENT, + (char *)send_params, message_size, &resp, + ep); + Free(send_params); + if (resp != NULL) { + if (resp->mmr_exitval != 0) { + free_result(resp); + return (-1); + } + free_result(resp); + } + if (result != 0) return (-1); - np = metaname(&spsetp, wm.wm_mdname, ep); - if (np == NULL) { - return (-1); + } else { + + if (!is_existing_meta_hsp(sp, wm.wm_mdname)) { + if ((key = meta_init_make_device(&sp, + wm.wm_mdname, ep)) <= 0) { + return (-1); + } + init = 1; } + } + + np = metaname(&spsetp, wm.wm_mdname, META_DEVICE, ep); + if (np == NULL) { + if (init) { + if (meta_getnmentbykey(sp->setno, MD_SIDEWILD, + key, NULL, &mnum, NULL, ep) != NULL) { + (void) metaioctl(MD_IOCREM_DEV, &mnum, + ep, NULL); + } + (void) del_self_name(sp, key, ep); + } + return (-1); + } } /* insert watermark into extent list */ @@ -1913,7 +1982,12 @@ int extn; if (options & PRINT_LARGEDEVICES) { - if (msp->common.revision != MD_64BIT_META_DEV) + if ((msp->common.revision & MD_64BIT_META_DEV) == 0) + return (0); + } + + if (options & PRINT_FN) { + if ((msp->common.revision & MD_FN_META_DEV) == 0) return (0); } @@ -1923,22 +1997,10 @@ /* print the component */ /* - * If the path is our standard /dev/rdsk or /dev/md/rdsk - * then just print out the cxtxdxsx or the dx, metainit - * will assume the default, otherwise we need the full - * pathname to make sure this works as we intend. + * Always print the full path name */ - if ((strstr(msp->compnamep->rname, "/dev/rdsk") == NULL) && - (strstr(msp->compnamep->rname, "/dev/md/rdsk") == NULL) && - (strstr(msp->compnamep->rname, "/dev/td/") == NULL)) { - /* not standard path so print full pathname */ - if (fprintf(fp, " %s", msp->compnamep->rname) == EOF) - return (mdsyserror(ep, errno, fname)); - } else { - /* standard path so print ctds or d number */ - if (fprintf(fp, " %s", msp->compnamep->cname) == EOF) - return (mdsyserror(ep, errno, fname)); - } + if (fprintf(fp, " %s", msp->compnamep->rname) == EOF) + return (mdsyserror(ep, errno, fname)); /* print out each extent */ for (extn = 0; (extn < msp->ext.ext_len); extn++) { @@ -2041,7 +2103,16 @@ uint_t tstate = 0; if (options & PRINT_LARGEDEVICES) { - if (msp->common.revision != MD_64BIT_META_DEV) { + if ((msp->common.revision & MD_64BIT_META_DEV) == 0) { + return (0); + } else { + if (meta_getdevs(sp, msp->common.namep, nlpp, ep) != 0) + return (-1); + } + } + + if (options & PRINT_FN) { + if ((msp->common.revision & MD_FN_META_DEV) == 0) { return (0); } else { if (meta_getdevs(sp, msp->common.namep, nlpp, ep) != 0) @@ -3704,7 +3775,7 @@ /* expect sp name, -p, optional -e, compname, and size parameters */ /* grab soft partition name */ - if ((np = metaname(spp, devname, ep)) == NULL) + if ((np = metaname(spp, devname, META_DEVICE, ep)) == NULL) goto out; /* see if it exists already */ @@ -3750,7 +3821,7 @@ if ((spcompnp = metaslicename(dnp, 0, ep)) == NULL) { goto out; } - } else if ((spcompnp = metaname(spp, compname, ep)) == NULL) { + } else if ((spcompnp = metaname(spp, compname, UNKNOWN, ep)) == NULL) { goto out; } assert(*spp != NULL); @@ -4347,10 +4418,10 @@ (void) memset(&set_params, 0, sizeof (set_params)); if (create_flag == MD_CRO_64BIT) { - mp->c.un_revision = MD_64BIT_META_DEV; + mp->c.un_revision |= MD_64BIT_META_DEV; set_params.options = MD_CRO_64BIT; } else { - mp->c.un_revision = MD_32BIT_META_DEV; + mp->c.un_revision &= ~MD_64BIT_META_DEV; set_params.options = MD_CRO_32BIT; } @@ -4730,7 +4801,7 @@ int count; md_sp_reset_t reset_params; - if ((compnp = metaname(&sp, name, ep)) == NULL) + if ((compnp = metaname(&sp, name, UNKNOWN, ep)) == NULL) return (-1); /* If we're starting out with no soft partitions, it's an error */ @@ -4959,10 +5030,10 @@ (void) memset(&grow_params, 0, sizeof (grow_params)); if (new_un->c.un_total_blocks > MD_MAX_BLKS_FOR_SMALL_DEVS) { grow_params.options = MD_CRO_64BIT; - new_un->c.un_revision = MD_64BIT_META_DEV; + new_un->c.un_revision |= MD_64BIT_META_DEV; } else { grow_params.options = MD_CRO_32BIT; - new_un->c.un_revision = MD_32BIT_META_DEV; + new_un->c.un_revision &= ~MD_64BIT_META_DEV; } grow_params.mnum = MD_SID(new_un); grow_params.size = new_un->c.un_size; @@ -5270,14 +5341,15 @@ newname[strlen(newname) - 1] = '\0'; if (!(is_metaname(newname)) || - (meta_init_make_device(&sp, newname, ep) != 0)) { + (meta_init_make_device(&sp, newname, ep) <= 0)) { (void) fprintf(stderr, dgettext(TEXT_DOMAIN, "Invalid metadevice name\n")); (void) fflush(stderr); continue; } - if ((*new_np = metaname(&sp, newname, ep)) == NULL) { + if ((*new_np = metaname(&sp, newname, + META_DEVICE, ep)) == NULL) { (void) fprintf(stderr, dgettext(TEXT_DOMAIN, "Invalid metadevice name\n")); (void) fflush(stderr); @@ -6092,9 +6164,9 @@ set_params.options = meta_check_devicesize(un_array[i]->un_length); if (set_params.options == MD_CRO_64BIT) { - un_array[i]->c.un_revision = MD_64BIT_META_DEV; + un_array[i]->c.un_revision |= MD_64BIT_META_DEV; } else { - un_array[i]->c.un_revision = MD_32BIT_META_DEV; + un_array[i]->c.un_revision &= ~MD_64BIT_META_DEV; } MD_SETDRIVERNAME(&set_params, MD_SP, MD_MIN2SET(set_params.mnum));
--- a/usr/src/lib/lvm/libmeta/common/meta_statconcise.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/lib/lvm/libmeta/common/meta_statconcise.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -1436,9 +1435,6 @@ case MDDB_F_HOTSPARE_POOL: /* * Ondisk and incore records are always same size. - * Also, hotspare pools will always be toplevel - * metadevices, so we don't need to store a - * hsp_self_id. */ hsp = (hot_spare_pool_ond_t *)((uintptr_t)rbp + (sizeof (mddb_rb_t) - sizeof (int))); @@ -1448,7 +1444,14 @@ bcopy(hsp, mdrec->record, newreqsize); hsp = (hot_spare_pool_ond_t *)mdrec->record; mdrec->dfunc = &process_hotspare_pool; - mdrec->un_self_id = NULL; + /* + * If the hsp has descriptive name we'll get + * the un_self_id + */ + if (HSP_ID_IS_FN(hsp->hsp_self_id)) + mdrec->un_self_id = hsp->hsp_self_id; + else + mdrec->un_self_id = NULL; mdrec->has_parent = 0; break; /* All valid cases have been dealt with */ @@ -1467,16 +1470,31 @@ nmname = (struct nm_name *)((char *)nmname + NAMSIZ(nmname))) { /* - * Matching the un_self_id for the record to the - * n_minor name in the NM record, to extract the - * metadevice name if it is in the namespace + * Extract the metadevice/hsp name if it is + * in the namespace. + * + * If it is a hot spare pool we will find our + * match by comparing the NM record's n_key + * with the extracted key from the hsp_self_id + * Else, match the un_self_id for the record + * to the n_minor name in the NM record. */ - if ((nmname->n_minor) == (uc.un_self_id)) { - (*mdrec).n_key = nmname->n_key; - uname = Strdup(nmname->n_name); - mdrec->n_name = uname; - break; - } + if (mdrec->md_type == MDDB_F_HOTSPARE_POOL) { + if (nmname->n_key == + HSP_ID_TO_KEY(hsp->hsp_self_id)) { + mdrec->n_key = nmname->n_key; + uname = Strdup(nmname->n_name); + mdrec->n_name = uname; + break; + } + } else { + if ((nmname->n_minor) == (uc.un_self_id)) { + (*mdrec).n_key = nmname->n_key; + uname = Strdup(nmname->n_name); + mdrec->n_name = uname; + break; + } + } } } @@ -1541,7 +1559,7 @@ mddb_rb32_t *rbp_32; mddb_rb_t *rbp_64; crc_skip_t *skip = NULL; - int is_32bit_record = 0; + int is_32bit_record; tmp_mdrec = Zalloc(sizeof (md_im_rec_t)); rbp = (void *)Zalloc(dbtob(dep->de_blkcount)); @@ -1596,9 +1614,16 @@ * revision for the current 64bit or 32bit record block. Also, * setting the flag for whether or not it is a 32bit record. */ - if (revchk(MDDB_REV_RB, rbp_32->rb_revision) == 0) { + is_32bit_record = 0; + switch (rbp_32->rb_revision) { + case MDDB_REV_RB: + case MDDB_REV_RBFN: is_32bit_record = 1; - } else if (revchk(MDDB_REV_RB64, rbp_32->rb_revision) != 0) { + break; + case MDDB_REV_RB64: + case MDDB_REV_RB64FN: + break; + default: rval = -1; (void) mdmddberror(ep, MDE_DB_NODB, 0, 0, 0, NULL); goto out;
--- a/usr/src/lib/lvm/libmeta/common/meta_stripe.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/lib/lvm/libmeta/common/meta_stripe.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -566,6 +565,13 @@ } } + if (options & PRINT_FN) { + if (stripep->common.revision != MD_FN_META_DEV) { + rval = 0; + goto out; + } + } + /* print name and num rows */ if (fprintf(fp, "%s %u", stripep->common.namep->cname, stripep->rows.rows_len) == EOF) @@ -580,32 +586,14 @@ if (fprintf(fp, " %u", rp->comps.comps_len) == EOF) goto out; - /* print components */ + /* + * Print components. Always print the full path name. + */ for (comp = 0; (comp < rp->comps.comps_len); ++comp) { md_comp_t *cp = &rp->comps.comps_val[comp]; - /* print component */ - /* - * If the path is our standard /dev/rdsk or /dev/md/rdsk - * then just print out the cxtxdxsx or the dx, metainit - * will assume the default, otherwise we need the full - * pathname to make sure this works as we intend. - */ - if ((strstr(cp->compnamep->rname, "/dev/rdsk") == - NULL) && (strstr(cp->compnamep->rname, - "/dev/md/rdsk") == NULL) && - (strstr(cp->compnamep->rname, "/dev/td/") == - NULL)) { - /* not standard path, print full pathname */ - if (fprintf(fp, " %s", cp->compnamep->rname) - == EOF) - goto out; - } else { - /* standard path */ - if (fprintf(fp, " %s", cp->compnamep->cname) - == EOF) - goto out; - } + if (fprintf(fp, " %s", cp->compnamep->rname) == EOF) + goto out; } /* print interlace */ @@ -998,7 +986,24 @@ * printing out the relocation information. */ if (options & PRINT_LARGEDEVICES) { - if (stripep->common.revision != MD_64BIT_META_DEV) { + if ((stripep->common.revision & MD_64BIT_META_DEV) == 0) { + rval = 0; + goto out; + } else { + if (meta_getdevs(sp, stripep->common.namep, + nlpp, ep) != 0) + goto out; + } + } + + /* + * if the -D option has been specified check to see if the + * metadevice has a descriptive name and print if so, also if a + * descriptive device name we need to store the ctd involved + * for use in printing out the relocation information. + */ + if (options & PRINT_FN) { + if ((stripep->common.revision & MD_FN_META_DEV) == 0) { rval = 0; goto out; } else { @@ -1493,10 +1498,10 @@ mgp.nrows = old_un->un_nrows; if (create_flag == MD_CRO_32BIT) { mgp.options = MD_CRO_32BIT; - new_un->c.un_revision = MD_32BIT_META_DEV; + new_un->c.un_revision &= ~MD_64BIT_META_DEV; } else { mgp.options = MD_CRO_64BIT; - new_un->c.un_revision = MD_64BIT_META_DEV; + new_un->c.un_revision |= MD_64BIT_META_DEV; } if ((MD_HAS_PARENT(old_un->c.un_parent)) && @@ -2096,10 +2101,10 @@ /* did the user tell us to generate a large device? */ if (create_flag == MD_CRO_64BIT) { - ms->c.un_revision = MD_64BIT_META_DEV; + ms->c.un_revision |= MD_64BIT_META_DEV; set_params.options = MD_CRO_64BIT; } else { - ms->c.un_revision = MD_32BIT_META_DEV; + ms->c.un_revision &= ~MD_64BIT_META_DEV; set_params.options = MD_CRO_32BIT; } @@ -2156,7 +2161,7 @@ if (argc < 1) goto syntax; - if ((stripenp = metaname(spp, uname, ep)) == NULL) + if ((stripenp = metaname(spp, uname, META_DEVICE, ep)) == NULL) goto out; assert(*spp != NULL); uname = stripenp->cname; @@ -2244,7 +2249,8 @@ meta_getminor(stripenp->dev), uname); goto out; } - if ((compnp = metaname(spp, argv[0], ep)) == NULL) { + if ((compnp = metaname(spp, argv[0], UNKNOWN, + ep)) == NULL) { goto out; } /* check for soft partition */
--- a/usr/src/lib/lvm/libmeta/common/meta_tab.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/lib/lvm/libmeta/common/meta_tab.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -137,7 +136,9 @@ */ static void parse_tab( - md_tab_t *tabp + md_tab_t *tabp, + char *metatab_name, + md_error_t *ep ) { uint_t lineno = 1; @@ -158,7 +159,7 @@ context = Malloc(len); /* parse lines */ - while (p < e) { + while (p < e && *p != '\0') { md_tab_line_t *linep; char *t; @@ -230,8 +231,12 @@ (! isspace(linep->argv[0][0]))); linep->context = Strdup(context); linep->type = meta_get_init_type(linep->argc, linep->argv); - linep->cname = Strdup(meta_canonicalize(NULL, linep->argv[0])); - assert(linep->cname != NULL); + linep->cname = meta_canonicalize(NULL, linep->argv[0]); + /* if cname is NULL then the meta/hsp name is invalid */ + if (linep->cname == NULL) { + (void) mderror(ep, MDE_SYNTAX, metatab_name); + break; + } } /* cleanup */ @@ -299,10 +304,11 @@ fd = -1; /* parse it up */ - parse_tab(tabp); + parse_tab(tabp, filename, ep); - /* return success */ - return (tabp); + /* return success if file was correctly parsed */ + if (mdisok(ep)) + return (tabp); /* cleanup, return error */ out: @@ -327,6 +333,10 @@ char *cname = meta_canonicalize(sp, name); size_t line; + /* if name is not legal meta name then return NULL */ + if (cname == NULL) + return (NULL); + for (line = 0; (line < tabp->nlines); ++line) { md_tab_line_t *linep = &tabp->lines[line];
--- a/usr/src/lib/lvm/libmeta/common/meta_trans.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/lib/lvm/libmeta/common/meta_trans.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -1106,8 +1105,8 @@ return (0); } - /* can't have a large trans */ - if (!(options & PRINT_LARGEDEVICES)) { + /* can't have a large trans or descriptive name trans */ + if (!(options & (PRINT_LARGEDEVICES | PRINT_FN))) { /* print appropriate detail */ if (options & PRINT_SHORT) { if (trans_print(transp, fname, fp, ep) != 0)
--- a/usr/src/lib/lvm/libmeta/common/metagetroot.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/lib/lvm/libmeta/common/metagetroot.c Tue Mar 14 14:53:36 2006 -0800 @@ -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. @@ -21,7 +20,7 @@ */ /* - * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -81,7 +80,7 @@ if ((curroot = meta_get_current_root(ep)) == NULL) return (NULL); - if ((rootnp = metaname(&sp, curroot, ep)) == NULL) + if ((rootnp = metaname(&sp, curroot, UNKNOWN, ep)) == NULL) return (NULL); if (metaismeta(rootnp)) { if ((miscname = metagetmiscname(rootnp, ep)) == NULL)
--- a/usr/src/lib/lvm/libmeta/spec/meta.spec Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/lib/lvm/libmeta/spec/meta.spec Tue Mar 14 14:53:36 2006 -0800 @@ -1,13 +1,12 @@ # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # 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. @@ -482,6 +481,10 @@ version SUNWprivate_1.1 end +function meta_gethspnmentbyid +version SUNWprivate_1.1 +end + function meta_get_hsp_common version SUNWprivate_1.1 end @@ -1158,6 +1161,14 @@ version SUNWprivate_1.1 end +function meta_is_all +version SUNWprivate_1.1 +end + +function meta_is_none +version SUNWprivate_1.1 +end + function is_hspname version SUNWprivate_1.1 end @@ -1166,6 +1177,14 @@ version SUNWprivate_1.1 end +function is_existing_metadevice +version SUNWprivate_1.1 +end + +function is_existing_hsp +version SUNWprivate_1.1 +end + function is_metaname version SUNWprivate_1.1 end @@ -1222,6 +1241,10 @@ version SUNWprivate_1.1 end +function metaflushmetanames +version SUNWprivate_1.1 +end + function metaflushnames version SUNWprivate_1.1 end @@ -1290,6 +1313,10 @@ version SUNWprivate_1.1 end +function meta_name_getname +version SUNWprivate_1.1 +end + function metaname version SUNWprivate_1.1 end @@ -1658,10 +1685,6 @@ version SUNWprivate_1.1 end -function meta_replace -version SUNWprivate_1.1 -end - function meta_replace_byname version SUNWprivate_1.1 end @@ -3713,3 +3736,11 @@ function read_master_block version SUNWprivate_1.1 end + +function add_self_name +version SUNWprivate_1.1 +end + +function del_self_name +version SUNWprivate_1.1 +end
--- a/usr/src/lib/lvm/libpreen/common/mdpreen.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/lib/lvm/libpreen/common/mdpreen.c Tue Mar 14 14:53:36 2006 -0800 @@ -236,7 +236,7 @@ /* * get list of underlying physical devices. */ - if ((namep = metaname(&sp, uname, ep)) == NULL) { + if ((namep = metaname(&sp, uname, UNKNOWN, ep)) == NULL) { ep_valid = 1; goto out; }
--- a/usr/src/lib/lvm/libsvm/common/metainterfaces.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/lib/lvm/libsvm/common/metainterfaces.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -346,7 +345,7 @@ debug_printf("get_mdcomponents(): Enter unit name %s\n", uname); - if (((namep = metaname(&sp, uname, ep)) == NULL) || + if (((namep = metaname(&sp, uname, META_DEVICE, ep)) == NULL) || (metachkmeta(namep, ep) != 0)) { debug_printf("get_mdcomponents(): " "metaname or metachkmeta failed\n");
--- a/usr/src/uts/common/io/lvm/hotspares/hotspares.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/uts/common/io/lvm/hotspares/hotspares.c Tue Mar 14 14:53:36 2006 -0800 @@ -88,21 +88,6 @@ return ((hot_spare_t *)NULL); } -static hot_spare_pool_t * -find_hot_spare_pool(set_t setno, int hsp_id) -{ - hot_spare_pool_t *hsp; - - hsp = (hot_spare_pool_t *)md_set[setno].s_hsp; - while (hsp != NULL) { - if (hsp->hsp_self_id == hsp_id) - return (hsp); - hsp = hsp->hsp_next; - } - - return ((hot_spare_pool_t *)0); -} - static int seths_create_hsp(set_hs_params_t *shs) @@ -129,11 +114,13 @@ shs->shs_hot_spare_pool)); #else recid = mddb_createrec(sizeof (hot_spare_pool_ond_t), typ1, - HSP_REC, MD_CRO_64BIT | MD_CRO_HOTSPARE_POOL, setno); + HSP_REC, MD_CRO_64BIT | MD_CRO_HOTSPARE_POOL | MD_CRO_FN, + setno); #endif } else { recid = mddb_createrec(sizeof (hot_spare_pool_ond_t), typ1, - HSP_REC, MD_CRO_32BIT | MD_CRO_HOTSPARE_POOL, setno); + HSP_REC, MD_CRO_32BIT | MD_CRO_HOTSPARE_POOL | MD_CRO_FN, + setno); } if (recid < 0) { @@ -150,6 +137,7 @@ hsp->hsp_next = (hot_spare_pool_t *)md_set[setno].s_hsp; hsp->hsp_refcount = 0; hsp->hsp_nhotspares = 0; + hsp->hsp_revision |= MD_FN_META_DEV; md_set[setno].s_hsp = (void *) hsp; @@ -176,6 +164,7 @@ hot_spare_pool_t *prev_hsp; hot_spare_pool_t *new_hsp; hot_spare_pool_t *old_hsp; + md_create_rec_option_t options; mddb_recid_t recid; mddb_recid_t recids[5]; size_t new_size; @@ -310,7 +299,8 @@ if (hsp == NULL) { /* create a hot spare pool record */ recid = mddb_createrec(sizeof (hot_spare_pool_ond_t), - typ1, HSP_REC, MD_CRO_32BIT | MD_CRO_HOTSPARE_POOL, setno); + typ1, HSP_REC, + MD_CRO_32BIT | MD_CRO_HOTSPARE_POOL | MD_CRO_FN, setno); if (recid < 0) { return (mdhsperror(&shs->mde, MDE_HSP_CREATE_FAILURE, @@ -326,6 +316,7 @@ hsp->hsp_next = (hot_spare_pool_t *)md_set[setno].s_hsp; hsp->hsp_refcount = 0; hsp->hsp_nhotspares = 0; + hsp->hsp_revision |= MD_FN_META_DEV; /* force prev_hsp to NULL, this will cause hsp to be linked */ prev_hsp = (hot_spare_pool_t *)0; @@ -356,8 +347,18 @@ */ new_size = sizeof (hot_spare_pool_ond_t) + (sizeof (mddb_recid_t) * hsp->hsp_nhotspares); - recid = mddb_createrec(new_size, typ1, HSP_REC, - MD_CRO_32BIT | MD_CRO_HOTSPARE_POOL, setno); + + /* + * The Friendly Name status of the new HSP should duplicate + * the status of the existing one. + */ + if (hsp->hsp_revision & MD_FN_META_DEV) { + options = + MD_CRO_32BIT | MD_CRO_HOTSPARE_POOL | MD_CRO_FN; + } else { + options = MD_CRO_32BIT | MD_CRO_HOTSPARE_POOL; + } + recid = mddb_createrec(new_size, typ1, HSP_REC, options, setno); if (recid < 0) { return (mdhsperror(&shs->mde, MDE_HSP_CREATE_FAILURE, @@ -395,9 +396,9 @@ } if (shs->shs_size_option & MD_CRO_64BIT) { - hs->hs_revision = MD_64BIT_META_DEV; + hs->hs_revision |= MD_64BIT_META_DEV; } else { - hs->hs_revision = MD_32BIT_META_DEV; + hs->hs_revision &= ~MD_64BIT_META_DEV; } /* lock the db records */ @@ -915,9 +916,9 @@ } if (shs->shs_size_option & MD_CRO_64BIT) { - new_hs->hs_revision = MD_64BIT_META_DEV; + new_hs->hs_revision |= MD_64BIT_META_DEV; } else { - new_hs->hs_revision = MD_32BIT_META_DEV; + new_hs->hs_revision &= ~MD_64BIT_META_DEV; } /* commit the db records */ @@ -1286,7 +1287,9 @@ dep = mddb_getrecdep(recid); dep->de_flags = MDDB_F_HOTSPARE; rbp = dep->de_rb; - if (rbp->rb_revision == MDDB_REV_RB) { + switch (rbp->rb_revision) { + case MDDB_REV_RB: + case MDDB_REV_RBFN: /* * Needs to convert to internal 64 bit */ @@ -1298,14 +1301,17 @@ dep->de_rb_userdata = b_hs; dep->de_reqsize = newreqsize; hs = b_hs; - } else { + break; + case MDDB_REV_RB64: + case MDDB_REV_RB64FN: hs = (hot_spare_t *)mddb_getrecaddr_resize (recid, sizeof (*hs), 0); + break; } - + NOTE_FN(rbp->rb_revision, hs->hs_revision); #if defined(_ILP32) - if (hs->hs_revision == MD_64BIT_META_DEV) { + if (hs->hs_revision & MD_64BIT_META_DEV) { char devname[MD_MAX_CTDLEN]; set_hot_spare_state(hs, HSS_BROKEN); @@ -1714,15 +1720,20 @@ dep = mddb_getrecdep(recid); rbp = dep->de_rb; - if (rbp->rb_revision == MDDB_REV_RB) { + switch (rbp->rb_revision) { + case MDDB_REV_RB: + case MDDB_REV_RBFN: /* * 32 bit hotspare */ hs32 = (hot_spare32_od_t *)mddb_getrecaddr(recid); hs_recid = &(hs32->hs_record_id); - } else { + break; + case MDDB_REV_RB64: + case MDDB_REV_RB64FN: hs64 = (hot_spare_t *)mddb_getrecaddr(recid); hs_recid = &(hs64->hs_record_id); + break; } /*
--- a/usr/src/uts/common/io/lvm/md/md.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/uts/common/io/lvm/md/md.c Tue Mar 14 14:53:36 2006 -0800 @@ -996,6 +996,8 @@ int size; int devid_flag; int retval; + uint_t un; + int un_next_set = 0; md_haltsnarf_enter(setno); @@ -1173,6 +1175,22 @@ } } while (i); + /* + * Set the first available slot and availability + */ + md_set[setno].s_un_avail = 0; + for (un = 0; un < MD_MAXUNITS; un++) { + if (md_set[setno].s_un[un] != NULL) { + continue; + } else { + if (!un_next_set) { + md_set[setno].s_un_next = un; + un_next_set = 1; + } + md_set[setno].s_un_avail++; + } + } + md_set_setstatus(setno, MD_SET_SNARFED); recid = mddb_makerecid(setno, 0); @@ -1884,3 +1902,54 @@ return (ENXIO); } + +/* + * Metadevice unit number dispatcher + * When this routine is called it will scan the + * incore unit array and return the avail slot + * hence the unit number to the caller + * + * Return -1 if there is nothing available + */ +unit_t +md_get_nextunit(set_t setno) +{ + unit_t un, start; + + /* + * If nothing available + */ + if (md_set[setno].s_un_avail == 0) { + return (MD_UNITBAD); + } + + mutex_enter(&md_mx); + start = un = md_set[setno].s_un_next; + + /* LINTED: E_CONSTANT_CONDITION */ + while (1) { + if (md_set[setno].s_un[un] == NULL) { + /* + * Advance the starting index for the next + * md_get_nextunit call + */ + if (un == MD_MAXUNITS - 1) { + md_set[setno].s_un_next = 0; + } else { + md_set[setno].s_un_next = un + 1; + } + break; + } + + un = ((un == MD_MAXUNITS - 1) ? 0 : un + 1); + + if (un == start) { + un = MD_UNITBAD; + break; + } + + } + + mutex_exit(&md_mx); + return (un); +}
--- a/usr/src/uts/common/io/lvm/md/md_ioctl.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/uts/common/io/lvm/md/md_ioctl.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -55,6 +54,7 @@ #include <sys/lvm/mdvar.h> #include <sys/lvm/md_rename.h> #include <sys/lvm/md_names.h> +#include <sys/lvm/md_hotspares.h> extern md_ops_t **md_ops; extern unit_t md_nunits; @@ -71,17 +71,22 @@ extern kmutex_t md_mx; extern kcondvar_t md_cv; +/* md_hotspares.c */ +extern hot_spare_pool_t *find_hot_spare_pool(set_t setno, int hsp_id); + /* md_med.c */ extern int med_addr_tab_nents; extern int med_get_t_size_ioctl(mddb_med_t_parm_t *tpp, int mode); extern int med_get_t_ioctl(mddb_med_t_parm_t *tpp, int mode); extern int med_set_t_ioctl(mddb_med_t_parm_t *tpp, int mode); +extern unit_t md_get_nextunit(set_t setno); static int md_mn_commd_present; /* md_mddb.c */ extern mddb_set_t *mddb_setenter(set_t setno, int flag, int *errorcodep); extern void mddb_setexit(mddb_set_t *s); +extern md_krwlock_t nm_lock; /* * md_mn_is_commd_present: @@ -185,8 +190,12 @@ } nm->key = md_setdevname(nm->setno, side, nm->key, nm->drvnm, - nm->mnum, name, 0); - if (((int)nm->key) < 0) { + nm->mnum, name, 0, &nm->mde); + /* + * If we got an error from md_setdevname & md_setdevname did not + * set the error code, we'll default to MDE_DB_NOSPACE. + */ + if ((((int)nm->key) < 0) && mdisok(&nm->mde)) { err = mdmddberror(&nm->mde, MDE_DB_NOSPACE, NODEV32, nm->setno); goto out; } @@ -205,6 +214,9 @@ char *name; side_t side; md_dev64_t dev = NODEV64; + mdc_unit_t *un; + uint_t id; + char *setname; int err = 0; mdclrerror(&nm->mde); @@ -215,7 +227,6 @@ if ((md_get_setstatus(nm->setno) & MD_SET_SNARFED) == 0) return (ENODEV); - name = kmem_alloc(MAXPATHLEN, KM_SLEEP); if (nm->side == -1) @@ -242,19 +253,61 @@ dev = md_makedevice(ddi_name_to_major(nm->drvnm), nm->mnum); } - err = md_getdevname(nm->setno, side, nm->key, dev, name, MAXPATHLEN); - if (err) { - if (err < 0) - err = EINVAL; - goto out; - } - - err = md_getnment(nm->setno, side, nm->key, dev, nm->drvnm, 16, - &nm->major, &nm->mnum, &nm->retkey); - if (err) { - if (err < 0) - err = EINVAL; - goto out; + + /* + * With the introduction of friendly names, all friendly named + * metadevices will have an entry in the name space. However, + * systems upgraded from pre-friendly name to a friendly name + * release won't have name space entries for pre-friendly name + * top level metadevices. + * + * So we search the name space for the our entry with either the + * given dev_t or key. If we can't find the entry, we'll try the + * un array to get information for our target metadevice. Note + * we only use the un array when searching by dev_t since a + * key implies an existing device which should have been + * found in the name space with the call md_getdevname. + */ + if (md_getdevname(nm->setno, side, nm->key, dev, name, + MAXPATHLEN) == 0) { + err = md_getnment(nm->setno, side, nm->key, dev, nm->drvnm, + sizeof (nm->drvnm), &nm->major, &nm->mnum, &nm->retkey); + if (err) { + if (err < 0) + err = EINVAL; + goto out; + } + } else { + if ((nm->key != MD_KEYWILD) || + (MD_UNIT(nm->mnum) == NULL)) { + err = ENOENT; + goto out; + } + + /* + * We're here because the mnum is of a pre-friendly + * name device. Make sure the major value is for + * metadevices. + */ + if (nm->major != md_major) { + err = ENOENT; + goto out; + } + + /* + * get the unit number and setname to construct the + * fully qualified name for the metadevice. + */ + un = MD_UNIT(nm->mnum); + id = MD_MIN2UNIT(un->un_self_id); + if (nm->setno != MD_LOCAL_SET) { + setname = mddb_getsetname(nm->setno); + (void) snprintf(name, MAXPATHLEN, + "/dev/md/%s/dsk/d%u", setname, id); + } else { + (void) snprintf(name, MAXPATHLEN, + "/dev/md/dsk/d%u", id); + } } err = ddi_copyout(name, (caddr_t)(uintptr_t)nm->devname, @@ -269,6 +322,193 @@ return (err); } +static int +gethspnm_ioctl( + mdhspnm_params_t *nm, + int mode +) +{ + char *name; + char *tmpname; + char *setname = NULL; + side_t side; + hot_spare_pool_t *hsp = NULL; + mdkey_t key = MD_KEYWILD; + int err = 0; + + mdclrerror(&nm->mde); + + if (md_snarf_db_set(MD_LOCAL_SET, &nm->mde) != 0) + return (0); + + if ((md_get_setstatus(nm->setno) & MD_SET_SNARFED) == 0) + return (ENODEV); + + name = kmem_zalloc(MAXPATHLEN, KM_SLEEP); + + if (nm->side == -1) + side = mddb_getsidenum(nm->setno); + else + side = nm->side; + + /* + * Get the key from input hspid, use different macros + * since the hspid could be either a FN or pre-FN hspid. + */ + if (nm->hspid != MD_HSPID_WILD) { + if (HSP_ID_IS_FN(nm->hspid)) + key = HSP_ID_TO_KEY(nm->hspid); + else + key = HSP_ID(nm->hspid); + } + + /* + * Get the input name if we're searching by hsp name. Check + * that the input name length is less than MAXPATHLEN. + */ + if ((nm->hspid == MD_HSPID_WILD) && + (nm->hspname_len <= MAXPATHLEN)) { + err = ddi_copyin((caddr_t)(uintptr_t)nm->hspname, + name, (sizeof (char)) * nm->hspname_len, mode); + + /* Stop if ddi_copyin failed. */ + if (err) { + err = EFAULT; + goto out; + } + } + + /* Must have either a valid hspid or a name to continue */ + if ((nm->hspid == MD_HSPID_WILD) && (name[0] == '\0')) { + err = EINVAL; + goto out; + } + + /* + * Try to find the hsp namespace entry corresponds to either + * the given hspid or name. If we can't find it, the hsp maybe + * a pre-friendly name hsp so we'll try to find it in the + * s_hsp array. + */ + if ((nm->hspid == MD_HSPID_WILD) || (HSP_ID_IS_FN(nm->hspid))) { + + if (md_gethspinfo(nm->setno, side, key, nm->drvnm, + &nm->ret_hspid, name) != 0) { + /* + * If we were given a key for a FN hsp and + * couldn't find its entry, simply errored + * out. + */ + if (HSP_ID_IS_FN(nm->hspid)) { + err = ENOENT; + goto out; + } + + /* + * Since md_gethspinfo failed and the hspid is + * not a FN hspid, we must have a name for a + * pre-FN hotspare pool + */ + if (name[0] == '\0') { + err = EINVAL; + goto out; + } + + tmpname = kmem_zalloc(MAXPATHLEN, KM_SLEEP); + if (nm->setno != MD_LOCAL_SET) + setname = mddb_getsetname(nm->setno); + + hsp = (hot_spare_pool_t *)md_set[nm->setno].s_hsp; + while (hsp != NULL) { + /* Only use the pre-friendly name hsp */ + if (!(hsp->hsp_revision & MD_FN_META_DEV)) { + + if (setname != NULL) { + (void) snprintf(tmpname, + MAXPATHLEN, + "%s/hsp%03u", setname, + HSP_ID(hsp->hsp_self_id)); + } else { + (void) snprintf(tmpname, + MAXPATHLEN, "hsp%03u", + HSP_ID(hsp->hsp_self_id)); + } + + if (strcmp(name, tmpname) == 0) + break; + } + + hsp = hsp->hsp_next; + } + kmem_free(tmpname, MAXPATHLEN); + + if (hsp == NULL) { + err = ENOENT; + goto out; + } + + /* Return hsp_self_id */ + nm->ret_hspid = hsp->hsp_self_id; + } + + } else { + /* + * We have a hspid for a pre-FN hotspare pool. Let's + * try to find the matching hsp using the given + * hspid. + */ + if (nm->hspid == MD_HSPID_WILD) { + err = ENOENT; + goto out; + } + + hsp = (hot_spare_pool_t *)md_set[nm->setno].s_hsp; + while (hsp != NULL) { + if (hsp->hsp_self_id == nm->hspid) + break; + hsp = hsp->hsp_next; + } + + if (hsp == NULL) { + err = ENOENT; + goto out; + } + + /* Prepare a name to return */ + if (nm->setno != MD_LOCAL_SET) + setname = mddb_getsetname(nm->setno); + + if (setname != NULL) { + (void) snprintf(name, MAXPATHLEN, "%s/hsp%03u", + setname, HSP_ID(hsp->hsp_self_id)); + } else { + (void) snprintf(name, MAXPATHLEN, "hsp%03u", + HSP_ID(hsp->hsp_self_id)); + } + + nm->ret_hspid = hsp->hsp_self_id; + } + + if (nm->hspid != MD_HSPID_WILD) { + if ((strlen(name) + 1) > nm->hspname_len) { + err = EINVAL; + goto out; + } + err = ddi_copyout(name, (caddr_t) + (uintptr_t)nm->hspname, strlen(name)+1, mode); + } + + if (err) { + if (err < 0) + err = EINVAL; + } + +out: + kmem_free(name, MAXPATHLEN); + return (err); +} + + /*ARGSUSED*/ static int update_loc_namespace_ioctl( @@ -1378,25 +1618,34 @@ mkdev_ioctl(md_mkdev_params_t *p) { set_t setno = p->md_driver.md_setno; + unit_t un; mdclrerror(&p->mde); + /* + * Get the next available unit number in this set + */ + un = md_get_nextunit(setno); + if (un == MD_UNITBAD) { + (void) mdmderror(&p->mde, MDE_UNIT_NOT_SETUP, un); + return (ENODEV); + } + /* Validate arguments passed in to ioctl */ if (setno >= MD_MAXSETS) { - (void) mdmderror(&p->mde, MDE_INVAL_UNIT, p->mnum); - return (EINVAL); - } - if (p->mnum >= MD_MAXUNITS) { - (void) mdmderror(&p->mde, MDE_INVAL_UNIT, p->mnum); + (void) mderror(&p->mde, MDE_NO_SET); return (EINVAL); } /* Create the device node */ - if (md_create_minor_node(setno, p->mnum)) { - (void) mdmderror(&p->mde, MDE_UNIT_NOT_SETUP, p->mnum); + if (md_create_minor_node(setno, un)) { + (void) mdmderror(&p->mde, MDE_UNIT_NOT_SETUP, un); return (ENODEV); } + /* Return the minor number */ + p->un = un; + return (0); } @@ -1782,6 +2031,33 @@ break; } + case MD_IOCGET_HSP_NM: + { + if (! (mode & FREAD)) + return (EACCES); + + sz = sizeof (mdhspnm_params_t); + d = kmem_alloc(sz, KM_SLEEP); + + if (ddi_copyin(data, d, sz, mode) != 0) { + err = EFAULT; + break; + } + + /* check data integrity */ + if (((mdhspnm_params_t *)d)->setno >= md_nsets) { + err = EINVAL; + break; + } + if (((mdhspnm_params_t *)d)->hspname == NULL) { + err = EINVAL; + break; + } + + err = gethspnm_ioctl((mdhspnm_params_t *)d, mode); + break; + } + case MD_IOCNXTKEY_NM: { if (! (mode & FREAD)) @@ -2960,6 +3236,42 @@ break; } + case MD_IOCREM_DEV: + { + set_t setno; + + if (! (mode & FWRITE)) + return (EACCES); + + sz = sizeof (minor_t); + + d = kmem_zalloc(sz, KM_SLEEP); + + if (ddi_copyin(data, d, sz, mode) != 0) { + err = EFAULT; + break; + } + + /* + * This ioctl is called to cleanup the device name + * space when metainit fails or -n is invoked + * In this case, reclaim the dispatched un slot + */ + setno = MD_MIN2SET(*(minor_t *)d); + if (md_set[setno].s_un_next <= 0) { + err = EFAULT; + break; + } else { + md_set[setno].s_un_next--; + } + + /* + * Attempt to remove the assocated device node + */ + (void) md_remove_minor_node(*(minor_t *)d); + break; + } + /* * Update md_mn_commd_present global to reflect presence or absence of * /usr/sbin/rpc.mdcommd. This allows us to determine if an RPC failure @@ -3030,6 +3342,7 @@ } kmem_free(d, sz); } + if (err) return (err); return (err_to_user); @@ -3166,7 +3479,7 @@ return (EINVAL); /* don't allow to create a vtoc for a big metadevice */ - if (un->c.un_revision == MD_64BIT_META_DEV) + if (un->c.un_revision & MD_64BIT_META_DEV) return (ENOTSUP); /* * Validate the partition table @@ -3589,3 +3902,25 @@ return (rval); } + + +/* + * Remove device node + */ +void +md_remove_minor_node(minor_t mnum) +{ + char name[16]; + extern dev_info_t *md_devinfo; + + /* + * Attempt release of its minor node + */ + (void) snprintf(name, sizeof (name), "%d,%d,blk", MD_MIN2SET(mnum), + MD_MIN2UNIT(mnum)); + ddi_remove_minor_node(md_devinfo, name); + + (void) snprintf(name, sizeof (name), "%d,%d,raw", MD_MIN2SET(mnum), + MD_MIN2UNIT(mnum)); + ddi_remove_minor_node(md_devinfo, name); +}
--- a/usr/src/uts/common/io/lvm/md/md_mddb.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/uts/common/io/lvm/md/md_mddb.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -250,7 +249,9 @@ ms_unit32_od_t *small_un; uint_t rb_off = offsetof(mddb_rb32_t, rb_data[0]); - if (revision == MDDB_REV_RB) { + switch (revision) { + case MDDB_REV_RB: + case MDDB_REV_RBFN: small_un = (ms_unit32_od_t *)un; skip_prev = &skip_start; @@ -279,7 +280,9 @@ skip_prev->skip_next = skip; skip_prev = skip; } - } else { + break; + case MDDB_REV_RB64: + case MDDB_REV_RB64FN: big_un = (ms_unit_t *)un; skip_prev = &skip_start; @@ -308,6 +311,7 @@ skip_prev->skip_next = skip; skip_prev = skip; } + break; } /* Return the start of the list of fields to skip */ return (skip_start.skip_next); @@ -332,12 +336,17 @@ skip_prev = &skip_start; skip = (crc_skip_t *)kmem_zalloc(sizeof (crc_skip_t), KM_SLEEP); - if (revision == MDDB_REV_RB) { + switch (revision) { + case MDDB_REV_RB: + case MDDB_REV_RBFN: skip->skip_offset = offsetof(mm_unit32_od_t, un_last_read) + rb_off; - } else { + break; + case MDDB_REV_RB64: + case MDDB_REV_RB64FN: skip->skip_offset = offsetof(mm_unit_t, un_last_read) + rb_off; + break; } skip->skip_size = sizeof (int); skip_prev->skip_next = skip; @@ -345,12 +354,17 @@ for (i = 0; i < NMIRROR; i++) { skip = (crc_skip_t *)kmem_zalloc(sizeof (crc_skip_t), KM_SLEEP); - if (revision == MDDB_REV_RB) { + switch (revision) { + case MDDB_REV_RB: + case MDDB_REV_RBFN: skip->skip_offset = offsetof(mm_unit32_od_t, un_sm[i].sm_timestamp) + rb_off; - } else { + break; + case MDDB_REV_RB64: + case MDDB_REV_RB64FN: skip->skip_offset = offsetof(mm_unit_t, un_sm[i].sm_timestamp) + rb_off; + break; } skip->skip_size = sizeof (md_timeval32_t); skip_prev->skip_next = skip; @@ -373,12 +387,17 @@ uint_t rb_off = offsetof(mddb_rb32_t, rb_data[0]); skip = (crc_skip_t *)kmem_zalloc(sizeof (crc_skip_t), KM_SLEEP); - if (revision == MDDB_REV_RB) { + switch (revision) { + case MDDB_REV_RB: + case MDDB_REV_RBFN: skip->skip_offset = offsetof(hot_spare32_od_t, hs_timestamp) + rb_off; - } else { + break; + case MDDB_REV_RB64: + case MDDB_REV_RB64FN: skip->skip_offset = offsetof(hot_spare_t, hs_timestamp) + rb_off; + break; } skip->skip_size = sizeof (md_timeval32_t); return (skip); @@ -1894,7 +1913,9 @@ return (MDDB_F_EFMT | MDDB_F_EDATA); } if ((revchk(MDDB_REV_RB, rbp->rb_revision) != 0) && - (revchk(MDDB_REV_RB64, rbp->rb_revision) != 0)) { + (revchk(MDDB_REV_RB64, rbp->rb_revision) != 0) && + (revchk(MDDB_REV_RBFN, rbp->rb_revision) != 0) && + (revchk(MDDB_REV_RB64FN, rbp->rb_revision) != 0)) { return (MDDB_F_EFMT | MDDB_F_EDATA); } /* Check crc for this record */ @@ -2312,7 +2333,8 @@ */ if (!(md_get_setstatus(setno) & MD_SET_IMPORT) && (type >= MDDB_FIRST_MODID) && - (rbp->rb_revision == MDDB_REV_RB)) { + ((rbp->rb_revision == MDDB_REV_RB) || + (rbp->rb_revision == MDDB_REV_RBFN))) { switch (dep->de_flags) { @@ -8859,9 +8881,15 @@ /* Do we have to create an old style (32 bit) record? */ if (options & MD_CRO_32BIT) { - rbp->rb_revision = MDDB_REV_RB; + if (options & MD_CRO_FN) + rbp->rb_revision = MDDB_REV_RBFN; + else + rbp->rb_revision = MDDB_REV_RB; } else { - rbp->rb_revision = MDDB_REV_RB64; + if (options & MD_CRO_FN) + rbp->rb_revision = MDDB_REV_RB64FN; + else + rbp->rb_revision = MDDB_REV_RB64; } /* set de_rb_userdata for non optimization records */ @@ -11971,6 +11999,14 @@ return (0); } +/* + * md_update_minor + * + * This function updates the minor in the namespace entry for an + * underlying metadevice. The function is called in mod_imp_set + * where mod is sp, stripe, mirror and raid. + * + */ int md_update_minor( set_t setno, @@ -12025,6 +12061,68 @@ return (retval); } +/* + * md_update_top_device_minor + * + * This function updates the minor in the namespace entry for a top + * level metadevice. The function is called in mod_imp_set where + * mod is sp, stripe, mirror and raid. + * + */ +int +md_update_top_device_minor( + set_t setno, + side_t side, + md_dev64_t dev +) +{ + struct nm_next_hdr *nh; + struct nm_name *n; + char *shn; + int retval = 1; + + /* + * Load the devid name space if it exists + */ + (void) md_load_namespace(setno, NULL, NM_DEVID); + if (! md_load_namespace(setno, NULL, 0L)) { + /* + * Unload the devid namespace + */ + (void) md_unload_namespace(setno, NM_DEVID); + return (0); + } + + rw_enter(&nm_lock.lock, RW_READER); + + if ((nh = get_first_record(setno, 0, NM_NOTSHARED)) == NULL) { + retval = 0; + goto out; + } + + /* + * Look up the key + */ + if ((n = lookup_entry(nh, setno, side, MD_KEYWILD, dev, 0L)) != NULL) { + /* + * Find the entry, update its n_minor if metadevice + */ + 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)); + } + } + +out: + rw_exit(&nm_lock.lock); + return (retval); +} + static void md_imp_nm( mddb_set_t *s @@ -12326,6 +12424,7 @@ md_drive_record *dr; size_t dr_size = sizeof (md_drive_record); mdkey_t dr_key; + md_error_t error = MDNULLERROR; if ((s = mddb_setenter(setno, MDDB_MUSTEXIST, &err)) == NULL) @@ -12356,7 +12455,7 @@ */ if ((dr_key = md_setdevname(MD_LOCAL_SET, 1, MD_KEYWILD, rip->ri_driver, md_getminor(rip->ri_dev), - rip->ri_devname, setno)) == 0) + rip->ri_devname, setno, &error)) == 0) continue; if (dr_key < 0) {
--- a/usr/src/uts/common/io/lvm/md/md_names.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/uts/common/io/lvm/md/md_names.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -50,6 +49,27 @@ void md_devid_cleanup(set_t, uint_t); extern md_krwlock_t nm_lock; +typedef enum lookup_dev_result { + LOOKUP_DEV_FOUND, /* Found a good record. */ + LOOKUP_DEV_NOMATCH, /* No matching record in DB. */ + LOOKUP_DEV_CONFLICT /* Name conflicts with existing record. */ +} lookup_dev_result_t; + +/* List of SVM module names. */ +static char *meta_names[] = { + "md", + MD_STRIPE, + MD_MIRROR, + MD_TRANS, + MD_HOTSPARES, + MD_RAID, + MD_VERIFY, + MD_SP, + MD_NOTIFY +}; + +#define META_NAME_COUNT (sizeof (meta_names) / sizeof (char *)) + /* * Used in translating from the md major name on miniroot to * md major name on target system. This is only needed during @@ -951,10 +971,18 @@ mdkey_t shn_key; ushort_t shn_namlen; - if (nm != (char *)0) + if (nm == (char *)0) { + /* No name. Search by key only. */ + if (key == MD_KEYBAD) { + /* No key either. Nothing to remove. */ + return (0); + } + } else { + /* How long is the name? */ nm_len = ((devid_nm & NM_DEVID) ? ddi_devid_sizeof((ddi_devid_t)nm) : (strlen(nm) + 1)); + } this_rh = ((devid_nm & NM_DEVID) ? &((struct devid_shr_rec *)record)->did_rec_hdr : @@ -1132,7 +1160,7 @@ if ((key == MD_KEYWILD) && !devid_nm && (dev == build_device_number(setno, - (struct nm_name *)n))) + (struct nm_name *)n))) return ((void *)n); } @@ -1162,7 +1190,29 @@ /*NOTREACHED*/ } -static struct nm_name * +static int +is_meta_drive(set_t setno, mdkey_t key) +{ + int i; + struct nm_next_hdr *nh; + struct nm_shared_name *shn; + + if ((nh = get_first_record(setno, 0, NM_SHARED)) == NULL) + return (FALSE); + if ((shn = (struct nm_shared_name *)lookup_shared_entry(nh, + key, NULL, NULL, NM_SHARED)) == NULL) { + return (FALSE); + } + + /* See if the name is a metadevice. */ + for (i = 0; i < META_NAME_COUNT; i++) { + if (strcmp(meta_names[i], shn->sn_name) == 0) + return (TRUE); + } + return (FALSE); +} + +static lookup_dev_result_t lookup_deventry( struct nm_next_hdr *nh, /* head record header */ set_t setno, /* set to lookup in */ @@ -1171,7 +1221,8 @@ char *drvnm, /* drvnm to be stored */ minor_t mnum, /* minor number to be stored */ char *dirnm, /* directory name to be stored */ - char *filenm /* device filename to be stored */ + char *filenm, /* device filename to be stored */ + struct nm_name **ret_rec /* place return found rec. */ ) { struct nm_next_hdr *this_nh = nh->nmn_nextp; @@ -1181,8 +1232,9 @@ size_t offset; mdkey_t dirkey, drvkey; + *ret_rec = NULL; if (this_nh == NULL) - return (0); + return (LOOKUP_DEV_NOMATCH); record = (struct nm_rec *)this_nh->nmn_record; this_rh = &record->r_rec_hdr; @@ -1191,11 +1243,16 @@ offset = sizeof (struct nm_rec) - sizeof (struct nm_name); if ((drvkey = getshared_key(setno, drvnm, 0L)) == MD_KEYBAD) - return (NULL); - - if ((dirkey = getshared_key(setno, dirnm, 0L)) == MD_KEYBAD) - return (NULL); - + return (LOOKUP_DEV_NOMATCH); + + if (dirnm == NULL) { + /* No directory name to look up. */ + dirkey = MD_KEYBAD; + } else { + /* Look up the directory name */ + if ((dirkey = getshared_key(setno, dirnm, 0L)) == MD_KEYBAD) + return (LOOKUP_DEV_NOMATCH); + } ASSERT(side != MD_SIDEWILD); /* code to see if EMPTY record */ @@ -1203,7 +1260,7 @@ /* Go to next record */ this_nh = this_nh->nmn_nextp; if (this_nh == NULL) - return (0); + return (LOOKUP_DEV_NOMATCH); record = (struct nm_rec *)this_nh->nmn_record; this_rh = &record->r_rec_hdr; n = &record->r_name[0]; @@ -1216,15 +1273,83 @@ (mnum == n->n_minor) && (drvkey == n->n_drv_key) && (dirkey == n->n_dir_key) && - (strcmp(filenm, n->n_name) == 0)) - return (n); - + (strcmp(filenm, n->n_name) == 0)) { + *ret_rec = n; + return (LOOKUP_DEV_FOUND); + } + + /* + * Now check for a name conflict. If the filenm of the + * current record matches filename passed in we have a + * potential conflict. If all the other parameters match + * except for the side number, then this is not a + * conflict. The reason is that there are cases where name + * record is added to each side of a set. + * + * There is one additional complication. It is only a + * conflict if the drvkeys both represent metadevices. It + * is legal for a metadevice and a physical device to have + * the same name. + */ + if (strcmp(filenm, n->n_name) == 0) { + int both_meta; + + /* + * It is hsp and we are trying to add it twice + */ + if (strcmp(getshared_name(setno, n->n_drv_key, 0L), + MD_HOTSPARES) == 0 && (side == n->n_side) && + find_hot_spare_pool(setno, + KEY_TO_HSP_ID(setno, n->n_key)) == NULL) { + /* + * All entries removed + */ + rw_exit(&nm_lock.lock); + (void) md_rem_hspname(setno, n->n_key); + rw_enter(&nm_lock.lock, RW_WRITER); + return (LOOKUP_DEV_NOMATCH); + } + + /* + * It is metadevice and we are trying to add it twice + */ + if (md_set[setno].s_un[MD_MIN2UNIT(n->n_minor)] + == NULL && (side == n->n_side) && + ddi_name_to_major(getshared_name(setno, + n->n_drv_key, 0L)) == md_major) { + /* + * Apparently it is invalid so + * clean it up + */ + (void) md_remove_minor_node(n->n_minor); + rw_exit(&nm_lock.lock); + (void) md_rem_selfname(n->n_minor); + rw_enter(&nm_lock.lock, RW_WRITER); + return (LOOKUP_DEV_NOMATCH); + } + + /* First see if the two drives are metadevices. */ + if (is_meta_drive(setno, drvkey) && + is_meta_drive(setno, n->n_drv_key)) { + both_meta = TRUE; + } else { + both_meta = FALSE; + } + /* Check rest of the parameters. */ + if ((both_meta == TRUE) && + ((key != n->n_key) || + (mnum != n->n_minor) || + (drvkey != n->n_drv_key) || + (dirkey != n->n_dir_key))) { + return (LOOKUP_DEV_CONFLICT); + } + } n = (struct nm_name *)get_next_entry(this_nh, (caddr_t)n, NAMSIZ(n), &offset); if (n == (struct nm_name *)0) { if (offset) - return (n); + return (LOOKUP_DEV_NOMATCH); /* Go to next record */ offset = sizeof (struct nm_rec) - @@ -1368,6 +1493,129 @@ /*NOTREACHED*/ } + +/* + * lookup_hspentry - Getting a hotspare pool entry from the namespace. + * Use either the NM key or the hotspare name to find + * a matching record in the namespace of the set. + */ +void * +lookup_hspentry( + 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 */ + char *name /* (alt. key 2), if key == MD_KEYWILD */ +) +{ + struct nm_next_hdr *this_nh = nh->nmn_nextp; + struct nm_rec *record; + struct nm_rec_hdr *this_rh; + struct nm_name *n; + size_t offset, n_offset, n_size; + side_t n_side; + mdkey_t n_key; + char *drv_name; + char *tmpname; + char *setname = NULL; + + if ((key == MD_KEYWILD) && (name == '\0')) + return ((void *)0); + + if (this_nh == NULL) + return ((void *)0); + + record = (struct nm_rec *)this_nh->nmn_record; + + this_rh = &record->r_rec_hdr; + + if (setno != MD_LOCAL_SET) { + setname = mddb_getsetname(setno); + if (setname == NULL) + return ((void *)0); + } + + /* code to see if EMPTY record */ + while (this_nh && this_rh->r_used_size == sizeof (struct nm_rec_hdr)) { + /* Go to next record */ + this_nh = this_nh->nmn_nextp; + if (this_nh == NULL) + return ((void *)0); + record = this_nh->nmn_record; + this_rh = &record->r_rec_hdr; + } + + /* + * n_offset will be used to reset offset + */ + n_offset = offset = (sizeof (struct nm_rec) - sizeof (struct nm_name)); + + n = ((struct nm_name *)&record->r_name[0]); + + tmpname = kmem_zalloc(MAXPATHLEN, KM_SLEEP); + + /*CONSTCOND*/ + while (1) { + n_side = n->n_side; + n_size = NAMSIZ(n); + if ((drv_name = (char *)getshared_name(setno, + n->n_drv_key, 0L)) != NULL) { + + /* We're only interested in hsp NM records */ + if ((strcmp(drv_name, "md_hotspares") == 0) && + ((side == n_side) || (side == MD_SIDEWILD))) { + n_key = n->n_key; + + if ((key != MD_KEYWILD) && (key == n_key)) + goto done; + + /* + * Searching by a hotspare pool name. + * Since the input name is of the form + * setname/hsp_name, we need to attach + * the string 'setname/' in front of the + * n->n_name. + */ + if (key == MD_KEYWILD) { + if (setname != NULL) + (void) snprintf(tmpname, MAXPATHLEN, + "%s/%s", setname, + ((struct nm_name *)n)->n_name); + else + (void) snprintf(tmpname, MAXPATHLEN, + "%s", + ((struct nm_name *)n)->n_name); + + if ((strcmp(name, tmpname)) == 0) + goto done; + } + } + } + + n = (struct nm_name *)get_next_entry(this_nh, (caddr_t)n, + n_size, &offset); + + if (n == NULL) { + /* + * No next record, return + */ + if (offset) + goto done; + + /* Go to next record */ + offset = n_offset; + this_nh = this_nh->nmn_nextp; + record = (struct nm_rec *)this_nh->nmn_record; + this_rh = &record->r_rec_hdr; + n = ((struct nm_name *)&record->r_name[0]); + } + } + +done: + kmem_free(tmpname, MAXPATHLEN); + return ((void *)n); +} + static int md_make_devname(struct nm_name *n, set_t setno, char *string, size_t max_size) { @@ -1484,7 +1732,8 @@ char *drvnm, /* store this driver name with devicename */ minor_t mnum, /* store this minor number as well */ char *devname, /* device name to be stored */ - set_t imp_setno /* used exclusively by import */ + set_t imp_setno, /* used exclusively by import */ + md_error_t *ep /* place to return error info */ ) { struct nm_next_hdr *nh, *did_nh = NULL; @@ -1500,6 +1749,7 @@ dev_t devt; char *mname = NULL; side_t thisside = MD_SIDEWILD; + lookup_dev_result_t lookup_res; mdkey_t min_devid_key = MD_KEYWILD; size_t min_len; @@ -1602,23 +1852,29 @@ /* find boundary between filename and directory */ cp = strrchr(devname, '/'); - ASSERT(cp != NULL); - - /* Isolate the directory name only; save character after '/' */ - c = *(cp + 1); - *(cp + 1) = '\0'; - dname = md_strdup(devname); - - /* Restore character after '/' */ - *(cp + 1) = c; - fname = cp+1; + + if (cp == NULL) { + /* No directory part to the name. */ + fname = devname; + dname = NULL; + } else { + /* Isolate the directory name only; save character after '/' */ + c = *(cp + 1); + *(cp + 1) = '\0'; + dname = md_strdup(devname); + + /* Restore character after '/' */ + *(cp + 1) = c; + fname = cp+1; + } /* * If it already there in the name space */ - if ((n = lookup_deventry(nh, setno, side, key, - drvnm, mnum, dname, fname)) != NULL) { - + lookup_res = lookup_deventry(nh, setno, side, key, drvnm, mnum, dname, + fname, &n); + switch (lookup_res) { + case LOOKUP_DEV_FOUND: /* If we are importing the set */ if (md_get_setstatus(imp_setno) & MD_SET_IMPORT) { retval = 0; @@ -1654,73 +1910,96 @@ } } goto out; - } - - /* Create a new name entry */ - new = 1; - n = (struct nm_name *)alloc_entry(nh, md_set[setno].s_nmid, - strlen(fname)+1, NM_NOTSHARED, &recids[0]); - - if (n == NULL) + + case LOOKUP_DEV_CONFLICT: + (void) mderror(ep, MDE_NAME_IN_USE); + retval = MD_KEYBAD; goto out; - n->n_minor = mnum; - n->n_side = side; - n->n_key = ((key == MD_KEYWILD) ? create_key(nh) : key); - n->n_count = 1; - - /* fill-in filename */ - (void) strcpy(n->n_name, fname); - n->n_namlen = (ushort_t)(strlen(fname) + 1); - - /* - * If MDE_DB_NOSPACE occurs - */ - if (((n->n_drv_key = - setshared_name(setno, drvnm, MD_KEYWILD, 0L)) == MD_KEYBAD) || - ((n->n_dir_key = - setshared_name(setno, dname, MD_KEYWILD, 0L)) == MD_KEYBAD)) { - /* - * Remove entry allocated by alloc_entry - * and return MD_KEYBAD - */ - (void) remove_entry(nh, n->n_side, n->n_key, 0L); - goto out; - } - - recids[1] = md_set[setno].s_nmid; - recids[2] = 0; - mddb_commitrecs_wrapper(recids); - retval = n->n_key; - - /* - * Now to find out if devid's were used for thisside and if - * so what is the devid_key for the entry so that the correct - * minor name entry (did_n) has the correct devid key. - * Also get the minor name of the device, use the minor name - * on this side because the assumption is that the slices are - * going to be consistant across the nodes. - */ - if (key != MD_KEYWILD && (shared & NM_DEVID)) { - if ((did_n = (struct did_min_name *) - lookup_entry(did_nh, setno, thisside, n->n_key, - NODEV64, NM_DEVID)) == NULL) { - shared &= ~NM_DEVID; - } else { - min_devid_key = did_n->min_devid_key; - min_len = (size_t)did_n->min_namlen; - } - } else { + case LOOKUP_DEV_NOMATCH: + /* Create a new name entry */ + new = 1; + n = (struct nm_name *)alloc_entry(nh, md_set[setno].s_nmid, + strlen(fname)+1, NM_NOTSHARED, &recids[0]); + + if (n == NULL) + goto out; + + n->n_minor = mnum; + n->n_side = side; + n->n_key = ((key == MD_KEYWILD) ? create_key(nh) : key); + n->n_count = 1; + + /* fill-in filename */ + (void) strcpy(n->n_name, fname); + n->n_namlen = (ushort_t)(strlen(fname) + 1); /* - * It is possible for the minor name to be null, for - * example a metadevice which means the minor name is - * not initialised. + * If MDE_DB_NOSPACE occurs */ - if (mname == NULL) + if (((n->n_drv_key = + setshared_name(setno, drvnm, MD_KEYWILD, 0L)) == + MD_KEYBAD)) { + /* + * Remove entry allocated by alloc_entry + * and return MD_KEYBAD + */ + (void) remove_entry(nh, n->n_side, n->n_key, 0L); goto out; - - min_len = strlen(mname) + 1; + } + if (dname == NULL) { + /* No directory name implies no key. */ + n->n_dir_key = MD_KEYBAD; + } else { + /* We have a directory name to save. */ + if ((n->n_dir_key = + setshared_name(setno, dname, MD_KEYWILD, 0L)) == + MD_KEYBAD) { + /* + * Remove entry allocated by alloc_entry + * and return MD_KEYBAD + */ + (void) remove_entry(nh, n->n_side, n->n_key, + 0L); + goto out; + } + } + + recids[1] = md_set[setno].s_nmid; + recids[2] = 0; + mddb_commitrecs_wrapper(recids); + retval = n->n_key; + + /* + * Now to find out if devid's were used for thisside and if + * so what is the devid_key for the entry so that the correct + * minor name entry (did_n) has the correct devid key. + * Also get the minor name of the device, use the minor name + * on this side because the assumption is that the slices are + * going to be consistant across the nodes. + */ + if (key != MD_KEYWILD && (shared & NM_DEVID)) { + if ((did_n = (struct did_min_name *) + lookup_entry(did_nh, setno, thisside, n->n_key, + NODEV64, NM_DEVID)) == NULL) { + shared &= ~NM_DEVID; + } else { + min_devid_key = did_n->min_devid_key; + min_len = (size_t)did_n->min_namlen; + } + } else { + + /* + * It is possible for the minor name to be null, for + * example a metadevice which means the minor name is + * not initialised. + */ + if (mname == NULL) + goto out; + + min_len = strlen(mname) + 1; + } + break; } /* @@ -2104,6 +2383,91 @@ } /* + * md_gethspinfo - Getting a hsp name or id from the database. + * A pointer to a character array is passed in for + * the hsp name to be built in. If a match is found, + * the corresponding hspid is stored in ret_hspid. + */ +int +md_gethspinfo( + set_t setno, /* which set to get name from */ + side_t side, /* (key 1) side number */ + mdkey_t key, /* (key 2) key provided by md_setdevname() */ + char *drvnm, /* return driver name here */ + hsp_t *ret_hspid, /* returned key if key is MD_KEYWILD */ + char *hspname /* alternate key or returned device name */ +) +{ + struct nm_next_hdr *nh; + struct nm_name *n; + char *drv_name; + int err = 0; + char *setname = NULL; + + /* + * Load the devid name space if it exists + */ + (void) md_load_namespace(setno, NULL, NM_DEVID); + if (! md_load_namespace(setno, NULL, 0L)) { + /* + * Unload the devid namespace + */ + (void) md_unload_namespace(setno, NM_DEVID); + return (ENOENT); + } + + rw_enter(&nm_lock.lock, RW_READER); + + if ((nh = get_first_record(setno, 0, NM_NOTSHARED)) == NULL) { + rw_exit(&nm_lock.lock); + return (ENOENT); + } + + if ((n = (struct nm_name *)lookup_hspentry(nh, setno, side, + key, hspname)) == NULL) { + rw_exit(&nm_lock.lock); + return (ENOENT); + } + + /* Copy the driver name, device name and key for return */ + drv_name = (char *)getshared_name(setno, n->n_drv_key, 0L); + if (!drv_name || (strlen(drv_name) > MD_MAXDRVNM)) { + rw_exit(&nm_lock.lock); + return (EFAULT); + } + + /* + * Pre-friendly hsp names are of the form hspxxx and we + * should not have an entry in the namespace for them. + * So make sure the NM entry we get is a hotspare pool. + */ + if ((strcmp(drv_name, "md_hotspares")) != 0) { + rw_exit(&nm_lock.lock); + return (ENOENT); + } + (void) strcpy(drvnm, drv_name); + + /* + * If the input key is not MD_KEYWILD, return the + * hspname we found. + */ + if (key != MD_KEYWILD) { + setname = mddb_getsetname(setno); + if (setname != NULL) + (void) snprintf(hspname, MAXPATHLEN, + "%s/%s", setname, n->n_name); + else + (void) snprintf(hspname, MAXPATHLEN, + "%s", n->n_name); + } + + *ret_hspid = KEY_TO_HSP_ID(setno, n->n_key); + + rw_exit(&nm_lock.lock); + return (err); +} + +/* * md_devid_found - Check to see if this key has devid entry or not * Return 1 if there is one or 0 if none */
--- a/usr/src/uts/common/io/lvm/md/md_rename.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/uts/common/io/lvm/md/md_rename.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 1996-2002 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -738,6 +737,8 @@ { minor_t from_min, to_min; sv_dev_t sv; + mddb_de_ic_t *dep; + mddb_rb32_t *rbp; ASSERT(rtxnp); ASSERT(rtxnp->op == MDRNOP_RENAME); @@ -756,8 +757,21 @@ /* * self id changes in our own unit struct */ + MD_SID(delta->unp) = to_min; - MD_SID(delta->unp) = to_min; + /* + * make sure that dest always has correct un_revision + * and rb_revision + */ + delta->unp->c.un_revision |= MD_FN_META_DEV; + dep = mddb_getrecdep(MD_RECID(delta->unp)); + ASSERT(dep); + rbp = dep->de_rb; + if (rbp->rb_revision & MDDB_REV_RB) { + rbp->rb_revision = MDDB_REV_RBFN; + } else if (rbp->rb_revision & MDDB_REV_RB64) { + rbp->rb_revision = MDDB_REV_RB64FN; + } /* * clear old array pointers to unit in-core and unit @@ -798,6 +812,11 @@ md_rem_names(&sv, 1); /* + * Remove associated device node as well + */ + (void) md_remove_minor_node(from_min); + + /* * and store the record id (from the unit struct) into recids * for later commitment by md_rename() */ @@ -1644,14 +1663,38 @@ IOLOCK *iolockp) { md_rendelta_t *family = NULL; - md_rentxn_t rtxn; - int err = 0; - set_t setno; + md_rentxn_t rtxn; + int err = 0; + set_t setno; + mdc_unit_t *mdc; ASSERT(iolockp); if (mrp == NULL) return (EINVAL); + setno = MD_MIN2SET(mrp->from.mnum); + if (setno >= md_nsets) { + return (EINVAL); + } + + /* + * Early exit if top is eof trans + */ + mdc = (mdc_unit_t *)md_set[setno].s_un[MD_MIN2UNIT(mrp->from.mnum)]; + while (mdc != NULL) { + if (!MD_HAS_PARENT(mdc->un_parent)) { + break; + } else { + mdc = (mdc_unit_t *)md_set[setno].s_un[MD_MIN2UNIT + (mdc->un_parent)]; + } + } + + if (mdc && mdc->un_type == MD_METATRANS) { + return (EINVAL); + } + + mdclrerror(&mrp->mde); bzero((void *) &rtxn, sizeof (md_rentxn_t)); @@ -1668,13 +1711,6 @@ rtxn.uflags = mrp->flags; rtxn.revision = mrp->revision; - - setno = MD_MIN2SET(rtxn.from.mnum); - if (setno >= md_nsets) { - err = EINVAL; - goto cleanup; - } - if (MD_MIN2UNIT(mrp->to.mnum) >= md_nunits) { err = EINVAL; goto cleanup;
--- a/usr/src/uts/common/io/lvm/md/md_subr.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/uts/common/io/lvm/md/md_subr.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -54,6 +53,7 @@ #include <sys/errno.h> #include <sys/door.h> #include <sys/lvm/mdmn_commd.h> +#include <sys/lvm/md_hotspares.h> #include <sys/lvm/mdvar.h> #include <sys/lvm/md_names.h> @@ -109,6 +109,9 @@ extern mddb_set_t *mddb_setenter(set_t setno, int flag, int *errorcodep); extern void mddb_setexit(mddb_set_t *s); +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); struct mdq_anchor md_done_daemon; /* done request queue */ struct mdq_anchor md_mstr_daemon; /* mirror timeout requests */ @@ -2837,7 +2840,7 @@ } /* setup the unavailable field */ #if defined(_ILP32) - if (((md_unit_t *)MD_UNIT(mnum))->c.un_revision == MD_64BIT_META_DEV) { + if (((md_unit_t *)MD_UNIT(mnum))->c.un_revision & MD_64BIT_META_DEV) { ui->ui_tstate |= MD_64MD_ON_32KERNEL; cmn_err(CE_NOTE, "d%d is unavailable because 64 bit " "metadevices are not accessible on a 32 bit kernel", @@ -2952,22 +2955,69 @@ minor_t mnum ) { - static char buf[MD_MAX_SIDENAME_LEN]; + static char buf[MAXPATHLEN]; + char *devname; + char *invalid = " (Invalid minor number %u) "; + char *metaname; + mdc_unit_t *un; + side_t side; set_t setno = MD_MIN2SET(mnum); unit_t unit = MD_MIN2UNIT(mnum); - if ((setno >= md_nsets) || (unit >= md_nunits)) { - (void) snprintf(buf, 40, " (Invalid minor number %u) ", mnum); + if ((un = MD_UNIT(mnum)) == NULL) { + (void) snprintf(buf, sizeof (buf), invalid, mnum); + return (buf); + } + + /* + * If unit is not a friendly name unit, derive the name from the + * minor number. + */ + if ((un->un_revision & MD_FN_META_DEV) == 0) { + /* This is a traditional metadevice */ + if (setno == MD_LOCAL_SET) { + (void) snprintf(buf, sizeof (buf), "d%u", + (unsigned)unit); + } else { + (void) snprintf(buf, sizeof (buf), "%s/d%u", + mddb_getsetname(setno), (unsigned)unit); + } return (buf); } - if (setno == 0) { - (void) sprintf(buf, "d%u", (unsigned)unit); + /* + * It is a friendly name metadevice, so we need to get its name. + */ + side = mddb_getsidenum(setno); + devname = (char *)kmem_alloc(MAXPATHLEN, KM_SLEEP); + if (md_getdevname(setno, side, MD_KEYWILD, + md_makedevice(md_major, mnum), devname, MAXPATHLEN) == 0) { + /* + * md_getdevname has given us either /dev/md/dsk/<metaname> + * or /dev/md/<setname>/dsk/<metname> depending on whether + * or not we are in the local set. Thus, we'll pull the + * metaname from this string. + */ + if ((metaname = strrchr(devname, '/')) == NULL) { + (void) snprintf(buf, sizeof (buf), invalid, mnum); + goto out; + } + metaname++; /* move past slash */ + if (setno == MD_LOCAL_SET) { + /* No set name. */ + (void) snprintf(buf, sizeof (buf), "%s", metaname); + } else { + /* Include setname */ + (void) snprintf(buf, sizeof (buf), "%s/%s", + mddb_getsetname(setno), metaname); + } } else { - (void) sprintf(buf, "%s/d%u", - mddb_getsetname(setno), (unsigned)unit); + /* We couldn't find the name. */ + (void) snprintf(buf, sizeof (buf), invalid, mnum); } +out: + kmem_free(devname, MAXPATHLEN); return (buf); } @@ -4036,3 +4086,82 @@ mutex_exit(cp->cc_lockp); return (ret != -1); } + + +void +md_rem_hspname(set_t setno, mdkey_t n_key) +{ + int s; + int max_sides; + + + /* All entries removed are in the same diskset */ + if (md_get_setstatus(setno) & MD_SET_MNSET) + max_sides = MD_MNMAXSIDES; + else + max_sides = MD_MAXSIDES; + + for (s = 0; s < max_sides; s++) + (void) md_remdevname(setno, s, n_key); +} + + +int +md_rem_selfname(minor_t selfid) +{ + int s; + set_t setno = MD_MIN2SET(selfid); + int max_sides; + md_dev64_t dev; + struct nm_next_hdr *nh; + struct nm_name *n; + mdkey_t key; + + /* + * Get the key since remove routine expects it + */ + dev = md_makedevice(md_major, selfid); + if ((nh = get_first_record(setno, 0, NM_NOTSHARED)) == NULL) { + return (ENOENT); + } + + if ((n = (struct nm_name *)lookup_entry(nh, setno, MD_SIDEWILD, + MD_KEYWILD, dev, 0L)) == NULL) { + return (ENOENT); + } + + /* All entries removed are in the same diskset */ + key = n->n_key; + if (md_get_setstatus(setno) & MD_SET_MNSET) + max_sides = MD_MNMAXSIDES; + else + max_sides = MD_MAXSIDES; + + for (s = 0; s < max_sides; s++) + (void) md_remdevname(setno, s, key); + + return (0); +} + +void +md_upd_set_unnext(set_t setno, unit_t un) +{ + if (un < md_set[setno].s_un_next) { + md_set[setno].s_un_next = un; + } +} + +struct hot_spare_pool * +find_hot_spare_pool(set_t setno, int hsp_id) +{ + hot_spare_pool_t *hsp; + + hsp = (hot_spare_pool_t *)md_set[setno].s_hsp; + while (hsp != NULL) { + if (hsp->hsp_self_id == hsp_id) + return (hsp); + hsp = hsp->hsp_next; + } + + return ((hot_spare_pool_t *)0); +}
--- a/usr/src/uts/common/io/lvm/mirror/mirror.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/uts/common/io/lvm/mirror/mirror.c Tue Mar 14 14:53:36 2006 -0800 @@ -49,6 +49,7 @@ #include <sys/debug.h> #include <sys/dklabel.h> #include <vm/hat.h> +#include <sys/lvm/mdvar.h> #include <sys/lvm/md_mirror.h> #include <sys/lvm/md_convert.h> #include <sys/lvm/md_mddb.h> @@ -1971,6 +1972,11 @@ MD_UNIT(mnum) = NULL; + /* + * Attempt release of its minor node + */ + (void) md_remove_minor_node(mnum); + if (!removing) return; @@ -2007,6 +2013,14 @@ cv_destroy(&un->un_rs_progress_cv); mutex_destroy(&un->un_dmr_mx); cv_destroy(&un->un_dmr_cv); + + /* + * Remove self from the namespace + */ + if (un->c.un_revision & MD_FN_META_DEV) { + (void) md_rem_selfname(un->c.un_self_id); + } + mddb_deleterec_wrapper(un->c.un_record_id); if (recid != 0) mddb_deleterec_wrapper(recid); @@ -4348,7 +4362,6 @@ mm_unit_t *un; mm_submirror_t *sm; char *sm_nm; - size_t namelen; uint_t next_side; void *kbuffer; @@ -4468,8 +4481,7 @@ sm = &un->un_sm[un->un_dmr_last_read]; sm_nm = md_shortname(md_getminor(sm->sm_dev)); - namelen = MIN(MD_MAX_SIDENAME_LEN, VOL_SIDENAME); - (void) strncpy(vdr->vdr_side_name, sm_nm, namelen); + (void) strncpy(vdr->vdr_side_name, sm_nm, sizeof (vdr->vdr_side_name)); /* * Determine if we've completed the read cycle. This is true iff the @@ -4996,43 +5008,55 @@ dep->de_flags = MDDB_F_MIRROR; rbp = dep->de_rb; - if ((rbp->rb_revision == MDDB_REV_RB) && - ((rbp->rb_private & MD_PRV_CONVD) == 0)) { - /* - * This means, we have an old and small record - * and this record hasn't already been converted. - * Before we create an incore metadevice from this - * we have to convert it to a big record. - */ - small_un = (mm_unit32_od_t *)mddb_getrecaddr(recid); - newreqsize = sizeof (mm_unit_t); - big_un = (mm_unit_t *)kmem_zalloc(newreqsize, KM_SLEEP); - mirror_convert((caddr_t)small_un, (caddr_t)big_un, - SMALL_2_BIG); - kmem_free(small_un, dep->de_reqsize); - - /* - * Update userdata and incore userdata - * incores are at the end of un - */ - dep->de_rb_userdata_ic = big_un; - dep->de_rb_userdata = big_un; - dep->de_icreqsize = newreqsize; - un = big_un; - rbp->rb_private |= MD_PRV_CONVD; - } else { + switch (rbp->rb_revision) { + case MDDB_REV_RB: + case MDDB_REV_RBFN: + if ((rbp->rb_private & MD_PRV_CONVD) == 0) { + /* + * This means, we have an old and small + * record and this record hasn't already + * been converted. Before we create an + * incore metadevice from this we have to + * convert it to a big record. + */ + small_un = + (mm_unit32_od_t *)mddb_getrecaddr(recid); + newreqsize = sizeof (mm_unit_t); + big_un = (mm_unit_t *)kmem_zalloc(newreqsize, + KM_SLEEP); + mirror_convert((caddr_t)small_un, + (caddr_t)big_un, SMALL_2_BIG); + kmem_free(small_un, dep->de_reqsize); + + /* + * Update userdata and incore userdata + * incores are at the end of un + */ + dep->de_rb_userdata_ic = big_un; + dep->de_rb_userdata = big_un; + dep->de_icreqsize = newreqsize; + un = big_un; + rbp->rb_private |= MD_PRV_CONVD; + } else { + /* + * Unit already converted, just get the + * record address. + */ + un = (mm_unit_t *)mddb_getrecaddr_resize(recid, + sizeof (*un), 0); + } + un->c.un_revision &= ~MD_64BIT_META_DEV; + break; + case MDDB_REV_RB64: + case MDDB_REV_RB64FN: /* Big device */ un = (mm_unit_t *)mddb_getrecaddr_resize(recid, sizeof (*un), 0); + un->c.un_revision |= MD_64BIT_META_DEV; + un->c.un_flag |= MD_EFILABEL; + break; } - - /* Set revision and flag accordingly */ - if (rbp->rb_revision == MDDB_REV_RB) { - un->c.un_revision = MD_32BIT_META_DEV; - } else { - un->c.un_revision = MD_64BIT_META_DEV; - un->c.un_flag |= MD_EFILABEL; - } + NOTE_FN(rbp->rb_revision, un->c.un_revision); /* * Create minor device node for snarfed entry. @@ -5397,6 +5421,7 @@ mddb_rb32_t *rbp; mm_unit32_od_t *un32; mm_unit_t *un64; + md_dev64_t self_devt; minor_t *self_id; /* minor needs to be updated */ md_parent_t *parent_id; /* parent needs to be updated */ mddb_recid_t *record_id; /* record id needs to be updated */ @@ -5417,7 +5442,9 @@ dep = mddb_getrecdep(recid); rbp = dep->de_rb; - if (rbp->rb_revision == MDDB_REV_RB) { + switch (rbp->rb_revision) { + case MDDB_REV_RB: + case MDDB_REV_RBFN: /* * Small device */ @@ -5437,7 +5464,9 @@ (setno), un32->un_sm[i].sm_key)) goto out; } - } else { + break; + case MDDB_REV_RB64: + case MDDB_REV_RB64FN: un64 = (mm_unit_t *)mddb_getrecaddr(recid); self_id = &(un64->c.un_self_id); parent_id = &(un64->c.un_parent); @@ -5454,6 +5483,21 @@ (setno), un64->un_sm[i].sm_key)) goto out; } + break; + } + + /* + * If this is a top level and a friendly name metadevice, + * update its minor in the namespace. + */ + if ((*parent_id == MD_NO_PARENT) && + ((rbp->rb_revision == MDDB_REV_RBFN) || + (rbp->rb_revision == MDDB_REV_RB64FN))) { + + self_devt = md_makedevice(md_major, *self_id); + if (!md_update_top_device_minor(setno, + mddb_getsidenum(setno), self_devt)) + goto out; } /*
--- a/usr/src/uts/common/io/lvm/mirror/mirror_ioctl.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/uts/common/io/lvm/mirror/mirror_ioctl.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -74,6 +73,7 @@ extern mdq_anchor_t md_ff_daemonq; extern void md_probe_one(); extern void mirror_openfail_console_info(); + #ifdef DEBUG extern int mirror_debug_flag; #endif @@ -194,7 +194,7 @@ return (mdmderror(&msp->mde, MDE_UNIT_TOO_LARGE, mnum)); #else recid = mddb_createrec((size_t)msp->size, typ1, MIRROR_REC, - MD_CRO_64BIT | MD_CRO_MIRROR, setno); + MD_CRO_64BIT | MD_CRO_MIRROR | MD_CRO_FN, setno); #endif } else { /* @@ -202,7 +202,7 @@ */ msp->size = sizeof (mm_unit32_od_t); recid = mddb_createrec((size_t)msp->size, typ1, MIRROR_REC, - MD_CRO_32BIT | MD_CRO_MIRROR, setno); + MD_CRO_32BIT | MD_CRO_MIRROR | MD_CRO_FN, setno); } if (recid < 0) return (mddbstatus2error(&msp->mde, (int)recid, @@ -229,6 +229,7 @@ un->c.un_flag |= MD_EFILABEL; } + un->c.un_revision |= MD_FN_META_DEV; MD_RECID(un) = recid; MD_CAPAB(un) = MD_CAN_PARENT | MD_CAN_META_CHILD | MD_CAN_SP; MD_PARENT(un) = MD_NO_PARENT; @@ -261,6 +262,11 @@ return (err); } + /* + * Update unit availability + */ + md_set[setno].s_un_avail--; + mirror_commit(un, ALL_SUBMIRRORS, 0); md_create_unit_incore(MD_SID(un), &mirror_md_ops, 0); mirror_check_failfast(mnum); @@ -354,6 +360,7 @@ minor_t mnum = mirp->mnum; mm_unit_t *un; mdi_unit_t *ui; + set_t setno = MD_MIN2SET(mnum); mdclrerror(&mirp->mde); @@ -393,6 +400,21 @@ } reset_mirror(un, mnum, 1); + + /* + * Update unit availability + */ + md_set[setno].s_un_avail++; + + /* + * If MN set, reset s_un_next so all nodes can have + * the same view of the next available slot when + * nodes are -w and -j + */ + if (MD_MNSET_SETNO(setno)) { + (void) md_upd_set_unnext(setno, MD_MIN2UNIT(mnum)); + } + rw_exit(&md_unit_array_rw.lock); return (0); } @@ -1300,7 +1322,7 @@ un->c.un_actual_tb = total_blocks; /* Is the mirror growing from 32 bit device to 64 bit device? */ - if ((un->c.un_revision == MD_32BIT_META_DEV) && + if (((un->c.un_revision & MD_64BIT_META_DEV) == 0) && (un->c.un_total_blocks > MD_MAX_BLKS_FOR_SMALL_DEVS)) { #if defined(_ILP32) return (mdmderror(ep, MDE_UNIT_TOO_LARGE, mnum)); @@ -1311,15 +1333,21 @@ mddb_recid_t old_recid = un->c.un_record_id; mddb_recid_t old_vtoc; mddb_de_ic_t *dep, *old_dep; + md_create_rec_option_t options; /* yup, new device size. So we need to replace the record */ typ1 = (mddb_type_t)md_getshared_key(MD_UN2SET(un), mirror_md_ops.md_driver.md_drivername); setno = MD_MIN2SET(mnum); + + /* Preserve the friendly name properties of growing unit */ + options = MD_CRO_64BIT | MD_CRO_MIRROR; + if (un->c.un_revision & MD_FN_META_DEV) + options |= MD_CRO_FN; recid = mddb_createrec(offsetof(mm_unit_t, un_smic), typ1, - MIRROR_REC, MD_CRO_64BIT | MD_CRO_MIRROR, setno); + MIRROR_REC, options, setno); /* Resize to include incore fields */ - un->c.un_revision = MD_64BIT_META_DEV; + un->c.un_revision |= MD_64BIT_META_DEV; /* All 64 bit metadevices only support EFI labels. */ un->c.un_flag |= MD_EFILABEL; /*
--- a/usr/src/uts/common/io/lvm/raid/raid.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/uts/common/io/lvm/raid/raid.c Tue Mar 14 14:53:36 2006 -0800 @@ -1075,6 +1075,11 @@ kmem_free(un->mr_ic, sizeof (*un->mr_ic)); + /* + * Attempt release of its minor node + */ + (void) md_remove_minor_node(mnum); + if (!removing) return; @@ -1120,6 +1125,12 @@ raid_commit(un, recids); + /* + * Remove self from the namespace + */ + if (un->c.un_revision & MD_FN_META_DEV) { + (void) md_rem_selfname(un->c.un_self_id); + } /* Remove the unit structure */ mddb_deleterec_wrapper(un->c.un_record_id); @@ -3649,38 +3660,49 @@ dep = mddb_getrecdep(recid); dep->de_flags = MDDB_F_RAID; rbp = dep->de_rb; - if ((rbp->rb_revision == MDDB_REV_RB) && - ((rbp->rb_private & MD_PRV_CONVD) == 0)) { - /* - * This means, we have an old and small record - * and this record hasn't already been converted. - * Before we create an incore metadevice from this - * we have to convert it to a big record. - */ - small_un = (mr_unit32_od_t *)mddb_getrecaddr(recid); - ncol = small_un->un_totalcolumncnt; - newreqsize = sizeof (mr_unit_t) + - ((ncol - 1) * sizeof (mr_column_t)); - big_un = (mr_unit_t *)kmem_zalloc(newreqsize, KM_SLEEP); - raid_convert((caddr_t)small_un, (caddr_t)big_un, - SMALL_2_BIG); - kmem_free(small_un, dep->de_reqsize); - dep->de_rb_userdata = big_un; - dep->de_reqsize = newreqsize; - un = big_un; - rbp->rb_private |= MD_PRV_CONVD; - } else { + switch (rbp->rb_revision) { + case MDDB_REV_RB: + case MDDB_REV_RBFN: + if ((rbp->rb_private & MD_PRV_CONVD) == 0) { + /* + * This means, we have an old and small record + * and this record hasn't already been + * converted. Before we create an incore + * metadevice from this we have to convert it to + * a big record. + */ + small_un = + (mr_unit32_od_t *)mddb_getrecaddr(recid); + ncol = small_un->un_totalcolumncnt; + newreqsize = sizeof (mr_unit_t) + + ((ncol - 1) * sizeof (mr_column_t)); + big_un = (mr_unit_t *)kmem_zalloc(newreqsize, + KM_SLEEP); + raid_convert((caddr_t)small_un, (caddr_t)big_un, + SMALL_2_BIG); + kmem_free(small_un, dep->de_reqsize); + dep->de_rb_userdata = big_un; + dep->de_reqsize = newreqsize; + un = big_un; + rbp->rb_private |= MD_PRV_CONVD; + } else { + /* + * Record has already been converted. Just + * get its address. + */ + un = (mr_unit_t *)mddb_getrecaddr(recid); + } + un->c.un_revision &= ~MD_64BIT_META_DEV; + break; + case MDDB_REV_RB64: + case MDDB_REV_RB64FN: /* Big device */ un = (mr_unit_t *)mddb_getrecaddr(recid); + un->c.un_revision |= MD_64BIT_META_DEV; + un->c.un_flag |= MD_EFILABEL; + break; } - - /* Set revision and flag accordingly */ - if (rbp->rb_revision == MDDB_REV_RB) { - un->c.un_revision = MD_32BIT_META_DEV; - } else { - un->c.un_revision = MD_64BIT_META_DEV; - un->c.un_flag |= MD_EFILABEL; - } + NOTE_FN(rbp->rb_revision, un->c.un_revision); /* * Create minor device node for snarfed entry. @@ -4255,6 +4277,7 @@ mddb_rb32_t *rbp; mr_unit_t *un64; mr_unit32_od_t *un32; + md_dev64_t self_devt; minor_t *self_id; /* minor needs to be updated */ md_parent_t *parent_id; /* parent needs to be updated */ mddb_recid_t *record_id; /* record id needs to be updated */ @@ -4273,7 +4296,9 @@ dep = mddb_getrecdep(recid); rbp = dep->de_rb; - if (rbp->rb_revision == MDDB_REV_RB) { + switch (rbp->rb_revision) { + case MDDB_REV_RB: + case MDDB_REV_RBFN: /* * Small device */ @@ -4295,7 +4320,9 @@ device->un_hs_id = MAKERECID( setno, device->un_hs_id); } - } else { + break; + case MDDB_REV_RB64: + case MDDB_REV_RB64FN: un64 = (mr_unit_t *)mddb_getrecaddr(recid); self_id = &(un64->c.un_self_id); parent_id = &(un64->c.un_parent); @@ -4314,6 +4341,21 @@ device->un_hs_id = MAKERECID( setno, device->un_hs_id); } + break; + } + + /* + * If this is a top level and a friendly name metadevice, + * update its minor in the namespace. + */ + if ((*parent_id == MD_NO_PARENT) && + ((rbp->rb_revision == MDDB_REV_RBFN) || + (rbp->rb_revision == MDDB_REV_RB64FN))) { + + self_devt = md_makedevice(md_major, *self_id); + if (!md_update_top_device_minor(setno, + mddb_getsidenum(setno), self_devt)) + goto out; } /*
--- a/usr/src/uts/common/io/lvm/raid/raid_ioctl.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/uts/common/io/lvm/raid/raid_ioctl.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -295,7 +294,7 @@ if (biowait(&bp)) err = 1; if (i == 0) { - if (un->c.un_revision == MD_64BIT_META_DEV) { + if (un->c.un_revision & MD_64BIT_META_DEV) { unit = ((raid_pwhdr_t *)buf)->rpw_unit; } else { unit = ((raid_pwhdr32_od_t *)buf)->rpw_unit; @@ -305,7 +304,7 @@ * depending upon being an 64bit or 32 bit raid, the * pre write headers have different layout */ - if (un->c.un_revision == MD_64BIT_META_DEV) { + if (un->c.un_revision & MD_64BIT_META_DEV) { if ((((raid_pwhdr_t *)buf)->rpw_column != i) || (((raid_pwhdr_t *)buf)->rpw_unit != unit)) err = 1; @@ -916,11 +915,11 @@ return (mdmderror(&msp->mde, MDE_UNIT_TOO_LARGE, mnum)); #else mr_recid = mddb_createrec(msp->size, typ1, 0, - MD_CRO_64BIT | MD_CRO_RAID, setno); + MD_CRO_64BIT | MD_CRO_RAID | MD_CRO_FN, setno); #endif } else { mr_recid = mddb_createrec(msp->size, typ1, 0, - MD_CRO_32BIT | MD_CRO_RAID, setno); + MD_CRO_32BIT | MD_CRO_RAID | MD_CRO_FN, setno); } if (mr_recid < 0) @@ -964,6 +963,7 @@ MD_CAPAB(un) = MD_CAN_PARENT | MD_CAN_SP; MD_PARENT(un) = MD_NO_PARENT; un->un_resync_copysize = 0; + un->c.un_revision |= MD_FN_META_DEV; if (UNIT_STATE(un) == RUS_INIT) MD_STATUS(un) |= MD_UN_GROW_PENDING; @@ -985,6 +985,11 @@ goto out; } + /* + * Update unit availability + */ + md_set[setno].s_un_avail--; + recids[rid] = 0; if (un->un_hsp_id != -1) { /* increment the reference count of the hot spare pool */ @@ -1674,6 +1679,7 @@ mddb_recid_t mr_recid; mddb_recid_t old_vtoc = 0; mddb_recid_t *recids; + md_create_rec_option_t options; int err; int col, i; int64_t tb, atb; @@ -1751,16 +1757,23 @@ typ1 = (mddb_type_t)md_getshared_key(setno, raid_md_ops.md_driver.md_drivername); + /* + * Preserve the friendly name nature of the device that is + * growing. + */ + options = MD_CRO_RAID; + if (un->c.un_revision & MD_FN_META_DEV) + options |= MD_CRO_FN; if (mgph->options & MD_CRO_64BIT) { #if defined(_ILP32) return (mdmderror(&mgph->mde, MDE_UNIT_TOO_LARGE, mnum)); #else mr_recid = mddb_createrec(mgph->size, typ1, 0, - MD_CRO_64BIT | MD_CRO_RAID, setno); + MD_CRO_64BIT | options, setno); #endif } else { mr_recid = mddb_createrec(mgph->size, typ1, 0, - MD_CRO_32BIT | MD_CRO_RAID, setno); + MD_CRO_32BIT | options, setno); } if (mr_recid < 0) { rval = mddbstatus2error(&mgph->mde, (int)mr_recid, @@ -1848,7 +1861,7 @@ * and had a vtoc record attached to it, we remove the * vtoc record, because the layout has changed completely. */ - if ((un->c.un_revision == MD_32BIT_META_DEV) && + if (((un->c.un_revision & MD_64BIT_META_DEV) == 0) && (un->c.un_vtoc_id != 0)) { old_vtoc = un->c.un_vtoc_id; new_un->c.un_vtoc_id = @@ -1971,6 +1984,7 @@ minor_t mnum = mirp->mnum; mr_unit_t *un; mdi_unit_t *ui; + set_t setno = MD_MIN2SET(mnum); mdclrerror(&mirp->mde); @@ -2004,6 +2018,21 @@ } reset_raid(un, mnum, 1); + + /* + * Update unit availability + */ + md_set[setno].s_un_avail++; + + /* + * If MN set, reset s_un_next so all nodes can have + * the same view of the next available slot when + * nodes are -w and -j + */ + if (MD_MNSET_SETNO(setno)) { + (void) md_upd_set_unnext(setno, MD_MIN2UNIT(mnum)); + } + rw_exit(&md_unit_array_rw.lock); return (0);
--- a/usr/src/uts/common/io/lvm/raid/raid_replay.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/uts/common/io/lvm/raid/raid_replay.c Tue Mar 14 14:53:36 2006 -0800 @@ -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. @@ -19,15 +18,14 @@ * * CDDL HEADER END */ +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ #pragma ident "%Z%%M% %I% %E% SMI" /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* * NAME: raid_replay.c * * DESCRIPTION: RAID driver source file containing routines related to replay @@ -745,13 +743,13 @@ else goto replay_failed; } - if (un->c.un_revision == MD_32BIT_META_DEV) { + if (un->c.un_revision & MD_64BIT_META_DEV) { + pwhdrp = (raid_pwhdr_t *) + rplybuf[j].rpl_data; + } else { RAID_CONVERT_RPW((raid_pwhdr32_od_t *) rplybuf[j].rpl_data, pwhdrp); - } else { - pwhdrp = (raid_pwhdr_t *) - rplybuf[j].rpl_data; } /* first check pre-write magic number */
--- a/usr/src/uts/common/io/lvm/softpart/sp.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/uts/common/io/lvm/softpart/sp.c Tue Mar 14 14:53:36 2006 -0800 @@ -265,6 +265,11 @@ MD_UNIT(mnum) = NULL; + /* + * Attempt release of minor node + */ + (void) md_remove_minor_node(mnum); + if (!removing) return; @@ -279,6 +284,13 @@ sv->key = un->un_key; vtoc_id = un->c.un_vtoc_id; + /* + * Remove self from the namespace + */ + if (un->c.un_revision & MD_FN_META_DEV) { + (void) md_rem_selfname(un->c.un_self_id); + } + /* Remove the unit structure */ mddb_deleterec_wrapper(un->c.un_record_id); @@ -1277,38 +1289,46 @@ dep->de_flags = MDDB_F_SOFTPART; rbp = dep->de_rb; - if ((rbp->rb_revision == MDDB_REV_RB) && - ((rbp->rb_private & MD_PRV_CONVD) == 0)) { - /* - * This means, we have an old and small record. - * And this record hasn't already been converted :-o - * before we create an incore metadevice from this - * we have to convert it to a big record. - */ - small_un = (mp_unit32_od_t *)mddb_getrecaddr(recid); - newreqsize = sizeof (mp_unit_t) + - ((small_un->un_numexts - 1) * - sizeof (struct mp_ext)); - big_un = (mp_unit_t *)kmem_zalloc(newreqsize, KM_SLEEP); - softpart_convert((caddr_t)small_un, (caddr_t)big_un, - SMALL_2_BIG); - kmem_free(small_un, dep->de_reqsize); - dep->de_rb_userdata = big_un; - dep->de_reqsize = newreqsize; - rbp->rb_private |= MD_PRV_CONVD; - un = big_un; - } else { + switch (rbp->rb_revision) { + case MDDB_REV_RB: + case MDDB_REV_RBFN: + if ((rbp->rb_private & MD_PRV_CONVD) == 0) { + /* + * This means, we have an old and small record. + * And this record hasn't already been converted + * :-o before we create an incore metadevice + * from this we have to convert it to a big + * record. + */ + small_un = + (mp_unit32_od_t *)mddb_getrecaddr(recid); + newreqsize = sizeof (mp_unit_t) + + ((small_un->un_numexts - 1) * + sizeof (struct mp_ext)); + big_un = (mp_unit_t *)kmem_zalloc(newreqsize, + KM_SLEEP); + softpart_convert((caddr_t)small_un, + (caddr_t)big_un, SMALL_2_BIG); + kmem_free(small_un, dep->de_reqsize); + dep->de_rb_userdata = big_un; + dep->de_reqsize = newreqsize; + rbp->rb_private |= MD_PRV_CONVD; + un = big_un; + } else { + /* Record has already been converted */ + un = (mp_unit_t *)mddb_getrecaddr(recid); + } + un->c.un_revision &= ~MD_64BIT_META_DEV; + break; + case MDDB_REV_RB64: + case MDDB_REV_RB64FN: /* Large device */ un = (mp_unit_t *)mddb_getrecaddr(recid); + un->c.un_revision |= MD_64BIT_META_DEV; + un->c.un_flag |= MD_EFILABEL; + break; } - - /* Set revision and flag accordingly */ - if (rbp->rb_revision == MDDB_REV_RB) { - un->c.un_revision = MD_32BIT_META_DEV; - } else { - un->c.un_revision = MD_64BIT_META_DEV; - un->c.un_flag |= MD_EFILABEL; - } + NOTE_FN(rbp->rb_revision, un->c.un_revision); /* * Create minor node for snarfed entry. @@ -1695,6 +1715,7 @@ mddb_rb32_t *rbp; mp_unit_t *un64; mp_unit32_od_t *un32; + md_dev64_t self_devt; minor_t *self_id; /* minor needs to be updated */ md_parent_t *parent_id; /* parent needs to be updated */ mddb_recid_t *record_id; /* record id needs to be updated */ @@ -1712,7 +1733,9 @@ dep = mddb_getrecdep(recid); rbp = dep->de_rb; - if (rbp->rb_revision == MDDB_REV_RB) { + switch (rbp->rb_revision) { + case MDDB_REV_RB: + case MDDB_REV_RBFN: /* * Small device */ @@ -1724,7 +1747,10 @@ if (!md_update_minor(setno, mddb_getsidenum (setno), un32->un_key)) goto out; - } else { + break; + + case MDDB_REV_RB64: + case MDDB_REV_RB64FN: un64 = (mp_unit_t *)mddb_getrecaddr(recid); self_id = &(un64->c.un_self_id); parent_id = &(un64->c.un_parent); @@ -1733,6 +1759,21 @@ if (!md_update_minor(setno, mddb_getsidenum (setno), un64->un_key)) goto out; + break; + } + + /* + * If this is a top level and a friendly name metadevice, + * update its minor in the namespace. + */ + if ((*parent_id == MD_NO_PARENT) && + ((rbp->rb_revision == MDDB_REV_RBFN) || + (rbp->rb_revision == MDDB_REV_RB64FN))) { + + self_devt = md_makedevice(md_major, *self_id); + if (!md_update_top_device_minor(setno, + mddb_getsidenum(setno), self_devt)) + goto out; } /*
--- a/usr/src/uts/common/io/lvm/softpart/sp_ioctl.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/uts/common/io/lvm/softpart/sp_ioctl.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -73,6 +72,7 @@ #include <sys/mkdev.h> #include <sys/stat.h> #include <sys/open.h> +#include <sys/lvm/mdvar.h> #include <sys/lvm/md_sp.h> #include <sys/lvm/md_notify.h> #include <sys/modctl.h> @@ -240,6 +240,12 @@ setno = MD_MIN2SET(mnum); side = mddb_getsidenum(setno); un = MD_UNIT(mnum); + + if (un == NULL) { + err = EFAULT; + goto out; + } + mdep = &mup->mde; mdclrerror(mdep); @@ -481,12 +487,12 @@ #if defined(_ILP32) return (mdmderror(mdep, MDE_UNIT_TOO_LARGE, mnum)); #else - recids[0] = mddb_createrec((size_t)msp->size, rec_type, - 0, MD_CRO_64BIT | MD_CRO_SOFTPART, setno); + recids[0] = mddb_createrec((size_t)msp->size, rec_type, 0, + MD_CRO_64BIT | MD_CRO_SOFTPART | MD_CRO_FN, setno); #endif } else { - recids[0] = mddb_createrec((size_t)msp->size, rec_type, - 0, MD_CRO_32BIT | MD_CRO_SOFTPART, setno); + recids[0] = mddb_createrec((size_t)msp->size, rec_type, 0, + MD_CRO_32BIT | MD_CRO_SOFTPART | MD_CRO_FN, setno); } /* set initial value for possible child record */ recids[1] = 0; @@ -521,6 +527,7 @@ MD_SID(un) = mnum; MD_RECID(un) = recids[0]; MD_PARENT(un) = MD_NO_PARENT; + un->c.un_revision |= MD_FN_META_DEV; /* if we are parenting a metadevice, set our child's parent field */ if (md_getmajor(un->un_dev) == md_major) { @@ -548,6 +555,11 @@ } /* + * Update unit availability + */ + md_set[setno].s_un_avail--; + + /* * commit the record. * if we had to update a child record, it will get commited * as well. @@ -649,6 +661,7 @@ mdi_unit_t *ui; mp_unit_t *un; md_unit_t *child_un; + set_t setno = MD_MIN2SET(mnum); mdclrerror(&softp->mde); @@ -688,6 +701,20 @@ /* remove the soft partition */ reset_sp(un, mnum, 1); + /* + * Update unit availability + */ + md_set[setno].s_un_avail++; + + /* + * If MN set, reset s_un_next so all nodes can have + * the same view of the next available slot when + * nodes are -w and -j + */ + if (MD_MNSET_SETNO(setno)) { + md_upd_set_unnext(setno, MD_MIN2UNIT(mnum)); + } + /* release locks and return */ out: rw_exit(&md_unit_array_rw.lock); @@ -723,6 +750,7 @@ mddb_recid_t recid; mddb_type_t rec_type; mddb_recid_t old_vtoc = 0; + md_create_rec_option_t options; int err; int rval = 0; set_t setno; @@ -776,17 +804,23 @@ rec_type = (mddb_type_t)md_getshared_key(setno, sp_md_ops.md_driver.md_drivername); + /* + * Preserve the friendly name nature of the unit that is growing. + */ + options = MD_CRO_SOFTPART; + if (un->c.un_revision & MD_FN_META_DEV) + options |= MD_CRO_FN; if (mgp->options & MD_CRO_64BIT) { #if defined(_ILP32) rval = mdmderror(mdep, MDE_UNIT_TOO_LARGE, mnum); goto out; #else recid = mddb_createrec((size_t)mgp->size, rec_type, 0, - MD_CRO_64BIT | MD_CRO_SOFTPART, setno); + MD_CRO_64BIT | options, setno); #endif } else { recid = mddb_createrec((size_t)mgp->size, rec_type, 0, - MD_CRO_32BIT | MD_CRO_SOFTPART, setno); + MD_CRO_32BIT | options, setno); } if (recid < 0) { rval = mddbstatus2error(mdep, (int)recid, mnum, setno); @@ -804,6 +838,8 @@ rval = EFAULT; goto out; } + if (options & MD_CRO_FN) + new_un->c.un_revision |= MD_FN_META_DEV; /* All 64 bit metadevices only support EFI labels. */ if (mgp->options & MD_CRO_64BIT) { @@ -813,7 +849,7 @@ * and had a vtoc record attached to it, we remove the * vtoc record, because the layout has changed completely. */ - if ((un->c.un_revision == MD_32BIT_META_DEV) && + if (((un->c.un_revision & MD_64BIT_META_DEV) == 0) && (un->c.un_vtoc_id != 0)) { old_vtoc = un->c.un_vtoc_id; new_un->c.un_vtoc_id =
--- a/usr/src/uts/common/io/lvm/stripe/stripe.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/uts/common/io/lvm/stripe/stripe.c Tue Mar 14 14:53:36 2006 -0800 @@ -369,6 +369,11 @@ MD_UNIT(mnum) = NULL; + /* + * Attempt release of its minor node + */ + (void) md_remove_minor_node(mnum); + if (!removing) return; @@ -467,6 +472,13 @@ vtoc_id = un->c.un_vtoc_id; + /* + * Remove self from the namespace + */ + if (un->c.un_revision & MD_FN_META_DEV) { + (void) md_rem_selfname(un->c.un_self_id); + } + /* Remove the unit structure */ mddb_deleterec_wrapper(un->c.un_record_id); @@ -835,37 +847,45 @@ dep->de_flags = MDDB_F_STRIPE; rbp = dep->de_rb; - if ((rbp->rb_revision == MDDB_REV_RB) && - ((rbp->rb_private & MD_PRV_CONVD) == 0)) { - /* - * This means, we have an old and small record - * and this record hasn't already been converted. - * Before we create an incore metadevice from this - * we have to convert it to a big record. - */ - small_un = (ms_unit32_od_t *)mddb_getrecaddr(recid); - newreqsize = get_big_stripe_req_size(small_un, - COMPLETE_STRUCTURE); - big_un = (ms_unit_t *)kmem_zalloc(newreqsize, KM_SLEEP); - stripe_convert((caddr_t)small_un, (caddr_t)big_un, - SMALL_2_BIG); - kmem_free(small_un, dep->de_reqsize); - dep->de_rb_userdata = big_un; - dep->de_reqsize = newreqsize; - un = big_un; - rbp->rb_private |= MD_PRV_CONVD; - } else { + switch (rbp->rb_revision) { + case MDDB_REV_RB: + case MDDB_REV_RBFN: + if ((rbp->rb_private & MD_PRV_CONVD) == 0) { + /* + * This means, we have an old and small record + * and this record hasn't already been + * converted. Before we create an incore + * metadevice from this we have to convert it to + * a big record. + */ + small_un = + (ms_unit32_od_t *)mddb_getrecaddr(recid); + newreqsize = get_big_stripe_req_size(small_un, + COMPLETE_STRUCTURE); + big_un = (ms_unit_t *)kmem_zalloc(newreqsize, + KM_SLEEP); + stripe_convert((caddr_t)small_un, + (caddr_t)big_un, SMALL_2_BIG); + kmem_free(small_un, dep->de_reqsize); + dep->de_rb_userdata = big_un; + dep->de_reqsize = newreqsize; + un = big_un; + rbp->rb_private |= MD_PRV_CONVD; + } else { + /* Small device had already been converted */ + un = (ms_unit_t *)mddb_getrecaddr(recid); + } + un->c.un_revision &= ~MD_64BIT_META_DEV; + break; + case MDDB_REV_RB64: + case MDDB_REV_RB64FN: /* Big device */ un = (ms_unit_t *)mddb_getrecaddr(recid); + un->c.un_revision |= MD_64BIT_META_DEV; + un->c.un_flag |= MD_EFILABEL; + break; } - - /* Set revision and flag accordingly */ - if (rbp->rb_revision == MDDB_REV_RB) { - un->c.un_revision = MD_32BIT_META_DEV; - } else { - un->c.un_revision = MD_64BIT_META_DEV; - un->c.un_flag |= MD_EFILABEL; - } + NOTE_FN(rbp->rb_revision, un->c.un_revision); /* Create minor node for snarfed unit. */ (void) md_create_minor_node(MD_MIN2SET(MD_SID(un)), MD_SID(un)); @@ -1591,6 +1611,7 @@ mddb_rb32_t *rbp; ms_unit32_od_t *un32; ms_unit_t *un64; + md_dev64_t self_devt; minor_t *self_id; /* minor needs to be updated */ md_parent_t *parent_id; /* parent needs to be updated */ mddb_recid_t *record_id; /* record id needs to be updated */ @@ -1612,7 +1633,9 @@ dep = mddb_getrecdep(recid); rbp = dep->de_rb; - if (rbp->rb_revision == MDDB_REV_RB) { + switch (rbp->rb_revision) { + case MDDB_REV_RB: + case MDDB_REV_RBFN: /* * Small device */ @@ -1640,7 +1663,9 @@ setno, mdc->un_mirror.ms_hs_id); } } - } else { + break; + case MDDB_REV_RB64: + case MDDB_REV_RB64FN: un64 = (ms_unit_t *)mddb_getrecaddr(recid); self_id = &(un64->c.un_self_id); parent_id = &(un64->c.un_parent); @@ -1665,6 +1690,21 @@ setno, mdc->un_mirror.ms_hs_id); } } + break; + } + + /* + * If this is a top level and a friendly name metadevice, + * update its minor in the namespace. + */ + if ((*parent_id == MD_NO_PARENT) && + ((rbp->rb_revision == MDDB_REV_RBFN) || + (rbp->rb_revision == MDDB_REV_RB64FN))) { + + self_devt = md_makedevice(md_major, *self_id); + if (!md_update_top_device_minor(setno, + mddb_getsidenum(setno), self_devt)) + goto out; } /*
--- a/usr/src/uts/common/io/lvm/stripe/stripe_ioctl.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/uts/common/io/lvm/stripe/stripe_ioctl.c Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -43,6 +42,7 @@ #include <sys/mkdev.h> #include <sys/stat.h> #include <sys/open.h> +#include <sys/lvm/mdvar.h> #include <sys/lvm/md_stripe.h> #include <sys/lvm/md_notify.h> #include <sys/modctl.h> @@ -176,11 +176,11 @@ return (mdmderror(mdep, MDE_UNIT_TOO_LARGE, mnum)); #else ms_recid = mddb_createrec((size_t)msp->size, typ1, 0, - MD_CRO_64BIT | MD_CRO_STRIPE, setno); + MD_CRO_64BIT | MD_CRO_STRIPE | MD_CRO_FN, setno); #endif } else { ms_recid = mddb_createrec((size_t)msp->size, typ1, 0, - MD_CRO_32BIT | MD_CRO_STRIPE, setno); + MD_CRO_32BIT | MD_CRO_STRIPE | MD_CRO_FN, setno); } if (ms_recid < 0) return (mddbstatus2error(mdep, ms_recid, mnum, setno)); @@ -229,6 +229,7 @@ MD_RECID(un) = recids[0]; MD_CAPAB(un) = MD_CAN_PARENT | MD_CAN_SUB_MIRROR | MD_CAN_SP; MD_PARENT(un) = MD_NO_PARENT; + un->c.un_revision |= MD_FN_META_DEV; if (err = stripe_build_incore(p, 0)) { MD_UNIT(mnum) = NULL; @@ -237,6 +238,11 @@ return (err); } + /* + * Update unit availability + */ + md_set[setno].s_un_avail--; + recids[rid] = 0; if (un->un_hsp_id != -1) err = md_hot_spare_ifc(HSP_INCREF, un->un_hsp_id, 0, 0, @@ -366,6 +372,21 @@ md_unit_openclose_exit(ui); reset_stripe(un, mnum, 1); + + /* + * Update unit availability + */ + md_set[setno].s_un_avail++; + + /* + * If MN set, reset s_un_next so all nodes can have + * the same view of the next available slot when + * nodes are -w and -j + */ + if (MD_MNSET_SETNO(setno)) { + (void) md_upd_set_unnext(setno, MD_MIN2UNIT(mnum)); + } + rw_exit(&md_unit_array_rw.lock); return (0); } @@ -383,6 +404,7 @@ mddb_recid_t ms_recid; mddb_recid_t old_vtoc = 0; mddb_recid_t *recids; + md_create_rec_option_t options; mddb_type_t typ1; int err; int64_t tb, atb; @@ -448,17 +470,23 @@ typ1 = (mddb_type_t)md_getshared_key(setno, stripe_md_ops.md_driver.md_drivername); + /* + * Preserve the friendly name nature of growing device. + */ + options = MD_CRO_STRIPE; + if (un->c.un_revision & MD_FN_META_DEV) + options |= MD_CRO_FN; if (mgp->options & MD_CRO_64BIT) { #if defined(_ILP32) rval = mdmderror(mdep, MDE_UNIT_TOO_LARGE, mnum); goto out; #else ms_recid = mddb_createrec((size_t)mgp->size, typ1, 0, - MD_CRO_64BIT | MD_CRO_STRIPE, setno); + MD_CRO_64BIT | options, setno); #endif } else { ms_recid = mddb_createrec((size_t)mgp->size, typ1, 0, - MD_CRO_32BIT | MD_CRO_STRIPE, setno); + MD_CRO_32BIT | options, setno); } @@ -486,6 +514,8 @@ rval = EFAULT; goto out; } + if (options & MD_CRO_FN) + new_un->c.un_revision |= MD_FN_META_DEV; /* * allocate the real recids array. since we may have to @@ -540,7 +570,7 @@ * and had a vtoc record attached to it, we remove the * vtoc record, because the layout has changed completely. */ - if ((un->c.un_revision == MD_32BIT_META_DEV) && + if (((un->c.un_revision & MD_64BIT_META_DEV) == 0) && (un->c.un_vtoc_id != 0)) { old_vtoc = un->c.un_vtoc_id; new_un->c.un_vtoc_id =
--- a/usr/src/uts/common/io/lvm/trans/mdtrans.c Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/uts/common/io/lvm/trans/mdtrans.c Tue Mar 14 14:53:36 2006 -0800 @@ -912,7 +912,7 @@ dep->de_icreqsize = newreqsize; rbp->rb_private |= MD_PRV_CONVD; un = big_un; - un->c.un_revision = MD_32BIT_META_DEV; + un->c.un_revision &= ~MD_64BIT_META_DEV; } else { /* already converted, just set the pointer */ un = dep->de_rb_userdata;
--- a/usr/src/uts/common/sys/lvm/md_mddb.h Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/uts/common/sys/lvm/md_mddb.h Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -120,6 +119,21 @@ /* * Set struct used by all parts of the driver, to store anchor pointers. + * + * Lock associated with field in this structure: + * + * Some of fields are accessible by both the single threaded ioctl thread + * and internal threads such as resync, hotsparing...etc. In this case + * additional protection is needed. For example, s_db is protected by + * s_dbmx additionally and s_un, s_ui are protected by md_unit_array_rw.lock + * s_nm, s_nmid, s_did_nm and s_did_nmid and s_dtp are protected by nm_lock + * Rest of other fileds are protected by md_mx. Two fields s_un_next and + * s_un_avail are introduced by the friendly name project and are ONLY + * accessible via a single threaded ioctl thread which already is protected + * by the ioctl lock and there is no need to add extra protection to them. + * However, in the future if they become accessible by other internal threads + * then an additional protection such as md_mx lock is highly recommended. + * */ typedef struct md_set { uint_t s_status; /* set status */ @@ -137,6 +151,8 @@ int s_am_i_master; /* incore master flag for this node */ md_mn_nodeid_t s_nodeid; /* nodeid of this node - for MN sets */ uint_t s_rcnt; /* incore resync count for set */ + unit_t s_un_next; /* s_un scan starts here */ + unit_t s_un_avail; /* number of avail slots */ } md_set_t; @@ -181,6 +197,17 @@ * with any nodeid (sideno) allowed. * The revision is set to MDDB_REV_MNLN which is a change of the * MDDB_REV_MAJOR portion of the revision. + * + * The record blocks have two binary properties. A record block can + * represent either a 32 or 64 bit unit. A record block can also represent + * a traditionally named unit or a friendly named unit. Thus, there are + * minor revisions of record block. + * + * Traditional Friendly + * Name Name + * ----------- -------- + * 32 bit MDDB_REV_RB MDDB_REV_RBFN + * 64 bit MDDB_REV_RB64 MDDB_REV_RB64FN */ #define MDDB_REV_MB (uint_t)0x0201 @@ -192,9 +219,25 @@ #define MDDB_REV_MNLN (uint_t)0x0300 #define MDDB_REV_RB (uint_t)0x0200 #define MDDB_REV_RB64 (uint_t)0x0201 +#define MDDB_REV_RBFN (uint_t)0x0202 +#define MDDB_REV_RB64FN (uint_t)0x0203 #define MDDB_REV_DT (uint_t)0x0100 #define MDDB_REV_DI (uint_t)0x0100 +/* + * Transfer record block friendly name status to unit/hs structure. + */ +#define NOTE_FN(rbv, unv) switch (rbv) { \ + case MDDB_REV_RB: \ + case MDDB_REV_RB64: \ + unv &= ~MD_FN_META_DEV; \ + break; \ + case MDDB_REV_RBFN: \ + case MDDB_REV_RB64FN: \ + unv |= MD_FN_META_DEV; \ + break; \ + } + #define MDDB_BSIZE (uint_t)DEV_BSIZE #define MDDB_PREFIXCNT 10 #define MDDB_DRVNMCNT 10 @@ -838,6 +881,8 @@ extern int mddb_getinvlb_devid(set_t setno, int count, int size, char **ctdptr); extern int md_update_minor(set_t, side_t, mdkey_t); +extern int md_update_top_device_minor(set_t, side_t, + md_dev64_t); #ifdef DEBUG extern void mddb_check(void); #endif /* DEBUG */
--- a/usr/src/uts/common/sys/lvm/md_raid.h Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/uts/common/sys/lvm/md_raid.h Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -93,7 +92,7 @@ #define RAID_FILLIN_RPW(buf, un, sum, colnum, \ blkno, blkcnt, id, \ colcount, col, magic) { \ - if ((un)->c.un_revision == MD_64BIT_META_DEV) { \ + if ((un)->c.un_revision & MD_64BIT_META_DEV) { \ raid_pwhdr_t *rpw64 = (raid_pwhdr_t *)(void *)(buf);\ rpw64->rpw_magic = magic; \ rpw64->rpw_sum = sum; \
--- a/usr/src/uts/common/sys/lvm/mdio.h Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/uts/common/sys/lvm/mdio.h Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -75,16 +74,55 @@ #define MAKE_HSP_ID(setno, id) (((setno) << HSP_SET_SHIFT) | (id)) /* + * The following macros were added to support friendly names for hot spare + * pools. Before the addition of friendly names the hsp_self_id was merely + * the conbination of the set number and the hot spare pool number. With + * friendly names a NM record is created to hold the hot spare pool name. + * The hsp_self_id now becomes the set number shifted left plus the NM + * record key plus 1000. The number 1000 is used to collision between + * traditional hsp_self_ids and friendly name self ids. In traditional hot + * spare pool the hot spare pool number could never be grater than 999. + * + * HSP_ID_IS_FN(hspid) returns TRUE if the hot spare pool ID is the ID of + * a friendly named hsp. Will return FALSE otherwise. + * hspid may contain the set bits, since HSP_ID_IS_FN + * will call HSP_ID as part of doing its work. + * + * KEY_TO_HSP_ID(setno, reckey) constructs a hot spare pool ID (hsp_t) from + * a set number and a NM record key. The result is + * suitable for storing in the hsp_self_id member of a + * hot_spare_pool struct. + * + * HSP_ID_TO_KEY(hspid) returns the NM key that is encoded in the hot spare + * pool ID. MD_KEYBAD will be returned if hspid does + * not represent a friendly named hsp. hspid may + * contain the set bits, since HSP_ID_TO_KEY will call + * HSP_ID as part of doing its work. + * + * HSP_KEY_OK(reckey) Insures that the NM record key is not so large as + * to interfere with the set number bits in a hot + * spare pool self id. This macro will probably only + * be used in meta_hs_add. + */ +#define HSP_FN_BASE (1000) +#define HSP_ID_IS_FN(hspid) (HSP_ID(hspid) > HSP_FN_BASE) +#define KEY_TO_HSP_ID(setno, key) ((setno << HSP_SET_SHIFT) | \ + (key + HSP_FN_BASE)) +#define HSP_ID_TO_KEY(hspid) ((HSP_ID_IS_FN(hspid)) ? \ + (HSP_ID(hspid) - HSP_FN_BASE) : MD_KEYBAD) +#define HSP_KEY_OK(key) (((key + HSP_FN_BASE) & HSP_SET_MASK) == 0) + +/* * for did stat ioctl */ #define MD_FIND_INVDID 0x01 #define MD_GET_INVDID 0x02 /* - * for setting the un_revision + * for setting the un_revision, hsp_revision and hs_revision */ -#define MD_32BIT_META_DEV 0 -#define MD_64BIT_META_DEV 1 +#define MD_64BIT_META_DEV 0x01 +#define MD_FN_META_DEV 0x02 /* Friendly named metadevice */ /* * for trans EOF error messages @@ -268,6 +306,18 @@ uint_t ref_count; /* returned n_count */ } mdnm_params_t; +typedef struct mdhspnm_params { + md_error_t mde; /* Error return */ + char drvnm[MD_MAXDRVNM]; /* drvnm for get/set/rem nm */ + uint_t hspname_len; /* Length of device name, for set nm */ + uint64_t hspname; /* Address of device name for set/get */ + set_t setno; /* Which namespace set to use */ + side_t side; /* -1 == current side, >0 specified */ + hsp_t hspid; /* 0 == alloc one, else use this key */ + hsp_t ret_hspid; /* return key here! */ + uint_t ref_count; /* returned n_count */ +} mdhspnm_params_t; + typedef struct md_getdevs_params { MD_DRIVER md_error_t mde; @@ -374,7 +424,7 @@ typedef struct md_mkdev_params { MD_DRIVER md_error_t mde; /* Error return */ - minor_t mnum; + unit_t un; } md_mkdev_params_t; /* @@ -697,6 +747,8 @@ #define MD_MN_SETSYNC (MDIOC|102) /* multi-threaded MD_IOCSETSYNC */ #define MD_MN_POKE_HOTSPARES (MDIOC|103) /* poke hotspares */ #define MD_DB_LBINITTIME (MDIOC|104) /* get the lb_inittime */ +#define MD_IOCGET_HSP_NM (MDIOC|105) /* get hsp entry from namespace */ +#define MD_IOCREM_DEV (MDIOC|106) /* remove device node for unit */ #define MDIOC_MISC (MDIOC|128) /* misc module base */ /* Used in DEBUG_TEST code */
--- a/usr/src/uts/common/sys/lvm/mdiox.x Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/uts/common/sys/lvm/mdiox.x Tue Mar 14 14:53:36 2006 -0800 @@ -1,13 +1,9 @@ %/* -% * Copyright 2005 Sun Microsystems, Inc. All rights reserved. -% * Use is subject to license terms. -% * % * 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. @@ -23,6 +19,11 @@ % * CDDL HEADER END % */ % +%/* +% * Copyright 2006 Sun Microsystems, Inc. All rights reserved. +% * Use is subject to license terms. +% */ +% %#pragma ident "%Z%%M% %I% %E% SMI" % %/* @@ -159,7 +160,8 @@ MD_CRO_TRANS_LOG = 0x100, MD_CRO_HOTSPARE = 0x200, MD_CRO_HOTSPARE_POOL = 0x400, - MD_CRO_CHANGELOG = 0x800 + MD_CRO_CHANGELOG = 0x800, + MD_CRO_FN = 0x1000 }; % @@ -532,9 +534,32 @@ MD_METASP }; +%/* SVM general device types +% * +% * META_DEVICE refers to any SVM metadevice +% * LOGICAL_DEVICE refers to any underlying physical device +% * HSP_DEVICE refers to a hotspare pool +% * +% * In the past, the device type can be determined via +% * the device name (such as d10, c1t1d1s1). With +% * the friendly name implementation, it is not possible +% * to determine from the device name. In the code, +% * whereever the device type is obvious that type will be +% * used explicitly otherwise 'UNKNOWN' will be used and +% * specific SVM lookup routines will be called to determine +% * the device type associated with the name. +% */ +enum meta_device_type_t { + UNKNOWN = 0, + META_DEVICE, + HSP_DEVICE, + LOGICAL_DEVICE +}; + #ifdef RPC_HDR % %/* misc module names */ +%/* When modifying this list also update meta_names in md_names.c */ %#define MD_STRIPE "md_stripe" %#define MD_MIRROR "md_mirror" %#define MD_TRANS "md_trans" @@ -1369,7 +1394,12 @@ MDE_STRIPE_TRUNC_MULTIPLE, /* multiple component stripe trun */ MDE_SMF_FAIL, /* service management facility error */ MDE_SMF_NO_SERVICE, /* service not enabled in SMF */ - MDE_ZONE_ADMIN /* in a zone & no admin device */ + MDE_AMBIGUOUS_DEV, /* Ambiguous device specified */ + MDE_NAME_IN_USE, /* Friendly name already in use. For */ + /* instance name desired for hot spare pool */ + /* is being used for a metadevice. */ + MDE_ZONE_ADMIN, /* in a zone & no admin device */ + MDE_NAME_ILLEGAL /* illegal syntax for metadevice or hsp name */ }; struct md_void_error_t {
--- a/usr/src/uts/common/sys/lvm/mdmn_commd.x Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/uts/common/sys/lvm/mdmn_commd.x Tue Mar 14 14:53:36 2006 -0800 @@ -1,27 +1,26 @@ -/* - * 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. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ +%/* +% * CDDL HEADER START +% * +% * The contents of this file are subject to the terms of the +% * 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. +% * See the License for the specific language governing permissions +% * and limitations under the License. +% * +% * When distributing Covered Code, include this CDDL HEADER in each +% * file and include the License file at usr/src/OPENSOLARIS.LICENSE. +% * If applicable, add the following below this CDDL HEADER, with the +% * fields enclosed by brackets "[]" replaced with your own identifying +% * information: Portions Copyright [yyyy] [name of copyright owner] +% * +% * CDDL HEADER END +% */ % %/* -% * Copyright 2005 Sun Microsystems, Inc. All rights reserved. +% * Copyright 2006 Sun Microsystems, Inc. All rights reserved. % * Use is subject to license terms. % */ % @@ -103,6 +102,7 @@ MD_MN_MSG_SP_SETSTAT2, /* Update softpart status on error */ MD_MN_MSG_SETSYNC, /* Set resync status */ MD_MN_MSG_POKE_HOTSPARES, /* Call poke_hotspares */ + MD_MN_MSG_ADDMDNAME, /* Add metadevice name */ MD_MN_NMESSAGES /* insert elements before */ }; @@ -314,6 +314,14 @@ char addkeyname_name[1]; /* must be last element */ }; +/* + * Add metadevice name into replica + */ +struct md_mn_msg_addmdname_t { + set_t addmdname_setno; + char addmdname_name[1]; +}; + /* Message format for DELKEYNAME message */ struct md_mn_msg_delkeyname_t {
--- a/usr/src/uts/common/sys/lvm/mdvar.h Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/uts/common/sys/lvm/mdvar.h Tue Mar 14 14:53:36 2006 -0800 @@ -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,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -707,6 +706,7 @@ extern md_parent_t md_get_parent(md_dev64_t); extern void md_set_parent(md_dev64_t, md_parent_t); extern void md_reset_parent(md_dev64_t); +extern struct hot_spare_pool *find_hot_spare_pool(set_t, int); extern int md_hot_spare_ifc(hs_cmds_t, mddb_recid_t, u_longlong_t, int, mddb_recid_t *, mdkey_t *, md_dev64_t *, diskaddr_t *); extern int md_notify_interface(md_event_cmds_t cmd, md_tags_t type, @@ -748,6 +748,9 @@ extern int md_init_probereq(struct md_probedev_impl *p, daemon_queue_t **hdrpp); extern boolean_t callb_md_mrs_cpr(void *, int); +extern void md_upd_set_unnext(set_t, unit_t); +extern int md_rem_selfname(minor_t); +extern void md_rem_hspname(set_t, mdkey_t); /* Externals from md_ioctl.c */ extern int md_mn_is_commd_present(void); @@ -762,13 +765,16 @@ extern int md_dkiocgetefi(minor_t, void *, int); extern int md_dkiocsetefi(minor_t, void *, int); extern int md_dkiocpartition(minor_t, void *, int); +extern void md_remove_minor_node(minor_t); /* Externals from md_names.c */ extern mdkey_t md_setdevname(set_t, side_t, mdkey_t, char *, minor_t, char *, - set_t); + set_t, md_error_t *); extern int md_getdevname(set_t, side_t, mdkey_t, md_dev64_t, char *, size_t); +extern int md_gethspinfo(set_t, side_t, mdkey_t, char *, hsp_t *, + char *); extern int md_getkeyfromdev(set_t, side_t, md_dev64_t, mdkey_t *, int *); extern int md_devid_found(set_t, side_t, mdkey_t); extern int md_getnment(set_t, side_t, mdkey_t, md_dev64_t,
--- a/usr/src/uts/common/sys/lvm/meta_basic.x Tue Mar 14 14:33:40 2006 -0800 +++ b/usr/src/uts/common/sys/lvm/meta_basic.x Tue Mar 14 14:53:36 2006 -0800 @@ -1,13 +1,9 @@ %/* -% * Copyright 2005 Sun Microsystems, Inc. All rights reserved. -% * Use is subject to license terms. -% * % * 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. @@ -23,6 +19,11 @@ % * CDDL HEADER END % */ % +%/* +% * Copyright 2006 Sun Microsystems, Inc. All rights reserved. +% * Use is subject to license terms. +% */ +% %#pragma ident "%Z%%M% %I% %E% SMI" % @@ -254,6 +255,8 @@ % %#define MD_KEYWILD ((mdkey_t)0) %#define MD_KEYBAD ((mdkey_t)~0UL) +%#define MD_UNITBAD ((unit_t)~0UL) +%#define MD_HSPID_WILD ((hsp_t)~0UL) %/* Maximum length of a metadevice name */ %#define MD_MAX_SIDENAME_LEN (MD_MAXDRVNM + MD_MAX_SETNAME + 2)