ll_rw_blk.c
来自「Linux块设备驱动源码」· C语言 代码 · 共 2,483 行 · 第 1/5 页
C
2,483 行
* @sectors: number of sectors to complete * * Description: * See blk_complete_barrier_rq(). This variant must be used if the caller * holds the queue lock. **/int blk_complete_barrier_rq_locked(request_queue_t *q, struct request *rq, int sectors){ return __blk_complete_barrier_rq(q, rq, sectors, 1);}EXPORT_SYMBOL(blk_complete_barrier_rq_locked);/** * blk_queue_bounce_limit - set bounce buffer limit for queue * @q: the request queue for the device * @dma_addr: bus address limit * * Description: * Different hardware can have different requirements as to what pages * it can do I/O directly to. A low level driver can call * blk_queue_bounce_limit to have lower memory pages allocated as bounce * buffers for doing I/O to pages residing above @page. By default * the block layer sets this to the highest numbered "low" memory page. **/void blk_queue_bounce_limit(request_queue_t *q, u64 dma_addr){ unsigned long bounce_pfn = dma_addr >> PAGE_SHIFT; /* * set appropriate bounce gfp mask -- unfortunately we don't have a * full 4GB zone, so we have to resort to low memory for any bounces. * ISA has its own < 16MB zone. */ if (bounce_pfn < blk_max_low_pfn) { BUG_ON(dma_addr < BLK_BOUNCE_ISA); init_emergency_isa_pool(); q->bounce_gfp = GFP_NOIO | GFP_DMA; } else q->bounce_gfp = GFP_NOIO; q->bounce_pfn = bounce_pfn;}EXPORT_SYMBOL(blk_queue_bounce_limit);/** * blk_queue_max_sectors - set max sectors for a request for this queue * @q: the request queue for the device * @max_sectors: max sectors in the usual 512b unit * * Description: * Enables a low level driver to set an upper limit on the size of * received requests. **/void blk_queue_max_sectors(request_queue_t *q, unsigned short max_sectors){ if ((max_sectors << 9) < PAGE_CACHE_SIZE) { max_sectors = 1 << (PAGE_CACHE_SHIFT - 9); printk("%s: set to minimum %d\n", __FUNCTION__, max_sectors); } q->max_sectors = q->max_hw_sectors = max_sectors;}EXPORT_SYMBOL(blk_queue_max_sectors);/** * blk_queue_max_phys_segments - set max phys segments for a request for this queue * @q: the request queue for the device * @max_segments: max number of segments * * Description: * Enables a low level driver to set an upper limit on the number of * physical data segments in a request. This would be the largest sized * scatter list the driver could handle. **/void blk_queue_max_phys_segments(request_queue_t *q, unsigned short max_segments){ if (!max_segments) { max_segments = 1; printk("%s: set to minimum %d\n", __FUNCTION__, max_segments); } q->max_phys_segments = max_segments;}EXPORT_SYMBOL(blk_queue_max_phys_segments);/** * blk_queue_max_hw_segments - set max hw segments for a request for this queue * @q: the request queue for the device * @max_segments: max number of segments * * Description: * Enables a low level driver to set an upper limit on the number of * hw data segments in a request. This would be the largest number of * address/length pairs the host adapter can actually give as once * to the device. **/void blk_queue_max_hw_segments(request_queue_t *q, unsigned short max_segments){ if (!max_segments) { max_segments = 1; printk("%s: set to minimum %d\n", __FUNCTION__, max_segments); } q->max_hw_segments = max_segments;}EXPORT_SYMBOL(blk_queue_max_hw_segments);/** * blk_queue_max_segment_size - set max segment size for blk_rq_map_sg * @q: the request queue for the device * @max_size: max size of segment in bytes * * Description: * Enables a low level driver to set an upper limit on the size of a * coalesced segment **/void blk_queue_max_segment_size(request_queue_t *q, unsigned int max_size){ if (max_size < PAGE_CACHE_SIZE) { max_size = PAGE_CACHE_SIZE; printk("%s: set to minimum %d\n", __FUNCTION__, max_size); } q->max_segment_size = max_size;}EXPORT_SYMBOL(blk_queue_max_segment_size);/** * blk_queue_hardsect_size - set hardware sector size for the queue * @q: the request queue for the device * @size: the hardware sector size, in bytes * * Description: * This should typically be set to the lowest possible sector size * that the hardware can operate on (possible without reverting to * even internal read-modify-write operations). Usually the default * of 512 covers most hardware. **/void blk_queue_hardsect_size(request_queue_t *q, unsigned short size){ q->hardsect_size = size;}EXPORT_SYMBOL(blk_queue_hardsect_size);/* * Returns the minimum that is _not_ zero, unless both are zero. */#define min_not_zero(l, r) (l == 0) ? r : ((r == 0) ? l : min(l, r))/** * blk_queue_stack_limits - inherit underlying queue limits for stacked drivers * @t: the stacking driver (top) * @b: the underlying device (bottom) **/void blk_queue_stack_limits(request_queue_t *t, request_queue_t *b){ /* zero is "infinity" */ t->max_sectors = t->max_hw_sectors = min_not_zero(t->max_sectors,b->max_sectors); t->max_phys_segments = min(t->max_phys_segments,b->max_phys_segments); t->max_hw_segments = min(t->max_hw_segments,b->max_hw_segments); t->max_segment_size = min(t->max_segment_size,b->max_segment_size); t->hardsect_size = max(t->hardsect_size,b->hardsect_size);}EXPORT_SYMBOL(blk_queue_stack_limits);/** * blk_queue_segment_boundary - set boundary rules for segment merging * @q: the request queue for the device * @mask: the memory boundary mask **/void blk_queue_segment_boundary(request_queue_t *q, unsigned long mask){ if (mask < PAGE_CACHE_SIZE - 1) { mask = PAGE_CACHE_SIZE - 1; printk("%s: set to minimum %lx\n", __FUNCTION__, mask); } q->seg_boundary_mask = mask;}EXPORT_SYMBOL(blk_queue_segment_boundary);/** * blk_queue_dma_alignment - set dma length and memory alignment * @q: the request queue for the device * @mask: alignment mask * * description: * set required memory and length aligment for direct dma transactions. * this is used when buiding direct io requests for the queue. * **/void blk_queue_dma_alignment(request_queue_t *q, int mask){ q->dma_alignment = mask;}EXPORT_SYMBOL(blk_queue_dma_alignment);/** * blk_queue_find_tag - find a request by its tag and queue * * @q: The request queue for the device * @tag: The tag of the request * * Notes: * Should be used when a device returns a tag and you want to match * it with a request. * * no locks need be held. **/struct request *blk_queue_find_tag(request_queue_t *q, int tag){ struct blk_queue_tag *bqt = q->queue_tags; if (unlikely(bqt == NULL || tag >= bqt->real_max_depth)) return NULL; return bqt->tag_index[tag];}EXPORT_SYMBOL(blk_queue_find_tag);/** * __blk_queue_free_tags - release tag maintenance info * @q: the request queue for the device * * Notes: * blk_cleanup_queue() will take care of calling this function, if tagging * has been used. So there's no need to call this directly. **/static void __blk_queue_free_tags(request_queue_t *q){ struct blk_queue_tag *bqt = q->queue_tags; if (!bqt) return; if (atomic_dec_and_test(&bqt->refcnt)) { BUG_ON(bqt->busy); BUG_ON(!list_empty(&bqt->busy_list)); kfree(bqt->tag_index); bqt->tag_index = NULL; kfree(bqt->tag_map); bqt->tag_map = NULL; kfree(bqt); } q->queue_tags = NULL; q->queue_flags &= ~(1 << QUEUE_FLAG_QUEUED);}/** * blk_queue_free_tags - release tag maintenance info * @q: the request queue for the device * * Notes: * This is used to disabled tagged queuing to a device, yet leave * queue in function. **/void blk_queue_free_tags(request_queue_t *q){ clear_bit(QUEUE_FLAG_QUEUED, &q->queue_flags);}EXPORT_SYMBOL(blk_queue_free_tags);static intinit_tag_map(request_queue_t *q, struct blk_queue_tag *tags, int depth){ struct request **tag_index; unsigned long *tag_map; int nr_ulongs; if (depth > q->nr_requests * 2) { depth = q->nr_requests * 2; printk(KERN_ERR "%s: adjusted depth to %d\n", __FUNCTION__, depth); } tag_index = kmalloc(depth * sizeof(struct request *), GFP_ATOMIC); if (!tag_index) goto fail; nr_ulongs = ALIGN(depth, BITS_PER_LONG) / BITS_PER_LONG; tag_map = kmalloc(nr_ulongs * sizeof(unsigned long), GFP_ATOMIC); if (!tag_map) goto fail; memset(tag_index, 0, depth * sizeof(struct request *)); memset(tag_map, 0, nr_ulongs * sizeof(unsigned long)); tags->real_max_depth = depth; tags->max_depth = depth; tags->tag_index = tag_index; tags->tag_map = tag_map; return 0;fail: kfree(tag_index); return -ENOMEM;}/** * blk_queue_init_tags - initialize the queue tag info * @q: the request queue for the device * @depth: the maximum queue depth supported * @tags: the tag to use **/int blk_queue_init_tags(request_queue_t *q, int depth, struct blk_queue_tag *tags){ int rc; BUG_ON(tags && q->queue_tags && tags != q->queue_tags); if (!tags && !q->queue_tags) { tags = kmalloc(sizeof(struct blk_queue_tag), GFP_ATOMIC); if (!tags) goto fail; if (init_tag_map(q, tags, depth)) goto fail; INIT_LIST_HEAD(&tags->busy_list); tags->busy = 0; atomic_set(&tags->refcnt, 1); } else if (q->queue_tags) { if ((rc = blk_queue_resize_tags(q, depth))) return rc; set_bit(QUEUE_FLAG_QUEUED, &q->queue_flags); return 0; } else atomic_inc(&tags->refcnt); /* * assign it, all done */ q->queue_tags = tags; q->queue_flags |= (1 << QUEUE_FLAG_QUEUED); return 0;fail: kfree(tags); return -ENOMEM;}EXPORT_SYMBOL(blk_queue_init_tags);/** * blk_queue_resize_tags - change the queueing depth * @q: the request queue for the device * @new_depth: the new max command queueing depth * * Notes: * Must be called with the queue lock held. **/int blk_queue_resize_tags(request_queue_t *q, int new_depth){ struct blk_queue_tag *bqt = q->queue_tags; struct request **tag_index; unsigned long *tag_map; int max_depth, nr_ulongs; if (!bqt) return -ENXIO; /* * if we already have large enough real_max_depth. just * adjust max_depth. *NOTE* as requests with tag value * between new_depth and real_max_depth can be in-flight, tag * map can not be shrunk blindly here. */ if (new_depth <= bqt->real_max_depth) { bqt->max_depth = new_depth; return 0; } /* * save the old state info, so we can copy it back */ tag_index = bqt->tag_index; tag_map = bqt->tag_map; max_depth = bqt->real_max_depth; if (init_tag_map(q, bqt, new_depth)) return -ENOMEM; memcpy(bqt->tag_index, tag_index, max_depth * sizeof(struct request *)); nr_ulongs = ALIGN(max_depth, BITS_PER_LONG) / BITS_PER_LONG; memcpy(bqt->tag_map, tag_map, nr_ulongs * sizeof(unsigned long)); kfree(tag_index); kfree(tag_map); return 0;}EXPORT_SYMBOL(blk_queue_resize_tags);/** * blk_queue_end_tag - end tag operations for a request * @q: the request queue for the device * @rq: the request that has completed * * Description: * Typically called when end_that_request_first() returns 0, meaning * all transfers have been done for a request. It's important to call * this function before end_that_request_last(), as that will put the * request back on the free list thus corrupting the internal tag list. * * Notes: * queue lock must be held. **/void blk_queue_end_tag(request_queue_t *q, struct request *rq){ struct blk_queue_tag *bqt = q->queue_tags; int tag = rq->tag; BUG_ON(tag == -1); if (unlikely(tag >= bqt->real_max_depth)) /* * This can happen after tag depth has been reduced. * FIXME: how about a warning or info message here? */ return; if (unlikely(!__test_and_clear_bit(tag, bqt->tag_map))) { printk(KERN_ERR "%s: attempt to clear non-busy tag (%d)\n", __FUNCTION__, tag); return; } list_del_init(&rq->queuelist); rq->flags &= ~REQ_QUEUED; rq->tag = -1; if (unlikely(bqt->tag_index[tag] == NULL)) printk(KERN_ERR "%s: tag %d is missing\n", __FUNCTION__, tag); bqt->tag_index[tag] = NULL; bqt->busy--;}EXPORT_SYMBOL(blk_queue_end_tag);/** * blk_queue_start_tag - find a free tag and assign it * @q: the request queue for the device * @rq: the block request that needs tagging * * Description: * This can either be used as a stand-alone helper, or possibly be * assigned as the queue &prep_rq_fn (in which case &struct request * automagically gets a tag assigned). Note that this function * assumes that any type of request can be queued! if this is not * true for your device, you must check the request type before * calling this function. The request will also be removed from * the request queue, so it's the drivers responsibility to readd * it if it should need to be restarted for some reason. * * Notes: * queue lock must be held. **/int blk_queue_start_tag(request_queue_t *q, struct request *rq){ struct blk_queue_tag *bqt = q->queue_tags; int tag; if (unlikely((rq->flags & REQ_QUEUED))) { printk(KERN_ERR "%s: request %p for device [%s] already tagged %d", __FUNCTION__, rq, rq->rq_disk ? rq->rq_disk->disk_name : "?", rq->tag); BUG(); } tag = find_first_zero_bit(bqt->tag_map, bqt->max_depth); if (tag >= bqt->max_depth) return 1; __set_bit(tag, bqt->tag_map); rq->flags |= REQ_QUEUED; rq->tag = tag;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?