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

📄 elevator.c

📁 Linux块设备驱动源码
💻 C
📖 第 1 页 / 共 2 页
字号:
		BUG_ON(q->ordered == QUEUE_ORDERED_NONE);		if (q->ordered == QUEUE_ORDERED_FLUSH &&		    !blk_barrier_preflush(rq))			rq = blk_start_pre_flush(q, rq);	}	return rq;}struct request *elv_next_request(request_queue_t *q){	struct request *rq;	int ret;	while ((rq = __elv_next_request(q)) != NULL) {		/*		 * just mark as started even if we don't start it, a request		 * that has been delayed should not be passed by new incoming		 * requests		 */		rq->flags |= REQ_STARTED;		if (rq == q->last_merge)			q->last_merge = NULL;		if ((rq->flags & REQ_DONTPREP) || !q->prep_rq_fn)			break;		ret = q->prep_rq_fn(q, rq);		if (ret == BLKPREP_OK) {			break;		} else if (ret == BLKPREP_DEFER) {			/*			 * the request may have been (partially) prepped.			 * we need to keep this request in the front to			 * avoid resource deadlock.  turn on softbarrier.			 */			rq->flags |= REQ_SOFTBARRIER;			rq = NULL;			break;		} else if (ret == BLKPREP_KILL) {			int nr_bytes = rq->hard_nr_sectors << 9;			if (!nr_bytes)				nr_bytes = rq->data_len;			blkdev_dequeue_request(rq);			rq->flags |= REQ_QUIET;			end_that_request_chunk(rq, 0, nr_bytes);			end_that_request_last(rq);		} else {			printk(KERN_ERR "%s: bad return=%d\n", __FUNCTION__,								ret);			break;		}	}	return rq;}void elv_remove_request(request_queue_t *q, struct request *rq){	elevator_t *e = q->elevator;	/*	 * the time frame between a request being removed from the lists	 * and to it is freed is accounted as io that is in progress at	 * the driver side. note that we only account requests that the	 * driver has seen (REQ_STARTED set), to avoid false accounting	 * for request-request merges	 */	if (blk_account_rq(rq))		q->in_flight++;	/*	 * the main clearing point for q->last_merge is on retrieval of	 * request by driver (it calls elv_next_request()), but it _can_	 * also happen here if a request is added to the queue but later	 * deleted without ever being given to driver (merged with another	 * request).	 */	if (rq == q->last_merge)		q->last_merge = NULL;	if (e->ops->elevator_remove_req_fn)		e->ops->elevator_remove_req_fn(q, rq);}int elv_queue_empty(request_queue_t *q){	elevator_t *e = q->elevator;	if (e->ops->elevator_queue_empty_fn)		return e->ops->elevator_queue_empty_fn(q);	return list_empty(&q->queue_head);}struct request *elv_latter_request(request_queue_t *q, struct request *rq){	struct list_head *next;	elevator_t *e = q->elevator;	if (e->ops->elevator_latter_req_fn)		return e->ops->elevator_latter_req_fn(q, rq);	next = rq->queuelist.next;	if (next != &q->queue_head && next != &rq->queuelist)		return list_entry_rq(next);	return NULL;}struct request *elv_former_request(request_queue_t *q, struct request *rq){	struct list_head *prev;	elevator_t *e = q->elevator;	if (e->ops->elevator_former_req_fn)		return e->ops->elevator_former_req_fn(q, rq);	prev = rq->queuelist.prev;	if (prev != &q->queue_head && prev != &rq->queuelist)		return list_entry_rq(prev);	return NULL;}int elv_set_request(request_queue_t *q, struct request *rq, struct bio *bio,		    int gfp_mask){	elevator_t *e = q->elevator;	if (e->ops->elevator_set_req_fn)		return e->ops->elevator_set_req_fn(q, rq, bio, gfp_mask);	rq->elevator_private = NULL;	return 0;}void elv_put_request(request_queue_t *q, struct request *rq){	elevator_t *e = q->elevator;	if (e->ops->elevator_put_req_fn)		e->ops->elevator_put_req_fn(q, rq);}int elv_may_queue(request_queue_t *q, int rw, struct bio *bio){	elevator_t *e = q->elevator;	if (e->ops->elevator_may_queue_fn)		return e->ops->elevator_may_queue_fn(q, rw, bio);	return ELV_MQUEUE_MAY;}void elv_completed_request(request_queue_t *q, struct request *rq){	elevator_t *e = q->elevator;	/*	 * request is released from the driver, io must be done	 */	if (blk_account_rq(rq))		q->in_flight--;	if (e->ops->elevator_completed_req_fn)		e->ops->elevator_completed_req_fn(q, rq);}int elv_register_queue(struct request_queue *q){	elevator_t *e = q->elevator;	e->kobj.parent = kobject_get(&q->kobj);	if (!e->kobj.parent)		return -EBUSY;	snprintf(e->kobj.name, KOBJ_NAME_LEN, "%s", "iosched");	e->kobj.ktype = e->elevator_type->elevator_ktype;	return kobject_register(&e->kobj);}void elv_unregister_queue(struct request_queue *q){	if (q) {		elevator_t *e = q->elevator;		kobject_unregister(&e->kobj);		kobject_put(&q->kobj);	}}int elv_register(struct elevator_type *e){	if (elevator_find(e->elevator_name))		BUG();	spin_lock_irq(&elv_list_lock);	list_add_tail(&e->list, &elv_list);	spin_unlock_irq(&elv_list_lock);	printk(KERN_INFO "io scheduler %s registered", e->elevator_name);	if (!strcmp(e->elevator_name, chosen_elevator))		printk(" (default)");	printk("\n");	return 0;}EXPORT_SYMBOL_GPL(elv_register);void elv_unregister(struct elevator_type *e){	spin_lock_irq(&elv_list_lock);	list_del_init(&e->list);	spin_unlock_irq(&elv_list_lock);}EXPORT_SYMBOL_GPL(elv_unregister);/* * switch to new_e io scheduler. be careful not to introduce deadlocks - * we don't free the old io scheduler, before we have allocated what we * need for the new one. this way we have a chance of going back to the old * one, if the new one fails init for some reason. we also do an intermediate * switch to noop to ensure safety with stack-allocated requests, since they * don't originate from the block layer allocator. noop is safe here, because * it never needs to touch the elevator itself for completion events. DRAIN * flags will make sure we don't touch it for additions either. */static void elevator_switch(request_queue_t *q, struct elevator_type *new_e){	elevator_t *e = kmalloc(sizeof(elevator_t), GFP_KERNEL);	struct elevator_type *noop_elevator = NULL;	elevator_t *old_elevator;	if (!e)		goto error;	/*	 * first step, drain requests from the block freelist	 */	blk_wait_queue_drained(q, 0);	/*	 * unregister old elevator data	 */	elv_unregister_queue(q);	old_elevator = q->elevator;	/* 	 * next step, switch to noop since it uses no private rq structures	 * and doesn't allocate any memory for anything. then wait for any	 * non-fs requests in-flight 	 */	noop_elevator = elevator_get("noop");	spin_lock_irq(q->queue_lock);	elevator_attach(q, noop_elevator, e);	spin_unlock_irq(q->queue_lock);	blk_wait_queue_drained(q, 1);	/*	 * attach and start new elevator	 */	if (elevator_attach(q, new_e, e))		goto fail;	if (elv_register_queue(q))		goto fail_register;	/*	 * finally exit old elevator and start queue again	 */	elevator_exit(old_elevator);	blk_finish_queue_drain(q);	elevator_put(noop_elevator);	return;fail_register:	/*	 * switch failed, exit the new io scheduler and reattach the old	 * one again (along with re-adding the sysfs dir)	 */	elevator_exit(e);fail:	q->elevator = old_elevator;	elv_register_queue(q);	blk_finish_queue_drain(q);error:	if (noop_elevator)		elevator_put(noop_elevator);	elevator_put(new_e);	printk(KERN_ERR "elevator: switch to %s failed\n",new_e->elevator_name);}ssize_t elv_iosched_store(request_queue_t *q, const char *name, size_t count){	char elevator_name[ELV_NAME_MAX];	struct elevator_type *e;	memset(elevator_name, 0, sizeof(elevator_name));	strncpy(elevator_name, name, sizeof(elevator_name));	if (elevator_name[strlen(elevator_name) - 1] == '\n')		elevator_name[strlen(elevator_name) - 1] = '\0';	e = elevator_get(elevator_name);	if (!e) {		printk(KERN_ERR "elevator: type %s not found\n", elevator_name);		return -EINVAL;	}	if (!strcmp(elevator_name, q->elevator->elevator_type->elevator_name))		return count;	elevator_switch(q, e);	return count;}ssize_t elv_iosched_show(request_queue_t *q, char *name){	elevator_t *e = q->elevator;	struct elevator_type *elv = e->elevator_type;	struct list_head *entry;	int len = 0;	spin_lock_irq(q->queue_lock);	list_for_each(entry, &elv_list) {		struct elevator_type *__e;		__e = list_entry(entry, struct elevator_type, list);		if (!strcmp(elv->elevator_name, __e->elevator_name))			len += sprintf(name+len, "[%s] ", elv->elevator_name);		else			len += sprintf(name+len, "%s ", __e->elevator_name);	}	spin_unlock_irq(q->queue_lock);	len += sprintf(len+name, "\n");	return len;}EXPORT_SYMBOL(elv_add_request);EXPORT_SYMBOL(__elv_add_request);EXPORT_SYMBOL(elv_requeue_request);EXPORT_SYMBOL(elv_next_request);EXPORT_SYMBOL(elv_remove_request);EXPORT_SYMBOL(elv_queue_empty);EXPORT_SYMBOL(elv_completed_request);EXPORT_SYMBOL(elevator_exit);EXPORT_SYMBOL(elevator_init);

⌨️ 快捷键说明

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