341 lines
11 KiB
Diff
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
|
|
|