- 论坛徽章:
- 0
|
块设备的IO请求处理
void request(request_queue_t *queue);由内核在适时读写时调用。
static void xxx_request(request_queue_t *q)
{
struct request *req;
while ((req=elv_next_request(q))!=NULL)
{
struct xxx_dev *dev = req->rq_disk->private_data;
if(!blk_fs_request(req))
{printk(KERN_NOTIC "skip no fs request \n");
end_request(req,0);
continue;
}
xxx_transfer(dev,req->sector, req->current_nr_sectors,
req->buffer, rq_data_dir(req));
end_request(req,1);
}
}
static void xxx_transfer(struct xxx_dev *dev, unsigned long sector,
unsigned long nsector, char *buffer, int write)
{
unsigned long offset = sector*KERNEL_SECTOR_SIZE;
unsigned long nbytes = nsect*KERNEL_SECTOR_SIZE;
if((offset + nbytes) >dev->size)
{prink(KERN_NOTICE "Beyond end write (%ld %ld) \n, offset, nbytes); return ;}
if(write)
{ write_dev(offset, buffer, nbytes);}
else read_dev(offset, bufferm nbytes);
}
void end_request(struct request *req, int update)
{
if(!end_that_request_first(req, uptodate, req->hard_sectors))
{
add_disk_randomness(req->rq_disks);
blkdev_dequeue_request(req);
end_that_request_last(req);
}
}
当一个设备完成一个IO请求的部分或全部扇区后,它必须告知设备层已经完成的扇区数目。
int end_that_request_first(struct request *req, int success, int count);
void end_that_request_last(struct request *req);告知所有等待这个请求完成的对象并回收
请求结构体。
==========================
遍历请求,BIO 段
static void xxx_full_request(request_queue_t *q)
{
struct request *req;
int sectors_xferred;
struct xxx_dev *dev = q->queuedata;
while((req=elv_next_request(q))!=NULL)
{
if(!blk_fs_request(req))
{printk(KERN_NOTIC "skip no fs request \n");
end_request(req,0);
continue;
}
sectors_xferred=xxx_xfer_request(dev,req);
if(!end_that_request_first(req, 1, sectors_xferred))
{blkdev_dequeue_request(req);
end_that_request_last(req);
}
}
}
static int xxx_xfer_request(struct xxx_dev *dev,struct request *req)
{
struct bio *bio;
int nsec=0;
rq_for_each_bio(bio, req)
{
xxx_xfer_bio(dev,bio);
nsect += bio->bi_size;
}
return nsect;
}
static int xxx_xfer_bio(struct xxx_dev *dev, struct bio *bio)
{
int i;
struct bio_vec *bvec;
sectors_t sector =bio->bi_sector;
bio_for_each_segment(bvec,bio, i)
{
char *buffer = __bio_map_atomic(bio, i, KM_USER0);
xxx_transfer(dev, sector, bio_cur_sectors(bio), buffer, bio_data_dir(bio) ==WRITE)
sector += bio_cur_sectors(bio);
__bio_kunmap(bio,KM_USER0);
}
return 0
}
======================
不使用请求队列
typedef int (make_request_fn) (request_queue_t *q, struct bio *bio);
完成后通知处理结束
void bio_endio(struct bio *bio, unsigned int bytes, int error)
bytes为已经传送的字节数。
static int xx_make_request(request_queue_t *q,struct bio *bio)
{
struct xxx_dev *dev = q->queuedata;
int status ;
status = xxx_xfer_bio(dec,bio);
bio_endio(bio,bio_bi_size, status);
return 0;
}
有请求队列 使用blk_init_queue(xxx_request,xxx_lock)
无 blk_alloc_queue blk_queue_make_request
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/69624/showart_1070882.html |
|