s390utils/0057-tunedasd-add-new-option-Q-query_reserve.patch
2011-03-25 14:59:32 +01:00

341 lines
11 KiB
Diff

From a3fd27a0ce5920b66afbf89cb83a9b61db9460c7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Dan=20Hor=C3=A1k?= <dan@danny.cz>
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" " <n> "
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 <row> "
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