summaryrefslogtreecommitdiff
path: root/usr
diff options
context:
space:
mode:
authorvikram <none@none>2006-10-02 14:44:57 -0700
committervikram <none@none>2006-10-02 14:44:57 -0700
commitaa646b9dad0e03cc01e7fe5bea924c5267e2df75 (patch)
tree384911d82a5925b707e1d508b09595c38f609130 /usr
parentf67ca41a3fe371a8ac34045eb45b3c5449ee601c (diff)
downloadillumos-joyent-aa646b9dad0e03cc01e7fe5bea924c5267e2df75.tar.gz
6462748 devfsadm link removal does not provide full interpose support
Diffstat (limited to 'usr')
-rw-r--r--usr/src/cmd/devfsadm/devfsadm.c150
-rw-r--r--usr/src/cmd/devfsadm/devfsadm.h24
-rw-r--r--usr/src/cmd/devfsadm/devfsadm_impl.h15
-rw-r--r--usr/src/cmd/devfsadm/lofi_link.c27
4 files changed, 199 insertions, 17 deletions
diff --git a/usr/src/cmd/devfsadm/devfsadm.c b/usr/src/cmd/devfsadm/devfsadm.c
index c1ffa5e1aa..1053dd8776 100644
--- a/usr/src/cmd/devfsadm/devfsadm.c
+++ b/usr/src/cmd/devfsadm/devfsadm.c
@@ -207,6 +207,10 @@ static int login_dev_enable = FALSE;
/* Global to use devinfo snapshot cache */
static int use_snapshot_cache = FALSE;
+/* Global for no-further-processing hash */
+static item_t **nfp_hash;
+static mutex_t nfp_mutex = DEFAULTMUTEX;
+
/*
* Packaged directories - not removed even when empty.
* The dirs must be listed in canonical form
@@ -391,6 +395,7 @@ update_drvconf(major_t major)
major);
}
+
static void
load_dev_acl()
{
@@ -2037,7 +2042,7 @@ static void
load_module(char *mname, char *cdir)
{
_devfsadm_create_reg_t *create_reg;
- _devfsadm_remove_reg_t *remove_reg;
+ _devfsadm_remove_reg_V1_t *remove_reg;
create_list_t *create_list_element;
create_list_t **create_list_next;
remove_list_t *remove_list_element;
@@ -2047,6 +2052,7 @@ load_module(char *mname, char *cdir)
char *dlerrstr;
void *dlhandle;
module_t *module;
+ int flags;
int n;
int i;
@@ -2079,7 +2085,7 @@ load_module(char *mname, char *cdir)
}
/* dlsym the _devfsadm_remove_reg structure */
- if (NULL == (remove_reg = (_devfsadm_remove_reg_t *)
+ if (NULL == (remove_reg = (_devfsadm_remove_reg_V1_t *)
dlsym(dlhandle, _DEVFSADM_REMOVE_REG))) {
vprint(MODLOAD_MID, "dlsym(%s,\n\t%s): symbol not found\n",
epath, _DEVFSADM_REMOVE_REG);
@@ -2220,13 +2226,17 @@ load_module(char *mname, char *cdir)
* put a ptr to each struct devfsadm_remove on "remove_head"
* list sorted by interpose_lvl.
*/
+ flags = 0;
if (remove_reg != NULL) {
+ if (remove_reg->version < DEVFSADM_V1)
+ flags |= RM_NOINTERPOSE;
for (i = 0; i < remove_reg->count; i++) {
remove_list_element = (remove_list_t *)
s_malloc(sizeof (remove_list_t));
remove_list_element->remove = &(remove_reg->tblp[i]);
+ remove_list_element->remove->flags |= flags;
remove_list_element->modptr = module;
for (remove_list_next = &(remove_head);
@@ -4004,6 +4014,9 @@ pre_and_post_cleanup(int flags)
rd.data = (void *)&cleanup_data;
cleanup_data.flags = flags;
+ (void) mutex_lock(&nfp_mutex);
+ nfphash_create();
+
for (rm = remove_head; rm != NULL; rm = rm->next) {
if ((flags & rm->remove->flags) == flags) {
cleanup_data.rm = rm;
@@ -4020,6 +4033,8 @@ pre_and_post_cleanup(int flags)
}
}
}
+ nfphash_destroy();
+ (void) mutex_unlock(&nfp_mutex);
}
/*
@@ -4044,7 +4059,7 @@ pre_and_post_cleanup(int flags)
*
*/
static int
-clean_ok(devfsadm_remove_t *remove)
+clean_ok(devfsadm_remove_V1_t *remove)
{
int i;
@@ -4103,6 +4118,7 @@ hot_cleanup(char *node_path, char *minor_name, char *ev_subclass,
char rmlink[PATH_MAX + 1];
nvlist_t *nvl = NULL;
int skip;
+ int ret;
/*
* dev links can go away as part of hot cleanup.
@@ -4120,6 +4136,9 @@ hot_cleanup(char *node_path, char *minor_name, char *ev_subclass,
vprint(REMOVE_MID, "%spath=%s\n", fcn, path);
+ (void) mutex_lock(&nfp_mutex);
+ nfphash_create();
+
for (rm = remove_head; rm != NULL; rm = rm->next) {
if ((RM_HOT & rm->remove->flags) == RM_HOT) {
head = get_cached_links(rm->remove->dev_dirs_re);
@@ -4137,6 +4156,14 @@ hot_cleanup(char *node_path, char *minor_name, char *ev_subclass,
* the next valid link.
*/
head->nextlink = link->next;
+
+ /*
+ * if devlink is in no-further-process hash,
+ * skip its remove
+ */
+ if (nfphash_lookup(link->devlink) != NULL)
+ continue;
+
if (minor_name)
skip = strcmp(link->contents, path);
else
@@ -4157,11 +4184,22 @@ hot_cleanup(char *node_path, char *minor_name, char *ev_subclass,
*/
(void) snprintf(rmlink, sizeof (rmlink),
"%s", link->devlink);
- (*(rm->remove->callback_fcn))(rmlink);
+ if (rm->remove->flags & RM_NOINTERPOSE) {
+ ((void (*)(char *))
+ (rm->remove->callback_fcn))(rmlink);
+ } else {
+ ret = ((int (*)(char *))
+ (rm->remove->callback_fcn))(rmlink);
+ if (ret == DEVFSADM_TERMINATE)
+ nfphash_insert(rmlink);
+ }
}
}
}
+ nfphash_destroy();
+ (void) mutex_unlock(&nfp_mutex);
+
/* update device allocation database */
if (system_labeled) {
int ret = 0;
@@ -4263,22 +4301,44 @@ static void
matching_dev(char *devpath, void *data)
{
cleanup_data_t *cleanup_data = data;
+ int norm_len = strlen(dev_dir) + strlen("/");
+ int ret;
char *fcn = "matching_dev: ";
vprint(RECURSEDEV_MID, "%sexamining devpath = '%s'\n", fcn,
devpath);
+ /*
+ * If the link is in the no-further-process hash
+ * don't do any remove operation on it.
+ */
+ if (nfphash_lookup(devpath + norm_len) != NULL)
+ return;
+
if (resolve_link(devpath, NULL, NULL, NULL, 1) == TRUE) {
if (call_minor_init(cleanup_data->rm->modptr) ==
DEVFSADM_FAILURE) {
return;
}
- devpath += strlen(dev_dir) + strlen("/");
+ devpath += norm_len;
vprint(RECURSEDEV_MID, "%scalling"
" callback %s\n", fcn, devpath);
- (*(cleanup_data->rm->remove->callback_fcn))(devpath);
+ if (cleanup_data->rm->remove->flags & RM_NOINTERPOSE)
+ ((void (*)(char *))
+ (cleanup_data->rm->remove->callback_fcn))(devpath);
+ else {
+ ret = ((int (*)(char *))
+ (cleanup_data->rm->remove->callback_fcn))(devpath);
+ if (ret == DEVFSADM_TERMINATE) {
+ /*
+ * We want no further remove processing for
+ * this link. Add it to the nfp_hash;
+ */
+ nfphash_insert(devpath);
+ }
+ }
}
}
@@ -8043,6 +8103,84 @@ is_blank(char *line)
return (1);
}
+/*
+ * Functions to deal with the no-further-processing hash
+ */
+
+static void
+nfphash_create(void)
+{
+ assert(nfp_hash == NULL);
+ nfp_hash = s_zalloc(NFP_HASH_SZ * sizeof (item_t *));
+}
+
+static int
+nfphash_fcn(char *key)
+{
+ int i;
+ uint64_t sum = 0;
+
+ for (i = 0; key[i] != '\0'; i++) {
+ sum += (uchar_t)key[i];
+ }
+
+ return (sum % NFP_HASH_SZ);
+}
+
+static item_t *
+nfphash_lookup(char *key)
+{
+ int index;
+ item_t *ip;
+
+ index = nfphash_fcn(key);
+
+ assert(index >= 0);
+
+ for (ip = nfp_hash[index]; ip; ip = ip->i_next) {
+ if (strcmp(ip->i_key, key) == 0)
+ return (ip);
+ }
+
+ return (NULL);
+}
+
+static void
+nfphash_insert(char *key)
+{
+ item_t *ip;
+ int index;
+
+ index = nfphash_fcn(key);
+
+ assert(index >= 0);
+
+ ip = s_zalloc(sizeof (item_t));
+ ip->i_key = s_strdup(key);
+
+ ip->i_next = nfp_hash[index];
+ nfp_hash[index] = ip;
+}
+
+static void
+nfphash_destroy(void)
+{
+ int i;
+ item_t *ip;
+
+ for (i = 0; i < NFP_HASH_SZ; i++) {
+ /*LINTED*/
+ while (ip = nfp_hash[i]) {
+ nfp_hash[i] = ip->i_next;
+ free(ip->i_key);
+ free(ip);
+ }
+ }
+
+ free(nfp_hash);
+ nfp_hash = NULL;
+}
+
static int
devname_kcall(int subcmd, void *args)
{
diff --git a/usr/src/cmd/devfsadm/devfsadm.h b/usr/src/cmd/devfsadm/devfsadm.h
index 4688e6043c..ae6216eb89 100644
--- a/usr/src/cmd/devfsadm/devfsadm.h
+++ b/usr/src/cmd/devfsadm/devfsadm.h
@@ -55,6 +55,7 @@ extern "C" {
#define ILEVEL_9 9
#define DEVFSADM_V0 0
+#define DEVFSADM_V1 1
#define DEVFSADM_CONTINUE 0
#define DEVFSADM_TERMINATE 1
@@ -66,6 +67,7 @@ extern "C" {
#define RM_PRE 0x02
#define RM_POST 0x04
#define RM_ALWAYS 0x08
+#define RM_NOINTERPOSE 0x10
#define TYPE_EXACT 0x01
#define TYPE_RE 0x02
@@ -109,9 +111,17 @@ typedef struct devfsadm_remove {
char *dev_dirs_re; /* dev dirs regex selector */
int flags; /* eg POST, PRE, HOT, ALWAYS */
int interpose_lvl; /* eg ILEVEL_0 .. ILEVEL_10 */
- void (*callback_fcn)(char *logical_link);
+ void (*callback_fcn)(char *);
} devfsadm_remove_t;
+typedef struct devfsadm_remove_V1 {
+ char *device_class; /* eg "disk", "tape", "display" */
+ char *dev_dirs_re; /* dev dirs regex selector */
+ int flags; /* eg POST, PRE, HOT, ALWAYS */
+ int interpose_lvl; /* eg ILEVEL_0 .. ILEVEL_10 */
+ int (*callback_fcn)(char *);
+} devfsadm_remove_V1_t;
+
typedef struct _devfsadm_create_reg {
uint_t version;
uint_t count; /* number of node type registration */
@@ -126,6 +136,12 @@ typedef struct _devfsadm_remove_reg {
devfsadm_remove_t *tblp;
} _devfsadm_remove_reg_t;
+typedef struct _devfsadm_remove_reg_V1 {
+ uint_t version;
+ uint_t count; /* number of node type registration */
+ /* structures */
+ devfsadm_remove_V1_t *tblp;
+} _devfsadm_remove_reg_V1_t;
/*
* "flags" in the devfs_enumerate structure can take the following values.
* These values specify the substring of devfs path to be used for
@@ -167,6 +183,12 @@ typedef struct devfsadm_enumerate {
(sizeof (tbl) / sizeof (devfsadm_remove_t)), \
((devfsadm_remove_t *)(tbl)) }
+#define DEVFSADM_REMOVE_INIT_V1(tbl)\
+ _devfsadm_remove_reg_V1_t _devfsadm_remove_reg = {\
+ DEVFSADM_V1, \
+ (sizeof (tbl) / sizeof (devfsadm_remove_V1_t)), \
+ ((devfsadm_remove_V1_t *)(tbl)) }
+
int devfsadm_noupdate(void);
const char *devfsadm_root_path(void);
int devfsadm_link_valid(char *link);
diff --git a/usr/src/cmd/devfsadm/devfsadm_impl.h b/usr/src/cmd/devfsadm/devfsadm_impl.h
index 3c22b42322..5c72e8124f 100644
--- a/usr/src/cmd/devfsadm/devfsadm_impl.h
+++ b/usr/src/cmd/devfsadm/devfsadm_impl.h
@@ -149,6 +149,7 @@ extern "C" {
#define LDEV_DRV_DELIMS ", \t\n"
#define LDEV_DEV_DELIM ":"
#define LDEV_DRVLIST_NAME "driver"
+#define NFP_HASH_SZ 256
#define TYPE_LINK 0x00
#define TYPE_DEVICES 0x01
@@ -284,11 +285,16 @@ struct mlist {
};
typedef struct remove_list {
- devfsadm_remove_t *remove;
+ devfsadm_remove_V1_t *remove;
module_t *modptr;
struct remove_list *next;
} remove_list_t;
+typedef struct item {
+ char *i_key;
+ struct item *i_next;
+} item_t;
+
typedef struct cleanup_data {
int flags;
char *phypath;
@@ -416,7 +422,7 @@ static void recurse_dev_re(char *current_dir, char *path_re, recurse_dev_t *rd);
static void matching_dev(char *devpath, void *data);
static int resolve_link(char *devpath, char **content_p, int *type_p,
char **devfs_path, int dangle);
-static int clean_ok(devfsadm_remove_t *remove);
+static int clean_ok(devfsadm_remove_V1_t *remove);
static int translate_major(dev_t old_dev, dev_t *new_dev);
static int get_major_no(char *driver, major_t *major);
static int load_n2m_table(char *filename);
@@ -511,6 +517,11 @@ static void reset_node_permissions(di_node_t, di_minor_t);
static void devname_lookup_handler(void *, char *, size_t,
door_desc_t *, uint_t); /* /dev name lookup server */
static int devname_kcall(int, void *); /* syscall into the devname fs */
+static void nfphash_create(void);
+static int nfphash_fcn(char *key);
+static item_t *nfphash_lookup(char *key);
+static void nfphash_insert(char *key);
+static void nfphash_destroy(void);
/* convenient short hands */
#define vprint devfsadm_print
diff --git a/usr/src/cmd/devfsadm/lofi_link.c b/usr/src/cmd/devfsadm/lofi_link.c
index c002b91e20..d86089f0bb 100644
--- a/usr/src/cmd/devfsadm/lofi_link.c
+++ b/usr/src/cmd/devfsadm/lofi_link.c
@@ -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,8 +19,8 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 1998-1999,2001 by 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"
@@ -37,6 +36,7 @@
static int lofi(di_minor_t minor, di_node_t node);
+static int lofi_rm_all(char *link);
/*
* devfs create callback register
@@ -51,11 +51,22 @@ DEVFSADM_CREATE_INIT_V0(lofi_create_cbt);
/*
* devfs cleanup register
*/
-static devfsadm_remove_t lofi_remove_cbt[] = {
+static devfsadm_remove_V1_t lofi_remove_cbt[] = {
{"pseudo", "^r?lofi/[0-9]+$", RM_ALWAYS | RM_PRE | RM_HOT,
- ILEVEL_0, devfsadm_rm_all},
+ ILEVEL_0, lofi_rm_all},
};
-DEVFSADM_REMOVE_INIT_V0(lofi_remove_cbt);
+DEVFSADM_REMOVE_INIT_V1(lofi_remove_cbt);
+
+/*
+ * Wrapper around devfsadm_rm_all() that allows termination of remove
+ * process
+ */
+static int
+lofi_rm_all(char *link)
+{
+ devfsadm_rm_all(link);
+ return (DEVFSADM_TERMINATE);
+}
/*