aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/block/dasd_eckd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/block/dasd_eckd.c')
-rw-r--r--drivers/s390/block/dasd_eckd.c69
1 files changed, 69 insertions, 0 deletions
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 50cf96389d2c..bf61274af3bb 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -2802,6 +2802,73 @@ dasd_eckd_steal_lock(struct dasd_device *device)
2802} 2802}
2803 2803
2804/* 2804/*
2805 * SNID - Sense Path Group ID
2806 * This ioctl may be used in situations where I/O is stalled due to
2807 * a reserve, so if the normal dasd_smalloc_request fails, we use the
2808 * preallocated dasd_reserve_req.
2809 */
2810static int dasd_eckd_snid(struct dasd_device *device,
2811 void __user *argp)
2812{
2813 struct dasd_ccw_req *cqr;
2814 int rc;
2815 struct ccw1 *ccw;
2816 int useglobal;
2817 struct dasd_snid_ioctl_data usrparm;
2818
2819 if (!capable(CAP_SYS_ADMIN))
2820 return -EACCES;
2821
2822 if (copy_from_user(&usrparm, argp, sizeof(usrparm)))
2823 return -EFAULT;
2824
2825 useglobal = 0;
2826 cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1,
2827 sizeof(struct dasd_snid_data), device);
2828 if (IS_ERR(cqr)) {
2829 mutex_lock(&dasd_reserve_mutex);
2830 useglobal = 1;
2831 cqr = &dasd_reserve_req->cqr;
2832 memset(cqr, 0, sizeof(*cqr));
2833 memset(&dasd_reserve_req->ccw, 0,
2834 sizeof(dasd_reserve_req->ccw));
2835 cqr->cpaddr = &dasd_reserve_req->ccw;
2836 cqr->data = &dasd_reserve_req->data;
2837 cqr->magic = DASD_ECKD_MAGIC;
2838 }
2839 ccw = cqr->cpaddr;
2840 ccw->cmd_code = DASD_ECKD_CCW_SNID;
2841 ccw->flags |= CCW_FLAG_SLI;
2842 ccw->count = 12;
2843 ccw->cda = (__u32)(addr_t) cqr->data;
2844 cqr->startdev = device;
2845 cqr->memdev = device;
2846 clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
2847 set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
2848 cqr->retries = 5;
2849 cqr->expires = 10 * HZ;
2850 cqr->buildclk = get_clock();
2851 cqr->status = DASD_CQR_FILLED;
2852 cqr->lpm = usrparm.path_mask;
2853
2854 rc = dasd_sleep_on_immediatly(cqr);
2855 /* verify that I/O processing didn't modify the path mask */
2856 if (!rc && usrparm.path_mask && (cqr->lpm != usrparm.path_mask))
2857 rc = -EIO;
2858 if (!rc) {
2859 usrparm.data = *((struct dasd_snid_data *)cqr->data);
2860 if (copy_to_user(argp, &usrparm, sizeof(usrparm)))
2861 rc = -EFAULT;
2862 }
2863
2864 if (useglobal)
2865 mutex_unlock(&dasd_reserve_mutex);
2866 else
2867 dasd_sfree_request(cqr, cqr->memdev);
2868 return rc;
2869}
2870
2871/*
2805 * Read performance statistics 2872 * Read performance statistics
2806 */ 2873 */
2807static int 2874static int
@@ -3036,6 +3103,8 @@ dasd_eckd_ioctl(struct dasd_block *block, unsigned int cmd, void __user *argp)
3036 return dasd_eckd_reserve(device); 3103 return dasd_eckd_reserve(device);
3037 case BIODASDSLCK: 3104 case BIODASDSLCK:
3038 return dasd_eckd_steal_lock(device); 3105 return dasd_eckd_steal_lock(device);
3106 case BIODASDSNID:
3107 return dasd_eckd_snid(device, argp);
3039 case BIODASDSYMMIO: 3108 case BIODASDSYMMIO:
3040 return dasd_symm_io(device, argp); 3109 return dasd_symm_io(device, argp);
3041 default: 3110 default: