阿弥陀佛
分类: 服务器与存储
2013-01-26 14:00:45
在这里梳理一下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); zio_execute(dio); } while (dio != lio);直到遍历到最后一个缓冲区的位置。 avl_add(&vq->vq_pending_tree, aio); list_remove(&vq->vq_io_list, vi); return (aio); }bcopy将每个dio的缓冲区复制到aio当中,形成一个大的缓冲区aio,aio为每个dio的parent zio。