summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvikram <none@none>2007-03-19 18:02:35 -0700
committervikram <none@none>2007-03-19 18:02:35 -0700
commit568e756a1c7e2218f16f91d883b56e54636081f7 (patch)
tree92fde0bc59604461e5507bb694da71dbc8066e2f
parent5e45752a44935a6b2445ae1c763867d868fa3fbb (diff)
downloadillumos-gate-568e756a1c7e2218f16f91d883b56e54636081f7.tar.gz
6527366 di_devlink_open() fails in the miniroot after devname integration
-rw-r--r--usr/src/cmd/devfsadm/devfsadm.c3
-rw-r--r--usr/src/cmd/devfsadm/message.h4
-rw-r--r--usr/src/lib/libdevinfo/devinfo_devlink.c59
3 files changed, 65 insertions, 1 deletions
diff --git a/usr/src/cmd/devfsadm/devfsadm.c b/usr/src/cmd/devfsadm/devfsadm.c
index d443b88a20..2cee988b13 100644
--- a/usr/src/cmd/devfsadm/devfsadm.c
+++ b/usr/src/cmd/devfsadm/devfsadm.c
@@ -1397,6 +1397,9 @@ unlock_dev(int flag)
if (build_dev == FALSE)
return;
+ if (devlink_cache == NULL) {
+ err_print(NO_DEVLINK_CACHE);
+ }
assert(devlink_cache);
if (flag == SYNC_STATE) {
diff --git a/usr/src/cmd/devfsadm/message.h b/usr/src/cmd/devfsadm/message.h
index 8d1436f38d..60f790293d 100644
--- a/usr/src/cmd/devfsadm/message.h
+++ b/usr/src/cmd/devfsadm/message.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -273,6 +273,8 @@ major_number ]\n\t\t[ -n ]\n\t\t[ -r rootdir ]\n\t\t[ -v ]\n")
#define NOT_DIR gettext("file is not a directory: %s\n")
+#define NO_DEVLINK_CACHE gettext("devlink cache does not exist\n")
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/lib/libdevinfo/devinfo_devlink.c b/usr/src/lib/libdevinfo/devinfo_devlink.c
index 34dad1c59b..6f53830b0c 100644
--- a/usr/src/lib/libdevinfo/devinfo_devlink.c
+++ b/usr/src/lib/libdevinfo/devinfo_devlink.c
@@ -39,6 +39,7 @@
#include <assert.h>
static mutex_t update_mutex = DEFAULTMUTEX; /* Protects update record lock */
+static mutex_t temp_file_mutex = DEFAULTMUTEX; /* for file creation tests */
static const size_t elem_sizes[DB_TYPES] = {
sizeof (struct db_node),
@@ -61,6 +62,8 @@ static const char *skip_files[] = {
#define N_SKIP_DIRS (sizeof (skip_dirs) / sizeof (skip_dirs[0]))
#define N_SKIP_FILES (sizeof (skip_files) / sizeof (skip_files[0]))
+#define DI_TEST_DB ETCDEV "di_test_db"
+
/*
*
* This file contains two sets of interfaces which operate on the reverse
@@ -311,6 +314,10 @@ handle_alloc(const char *root_dir, uint_t flags)
{
char dev_dir[PATH_MAX], path[PATH_MAX], db_dir[PATH_MAX];
struct di_devlink_handle *hdp, proto = {0};
+ int install = 0;
+ int isroot = 0;
+ struct stat sb;
+ char can_path[PATH_MAX];
assert(flags == OPEN_RDWR || flags == OPEN_RDONLY);
@@ -335,6 +342,11 @@ handle_alloc(const char *root_dir, uint_t flags)
(realpath(root_dir, db_dir) == NULL)) {
return (NULL);
}
+ } else {
+ /*
+ * The dev dir is at /dev i.e. we are not doing a -r /altroot
+ */
+ isroot = 1;
}
if (strcmp(dev_dir, "/") == 0) {
@@ -347,6 +359,53 @@ handle_alloc(const char *root_dir, uint_t flags)
(void) strlcat(dev_dir, DEV, sizeof (dev_dir));
(void) strlcat(db_dir, ETCDEV, sizeof (db_dir));
+ /*
+ * The following code is for install. Readers and writers need
+ * to be redirected to /tmp/etc/dev for the database file.
+ * Note that we test for readonly /etc by actually creating a
+ * file since statvfs is not a reliable method for determining
+ * readonly filesystems.
+ */
+ install = 0;
+ (void) snprintf(can_path, sizeof (can_path), "%s/%s", ETCDEV, DB_FILE);
+ if (flags == OPEN_RDWR && isroot) {
+ char di_test_db[PATH_MAX];
+ int fd;
+ (void) mutex_lock(&temp_file_mutex);
+ (void) snprintf(di_test_db, sizeof (di_test_db), "%s.%d",
+ DI_TEST_DB, getpid());
+ fd = open(di_test_db, O_CREAT|O_RDWR|O_EXCL, 0644);
+ if (fd == -1 && errno == EROFS && stat(can_path, &sb) == -1)
+ install = 1;
+ if (fd != -1) {
+ (void) close(fd);
+ (void) unlink(di_test_db);
+ }
+ (void) mutex_unlock(&temp_file_mutex);
+ } else if (isroot) {
+ /*
+ * Readers can be non-privileged so we cannot test by creating
+ * a file in /etc/dev. Instead we check if the database
+ * file is missing in /etc/dev and is present in /tmp/etc/dev
+ * and is owned by root.
+ */
+ char install_path[PATH_MAX];
+
+ (void) snprintf(install_path, sizeof (install_path),
+ "/tmp%s/%s", ETCDEV, DB_FILE);
+ if (stat(can_path, &sb) == -1 && stat(install_path, &sb)
+ != -1 && sb.st_uid == 0) {
+ install = 1;
+ }
+ }
+
+ /*
+ * Check if we are in install. If we are, the database will be in
+ * /tmp/etc/dev
+ */
+ if (install)
+ (void) snprintf(db_dir, sizeof (db_dir), "/tmp%s", ETCDEV);
+
proto.dev_dir = dev_dir;
proto.db_dir = db_dir;
proto.flags = flags;