aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>2006-09-29 14:20:52 +0100
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>2006-09-29 14:20:52 +0100
commitada55182d201bf569fc547bbfe1b5d36c23711fa (patch)
treea250392a79d5311e15da569dd4f6a8e40a2f3630 /tools
parent448496a5e2d50d023a5d2aae9d7f35d90b63d78d (diff)
downloadxen-ada55182d201bf569fc547bbfe1b5d36c23711fa.tar.gz
xen-ada55182d201bf569fc547bbfe1b5d36c23711fa.tar.bz2
xen-ada55182d201bf569fc547bbfe1b5d36c23711fa.zip
[LINUX] Make evtchn device use a dynamic minor number.
Also update the code in tools to create the device node if udev fails. The tools now read the sysfs system to find the minor number needed. Original patch from Steven Rostedt <srostedt@redhat.com> Signed-off-by: Keir Fraser <keir@xensource.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/libxc/xc_linux.c82
-rw-r--r--tools/libxc/xenctrl.h10
2 files changed, 85 insertions, 7 deletions
diff --git a/tools/libxc/xc_linux.c b/tools/libxc/xc_linux.c
index c803b9a827..a70307a542 100644
--- a/tools/libxc/xc_linux.c
+++ b/tools/libxc/xc_linux.c
@@ -133,27 +133,95 @@ int do_xen_hypercall(int xc_handle, privcmd_hypercall_t *hypercall)
(unsigned long)hypercall);
}
+#define MTAB "/proc/mounts"
+#define MAX_PATH 255
+#define _STR(x) #x
+#define STR(x) _STR(x)
+
+static int find_sysfsdir(char *sysfsdir)
+{
+ FILE *fp;
+ char type[MAX_PATH + 1];
+
+ if ( (fp = fopen(MTAB, "r")) == NULL )
+ return -1;
+
+ while ( fscanf(fp, "%*s %"
+ STR(MAX_PATH)
+ "s %"
+ STR(MAX_PATH)
+ "s %*s %*d %*d\n",
+ sysfsdir, type) == 2 )
+ {
+ if ( strncmp(type, "sysfs", 5) == 0 )
+ break;
+ }
+
+ fclose(fp);
+
+ return ((strncmp(type, "sysfs", 5) == 0) ? 0 : -1);
+}
+
+int xc_find_device_number(const char *name)
+{
+ FILE *fp;
+ int i, major, minor;
+ char sysfsdir[MAX_PATH + 1];
+ static char *classlist[] = { "xen", "misc" };
+
+ for ( i = 0; i < (sizeof(classlist) / sizeof(classlist[0])); i++ )
+ {
+ if ( find_sysfsdir(sysfsdir) < 0 )
+ goto not_found;
+
+ /* <base>/class/<classname>/<devname>/dev */
+ strncat(sysfsdir, "/class/", MAX_PATH);
+ strncat(sysfsdir, classlist[i], MAX_PATH);
+ strncat(sysfsdir, "/", MAX_PATH);
+ strncat(sysfsdir, name, MAX_PATH);
+ strncat(sysfsdir, "/dev", MAX_PATH);
+
+ if ( (fp = fopen(sysfsdir, "r")) != NULL )
+ goto found;
+ }
+
+ not_found:
+ errno = -ENOENT;
+ return -1;
+
+ found:
+ if ( fscanf(fp, "%d:%d", &major, &minor) != 2 )
+ {
+ fclose(fp);
+ goto not_found;
+ }
+
+ fclose(fp);
+
+ return makedev(major, minor);
+}
+
#define EVTCHN_DEV_NAME "/dev/xen/evtchn"
-#define EVTCHN_DEV_MAJOR 10
-#define EVTCHN_DEV_MINOR 201
int xc_evtchn_open(void)
{
struct stat st;
int fd;
+ int devnum;
+
+ devnum = xc_find_device_number("evtchn");
/* Make sure any existing device file links to correct device. */
- if ((lstat(EVTCHN_DEV_NAME, &st) != 0) || !S_ISCHR(st.st_mode) ||
- (st.st_rdev != makedev(EVTCHN_DEV_MAJOR, EVTCHN_DEV_MINOR)))
+ if ( (lstat(EVTCHN_DEV_NAME, &st) != 0) || !S_ISCHR(st.st_mode) ||
+ (st.st_rdev != devnum) )
(void)unlink(EVTCHN_DEV_NAME);
-reopen:
+ reopen:
if ( (fd = open(EVTCHN_DEV_NAME, O_RDWR)) == -1 )
{
if ( (errno == ENOENT) &&
((mkdir("/dev/xen", 0755) == 0) || (errno == EEXIST)) &&
- (mknod(EVTCHN_DEV_NAME, S_IFCHR|0600,
- makedev(EVTCHN_DEV_MAJOR, EVTCHN_DEV_MINOR)) == 0) )
+ (mknod(EVTCHN_DEV_NAME, S_IFCHR|0600, devnum) == 0) )
goto reopen;
PERROR("Could not open event channel interface");
diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h
index 0a5cfadd3d..d74c1c8c27 100644
--- a/tools/libxc/xenctrl.h
+++ b/tools/libxc/xenctrl.h
@@ -92,6 +92,16 @@ int xc_interface_open(void);
int xc_interface_close(int xc_handle);
/*
+ * KERNEL INTERFACES
+ */
+
+/*
+ * Resolve a kernel device name (e.g., "evtchn", "blktap0") into a kernel
+ * device number. Returns -1 on error (and sets errno).
+ */
+int xc_find_device_number(const char *name);
+
+/*
* DOMAIN DEBUGGING FUNCTIONS
*/