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 + -
显示快捷键?