}
bdrv_iostatus_disable(bs);
notifier_list_init(&bs->close_notifiers);
+ notifier_with_return_list_init(&bs->before_write_notifiers);
return bs;
}
extract_subqdict(options, &file_options, "file.");
ret = bdrv_file_open(&file, filename, file_options,
- bdrv_open_flags(bs, flags));
+ bdrv_open_flags(bs, flags | BDRV_O_UNMAP));
if (ret < 0) {
goto fail;
}
return 0;
}
-struct BdrvTrackedRequest {
- BlockDriverState *bs;
- int64_t sector_num;
- int nb_sectors;
- bool is_write;
- QLIST_ENTRY(BdrvTrackedRequest) list;
- Coroutine *co; /* owner, used for deadlock detection */
- CoQueue wait_queue; /* coroutines blocked on this request */
-};
-
/**
* Remove an active request from the tracked requests list
*
tracked_request_begin(&req, bs, sector_num, nb_sectors, true);
- if (flags & BDRV_REQ_ZERO_WRITE) {
+ ret = notifier_with_return_list_notify(&bs->before_write_notifiers, &req);
+
+ if (ret < 0) {
+ /* Do nothing, write notifier decided to fail this request */
+ } else if (flags & BDRV_REQ_ZERO_WRITE) {
ret = bdrv_co_do_write_zeroes(bs, sector_num, nb_sectors);
} else {
ret = drv->bdrv_co_writev(bs, sector_num, nb_sectors, qiov);
}
}
+int bdrv_has_zero_init_1(BlockDriverState *bs)
+{
+ return 1;
+}
+
int bdrv_has_zero_init(BlockDriverState *bs)
{
assert(bs->drv);
return bs->drv->bdrv_has_zero_init(bs);
}
- return 1;
+ /* safe default */
+ return 0;
}
typedef struct BdrvCoIsAllocatedData {
/* Currently BlockDriverState always uses the main loop AioContext */
return qemu_get_aio_context();
}
+
+void bdrv_add_before_write_notifier(BlockDriverState *bs,
+ NotifierWithReturn *notifier)
+{
+ notifier_with_return_list_add(&bs->before_write_notifiers, notifier);
+}