summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/boot/Makefile.version2
-rw-r--r--usr/src/boot/sys/boot/efi/include/efidevp.h8
-rw-r--r--usr/src/boot/sys/boot/efi/include/efilib.h1
-rw-r--r--usr/src/boot/sys/boot/efi/libefi/devpath.c10
-rw-r--r--usr/src/boot/sys/boot/efi/libefi/efipart.c531
-rw-r--r--usr/src/cmd/zfs/zfs_main.c24
-rw-r--r--usr/src/lib/libproc/common/Pzone.c9
-rw-r--r--usr/src/lib/libshare/common/libshare.c16
-rw-r--r--usr/src/lib/libshare/common/libshare.h4
-rw-r--r--usr/src/lib/libshare/common/mapfile-vers2
-rw-r--r--usr/src/lib/libzfs/common/libzfs_mount.c49
-rw-r--r--usr/src/uts/common/io/comstar/lu/stmf_sbd/sbd_scsi.c6
12 files changed, 391 insertions, 271 deletions
diff --git a/usr/src/boot/Makefile.version b/usr/src/boot/Makefile.version
index dbae2fd094..b8a19bf5ed 100644
--- a/usr/src/boot/Makefile.version
+++ b/usr/src/boot/Makefile.version
@@ -33,4 +33,4 @@ LOADER_VERSION = 1.1
# Use date like formatting here, YYYY.MM.DD.XX, without leading zeroes.
# The version is processed from left to right, the version number can only
# be increased.
-BOOT_VERSION = $(LOADER_VERSION)-2019.11.15.1
+BOOT_VERSION = $(LOADER_VERSION)-2019.11.26.1
diff --git a/usr/src/boot/sys/boot/efi/include/efidevp.h b/usr/src/boot/sys/boot/efi/include/efidevp.h
index 51ebd624e4..bd8f304922 100644
--- a/usr/src/boot/sys/boot/efi/include/efidevp.h
+++ b/usr/src/boot/sys/boot/efi/include/efidevp.h
@@ -282,6 +282,14 @@ typedef struct _UART_DEVICE_PATH {
#define DEVICE_PATH_MESSAGING_VT_UTF8 \
{ 0xad15a0d6, 0x8bec, 0x4acf, {0xa0, 0x73, 0xd0, 0x1d, 0xe7, 0x7e, 0x2d, 0x88} }
+/* Device Logical Unit SubType. */
+#define MSG_DEVICE_LOGICAL_UNIT_DP 0x11
+typedef struct {
+ EFI_DEVICE_PATH Header;
+ /* Logical Unit Number for the interface. */
+ UINT8 Lun;
+} DEVICE_LOGICAL_UNIT_DEVICE_PATH;
+
#define MSG_SATA_DP 0x12
typedef struct _SATA_DEVICE_PATH {
EFI_DEVICE_PATH Header;
diff --git a/usr/src/boot/sys/boot/efi/include/efilib.h b/usr/src/boot/sys/boot/efi/include/efilib.h
index bf975d1bbc..d1cced2e4d 100644
--- a/usr/src/boot/sys/boot/efi/include/efilib.h
+++ b/usr/src/boot/sys/boot/efi/include/efilib.h
@@ -79,6 +79,7 @@ int efi_handle_update_dev(EFI_HANDLE, struct devsw *, int, uint64_t);
EFI_DEVICE_PATH *efi_lookup_image_devpath(EFI_HANDLE);
EFI_DEVICE_PATH *efi_lookup_devpath(EFI_HANDLE);
+void efi_close_devpath(EFI_HANDLE);
EFI_HANDLE efi_devpath_handle(EFI_DEVICE_PATH *);
EFI_DEVICE_PATH *efi_devpath_last_node(EFI_DEVICE_PATH *);
EFI_DEVICE_PATH *efi_devpath_trim(EFI_DEVICE_PATH *);
diff --git a/usr/src/boot/sys/boot/efi/libefi/devpath.c b/usr/src/boot/sys/boot/efi/libefi/devpath.c
index fd67bc5d77..257d49fdd6 100644
--- a/usr/src/boot/sys/boot/efi/libefi/devpath.c
+++ b/usr/src/boot/sys/boot/efi/libefi/devpath.c
@@ -61,6 +61,16 @@ efi_lookup_devpath(EFI_HANDLE handle)
return (devpath);
}
+void
+efi_close_devpath(EFI_HANDLE handle)
+{
+ EFI_STATUS status;
+
+ status = BS->CloseProtocol(handle, &DevicePathGUID, IH, NULL);
+ if (EFI_ERROR(status))
+ printf("CloseProtocol error: %lu\n", EFI_ERROR_CODE(status));
+}
+
CHAR16 *
efi_devpath_name(EFI_DEVICE_PATH *devpath)
{
diff --git a/usr/src/boot/sys/boot/efi/libefi/efipart.c b/usr/src/boot/sys/boot/efi/libefi/efipart.c
index 65870cfc7a..fb9874f52b 100644
--- a/usr/src/boot/sys/boot/efi/libefi/efipart.c
+++ b/usr/src/boot/sys/boot/efi/libefi/efipart.c
@@ -43,9 +43,11 @@
static EFI_GUID blkio_guid = BLOCK_IO_PROTOCOL;
+typedef bool (*pd_test_cb_t)(pdinfo_t *, pdinfo_t *);
static int efipart_initfd(void);
static int efipart_initcd(void);
static int efipart_inithd(void);
+static void efipart_cdinfo_add(pdinfo_t *);
static int efipart_strategy(void *, int, daddr_t, size_t, char *, size_t *);
static int efipart_realstrategy(void *, int, daddr_t, size_t, char *, size_t *);
@@ -195,6 +197,123 @@ efiblk_pdinfo_count(pdinfo_list_t *pdi)
return (i);
}
+static pdinfo_t *
+efipart_find_parent(pdinfo_list_t *pdi, EFI_DEVICE_PATH *devpath)
+{
+ pdinfo_t *pd;
+ EFI_DEVICE_PATH *parent;
+
+ /* We want to find direct parent */
+ parent = efi_devpath_trim(devpath);
+ /* We should not get out of memory here but be careful. */
+ if (parent == NULL)
+ return (NULL);
+
+ STAILQ_FOREACH(pd, pdi, pd_link) {
+ /* We must have exact match. */
+ if (efi_devpath_match(pd->pd_devpath, parent))
+ break;
+ }
+ free(parent);
+ return (pd);
+}
+
+/*
+ * Return true when we should ignore this device.
+ */
+static bool
+efipart_ignore_device(EFI_HANDLE h, EFI_BLOCK_IO *blkio,
+ EFI_DEVICE_PATH *devpath)
+{
+ EFI_DEVICE_PATH *node, *parent;
+
+ /*
+ * We assume the block size 512 or greater power of 2.
+ * Also skip devices with block size > 64k (16 is max
+ * ashift supported by zfs).
+ * iPXE is known to insert stub BLOCK IO device with
+ * BlockSize 1.
+ */
+ if (blkio->Media->BlockSize < 512 ||
+ blkio->Media->BlockSize > (1 << 16) ||
+ !powerof2(blkio->Media->BlockSize)) {
+ efi_close_devpath(h);
+ return (true);
+ }
+
+ /* Allowed values are 0, 1 and power of 2. */
+ if (blkio->Media->IoAlign > 1 &&
+ !powerof2(blkio->Media->IoAlign)) {
+ efi_close_devpath(h);
+ return (true);
+ }
+
+ /*
+ * With device tree setup:
+ * PciRoot(0x0)/Pci(0x14,0x0)/USB(0x5,0)/USB(0x2,0x0)
+ * PciRoot(0x0)/Pci(0x14,0x0)/USB(0x5,0)/USB(0x2,0x0)/Unit(0x1)
+ * PciRoot(0x0)/Pci(0x14,0x0)/USB(0x5,0)/USB(0x2,0x0)/Unit(0x2)
+ * PciRoot(0x0)/Pci(0x14,0x0)/USB(0x5,0)/USB(0x2,0x0)/Unit(0x3)
+ * PciRoot(0x0)/Pci(0x14,0x0)/USB(0x5,0)/USB(0x2,0x0)/Unit(0x3)/CDROM..
+ * PciRoot(0x0)/Pci(0x14,0x0)/USB(0x5,0)/USB(0x2,0x0)/Unit(0x3)/CDROM..
+ * PciRoot(0x0)/Pci(0x14,0x0)/USB(0x5,0)/USB(0x2,0x0)/Unit(0x4)
+ * PciRoot(0x0)/Pci(0x14,0x0)/USB(0x5,0)/USB(0x2,0x0)/Unit(0x5)
+ * PciRoot(0x0)/Pci(0x14,0x0)/USB(0x5,0)/USB(0x2,0x0)/Unit(0x6)
+ * PciRoot(0x0)/Pci(0x14,0x0)/USB(0x5,0)/USB(0x2,0x0)/Unit(0x7)
+ *
+ * In above exmple only Unit(0x3) has media, all other nodes are
+ * missing media and should not be used.
+ *
+ * No media does not always mean there is no device, but in above
+ * case, we can not really assume there is any device.
+ * Therefore, if this node is USB, or this node is Unit (LUN) and
+ * direct parent is USB and we have no media, we will ignore this
+ * device.
+ */
+
+ /* Do not ignore device with media. */
+ if (blkio->Media->MediaPresent)
+ return (false);
+
+ node = efi_devpath_last_node(devpath);
+ if (node == NULL)
+ return (false);
+
+ /* USB without media present */
+ if (DevicePathType(node) == MESSAGING_DEVICE_PATH &&
+ DevicePathSubType(node) == MSG_USB_DP) {
+ efi_close_devpath(h);
+ return (true);
+ }
+
+ parent = efi_devpath_trim(devpath);
+ if (parent != NULL) {
+ bool parent_is_usb = false;
+
+ node = efi_devpath_last_node(parent);
+ if (node == NULL) {
+ free(parent);
+ return (false);
+ }
+ if (DevicePathType(node) == MESSAGING_DEVICE_PATH &&
+ DevicePathSubType(node) == MSG_USB_DP)
+ parent_is_usb = true;
+ free(parent);
+
+ /* no media, parent is usb and devicepath is lun. */
+ node = efi_devpath_last_node(devpath);
+ if (node == NULL)
+ return (false);
+ if (parent_is_usb &&
+ DevicePathType(node) == MESSAGING_DEVICE_PATH &&
+ DevicePathSubType(node) == MSG_DEVICE_LOGICAL_UNIT_DP) {
+ efi_close_devpath(h);
+ return (true);
+ }
+ }
+ return (false);
+}
+
int
efipart_inithandles(void)
{
@@ -242,24 +361,8 @@ efipart_inithandles(void)
continue;
}
- /*
- * We assume the block size 512 or greater power of 2.
- * Also skip devices with block size > 64k (16 is max
- * ashift supported by zfs).
- * iPXE is known to insert stub BLOCK IO device with
- * BlockSize 1.
- */
- if (blkio->Media->BlockSize < 512 ||
- blkio->Media->BlockSize > (1 << 16) ||
- !powerof2(blkio->Media->BlockSize)) {
+ if (efipart_ignore_device(hin[i], blkio, devpath))
continue;
- }
-
- /* Allowed values are 0, 1 and power of 2. */
- if (blkio->Media->IoAlign > 1 &&
- !powerof2(blkio->Media->IoAlign)) {
- continue;
- }
/* This is bad. */
if ((pd = calloc(1, sizeof (*pd))) == NULL) {
@@ -275,10 +378,32 @@ efipart_inithandles(void)
STAILQ_INSERT_TAIL(&pdinfo, pd, pd_link);
}
+ /*
+ * Walk pdinfo and set parents based on device path.
+ */
+ STAILQ_FOREACH(pd, &pdinfo, pd_link) {
+ pd->pd_parent = efipart_find_parent(&pdinfo, pd->pd_devpath);
+ }
free(hin);
return (0);
}
+/*
+ * Get node identified by pd_test() from plist.
+ */
+static pdinfo_t *
+efipart_get_pd(pdinfo_list_t *plist, pd_test_cb_t pd_test, pdinfo_t *data)
+{
+ pdinfo_t *pd;
+
+ STAILQ_FOREACH(pd, plist, pd_link) {
+ if (pd_test(pd, data))
+ break;
+ }
+
+ return (pd);
+}
+
static ACPI_HID_DEVICE_PATH *
efipart_floppy(EFI_DEVICE_PATH *node)
{
@@ -296,19 +421,19 @@ efipart_floppy(EFI_DEVICE_PATH *node)
return (NULL);
}
-static pdinfo_t *
-efipart_find_parent(pdinfo_list_t *pdi, EFI_DEVICE_PATH *devpath)
+static bool
+efipart_testfd(pdinfo_t *fd, pdinfo_t *data __unused)
{
- pdinfo_t *pd, *part;
+ EFI_DEVICE_PATH *node;
- STAILQ_FOREACH(pd, pdi, pd_link) {
- if (efi_devpath_is_prefix(pd->pd_devpath, devpath))
- return (pd);
- part = efipart_find_parent(&pd->pd_part, devpath);
- if (part != NULL)
- return (part);
- }
- return (NULL);
+ node = efi_devpath_last_node(fd->pd_devpath);
+ if (node == NULL)
+ return (false);
+
+ if (efipart_floppy(node) != NULL)
+ return (true);
+
+ return (false);
}
static int
@@ -318,8 +443,7 @@ efipart_initfd(void)
ACPI_HID_DEVICE_PATH *acpi;
pdinfo_t *parent, *fd;
-restart:
- STAILQ_FOREACH(fd, &pdinfo, pd_link) {
+ while ((fd = efipart_get_pd(&pdinfo, efipart_testfd, NULL)) != NULL) {
if ((node = efi_devpath_last_node(fd->pd_devpath)) == NULL)
continue;
@@ -327,7 +451,7 @@ restart:
continue;
STAILQ_REMOVE(&pdinfo, fd, pdinfo, pd_link);
- parent = efipart_find_parent(&pdinfo, fd->pd_devpath);
+ parent = fd->pd_parent;
if (parent != NULL) {
STAILQ_REMOVE(&pdinfo, parent, pdinfo, pd_link);
parent->pd_alias = fd->pd_handle;
@@ -339,7 +463,6 @@ restart:
}
fd->pd_devsw = &efipart_fddev;
STAILQ_INSERT_TAIL(&fdinfo, fd, pd_link);
- goto restart;
}
bcache_add_dev(efiblk_pdinfo_count(&fdinfo));
@@ -352,21 +475,36 @@ restart:
static void
efipart_cdinfo_add(pdinfo_t *cd)
{
- pdinfo_t *pd, *last;
-
- STAILQ_FOREACH(pd, &cdinfo, pd_link) {
- if (efi_devpath_is_prefix(pd->pd_devpath, cd->pd_devpath)) {
- last = STAILQ_LAST(&pd->pd_part, pdinfo, pd_link);
- if (last != NULL)
- cd->pd_unit = last->pd_unit + 1;
- else
- cd->pd_unit = 0;
- cd->pd_parent = pd;
- cd->pd_devsw = &efipart_cddev;
- STAILQ_INSERT_TAIL(&pd->pd_part, cd, pd_link);
- return;
+ pdinfo_t *parent, *pd, *last;
+
+ if (cd == NULL)
+ return;
+
+ parent = cd->pd_parent;
+ /* Make sure we have parent added */
+ efipart_cdinfo_add(parent);
+
+ STAILQ_FOREACH(pd, &pdinfo, pd_link) {
+ if (efi_devpath_match(pd->pd_devpath, cd->pd_devpath)) {
+ STAILQ_REMOVE(&pdinfo, cd, pdinfo, pd_link);
+ break;
}
}
+ if (pd == NULL) {
+ /* This device is already added. */
+ return;
+ }
+
+ if (parent != NULL) {
+ last = STAILQ_LAST(&parent->pd_part, pdinfo, pd_link);
+ if (last != NULL)
+ cd->pd_unit = last->pd_unit + 1;
+ else
+ cd->pd_unit = 0;
+ cd->pd_devsw = &efipart_cddev;
+ STAILQ_INSERT_TAIL(&parent->pd_part, cd, pd_link);
+ return;
+ }
last = STAILQ_LAST(&cdinfo, pdinfo, pd_link);
if (last != NULL)
@@ -374,189 +512,99 @@ efipart_cdinfo_add(pdinfo_t *cd)
else
cd->pd_unit = 0;
- cd->pd_parent = NULL;
cd->pd_devsw = &efipart_cddev;
STAILQ_INSERT_TAIL(&cdinfo, cd, pd_link);
}
static bool
-efipart_testcd(EFI_DEVICE_PATH *node, EFI_BLOCK_IO *blkio)
+efipart_testcd(pdinfo_t *cd, pdinfo_t *data __unused)
{
+ EFI_DEVICE_PATH *node;
+
+ node = efi_devpath_last_node(cd->pd_devpath);
+ if (node == NULL)
+ return (false);
+
+ if (efipart_floppy(node) != NULL)
+ return (false);
+
if (DevicePathType(node) == MEDIA_DEVICE_PATH &&
DevicePathSubType(node) == MEDIA_CDROM_DP) {
return (true);
}
/* cd drive without the media. */
- if (blkio->Media->RemovableMedia &&
- !blkio->Media->MediaPresent) {
+ if (cd->pd_blkio->Media->RemovableMedia &&
+ !cd->pd_blkio->Media->MediaPresent) {
return (true);
}
return (false);
}
-static void
-efipart_updatecd(void)
+/*
+ * Test if pd is parent for device.
+ */
+static bool
+efipart_testchild(pdinfo_t *dev, pdinfo_t *pd)
{
- EFI_DEVICE_PATH *devpath, *node;
- EFI_STATUS status;
- pdinfo_t *parent, *cd;
-
-restart:
- STAILQ_FOREACH(cd, &pdinfo, pd_link) {
- if ((node = efi_devpath_last_node(cd->pd_devpath)) == NULL)
- continue;
-
- if (efipart_floppy(node) != NULL)
- continue;
-
- /* Is parent of this device already registered? */
- parent = efipart_find_parent(&cdinfo, cd->pd_devpath);
- if (parent != NULL) {
- STAILQ_REMOVE(&pdinfo, cd, pdinfo, pd_link);
- efipart_cdinfo_add(cd);
- goto restart;
- }
-
- if (!efipart_testcd(node, cd->pd_blkio))
- continue;
-
- /* Find parent and unlink both parent and cd from pdinfo */
- STAILQ_REMOVE(&pdinfo, cd, pdinfo, pd_link);
- parent = efipart_find_parent(&pdinfo, cd->pd_devpath);
- if (parent != NULL) {
- STAILQ_REMOVE(&pdinfo, parent, pdinfo, pd_link);
- efipart_cdinfo_add(parent);
- }
-
- if (parent == NULL)
- parent = efipart_find_parent(&cdinfo, cd->pd_devpath);
-
- /*
- * If we come across a logical partition of subtype CDROM
- * it doesn't refer to the CD filesystem itself, but rather
- * to any usable El Torito boot image on it. In this case
- * we try to find the parent device and add that instead as
- * that will be the CD filesystem.
- */
- if (DevicePathType(node) == MEDIA_DEVICE_PATH &&
- DevicePathSubType(node) == MEDIA_CDROM_DP &&
- parent == NULL) {
- parent = calloc(1, sizeof (*parent));
- if (parent == NULL) {
- printf("efipart_updatecd: out of memory\n");
- /* this device is lost but try again. */
- free(cd);
- goto restart;
- }
-
- devpath = efi_devpath_trim(cd->pd_devpath);
- if (devpath == NULL) {
- printf("efipart_updatecd: out of memory\n");
- /* this device is lost but try again. */
- free(parent);
- free(cd);
- goto restart;
- }
- parent->pd_devpath = devpath;
- status = BS->LocateDevicePath(&blkio_guid,
- &parent->pd_devpath, &parent->pd_handle);
- free(devpath);
- if (EFI_ERROR(status)) {
- printf("efipart_updatecd: error %lu\n",
- EFI_ERROR_CODE(status));
- free(parent);
- free(cd);
- goto restart;
- }
- parent->pd_devpath =
- efi_lookup_devpath(parent->pd_handle);
- efipart_cdinfo_add(parent);
- }
+ /* device with no parent. */
+ if (dev->pd_parent == NULL)
+ return (false);
- efipart_cdinfo_add(cd);
- goto restart;
+ if (efi_devpath_match(dev->pd_parent->pd_devpath, pd->pd_devpath)) {
+ return (true);
}
+ return (false);
}
static int
efipart_initcd(void)
{
- efipart_updatecd();
+ pdinfo_t *cd;
+
+ while ((cd = efipart_get_pd(&pdinfo, efipart_testcd, NULL)) != NULL)
+ efipart_cdinfo_add(cd);
+
+ /* Find all children of CD devices we did add above. */
+ STAILQ_FOREACH(cd, &cdinfo, pd_link) {
+ pdinfo_t *child;
+ for (child = efipart_get_pd(&pdinfo, efipart_testchild, cd);
+ child != NULL;
+ child = efipart_get_pd(&pdinfo, efipart_testchild, cd))
+ efipart_cdinfo_add(child);
+ }
bcache_add_dev(efiblk_pdinfo_count(&cdinfo));
return (0);
}
-static bool
+static void
efipart_hdinfo_add_node(pdinfo_t *hd, EFI_DEVICE_PATH *node)
{
- pdinfo_t *pd, *ptr;
+ pdinfo_t *parent, *ptr;
if (node == NULL)
- return (false);
-
- /* Find our disk device. */
- STAILQ_FOREACH(pd, &hdinfo, pd_link) {
- if (efi_devpath_is_prefix(pd->pd_devpath, hd->pd_devpath))
- break;
- }
- if (pd == NULL)
- return (false);
+ return;
- /* If the node is not MEDIA_HARDDRIVE_DP, it is sub-partition. */
+ parent = hd->pd_parent;
+ /*
+ * If the node is not MEDIA_HARDDRIVE_DP, it is sub-partition.
+ * This can happen with Vendor nodes, and since we do not know
+ * the more about those nodes, we just count them.
+ */
if (DevicePathSubType(node) != MEDIA_HARDDRIVE_DP) {
- STAILQ_FOREACH(ptr, &pd->pd_part, pd_link) {
- if (efi_devpath_is_prefix(ptr->pd_devpath,
- hd->pd_devpath))
- break;
- }
- /*
- * If we don't find a pdinfo_t for this node, then that
- * means that the partition list we got from firmware isn't
- * properly ordered. We assume that firmware has ordered it.
- * In case we don't find anything, rather than blow up, we
- * add this node as another partition.
- */
- if (ptr != NULL)
- pd = ptr;
-
- /* Add the partition. */
- ptr = STAILQ_LAST(&pd->pd_part, pdinfo, pd_link);
+ ptr = STAILQ_LAST(&parent->pd_part, pdinfo, pd_link);
if (ptr != NULL)
hd->pd_unit = ptr->pd_unit + 1;
else
hd->pd_unit = 0;
} else {
- /* Add the partition. */
hd->pd_unit = ((HARDDRIVE_DEVICE_PATH *)node)->PartitionNumber;
}
- hd->pd_parent = pd;
hd->pd_devsw = &efipart_hddev;
-
- STAILQ_INSERT_TAIL(&pd->pd_part, hd, pd_link);
- return (true);
-}
-
-static void
-efipart_hdinfo_add(pdinfo_t *hd, EFI_DEVICE_PATH *node)
-{
- pdinfo_t *last;
-
- if (efipart_hdinfo_add_node(hd, node))
- return;
-
- last = STAILQ_LAST(&hdinfo, pdinfo, pd_link);
- if (last != NULL)
- hd->pd_unit = last->pd_unit + 1;
- else
- hd->pd_unit = 0;
-
- /* Add the disk. */
- hd->pd_devsw = &efipart_hddev;
- STAILQ_INSERT_TAIL(&hdinfo, hd, pd_link);
+ STAILQ_INSERT_TAIL(&parent->pd_part, hd, pd_link);
}
/*
@@ -629,96 +677,75 @@ efipart_hdinfo_add_filepath(pdinfo_t *hd, FILEPATH_DEVICE_PATH *node)
}
static void
-efipart_updatehd(void)
+efipart_hdinfo_add(pdinfo_t *hd)
{
- EFI_DEVICE_PATH *devpath, *node;
- EFI_STATUS status;
- pdinfo_t *parent, *hd;
-
-restart:
- STAILQ_FOREACH(hd, &pdinfo, pd_link) {
- if ((node = efi_devpath_last_node(hd->pd_devpath)) == NULL)
- continue;
+ pdinfo_t *parent, *pd, *last;
+ EFI_DEVICE_PATH *node;
- if (efipart_floppy(node) != NULL)
- continue;
+ if (hd == NULL)
+ return;
- if (efipart_testcd(node, hd->pd_blkio))
- continue;
+ parent = hd->pd_parent;
+ /* Make sure we have parent added */
+ efipart_hdinfo_add(parent);
- if (DevicePathType(node) == HARDWARE_DEVICE_PATH &&
- (DevicePathSubType(node) == HW_PCI_DP ||
- DevicePathSubType(node) == HW_VENDOR_DP)) {
+ STAILQ_FOREACH(pd, &pdinfo, pd_link) {
+ if (efi_devpath_match(pd->pd_devpath, hd->pd_devpath)) {
STAILQ_REMOVE(&pdinfo, hd, pdinfo, pd_link);
- efipart_hdinfo_add(hd, NULL);
- goto restart;
+ break;
}
+ }
+ if (pd == NULL) {
+ /* This device is already added. */
+ return;
+ }
- if (DevicePathType(node) == MEDIA_DEVICE_PATH &&
- DevicePathSubType(node) == MEDIA_FILEPATH_DP) {
- STAILQ_REMOVE(&pdinfo, hd, pdinfo, pd_link);
- efipart_hdinfo_add_filepath(hd,
- (FILEPATH_DEVICE_PATH *)node);
- goto restart;
- }
+ if ((node = efi_devpath_last_node(hd->pd_devpath)) == NULL)
+ return;
- STAILQ_REMOVE(&pdinfo, hd, pdinfo, pd_link);
- parent = efipart_find_parent(&pdinfo, hd->pd_devpath);
- if (parent != NULL) {
- STAILQ_REMOVE(&pdinfo, parent, pdinfo, pd_link);
- efipart_hdinfo_add(parent, NULL);
- } else {
- parent = efipart_find_parent(&hdinfo, hd->pd_devpath);
- }
+ if (DevicePathType(node) == MEDIA_DEVICE_PATH &&
+ DevicePathSubType(node) == MEDIA_FILEPATH_DP) {
+ efipart_hdinfo_add_filepath(hd,
+ (FILEPATH_DEVICE_PATH *)node);
+ return;
+ }
- if (DevicePathType(node) == MEDIA_DEVICE_PATH &&
- DevicePathSubType(node) == MEDIA_HARDDRIVE_DP &&
- parent == NULL) {
- parent = calloc(1, sizeof (*parent));
- if (parent == NULL) {
- printf("efipart_updatehd: out of memory\n");
- /* this device is lost but try again. */
- free(hd);
- goto restart;
- }
+ if (parent != NULL) {
+ efipart_hdinfo_add_node(hd, node);
+ return;
+ }
- devpath = efi_devpath_trim(hd->pd_devpath);
- if (devpath == NULL) {
- printf("efipart_updatehd: out of memory\n");
- /* this device is lost but try again. */
- free(parent);
- free(hd);
- goto restart;
- }
+ last = STAILQ_LAST(&hdinfo, pdinfo, pd_link);
+ if (last != NULL)
+ hd->pd_unit = last->pd_unit + 1;
+ else
+ hd->pd_unit = 0;
- parent->pd_devpath = devpath;
- status = BS->LocateDevicePath(&blkio_guid,
- &parent->pd_devpath, &parent->pd_handle);
- free(devpath);
- if (EFI_ERROR(status)) {
- printf("efipart_updatehd: error %lu\n",
- EFI_ERROR_CODE(status));
- free(parent);
- free(hd);
- goto restart;
- }
+ /* Add the disk. */
+ hd->pd_devsw = &efipart_hddev;
+ STAILQ_INSERT_TAIL(&hdinfo, hd, pd_link);
+}
- parent->pd_devpath =
- efi_lookup_devpath(&parent->pd_handle);
+static bool
+efipart_testhd(pdinfo_t *hd, pdinfo_t *data __unused)
+{
+ if (efipart_testfd(hd, NULL))
+ return (false);
- efipart_hdinfo_add(parent, NULL);
- }
+ if (efipart_testcd(hd, NULL))
+ return (false);
- efipart_hdinfo_add(hd, node);
- goto restart;
- }
+ /* Anything else must be HD. */
+ return (true);
}
static int
efipart_inithd(void)
{
+ pdinfo_t *hd;
- efipart_updatehd();
+ while ((hd = efipart_get_pd(&pdinfo, efipart_testhd, NULL)) != NULL)
+ efipart_hdinfo_add(hd);
bcache_add_dev(efiblk_pdinfo_count(&hdinfo));
return (0);
diff --git a/usr/src/cmd/zfs/zfs_main.c b/usr/src/cmd/zfs/zfs_main.c
index faf6b7c473..ef3f9155f3 100644
--- a/usr/src/cmd/zfs/zfs_main.c
+++ b/usr/src/cmd/zfs/zfs_main.c
@@ -6999,6 +6999,30 @@ unshare_unmount(int op, int argc, char **argv)
}
/*
+ * Initialize libshare SA_INIT_SHARE_API_SELECTIVE here
+ * to avoid unnecessary load/unload of the libshare API
+ * per shared dataset downstream.
+ */
+ if (op == OP_SHARE) {
+ get_all_cb_t dslist = { 0 };
+ get_all_datasets(&dslist, B_FALSE);
+
+ if (dslist.cb_used != 0) {
+ sa_init_selective_arg_t sharearg;
+ sharearg.zhandle_arr = dslist.cb_handles;
+ sharearg.zhandle_len = dslist.cb_used;
+ if ((ret = zfs_init_libshare_arg(g_zfs,
+ SA_INIT_SHARE_API_SELECTIVE, &sharearg)) !=
+ SA_OK) {
+ (void) fprintf(stderr, gettext(
+ "Could not initialize libshare, "
+ "%d"), ret);
+ return (1);
+ }
+ }
+ }
+
+ /*
* Walk the AVL tree in reverse, unmounting each filesystem and
* removing it from the AVL tree in the process.
*/
diff --git a/usr/src/lib/libproc/common/Pzone.c b/usr/src/lib/libproc/common/Pzone.c
index 3c4999bbe4..d2562a2a79 100644
--- a/usr/src/lib/libproc/common/Pzone.c
+++ b/usr/src/lib/libproc/common/Pzone.c
@@ -795,9 +795,14 @@ Pfindmap(struct ps_prochandle *P, map_info_t *mptr, char *s, size_t n)
/* Try /proc first to get the real object name */
if ((Pstate(P) != PS_DEAD) && (mptr->map_pmap.pr_mapname[0] != '\0')) {
- (void) snprintf(buf, sizeof (buf), "%s/%d/path/%s",
+ char path[PATH_MAX];
+
+ len = snprintf(path, sizeof (path), "%s/%d/path/%s",
procfs_path, (int)P->pid, mptr->map_pmap.pr_mapname);
- if ((len = readlink(buf, buf, sizeof (buf))) > 0) {
+ if (len < 0 || (size_t)len >= sizeof (path))
+ return (NULL);
+
+ if ((len = readlink(path, buf, sizeof (buf))) > 0) {
buf[len] = '\0';
(void) Plofspath(buf, buf, sizeof (buf));
(void) strlcpy(s, buf, n);
diff --git a/usr/src/lib/libshare/common/libshare.c b/usr/src/lib/libshare/common/libshare.c
index 5a58e0268e..a507e8a1a5 100644
--- a/usr/src/lib/libshare/common/libshare.c
+++ b/usr/src/lib/libshare/common/libshare.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2016 by Delphix. All rights reserved.
*/
@@ -1153,6 +1153,20 @@ sa_fini(sa_handle_t handle)
}
/*
+ * sa_service(sa_handle_t handle)
+ *
+ * Returns the service for which the handle is currently initialized.
+ */
+int
+sa_service(sa_handle_t handle)
+{
+ if (handle == NULL)
+ return (0);
+
+ return (((sa_handle_impl_t)handle)->sa_service);
+}
+
+/*
* sa_get_protocols(char **protocol)
* Get array of protocols that are supported
* Returns pointer to an allocated and NULL terminated
diff --git a/usr/src/lib/libshare/common/libshare.h b/usr/src/lib/libshare/common/libshare.h
index 7ad9fefdcd..042a6f8cee 100644
--- a/usr/src/lib/libshare/common/libshare.h
+++ b/usr/src/lib/libshare/common/libshare.h
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2016 by Delphix. All rights reserved.
*/
@@ -171,6 +171,8 @@ typedef struct sa_init_selective_arg sa_init_selective_arg_t;
extern sa_handle_t sa_init(int);
extern sa_handle_t sa_init_arg(int, void *);
extern void sa_fini(sa_handle_t);
+extern int sa_service(sa_handle_t);
+
extern int sa_update_config(sa_handle_t);
extern boolean_t sa_needs_refresh(sa_handle_t);
extern char *sa_errorstr(int);
diff --git a/usr/src/lib/libshare/common/mapfile-vers b/usr/src/lib/libshare/common/mapfile-vers
index de74d62038..c661589eda 100644
--- a/usr/src/lib/libshare/common/mapfile-vers
+++ b/usr/src/lib/libshare/common/mapfile-vers
@@ -21,6 +21,7 @@
#
# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2016 by Delphix. All rights reserved.
+# Copyright 2018 Nexenta Systems, Inc. All rights reserved.
#
#
@@ -114,6 +115,7 @@ SYMBOL_VERSION SUNWprivate {
sa_get_protocol_status;
sa_init;
sa_init_arg;
+ sa_service;
sa_find_share;
sa_set_protocol_property;
sa_fini;
diff --git a/usr/src/lib/libzfs/common/libzfs_mount.c b/usr/src/lib/libzfs/common/libzfs_mount.c
index 44c0ec89e9..aea93fb91e 100644
--- a/usr/src/lib/libzfs/common/libzfs_mount.c
+++ b/usr/src/lib/libzfs/common/libzfs_mount.c
@@ -612,6 +612,7 @@ zfs_is_shared_smb(zfs_handle_t *zhp, char **where)
static sa_handle_t (*_sa_init)(int);
static sa_handle_t (*_sa_init_arg)(int, void *);
+static int (*_sa_service)(sa_handle_t);
static void (*_sa_fini)(sa_handle_t);
static sa_share_t (*_sa_find_share)(sa_handle_t, char *);
static int (*_sa_enable_share)(sa_share_t, char *);
@@ -654,6 +655,8 @@ _zfs_init_libshare(void)
_sa_init_arg = (sa_handle_t (*)(int, void *))dlsym(libshare,
"sa_init_arg");
_sa_fini = (void (*)(sa_handle_t))dlsym(libshare, "sa_fini");
+ _sa_service = (int (*)(sa_handle_t))dlsym(libshare,
+ "sa_service");
_sa_find_share = (sa_share_t (*)(sa_handle_t, char *))
dlsym(libshare, "sa_find_share");
_sa_enable_share = (int (*)(sa_share_t, char *))dlsym(libshare,
@@ -677,10 +680,11 @@ _zfs_init_libshare(void)
_sa_enable_share == NULL || _sa_disable_share == NULL ||
_sa_errorstr == NULL || _sa_parse_legacy_options == NULL ||
_sa_needs_refresh == NULL || _sa_get_zfs_handle == NULL ||
- _sa_zfs_process_share == NULL ||
+ _sa_zfs_process_share == NULL || _sa_service == NULL ||
_sa_update_sharetab_ts == NULL) {
_sa_init = NULL;
_sa_init_arg = NULL;
+ _sa_service = NULL;
_sa_fini = NULL;
_sa_disable_share = NULL;
_sa_enable_share = NULL;
@@ -839,11 +843,25 @@ zfs_share_proto(zfs_handle_t *zhp, zfs_share_proto_t *proto)
sa_share_t share;
zfs_share_proto_t *curr_proto;
zprop_source_t sourcetype;
+ int service = SA_INIT_ONE_SHARE_FROM_HANDLE;
int ret;
if (!zfs_is_mountable(zhp, mountpoint, sizeof (mountpoint), NULL))
return (0);
+ /*
+ * Function may be called in a loop from higher up stack, with libshare
+ * initialized for multiple shares (SA_INIT_SHARE_API_SELECTIVE).
+ * zfs_init_libshare_arg will refresh the handle's cache if necessary.
+ * In this case we do not want to switch to per share initialization.
+ * Specify SA_INIT_SHARE_API to do full refresh, if refresh required.
+ */
+ if ((hdl->libzfs_sharehdl != NULL) && (_sa_service != NULL) &&
+ (_sa_service(hdl->libzfs_sharehdl) ==
+ SA_INIT_SHARE_API_SELECTIVE)) {
+ service = SA_INIT_SHARE_API;
+ }
+
for (curr_proto = proto; *curr_proto != PROTO_END; curr_proto++) {
/*
* Return success if there are no share options.
@@ -853,8 +871,7 @@ zfs_share_proto(zfs_handle_t *zhp, zfs_share_proto_t *proto)
ZFS_MAXPROPLEN, B_FALSE) != 0 ||
strcmp(shareopts, "off") == 0)
continue;
- ret = zfs_init_libshare_arg(hdl, SA_INIT_ONE_SHARE_FROM_HANDLE,
- zhp);
+ ret = zfs_init_libshare_arg(hdl, service, zhp);
if (ret != SA_OK) {
(void) zfs_error_fmt(hdl, EZFS_SHARENFSFAILED,
dgettext(TEXT_DOMAIN, "cannot share '%s': %s"),
@@ -948,6 +965,7 @@ unshare_one(libzfs_handle_t *hdl, const char *name, const char *mountpoint,
sa_share_t share;
int err;
char *mntpt;
+ int service = SA_INIT_ONE_SHARE_FROM_NAME;
/*
* Mountpoint could get trashed if libshare calls getmntany
@@ -957,13 +975,20 @@ unshare_one(libzfs_handle_t *hdl, const char *name, const char *mountpoint,
mntpt = zfs_strdup(hdl, mountpoint);
/*
- * make sure libshare initialized, initialize everything because we
- * don't know what other unsharing may happen later. Functions up the
- * stack are allowed to initialize instead a subset of shares at the
- * time the set is known.
+ * Function may be called in a loop from higher up stack, with libshare
+ * initialized for multiple shares (SA_INIT_SHARE_API_SELECTIVE).
+ * zfs_init_libshare_arg will refresh the handle's cache if necessary.
+ * In this case we do not want to switch to per share initialization.
+ * Specify SA_INIT_SHARE_API to do full refresh, if refresh required.
*/
- if ((err = zfs_init_libshare_arg(hdl, SA_INIT_ONE_SHARE_FROM_NAME,
- (void *)name)) != SA_OK) {
+ if ((hdl->libzfs_sharehdl != NULL) && (_sa_service != NULL) &&
+ (_sa_service(hdl->libzfs_sharehdl) ==
+ SA_INIT_SHARE_API_SELECTIVE)) {
+ service = SA_INIT_SHARE_API;
+ }
+
+ err = zfs_init_libshare_arg(hdl, service, (void *)name);
+ if (err != SA_OK) {
free(mntpt); /* don't need the copy anymore */
return (zfs_error_fmt(hdl, proto_table[proto].p_unshare_err,
dgettext(TEXT_DOMAIN, "cannot unshare '%s': %s"),
@@ -1532,9 +1557,9 @@ zpool_enable_datasets(zpool_handle_t *zhp, const char *mntopts, int flags)
ret = ms.ms_mntstatus;
/*
- * Share all filesystems that need to be shared. This needs to be
- * a separate pass because libshare is not mt-safe, and so we need
- * to share serially.
+ * Initialize libshare SA_INIT_SHARE_API_SELECTIVE here
+ * to avoid unnecessary load/unload of the libshare API
+ * per shared dataset downstream.
*/
sharearg.zhandle_arr = cb.cb_handles;
sharearg.zhandle_len = cb.cb_used;
diff --git a/usr/src/uts/common/io/comstar/lu/stmf_sbd/sbd_scsi.c b/usr/src/uts/common/io/comstar/lu/stmf_sbd/sbd_scsi.c
index 8c6cac96c9..4ab032e354 100644
--- a/usr/src/uts/common/io/comstar/lu/stmf_sbd/sbd_scsi.c
+++ b/usr/src/uts/common/io/comstar/lu/stmf_sbd/sbd_scsi.c
@@ -23,6 +23,7 @@
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2017 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright 2019 Joyent, Inc.
*/
#include <sys/conf.h>
@@ -3988,8 +3989,7 @@ sbd_lu_reset_state(stmf_lu_t *lu)
sbd_status_t
sbd_flush_data_cache(sbd_lu_t *sl, int fsync_done)
{
- int r = 0;
- sbd_status_t ret;
+ sbd_status_t ret = SBD_SUCCESS;
rw_enter(&sl->sl_access_state_lock, RW_READER);
if ((sl->sl_flags & SL_MEDIA_LOADED) == 0) {
@@ -4007,6 +4007,8 @@ sbd_flush_data_cache(sbd_lu_t *sl, int fsync_done)
over_fsync:
if (((sl->sl_data_vtype == VCHR) || (sl->sl_data_vtype == VBLK)) &&
((sl->sl_flags & SL_NO_DATA_DKIOFLUSH) == 0)) {
+ int r = 0;
+
ret = VOP_IOCTL(sl->sl_data_vp, DKIOCFLUSHWRITECACHE, 0,
FKIOCTL, kcred, &r, NULL);
if ((ret == ENOTTY) || (ret == ENOTSUP)) {