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