Files
s390-tools/libdasd/dasd_ioctl.c
Eduard Shishkin 6bd93f475c Clean up of libdasd
Remove standalone IOCTLs definitions and use sys/mount.h instead

Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com>
Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-29 17:03:57 +01:00

484 lines
10 KiB
C

/*
* 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 <sys/mount.h>
#include <unistd.h>
#include <string.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 { \
int rc = ioctl(fd, req, argp); \
if (rc != 0) { \
if (rc == -1) \
rc = errno; \
if (rc != EBADF) \
dasd_close_device(fd); \
return rc; \
} \
} 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_RDONLY);
RUN_IOCTL(fd, BLKROGET, &val);
*ro = (val != 0) ? true : false;
dasd_close_device(fd);
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;
}
/*
* Release Allocated Space
*
* @param[in] fd device node's file descriptor
* @param[in] r format options
*
* @retval 0 in case of success
* @retval errno in case of failure
*/
int dasd_release_space(const char *device, format_data_t *r)
{
int fd;
fd = dasd_open_device(device, O_RDONLY);
RUN_IOCTL(fd, BIODASDRAS, r);
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;
}
/*
* Reserve 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_reserve(const char *device)
{
int fd;
fd = dasd_open_device(device, O_RDONLY);
RUN_IOCTL(fd, BIODASDRSRV, NULL);
dasd_close_device(fd);
return 0;
}
/*
* Release 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_release(const char *device)
{
int fd;
fd = dasd_open_device(device, O_RDONLY);
RUN_IOCTL(fd, BIODASDRLSE, NULL);
dasd_close_device(fd);
return 0;
}
/*
* Unconditionally reserve DASD disk
*
* An existing reserve lock is lifted (steal lock) and the device
* is reserved.
*
* @param[in] device node device node's name
*
* @retval 0 in case of success
* @retval errno in case of failure
*/
int dasd_slock(const char *device)
{
int fd;
fd = dasd_open_device(device, O_RDONLY);
RUN_IOCTL(fd, BIODASDSLCK, NULL);
dasd_close_device(fd);
return 0;
}
/*
* Get the caching algorithm used for the channel programs of this device.
*
* @param[in] device node device node's name
* @param[out] attrib_data pointer to dasd attrib data with:
* 'cache' is the caching mode
* 'no_cyl' the number of cylinders to be cached.
*
* @retval 0 in case of success
* @retval errno in case of failure
*/
int dasd_get_cache(const char *device, attrib_data_t *attrib_data)
{
int fd;
fd = dasd_open_device(device, O_RDONLY);
RUN_IOCTL(fd, BIODASDGATTR, attrib_data);
dasd_close_device(fd);
return 0;
}
/*
* Set the caching algorithm used for the channel programs of this device.
*
* @param[in] device node device node's name
* @param[in] attrib_data pointer to dasd attrib data with:
* 'cache' is the caching mode
* 'no_cyl' the number of cylinders to be cached.
*
* @retval 0 in case of success
* @retval errno in case of failure
*/
int dasd_set_cache(const char *device, attrib_data_t *attrib_data)
{
int fd;
fd = dasd_open_device(device, O_RDONLY);
RUN_IOCTL(fd, BIODASDSATTR, attrib_data);
dasd_close_device(fd);
return 0;
}
/*
* Get reserve status of device.
*
* @param[in] device node device node's name
*
* @retval errno in case of failure
* @retval 0 unreserved
* @retval 1 implicit reserved
* @retval 2 other reservation
* @retval 3 reserved
*/
int dasd_query_reserve(const char *device)
{
struct dasd_snid_ioctl_data snid = { 0 };
int fd;
fd = dasd_open_device(device, O_RDONLY);
RUN_IOCTL(fd, BIODASDSNID, &snid);
dasd_close_device(fd);
return snid.data.path_state.reserve;
}
/*
* Get and print the profiling info of the device.
*
* @param[in] device node device node's name
* @param[in] dasd_profile_info pointer to dasd profile info
*
* @retval 0 in case of success
* @retval errno in case of failure
*/
int dasd_profile(const char *device, dasd_profile_info_t *dasd_profile_info)
{
int fd;
fd = dasd_open_device(device, O_RDONLY);
RUN_IOCTL(fd, BIODASDPRRD, dasd_profile_info);
dasd_close_device(fd);
return 0;
}
/*
* Reset the profiling counters of the device.
*
* @param[in] device node device node's name
*
* @retval 0 in case of success
* @retval errno in case of failure
*/
int dasd_reset_profile(const char *device)
{
int fd;
fd = dasd_open_device(device, O_RDONLY);
RUN_IOCTL(fd, BIODASDPRRST, NULL);
dasd_close_device(fd);
return 0;
}
/*
* Initiate the swap of a copy pairs primary,secondary relation.
* The old secondary will become the new primary and vice versa.
*
* @param[in] device node device node's name
* @param[in] copy_pair data pointer to dasd copypair data with:
* 'primary' old primary, becoming secondary
* 'secondary' old secondary, becoming primary.
*
* @retval errno in case of failure
* @retval 0 in case of success
* @retval 1 swap data invalid
* @retval 2 no active device found
* @retval 3 wrong primary specified
* @retval 4 secondary device not found
* @retval 5 swap already running
*/
int dasd_copy_swap(const char *device, struct dasd_copypair_swap_data *data)
{
int fd;
fd = dasd_open_device(device, O_RDONLY);
RUN_IOCTL(fd, BIODASDPPRCSWAP, data);
dasd_close_device(fd);
return 0;
}