summaryrefslogtreecommitdiff
path: root/usr/src/cmd/devfsadm
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/devfsadm')
-rw-r--r--usr/src/cmd/devfsadm/devfsadm.c76
-rw-r--r--usr/src/cmd/devfsadm/disk_link.c66
-rw-r--r--usr/src/cmd/devfsadm/lofi_link.c29
3 files changed, 126 insertions, 45 deletions
diff --git a/usr/src/cmd/devfsadm/devfsadm.c b/usr/src/cmd/devfsadm/devfsadm.c
index 448554a5e0..7d7904e9c0 100644
--- a/usr/src/cmd/devfsadm/devfsadm.c
+++ b/usr/src/cmd/devfsadm/devfsadm.c
@@ -20,6 +20,7 @@
*/
/*
+ * Copyright 2016 Toomas Soome <tsoome@me.com>
* Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
*/
@@ -3289,7 +3290,7 @@ rm_parent_dir_if_empty(char *pathname)
*/
void
devfsadm_rm_stale_links(char *dir_re, char *valid_link, di_node_t node,
- di_minor_t minor)
+ di_minor_t minor)
{
link_t *link;
linkhead_t *head;
@@ -4837,7 +4838,7 @@ get_component(char *str, const char *comp_str)
*/
int
devfsadm_enumerate_int(char *devfs_path, int index, char **buf,
- devfsadm_enumerate_t rules[], int nrules)
+ devfsadm_enumerate_t rules[], int nrules)
{
return (find_enum_id(rules, nrules,
devfs_path, index, "0", INTEGER, buf, 0));
@@ -4857,7 +4858,7 @@ disk_enumerate_int(char *devfs_path, int index, char **buf,
*/
static int
devfsadm_enumerate_int_start(char *devfs_path, int index, char **buf,
- devfsadm_enumerate_t rules[], int nrules, char *start)
+ devfsadm_enumerate_t rules[], int nrules, char *start)
{
return (find_enum_id(rules, nrules,
devfs_path, index, start, INTEGER, buf, 0));
@@ -4869,7 +4870,7 @@ devfsadm_enumerate_int_start(char *devfs_path, int index, char **buf,
*/
int
devfsadm_enumerate_char(char *devfs_path, int index, char **buf,
- devfsadm_enumerate_t rules[], int nrules)
+ devfsadm_enumerate_t rules[], int nrules)
{
return (find_enum_id(rules, nrules,
devfs_path, index, "a", LETTER, buf, 0));
@@ -4881,7 +4882,7 @@ devfsadm_enumerate_char(char *devfs_path, int index, char **buf,
*/
int
devfsadm_enumerate_char_start(char *devfs_path, int index, char **buf,
- devfsadm_enumerate_t rules[], int nrules, char *start)
+ devfsadm_enumerate_t rules[], int nrules, char *start)
{
return (find_enum_id(rules, nrules,
devfs_path, index, start, LETTER, buf, 0));
@@ -4898,8 +4899,8 @@ devfsadm_enumerate_char_start(char *devfs_path, int index, char **buf,
*/
static int
find_enum_id(devfsadm_enumerate_t rules[], int nrules,
- char *devfs_path, int index, char *min, int type, char **buf,
- int multiple)
+ char *devfs_path, int index, char *min, int type, char **buf,
+ int multiple)
{
numeral_t *matchnp;
numeral_t *numeral;
@@ -4999,7 +5000,7 @@ find_enum_id(devfsadm_enumerate_t rules[], int nrules,
*/
static int
lookup_enum_cache(numeral_set_t *set, char *cmp_str,
- devfsadm_enumerate_t rules[], int index, numeral_t **matchnpp)
+ devfsadm_enumerate_t rules[], int index, numeral_t **matchnpp)
{
int matchcount = 0, rv = -1;
int uncached;
@@ -5390,7 +5391,7 @@ new_id(numeral_t *numeral, int type, char *min)
static int
enumerate_parse(char *rsvstr, char *path_left, numeral_set_t *setp,
- devfsadm_enumerate_t rules[], int index)
+ devfsadm_enumerate_t rules[], int index)
{
char *slash1 = NULL;
char *slash2 = NULL;
@@ -5506,7 +5507,7 @@ out:
*/
static void
enumerate_recurse(char *current_dir, char *path_left, numeral_set_t *setp,
- devfsadm_enumerate_t rules[], int index)
+ devfsadm_enumerate_t rules[], int index)
{
char *slash;
char *new_path;
@@ -5661,7 +5662,7 @@ create_reserved_numeral(numeral_set_t *setp, char *numeral_id)
*/
static void
create_cached_numeral(char *path, numeral_set_t *setp, char *numeral_id,
- devfsadm_enumerate_t rules[], int index)
+ devfsadm_enumerate_t rules[], int index)
{
char linkbuf[PATH_MAX + 1];
char lpath[PATH_MAX + 1];
@@ -5838,7 +5839,7 @@ devfsadm_copy(void)
/*ARGSUSED*/
static int
devfsadm_copy_file(const char *file, const struct stat *stat,
- int flags, struct FTW *ftw)
+ int flags, struct FTW *ftw)
{
struct stat sp;
dev_t newdev;
@@ -6290,7 +6291,7 @@ read_devlinktab_file(void)
*/
static int
split_devlinktab_entry(char *entry, char **selector, char **p_link,
- char **s_link)
+ char **s_link)
{
char *tab;
@@ -6726,7 +6727,7 @@ get_anchored_re(char *link, char *anchored_re, char *pattern)
static int
construct_devlink(char *link, link_list_t *link_build, char *contents,
- di_minor_t minor, di_node_t node, char *pattern)
+ di_minor_t minor, di_node_t node, char *pattern)
{
int counter_offset = -1;
devfsadm_enumerate_t rules[1] = {NULL};
@@ -7133,7 +7134,7 @@ dequote(char *src)
*/
static void
getattr(char *phy_path, char *aminor, int spectype, dev_t dev, mode_t *mode,
- uid_t *uid, gid_t *gid)
+ uid_t *uid, gid_t *gid)
{
char devname[PATH_MAX + 1];
char *node_name;
@@ -8219,6 +8220,26 @@ build_event_attributes(char *class, char *subclass, char *node_path,
goto out;
if (strcmp(subclass, ESC_DISK) == 0) {
+ /*
+ * While we're removing labeled lofi device, we will receive
+ * event for every registered minor device and lastly,
+ * an event with minor set to NULL, as in following example:
+ * class: EC_dev_remove subclass: disk
+ * node_path: /pseudo/lofi@1 driver: lofi minor: u,raw
+ * class: EC_dev_remove subclass: disk
+ * node_path: /pseudo/lofi@1 driver: lofi minor: NULL
+ *
+ * When we receive this last event with minor set to NULL,
+ * all lofi minor devices are already removed and the call to
+ * lookup_disk_dev_name() would result in error.
+ * To prevent name lookup error messages for this case, we
+ * need to filter out that last event.
+ */
+ if (strcmp(class, EC_DEV_REMOVE) == 0 &&
+ strcmp(driver_name, "lofi") == 0 && minor == NULL) {
+ nvlist_free(nvl);
+ return (NULL);
+ }
if ((dev_name = lookup_disk_dev_name(node_path)) == NULL) {
dev_name_lookup_err = 1;
goto out;
@@ -8239,11 +8260,26 @@ build_event_attributes(char *class, char *subclass, char *node_path,
* The raw minor node is created or removed after the block
* node. Lofi devfs events are dependent on this behavior.
* Generate the sysevent only for the raw minor node.
+ *
+ * If the lofi mapping is created, we will receive the following
+ * event: class: EC_dev_add subclass: lofi minor: NULL
+ *
+ * As in case of EC_dev_add, the minor is NULL pointer,
+ * to get device links created, we will need to provide the
+ * type of minor node for lookup_lofi_dev_name()
+ *
+ * If the lofi device is unmapped, we will receive following
+ * events:
+ * class: EC_dev_remove subclass: lofi minor: disk
+ * class: EC_dev_remove subclass: lofi minor: disk,raw
+ * class: EC_dev_remove subclass: lofi minor: NULL
*/
- if (strstr(minor, "raw") == NULL) {
- if (nvl) {
- nvlist_free(nvl);
- }
+
+ if (strcmp(class, EC_DEV_ADD) == 0 && minor == NULL)
+ minor = "disk,raw";
+
+ if (minor == NULL || strstr(minor, "raw") == NULL) {
+ nvlist_free(nvl);
return (NULL);
}
if ((dev_name = lookup_lofi_dev_name(node_path, minor)) ==
@@ -8374,7 +8410,7 @@ process_syseventq()
static void
build_and_enq_event(char *class, char *subclass, char *node_path,
- di_node_t node, char *minor)
+ di_node_t node, char *minor)
{
nvlist_t *nvl;
diff --git a/usr/src/cmd/devfsadm/disk_link.c b/usr/src/cmd/devfsadm/disk_link.c
index 80e75c1694..0baa608912 100644
--- a/usr/src/cmd/devfsadm/disk_link.c
+++ b/usr/src/cmd/devfsadm/disk_link.c
@@ -19,6 +19,7 @@
* CDDL HEADER END
*/
/*
+ * Copyright 2016 Toomas Soome <tsoome@me.com>
* Copyright 2012 Nexenta Systems, Inc. All rights reserved.
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
@@ -30,11 +31,13 @@
#include <stdlib.h>
#include <limits.h>
#include <ctype.h>
+#include <unistd.h>
#include <sys/int_fmtio.h>
#include <sys/stat.h>
#include <bsm/devalloc.h>
#include <sys/scsi/scsi_address.h>
#include <sys/libdevid.h>
+#include <sys/lofi.h>
#define DISK_SUBPATH_MAX 100
#define RM_STALE 0x01
@@ -69,6 +72,7 @@ static void disk_common(di_minor_t minor, di_node_t node, char *disk,
int flags);
static char *diskctrl(di_node_t node, di_minor_t minor);
static int reserved_links_exist(di_node_t node, di_minor_t minor, int nflags);
+static void disk_rm_lofi_all(char *file);
static devfsadm_create_t disk_cbt[] = {
@@ -104,9 +108,12 @@ static devfsadm_create_t disk_cbt[] = {
DEVFSADM_CREATE_INIT_V0(disk_cbt);
/*
- * HOT auto cleanup of disks not desired.
+ * HOT auto cleanup of disks is done for lofi devices only.
*/
static devfsadm_remove_t disk_remove_cbt[] = {
+ { "disk", DISK_LINK_RE, RM_HOT | RM_POST | RM_ALWAYS,
+ ILEVEL_0, disk_rm_lofi_all
+ },
{ "disk", DISK_LINK_RE, RM_POST,
ILEVEL_0, devfsadm_rm_all
}
@@ -124,6 +131,44 @@ static devlink_re_t disks_re_array[] = {
static char *disk_mid = "disk_mid";
static char *modname = "disk_link";
+/*
+ * Check if link is from lofi by checking path from readlink().
+ */
+static int
+is_lofi_disk(char *file)
+{
+ char buf[PATH_MAX + 1];
+ char filepath[PATH_MAX];
+ char *ptr;
+ ssize_t size;
+
+ size = snprintf(filepath, sizeof (filepath), "%s/dev/%s",
+ devfsadm_root_path(), file);
+ if (size > sizeof (filepath))
+ return (0);
+
+ size = readlink(filepath, buf, sizeof (buf) - 1);
+ if (size == -1)
+ return (0);
+ buf[size] = '\0';
+ ptr = strchr(buf, '@');
+ if (ptr == NULL)
+ return (0);
+ ptr[1] = '\0';
+ if (strcmp(buf, "../../devices/pseudo/lofi@") != 0)
+ return (0);
+ return (1);
+}
+
+/*
+ * Wrapper around devfsadm_rm_link() for lofi devices.
+ */
+static void disk_rm_lofi_all(char *file)
+{
+ if (is_lofi_disk(file))
+ devfsadm_rm_link(file);
+}
+
int
minor_init()
{
@@ -137,13 +182,20 @@ static int
disk_callback_chan(di_minor_t minor, di_node_t node)
{
char *addr;
- char disk[20];
- uint_t targ;
- uint_t lun;
+ char disk[23];
+ char *driver;
+ uint_t targ = 0;
+ uint_t lun = 0;
+
+ driver = di_driver_name(node);
+ if (strcmp(driver, LOFI_DRIVER_NAME) != 0) {
+ addr = di_bus_addr(node);
+ (void) sscanf(addr, "%X,%X", &targ, &lun);
+ } else {
+ targ = di_instance(node);
+ }
- addr = di_bus_addr(node);
- (void) sscanf(addr, "%X,%X", &targ, &lun);
- (void) sprintf(disk, "t%dd%d", targ, lun);
+ (void) snprintf(disk, sizeof (disk), "t%dd%d", targ, lun);
disk_common(minor, node, disk, 0);
return (DEVFSADM_CONTINUE);
diff --git a/usr/src/cmd/devfsadm/lofi_link.c b/usr/src/cmd/devfsadm/lofi_link.c
index d86089f0bb..36fbe987d4 100644
--- a/usr/src/cmd/devfsadm/lofi_link.c
+++ b/usr/src/cmd/devfsadm/lofi_link.c
@@ -19,12 +19,11 @@
* CDDL HEADER END
*/
/*
+ * Copyright 2016 Toomas Soome <tsoome@me.com>
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <regex.h>
#include <devfsadm.h>
#include <stdio.h>
@@ -73,16 +72,14 @@ lofi_rm_all(char *link)
* For the master device:
* /dev/lofictl -> /devices/pseudo/lofi@0:ctl
* For each other device
- * /dev/lofi/1 -> /devices/pseudo/lofi@0:1
- * /dev/rlofi/1 -> /devices/pseudo/lofi@0:1,raw
+ * /dev/lofi/1 -> /devices/pseudo/lofi@1:disk
+ * /dev/rlofi/1 -> /devices/pseudo/lofi@1:disk,raw
*/
static int
lofi(di_minor_t minor, di_node_t node)
{
- dev_t dev;
+ int instance;
char mn[MAXNAMELEN + 1];
- char blkname[MAXNAMELEN + 1];
- char rawname[MAXNAMELEN + 1];
char path[PATH_MAX + 1];
(void) strcpy(mn, di_minor_name(minor));
@@ -90,18 +87,14 @@ lofi(di_minor_t minor, di_node_t node)
if (strcmp(mn, "ctl") == 0) {
(void) devfsadm_mklink(LOFI_CTL_NAME, node, minor, 0);
} else {
- dev = di_minor_devt(minor);
- (void) snprintf(blkname, sizeof (blkname), "%d",
- (int)minor(dev));
- (void) snprintf(rawname, sizeof (rawname), "%d,raw",
- (int)minor(dev));
+ instance = di_instance(node);
- if (strcmp(mn, blkname) == 0) {
- (void) snprintf(path, sizeof (path), "%s/%s",
- LOFI_BLOCK_NAME, blkname);
- } else if (strcmp(mn, rawname) == 0) {
- (void) snprintf(path, sizeof (path), "%s/%s",
- LOFI_CHAR_NAME, blkname);
+ if (strcmp(mn, LOFI_BLOCK_NODE) == 0) {
+ (void) snprintf(path, sizeof (path), "%s/%d",
+ LOFI_BLOCK_NAME, instance);
+ } else if (strcmp(mn, LOFI_CHAR_NODE) == 0) {
+ (void) snprintf(path, sizeof (path), "%s/%d",
+ LOFI_CHAR_NAME, instance);
} else {
return (DEVFSADM_CONTINUE);
}