示例#1
0
文件: dasd_erp.c 项目: ena30/snake-os
void
dasd_log_ccw(struct dasd_ccw_req * cqr, int caller, __u32 cpa)
{
	struct dasd_device *device;
	struct dasd_ccw_req *lcqr;
	struct ccw1 *ccw;
	int cplength;

	device = cqr->device;
	/* log the channel program */
	for (lcqr = cqr; lcqr != NULL; lcqr = lcqr->refers) {
		DEV_MESSAGE(KERN_ERR, device,
			    "(%s) ERP chain report for req: %p",
			    caller == 0 ? "EXAMINE" : "ACTION", lcqr);
		hex_dump_memory(device, lcqr, sizeof(struct dasd_ccw_req));

		cplength = 1;
		ccw = lcqr->cpaddr;
		while (ccw++->flags & (CCW_FLAG_DC | CCW_FLAG_CC))
			cplength++;

		if (cplength > 40) {	/* log only parts of the CP */
			DEV_MESSAGE(KERN_ERR, device, "%s",
				    "Start of channel program:");
			hex_dump_memory(device, lcqr->cpaddr,
					40*sizeof(struct ccw1));

			DEV_MESSAGE(KERN_ERR, device, "%s",
				    "End of channel program:");
			hex_dump_memory(device, lcqr->cpaddr + cplength - 10,
					10*sizeof(struct ccw1));
		} else {	/* log the whole CP */
			DEV_MESSAGE(KERN_ERR, device, "%s",
				    "Channel program (complete):");
			hex_dump_memory(device, lcqr->cpaddr,
					cplength*sizeof(struct ccw1));
		}

		if (lcqr != cqr)
			continue;

		/*
		 * Log bytes arround failed CCW but only if we did
		 * not log the whole CP of the CCW is outside the
		 * logged CP. 
		 */
		if (cplength > 40 ||
		    ((addr_t) cpa < (addr_t) lcqr->cpaddr &&
		     (addr_t) cpa > (addr_t) (lcqr->cpaddr + cplength + 4))) {
			
			DEV_MESSAGE(KERN_ERR, device,
				    "Failed CCW (%p) (area):",
				    (void *) (long) cpa);
			hex_dump_memory(device, cqr->cpaddr - 10,
					20*sizeof(struct ccw1));
		}
	}

}				/* end log_erp_chain */
示例#2
0
/*
 * performs formatting of _device_ according to _fdata_
 * Note: The discipline's format_function is assumed to deliver formatting
 * commands to format a single unit of the device. In terms of the ECKD
 * devices this means CCWs are generated to format a single track.
 */
static int dasd_format(struct dasd_block *block, struct format_data_t *fdata)
{
    struct dasd_ccw_req *cqr;
    struct dasd_device *base;
    int rc;

    base = block->base;
    if (base->discipline->format_device == NULL)
        return -EPERM;

    if (base->state != DASD_STATE_BASIC) {
        DEV_MESSAGE(KERN_WARNING, base, "%s",
                    "dasd_format: device is not disabled! ");
        return -EBUSY;
    }

    DBF_DEV_EVENT(DBF_NOTICE, base,
                  "formatting units %d to %d (%d B blocks) flags %d",
                  fdata->start_unit,
                  fdata->stop_unit, fdata->blksize, fdata->intensity);

    /* Since dasdfmt keeps the device open after it was disabled,
     * there still exists an inode for this device.
     * We must update i_blkbits, otherwise we might get errors when
     * enabling the device later.
     */
    if (fdata->start_unit == 0) {
        struct block_device *bdev = bdget_disk(block->gdp, 0);
        bdev->bd_inode->i_blkbits = blksize_bits(fdata->blksize);
        bdput(bdev);
    }

    while (fdata->start_unit <= fdata->stop_unit) {
        cqr = base->discipline->format_device(base, fdata);
        if (IS_ERR(cqr))
            return PTR_ERR(cqr);
        rc = dasd_sleep_on_interruptible(cqr);
        dasd_sfree_request(cqr, cqr->memdev);
        if (rc) {
            if (rc != -ERESTARTSYS)
                DEV_MESSAGE(KERN_ERR, base,
                            " Formatting of unit %d failed "
                            "with rc = %d",
                            fdata->start_unit, rc);
            return rc;
        }
        fdata->start_unit++;
    }
    return 0;
}
/*
 * dasd_default_erp_action just retries the current cqr
 */
struct dasd_ccw_req *
dasd_default_erp_action(struct dasd_ccw_req *cqr)
{
	struct dasd_device *device;

	device = cqr->startdev;

        /* just retry - there is nothing to save ... I got no sense data.... */
        if (cqr->retries > 0) {
		DEV_MESSAGE (KERN_DEBUG, device,
                             "default ERP called (%i retries left)",
                             cqr->retries);
		cqr->lpm    = LPM_ANYPATH;
		cqr->status = DASD_CQR_FILLED;
        } else {
                DEV_MESSAGE (KERN_WARNING, device, "%s",
			     "default ERP called (NO retry left)");
		cqr->status = DASD_CQR_FAILED;
		cqr->stopclk = get_clock();
        }
        return cqr;
}				/* end dasd_default_erp_action */
示例#4
0
文件: dasd_erp.c 项目: ena30/snake-os
/*
 * Print the hex dump of the memory used by a request. This includes
 * all error recovery ccws that have been chained in from of the 
 * real request.
 */
static inline void
hex_dump_memory(struct dasd_device *device, void *data, int len)
{
	int *pint;

	pint = (int *) data;
	while (len > 0) {
		DEV_MESSAGE(KERN_ERR, device, "%p: %08x %08x %08x %08x",
			    pint, pint[0], pint[1], pint[2], pint[3]);
		pint += 4;
		len -= 16;
	}
}
示例#5
0
/*
 * Quiesce device.
 */
static int dasd_ioctl_quiesce(struct dasd_block *block)
{
    unsigned long flags;
    struct dasd_device *base;

    base = block->base;
    if (!capable (CAP_SYS_ADMIN))
        return -EACCES;

    DEV_MESSAGE(KERN_DEBUG, base, "%s", "Quiesce IO on device");
    spin_lock_irqsave(get_ccwdev_lock(base->cdev), flags);
    base->stopped |= DASD_STOPPED_QUIESCE;
    spin_unlock_irqrestore(get_ccwdev_lock(base->cdev), flags);
    return 0;
}
示例#6
0
/*
 * Quiesce device.
 */
static int
dasd_ioctl_resume(struct dasd_device *device)
{
	unsigned long flags;

	if (!capable (CAP_SYS_ADMIN))
		return -EACCES;

	DEV_MESSAGE (KERN_DEBUG, device, "%s",
		     "resume IO on device");

	spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
	device->stopped &= ~DASD_STOPPED_QUIESCE;
	spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);

	dasd_schedule_bh (device);
	return 0;
}
示例#7
0
/*
 * Format device.
 */
static int
dasd_ioctl_format(struct block_device *bdev, void __user *argp)
{
    struct dasd_block *block = bdev->bd_disk->private_data;
    struct format_data_t fdata;

    if (!capable(CAP_SYS_ADMIN))
        return -EACCES;
    if (!argp)
        return -EINVAL;

    if (block->base->features & DASD_FEATURE_READONLY)
        return -EROFS;
    if (copy_from_user(&fdata, argp, sizeof(struct format_data_t)))
        return -EFAULT;
    if (bdev != bdev->bd_contains) {
        DEV_MESSAGE(KERN_WARNING, block->base, "%s",
                    "Cannot low-level format a partition");
        return -EINVAL;
    }
    return dasd_format(block, &fdata);
}