mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
libdasd: Add common DASD ioctl's to the lib
This will avoid code duplication in dasd-related programs. GitHub-ID: #19 Signed-off-by: Rafael Fonseca <r4f4rfs@gmail.com> Acked-by: Jan Höppner <hoeppner@linux.vnet.ibm.com> Signed-off-by: Stefan Haberland <sth@linux.vnet.ibm.com>
This commit is contained in:
committed by
Stefan Haberland
parent
0348a8443e
commit
a5c1923d32
207
include/lib/dasd_base.h
Normal file
207
include/lib/dasd_base.h
Normal file
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
* dasd_base - Library for DASD related functions
|
||||
*
|
||||
* DASD related helper functions for accessing device information
|
||||
*
|
||||
* Copyright IBM Corp. 2013, 2017
|
||||
* Copyright Red Hat Inc. 2017
|
||||
*
|
||||
* s390-tools is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
*/
|
||||
|
||||
#ifndef LIB_DASD_BASE_H
|
||||
#define LIB_DASD_BASE_H
|
||||
|
||||
#ifdef __linux__
|
||||
#include <linux/hdreg.h>
|
||||
#endif
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
typedef struct dasd_information2_t {
|
||||
unsigned int devno; /* S/390 devno */
|
||||
unsigned int real_devno; /* for aliases */
|
||||
unsigned int schid; /* S/390 subchannel identifier */
|
||||
unsigned int cu_type : 16; /* from SenseID */
|
||||
unsigned int cu_model : 8; /* from SenseID */
|
||||
unsigned int dev_type : 16; /* from SenseID */
|
||||
unsigned int dev_model : 8; /* from SenseID */
|
||||
unsigned int open_count;
|
||||
unsigned int req_queue_len;
|
||||
unsigned int chanq_len; /* length of chanq */
|
||||
char type[4]; /* from discipline.name, 'none' for unknown */
|
||||
unsigned int status; /* current device level */
|
||||
unsigned int label_block; /* where to find the VOLSER */
|
||||
unsigned int FBA_layout; /* fixed block size (like AIXVOL) */
|
||||
unsigned int characteristics_size;
|
||||
unsigned int confdata_size;
|
||||
unsigned char characteristics[64];/*from read_device_characteristics */
|
||||
unsigned char configuration_data[256];/*from read_configuration_data */
|
||||
unsigned int format; /* format info like formatted/cdl/ldl/... */
|
||||
unsigned int features; /* dasd features like 'ro',... */
|
||||
unsigned int reserved0; /* reserved for further use ,... */
|
||||
unsigned int reserved1; /* reserved for further use ,... */
|
||||
unsigned int reserved2; /* reserved for further use ,... */
|
||||
unsigned int reserved3; /* reserved for further use ,... */
|
||||
unsigned int reserved4; /* reserved for further use ,... */
|
||||
unsigned int reserved5; /* reserved for further use ,... */
|
||||
unsigned int reserved6; /* reserved for further use ,... */
|
||||
unsigned int reserved7; /* reserved for further use ,... */
|
||||
} dasd_information2_t;
|
||||
|
||||
struct dasd_eckd_characteristics {
|
||||
unsigned short cu_type;
|
||||
struct {
|
||||
unsigned char support:2;
|
||||
unsigned char async:1;
|
||||
unsigned char reserved:1;
|
||||
unsigned char cache_info:1;
|
||||
unsigned char model:3;
|
||||
} __attribute__ ((packed)) cu_model;
|
||||
unsigned short dev_type;
|
||||
unsigned char dev_model;
|
||||
struct {
|
||||
unsigned char mult_burst:1;
|
||||
unsigned char RT_in_LR:1;
|
||||
unsigned char reserved1:1;
|
||||
unsigned char RD_IN_LR:1;
|
||||
unsigned char reserved2:4;
|
||||
unsigned char reserved3:8;
|
||||
unsigned char defect_wr:1;
|
||||
unsigned char XRC_supported:1;
|
||||
unsigned char reserved4:1;
|
||||
unsigned char striping:1;
|
||||
unsigned char reserved5:4;
|
||||
unsigned char cfw:1;
|
||||
unsigned char reserved6:2;
|
||||
unsigned char cache:1;
|
||||
unsigned char dual_copy:1;
|
||||
unsigned char dfw:1;
|
||||
unsigned char reset_alleg:1;
|
||||
unsigned char sense_down:1;
|
||||
} __attribute__ ((packed)) facilities;
|
||||
unsigned char dev_class;
|
||||
unsigned char unit_type;
|
||||
unsigned short no_cyl;
|
||||
unsigned short trk_per_cyl;
|
||||
unsigned char sec_per_trk;
|
||||
unsigned char byte_per_track[3];
|
||||
unsigned short home_bytes;
|
||||
unsigned char formula;
|
||||
union {
|
||||
struct {
|
||||
unsigned char f1;
|
||||
unsigned short f2;
|
||||
unsigned short f3;
|
||||
} __attribute__ ((packed)) f_0x01;
|
||||
struct {
|
||||
unsigned char f1;
|
||||
unsigned char f2;
|
||||
unsigned char f3;
|
||||
unsigned char f4;
|
||||
unsigned char f5;
|
||||
} __attribute__ ((packed)) f_0x02;
|
||||
} __attribute__ ((packed)) factors;
|
||||
unsigned short first_alt_trk;
|
||||
unsigned short no_alt_trk;
|
||||
unsigned short first_dia_trk;
|
||||
unsigned short no_dia_trk;
|
||||
unsigned short first_sup_trk;
|
||||
unsigned short no_sup_trk;
|
||||
unsigned char MDR_ID;
|
||||
unsigned char OBR_ID;
|
||||
unsigned char director;
|
||||
unsigned char rd_trk_set;
|
||||
unsigned short max_rec_zero;
|
||||
unsigned char reserved1;
|
||||
unsigned char RWANY_in_LR;
|
||||
unsigned char factor6;
|
||||
unsigned char factor7;
|
||||
unsigned char factor8;
|
||||
unsigned char reserved2[3];
|
||||
unsigned char reserved3[6];
|
||||
unsigned int long_no_cyl;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/*
|
||||
* struct format_data_t
|
||||
* represents all data necessary to format a dasd
|
||||
*/
|
||||
typedef struct format_data_t {
|
||||
unsigned int start_unit; /* from track */
|
||||
unsigned int stop_unit; /* to track */
|
||||
unsigned int blksize; /* sectorsize */
|
||||
unsigned int intensity;
|
||||
} format_data_t;
|
||||
|
||||
/*
|
||||
* struct format_check_t
|
||||
* represents all data necessary to evaluate the format of
|
||||
* different tracks of a dasd
|
||||
*/
|
||||
typedef struct format_check_t {
|
||||
/* Input */
|
||||
struct format_data_t expect;
|
||||
|
||||
/* Output */
|
||||
unsigned int result; /* Error indication (DASD_FMT_ERR_*) */
|
||||
unsigned int unit; /* Track that is in error */
|
||||
unsigned int rec; /* Record that is in error */
|
||||
unsigned int num_records; /* Records in the track in error */
|
||||
unsigned int blksize; /* Block-size of first record in error */
|
||||
unsigned int key_length; /* Key length of first record in error */
|
||||
} format_check_t;
|
||||
|
||||
#ifndef __linux__
|
||||
/* definition from hdreg.h */
|
||||
struct hd_geometry {
|
||||
unsigned char heads;
|
||||
unsigned char sectors;
|
||||
unsigned short cylinders;
|
||||
unsigned long start;
|
||||
};
|
||||
#endif
|
||||
|
||||
#define DASD_IOCTL_LETTER 'D'
|
||||
|
||||
/* Disable the volume (for Linux) */
|
||||
#define BIODASDDISABLE _IO(DASD_IOCTL_LETTER, 0)
|
||||
/* Enable the volume (for Linux) */
|
||||
#define BIODASDENABLE _IO(DASD_IOCTL_LETTER, 1)
|
||||
/* Get information on a dasd device (enhanced) */
|
||||
#define BIODASDINFO2 _IOR(DASD_IOCTL_LETTER, 3, dasd_information2_t)
|
||||
/* #define BIODASDFORMAT _IOW(IOCTL_LETTER,0,format_data_t) , deprecated */
|
||||
#define BIODASDFMT _IOW(DASD_IOCTL_LETTER, 1, format_data_t)
|
||||
/* Check device format according to format_data_t */
|
||||
#define BIODASDCHECKFMT _IOWR(DASD_IOCTL_LETTER, 2, format_check_t)
|
||||
|
||||
/********************************************************************************
|
||||
* SECTION: Further IOCTL Definitions (see fs.h and hdreq.h)
|
||||
*******************************************************************************/
|
||||
/* get read-only status (0 = read_write) */
|
||||
#define BLKROGET _IO(0x12, 94)
|
||||
/* re-read partition table */
|
||||
#define BLKRRPART _IO(0x12, 95)
|
||||
/* get block device sector size */
|
||||
#define BLKSSZGET _IO(0x12, 104)
|
||||
/* return device size in bytes (u64 *arg) */
|
||||
#define BLKGETSIZE64 _IOR(0x12, 114, size_t)
|
||||
|
||||
#ifndef __linux__ /* from <linux/hdreg.h> */
|
||||
#define HDIO_GETGEO 0x0301
|
||||
#endif
|
||||
|
||||
int dasd_check_format(const char *device, format_check_t *p);
|
||||
int dasd_format_disk(int fd, format_data_t *p);
|
||||
int dasd_disk_disable(const char *device, int *fd);
|
||||
int dasd_disk_enable(int fd);
|
||||
int dasd_get_blocksize(const char *device, unsigned int *blksize);
|
||||
int dasd_get_blocksize_in_bytes(const char *device, unsigned long long *blksize);
|
||||
int dasd_get_geo(const char *device, struct hd_geometry *geo);
|
||||
int dasd_get_info(const char *device, dasd_information2_t *info);
|
||||
int dasd_is_ro(const char *device, bool *ro);
|
||||
int dasd_reread_partition_table(const char *device, int ntries);
|
||||
|
||||
#endif /* LIB_DASD_BASE_H */
|
||||
@@ -4,7 +4,7 @@ lib = libdasd.a
|
||||
|
||||
all: $(lib)
|
||||
|
||||
objects = dasd_sys.o
|
||||
objects = dasd_sys.o dasd_ioctl.o
|
||||
|
||||
$(lib): $(objects) Makefile
|
||||
|
||||
|
||||
263
libdasd/dasd_ioctl.c
Normal file
263
libdasd/dasd_ioctl.c
Normal file
@@ -0,0 +1,263 @@
|
||||
/*
|
||||
* dasd_ioctl - Library for dasd-related ioctls
|
||||
*
|
||||
* DASD related helper functions for accessing device information via ioctls
|
||||
*
|
||||
* Copyright IBM Corp. 2013, 2017
|
||||
* Copyright Red Hat Inc. 2017
|
||||
*
|
||||
* s390-tools is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
*/
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "lib/dasd_base.h"
|
||||
|
||||
#define COULD_NOT_OPEN_WARN(device) \
|
||||
warn("Could not open device '%s'", device)
|
||||
|
||||
#define COULD_NOT_CLOSE_WARN \
|
||||
warn("Unable to close device")
|
||||
|
||||
#define RUN_IOCTL(fd, req, argp) \
|
||||
do { \
|
||||
if (ioctl(fd, req, argp) != 0) { \
|
||||
int err = errno; \
|
||||
if (err != EBADF) \
|
||||
dasd_close_device(fd); \
|
||||
return err; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static int dasd_open_device(const char *device, int flags)
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = open(device, flags);
|
||||
if (fd == -1)
|
||||
COULD_NOT_OPEN_WARN(device);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
static void dasd_close_device(int fd)
|
||||
{
|
||||
if (close(fd) != 0)
|
||||
COULD_NOT_CLOSE_WARN;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get DASD block size information for device
|
||||
*
|
||||
* @param[in] device node device node's name
|
||||
* @param[out] blksize the block size
|
||||
*
|
||||
* @retval 0 in case of success
|
||||
* @retval errno in case of failure
|
||||
*
|
||||
*/
|
||||
int dasd_get_blocksize(const char *device, unsigned int *blksize)
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = dasd_open_device(device, O_RDONLY);
|
||||
RUN_IOCTL(fd, BLKSSZGET, blksize);
|
||||
dasd_close_device(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get DASD block size information (in bytes) for device
|
||||
*
|
||||
* @param[in] device node device node's name
|
||||
* @param[out] blksize block size in bytes
|
||||
*
|
||||
* @retval 0 in case of success
|
||||
* @retval errno in case of failure
|
||||
*/
|
||||
int dasd_get_blocksize_in_bytes(const char *device, unsigned long long *blksize)
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = dasd_open_device(device, O_RDONLY);
|
||||
RUN_IOCTL(fd, BLKGETSIZE64, blksize);
|
||||
dasd_close_device(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get DASD disk information for device
|
||||
*
|
||||
* @param[in] device node device node's name
|
||||
* @param[out] info pointer to dasd information
|
||||
*
|
||||
* @retval 0 in case of success
|
||||
* @retval errno in case of failure
|
||||
*/
|
||||
int dasd_get_info(const char *device, dasd_information2_t *info)
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = dasd_open_device(device, O_RDONLY);
|
||||
RUN_IOCTL(fd, BIODASDINFO2, info);
|
||||
dasd_close_device(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get DASD disk geometry information for device
|
||||
*
|
||||
* @param[in] device node device node's name
|
||||
* @param[out] geo pointer to device geometry information
|
||||
*
|
||||
* @retval errno in case of failure
|
||||
* @retval 0 in case of success
|
||||
*/
|
||||
int dasd_get_geo(const char *device, struct hd_geometry *geo)
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = dasd_open_device(device, O_RDONLY);
|
||||
RUN_IOCTL(fd, HDIO_GETGEO, geo);
|
||||
dasd_close_device(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get DASD read/write status information for device
|
||||
*
|
||||
* @param[in] device node device node's name
|
||||
* @param[out] ro read-only status (1 for ro, 0 for rw)
|
||||
*
|
||||
* @retval 0 in case of success
|
||||
* @retval errno in case of failure
|
||||
*/
|
||||
int dasd_is_ro(const char *device, bool *ro)
|
||||
{
|
||||
int fd, val;
|
||||
|
||||
fd = dasd_open_device(device, O_RDWR);
|
||||
RUN_IOCTL(fd, BLKROGET, &val);
|
||||
*ro = (val != 0) ? true : false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable DASD disk.
|
||||
*
|
||||
* @param[in] device node device node's name
|
||||
*
|
||||
* @retval 0 in case of success
|
||||
* @retval errno in case of failure
|
||||
*
|
||||
* Note: Before BIODASDFMT can be called, a DASD has to be disabled (or rather
|
||||
* put into a BASIC state) via BIODASDDISABLE. However, if you disable the DASD,
|
||||
* close the file descriptor, and then try to reopen it, it won't work as the
|
||||
* device isn't fully usable anymore. For BIODASDFMT to work, the file
|
||||
* descriptor opened for BIODASDISABLE has to be kept open until BIODASDFMT has
|
||||
* finished.
|
||||
*/
|
||||
int dasd_disk_disable(const char *device, int *fd)
|
||||
{
|
||||
*fd = dasd_open_device(device, O_RDWR);
|
||||
RUN_IOCTL(*fd, BIODASDDISABLE, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable DASD disk
|
||||
*
|
||||
* @param[in] device node device node's name
|
||||
*
|
||||
* @retval 0 in case of success
|
||||
* @retval errno in case of failure
|
||||
*/
|
||||
int dasd_disk_enable(int fd)
|
||||
{
|
||||
RUN_IOCTL(fd, BIODASDENABLE, NULL);
|
||||
dasd_close_device(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Format DASD disk
|
||||
*
|
||||
* @param[in] fd device node's file descriptor
|
||||
* @param[in] p format options
|
||||
*
|
||||
* @retval 0 in case of success
|
||||
* @retval errno in case of failure
|
||||
*/
|
||||
int dasd_format_disk(int fd, format_data_t *p)
|
||||
{
|
||||
RUN_IOCTL(fd, BIODASDFMT, p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check DASD format
|
||||
*
|
||||
* @param[in] device node device node's name
|
||||
* @param[in] p format params
|
||||
*
|
||||
* @retval 0 in case of success
|
||||
* @retval errno in case of failure
|
||||
*/
|
||||
int dasd_check_format(const char *device, format_check_t *p)
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = dasd_open_device(device, O_RDONLY);
|
||||
RUN_IOCTL(fd, BIODASDCHECKFMT, p);
|
||||
dasd_close_device(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reread partition table
|
||||
*
|
||||
* @param[in] device node device node's name
|
||||
* @param[in] ntries maximum number of tries
|
||||
*
|
||||
* @retval 0 in case of success
|
||||
* @retval errno in case of failure
|
||||
*/
|
||||
int dasd_reread_partition_table(const char *device, int ntries)
|
||||
{
|
||||
int i, fd, err = 0;
|
||||
|
||||
fd = dasd_open_device(device, O_RDONLY);
|
||||
|
||||
/*
|
||||
* If the BLKRRPART ioctl fails, it is most likely due to the device
|
||||
* just being in use by udev. So it is worthwhile to retry the ioctl
|
||||
* after a second as it is likely to succeed.
|
||||
*/
|
||||
for (i = 0; i < ntries; i++) {
|
||||
if (ioctl(fd, BLKRRPART, NULL) != 0) {
|
||||
err = errno;
|
||||
sleep(1);
|
||||
} else {
|
||||
err = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
dasd_close_device(fd);
|
||||
|
||||
return err;
|
||||
}
|
||||
Reference in New Issue
Block a user