forked from pool/s390-tools
Marcus Meissner
9b729e2acc
New package per "Factory first" policy. Please list me as bug owner and maintainer, if possible. OBS-URL: https://build.opensuse.org/request/show/459343 OBS-URL: https://build.opensuse.org/package/show/Base:System/s390-tools?expand=0&rev=1
745 lines
22 KiB
Diff
745 lines
22 KiB
Diff
Subject: [PATCH] [FEAT LS1213] dasd: add query host access to volume support
|
|
From: Stefan Haberland <sth@linux.vnet.ibm.com>
|
|
|
|
Summary: dasd: add query host access to volume support
|
|
Description: With this feature, applications can query if a DASD volume is
|
|
online to another operating system instances by checking the
|
|
online status of all attached hosts from the storage server.
|
|
Upstream-ID: -
|
|
Problem-ID: LS1213
|
|
|
|
Signed-off-by: Stefan Haberland <sth@linux.vnet.ibm.com>
|
|
---
|
|
dasdfmt/dasdfmt.8 | 7 ++
|
|
dasdfmt/dasdfmt.c | 38 ++++++++++++--
|
|
dasdfmt/dasdfmt.h | 4 +
|
|
fdasd/fdasd.8 | 9 ++-
|
|
fdasd/fdasd.c | 32 ++++++++++++
|
|
fdasd/fdasd.h | 28 +++++-----
|
|
include/libzds.h | 1
|
|
include/u2s.h | 5 +
|
|
libu2s/u2s.c | 43 ++++++++++++++++
|
|
libzds/Makefile | 2
|
|
libzds/libzds.c | 46 +++++++++++++++--
|
|
zconf/lsdasd | 139 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
|
|
zconf/lsdasd.8 | 5 +
|
|
zdsfs/zdsfs.1 | 4 +
|
|
zdsfs/zdsfs.c | 18 ++++++
|
|
15 files changed, 345 insertions(+), 36 deletions(-)
|
|
|
|
--- a/dasdfmt/dasdfmt.8
|
|
+++ b/dasdfmt/dasdfmt.8
|
|
@@ -7,7 +7,7 @@ dasdfmt \- formatting of DASD (ECKD) dis
|
|
.br
|
|
[-r \fIcylinder\fR] [-b \fIblksize\fR] [-l \fIvolser\fR] [-d \fIlayout\fR]
|
|
.br
|
|
- [-L] [-V] [-F] [-k] \fIdevice\fR
|
|
+ [-L] [-V] [-F] [-k] [-C] \fIdevice\fR
|
|
|
|
.SH DESCRIPTION
|
|
\fBdasdfmt\fR formats a DASD (ECKD) disk drive to prepare it
|
|
@@ -70,6 +70,11 @@ Print version number and exit.
|
|
Formats the device without checking, if the device is in use.
|
|
|
|
.TP
|
|
+\fB-C\fR or \fB--check_host_count\fR
|
|
+Force dasdfmt to check the host access open count to ensure the device
|
|
+is not online on another operating system instance
|
|
+
|
|
+.TP
|
|
\fB-d\fR \fIlayout\fR or \fB--disk_layout\fR=\fIlayout\fR
|
|
Formats the device with compatible disk layout or linux disk layout.
|
|
\fIlayout\fR is either \fIcdl\fR for the compatible disk layout
|
|
--- a/dasdfmt/dasdfmt.c
|
|
+++ b/dasdfmt/dasdfmt.c
|
|
@@ -18,6 +18,8 @@
|
|
#include "util_proc.h"
|
|
#include "dasd_sys.h"
|
|
|
|
+#define BUSIDSIZE 8
|
|
+
|
|
/* Full tool name */
|
|
static const char tool_name[] = "dasdfmt: zSeries DASD format program";
|
|
|
|
@@ -46,7 +48,7 @@ print_version (void)
|
|
*/
|
|
static void exit_usage(int exitcode)
|
|
{
|
|
- printf("Usage: %s [-htvypPLVFk]\n"
|
|
+ printf("Usage: %s [-htvypPLVFkC]\n"
|
|
" [-l <volser> | --label=<volser>]\n"
|
|
" [-b <blocksize> | --blocksize=<blocksize>]\n"
|
|
" [-d <disk layout> | --disk_layout=<disk layout>]\n"
|
|
@@ -65,6 +67,9 @@ static void exit_usage(int exitcode)
|
|
" -v means verbose mode\n"
|
|
" -F means don't check if the device is in use\n"
|
|
" -k means keep volume serial\n"
|
|
+ " -C or --check_host_count means force dasdfmt to check\n"
|
|
+ " the host access open count to ensure the device\n"
|
|
+ " is not online on another operating system instance\n"
|
|
" --norecordzero prevent storage server from modifying"
|
|
" record 0\n\n"
|
|
" <volser> is the volume identifier, which is converted\n"
|
|
@@ -190,7 +195,6 @@ static void get_device_name(dasdfmt_info
|
|
}
|
|
}
|
|
|
|
-
|
|
/*
|
|
* initialize the dasdfmt info structure
|
|
*/
|
|
@@ -214,6 +218,7 @@ static void init_info(dasdfmt_info_t *in
|
|
info->node_specified = 0;
|
|
info->device_id = 0;
|
|
info->keep_volser = 0;
|
|
+ info->force_host = 0;
|
|
}
|
|
|
|
|
|
@@ -776,6 +781,7 @@ static void do_format_dasd(dasdfmt_info_
|
|
dasd_information_t dasd_info;
|
|
struct dasd_eckd_characteristics *characteristics;
|
|
unsigned int cylinders, heads;
|
|
+ int count;
|
|
|
|
if (info->verbosity > 0) printf("Retrieving disk geometry...\n");
|
|
|
|
@@ -835,6 +841,27 @@ static void do_format_dasd(dasdfmt_info_
|
|
if ((info->verbosity > 0) || (!info->withoutprompt))
|
|
dasdfmt_print_info(info, vlabel, cylinders, heads, p);
|
|
|
|
+ count = u2s_get_host_access_count(info->devname);
|
|
+ if (info->force_host) {
|
|
+ if (count > 1) {
|
|
+ ERRMSG_EXIT(EXIT_FAILURE,
|
|
+ "\n%s: Disk %s is online on OS instances in %d different LPARs.\n"
|
|
+ "Note: Your installation might include z/VM systems that are configured to\n"
|
|
+ "automatically vary on disks, regardless of whether they are subsequently used.\n\n",
|
|
+ prog_name, info->devname, count);
|
|
+ } else if (count < 0) {
|
|
+ ERRMSG("\nHosts access information not available for disk %s.\n\n",
|
|
+ info->devname);
|
|
+ return;
|
|
+ }
|
|
+ } else if (count > 1)
|
|
+ ERRMSG("\nWARNING:\n"
|
|
+ "Disk %s is online on operating system instances in %d different LPARs.\n"
|
|
+ "Ensure that the disk is not being used by a system outside your LPAR.\n"
|
|
+ "Note: Your installation might include z/VM systems that are configured to\n"
|
|
+ "automatically vary on disks, regardless of whether they are subsequently used.\n",
|
|
+ info->devname, count);
|
|
+
|
|
if (!info->testmode) {
|
|
if (!info->withoutprompt) {
|
|
printf("\n--->> ATTENTION! <<---\n");
|
|
@@ -916,10 +943,6 @@ int main(int argc,char *argv[])
|
|
info.force=1;
|
|
break;
|
|
|
|
- case 'C':
|
|
- format_params.intensity |= DASD_FMT_INT_COMPAT;
|
|
- break;
|
|
-
|
|
case 'd' :
|
|
if (strncmp(optarg,"cdl",3)==0)
|
|
{
|
|
@@ -1017,6 +1040,9 @@ int main(int argc,char *argv[])
|
|
case 'k' :
|
|
info.keep_volser=1;
|
|
break;
|
|
+ case 'C':
|
|
+ info.force_host = 1;
|
|
+ break;
|
|
case -1:
|
|
/* End of options string - start of devices list */
|
|
info.device_id = optind;
|
|
--- a/dasdfmt/dasdfmt.h
|
|
+++ b/dasdfmt/dasdfmt.h
|
|
@@ -214,7 +214,7 @@ typedef struct format_data_t {
|
|
if (*endptr) ERRMSG_EXIT(EXIT_MISUSE,"%s: " str " " \
|
|
"is in invalid format\n",prog_name);}
|
|
|
|
-#define dasdfmt_getopt_string "b:n:l:f:d:m:r:hpPLtyvVFk"
|
|
+#define dasdfmt_getopt_string "b:n:l:f:d:m:r:hpPLtyvVFkC"
|
|
|
|
static struct option dasdfmt_getopt_long_options[]=
|
|
{
|
|
@@ -233,6 +233,7 @@ static struct option dasdfmt_getopt_long
|
|
{ "help", 0, 0, 'h'},
|
|
{ "keep_volser", 0, 0, 'k'},
|
|
{ "norecordzero", 0, 0, 'z'},
|
|
+ { "check_host_count", 0, 0, 'C'},
|
|
{0, 0, 0, 0}
|
|
};
|
|
|
|
@@ -265,6 +266,7 @@ typedef struct dasdfmt_info {
|
|
int node_specified;
|
|
int device_id;
|
|
int keep_volser;
|
|
+ int force_host;
|
|
} dasdfmt_info_t;
|
|
|
|
|
|
--- a/fdasd/fdasd.8
|
|
+++ b/fdasd/fdasd.8
|
|
@@ -4,11 +4,11 @@ fdasd \- partitioning tool.
|
|
.SH SYNOPSIS
|
|
interactive mode:
|
|
.br
|
|
- \fBfdasd\fR [-s] [-r] \fIdevice\fR
|
|
+ \fBfdasd\fR [-s] [-r] [-C] \fIdevice\fR
|
|
.br
|
|
command line mode:
|
|
.br
|
|
- \fBfdasd\fR [-s] [-r] {-a[-k|-l \fIvolser\fR]|-i|-p|-c \fIconf_file\fR}
|
|
+ \fBfdasd\fR [-s] [-r] [-C] {-a[-k|-l \fIvolser\fR]|-i|-p|-c \fIconf_file\fR}
|
|
[-f \fI[type,blocksize]\fR] \fIdevice\fR
|
|
.br
|
|
help:
|
|
@@ -131,6 +131,11 @@ In combination with the -s option fdasd
|
|
partition table.
|
|
|
|
.TP
|
|
+\fB-C\fR or \fB--check_host_count\fR
|
|
+Force fdasd to check the host access open count to ensure the device
|
|
+is not online on another operating system instance
|
|
+
|
|
+.TP
|
|
\fB-f\fR \fI[type,blocksize]\fR or \fB--force\fR \fI[type,blocksize]\fR
|
|
Force fdasd to work on non DASD devices.
|
|
.br
|
|
--- a/fdasd/fdasd.c
|
|
+++ b/fdasd/fdasd.c
|
|
@@ -369,7 +369,10 @@ fdasd_usage (void)
|
|
" found in CONFIGFILE\n"
|
|
"-i, --volser Print volume serial\n"
|
|
"-p, --table Print partition table\n"
|
|
- "-f, --force Force fdasd to work on non DASD devices\n");
|
|
+ "-f, --force Force fdasd to work on non DASD devices\n"
|
|
+ "-C, --check_host_count Force fdasd to check the host access\n"
|
|
+ " open count to ensure the device is not\n"
|
|
+ " online on another operating system instance\n");
|
|
}
|
|
|
|
|
|
@@ -572,6 +575,9 @@ fdasd_parse_options (fdasd_anchor_t *anc
|
|
anc->force_virtual++;
|
|
fdasd_parse_force_options(anc, optarg);
|
|
break;
|
|
+ case 'C':
|
|
+ anc->force_host++;
|
|
+ break;
|
|
case -1:
|
|
/* End of options string - start of devices list */
|
|
break;
|
|
@@ -824,6 +830,7 @@ fdasd_verify_device (fdasd_anchor_t *anc
|
|
{
|
|
struct stat dst;
|
|
char err_str[ERROR_STRING_SIZE];
|
|
+ int count;
|
|
|
|
if ((stat(name, &dst)) < 0 ) {
|
|
snprintf(err_str, ERROR_STRING_SIZE,
|
|
@@ -856,6 +863,29 @@ fdasd_verify_device (fdasd_anchor_t *anc
|
|
fdasd_error(anc, device_verification_failed, err_str);
|
|
}
|
|
|
|
+ count = u2s_get_host_access_count(name);
|
|
+ if (anc->force_host) {
|
|
+ if (count > 1) {
|
|
+ snprintf(err_str, ERROR_STRING_SIZE,
|
|
+ "Disk %s is online on operating system instances in %d different LPARs.\n"
|
|
+ "Note: Your installation might include z/VM systems that are configured to\n"
|
|
+ "automatically vary on disks, regardless of whether they are subsequently used.\n",
|
|
+ name, count);
|
|
+ fdasd_error(anc, device_verification_failed, err_str);
|
|
+ } else if (count < 0) {
|
|
+ snprintf(err_str, ERROR_STRING_SIZE,
|
|
+ "Hosts access information not available for disk %s.\n",
|
|
+ name);
|
|
+ fdasd_error(anc, device_verification_failed, err_str);
|
|
+ }
|
|
+ } else if (count > 1)
|
|
+ printf("\nWARNING:\n"
|
|
+ "Disk %s is online on operating system instances in %d different LPARs.\n"
|
|
+ "Ensure that the disk is not being used by a system outside your LPAR.\n"
|
|
+ "Note: Your installation might include z/VM systems that are configured to\n"
|
|
+ "automatically vary on disks, regardless of whether they are subsequently used.\n\n",
|
|
+ name, count);
|
|
+
|
|
if (anc->verbose)
|
|
printf("Verification successful for '%s' (%d/%d)\n", name,
|
|
(unsigned short) major(dst.st_rdev),
|
|
--- a/fdasd/fdasd.h
|
|
+++ b/fdasd/fdasd.h
|
|
@@ -157,22 +157,23 @@ struct dasd_eckd_characteristics {
|
|
#define PARTITION_GPFS 5
|
|
|
|
static struct option fdasd_long_options[] = {
|
|
- { "version", no_argument, NULL, 'v'},
|
|
- { "auto", no_argument, NULL, 'a'},
|
|
- { "silent", no_argument, NULL, 's'},
|
|
- { "verbose", no_argument, NULL, 'r'},
|
|
- { "label", required_argument, NULL, 'l'},
|
|
- { "config", required_argument, NULL, 'c'},
|
|
- { "help", no_argument, NULL, 'h'},
|
|
- { "table", no_argument, NULL, 'p'},
|
|
- { "volser", no_argument, NULL, 'i'},
|
|
- { "keep_volser", no_argument, NULL, 'k'},
|
|
- { "force", optional_argument, NULL, 'f'},
|
|
- { 0, 0, 0, 0 }
|
|
+ { "version", no_argument, NULL, 'v'},
|
|
+ { "auto", no_argument, NULL, 'a'},
|
|
+ { "silent", no_argument, NULL, 's'},
|
|
+ { "verbose", no_argument, NULL, 'r'},
|
|
+ { "label", required_argument, NULL, 'l'},
|
|
+ { "config", required_argument, NULL, 'c'},
|
|
+ { "help", no_argument, NULL, 'h'},
|
|
+ { "table", no_argument, NULL, 'p'},
|
|
+ { "volser", no_argument, NULL, 'i'},
|
|
+ { "keep_volser", no_argument, NULL, 'k'},
|
|
+ { "force", optional_argument, NULL, 'f'},
|
|
+ { "check_host_count", no_argument, NULL, 'C'},
|
|
+ { 0, 0, 0, 0 }
|
|
};
|
|
|
|
/* Command line option abbreviations */
|
|
-static const char option_string[] = "vasrl:c:hpikf::";
|
|
+static const char option_string[] = "vasrl:c:hpikf::C";
|
|
|
|
struct fdasd_options {
|
|
char *device;
|
|
@@ -214,6 +215,7 @@ typedef struct fdasd_anchor {
|
|
int print_volser;
|
|
int keep_volser;
|
|
int force_virtual;
|
|
+ int force_host;
|
|
int big_disk;
|
|
int silent;
|
|
int verbose;
|
|
--- a/include/libzds.h
|
|
+++ b/include/libzds.h
|
|
@@ -803,6 +803,7 @@ int lzds_zdsroot_extract_datasets_from_d
|
|
void lzds_DS1RECFM_to_recfm(char DS1RECFM, char *buffer);
|
|
|
|
|
|
+int lzds_analyse_open_count(struct zdsroot *root, int warn);
|
|
|
|
/** @} */ /* end of group libzds_functions_helper */
|
|
|
|
--- a/include/u2s.h
|
|
+++ b/include/u2s.h
|
|
@@ -13,7 +13,8 @@
|
|
|
|
#define U2S_BUS_ID_SIZE 32
|
|
|
|
-int
|
|
-u2s_getbusid(char * devicenode, char * busid);
|
|
+int u2s_getbusid(char *, char *);
|
|
+int u2s_read_attribute(char *, char *, char *, size_t);
|
|
+int u2s_get_host_access_count(char *);
|
|
|
|
#endif /* U2S_H */
|
|
--- a/libu2s/u2s.c
|
|
+++ b/libu2s/u2s.c
|
|
@@ -17,6 +17,7 @@
|
|
#include <fcntl.h>
|
|
#include <sys/sysmacros.h>
|
|
#include <dirent.h>
|
|
+#include <stdlib.h>
|
|
|
|
#include "u2s.h"
|
|
|
|
@@ -282,3 +283,45 @@ int u2s_getbusid(char *devicenode, char
|
|
|
|
return rc;
|
|
}
|
|
+
|
|
+/*
|
|
+ * Attempts to find the sysfs entry for the given busid and reads
|
|
+ * the contents of a specified attribute to the buffer
|
|
+ */
|
|
+int u2s_read_attribute(char *busid, char *attribute, char *buffer,
|
|
+ size_t count)
|
|
+{
|
|
+ char path[100];
|
|
+ int rc, fd;
|
|
+ ssize_t rcount;
|
|
+
|
|
+ rc = 0;
|
|
+ snprintf(path, sizeof(path), "/sys/bus/ccw/devices/%s/%s",
|
|
+ busid, attribute);
|
|
+ fd = open(path, O_RDONLY);
|
|
+ if (fd < 0)
|
|
+ return errno;
|
|
+ rcount = read(fd, buffer, count);
|
|
+ if (rcount < 0)
|
|
+ rc = errno;
|
|
+ close(fd);
|
|
+ return rc;
|
|
+}
|
|
+
|
|
+int u2s_get_host_access_count(char *devicenode)
|
|
+{
|
|
+ char busid[BUSIDSIZE];
|
|
+ unsigned long value;
|
|
+ char buffer[10];
|
|
+ char *endp;
|
|
+
|
|
+ u2s_getbusid(devicenode, busid);
|
|
+ u2s_read_attribute(busid, "host_access_count", buffer, sizeof(buffer));
|
|
+
|
|
+ value = strtoul(buffer, &endp, 0);
|
|
+
|
|
+ if (endp == buffer)
|
|
+ return -EINVAL;
|
|
+
|
|
+ return value;
|
|
+}
|
|
--- a/libzds/Makefile
|
|
+++ b/libzds/Makefile
|
|
@@ -8,7 +8,7 @@ CFLAGS += -D_FILE_OFFSET_BITS=64
|
|
|
|
all: libzds.a
|
|
|
|
-libzds.a: libzds.o $(rootdir)/libutil/util_list.o $(rootdir)/libvtoc/vtoc.o
|
|
+libzds.a: libzds.o $(rootdir)/libutil/util_list.o $(rootdir)/libvtoc/vtoc.o $(rootdir)/libu2s/u2s.o
|
|
|
|
libzds.o: ../include/libzds.h
|
|
|
|
--- a/libzds/libzds.c
|
|
+++ b/libzds/libzds.c
|
|
@@ -29,6 +29,7 @@
|
|
#include "libzds.h"
|
|
|
|
#include "util.h"
|
|
+#include "u2s.h"
|
|
|
|
#include <malloc.h>
|
|
#include <linux/types.h>
|
|
@@ -72,6 +73,8 @@ struct errorlog {
|
|
*/
|
|
#define ERRORMSG 240
|
|
|
|
+#define BUSIDSIZE 8
|
|
+
|
|
/**
|
|
* @brief An internal structure that represents an entry in the error log.
|
|
*/
|
|
@@ -3760,15 +3763,46 @@ void lzds_DS1RECFM_to_recfm(char DS1RECF
|
|
*/
|
|
}
|
|
|
|
+int lzds_analyse_open_count(struct zdsroot *root, int warn)
|
|
+{
|
|
+ struct dasd *dasd;
|
|
+ int value;
|
|
+ int rc = 0;
|
|
|
|
+ util_list_iterate(root->dasdlist, dasd) {
|
|
+ value = u2s_get_host_access_count(dasd->device);
|
|
|
|
+ if (value < 0) {
|
|
+ fprintf(stderr,
|
|
+ "Hosts access information not available for disk %s.\n",
|
|
+ dasd->device);
|
|
+ rc = value;
|
|
+ continue;
|
|
+ }
|
|
|
|
+ if (value == 1)
|
|
+ continue;
|
|
|
|
+ if (warn)
|
|
+ fprintf(stderr,
|
|
+ "\nWARNING:\n"
|
|
+ "Disk %s is online on operating system instances in %d different LPARs.\n"
|
|
+ "Ensure that the disk is not being used by a system outside your LPAR.\n"
|
|
+ "Note: Your installation might include z/VM systems that are configured to\n"
|
|
+ "automatically vary on disks, regardless of whether they are subsequently used.\n",
|
|
+ dasd->device, value);
|
|
+ else {
|
|
+ fprintf(stderr,
|
|
+ "\nERROR:\n"
|
|
+ "Disk %s is online on operating system instances in %d different LPARs.\n"
|
|
+ "Ensure that the disk is not being used by a system outside your LPAR.\n"
|
|
+ "Note: Your installation might include z/VM systems that are configured to\n"
|
|
+ "automatically vary on disks, regardless of whether they are subsequently used.\n",
|
|
+ dasd->device, value);
|
|
+ rc = -EACCES;
|
|
+ }
|
|
+ }
|
|
|
|
-
|
|
-
|
|
-
|
|
-
|
|
-
|
|
-
|
|
+ return rc;
|
|
+}
|
|
|
|
--- a/zconf/lsdasd
|
|
+++ b/zconf/lsdasd
|
|
@@ -30,6 +30,8 @@ function PrintUsage() {
|
|
Print old version of lsdasd output.
|
|
-l|--long
|
|
Print extended information about DASDs.
|
|
+ -H|--host-access-list
|
|
+ Print information about hosts accessing DASDs.
|
|
-v|--verbose
|
|
For compatibility/future use. Currently ignored.
|
|
--version
|
|
@@ -115,6 +117,33 @@ function listDASDDeviceDirectories() {
|
|
}
|
|
|
|
#------------------------------------------------------------------------------
|
|
+# find dasd directory in debugfs
|
|
+#------------------------------------------------------------------------------
|
|
+function findDASDDebugfsDirectorie() {
|
|
+ local mntentries
|
|
+
|
|
+ while read -a mntentries
|
|
+ do
|
|
+ if [[ "${mntentries[2]}" == "debugfs" ]]
|
|
+ then
|
|
+ DASD_DBF_DIR="${mntentries[1]}"
|
|
+ break;
|
|
+ fi
|
|
+ done < /etc/mtab
|
|
+ if [[ "$DASD_DBF_DIR" == "" ]]
|
|
+ then
|
|
+ echo "$CMD: No debugfs mount point found" >&2
|
|
+ exit 1
|
|
+ fi
|
|
+ DASD_DBF_DIR="$DASD_DBF_DIR/dasd"
|
|
+ if [[ ! -d "$DASD_DBF_DIR" ]]
|
|
+ then
|
|
+ echo "$CMD: Default DASD debugfs directory $DASD_DBF_DIR does not exist" >&2
|
|
+ exit 1
|
|
+ fi
|
|
+}
|
|
+
|
|
+#------------------------------------------------------------------------------
|
|
# gather device data and call appropriate output function
|
|
#------------------------------------------------------------------------------
|
|
function gatherDeviceData() {
|
|
@@ -197,6 +226,8 @@ function gatherDeviceData() {
|
|
extended
|
|
elif [[ "$PRINTUID" == "true" ]]; then
|
|
uid
|
|
+ elif [[ "$OUTPUT" == "host" ]]; then
|
|
+ host
|
|
else
|
|
newoutput
|
|
fi
|
|
@@ -527,6 +558,104 @@ function extended()
|
|
"${HPF_PATHS[@]}" ;
|
|
}
|
|
|
|
+function host()
|
|
+{
|
|
+findDASDDebugfsDirectorie
|
|
+
|
|
+if [[ ! -f "$DASD_DBF_DIR/$BUSID/host_access_list" ]]
|
|
+then
|
|
+ printf "\n%s: hosts access information not available\n" "$BUSID"
|
|
+ return
|
|
+fi
|
|
+
|
|
+local temp=`mktemp /tmp/lsdasd.XXXXXX`
|
|
+if test -w $temp ; then :; else
|
|
+ printf "\nCreating temporary file failed\n"
|
|
+ return
|
|
+fi
|
|
+
|
|
+cat $DASD_DBF_DIR/$BUSID/host_access_list > $temp 2> /dev/null
|
|
+ret=$?
|
|
+if [[ $ret -ne 0 ]]
|
|
+then
|
|
+ printf "%s: hosts access information not available\n" "$BUSID"
|
|
+ rm -f $temp
|
|
+ return $ret
|
|
+fi
|
|
+
|
|
+unset index
|
|
+unset array
|
|
+declare -a array
|
|
+
|
|
+index=(pgid status_flags sysplex_name supported_cylinder timestamp)
|
|
+
|
|
+for element in ${index[@]}
|
|
+do
|
|
+ count=0
|
|
+
|
|
+ declare -a $element
|
|
+ OLDIFS=$IFS
|
|
+ IFS=$'\n'
|
|
+ for value in `grep $element $temp`
|
|
+ do
|
|
+ (( ++count ))
|
|
+ value=$(echo -e $value | cut -d ' ' -f2)
|
|
+ eval $element[$count]=$value
|
|
+ done
|
|
+ IFS=$OLDIFS
|
|
+done
|
|
+
|
|
+printf "Host information for %s\n" "$BUSID";
|
|
+printf "Path-Group-ID LPAR CPU FL Status Sysplex Max_Cyls Time\n";
|
|
+printf "================================================================================\n";
|
|
+
|
|
+# mask bits for online and reserved state
|
|
+online_reserved_mask=0xE0
|
|
+
|
|
+# print name value lists
|
|
+for i in `seq 1 $count`;
|
|
+do
|
|
+ # get flags field
|
|
+ value=${status_flags[$i]}
|
|
+ # mark as hex value
|
|
+ value=0x$value
|
|
+ # mask online and reserved bits
|
|
+ value=$(($value & $online_reserved_mask))
|
|
+
|
|
+ case $value in
|
|
+ 0 ) # 0x00
|
|
+ STATE="OFF"
|
|
+ ;;
|
|
+ 32 ) # 0x20
|
|
+ STATE="OFF-RSV"
|
|
+ ;;
|
|
+ 64 ) # 0x40
|
|
+ STATE="ON"
|
|
+ ;;
|
|
+ 96 ) # 0x60
|
|
+ STATE="ON-RSV"
|
|
+ ;;
|
|
+ * )
|
|
+ STATE="-"
|
|
+ ;;
|
|
+ esac
|
|
+
|
|
+ printf "%22s %02s %07s %02s %-6s %-8s %11u %10lu\n" \
|
|
+ "${pgid[$i]}" \
|
|
+ "${pgid[$i]:4:2}" \
|
|
+ "${pgid[$i]:6:4}" \
|
|
+ "${status_flags[$i]}" \
|
|
+ "$STATE" \
|
|
+ "${sysplex_name[$i]}" \
|
|
+ "${supported_cylinder[$i]}" \
|
|
+ "${timestamp[$i]}" \
|
|
+ ;
|
|
+done
|
|
+printf "\n";
|
|
+
|
|
+rm -f $temp
|
|
+}
|
|
+
|
|
function uid()
|
|
{
|
|
#-------------------------------------------#
|
|
@@ -586,6 +715,9 @@ while [ $# -gt 0 ]; do
|
|
--long|-l)
|
|
OUTPUT="extended"
|
|
;;
|
|
+ --host-access-list|-H)
|
|
+ OUTPUT="host"
|
|
+ ;;
|
|
--version)
|
|
PrintVersion
|
|
exit 0
|
|
@@ -626,8 +758,13 @@ fi
|
|
|
|
# gather information on devices in list
|
|
PROCESSING=" $PROCESSING | gatherDeviceData "
|
|
+
|
|
# sort resulting list
|
|
-PROCESSING=" $PROCESSING | sort -t: -k1n -k2 | cut -d: -f3- "
|
|
+if [[ "$OUTPUT" == "host" ]]; then
|
|
+ PROCESSING=" $PROCESSING"
|
|
+else
|
|
+ PROCESSING=" $PROCESSING | sort -t: -k1n -k2 | cut -d: -f3- "
|
|
+fi
|
|
|
|
if [[ "$PRINTUID" == "true" ]] && [[ "$OUTPUT" != "old" ]]; then
|
|
printf "Bus-ID Name UID\n"
|
|
--- a/zconf/lsdasd.8
|
|
+++ b/zconf/lsdasd.8
|
|
@@ -40,11 +40,14 @@ Include only base devices.
|
|
Old output of lsdasd for compatibility.
|
|
.TP
|
|
.BR -l | --long
|
|
-Extended output of lsdasd including UID, attributes and path information.
|
|
+Extended output of lsdasd including UID and attributes.
|
|
.TP
|
|
.BR -u | --uid
|
|
Output includes and is sorted by UID.
|
|
.TP
|
|
+.BR -H | --host-acces
|
|
+Show information about all hosts using this device.
|
|
+.TP
|
|
.BR -v | --verbose
|
|
Only for compatibility (and maybe future) use. This option currently does
|
|
nothing.
|
|
--- a/zdsfs/zdsfs.1
|
|
+++ b/zdsfs/zdsfs.1
|
|
@@ -150,6 +150,10 @@ If \fI<s>\fR is set to 0, no seek histor
|
|
case `seek' is still supported, but a `seek' operation might result in a
|
|
read from the beginning of the data set.
|
|
|
|
+.TP
|
|
+\fB\-o\fR check_host_count
|
|
+Stop processing if the device is used by another operating system instance.
|
|
+
|
|
.SS "Applicable FUSE options (version 2.8):"
|
|
This is a selected subset of all FUSE options. Use the zdsfs
|
|
\fB\--help\fR option to print a full list.
|
|
--- a/zdsfs/zdsfs.c
|
|
+++ b/zdsfs/zdsfs.c
|
|
@@ -39,6 +39,7 @@ struct zdsfs_info {
|
|
int devcount;
|
|
int allow_inclomplete_multi_volume;
|
|
int keepRDW;
|
|
+ int host_count;
|
|
unsigned int tracks_per_frame;
|
|
unsigned long long seek_buffer_size;
|
|
struct zdsroot *zdsroot;
|
|
@@ -765,6 +766,7 @@ static const struct fuse_opt zdsfs_opts[
|
|
FUSE_OPT_KEY("seekbuffer=", KEY_SEEKBUFFER),
|
|
ZDSFS_OPT("rdw", keepRDW, 1),
|
|
ZDSFS_OPT("ignore_incomplete", allow_inclomplete_multi_volume, 1),
|
|
+ ZDSFS_OPT("check_host_count", host_count, 1),
|
|
FUSE_OPT_END
|
|
};
|
|
|
|
@@ -790,7 +792,10 @@ static void usage(const char *progname)
|
|
" data set are missing\n"
|
|
" -o tracks=N Size of the track buffer in tracks (default 128)\n"
|
|
" -o seekbuffer=S Upper limit in bytes for the seek history buffer\n"
|
|
-" size (default 1048576)\n", progname);
|
|
+" size (default 1048576)\n"
|
|
+" -o check_host_count Stop processing if the device is used by another\n"
|
|
+" operating system instance\n"
|
|
+ , progname);
|
|
}
|
|
|
|
static void zdsfs_process_device(const char *device)
|
|
@@ -1014,6 +1019,17 @@ int main(int argc, char *argv[])
|
|
argv[0]);
|
|
exit(1);
|
|
}
|
|
+
|
|
+ if (zdsfsinfo.host_count) {
|
|
+ /* check, print error and exit if multiple online */
|
|
+ rc = lzds_analyse_open_count(zdsfsinfo.zdsroot, 0);
|
|
+ if (rc == -EACCES)
|
|
+ goto cleanup;
|
|
+ } else {
|
|
+ /* check, print warning if multiple online */
|
|
+ lzds_analyse_open_count(zdsfsinfo.zdsroot, 1);
|
|
+ }
|
|
+
|
|
rc = zdsfs_verify_datasets();
|
|
if (rc)
|
|
goto cleanup;
|