1 /* 2 * snapshot_access block driver 3 * 4 * Copyright (c) 2022 Virtuozzo International GmbH. 5 * 6 * Author: 7 * Sementsov-Ogievskiy Vladimir <vsementsov@virtuozzo.com> 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program. If not, see <http://www.gnu.org/licenses/>. 21 */ 22 23 #include "qemu/osdep.h" 24 25 #include "sysemu/block-backend.h" 26 #include "qemu/cutils.h" 27 #include "block/block_int.h" 28 29 static coroutine_fn int 30 snapshot_access_co_preadv_part(BlockDriverState *bs, 31 int64_t offset, int64_t bytes, 32 QEMUIOVector *qiov, size_t qiov_offset, 33 BdrvRequestFlags flags) 34 { 35 if (flags) { 36 return -ENOTSUP; 37 } 38 39 return bdrv_co_preadv_snapshot(bs->file, offset, bytes, qiov, qiov_offset); 40 } 41 42 static int coroutine_fn 43 snapshot_access_co_block_status(BlockDriverState *bs, 44 bool want_zero, int64_t offset, 45 int64_t bytes, int64_t *pnum, 46 int64_t *map, BlockDriverState **file) 47 { 48 return bdrv_co_snapshot_block_status(bs->file->bs, want_zero, offset, 49 bytes, pnum, map, file); 50 } 51 52 static int coroutine_fn snapshot_access_co_pdiscard(BlockDriverState *bs, 53 int64_t offset, int64_t bytes) 54 { 55 return bdrv_co_pdiscard_snapshot(bs->file->bs, offset, bytes); 56 } 57 58 static int coroutine_fn 59 snapshot_access_co_pwrite_zeroes(BlockDriverState *bs, 60 int64_t offset, int64_t bytes, 61 BdrvRequestFlags flags) 62 { 63 return -ENOTSUP; 64 } 65 66 static coroutine_fn int 67 snapshot_access_co_pwritev_part(BlockDriverState *bs, 68 int64_t offset, int64_t bytes, 69 QEMUIOVector *qiov, size_t qiov_offset, 70 BdrvRequestFlags flags) 71 { 72 return -ENOTSUP; 73 } 74 75 76 static void snapshot_access_refresh_filename(BlockDriverState *bs) 77 { 78 pstrcpy(bs->exact_filename, sizeof(bs->exact_filename), 79 bs->file->bs->filename); 80 } 81 82 static int snapshot_access_open(BlockDriverState *bs, QDict *options, int flags, 83 Error **errp) 84 { 85 bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, 86 BDRV_CHILD_DATA | BDRV_CHILD_PRIMARY, 87 false, errp); 88 if (!bs->file) { 89 return -EINVAL; 90 } 91 92 bs->total_sectors = bs->file->bs->total_sectors; 93 94 return 0; 95 } 96 97 static void snapshot_access_child_perm(BlockDriverState *bs, BdrvChild *c, 98 BdrvChildRole role, 99 BlockReopenQueue *reopen_queue, 100 uint64_t perm, uint64_t shared, 101 uint64_t *nperm, uint64_t *nshared) 102 { 103 /* 104 * Currently, we don't need any permissions. If bs->file provides 105 * snapshot-access API, we can use it. 106 */ 107 *nperm = 0; 108 *nshared = BLK_PERM_ALL; 109 } 110 111 BlockDriver bdrv_snapshot_access_drv = { 112 .format_name = "snapshot-access", 113 114 .bdrv_open = snapshot_access_open, 115 116 .bdrv_co_preadv_part = snapshot_access_co_preadv_part, 117 .bdrv_co_pwritev_part = snapshot_access_co_pwritev_part, 118 .bdrv_co_pwrite_zeroes = snapshot_access_co_pwrite_zeroes, 119 .bdrv_co_pdiscard = snapshot_access_co_pdiscard, 120 .bdrv_co_block_status = snapshot_access_co_block_status, 121 122 .bdrv_refresh_filename = snapshot_access_refresh_filename, 123 124 .bdrv_child_perm = snapshot_access_child_perm, 125 }; 126 127 static void snapshot_access_init(void) 128 { 129 bdrv_register(&bdrv_snapshot_access_drv); 130 } 131 132 block_init(snapshot_access_init); 133