* Add xenvb_id utility to identify Xen disk and CD-ROM devices. * Add support to path_id for Xen vbd devices With this symlinks such as /dev/cdrom are correctly created for Xen devices configured with the "cdrom" tag and utilities which rely on ID_TYPE or ID_CDROM (such as the Debian Installer) can correctly identify the disks. Signed-off-by: Ian Campbell <ijc@xxxxxxxxxxxxxx> --- configure.ac | 1 + extras/Makefile.am | 3 +- extras/path_id/path_id | 27 ++++ extras/xenvbd_id/.gitignore | 1 + extras/xenvbd_id/60-xenvbd_id.rules | 3 + extras/xenvbd_id/Makefile.am | 19 +++ extras/xenvbd_id/xenvbd_id.8 | 37 ++++++ extras/xenvbd_id/xenvbd_id.c | 227 +++++++++++++++++++++++++++++++++++ 8 files changed, 317 insertions(+), 1 deletions(-) create mode 100644 extras/xenvbd_id/.gitignore create mode 100644 extras/xenvbd_id/60-xenvbd_id.rules create mode 100644 extras/xenvbd_id/Makefile.am create mode 100644 extras/xenvbd_id/xenvbd_id.8 create mode 100644 extras/xenvbd_id/xenvbd_id.c diff --git a/configure.ac b/configure.ac index cbe2833..a968163 100644 --- a/configure.ac +++ b/configure.ac @@ -100,6 +100,7 @@ AC_CONFIG_FILES([ extras/volume_id/Makefile extras/volume_id/lib/Makefile extras/volume_id/lib/libvolume_id.pc + extras/xenvbd_id/Makefile ]) AC_OUTPUT diff --git a/extras/Makefile.am b/extras/Makefile.am index fc46668..f364631 100644 --- a/extras/Makefile.am +++ b/extras/Makefile.am @@ -12,4 +12,5 @@ SUBDIRS = \ rule_generator \ scsi_id \ usb_id \ - volume_id + volume_id \ + xenvbd_id diff --git a/extras/path_id/path_id b/extras/path_id/path_id index d21dea7..7b4973f 100755 --- a/extras/path_id/path_id +++ b/extras/path_id/path_id @@ -129,6 +129,30 @@ handle_platform () { RESULT=0 } +handle_xen () { + local DEV=$1 + cd -P $1 + vbd_id=${DEV##*/} + host_dev_path=$DEV + while [ ! -z "$host_dev_path" ] ; do + case "$host_dev_path" in + */vbd*) + host_dev_path=${host_dev_path%/*} + ;; + *) + break + ;; + esac + done + if [ "$d" ]; then + d="xen-$vbd_id-$d" + else + d="xen-$vbd_id" + fi + D="$host_dev_path" + RESULT=0 +} + handle_serio () { local DEV=$1 cd -P $1 @@ -532,6 +556,9 @@ handle_device () { */platform/*) handle_platform "$D" ;; + */vbd-[0-9]*) + handle_xen "$D" + ;; */devices) D= ;; diff --git a/extras/xenvbd_id/.gitignore b/extras/xenvbd_id/.gitignore new file mode 100644 index 0000000..c0ae90e --- /dev/null +++ b/extras/xenvbd_id/.gitignore @@ -0,0 +1 @@ +xenvbd_id diff --git a/extras/xenvbd_id/60-xenvbd_id.rules b/extras/xenvbd_id/60-xenvbd_id.rules new file mode 100644 index 0000000..ed3aa5f --- /dev/null +++ b/extras/xenvbd_id/60-xenvbd_id.rules @@ -0,0 +1,3 @@ +# import Xen virtual drive properties + +ACTION=="add|change", KERNEL=="xvd*[!0-9]", DRIVERS=="vbd", IMPORT{program}="xenvbd_id --export $tempnode" diff --git a/extras/xenvbd_id/Makefile.am b/extras/xenvbd_id/Makefile.am new file mode 100644 index 0000000..370db2b --- /dev/null +++ b/extras/xenvbd_id/Makefile.am @@ -0,0 +1,19 @@ +include $(top_srcdir)/Makefile.am.inc + +udevhomedir = $(udev_prefix)/lib/udev +udevhome_PROGRAMS = \ + xenvbd_id + +udevrulesdir = $(udev_prefix)/lib/udev/rules.d +dist_udevrules_DATA = \ + 60-xenvbd_id.rules + +xenvbd_id_SOURCES = \ + xenvbd_id.c \ + ../../udev/lib/libudev.h \ + ../../udev/lib/libudev.c \ + ../../udev/lib/libudev-list.c \ + ../../udev/lib/libudev-util.c + +dist_man_MANS = \ + xenvbd_id.8 diff --git a/extras/xenvbd_id/xenvbd_id.8 b/extras/xenvbd_id/xenvbd_id.8 new file mode 100644 index 0000000..420a412 --- /dev/null +++ b/extras/xenvbd_id/xenvbd_id.8 @@ -0,0 +1,37 @@ +.TH XENVBD_ID 8 "January 2009" "" "Linux Administrator's Manual" +.SH NAME +xenvbd_id \- udev callout to determine the capabilities of Xen virtual +block devices +.SH SYNOPSIS +.B xenvbd_id +[\fB--export\fP] [\fB--debug\fP] \fIdevice\fP +.br +.B xenvbd_id +\fB--help\fP +.SH "DESCRIPTION" +.B xenvbd_id +is normally called from a udev rule, to provide udev with the list of +capabilities of a Xen virtual block device. +.SH USAGE +.B xenvbd_id +opens the device node specified at the commandline and prints the +discovered capabilities. +.SH OPTIONS +The following commandline switches are supported to specify what xenvbd_id +should print: +.TP +.B -x, --export +Print all values as environment keys. This is the default at present, so this +option is currently redundant. +.TP +.B -d, --debug +Print a debug trace. +.TP +.B -h, --help +Print usage help. +.RE +.SH SEE ALSO +.BR udev (7) +.SH AUTHORS +Developed by Ian Campbell <ijc@xxxxxxxxxxxxxx> based on cdrom_id by Kay Sievers <kay.sievers@xxxxxxxx>. + diff --git a/extras/xenvbd_id/xenvbd_id.c b/extras/xenvbd_id/xenvbd_id.c new file mode 100644 index 0000000..4dadf01 --- /dev/null +++ b/extras/xenvbd_id/xenvbd_id.c @@ -0,0 +1,227 @@ +/* + * xenvbd_id - optical drive and media information prober + * + * Copyright (C) 2009 Ian Campbell <ijc@xxxxxxxxxxxxxx> + * Copyright (C) 2008 Kay Sievers <kay.sievers@xxxxxxxx> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE 1 +#endif + +#include <stdio.h> +#include <stddef.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <limits.h> +#include <fcntl.h> +#include <errno.h> +#include <getopt.h> +#include <scsi/sg.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <sys/ioctl.h> +#include <linux/cdrom.h> + +#include "../../udev/udev.h" + +static int debug; + +static void log_fn(struct udev *udev, int priority, + const char *file, int line, const char *fn, + const char *format, va_list args) +{ + if (debug) { + fprintf(stderr, "%s: ", fn); + vfprintf(stderr, format, args); + } else { + vsyslog(priority, format, args); + } +} + +/* device info */ +static unsigned int cd_cd_rom; +static unsigned int cd_cd_r; +static unsigned int cd_cd_rw; +static unsigned int cd_dvd_rom; +static unsigned int cd_dvd_r; +static unsigned int cd_dvd_rw; +static unsigned int cd_dvd_ram; +static unsigned int cd_dvd_plus_r; +static unsigned int cd_dvd_plus_rw; +static unsigned int cd_dvd_plus_r_dl; +static unsigned int cd_dvd_plus_rw_dl; +static unsigned int cd_bd; +static unsigned int cd_bd_r; +static unsigned int cd_bd_re; +static unsigned int cd_hddvd; +static unsigned int cd_hddvd_r; +static unsigned int cd_hddvd_rw; +static unsigned int cd_mo; +static unsigned int cd_mrw; +static unsigned int cd_mrw_w; + +static int cd_capability_compat(struct udev *udev, int fd) +{ + int capabilty; + + capabilty = ioctl(fd, CDROM_GET_CAPABILITY, NULL); + if (capabilty < 0) { + info(udev, "CDROM_GET_CAPABILITY failed\n"); + return -1; + } + + if (capabilty & CDC_CD_R) + cd_cd_r = 1; + if (capabilty & CDC_CD_RW) + cd_cd_rw = 1; + if (capabilty & CDC_DVD) + cd_dvd_rom = 1; + if (capabilty & CDC_DVD_R) + cd_dvd_r = 1; + if (capabilty & CDC_DVD_RAM) + cd_dvd_ram = 1; + if (capabilty & CDC_MRW) + cd_mrw = 1; + if (capabilty & CDC_MRW_W) + cd_mrw_w = 1; + return 0; +} + +int main(int argc, char *argv[]) +{ + struct udev *udev; + static const struct option options[] = { + { "export", no_argument, NULL, 'x' }, + { "debug", no_argument, NULL, 'd' }, + { "help", no_argument, NULL, 'h' }, + {} + }; + const char *node = NULL; + int export = 0; + int fd = -1; + int rc = 0; + + udev = udev_new(); + if (udev == NULL) + goto exit; + + logging_init("xenvbd_id"); + udev_set_log_fn(udev, log_fn); + + while (1) { + int option; + + option = getopt_long(argc, argv, "dxh", options, NULL); + if (option == -1) + break; + + switch (option) { + case 'd': + debug = 1; + if (udev_get_log_priority(udev) < LOG_INFO) + udev_set_log_priority(udev, LOG_INFO); + break; + case 'x': + export = 1; + break; + case 'h': + printf("Usage: xenvbd_id [options] <device>\n" + " --export export key/value pairs\n" + " --debug debug to stderr\n" + " --help print this help text\n\n"); + goto exit; + default: + rc = 1; + goto exit; + } + } + + node = argv[optind]; + if (!node) { + err(udev, "no device\n"); + fprintf(stderr, "no device\n"); + rc = 1; + goto exit; + } + + fd = open(node, O_RDONLY | O_NONBLOCK); + if (fd < 0) { + info(udev, "unable to open '%s'\n", node); + rc = 1; + goto exit; + } + info(udev, "probing: '%s'\n", node); + + /* same data as original cdrom_id */ + if (cd_capability_compat(udev, fd) < 0) { + printf("ID_TYPE=disk\n"); + } else { + printf("ID_TYPE=cd\n"); + printf("ID_CDROM=1\n"); + + if (cd_cd_rom) + printf("ID_CDROM_CD=1\n"); + if (cd_cd_r) + printf("ID_CDROM_CD_R=1\n"); + if (cd_cd_rw) + printf("ID_CDROM_CD_RW=1\n"); + if (cd_dvd_rom) + printf("ID_CDROM_DVD=1\n"); + if (cd_dvd_r) + printf("ID_CDROM_DVD_R=1\n"); + if (cd_dvd_rw) + printf("ID_CDROM_DVD_RW=1\n"); + if (cd_dvd_ram) + printf("ID_CDROM_DVD_RAM=1\n"); + if (cd_dvd_plus_r) + printf("ID_CDROM_DVD_PLUS_R=1\n"); + if (cd_dvd_plus_rw) + printf("ID_CDROM_DVD_PLUS_RW=1\n"); + if (cd_dvd_plus_r_dl) + printf("ID_CDROM_DVD_PLUS_R_DL=1\n"); + if (cd_dvd_plus_rw_dl) + printf("ID_CDROM_DVD_PLUS_RW_DL=1\n"); + if (cd_bd) + printf("ID_CDROM_BD=1\n"); + if (cd_bd_r) + printf("ID_CDROM_BD_R=1\n"); + if (cd_bd_re) + printf("ID_CDROM_BD_RE=1\n"); + if (cd_hddvd) + printf("ID_CDROM_HDDVD=1\n"); + if (cd_hddvd_r) + printf("ID_CDROM_HDDVD_R=1\n"); + if (cd_hddvd_rw) + printf("ID_CDROM_HDDVD_RW=1\n"); + if (cd_mo) + printf("ID_CDROM_MO=1\n"); + if (cd_mrw) + printf("ID_CDROM_MRW=1\n"); + if (cd_mrw_w) + printf("ID_CDROM_MRW_W=1\n"); + + } +exit: + if (fd >= 0) + close(fd); + udev_unref(udev); + logging_close(); + return rc; +} + -- 1.6.2.2 -- Ian Campbell Consultation, n.: Medical term meaning "to share the wealth."
Attachment:
signature.asc
Description: This is a digitally signed message part