⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dasd_eckd.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
        cqr->cpaddr->flags |= CCW_FLAG_SLI;        cqr->cpaddr->count = 32;	cqr->cpaddr->cda = (__u32)(addr_t) cqr->data;	cqr->device = device;	clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);	cqr->retries = 0;	cqr->expires = 2 * HZ;	cqr->buildclk = get_clock();	cqr->status = DASD_CQR_FILLED;	rc = dasd_sleep_on_immediatly(cqr);	dasd_sfree_request(cqr, cqr->device);	return rc;}/* * Steal lock ioctl - unconditional reserve device. * Buils a channel programm to break a device's reservation.  * (unconditional reserve) */static intdasd_eckd_steal_lock(struct block_device *bdev, int no, long args){	struct dasd_device *device;	struct dasd_ccw_req *cqr;	int rc;	if (!capable(CAP_SYS_ADMIN))		return -EACCES;	device = bdev->bd_disk->private_data;	if (device == NULL)		return -ENODEV;	cqr = dasd_smalloc_request(dasd_eckd_discipline.name,				   1, 32, device);	if (IS_ERR(cqr)) {		DEV_MESSAGE(KERN_WARNING, device, "%s",			    "Could not allocate initialization request");		return PTR_ERR(cqr);	}	cqr->cpaddr->cmd_code = DASD_ECKD_CCW_SLCK;        cqr->cpaddr->flags |= CCW_FLAG_SLI;        cqr->cpaddr->count = 32;	cqr->cpaddr->cda = (__u32)(addr_t) cqr->data;	cqr->device = device;	clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);	cqr->retries = 0;	cqr->expires = 2 * HZ;	cqr->buildclk = get_clock();	cqr->status = DASD_CQR_FILLED;	rc = dasd_sleep_on_immediatly(cqr);	dasd_sfree_request(cqr, cqr->device);	return rc;}/* * Read performance statistics */static intdasd_eckd_performance(struct block_device *bdev, int no, long args){	struct dasd_device *device;	struct dasd_psf_prssd_data *prssdp;	struct dasd_rssd_perf_stats_t *stats;	struct dasd_ccw_req *cqr;	struct ccw1 *ccw;	int rc;	device = bdev->bd_disk->private_data;	if (device == NULL)		return -ENODEV;	cqr = dasd_smalloc_request(dasd_eckd_discipline.name,				   1 /* PSF */  + 1 /* RSSD */ ,				   (sizeof (struct dasd_psf_prssd_data) +				    sizeof (struct dasd_rssd_perf_stats_t)),				   device);	if (IS_ERR(cqr)) {		DEV_MESSAGE(KERN_WARNING, device, "%s",			    "Could not allocate initialization request");		return PTR_ERR(cqr);	}	cqr->device = device;	cqr->retries = 0;	cqr->expires = 10 * HZ;	/* Prepare for Read Subsystem Data */	prssdp = (struct dasd_psf_prssd_data *) cqr->data;	memset(prssdp, 0, sizeof (struct dasd_psf_prssd_data));	prssdp->order = PSF_ORDER_PRSSD;	prssdp->suborder = 0x01;	/* Perfomance Statistics */	prssdp->varies[1] = 0x01;	/* Perf Statistics for the Subsystem */	ccw = cqr->cpaddr;	ccw->cmd_code = DASD_ECKD_CCW_PSF;	ccw->count = sizeof (struct dasd_psf_prssd_data);	ccw->flags |= CCW_FLAG_CC;	ccw->cda = (__u32)(addr_t) prssdp;	/* Read Subsystem Data - Performance Statistics */	stats = (struct dasd_rssd_perf_stats_t *) (prssdp + 1);	memset(stats, 0, sizeof (struct dasd_rssd_perf_stats_t));	ccw++;	ccw->cmd_code = DASD_ECKD_CCW_RSSD;	ccw->count = sizeof (struct dasd_rssd_perf_stats_t);	ccw->cda = (__u32)(addr_t) stats;	cqr->buildclk = get_clock();	cqr->status = DASD_CQR_FILLED;	rc = dasd_sleep_on(cqr);	if (rc == 0) {		/* Prepare for Read Subsystem Data */		prssdp = (struct dasd_psf_prssd_data *) cqr->data;		stats = (struct dasd_rssd_perf_stats_t *) (prssdp + 1);		rc = copy_to_user((long __user *) args, (long *) stats,				  sizeof(struct dasd_rssd_perf_stats_t));	}	dasd_sfree_request(cqr, cqr->device);	return rc;}/* * Get attributes (cache operations) * Returnes the cache attributes used in Define Extend (DE). */static intdasd_eckd_get_attrib (struct block_device *bdev, int no, long args){	struct dasd_device *device;        struct dasd_eckd_private *private;        struct attrib_data_t attrib;	int rc;        if (!capable(CAP_SYS_ADMIN))                return -EACCES;        if (!args)                return -EINVAL;        device = bdev->bd_disk->private_data;        if (device == NULL)                return -ENODEV;        private = (struct dasd_eckd_private *) device->private;        attrib = private->attrib;        rc = copy_to_user((long __user *) args, (long *) &attrib,			  sizeof (struct attrib_data_t));	return rc;}/* * Set attributes (cache operations) * Stores the attributes for cache operation to be used in Define Extend (DE). */static intdasd_eckd_set_attrib(struct block_device *bdev, int no, long args){	struct dasd_device *device;	struct dasd_eckd_private *private;	struct attrib_data_t attrib;	if (!capable(CAP_SYS_ADMIN))		return -EACCES;	if (!args)		return -EINVAL;	device = bdev->bd_disk->private_data;	if (device == NULL)		return -ENODEV;	if (copy_from_user(&attrib, (void __user *) args,			   sizeof (struct attrib_data_t))) {		return -EFAULT;	}	private = (struct dasd_eckd_private *) device->private;	private->attrib = attrib;	DEV_MESSAGE(KERN_INFO, device,		    "cache operation mode set to %x (%i cylinder prestage)",		    private->attrib.operation, private->attrib.nr_cyl);	return 0;}/* * Print sense data and related channel program. * Parts are printed because printk buffer is only 1024 bytes. */static voiddasd_eckd_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,		     struct irb *irb){	char *page;	struct ccw1 *act, *end, *last;	int len, sl, sct, count;	page = (char *) get_zeroed_page(GFP_ATOMIC);	if (page == NULL) {		DEV_MESSAGE(KERN_ERR, device, " %s",			    "No memory to dump sense data");		return;	}	len = sprintf(page, KERN_ERR PRINTK_HEADER		      " I/O status report for device %s:\n",		      device->cdev->dev.bus_id);	len += sprintf(page + len, KERN_ERR PRINTK_HEADER		       " in req: %p CS: 0x%02X DS: 0x%02X\n", req,		       irb->scsw.cstat, irb->scsw.dstat);	len += sprintf(page + len, KERN_ERR PRINTK_HEADER		       " device %s: Failing CCW: %p\n",		       device->cdev->dev.bus_id,		       (void *) (addr_t) irb->scsw.cpa);	if (irb->esw.esw0.erw.cons) {		for (sl = 0; sl < 4; sl++) {			len += sprintf(page + len, KERN_ERR PRINTK_HEADER				       " Sense(hex) %2d-%2d:",				       (8 * sl), ((8 * sl) + 7));			for (sct = 0; sct < 8; sct++) {				len += sprintf(page + len, " %02x",					       irb->ecw[8 * sl + sct]);			}			len += sprintf(page + len, "\n");		}		if (irb->ecw[27] & DASD_SENSE_BIT_0) {			/* 24 Byte Sense Data */			len += sprintf(page + len, KERN_ERR PRINTK_HEADER				       " 24 Byte: %x MSG %x, "				       "%s MSGb to SYSOP\n",				       irb->ecw[7] >> 4, irb->ecw[7] & 0x0f,				       irb->ecw[1] & 0x10 ? "" : "no");		} else {			/* 32 Byte Sense Data */			len += sprintf(page + len, KERN_ERR PRINTK_HEADER				       " 32 Byte: Format: %x "				       "Exception class %x\n",				       irb->ecw[6] & 0x0f, irb->ecw[22] >> 4);		}	} else {	        len += sprintf(page + len, KERN_ERR PRINTK_HEADER			       " SORRY - NO VALID SENSE AVAILABLE\n");	}	MESSAGE_LOG(KERN_ERR, "%s",		    page + sizeof(KERN_ERR PRINTK_HEADER));	/* dump the Channel Program */	/* print first CCWs (maximum 8) */	act = req->cpaddr;        for (last = act; last->flags & (CCW_FLAG_CC | CCW_FLAG_DC); last++);	end = min(act + 8, last);	len = sprintf(page, KERN_ERR PRINTK_HEADER		      " Related CP in req: %p\n", req);	while (act <= end) {		len += sprintf(page + len, KERN_ERR PRINTK_HEADER			       " CCW %p: %08X %08X DAT:",			       act, ((int *) act)[0], ((int *) act)[1]);		for (count = 0; count < 32 && count < act->count;		     count += sizeof(int))			len += sprintf(page + len, " %08X",				       ((int *) (addr_t) act->cda)				       [(count>>2)]);		len += sprintf(page + len, "\n");		act++;	}	MESSAGE_LOG(KERN_ERR, "%s",		    page + sizeof(KERN_ERR PRINTK_HEADER));	/* print failing CCW area */	len = 0;	if (act <  ((struct ccw1 *)(addr_t) irb->scsw.cpa) - 2) {		act = ((struct ccw1 *)(addr_t) irb->scsw.cpa) - 2;		len += sprintf(page + len, KERN_ERR PRINTK_HEADER "......\n");	}	end = min((struct ccw1 *)(addr_t) irb->scsw.cpa + 2, last);	while (act <= end) {		len += sprintf(page + len, KERN_ERR PRINTK_HEADER			       " CCW %p: %08X %08X DAT:",			       act, ((int *) act)[0], ((int *) act)[1]);		for (count = 0; count < 32 && count < act->count;		     count += sizeof(int))			len += sprintf(page + len, " %08X",				       ((int *) (addr_t) act->cda)				       [(count>>2)]);		len += sprintf(page + len, "\n");		act++;	}	/* print last CCWs */	if (act <  last - 2) {		act = last - 2;		len += sprintf(page + len, KERN_ERR PRINTK_HEADER "......\n");	}	while (act <= last) {		len += sprintf(page + len, KERN_ERR PRINTK_HEADER			       " CCW %p: %08X %08X DAT:",			       act, ((int *) act)[0], ((int *) act)[1]);		for (count = 0; count < 32 && count < act->count;		     count += sizeof(int))			len += sprintf(page + len, " %08X",				       ((int *) (addr_t) act->cda)				       [(count>>2)]);		len += sprintf(page + len, "\n");		act++;	}	if (len > 0)		MESSAGE_LOG(KERN_ERR, "%s",			    page + sizeof(KERN_ERR PRINTK_HEADER));	free_page((unsigned long) page);}/* * max_blocks is dependent on the amount of storage that is available * in the static io buffer for each device. Currently each device has * 8192 bytes (=2 pages). For 64 bit one dasd_mchunkt_t structure has * 24 bytes, the struct dasd_ccw_req has 136 bytes and each block can use * up to 16 bytes (8 for the ccw and 8 for the idal pointer). In * addition we have one define extent ccw + 16 bytes of data and one * locate record ccw + 16 bytes of data. That makes: * (8192 - 24 - 136 - 8 - 16 - 8 - 16) / 16 = 499 blocks at maximum. * We want to fit two into the available memory so that we can immediately * start the next request if one finishes off. That makes 249.5 blocks * for one request. Give a little safety and the result is 240. */static struct dasd_discipline dasd_eckd_discipline = {	.owner = THIS_MODULE,	.name = "ECKD",	.ebcname = "ECKD",	.max_blocks = 240,	.check_device = dasd_eckd_check_characteristics,	.do_analysis = dasd_eckd_do_analysis,	.fill_geometry = dasd_eckd_fill_geometry,	.start_IO = dasd_start_IO,	.term_IO = dasd_term_IO,	.format_device = dasd_eckd_format_device,	.examine_error = dasd_eckd_examine_error,	.erp_action = dasd_eckd_erp_action,	.erp_postaction = dasd_eckd_erp_postaction,	.build_cp = dasd_eckd_build_cp,	.free_cp = dasd_eckd_free_cp,	.dump_sense = dasd_eckd_dump_sense,	.fill_info = dasd_eckd_fill_info,};static int __initdasd_eckd_init(void){	int ret;	dasd_ioctl_no_register(THIS_MODULE, BIODASDGATTR,			       dasd_eckd_get_attrib);	dasd_ioctl_no_register(THIS_MODULE, BIODASDSATTR,			       dasd_eckd_set_attrib);	dasd_ioctl_no_register(THIS_MODULE, BIODASDPSRD,			       dasd_eckd_performance);	dasd_ioctl_no_register(THIS_MODULE, BIODASDRLSE,			       dasd_eckd_release);	dasd_ioctl_no_register(THIS_MODULE, BIODASDRSRV,			       dasd_eckd_reserve);	dasd_ioctl_no_register(THIS_MODULE, BIODASDSLCK,			       dasd_eckd_steal_lock);	ASCEBC(dasd_eckd_discipline.ebcname, 4);	ret = ccw_driver_register(&dasd_eckd_driver);	if (ret) {		dasd_ioctl_no_unregister(THIS_MODULE, BIODASDGATTR,					 dasd_eckd_get_attrib);		dasd_ioctl_no_unregister(THIS_MODULE, BIODASDSATTR,					 dasd_eckd_set_attrib);		dasd_ioctl_no_unregister(THIS_MODULE, BIODASDPSRD,					 dasd_eckd_performance);		dasd_ioctl_no_unregister(THIS_MODULE, BIODASDRLSE,					 dasd_eckd_release);		dasd_ioctl_no_unregister(THIS_MODULE, BIODASDRSRV,					 dasd_eckd_reserve);		dasd_ioctl_no_unregister(THIS_MODULE, BIODASDSLCK,					 dasd_eckd_steal_lock);		return ret;	}	dasd_generic_auto_online(&dasd_eckd_driver);	return 0;}static void __exitdasd_eckd_cleanup(void){	ccw_driver_unregister(&dasd_eckd_driver);	dasd_ioctl_no_unregister(THIS_MODULE, BIODASDGATTR,				 dasd_eckd_get_attrib);	dasd_ioctl_no_unregister(THIS_MODULE, BIODASDSATTR,				 dasd_eckd_set_attrib);	dasd_ioctl_no_unregister(THIS_MODULE, BIODASDPSRD,				 dasd_eckd_performance);	dasd_ioctl_no_unregister(THIS_MODULE, BIODASDRLSE,				 dasd_eckd_release);	dasd_ioctl_no_unregister(THIS_MODULE, BIODASDRSRV,				 dasd_eckd_reserve);	dasd_ioctl_no_unregister(THIS_MODULE, BIODASDSLCK,				 dasd_eckd_steal_lock);}module_init(dasd_eckd_init);module_exit(dasd_eckd_cleanup);/* * 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: 1 * tab-width: 8 * End: */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -