From a3fd27a0ce5920b66afbf89cb83a9b61db9460c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dan=20Hor=C3=A1k?= Date: Fri, 28 Jan 2011 14:26:53 +0100 Subject: [PATCH 57/61] tunedasd: add new option -Q / --query_reserve Summary: tunedasd: add new option -Q / --query_reserve Description: The new option -Q / --query_reserve uses the BIODASDSNID ioctl to determine the device reservation status for the given device and prints it to stdout. --- tunedasd/include/disk.h | 1 + tunedasd/man/tunedasd.8 | 22 +++++++++- tunedasd/src/disk.c | 65 +++++++++++++++++++++++++++++ tunedasd/src/tunedasd.c | 104 +++++++++++++++++++++++++++-------------------- 4 files changed, 147 insertions(+), 45 deletions(-) diff --git a/tunedasd/include/disk.h b/tunedasd/include/disk.h index 4b98fb0..ece8cb5 100644 --- a/tunedasd/include/disk.h +++ b/tunedasd/include/disk.h @@ -25,6 +25,7 @@ int disk_set_cache (char* device, char* cache, char* no_cyl); int disk_reserve (char* device); int disk_release (char* device); int disk_slock (char* device); +int disk_query_reserve_status(char* device); int disk_profile (char* device, char* prof_item); int disk_reset_prof (char* device); diff --git a/tunedasd/man/tunedasd.8 b/tunedasd/man/tunedasd.8 index 2d99bdc..a96913e 100644 --- a/tunedasd/man/tunedasd.8 +++ b/tunedasd/man/tunedasd.8 @@ -66,7 +66,6 @@ Enterprise Storage Servers (ESS): (Record Access) .IP "" 7 More details about caching can be found in the 'Storage Control Reference' of the attached storage server. - .TP .BR "\-n" " or " "\-\-no_cyl" " " Number of cylinders to be cached (only valid together with --cache). @@ -91,6 +90,27 @@ Profile info must be available and enabled ('echo set on > /proc/dasd/statistics') in the kernel to get valid results out of the profile commands. .TP +.BR "\-Q" " or " "\-\-query_reserve" +Query the current reserve status of the device. +The following states are defined: +.br +.IP " \(bu" 12 +.I none: +The device is not reserved. +.IP " \(bu" 12 +.I implicit: +The device is not reserved, but there is a contingent or implicit +allegiance to this Linux instance. +.IP " \(bu" 12 +.I other: +The device is reserved to another operating system instance. +.IP " \(bu" 12 +.I reserved: +The device is reserved to this Linux instance. +.IP "" 7 +More details about reserve/release can be found in the 'Storage Control Reference' of the attached storage server. + +.TP .BR "\-I" " or " "\-\-prof_item " Print single profile item data row (without header). .br diff --git a/tunedasd/src/disk.c b/tunedasd/src/disk.c index afbe851..3eaa4f3 100644 --- a/tunedasd/src/disk.c +++ b/tunedasd/src/disk.c @@ -68,6 +68,25 @@ typedef struct attrib_data_t { #define DASD_REC_ACCESS 0x5 /* + * Data returned by Sense Path Group ID (SNID) + */ +struct dasd_snid_data { + struct { + __u8 group:2; + __u8 reserve:2; + __u8 mode:1; + __u8 res:3; + } __attribute__ ((packed)) path_state; + __u8 pgid[11]; +} __attribute__ ((packed)); + +struct dasd_snid_ioctl_data { + struct dasd_snid_data data; + __u8 path_mask; +} __attribute__ ((packed)); + + +/* * DASD-IOCTLs (copied from dasd.h) */ /* Issue a reserve/release command, rsp. */ @@ -85,6 +104,9 @@ typedef struct attrib_data_t { /* Set Attributes (cache operations) */ #define BIODASDSATTR _IOW (DASD_IOCTL_LETTER,2,attrib_data_t) +/* Get Sense Path Group ID (SNID) data */ +#define BIODASDSNID _IOWR(DASD_IOCTL_LETTER, 1, struct dasd_snid_ioctl_data) + /* id definition for profile items */ enum prof_id { @@ -378,6 +400,49 @@ disk_slock (char* device) return 0; } + +/* + * Uses the Sense Path Group ID (SNID) ioctl to find out if + * a device is reserved to it's path group. + */ +int +disk_query_reserve_status(char* device) +{ + int fd; + struct dasd_snid_ioctl_data snid; + + /* Open device file */ + fd = open (device, O_RDONLY); + if (fd == -1) { + error_print ("<%s> - %s", device, strerror (errno)); + return -1; + } + snid.path_mask = 0; + /* Release device */ + if (ioctl(fd, BIODASDSNID, &snid)) { + error_print("Could not read reserve status" + " for device <%s>", device); + close (fd); + return -1; + } + switch (snid.data.path_state.reserve) { + case 0: + printf("none\n"); + break; + case 1: + printf("implicit\n"); + break; + case 2: + printf("other\n"); + break; + case 3: + printf("reserved\n"); + break; + } + close (fd); + return 0; +} + int disk_profile_summary (dasd_profile_info_t dasd_profile_info) { diff --git a/tunedasd/src/tunedasd.c b/tunedasd/src/tunedasd.c index 05e0344..fbb7a1e 100644 --- a/tunedasd/src/tunedasd.c +++ b/tunedasd/src/tunedasd.c @@ -47,6 +47,7 @@ static const char* usage_text[] = { "-O, --slock Unconditional reserve device", " Note: Use with care, this breaks an existing " "lock", + "-Q, --query_reserve Print reserve status of device ", "-P, --profile Print profile info of device", "-I, --prof_item Print single profile item", " (reqs/sects/sizes/total/totsect/start/irq/", @@ -54,21 +55,22 @@ static const char* usage_text[] = { "-R, --reset_prof Reset profile info of device" }; -#define CMD_KEYWORD_NUM 11 +#define CMD_KEYWORD_NUM 12 #define DEVICES_NUM 256 enum cmd_keyword_id { - cmd_keyword_help = 0, - cmd_keyword_version = 1, - cmd_keyword_get_cache = 2, - cmd_keyword_cache = 3, - cmd_keyword_no_cyl = 4, - cmd_keyword_reserve = 5, - cmd_keyword_release = 6, - cmd_keyword_slock = 7, - cmd_keyword_profile = 8, - cmd_keyword_prof_item = 9, - cmd_keyword_reset_prof = 10, + cmd_keyword_help = 0, + cmd_keyword_version = 1, + cmd_keyword_get_cache = 2, + cmd_keyword_cache = 3, + cmd_keyword_no_cyl = 4, + cmd_keyword_reserve = 5, + cmd_keyword_release = 6, + cmd_keyword_slock = 7, + cmd_keyword_profile = 8, + cmd_keyword_prof_item = 9, + cmd_keyword_reset_prof = 10, + cmd_keyword_query_reserve = 11, }; @@ -77,17 +79,18 @@ static const struct { char* keyword; enum cmd_keyword_id id; } keyword_list[] = { - { "help", cmd_keyword_help }, - { "version", cmd_keyword_version }, - { "get_cache", cmd_keyword_get_cache }, - { "cache", cmd_keyword_cache }, - { "no_cyl", cmd_keyword_no_cyl }, - { "reserve", cmd_keyword_reserve }, - { "release", cmd_keyword_release }, - { "slock", cmd_keyword_slock }, - { "profile", cmd_keyword_profile }, - { "prof_item", cmd_keyword_prof_item }, - { "reset_prof", cmd_keyword_reset_prof } + { "help", cmd_keyword_help }, + { "version", cmd_keyword_version }, + { "get_cache", cmd_keyword_get_cache }, + { "cache", cmd_keyword_cache }, + { "no_cyl", cmd_keyword_no_cyl }, + { "reserve", cmd_keyword_reserve }, + { "release", cmd_keyword_release }, + { "slock", cmd_keyword_slock }, + { "profile", cmd_keyword_profile }, + { "prof_item", cmd_keyword_prof_item }, + { "reset_prof", cmd_keyword_reset_prof }, + { "query_reserve", cmd_keyword_query_reserve } }; @@ -100,21 +103,22 @@ enum cmd_key_state { /* Determines which combination of keywords are valid */ enum cmd_key_state cmd_key_table[CMD_KEYWORD_NUM][CMD_KEYWORD_NUM] = { - /* help vers get_ cach no_c rese rele sloc prof prof rese - * ion cach e yl rve ase k ile _ite t_pr - * e m of - */ - /* help */ { req, opt, opt, opt, opt, opt, opt, opt, opt, opt, opt }, - /* version */ { inv, req, inv, inv, inv, inv, inv, inv, inv, inv, inv }, - /* get_cache */ { opt, opt, req, inv, inv, inv, inv, inv, inv, inv, inv }, - /* cache */ { opt, opt, inv, req, opt, inv, inv, inv, inv, inv, inv }, - /* no_cyl */ { opt, opt, inv, req, req, inv, inv, inv, inv, inv, inv }, - /* reserve */ { opt, opt, inv, inv, inv, req, inv, inv, inv, inv, inv }, - /* release */ { opt, opt, inv, inv, inv, inv, req, inv, inv, inv, inv }, - /* slock */ { opt, opt, inv, inv, inv, inv, inv, req, inv, inv, inv }, - /* profile */ { opt, opt, inv, inv, inv, inv, inv, inv, req, opt, inv }, - /* prof_item */ { opt, opt, inv, inv, inv, inv, inv, inv, req, req, inv }, - /* reset_prof */ { opt, opt, inv, inv, inv, inv, inv, inv, inv, inv, req }, + /* help vers get_ cach no_c rese rele sloc prof prof rese quer + * ion cach e yl rve ase k ile _ite t_pr y_re + * e m of serv + */ + /* help */ { req, opt, opt, opt, opt, opt, opt, opt, opt, opt, opt, inv }, + /* version */ { inv, req, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv }, + /* get_cache */ { opt, opt, req, inv, inv, inv, inv, inv, inv, inv, inv, inv }, + /* cache */ { opt, opt, inv, req, opt, inv, inv, inv, inv, inv, inv, inv }, + /* no_cyl */ { opt, opt, inv, req, req, inv, inv, inv, inv, inv, inv, inv }, + /* reserve */ { opt, opt, inv, inv, inv, req, inv, inv, inv, inv, inv, inv }, + /* release */ { opt, opt, inv, inv, inv, inv, req, inv, inv, inv, inv, inv }, + /* slock */ { opt, opt, inv, inv, inv, inv, inv, req, inv, inv, inv, inv }, + /* profile */ { opt, opt, inv, inv, inv, inv, inv, inv, req, opt, inv, inv }, + /* prof_item */ { opt, opt, inv, inv, inv, inv, inv, inv, req, req, inv, inv }, + /* reset_prof */ { opt, opt, inv, inv, inv, inv, inv, inv, inv, inv, req, inv }, + /* query_reserve */ { inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req }, }; struct parameter { @@ -141,11 +145,12 @@ static struct option options[] = { { "profile", no_argument, NULL, 'P'}, { "prof_item", required_argument, NULL, 'I'}, { "reset_prof", no_argument, NULL, 'R'}, + { "query_reserve", no_argument, NULL, 'Q'}, { NULL, 0, NULL, 0 } }; /* Command line option abbreviations */ -static const char option_string[] = "hvgc:n:SLOPI:R"; +static const char option_string[] = "hvgc:n:SLOPI:RQ"; /* Error message string */ @@ -372,6 +377,11 @@ get_command_line (int argc, char* argv[], struct command_line* line) rc = store_option (&cmdline, cmd_keyword_reset_prof, optarg); break; + case 'Q': + rc = store_option (&cmdline, cmd_keyword_query_reserve, + optarg); + break; + case -1: /* End of options string - start of devices list */ cmdline.device_id = optind; @@ -431,8 +441,11 @@ do_command (char* device, struct command_line cmdline) rc = disk_reset_prof (device); break; case cmd_keyword_prof_item: - break; - default: + break; + case cmd_keyword_query_reserve: + rc = disk_query_reserve_status(device); + break; + default: error_print ("Unknown command '%s' specified", get_keyword_name (i)); break; @@ -449,7 +462,7 @@ int main (int argc, char* argv[]) { struct command_line cmdline; - int rc; + int rc, finalrc; /* Find out what we're supposed to do */ rc = get_command_line (argc, argv, &cmdline); @@ -484,9 +497,12 @@ main (int argc, char* argv[]) return 1; } - while (cmdline.device_id < argc) { + finalrc = 0; + while (cmdline.device_id < argc) { rc = do_command (argv[cmdline.device_id], cmdline); + if (rc && !finalrc) + finalrc = rc; cmdline.device_id++; } - return 0; + return finalrc; } -- 1.7.3.5