dasd.c

来自「linux-2.4.29操作系统的源码」· C语言 代码 · 共 2,133 行 · 第 1/5 页

C
2,133
字号
                switch (rc) {                case 0:         /* termination successful */                        check_then_set (&cqr->status,                                        CQR_STATUS_IN_IO,                                         CQR_STATUS_FAILED);                                                cqr->stopclk = get_clock ();                        break;                case -ENODEV:                        DBF_DEV_EVENT (DBF_ERR, device, "%s",                                       "device gone, retry");                        break;                case -EIO:                        DBF_DEV_EVENT (DBF_ERR, device, "%s",                                       "I/O error, retry");                        break;                case -EBUSY:                        DBF_DEV_EVENT (DBF_ERR, device, "%s",                                       "device busy, retry later");                        break;                default:                        DEV_MESSAGE (KERN_ERR, device,                                     "line %d unknown RC=%d, please "                                     "report to linux390@de.ibm.com",                                      __LINE__,                                      rc);                        BUG ();                        break;                }                dasd_schedule_bh (device);                retries ++;        }	return rc;}/* * function dasd_start_IO * attempts to start the IO and returns an appropriate return code */intdasd_start_IO (ccw_req_t * cqr){	int rc = 0;	dasd_device_t *device = cqr->device;	int irq;	unsigned long long now;	if (!cqr) {		BUG ();	}	irq = device->devinfo.irq;	if (strncmp ((char *) &cqr->magic,                      device->discipline->ebcname, 4)) {		DEV_MESSAGE (KERN_ERR, device,                             " ccw_req_t 0x%08x magic doesn't match"                             " discipline 0x%08x",                             cqr->magic,                             *(unsigned int *) device->discipline->name);		return -EINVAL;	}	now = get_clock ();        cqr->startclk = now;        if (!device->stopped)                rc = do_IO (irq, cqr->cpaddr, (long) cqr, cqr->lpm, cqr->options);        else                rc = -EBUSY;	switch (rc) {	case 0:                if (cqr->options & DOIO_WAIT_FOR_INTERRUPT) {                        /* request already finished (synchronous IO) */                        check_then_set (&cqr->status,                                        CQR_STATUS_QUEUED,                                         CQR_STATUS_DONE);                        cqr->stopclk = now;                        dasd_schedule_bh (device);                                        } else {                        check_then_set (&cqr->status,                                        CQR_STATUS_QUEUED,                                         CQR_STATUS_IN_IO);                }		break;	case -EBUSY:		DBF_DEV_EVENT (DBF_ERR, device, "%s",                               "device busy, retry later");                if (!timer_pending(&device->timer)) {                        init_timer (&device->timer);                        device->timer.function = dasd_schedule_bh_timed;                         device->timer.data     = (unsigned long) device;                        device->timer.expires  = jiffies + (HZ >> 4);                        add_timer (&device->timer);                } else {                        mod_timer(&device->timer, jiffies + (HZ >> 4));                }		break;	case -ETIMEDOUT: 		DBF_DEV_EVENT (DBF_ERR, device, "%s",                               "request timeout - terminated");	case -ENODEV:	case -EIO:		check_then_set (&cqr->status,				CQR_STATUS_QUEUED,                                 CQR_STATUS_FAILED);                cqr->stopclk = now;                dasd_schedule_bh (device);		break;	default:		DEV_MESSAGE (KERN_ERR, device,                             "line %d unknown RC=%d, please report"                             " to linux390@de.ibm.com",                             __LINE__,                              rc);		BUG ();		break;	}	return rc;}/* * function dasd_sleep_on_req * attempts to start the IO and waits for completion */intdasd_sleep_on_req (ccw_req_t * cqr){	unsigned long flags;	dasd_device_t *device = (dasd_device_t *) cqr->device;        if (signal_pending(current)) {                return -ERESTARTSYS;        }	s390irq_spin_lock_irqsave (device->devinfo.irq,                                    flags);        	dasd_chanq_enq (&device->queue,                         cqr);	/* let the bh start the request to keep them in order */	dasd_schedule_bh (device);        s390irq_spin_unlock_irqrestore (device->devinfo.irq,                                         flags);        wait_event (device->wait_q,                    cqr->flags & CQR_FLAGS_FINALIZED);         if (cqr->status == CQR_STATUS_FAILED) {                return -EIO;        }	return 0;} /* end dasd_sleep_on_req *//* * function dasd_sleep_on_immediate * same as dasd_sleep_on_req, but attempts to start the IO immediately  * (killing the actual running IO).  */static intdasd_sleep_on_immediate (ccw_req_t *cqr){	unsigned long flags;	dasd_device_t *device = (dasd_device_t *) cqr->device;        if (signal_pending(current))                return -ERESTARTSYS;	s390irq_spin_lock_irqsave (device->devinfo.irq,                                    flags);                /* terminate currently running IO */        if (device->queue.head->status == CQR_STATUS_IN_IO) {                device->discipline->term_IO (device->queue.head);                device->queue.head->status = CQR_STATUS_QUEUED;        }	dasd_chanq_enq_head (&device->queue,                              cqr);	/* let the bh start the request to keep them in order */	dasd_schedule_bh (device);        s390irq_spin_unlock_irqrestore (device->devinfo.irq,                                         flags);                wait_event (device->wait_q,                    cqr->flags & CQR_FLAGS_FINALIZED);                 if (cqr->status == CQR_STATUS_FAILED) {                return -EIO;        }	return 0;} /* end dasd_sleep_on_immediate *//* * function dasd_end_request * posts the buffer_cache about a finalized request * FIXME: for requests splitted to serveral cqrs */static inline voiddasd_end_request (struct request *req, int uptodate){	while (end_that_request_first (req, uptodate, DASD_NAME)) {	}#ifndef DEVICE_NO_RANDOM	add_blkdev_randomness (MAJOR (req->rq_dev));#endif	end_that_request_last (req);	return;}/* * function dasd_get_queue * returns the queue corresponding to a device behind a kdev */static request_queue_t *dasd_get_queue (kdev_t kdev){	dasd_device_t *device = dasd_device_from_kdev (kdev);	if (!device) {		return NULL;	}	return device->request_queue;}/* * function dasd_check_expire_time * check the request given as argument for expiration * and returns 0 if not yet expired, EIO else */static inline intdasd_check_expire_time (ccw_req_t * cqr){	unsigned long long now;	int rc = 0;	now = get_clock ();	if (cqr->expires &&             cqr->expires + cqr->startclk < now) {		DBF_DEV_EVENT (DBF_WARNING, ((dasd_device_t *) cqr->device),                               "IO timeout 0x%08lx%08lx usecs in req %p",                               (long) (cqr->expires >> 44),                               (long) (cqr->expires >> 12),                                cqr);		cqr->expires <<= 1;                rc = -EIO;	}	return rc;}/* * function dasd_finalize_request * implemets the actions to perform, when a request is finally finished * namely in status CQR_STATUS_DONE || CQR_STATUS_FAILED */static inline voiddasd_finalize_request (ccw_req_t * cqr){	dasd_device_t *device = cqr->device;	cqr->endclk = get_clock ();	if (cqr->req) {#ifdef DASD_PROFILE                if (dasd_profile_level == DASD_PROFILE_ON) {                        dasd_profile_add (cqr);                }#endif		dasd_end_request (cqr->req, (cqr->status == CQR_STATUS_DONE));		/* free request if nobody is waiting on it */		dasd_free_request (cqr, cqr->device);	} else {                if (cqr == device->init_cqr && /* bring late devices online */                    device->level <= DASD_STATE_ONLINE ) {                         if (!timer_pending(&device->late_timer)) {                                init_timer(&device->late_timer);                                device->late_timer.function = dasd_enable_single_device;                                 device->late_timer.data     = (unsigned long) device;                                device->late_timer.expires  = jiffies;                                add_timer(&device->late_timer);                        } else {                                mod_timer(&device->late_timer, jiffies);                        }                } else {                        /* notify sleep_on_xxx about finished cqr */                        cqr->flags |= CQR_FLAGS_FINALIZED;                }		/* notify sleeping task about finished postprocessing */		wake_up (&device->wait_q);                	}	return;}/* * function dasd_process_queues * transfers the requests on the queue given as argument to the chanq * if possible, the request ist started on a fastpath */static voiddasd_process_queues (dasd_device_t * device){	unsigned long flags;	struct request *req;	request_queue_t *queue = device->request_queue;	dasd_chanq_t *qp = &device->queue;	int irq = device->devinfo.irq;	ccw_req_t *final_requests = NULL;	int chanq_max_size = DASD_CHANQ_MAX_SIZE;	ccw_req_t *cqr = NULL, *temp;	dasd_erp_postaction_fn_t erp_postaction;	s390irq_spin_lock_irqsave (irq, flags);	/* First we dechain the requests, processed with completed status */	while (qp->head &&	       ((qp->head->status == CQR_STATUS_DONE  ) ||		(qp->head->status == CQR_STATUS_FAILED) ||		(qp->head->status == CQR_STATUS_ERROR )   )) {		dasd_erp_action_fn_t erp_action;		ccw_req_t            *erp_cqr = NULL;		/*  preprocess requests with CQR_STATUS_ERROR */		if (qp->head->status == CQR_STATUS_ERROR) {                        qp->head->retries--; 			if ((qp->head->dstat == NULL                                         ) ||			    ((qp->head->dstat->flag & DEVSTAT_FLAG_SENSE_AVAIL) == 0         ) ||			    (device->discipline->erp_action == NULL                          ) ||			    ((erp_action = device->discipline->erp_action (qp->head)) == NULL)   ) {                                				erp_cqr = dasd_default_erp_action (qp->head);			} else { /* call discipline ERP action */                                erp_cqr = erp_action (qp->head);                        }                        continue;		} else if (qp->head->refers) {	/* we deal with a finished ERP */			if (qp->head->status == CQR_STATUS_DONE) {                                DBF_DEV_EVENT (DBF_NOTICE, device, "%s",                                               "ERP successful");			} else {                                DEV_MESSAGE (KERN_WARNING, device, "%s",                                             "ERP unsuccessful");			}			if ((device->discipline->erp_postaction == NULL                              )||			    ((erp_postaction = device->discipline->erp_postaction (qp->head)) == NULL)  ) {                                dasd_default_erp_postaction (qp->head);			} else {  /* call ERP postaction of discipline */                                erp_postaction (qp->head);                        }			continue;		}		/* dechain request now */		if (final_requests == NULL)			final_requests = qp->head;		cqr      = qp->head;		qp->head = qp->head->next;		if (qp->head == NULL)			qp->tail = NULL;	} /* end while over completed requests */	if (cqr)		cqr->next = NULL;         /* terminate final_requests queue */	/* Now clean the requests with final status */	while (final_requests) { 		temp = final_requests;		final_requests = temp->next;		dasd_finalize_request (temp);	}	/* Now we try to fetch requests from the request queue */	for (temp = qp->head; temp != NULL; temp = temp->next) {		if (temp->status == CQR_STATUS_QUEUED)			chanq_max_size--;        }	while ((atomic_read(&device->plugged) == 0) &&               (queue) &&               (!queue->plugged) &&	       (!list_empty (&queue->queue_head)) &&	       (req = dasd_next_request (queue)) &&               (qp->head == NULL || chanq_max_size > 0)) {		/* queue empty or certain critera fulfille

⌨️ 快捷键说明

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