在这里梳理一下zfs合并请求的代码部分。 如果fio 不等于lio,说明可以合并临近的IO请求。
if (fio != lio) {
uint64_t size = IO_SPAN(fio, lio); 找到IO之间的差值作为新的zio 的size。
ASSERT(size <= zfs_vdev_aggregation_limit);
ASSERT(vi != NULL);
以第一个zio的io_offset作为起始偏移量。
aio = zio_vdev_delegated_io(fio->io_vd, fio->io_offset,
vi, size, fio->io_type, ZIO_PRIORITY_AGG,
flags | ZIO_FLAG_DONT_CACHE | ZIO_FLAG_DONT_QUEUE,
vdev_queue_agg_io_done, NULL);
nio = fio;
do {
dio = nio;
nio = AVL_NEXT(t, dio);
ASSERT(dio->io_type == aio->io_type);
ASSERT(dio->io_vdev_tree == t);
if (dio->io_flags & ZIO_FLAG_NODATA) {
ASSERT(dio->io_type == ZIO_TYPE_WRITE);
bzero((char *)aio->io_data + (dio->io_offset -
aio->io_offset), dio->io_size);
} else if (dio->io_type == ZIO_TYPE_WRITE) {如果请求为写请求,那么就遍历avl树,由于写请求是按照偏移量来排序的,所以从dio当中复制缓冲区到aio当中。
bcopy(dio->io_data, (char *)aio->io_data +
(dio->io_offset - aio->io_offset),
dio->io_size);
}
zio_add_child(dio, aio);
vdev_queue_io_remove(vq, dio);
zio_vdev_io_bypass(dio);