static struct request * deadline_find_drq_hash(struct deadline_data *dd, sector_t offset) { struct list_head *hash_list = &dd->hash[DL_HASH_FN(offset)]; struct list_head *entry, *next = hash_list->next; while ((entry = next) != hash_list) { struct deadline_rq *drq = list_entry_hash(entry); struct request *__rq = drq->request; next = entry->next; BUG_ON(!ON_HASH(drq)); if (!rq_mergeable(__rq)) { __deadline_del_drq_hash(drq); continue; } if (rq_hash_key(__rq) == offset) return __rq; } return NULL; }
/* * can we safely merge with this request? */ int elv_rq_merge_ok(struct request *rq, struct bio *bio) { if (!rq_mergeable(rq)) return 0; /* * Don't merge file system requests and discard requests */ <<<<<<< HEAD
/* * add drq to rbtree and fifo */ static inline void deadline_add_request(struct request_queue *q, struct request *rq) { struct deadline_data *dd = q->elevator->elevator_data; struct deadline_rq *drq = RQ_DATA(rq); const int data_dir = rq_data_dir(drq->request); deadline_add_drq_rb(dd, drq); /* * set expire time (only used for reads) and add to fifo list */ drq->expires = jiffies + dd->fifo_expire[data_dir]; list_add_tail(&drq->fifo, &dd->fifo_list[data_dir]); if (rq_mergeable(rq)) { deadline_add_drq_hash(dd, drq); if (!q->last_merge) q->last_merge = rq; } }
bool blk_rq_merge_ok(struct request *rq, struct bio *bio) { struct request_queue *q = rq->q; if (!rq_mergeable(rq) || !bio_mergeable(bio)) return false; if (!blk_check_merge_flags(rq->cmd_flags, bio->bi_rw)) return false; /* different data direction or already started, don't merge */ if (bio_data_dir(bio) != rq_data_dir(rq)) return false; /* must be same device and not a special request */ if (rq->rq_disk != bio->bi_bdev->bd_disk || req_no_special_merge(rq)) return false; /* only merge integrity protected bio into ditto rq */ if (blk_integrity_merge_bio(rq->q, rq, bio) == false) return false; /* must be using the same buffer */ if (rq->cmd_flags & REQ_WRITE_SAME && !blk_write_same_mergeable(rq->bio, bio)) return false; /* Only check gaps if the bio carries data */ if (q->queue_flags & (1 << QUEUE_FLAG_SG_GAPS) && bio_has_data(bio)) { struct bio_vec *bprev; bprev = &rq->biotail->bi_io_vec[rq->biotail->bi_vcnt - 1]; if (bvec_gap_to_prev(bprev, bio->bi_io_vec[0].bv_offset)) return false; } return true; }
/* * Has to be called with the request spinlock acquired */ static int attempt_merge(struct request_queue *q, struct request *req, struct request *next) { if (!rq_mergeable(req) || !rq_mergeable(next)) return 0; if (!blk_check_merge_flags(req->cmd_flags, next->cmd_flags)) return 0; /* * not contiguous */ if (blk_rq_pos(req) + blk_rq_sectors(req) != blk_rq_pos(next)) return 0; if (rq_data_dir(req) != rq_data_dir(next) || req->rq_disk != next->rq_disk || req_no_special_merge(next)) return 0; if (req->cmd_flags & REQ_WRITE_SAME && !blk_write_same_mergeable(req->bio, next->bio)) return 0; /* * If we are allowed to merge, then append bio list * from next to rq and release next. merge_requests_fn * will have updated segment counts, update sector * counts here. */ if (!ll_merge_requests_fn(q, req, next)) return 0; /* * If failfast settings disagree or any of the two is already * a mixed merge, mark both as mixed before proceeding. This * makes sure that all involved bios have mixable attributes * set properly. */ if ((req->cmd_flags | next->cmd_flags) & REQ_MIXED_MERGE || (req->cmd_flags & REQ_FAILFAST_MASK) != (next->cmd_flags & REQ_FAILFAST_MASK)) { blk_rq_set_mixed_merge(req); blk_rq_set_mixed_merge(next); } /* * At this point we have either done a back merge * or front merge. We need the smaller start_time of * the merged requests to be the current request * for accounting purposes. */ if (time_after(req->start_time, next->start_time)) req->start_time = next->start_time; req->biotail->bi_next = next->bio; req->biotail = next->biotail; req->__data_len += blk_rq_bytes(next); elv_merge_requests(q, req, next); /* * 'next' is going away, so update stats accordingly */ blk_account_io_merge(next); req->ioprio = ioprio_best(req->ioprio, next->ioprio); if (blk_rq_cpu_valid(next)) req->cpu = next->cpu; /* owner-ship of bio passed from next to req */ next->bio = NULL; __blk_put_request(q, next); return 1; }