[S390] dasd: provide a Sense Path Group ID ioctl
The BIODASDSNID ioctl executes a 'Sense Path Group ID' command on a DASD ECKD device. The returned path group data allows user space programs to determine path state and path group ID of the channel paths to the device. Signed-off-by: Stefan Weinhuber <wein@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
Родитель
b25c477b34
Коммит
196339f173
|
@ -217,6 +217,25 @@ typedef struct dasd_symmio_parms {
|
|||
int rssd_result_len;
|
||||
} __attribute__ ((packed)) dasd_symmio_parms_t;
|
||||
|
||||
/*
|
||||
* 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));
|
||||
|
||||
|
||||
/********************************************************************************
|
||||
* SECTION: Definition of IOCTLs
|
||||
*
|
||||
|
@ -261,25 +280,10 @@ typedef struct dasd_symmio_parms {
|
|||
/* 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)
|
||||
|
||||
#define BIODASDSYMMIO _IOWR(DASD_IOCTL_LETTER, 240, dasd_symmio_parms_t)
|
||||
|
||||
#endif /* DASD_H */
|
||||
|
||||
/*
|
||||
* Overrides for Emacs so that we follow Linus's tabbing style.
|
||||
* Emacs will notice this stuff at the end of the file and automatically
|
||||
* adjust the settings for this buffer only. This must remain at the end
|
||||
* of the file.
|
||||
* ---------------------------------------------------------------------------
|
||||
* Local variables:
|
||||
* c-indent-level: 4
|
||||
* c-brace-imaginary-offset: 0
|
||||
* c-brace-offset: -4
|
||||
* c-argdecl-indent: 4
|
||||
* c-label-offset: -4
|
||||
* c-continued-statement-offset: 4
|
||||
* c-continued-brace-offset: 0
|
||||
* indent-tabs-mode: nil
|
||||
* tab-width: 8
|
||||
* End:
|
||||
*/
|
||||
|
|
|
@ -2801,6 +2801,73 @@ dasd_eckd_steal_lock(struct dasd_device *device)
|
|||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* SNID - Sense Path Group ID
|
||||
* This ioctl may be used in situations where I/O is stalled due to
|
||||
* a reserve, so if the normal dasd_smalloc_request fails, we use the
|
||||
* preallocated dasd_reserve_req.
|
||||
*/
|
||||
static int dasd_eckd_snid(struct dasd_device *device,
|
||||
void __user *argp)
|
||||
{
|
||||
struct dasd_ccw_req *cqr;
|
||||
int rc;
|
||||
struct ccw1 *ccw;
|
||||
int useglobal;
|
||||
struct dasd_snid_ioctl_data usrparm;
|
||||
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EACCES;
|
||||
|
||||
if (copy_from_user(&usrparm, argp, sizeof(usrparm)))
|
||||
return -EFAULT;
|
||||
|
||||
useglobal = 0;
|
||||
cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1,
|
||||
sizeof(struct dasd_snid_data), device);
|
||||
if (IS_ERR(cqr)) {
|
||||
mutex_lock(&dasd_reserve_mutex);
|
||||
useglobal = 1;
|
||||
cqr = &dasd_reserve_req->cqr;
|
||||
memset(cqr, 0, sizeof(*cqr));
|
||||
memset(&dasd_reserve_req->ccw, 0,
|
||||
sizeof(dasd_reserve_req->ccw));
|
||||
cqr->cpaddr = &dasd_reserve_req->ccw;
|
||||
cqr->data = &dasd_reserve_req->data;
|
||||
cqr->magic = DASD_ECKD_MAGIC;
|
||||
}
|
||||
ccw = cqr->cpaddr;
|
||||
ccw->cmd_code = DASD_ECKD_CCW_SNID;
|
||||
ccw->flags |= CCW_FLAG_SLI;
|
||||
ccw->count = 12;
|
||||
ccw->cda = (__u32)(addr_t) cqr->data;
|
||||
cqr->startdev = device;
|
||||
cqr->memdev = device;
|
||||
clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
|
||||
set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
|
||||
cqr->retries = 5;
|
||||
cqr->expires = 10 * HZ;
|
||||
cqr->buildclk = get_clock();
|
||||
cqr->status = DASD_CQR_FILLED;
|
||||
cqr->lpm = usrparm.path_mask;
|
||||
|
||||
rc = dasd_sleep_on_immediatly(cqr);
|
||||
/* verify that I/O processing didn't modify the path mask */
|
||||
if (!rc && usrparm.path_mask && (cqr->lpm != usrparm.path_mask))
|
||||
rc = -EIO;
|
||||
if (!rc) {
|
||||
usrparm.data = *((struct dasd_snid_data *)cqr->data);
|
||||
if (copy_to_user(argp, &usrparm, sizeof(usrparm)))
|
||||
rc = -EFAULT;
|
||||
}
|
||||
|
||||
if (useglobal)
|
||||
mutex_unlock(&dasd_reserve_mutex);
|
||||
else
|
||||
dasd_sfree_request(cqr, cqr->memdev);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read performance statistics
|
||||
*/
|
||||
|
@ -3036,6 +3103,8 @@ dasd_eckd_ioctl(struct dasd_block *block, unsigned int cmd, void __user *argp)
|
|||
return dasd_eckd_reserve(device);
|
||||
case BIODASDSLCK:
|
||||
return dasd_eckd_steal_lock(device);
|
||||
case BIODASDSNID:
|
||||
return dasd_eckd_snid(device, argp);
|
||||
case BIODASDSYMMIO:
|
||||
return dasd_symm_io(device, argp);
|
||||
default:
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#define DASD_ECKD_CCW_WRITE_CKD 0x1d
|
||||
#define DASD_ECKD_CCW_READ_CKD 0x1e
|
||||
#define DASD_ECKD_CCW_PSF 0x27
|
||||
#define DASD_ECKD_CCW_SNID 0x34
|
||||
#define DASD_ECKD_CCW_RSSD 0x3e
|
||||
#define DASD_ECKD_CCW_LOCATE_RECORD 0x47
|
||||
#define DASD_ECKD_CCW_SNSS 0x54
|
||||
|
|
Загрузка…
Ссылка в новой задаче