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 int coroutine_fn GRAPH_RDLOCK 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 GRAPH_RDLOCK 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 GRAPH_RDLOCK 53 snapshot_access_co_pdiscard(BlockDriverState *bs, 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 GRAPH_RDLOCK 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 bdrv_open_child(NULL, options, "file", bs, &child_of_bds, 86 BDRV_CHILD_DATA | BDRV_CHILD_PRIMARY, 87 false, errp); 88 89 GRAPH_RDLOCK_GUARD_MAINLOOP(); 90 91 if (!bs->file) { 92 return -EINVAL; 93 } 94 95 bs->total_sectors = bs->file->bs->total_sectors; 96 97 return 0; 98 } 99 100 static void snapshot_access_child_perm(BlockDriverState *bs, BdrvChild *c, 101 BdrvChildRole role, 102 BlockReopenQueue *reopen_queue, 103 uint64_t perm, uint64_t shared, 104 uint64_t *nperm, uint64_t *nshared) 105 { 106 /* 107 * Currently, we don't need any permissions. If bs->file provides 108 * snapshot-access API, we can use it. 109 */ 110 *nperm = 0; 111 *nshared = BLK_PERM_ALL; 112 } 113 114 static BlockDriver bdrv_snapshot_access_drv = { 115 .format_name = "snapshot-access", 116 117 .bdrv_open = snapshot_access_open, 118 119 .bdrv_co_preadv_part = snapshot_access_co_preadv_part, 120 .bdrv_co_pwritev_part = snapshot_access_co_pwritev_part, 121 .bdrv_co_pwrite_zeroes = snapshot_access_co_pwrite_zeroes, 122 .bdrv_co_pdiscard = snapshot_access_co_pdiscard, 123 .bdrv_co_block_status = snapshot_access_co_block_status, 124 125 .bdrv_refresh_filename = snapshot_access_refresh_filename, 126 127 .bdrv_child_perm = snapshot_access_child_perm, 128 }; 129 130 static void snapshot_access_init(void) 131 { 132 bdrv_register(&bdrv_snapshot_access_drv); 133 } 134 135 block_init(snapshot_access_init); 136