summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorgp87344 <none@none>2007-05-01 13:28:00 -0700
committergp87344 <none@none>2007-05-01 13:28:00 -0700
commit8cecff49db8e75ebf1858567ff985fdf50f1b899 (patch)
treec34c2b5db1b4a059af9d3dfadc88a17675b6a785 /usr/src
parentc22c4bcbc84edc468c452180619bf77fdee93726 (diff)
downloadillumos-joyent-8cecff49db8e75ebf1858567ff985fdf50f1b899.tar.gz
6449836 stmsboot -d failed to boot if several luns or targets map to the same partition
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/stmsboot/stmsboot.sh34
-rw-r--r--usr/src/cmd/stmsboot/stmsboot_util.c213
2 files changed, 160 insertions, 87 deletions
diff --git a/usr/src/cmd/stmsboot/stmsboot.sh b/usr/src/cmd/stmsboot/stmsboot.sh
index f5ce397a4e..109eff2607 100644
--- a/usr/src/cmd/stmsboot/stmsboot.sh
+++ b/usr/src/cmd/stmsboot/stmsboot.sh
@@ -242,34 +242,6 @@ update_sysfiles()
done
fi
- # if we're an x86/x64 machine and our bootpath is on fibrechannel
- # then we cannot disable mpxio for that controller. Yet.....
- # This code block is an ugly hack and when we either get full-time
- # mpxio for all devices, or devfsadm gets re-written then we can
- # remove it. For now, though, we have to see the beauty in ugly.
-
- if [ "x$MACH" = "xi386" ]; then
- BOOTPATH=`/usr/sbin/eeprom bootpath | $AWK -F"=" '{print $2}'`
- FPBOOT=`echo "$BOOTPATH" | $GREP "/fp@"`
- if [ ! -z "$FPBOOT" ]; then
- NEWP=`/usr/bin/dirname $BOOTPATH`
- NNEWP=`/usr/bin/dirname $NEWP`
-
- # check that we haven't already got this entry
- # in /kernel/drv/fp.conf.
-
- EXISTP=`$GREP "^name.*$NNEWP" /kernel/drv/fp.conf`
- if [ $? != 0 ]; then
- cat >>/kernel/drv/fp.conf << EOF
-# This entry must be the last one in the fp.conf file
-# to ensure that the boot path mpxio setting is not
-# accidentally overridden
-name="fp" parent="$NNEWP" port=0 mpxio-disable="no";
-EOF
- fi
- fi
- fi
-
if [ $need_bootscript -gt 0 ]; then
need_bootscript=1
if [ "x$MACH" = "xi386" -a "x$new_bootpath" != "x" ]; then
@@ -451,7 +423,8 @@ emit_driver_warning_msg() {
gettext "Do you wish to continue? [y/n] (default: y) " 1>&2
read response
- if [ "x$response" != "xY" -a "x$response" != "xy" ]; then
+ if [ "x$response" != "x" -a "x$response" != "xY" -a \
+ "x$response" != "xy" ]; then
exit
fi
@@ -553,7 +526,8 @@ if [ "x$cmd" = xenable -o "x$cmd" = xdisable -o "x$cmd" = xupdate ]; then
echo "Do you wish to reboot the system now? (y/n, default y) \c"
read response
- if [ "x$response" = "xY" -o "x$response" = "xy" ]; then
+ if [ "x$response" = "x" -o "x$response" = "xY" -o \
+ "x$response" = "xy" ]; then
/usr/sbin/reboot
else
/bin/echo ""
diff --git a/usr/src/cmd/stmsboot/stmsboot_util.c b/usr/src/cmd/stmsboot/stmsboot_util.c
index 81ac16eadc..5fa8e9701b 100644
--- a/usr/src/cmd/stmsboot/stmsboot_util.c
+++ b/usr/src/cmd/stmsboot/stmsboot_util.c
@@ -46,6 +46,7 @@
#include <locale.h>
#include <libintl.h>
#include <sys/syscall.h>
+#include <sys/mnttab.h>
#include <sys/vfstab.h>
#include <sys/mount.h>
#include <devid.h>
@@ -120,6 +121,7 @@ static int list_mappings(int, int);
static int canopen(char *);
static client_type_t client_by_props(char *path);
static void list_nodes(char *drivername);
+static int canread(char *, char *);
static void logerr(char *, ...);
static void logdmsg(char *, ...);
@@ -756,6 +758,57 @@ out:
/*
+ * Given a phci or vhci devname which is either a /dev link or /devices name
+ * get the corresponding physical node path (without the /devices prefix)
+ * and minor name.
+ *
+ * Returns 0 on success, -1 on failure.
+ */
+static int
+get_physname_minor(char *devname, char *physname, int physname_len,
+ char *minorname, int minorname_len)
+{
+ int linksize;
+ char buf[MAXPATHLEN];
+ char *p, *m;
+
+ if (strncmp(devname, DEV_DSK, sizeof (DEV_DSK) - 1) == 0 ||
+ strncmp(devname, DEV_RDSK, sizeof (DEV_RDSK) - 1) == 0) {
+ if ((linksize = readlink(devname, buf, MAXPATHLEN))
+ > 0 && linksize <= (MAXPATHLEN - 1)) {
+ buf[linksize] = '\0';
+ } else
+ return (-1);
+ } else
+ s_strlcpy(buf, devname, MAXPATHLEN);
+
+ if ((p = strstr(buf, SLASH_DEVICES)) == NULL)
+ return (-1);
+
+ /* point to '/' after /devices */
+ p += sizeof (SLASH_DEVICES) - 2;
+
+ if ((m = strrchr(p, ':')) == NULL) {
+ logdmsg("get_physname_minor: no minor name component in %s\n",
+ buf);
+ return (-1);
+ }
+
+ *m = '\0';
+ m++;
+
+ if (client_name_type(p) == CLIENT_TYPE_UNKNOWN)
+ return (-1);
+
+ s_strlcpy(physname, p, physname_len);
+ s_strlcpy(minorname, m, minorname_len);
+ logdmsg("get_physname_minor: %s: physname = %s, minor = %s\n",
+ devname, physname, minorname);
+ return (0);
+}
+
+
+/*
* Map phci based client name to vhci based client name.
*
* phci_name
@@ -860,18 +913,43 @@ phci_to_vhci(char *phci_name, char *vhci_name, size_t vhci_name_len)
* phci_name_len
* Length of the caller supplied phci_name buffer.
*
+ * minor
+ * The slice of the disk of interest.
+ *
* Returns 0 on success, -1 on failure.
*/
static int
-vhci_to_phci(char *vhci_name, char *phci_name, size_t phci_name_len)
+vhci_to_phci(char *vhci_name, char *phci_name, size_t phci_name_len,
+ char *minor)
{
di_node_t node = DI_NODE_NIL;
char *vhci_guid, *devfspath;
char phci_guid[MAXPATHLEN];
+ char root_guid[MAXPATHLEN];
+ char root_phys[MAXPATHLEN];
+ char root_minor[MAXPATHLEN];
+ char root_path[MAXPATHLEN];
char *node_name;
+ FILE *mntfp;
+ struct mnttab mntpref, rootmnt;
logdmsg("vhci_to_phci: client = %s\n", vhci_name);
+ bzero(&mntpref, sizeof (mntpref));
+ mntpref.mnt_mountp = "/";
+
+ if (!(mntfp = fopen(MNTTAB, "r"))) {
+ logdmsg("vhci_to_phci: can't open %s\n", MNTTAB);
+ return (-1);
+ }
+
+ if (getmntany(mntfp, &rootmnt, &mntpref)) {
+ logdmsg("vhci_to_phci: can't find / in %s\n", MNTTAB);
+ return (-1);
+ }
+
+ (void) fclose(mntfp);
+
if (client_name_type(vhci_name) != CLIENT_TYPE_VHCI) {
logdmsg("vhci_to_phci: %s is not of CLIENT_TYPE_VHCI\n",
vhci_name);
@@ -903,6 +981,37 @@ vhci_to_phci(char *vhci_name, char *phci_name, size_t phci_name_len)
logdmsg("vhci_to_phci: done taking devinfo snapshot\n");
}
+ if (strncmp(rootmnt.mnt_special, SLASH_DEVICES,
+ sizeof (SLASH_DEVICES)-1))
+ (void) snprintf(root_path, sizeof (root_path), "/devices%s",
+ rootmnt.mnt_special);
+ else
+ (void) strcpy(root_path, rootmnt.mnt_special);
+
+ /*
+ * remove the /devices and minor components to call get_guid()
+ * if we can't get the guid, drop through to the regular processing.
+ */
+ if ((get_physname_minor(root_path, root_phys, sizeof (root_phys),
+ root_minor, sizeof (root_minor)) ||
+ (get_guid(root_phys, root_guid, sizeof (root_guid), 0,
+ node) != 0))) {
+ logdmsg("vhci_to_phci: can't get_guid for / (%s)\n",
+ rootmnt.mnt_special);
+ (void) strcpy(root_guid, "");
+ }
+
+ /*
+ * We check the guid of the root device against the vhci guid so we
+ * can return a preferred path.
+ */
+ if ((strcmp(root_guid, vhci_guid) == 0) &&
+ (canread(root_phys, minor))) {
+ s_strlcpy(phci_name, root_phys, phci_name_len);
+ logdmsg("vhci_to_phci: %s maps to %s preferred path\n",
+ vhci_name, phci_name);
+ return (0);
+ }
/*
* When we finally get a unified "sd" driver for all
@@ -934,7 +1043,12 @@ vhci_to_phci(char *vhci_name, char *phci_name, size_t phci_name_len)
sizeof (phci_guid), 0, node) != 0)
continue;
- if (strcmp(phci_guid, vhci_guid) == 0) {
+ /*
+ * If the GUID's match, and we can read data from the path of
+ * interest, we conclude we have the correct path to use.
+ */
+ if ((strcmp(phci_guid, vhci_guid) == 0) &&
+ (canread(devfspath, minor))) {
s_strlcpy(phci_name, devfspath, phci_name_len);
di_devfs_path_free(devfspath);
logdmsg("vhci_to_phci: %s maps to %s\n", vhci_name,
@@ -970,7 +1084,12 @@ vhci_to_phci(char *vhci_name, char *phci_name, size_t phci_name_len)
sizeof (phci_guid), 0, node) != 0)
continue;
- if (strcmp(phci_guid, vhci_guid) == 0) {
+ /*
+ * If the GUID's match, and we can read data from the path of
+ * interest, we conclude we have the correct path to use.
+ */
+ if ((strcmp(phci_guid, vhci_guid) == 0) &&
+ (canread(devfspath, minor))) {
s_strlcpy(phci_name, devfspath, phci_name_len);
di_devfs_path_free(devfspath);
logdmsg("vhci_to_phci: %s maps to %s\n", vhci_name,
@@ -1116,10 +1235,13 @@ out:
* len
* Length of the caller supplied new_physname buffer.
*
+ * minor
+ * The slice of the disk of interest.
+ *
* Returns 0 on success, -1 on failure.
*/
static int
-map_physname(char *physname, char *new_physname, size_t len)
+map_physname(char *physname, char *new_physname, size_t len, char *minor)
{
int type;
int rv;
@@ -1129,7 +1251,7 @@ map_physname(char *physname, char *new_physname, size_t len)
type, physname);
if (type == CLIENT_TYPE_VHCI)
- rv = vhci_to_phci(physname, new_physname, len);
+ rv = vhci_to_phci(physname, new_physname, len, minor);
else if (type == CLIENT_TYPE_PHCI)
rv = phci_to_vhci(physname, new_physname, len);
else
@@ -1139,56 +1261,6 @@ map_physname(char *physname, char *new_physname, size_t len)
return (rv);
}
-/*
- * Given a phci or vhci devname which is either a /dev link or /devices name
- * get the corresponding physical node path (without the /devices prefix)
- * and minor name.
- *
- * Returns 0 on success, -1 on failure.
- */
-static int
-get_physname_minor(char *devname, char *physname, int physname_len,
- char *minorname, int minorname_len)
-{
- int linksize;
- char buf[MAXPATHLEN];
- char *p, *m;
-
- if (strncmp(devname, DEV_DSK, sizeof (DEV_DSK) - 1) == 0 ||
- strncmp(devname, DEV_RDSK, sizeof (DEV_RDSK) - 1) == 0) {
- if ((linksize = readlink(devname, buf, MAXPATHLEN))
- > 0 && linksize <= (MAXPATHLEN - 1)) {
- buf[linksize] = '\0';
- } else
- return (-1);
- } else
- s_strlcpy(buf, devname, MAXPATHLEN);
-
- if ((p = strstr(buf, SLASH_DEVICES)) == NULL)
- return (-1);
-
- /* point to '/' after /devices */
- p += sizeof (SLASH_DEVICES) - 2;
-
- if ((m = strrchr(p, ':')) == NULL) {
- logdmsg("get_physname_minor: no minor name component in %s\n",
- buf);
- return (-1);
- }
-
- *m = '\0';
- m++;
-
- if (client_name_type(p) == CLIENT_TYPE_UNKNOWN)
- return (-1);
-
- s_strlcpy(physname, p, physname_len);
- s_strlcpy(minorname, m, minorname_len);
- logdmsg("get_physname_minor: %s: physname = %s, minor = %s\n",
- devname, physname, minorname);
- return (0);
-}
-
static int
devlink_callback(di_devlink_t devlink, void *argptr)
{
@@ -1333,7 +1405,7 @@ map_devname(char *devname, char *new_devname, size_t len, int devlink_flag)
minor, sizeof (minor)) == 0) &&
(canopen(devname) == 0) &&
(map_physname(physname, new_physname,
- sizeof (new_physname)) == 0)) {
+ sizeof (new_physname), minor) == 0)) {
logdmsg("map_devname: now looking up devlink\n");
@@ -1469,7 +1541,7 @@ update_vfstab(char *vfstab_in, char *vfstab_out)
canopen(bdev) ||
(map_physname(phys_bdev, new_physname,
- sizeof (new_physname)) != 0) ||
+ sizeof (new_physname), bdev_minor) != 0) ||
(lookup_devlink(new_physname, bdev_minor, new_bdevlink,
sizeof (new_bdevlink)) != 0) ||
@@ -1855,3 +1927,30 @@ clean_exit(int status)
exit(status);
}
+
+/*
+ * Attempt to read some data from the specified slice from the device.
+ */
+static int
+canread(char *physname, char *minor)
+{
+ char devname[MAXPATHLEN];
+ int fd, rv = 0;
+ char tbuf[512];
+
+ (void) snprintf(devname, MAXPATHLEN, "/devices%s:%s", physname, minor);
+ if ((fd = open(devname, O_RDONLY)) == -1) {
+ logdmsg("canread: failed to open %s: %s\n", devname,
+ strerror(errno));
+ return (rv);
+ }
+
+ if (read(fd, tbuf, sizeof (tbuf)) < 0)
+ logdmsg("canread: failed to read %s: %s\n", devname,
+ strerror(errno));
+ else
+ rv = 1;
+
+ (void) close(fd);
+ return (rv);
+}