qemu

Форк
0
/
raw-format.c 
682 строки · 19.9 Кб
1
/* BlockDriver implementation for "raw" format driver
2
 *
3
 * Copyright (C) 2010-2016 Red Hat, Inc.
4
 * Copyright (C) 2010, Blue Swirl <blauwirbel@gmail.com>
5
 * Copyright (C) 2009, Anthony Liguori <aliguori@us.ibm.com>
6
 *
7
 * Author:
8
 *   Laszlo Ersek <lersek@redhat.com>
9
 *
10
 * Permission is hereby granted, free of charge, to any person obtaining a copy
11
 * of this software and associated documentation files (the "Software"), to
12
 * deal in the Software without restriction, including without limitation the
13
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
14
 * sell copies of the Software, and to permit persons to whom the Software is
15
 * furnished to do so, subject to the following conditions:
16
 *
17
 * The above copyright notice and this permission notice shall be included in
18
 * all copies or substantial portions of the Software.
19
 *
20
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
26
 * IN THE SOFTWARE.
27
 */
28

29
#include "qemu/osdep.h"
30
#include "block/block-io.h"
31
#include "block/block_int.h"
32
#include "qapi/error.h"
33
#include "qemu/module.h"
34
#include "qemu/option.h"
35
#include "qemu/memalign.h"
36

37
typedef struct BDRVRawState {
38
    uint64_t offset;
39
    uint64_t size;
40
    bool has_size;
41
} BDRVRawState;
42

43
static const char *const mutable_opts[] = { "offset", "size", NULL };
44

45
static QemuOptsList raw_runtime_opts = {
46
    .name = "raw",
47
    .head = QTAILQ_HEAD_INITIALIZER(raw_runtime_opts.head),
48
    .desc = {
49
        {
50
            .name = "offset",
51
            .type = QEMU_OPT_SIZE,
52
            .help = "offset in the disk where the image starts",
53
        },
54
        {
55
            .name = "size",
56
            .type = QEMU_OPT_SIZE,
57
            .help = "virtual disk size",
58
        },
59
        { /* end of list */ }
60
    },
61
};
62

63
static QemuOptsList raw_create_opts = {
64
    .name = "raw-create-opts",
65
    .head = QTAILQ_HEAD_INITIALIZER(raw_create_opts.head),
66
    .desc = {
67
        {
68
            .name = BLOCK_OPT_SIZE,
69
            .type = QEMU_OPT_SIZE,
70
            .help = "Virtual disk size"
71
        },
72
        { /* end of list */ }
73
    }
74
};
75

76
static int raw_read_options(QDict *options, uint64_t *offset, bool *has_size,
77
                            uint64_t *size, Error **errp)
78
{
79
    QemuOpts *opts = NULL;
80
    int ret;
81

82
    opts = qemu_opts_create(&raw_runtime_opts, NULL, 0, &error_abort);
83
    if (!qemu_opts_absorb_qdict(opts, options, errp)) {
84
        ret = -EINVAL;
85
        goto end;
86
    }
87

88
    *offset = qemu_opt_get_size(opts, "offset", 0);
89
    *has_size = qemu_opt_find(opts, "size");
90
    *size = qemu_opt_get_size(opts, "size", 0);
91

92
    ret = 0;
93
end:
94
    qemu_opts_del(opts);
95
    return ret;
96
}
97

98
static int GRAPH_RDLOCK
99
raw_apply_options(BlockDriverState *bs, BDRVRawState *s, uint64_t offset,
100
                  bool has_size, uint64_t size, Error **errp)
101
{
102
    int64_t real_size = 0;
103

104
    real_size = bdrv_getlength(bs->file->bs);
105
    if (real_size < 0) {
106
        error_setg_errno(errp, -real_size, "Could not get image size");
107
        return real_size;
108
    }
109

110
    /* Check size and offset */
111
    if (offset > real_size) {
112
        error_setg(errp, "Offset (%" PRIu64 ") cannot be greater than "
113
                   "size of the containing file (%" PRId64 ")",
114
                   s->offset, real_size);
115
        return -EINVAL;
116
    }
117

118
    if (has_size && (real_size - offset) < size) {
119
        error_setg(errp, "The sum of offset (%" PRIu64 ") and size "
120
                   "(%" PRIu64 ") has to be smaller or equal to the "
121
                   " actual size of the containing file (%" PRId64 ")",
122
                   s->offset, s->size, real_size);
123
        return -EINVAL;
124
    }
125

126
    /* Make sure size is multiple of BDRV_SECTOR_SIZE to prevent rounding
127
     * up and leaking out of the specified area. */
128
    if (has_size && !QEMU_IS_ALIGNED(size, BDRV_SECTOR_SIZE)) {
129
        error_setg(errp, "Specified size is not multiple of %llu",
130
                   BDRV_SECTOR_SIZE);
131
        return -EINVAL;
132
    }
133

134
    s->offset = offset;
135
    s->has_size = has_size;
136
    s->size = has_size ? size : real_size - offset;
137

138
    return 0;
139
}
140

141
static int raw_reopen_prepare(BDRVReopenState *reopen_state,
142
                              BlockReopenQueue *queue, Error **errp)
143
{
144
    bool has_size;
145
    uint64_t offset, size;
146
    int ret;
147

148
    GLOBAL_STATE_CODE();
149
    GRAPH_RDLOCK_GUARD_MAINLOOP();
150

151
    assert(reopen_state != NULL);
152
    assert(reopen_state->bs != NULL);
153

154
    reopen_state->opaque = g_new0(BDRVRawState, 1);
155

156
    ret = raw_read_options(reopen_state->options, &offset, &has_size, &size,
157
                           errp);
158
    if (ret < 0) {
159
        return ret;
160
    }
161

162
    ret = raw_apply_options(reopen_state->bs, reopen_state->opaque,
163
                            offset, has_size, size, errp);
164
    if (ret < 0) {
165
        return ret;
166
    }
167

168
    return 0;
169
}
170

171
static void raw_reopen_commit(BDRVReopenState *state)
172
{
173
    BDRVRawState *new_s = state->opaque;
174
    BDRVRawState *s = state->bs->opaque;
175

176
    memcpy(s, new_s, sizeof(BDRVRawState));
177

178
    g_free(state->opaque);
179
    state->opaque = NULL;
180
}
181

182
static void raw_reopen_abort(BDRVReopenState *state)
183
{
184
    g_free(state->opaque);
185
    state->opaque = NULL;
186
}
187

188
/* Check and adjust the offset, against 'offset' and 'size' options. */
189
static inline int raw_adjust_offset(BlockDriverState *bs, int64_t *offset,
190
                                    int64_t bytes, bool is_write)
191
{
192
    BDRVRawState *s = bs->opaque;
193

194
    if (s->has_size && (*offset > s->size || bytes > (s->size - *offset))) {
195
        /* There's not enough space for the write, or the read request is
196
         * out-of-range. Don't read/write anything to prevent leaking out of
197
         * the size specified in options. */
198
        return is_write ? -ENOSPC : -EINVAL;
199
    }
200

201
    if (*offset > INT64_MAX - s->offset) {
202
        return -EINVAL;
203
    }
204
    *offset += s->offset;
205

206
    return 0;
207
}
208

209
static int coroutine_fn GRAPH_RDLOCK
210
raw_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
211
              QEMUIOVector *qiov, BdrvRequestFlags flags)
212
{
213
    int ret;
214

215
    ret = raw_adjust_offset(bs, &offset, bytes, false);
216
    if (ret) {
217
        return ret;
218
    }
219

220
    BLKDBG_CO_EVENT(bs->file, BLKDBG_READ_AIO);
221
    return bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
222
}
223

224
static int coroutine_fn GRAPH_RDLOCK
225
raw_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
226
               QEMUIOVector *qiov, BdrvRequestFlags flags)
227
{
228
    void *buf = NULL;
229
    BlockDriver *drv;
230
    QEMUIOVector local_qiov;
231
    int ret;
232

233
    if (bs->probed && offset < BLOCK_PROBE_BUF_SIZE && bytes) {
234
        /* Handling partial writes would be a pain - so we just
235
         * require that guests have 512-byte request alignment if
236
         * probing occurred */
237
        QEMU_BUILD_BUG_ON(BLOCK_PROBE_BUF_SIZE != 512);
238
        QEMU_BUILD_BUG_ON(BDRV_SECTOR_SIZE != 512);
239
        assert(offset == 0 && bytes >= BLOCK_PROBE_BUF_SIZE);
240

241
        buf = qemu_try_blockalign(bs->file->bs, 512);
242
        if (!buf) {
243
            ret = -ENOMEM;
244
            goto fail;
245
        }
246

247
        ret = qemu_iovec_to_buf(qiov, 0, buf, 512);
248
        if (ret != 512) {
249
            ret = -EINVAL;
250
            goto fail;
251
        }
252

253
        drv = bdrv_probe_all(buf, 512, NULL);
254
        if (drv != bs->drv) {
255
            ret = -EPERM;
256
            goto fail;
257
        }
258

259
        /* Use the checked buffer, a malicious guest might be overwriting its
260
         * original buffer in the background. */
261
        qemu_iovec_init(&local_qiov, qiov->niov + 1);
262
        qemu_iovec_add(&local_qiov, buf, 512);
263
        qemu_iovec_concat(&local_qiov, qiov, 512, qiov->size - 512);
264
        qiov = &local_qiov;
265

266
        flags &= ~BDRV_REQ_REGISTERED_BUF;
267
    }
268

269
    ret = raw_adjust_offset(bs, &offset, bytes, true);
270
    if (ret) {
271
        goto fail;
272
    }
273

274
    BLKDBG_CO_EVENT(bs->file, BLKDBG_WRITE_AIO);
275
    ret = bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);
276

277
fail:
278
    if (qiov == &local_qiov) {
279
        qemu_iovec_destroy(&local_qiov);
280
    }
281
    qemu_vfree(buf);
282
    return ret;
283
}
284

285
static int coroutine_fn GRAPH_RDLOCK
286
raw_co_block_status(BlockDriverState *bs, bool want_zero, int64_t offset,
287
                    int64_t bytes, int64_t *pnum, int64_t *map,
288
                    BlockDriverState **file)
289
{
290
    BDRVRawState *s = bs->opaque;
291
    *pnum = bytes;
292
    *file = bs->file->bs;
293
    *map = offset + s->offset;
294
    return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID;
295
}
296

297
static int coroutine_fn GRAPH_RDLOCK
298
raw_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
299
                     BdrvRequestFlags flags)
300
{
301
    int ret;
302

303
    ret = raw_adjust_offset(bs, &offset, bytes, true);
304
    if (ret) {
305
        return ret;
306
    }
307
    return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
308
}
309

310
static int coroutine_fn GRAPH_RDLOCK
311
raw_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
312
{
313
    int ret;
314

315
    ret = raw_adjust_offset(bs, &offset, bytes, true);
316
    if (ret) {
317
        return ret;
318
    }
319
    return bdrv_co_pdiscard(bs->file, offset, bytes);
320
}
321

322
static int coroutine_fn GRAPH_RDLOCK
323
raw_co_zone_report(BlockDriverState *bs, int64_t offset,
324
                   unsigned int *nr_zones,
325
                   BlockZoneDescriptor *zones)
326
{
327
    return bdrv_co_zone_report(bs->file->bs, offset, nr_zones, zones);
328
}
329

330
static int coroutine_fn GRAPH_RDLOCK
331
raw_co_zone_mgmt(BlockDriverState *bs, BlockZoneOp op,
332
                 int64_t offset, int64_t len)
333
{
334
    return bdrv_co_zone_mgmt(bs->file->bs, op, offset, len);
335
}
336

337
static int coroutine_fn GRAPH_RDLOCK
338
raw_co_zone_append(BlockDriverState *bs,int64_t *offset, QEMUIOVector *qiov,
339
                   BdrvRequestFlags flags)
340
{
341
    return bdrv_co_zone_append(bs->file->bs, offset, qiov, flags);
342
}
343

344
static int64_t coroutine_fn GRAPH_RDLOCK
345
raw_co_getlength(BlockDriverState *bs)
346
{
347
    int64_t len;
348
    BDRVRawState *s = bs->opaque;
349

350
    /* Update size. It should not change unless the file was externally
351
     * modified. */
352
    len = bdrv_co_getlength(bs->file->bs);
353
    if (len < 0) {
354
        return len;
355
    }
356

357
    if (len < s->offset) {
358
        s->size = 0;
359
    } else {
360
        if (s->has_size) {
361
            /* Try to honour the size */
362
            s->size = MIN(s->size, len - s->offset);
363
        } else {
364
            s->size = len - s->offset;
365
        }
366
    }
367

368
    return s->size;
369
}
370

371
static BlockMeasureInfo *raw_measure(QemuOpts *opts, BlockDriverState *in_bs,
372
                                     Error **errp)
373
{
374
    BlockMeasureInfo *info;
375
    int64_t required;
376

377
    if (in_bs) {
378
        required = bdrv_getlength(in_bs);
379
        if (required < 0) {
380
            error_setg_errno(errp, -required, "Unable to get image size");
381
            return NULL;
382
        }
383
    } else {
384
        required = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
385
                            BDRV_SECTOR_SIZE);
386
    }
387

388
    info = g_new0(BlockMeasureInfo, 1);
389
    info->required = required;
390

391
    /* Unallocated sectors count towards the file size in raw images */
392
    info->fully_allocated = info->required;
393
    return info;
394
}
395

396
static int coroutine_fn GRAPH_RDLOCK
397
raw_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
398
{
399
    return bdrv_co_get_info(bs->file->bs, bdi);
400
}
401

402
static void GRAPH_RDLOCK raw_refresh_limits(BlockDriverState *bs, Error **errp)
403
{
404
    bs->bl.has_variable_length = bs->file->bs->bl.has_variable_length;
405

406
    if (bs->probed) {
407
        /* To make it easier to protect the first sector, any probed
408
         * image is restricted to read-modify-write on sub-sector
409
         * operations. */
410
        bs->bl.request_alignment = BDRV_SECTOR_SIZE;
411
    }
412
}
413

414
static int coroutine_fn GRAPH_RDLOCK
415
raw_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
416
                PreallocMode prealloc, BdrvRequestFlags flags, Error **errp)
417
{
418
    BDRVRawState *s = bs->opaque;
419

420
    if (s->has_size) {
421
        error_setg(errp, "Cannot resize fixed-size raw disks");
422
        return -ENOTSUP;
423
    }
424

425
    if (INT64_MAX - offset < s->offset) {
426
        error_setg(errp, "Disk size too large for the chosen offset");
427
        return -EINVAL;
428
    }
429

430
    s->size = offset;
431
    offset += s->offset;
432
    return bdrv_co_truncate(bs->file, offset, exact, prealloc, flags, errp);
433
}
434

435
static void coroutine_fn GRAPH_RDLOCK
436
raw_co_eject(BlockDriverState *bs, bool eject_flag)
437
{
438
    bdrv_co_eject(bs->file->bs, eject_flag);
439
}
440

441
static void coroutine_fn GRAPH_RDLOCK
442
raw_co_lock_medium(BlockDriverState *bs, bool locked)
443
{
444
    bdrv_co_lock_medium(bs->file->bs, locked);
445
}
446

447
static int coroutine_fn GRAPH_RDLOCK
448
raw_co_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
449
{
450
    BDRVRawState *s = bs->opaque;
451
    if (s->offset || s->has_size) {
452
        return -ENOTSUP;
453
    }
454
    return bdrv_co_ioctl(bs->file->bs, req, buf);
455
}
456

457
static int GRAPH_RDLOCK raw_has_zero_init(BlockDriverState *bs)
458
{
459
    return bdrv_has_zero_init(bs->file->bs);
460
}
461

462
static int coroutine_fn GRAPH_UNLOCKED
463
raw_co_create_opts(BlockDriver *drv, const char *filename,
464
                   QemuOpts *opts, Error **errp)
465
{
466
    return bdrv_co_create_file(filename, opts, errp);
467
}
468

469
static int raw_open(BlockDriverState *bs, QDict *options, int flags,
470
                    Error **errp)
471
{
472
    BDRVRawState *s = bs->opaque;
473
    bool has_size;
474
    uint64_t offset, size;
475
    BdrvChildRole file_role;
476
    int ret;
477

478
    GLOBAL_STATE_CODE();
479

480
    ret = raw_read_options(options, &offset, &has_size, &size, errp);
481
    if (ret < 0) {
482
        return ret;
483
    }
484

485
    /*
486
     * Without offset and a size limit, this driver behaves very much
487
     * like a filter.  With any such limit, it does not.
488
     */
489
    if (offset || has_size) {
490
        file_role = BDRV_CHILD_DATA | BDRV_CHILD_PRIMARY;
491
    } else {
492
        file_role = BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY;
493
    }
494

495
    bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
496
                    file_role, false, errp);
497

498
    GRAPH_RDLOCK_GUARD_MAINLOOP();
499
    if (!bs->file) {
500
        return -EINVAL;
501
    }
502

503
    bs->sg = bdrv_is_sg(bs->file->bs);
504
    bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED |
505
        (BDRV_REQ_FUA & bs->file->bs->supported_write_flags);
506
    bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
507
        ((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
508
            bs->file->bs->supported_zero_flags);
509
    bs->supported_truncate_flags = bs->file->bs->supported_truncate_flags &
510
                                   BDRV_REQ_ZERO_WRITE;
511

512
    if (bs->probed && !bdrv_is_read_only(bs)) {
513
        bdrv_refresh_filename(bs->file->bs);
514
        fprintf(stderr,
515
                "WARNING: Image format was not specified for '%s' and probing "
516
                "guessed raw.\n"
517
                "         Automatically detecting the format is dangerous for "
518
                "raw images, write operations on block 0 will be restricted.\n"
519
                "         Specify the 'raw' format explicitly to remove the "
520
                "restrictions.\n",
521
                bs->file->bs->filename);
522
    }
523

524
    ret = raw_apply_options(bs, s, offset, has_size, size, errp);
525
    if (ret < 0) {
526
        return ret;
527
    }
528

529
    if (bdrv_is_sg(bs) && (s->offset || s->has_size)) {
530
        error_setg(errp, "Cannot use offset/size with SCSI generic devices");
531
        return -EINVAL;
532
    }
533

534
    return 0;
535
}
536

537
static int raw_probe(const uint8_t *buf, int buf_size, const char *filename)
538
{
539
    /* smallest possible positive score so that raw is used if and only if no
540
     * other block driver works
541
     */
542
    return 1;
543
}
544

545
static int GRAPH_RDLOCK
546
raw_probe_blocksizes(BlockDriverState *bs, BlockSizes *bsz)
547
{
548
    BDRVRawState *s = bs->opaque;
549
    int ret;
550

551
    ret = bdrv_probe_blocksizes(bs->file->bs, bsz);
552
    if (ret < 0) {
553
        return ret;
554
    }
555

556
    if (!QEMU_IS_ALIGNED(s->offset, MAX(bsz->log, bsz->phys))) {
557
        return -ENOTSUP;
558
    }
559

560
    return 0;
561
}
562

563
static int GRAPH_RDLOCK
564
raw_probe_geometry(BlockDriverState *bs, HDGeometry *geo)
565
{
566
    BDRVRawState *s = bs->opaque;
567
    if (s->offset || s->has_size) {
568
        return -ENOTSUP;
569
    }
570
    return bdrv_probe_geometry(bs->file->bs, geo);
571
}
572

573
static int coroutine_fn GRAPH_RDLOCK
574
raw_co_copy_range_from(BlockDriverState *bs,
575
                       BdrvChild *src, int64_t src_offset,
576
                       BdrvChild *dst, int64_t dst_offset,
577
                       int64_t bytes, BdrvRequestFlags read_flags,
578
                       BdrvRequestFlags write_flags)
579
{
580
    int ret;
581

582
    ret = raw_adjust_offset(bs, &src_offset, bytes, false);
583
    if (ret) {
584
        return ret;
585
    }
586
    return bdrv_co_copy_range_from(bs->file, src_offset, dst, dst_offset,
587
                                   bytes, read_flags, write_flags);
588
}
589

590
static int coroutine_fn GRAPH_RDLOCK
591
raw_co_copy_range_to(BlockDriverState *bs,
592
                     BdrvChild *src, int64_t src_offset,
593
                     BdrvChild *dst, int64_t dst_offset,
594
                     int64_t bytes, BdrvRequestFlags read_flags,
595
                     BdrvRequestFlags write_flags)
596
{
597
    int ret;
598

599
    ret = raw_adjust_offset(bs, &dst_offset, bytes, true);
600
    if (ret) {
601
        return ret;
602
    }
603
    return bdrv_co_copy_range_to(src, src_offset, bs->file, dst_offset, bytes,
604
                                 read_flags, write_flags);
605
}
606

607
static const char *const raw_strong_runtime_opts[] = {
608
    "offset",
609
    "size",
610

611
    NULL
612
};
613

614
static void GRAPH_RDLOCK raw_cancel_in_flight(BlockDriverState *bs)
615
{
616
    bdrv_cancel_in_flight(bs->file->bs);
617
}
618

619
static void raw_child_perm(BlockDriverState *bs, BdrvChild *c,
620
                           BdrvChildRole role,
621
                           BlockReopenQueue *reopen_queue,
622
                           uint64_t parent_perm, uint64_t parent_shared,
623
                           uint64_t *nperm, uint64_t *nshared)
624
{
625
    bdrv_default_perms(bs, c, role, reopen_queue, parent_perm,
626
                       parent_shared, nperm, nshared);
627

628
    /*
629
     * bdrv_default_perms() may add WRITE and/or RESIZE (see comment in
630
     * bdrv_default_perms_for_storage() for an explanation) but we only need
631
     * them if they are in parent_perm. Drop WRITE and RESIZE whenever possible
632
     * to avoid permission conflicts.
633
     */
634
    *nperm &= ~(BLK_PERM_WRITE | BLK_PERM_RESIZE);
635
    *nperm |= parent_perm & (BLK_PERM_WRITE | BLK_PERM_RESIZE);
636
}
637

638
BlockDriver bdrv_raw = {
639
    .format_name          = "raw",
640
    .instance_size        = sizeof(BDRVRawState),
641
    .supports_zoned_children = true,
642
    .bdrv_probe           = &raw_probe,
643
    .bdrv_reopen_prepare  = &raw_reopen_prepare,
644
    .bdrv_reopen_commit   = &raw_reopen_commit,
645
    .bdrv_reopen_abort    = &raw_reopen_abort,
646
    .bdrv_open            = &raw_open,
647
    .bdrv_child_perm      = raw_child_perm,
648
    .bdrv_co_create_opts  = &raw_co_create_opts,
649
    .bdrv_co_preadv       = &raw_co_preadv,
650
    .bdrv_co_pwritev      = &raw_co_pwritev,
651
    .bdrv_co_pwrite_zeroes = &raw_co_pwrite_zeroes,
652
    .bdrv_co_pdiscard     = &raw_co_pdiscard,
653
    .bdrv_co_zone_report  = &raw_co_zone_report,
654
    .bdrv_co_zone_mgmt  = &raw_co_zone_mgmt,
655
    .bdrv_co_zone_append = &raw_co_zone_append,
656
    .bdrv_co_block_status = &raw_co_block_status,
657
    .bdrv_co_copy_range_from = &raw_co_copy_range_from,
658
    .bdrv_co_copy_range_to  = &raw_co_copy_range_to,
659
    .bdrv_co_truncate     = &raw_co_truncate,
660
    .bdrv_co_getlength    = &raw_co_getlength,
661
    .is_format            = true,
662
    .bdrv_measure         = &raw_measure,
663
    .bdrv_co_get_info     = &raw_co_get_info,
664
    .bdrv_refresh_limits  = &raw_refresh_limits,
665
    .bdrv_probe_blocksizes = &raw_probe_blocksizes,
666
    .bdrv_probe_geometry  = &raw_probe_geometry,
667
    .bdrv_co_eject        = &raw_co_eject,
668
    .bdrv_co_lock_medium  = &raw_co_lock_medium,
669
    .bdrv_co_ioctl        = &raw_co_ioctl,
670
    .create_opts          = &raw_create_opts,
671
    .bdrv_has_zero_init   = &raw_has_zero_init,
672
    .strong_runtime_opts  = raw_strong_runtime_opts,
673
    .mutable_opts         = mutable_opts,
674
    .bdrv_cancel_in_flight = raw_cancel_in_flight,
675
};
676

677
static void bdrv_raw_init(void)
678
{
679
    bdrv_register(&bdrv_raw);
680
}
681

682
block_init(bdrv_raw_init);
683

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.