blkdebug.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107
  1. /*
  2. * Block protocol for I/O error injection
  3. *
  4. * Copyright (C) 2016-2017 Red Hat, Inc.
  5. * Copyright (c) 2010 Kevin Wolf <kwolf@redhat.com>
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a copy
  8. * of this software and associated documentation files (the "Software"), to deal
  9. * in the Software without restriction, including without limitation the rights
  10. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. * copies of the Software, and to permit persons to whom the Software is
  12. * furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included in
  15. * all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  20. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23. * THE SOFTWARE.
  24. */
  25. #include "qemu/osdep.h"
  26. #include "qapi/error.h"
  27. #include "qemu/cutils.h"
  28. #include "qemu/config-file.h"
  29. #include "block/block-io.h"
  30. #include "block/block_int.h"
  31. #include "block/qdict.h"
  32. #include "qemu/module.h"
  33. #include "qemu/option.h"
  34. #include "qapi/qapi-visit-block-core.h"
  35. #include "qobject/qdict.h"
  36. #include "qobject/qlist.h"
  37. #include "qobject/qstring.h"
  38. #include "qapi/qobject-input-visitor.h"
  39. #include "system/qtest.h"
  40. /* All APIs are thread-safe */
  41. typedef struct BDRVBlkdebugState {
  42. /* IN: initialized in blkdebug_open() and never changed */
  43. uint64_t align;
  44. uint64_t max_transfer;
  45. uint64_t opt_write_zero;
  46. uint64_t max_write_zero;
  47. uint64_t opt_discard;
  48. uint64_t max_discard;
  49. char *config_file; /* For blkdebug_refresh_filename() */
  50. /* initialized in blkdebug_parse_perms() */
  51. uint64_t take_child_perms;
  52. uint64_t unshare_child_perms;
  53. /* State. Protected by lock */
  54. int state;
  55. QLIST_HEAD(, BlkdebugRule) rules[BLKDBG__MAX];
  56. QSIMPLEQ_HEAD(, BlkdebugRule) active_rules;
  57. QLIST_HEAD(, BlkdebugSuspendedReq) suspended_reqs;
  58. QemuMutex lock;
  59. } BDRVBlkdebugState;
  60. typedef struct BlkdebugAIOCB {
  61. BlockAIOCB common;
  62. int ret;
  63. } BlkdebugAIOCB;
  64. typedef struct BlkdebugSuspendedReq {
  65. /* IN: initialized in suspend_request() */
  66. Coroutine *co;
  67. char *tag;
  68. /* List entry protected BDRVBlkdebugState's lock */
  69. QLIST_ENTRY(BlkdebugSuspendedReq) next;
  70. } BlkdebugSuspendedReq;
  71. enum {
  72. ACTION_INJECT_ERROR,
  73. ACTION_SET_STATE,
  74. ACTION_SUSPEND,
  75. ACTION__MAX,
  76. };
  77. typedef struct BlkdebugRule {
  78. /* IN: initialized in add_rule() or blkdebug_debug_breakpoint() */
  79. BlkdebugEvent event;
  80. int action;
  81. int state;
  82. union {
  83. struct {
  84. uint64_t iotype_mask;
  85. int error;
  86. int immediately;
  87. int once;
  88. int64_t offset;
  89. } inject;
  90. struct {
  91. int new_state;
  92. } set_state;
  93. struct {
  94. char *tag;
  95. } suspend;
  96. } options;
  97. /* List entries protected BDRVBlkdebugState's lock */
  98. QLIST_ENTRY(BlkdebugRule) next;
  99. QSIMPLEQ_ENTRY(BlkdebugRule) active_next;
  100. } BlkdebugRule;
  101. QEMU_BUILD_BUG_MSG(BLKDEBUG_IO_TYPE__MAX > 64,
  102. "BlkdebugIOType mask does not fit into an uint64_t");
  103. static QemuOptsList inject_error_opts = {
  104. .name = "inject-error",
  105. .head = QTAILQ_HEAD_INITIALIZER(inject_error_opts.head),
  106. .desc = {
  107. {
  108. .name = "event",
  109. .type = QEMU_OPT_STRING,
  110. },
  111. {
  112. .name = "state",
  113. .type = QEMU_OPT_NUMBER,
  114. },
  115. {
  116. .name = "iotype",
  117. .type = QEMU_OPT_STRING,
  118. },
  119. {
  120. .name = "errno",
  121. .type = QEMU_OPT_NUMBER,
  122. },
  123. {
  124. .name = "sector",
  125. .type = QEMU_OPT_NUMBER,
  126. },
  127. {
  128. .name = "once",
  129. .type = QEMU_OPT_BOOL,
  130. },
  131. {
  132. .name = "immediately",
  133. .type = QEMU_OPT_BOOL,
  134. },
  135. { /* end of list */ }
  136. },
  137. };
  138. static QemuOptsList set_state_opts = {
  139. .name = "set-state",
  140. .head = QTAILQ_HEAD_INITIALIZER(set_state_opts.head),
  141. .desc = {
  142. {
  143. .name = "event",
  144. .type = QEMU_OPT_STRING,
  145. },
  146. {
  147. .name = "state",
  148. .type = QEMU_OPT_NUMBER,
  149. },
  150. {
  151. .name = "new_state",
  152. .type = QEMU_OPT_NUMBER,
  153. },
  154. { /* end of list */ }
  155. },
  156. };
  157. static QemuOptsList *config_groups[] = {
  158. &inject_error_opts,
  159. &set_state_opts,
  160. NULL
  161. };
  162. struct add_rule_data {
  163. BDRVBlkdebugState *s;
  164. int action;
  165. };
  166. static int add_rule(void *opaque, QemuOpts *opts, Error **errp)
  167. {
  168. struct add_rule_data *d = opaque;
  169. BDRVBlkdebugState *s = d->s;
  170. const char *event_name;
  171. int event;
  172. struct BlkdebugRule *rule;
  173. int64_t sector;
  174. BlkdebugIOType iotype;
  175. Error *local_error = NULL;
  176. /* Find the right event for the rule */
  177. event_name = qemu_opt_get(opts, "event");
  178. if (!event_name) {
  179. error_setg(errp, "Missing event name for rule");
  180. return -1;
  181. }
  182. event = qapi_enum_parse(&BlkdebugEvent_lookup, event_name, -1, errp);
  183. if (event < 0) {
  184. return -1;
  185. }
  186. /* Set attributes common for all actions */
  187. rule = g_malloc0(sizeof(*rule));
  188. *rule = (struct BlkdebugRule) {
  189. .event = event,
  190. .action = d->action,
  191. .state = qemu_opt_get_number(opts, "state", 0),
  192. };
  193. /* Parse action-specific options */
  194. switch (d->action) {
  195. case ACTION_INJECT_ERROR:
  196. rule->options.inject.error = qemu_opt_get_number(opts, "errno", EIO);
  197. rule->options.inject.once = qemu_opt_get_bool(opts, "once", 0);
  198. rule->options.inject.immediately =
  199. qemu_opt_get_bool(opts, "immediately", 0);
  200. sector = qemu_opt_get_number(opts, "sector", -1);
  201. rule->options.inject.offset =
  202. sector == -1 ? -1 : sector * BDRV_SECTOR_SIZE;
  203. iotype = qapi_enum_parse(&BlkdebugIOType_lookup,
  204. qemu_opt_get(opts, "iotype"),
  205. BLKDEBUG_IO_TYPE__MAX, &local_error);
  206. if (local_error) {
  207. error_propagate(errp, local_error);
  208. g_free(rule);
  209. return -1;
  210. }
  211. if (iotype != BLKDEBUG_IO_TYPE__MAX) {
  212. rule->options.inject.iotype_mask = (1ull << iotype);
  213. } else {
  214. /* Apply the default */
  215. rule->options.inject.iotype_mask =
  216. (1ull << BLKDEBUG_IO_TYPE_READ)
  217. | (1ull << BLKDEBUG_IO_TYPE_WRITE)
  218. | (1ull << BLKDEBUG_IO_TYPE_WRITE_ZEROES)
  219. | (1ull << BLKDEBUG_IO_TYPE_DISCARD)
  220. | (1ull << BLKDEBUG_IO_TYPE_FLUSH);
  221. }
  222. break;
  223. case ACTION_SET_STATE:
  224. rule->options.set_state.new_state =
  225. qemu_opt_get_number(opts, "new_state", 0);
  226. break;
  227. case ACTION_SUSPEND:
  228. rule->options.suspend.tag =
  229. g_strdup(qemu_opt_get(opts, "tag"));
  230. break;
  231. };
  232. /* Add the rule */
  233. qemu_mutex_lock(&s->lock);
  234. QLIST_INSERT_HEAD(&s->rules[event], rule, next);
  235. qemu_mutex_unlock(&s->lock);
  236. return 0;
  237. }
  238. /* Called with lock held or from .bdrv_close */
  239. static void remove_rule(BlkdebugRule *rule)
  240. {
  241. switch (rule->action) {
  242. case ACTION_INJECT_ERROR:
  243. case ACTION_SET_STATE:
  244. break;
  245. case ACTION_SUSPEND:
  246. g_free(rule->options.suspend.tag);
  247. break;
  248. }
  249. QLIST_REMOVE(rule, next);
  250. g_free(rule);
  251. }
  252. static int read_config(BDRVBlkdebugState *s, const char *filename,
  253. QDict *options, Error **errp)
  254. {
  255. FILE *f = NULL;
  256. int ret;
  257. struct add_rule_data d;
  258. Error *local_err = NULL;
  259. if (filename) {
  260. f = fopen(filename, "r");
  261. if (f == NULL) {
  262. error_setg_errno(errp, errno, "Could not read blkdebug config file");
  263. return -errno;
  264. }
  265. ret = qemu_config_parse(f, config_groups, filename, errp);
  266. if (ret < 0) {
  267. goto fail;
  268. }
  269. }
  270. if (!qemu_config_parse_qdict(options, config_groups, errp)) {
  271. ret = -EINVAL;
  272. goto fail;
  273. }
  274. d.s = s;
  275. d.action = ACTION_INJECT_ERROR;
  276. qemu_opts_foreach(&inject_error_opts, add_rule, &d, &local_err);
  277. if (local_err) {
  278. error_propagate(errp, local_err);
  279. ret = -EINVAL;
  280. goto fail;
  281. }
  282. d.action = ACTION_SET_STATE;
  283. qemu_opts_foreach(&set_state_opts, add_rule, &d, &local_err);
  284. if (local_err) {
  285. error_propagate(errp, local_err);
  286. ret = -EINVAL;
  287. goto fail;
  288. }
  289. ret = 0;
  290. fail:
  291. qemu_opts_reset(&inject_error_opts);
  292. qemu_opts_reset(&set_state_opts);
  293. if (f) {
  294. fclose(f);
  295. }
  296. return ret;
  297. }
  298. /* Valid blkdebug filenames look like blkdebug:path/to/config:path/to/image */
  299. static void blkdebug_parse_filename(const char *filename, QDict *options,
  300. Error **errp)
  301. {
  302. const char *c;
  303. /* Parse the blkdebug: prefix */
  304. if (!strstart(filename, "blkdebug:", &filename)) {
  305. /* There was no prefix; therefore, all options have to be already
  306. present in the QDict (except for the filename) */
  307. qdict_put_str(options, "x-image", filename);
  308. return;
  309. }
  310. /* Parse config file path */
  311. c = strchr(filename, ':');
  312. if (c == NULL) {
  313. error_setg(errp, "blkdebug requires both config file and image path");
  314. return;
  315. }
  316. if (c != filename) {
  317. QString *config_path;
  318. config_path = qstring_from_substr(filename, 0, c - filename);
  319. qdict_put(options, "config", config_path);
  320. }
  321. /* TODO Allow multi-level nesting and set file.filename here */
  322. filename = c + 1;
  323. qdict_put_str(options, "x-image", filename);
  324. }
  325. static int blkdebug_parse_perm_list(uint64_t *dest, QDict *options,
  326. const char *prefix, Error **errp)
  327. {
  328. int ret = 0;
  329. QDict *subqdict = NULL;
  330. QObject *crumpled_subqdict = NULL;
  331. Visitor *v = NULL;
  332. BlockPermissionList *perm_list = NULL, *element;
  333. *dest = 0;
  334. qdict_extract_subqdict(options, &subqdict, prefix);
  335. if (!qdict_size(subqdict)) {
  336. goto out;
  337. }
  338. crumpled_subqdict = qdict_crumple(subqdict, errp);
  339. if (!crumpled_subqdict) {
  340. ret = -EINVAL;
  341. goto out;
  342. }
  343. v = qobject_input_visitor_new(crumpled_subqdict);
  344. if (!visit_type_BlockPermissionList(v, NULL, &perm_list, errp)) {
  345. ret = -EINVAL;
  346. goto out;
  347. }
  348. for (element = perm_list; element; element = element->next) {
  349. *dest |= bdrv_qapi_perm_to_blk_perm(element->value);
  350. }
  351. out:
  352. qapi_free_BlockPermissionList(perm_list);
  353. visit_free(v);
  354. qobject_unref(subqdict);
  355. qobject_unref(crumpled_subqdict);
  356. return ret;
  357. }
  358. static int blkdebug_parse_perms(BDRVBlkdebugState *s, QDict *options,
  359. Error **errp)
  360. {
  361. int ret;
  362. ret = blkdebug_parse_perm_list(&s->take_child_perms, options,
  363. "take-child-perms.", errp);
  364. if (ret < 0) {
  365. return ret;
  366. }
  367. ret = blkdebug_parse_perm_list(&s->unshare_child_perms, options,
  368. "unshare-child-perms.", errp);
  369. if (ret < 0) {
  370. return ret;
  371. }
  372. return 0;
  373. }
  374. static QemuOptsList runtime_opts = {
  375. .name = "blkdebug",
  376. .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
  377. .desc = {
  378. {
  379. .name = "config",
  380. .type = QEMU_OPT_STRING,
  381. .help = "Path to the configuration file",
  382. },
  383. {
  384. .name = "x-image",
  385. .type = QEMU_OPT_STRING,
  386. .help = "[internal use only, will be removed]",
  387. },
  388. {
  389. .name = "align",
  390. .type = QEMU_OPT_SIZE,
  391. .help = "Required alignment in bytes",
  392. },
  393. {
  394. .name = "max-transfer",
  395. .type = QEMU_OPT_SIZE,
  396. .help = "Maximum transfer size in bytes",
  397. },
  398. {
  399. .name = "opt-write-zero",
  400. .type = QEMU_OPT_SIZE,
  401. .help = "Optimum write zero alignment in bytes",
  402. },
  403. {
  404. .name = "max-write-zero",
  405. .type = QEMU_OPT_SIZE,
  406. .help = "Maximum write zero size in bytes",
  407. },
  408. {
  409. .name = "opt-discard",
  410. .type = QEMU_OPT_SIZE,
  411. .help = "Optimum discard alignment in bytes",
  412. },
  413. {
  414. .name = "max-discard",
  415. .type = QEMU_OPT_SIZE,
  416. .help = "Maximum discard size in bytes",
  417. },
  418. { /* end of list */ }
  419. },
  420. };
  421. static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags,
  422. Error **errp)
  423. {
  424. BDRVBlkdebugState *s = bs->opaque;
  425. QemuOpts *opts;
  426. int ret;
  427. uint64_t align;
  428. qemu_mutex_init(&s->lock);
  429. opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
  430. if (!qemu_opts_absorb_qdict(opts, options, errp)) {
  431. ret = -EINVAL;
  432. goto out;
  433. }
  434. /* Read rules from config file or command line options */
  435. s->config_file = g_strdup(qemu_opt_get(opts, "config"));
  436. ret = read_config(s, s->config_file, options, errp);
  437. if (ret) {
  438. goto out;
  439. }
  440. /* Set initial state */
  441. s->state = 1;
  442. /* Parse permissions modifiers before opening the image file */
  443. ret = blkdebug_parse_perms(s, options, errp);
  444. if (ret < 0) {
  445. goto out;
  446. }
  447. /* Open the image file */
  448. ret = bdrv_open_file_child(qemu_opt_get(opts, "x-image"), options, "image",
  449. bs, errp);
  450. if (ret < 0) {
  451. goto out;
  452. }
  453. bdrv_graph_rdlock_main_loop();
  454. bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED |
  455. (BDRV_REQ_FUA & bs->file->bs->supported_write_flags);
  456. bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
  457. ((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
  458. bs->file->bs->supported_zero_flags);
  459. ret = -EINVAL;
  460. /* Set alignment overrides */
  461. s->align = qemu_opt_get_size(opts, "align", 0);
  462. if (s->align && (s->align >= INT_MAX || !is_power_of_2(s->align))) {
  463. error_setg(errp, "Cannot meet constraints with align %" PRIu64,
  464. s->align);
  465. goto out_rdlock;
  466. }
  467. align = MAX(s->align, bs->file->bs->bl.request_alignment);
  468. s->max_transfer = qemu_opt_get_size(opts, "max-transfer", 0);
  469. if (s->max_transfer &&
  470. (s->max_transfer >= INT_MAX ||
  471. !QEMU_IS_ALIGNED(s->max_transfer, align))) {
  472. error_setg(errp, "Cannot meet constraints with max-transfer %" PRIu64,
  473. s->max_transfer);
  474. goto out_rdlock;
  475. }
  476. s->opt_write_zero = qemu_opt_get_size(opts, "opt-write-zero", 0);
  477. if (s->opt_write_zero &&
  478. (s->opt_write_zero >= INT_MAX ||
  479. !QEMU_IS_ALIGNED(s->opt_write_zero, align))) {
  480. error_setg(errp, "Cannot meet constraints with opt-write-zero %" PRIu64,
  481. s->opt_write_zero);
  482. goto out_rdlock;
  483. }
  484. s->max_write_zero = qemu_opt_get_size(opts, "max-write-zero", 0);
  485. if (s->max_write_zero &&
  486. (s->max_write_zero >= INT_MAX ||
  487. !QEMU_IS_ALIGNED(s->max_write_zero,
  488. MAX(s->opt_write_zero, align)))) {
  489. error_setg(errp, "Cannot meet constraints with max-write-zero %" PRIu64,
  490. s->max_write_zero);
  491. goto out_rdlock;
  492. }
  493. s->opt_discard = qemu_opt_get_size(opts, "opt-discard", 0);
  494. if (s->opt_discard &&
  495. (s->opt_discard >= INT_MAX ||
  496. !QEMU_IS_ALIGNED(s->opt_discard, align))) {
  497. error_setg(errp, "Cannot meet constraints with opt-discard %" PRIu64,
  498. s->opt_discard);
  499. goto out_rdlock;
  500. }
  501. s->max_discard = qemu_opt_get_size(opts, "max-discard", 0);
  502. if (s->max_discard &&
  503. (s->max_discard >= INT_MAX ||
  504. !QEMU_IS_ALIGNED(s->max_discard,
  505. MAX(s->opt_discard, align)))) {
  506. error_setg(errp, "Cannot meet constraints with max-discard %" PRIu64,
  507. s->max_discard);
  508. goto out_rdlock;
  509. }
  510. bdrv_debug_event(bs, BLKDBG_NONE);
  511. ret = 0;
  512. out_rdlock:
  513. bdrv_graph_rdunlock_main_loop();
  514. out:
  515. if (ret < 0) {
  516. qemu_mutex_destroy(&s->lock);
  517. g_free(s->config_file);
  518. }
  519. qemu_opts_del(opts);
  520. return ret;
  521. }
  522. static int coroutine_fn rule_check(BlockDriverState *bs, uint64_t offset,
  523. uint64_t bytes, BlkdebugIOType iotype)
  524. {
  525. BDRVBlkdebugState *s = bs->opaque;
  526. BlkdebugRule *rule = NULL;
  527. int error;
  528. bool immediately;
  529. qemu_mutex_lock(&s->lock);
  530. QSIMPLEQ_FOREACH(rule, &s->active_rules, active_next) {
  531. uint64_t inject_offset = rule->options.inject.offset;
  532. if ((inject_offset == -1 ||
  533. (bytes && inject_offset >= offset &&
  534. inject_offset < offset + bytes)) &&
  535. (rule->options.inject.iotype_mask & (1ull << iotype)))
  536. {
  537. break;
  538. }
  539. }
  540. if (!rule || !rule->options.inject.error) {
  541. qemu_mutex_unlock(&s->lock);
  542. return 0;
  543. }
  544. immediately = rule->options.inject.immediately;
  545. error = rule->options.inject.error;
  546. if (rule->options.inject.once) {
  547. QSIMPLEQ_REMOVE(&s->active_rules, rule, BlkdebugRule, active_next);
  548. remove_rule(rule);
  549. }
  550. qemu_mutex_unlock(&s->lock);
  551. if (!immediately) {
  552. aio_co_schedule(qemu_get_current_aio_context(), qemu_coroutine_self());
  553. qemu_coroutine_yield();
  554. }
  555. return -error;
  556. }
  557. static int coroutine_fn GRAPH_RDLOCK
  558. blkdebug_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
  559. QEMUIOVector *qiov, BdrvRequestFlags flags)
  560. {
  561. int err;
  562. /* Sanity check block layer guarantees */
  563. assert(QEMU_IS_ALIGNED(offset, bs->bl.request_alignment));
  564. assert(QEMU_IS_ALIGNED(bytes, bs->bl.request_alignment));
  565. if (bs->bl.max_transfer) {
  566. assert(bytes <= bs->bl.max_transfer);
  567. }
  568. err = rule_check(bs, offset, bytes, BLKDEBUG_IO_TYPE_READ);
  569. if (err) {
  570. return err;
  571. }
  572. return bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
  573. }
  574. static int coroutine_fn GRAPH_RDLOCK
  575. blkdebug_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
  576. QEMUIOVector *qiov, BdrvRequestFlags flags)
  577. {
  578. int err;
  579. /* Sanity check block layer guarantees */
  580. assert(QEMU_IS_ALIGNED(offset, bs->bl.request_alignment));
  581. assert(QEMU_IS_ALIGNED(bytes, bs->bl.request_alignment));
  582. if (bs->bl.max_transfer) {
  583. assert(bytes <= bs->bl.max_transfer);
  584. }
  585. err = rule_check(bs, offset, bytes, BLKDEBUG_IO_TYPE_WRITE);
  586. if (err) {
  587. return err;
  588. }
  589. return bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);
  590. }
  591. static int GRAPH_RDLOCK coroutine_fn blkdebug_co_flush(BlockDriverState *bs)
  592. {
  593. int err = rule_check(bs, 0, 0, BLKDEBUG_IO_TYPE_FLUSH);
  594. if (err) {
  595. return err;
  596. }
  597. return bdrv_co_flush(bs->file->bs);
  598. }
  599. static int coroutine_fn GRAPH_RDLOCK
  600. blkdebug_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
  601. BdrvRequestFlags flags)
  602. {
  603. uint32_t align = MAX(bs->bl.request_alignment,
  604. bs->bl.pwrite_zeroes_alignment);
  605. int err;
  606. /* Only pass through requests that are larger than requested
  607. * preferred alignment (so that we test the fallback to writes on
  608. * unaligned portions), and check that the block layer never hands
  609. * us anything unaligned that crosses an alignment boundary. */
  610. if (bytes < align) {
  611. assert(QEMU_IS_ALIGNED(offset, align) ||
  612. QEMU_IS_ALIGNED(offset + bytes, align) ||
  613. DIV_ROUND_UP(offset, align) ==
  614. DIV_ROUND_UP(offset + bytes, align));
  615. return -ENOTSUP;
  616. }
  617. assert(QEMU_IS_ALIGNED(offset, align));
  618. assert(QEMU_IS_ALIGNED(bytes, align));
  619. if (bs->bl.max_pwrite_zeroes) {
  620. assert(bytes <= bs->bl.max_pwrite_zeroes);
  621. }
  622. err = rule_check(bs, offset, bytes, BLKDEBUG_IO_TYPE_WRITE_ZEROES);
  623. if (err) {
  624. return err;
  625. }
  626. return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
  627. }
  628. static int coroutine_fn GRAPH_RDLOCK
  629. blkdebug_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
  630. {
  631. uint32_t align = bs->bl.pdiscard_alignment;
  632. int err;
  633. /* Only pass through requests that are larger than requested
  634. * minimum alignment, and ensure that unaligned requests do not
  635. * cross optimum discard boundaries. */
  636. if (bytes < bs->bl.request_alignment) {
  637. assert(QEMU_IS_ALIGNED(offset, align) ||
  638. QEMU_IS_ALIGNED(offset + bytes, align) ||
  639. DIV_ROUND_UP(offset, align) ==
  640. DIV_ROUND_UP(offset + bytes, align));
  641. return -ENOTSUP;
  642. }
  643. assert(QEMU_IS_ALIGNED(offset, bs->bl.request_alignment));
  644. assert(QEMU_IS_ALIGNED(bytes, bs->bl.request_alignment));
  645. if (align && bytes >= align) {
  646. assert(QEMU_IS_ALIGNED(offset, align));
  647. assert(QEMU_IS_ALIGNED(bytes, align));
  648. }
  649. if (bs->bl.max_pdiscard) {
  650. assert(bytes <= bs->bl.max_pdiscard);
  651. }
  652. err = rule_check(bs, offset, bytes, BLKDEBUG_IO_TYPE_DISCARD);
  653. if (err) {
  654. return err;
  655. }
  656. return bdrv_co_pdiscard(bs->file, offset, bytes);
  657. }
  658. static int coroutine_fn GRAPH_RDLOCK
  659. blkdebug_co_block_status(BlockDriverState *bs, bool want_zero, int64_t offset,
  660. int64_t bytes, int64_t *pnum, int64_t *map,
  661. BlockDriverState **file)
  662. {
  663. int err;
  664. assert(QEMU_IS_ALIGNED(offset | bytes, bs->bl.request_alignment));
  665. err = rule_check(bs, offset, bytes, BLKDEBUG_IO_TYPE_BLOCK_STATUS);
  666. if (err) {
  667. return err;
  668. }
  669. assert(bs->file && bs->file->bs);
  670. *pnum = bytes;
  671. *map = offset;
  672. *file = bs->file->bs;
  673. return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID;
  674. }
  675. static void blkdebug_close(BlockDriverState *bs)
  676. {
  677. BDRVBlkdebugState *s = bs->opaque;
  678. BlkdebugRule *rule, *next;
  679. int i;
  680. for (i = 0; i < BLKDBG__MAX; i++) {
  681. QLIST_FOREACH_SAFE(rule, &s->rules[i], next, next) {
  682. remove_rule(rule);
  683. }
  684. }
  685. g_free(s->config_file);
  686. qemu_mutex_destroy(&s->lock);
  687. }
  688. /* Called with lock held. */
  689. static void suspend_request(BlockDriverState *bs, BlkdebugRule *rule)
  690. {
  691. BDRVBlkdebugState *s = bs->opaque;
  692. BlkdebugSuspendedReq *r;
  693. r = g_new(BlkdebugSuspendedReq, 1);
  694. r->co = qemu_coroutine_self();
  695. r->tag = g_strdup(rule->options.suspend.tag);
  696. remove_rule(rule);
  697. QLIST_INSERT_HEAD(&s->suspended_reqs, r, next);
  698. if (!qtest_enabled()) {
  699. printf("blkdebug: Suspended request '%s'\n", r->tag);
  700. }
  701. }
  702. /* Called with lock held. */
  703. static void process_rule(BlockDriverState *bs, struct BlkdebugRule *rule,
  704. int *action_count, int *new_state)
  705. {
  706. BDRVBlkdebugState *s = bs->opaque;
  707. /* Only process rules for the current state */
  708. if (rule->state && rule->state != s->state) {
  709. return;
  710. }
  711. /* Take the action */
  712. action_count[rule->action]++;
  713. switch (rule->action) {
  714. case ACTION_INJECT_ERROR:
  715. if (action_count[ACTION_INJECT_ERROR] == 1) {
  716. QSIMPLEQ_INIT(&s->active_rules);
  717. }
  718. QSIMPLEQ_INSERT_HEAD(&s->active_rules, rule, active_next);
  719. break;
  720. case ACTION_SET_STATE:
  721. *new_state = rule->options.set_state.new_state;
  722. break;
  723. case ACTION_SUSPEND:
  724. suspend_request(bs, rule);
  725. break;
  726. }
  727. }
  728. static void coroutine_fn
  729. blkdebug_co_debug_event(BlockDriverState *bs, BlkdebugEvent event)
  730. {
  731. BDRVBlkdebugState *s = bs->opaque;
  732. struct BlkdebugRule *rule, *next;
  733. int new_state;
  734. int actions_count[ACTION__MAX] = { 0 };
  735. assert((int)event >= 0 && event < BLKDBG__MAX);
  736. WITH_QEMU_LOCK_GUARD(&s->lock) {
  737. new_state = s->state;
  738. QLIST_FOREACH_SAFE(rule, &s->rules[event], next, next) {
  739. process_rule(bs, rule, actions_count, &new_state);
  740. }
  741. s->state = new_state;
  742. }
  743. while (actions_count[ACTION_SUSPEND] > 0) {
  744. qemu_coroutine_yield();
  745. actions_count[ACTION_SUSPEND]--;
  746. }
  747. }
  748. static int blkdebug_debug_breakpoint(BlockDriverState *bs, const char *event,
  749. const char *tag)
  750. {
  751. BDRVBlkdebugState *s = bs->opaque;
  752. struct BlkdebugRule *rule;
  753. int blkdebug_event;
  754. blkdebug_event = qapi_enum_parse(&BlkdebugEvent_lookup, event, -1, NULL);
  755. if (blkdebug_event < 0) {
  756. return -ENOENT;
  757. }
  758. rule = g_malloc(sizeof(*rule));
  759. *rule = (struct BlkdebugRule) {
  760. .event = blkdebug_event,
  761. .action = ACTION_SUSPEND,
  762. .state = 0,
  763. .options.suspend.tag = g_strdup(tag),
  764. };
  765. qemu_mutex_lock(&s->lock);
  766. QLIST_INSERT_HEAD(&s->rules[blkdebug_event], rule, next);
  767. qemu_mutex_unlock(&s->lock);
  768. return 0;
  769. }
  770. /* Called with lock held. May temporarily release lock. */
  771. static int resume_req_by_tag(BDRVBlkdebugState *s, const char *tag, bool all)
  772. {
  773. BlkdebugSuspendedReq *r;
  774. retry:
  775. /*
  776. * No need for _SAFE, since a different coroutine can remove another node
  777. * (not the current one) in this list, and when the current one is removed
  778. * the iteration starts back from beginning anyways.
  779. */
  780. QLIST_FOREACH(r, &s->suspended_reqs, next) {
  781. if (!strcmp(r->tag, tag)) {
  782. Coroutine *co = r->co;
  783. if (!qtest_enabled()) {
  784. printf("blkdebug: Resuming request '%s'\n", r->tag);
  785. }
  786. QLIST_REMOVE(r, next);
  787. g_free(r->tag);
  788. g_free(r);
  789. qemu_mutex_unlock(&s->lock);
  790. qemu_coroutine_enter(co);
  791. qemu_mutex_lock(&s->lock);
  792. if (all) {
  793. goto retry;
  794. }
  795. return 0;
  796. }
  797. }
  798. return -ENOENT;
  799. }
  800. static int blkdebug_debug_resume(BlockDriverState *bs, const char *tag)
  801. {
  802. BDRVBlkdebugState *s = bs->opaque;
  803. QEMU_LOCK_GUARD(&s->lock);
  804. return resume_req_by_tag(s, tag, false);
  805. }
  806. static int blkdebug_debug_remove_breakpoint(BlockDriverState *bs,
  807. const char *tag)
  808. {
  809. BDRVBlkdebugState *s = bs->opaque;
  810. BlkdebugRule *rule, *next;
  811. int i, ret = -ENOENT;
  812. QEMU_LOCK_GUARD(&s->lock);
  813. for (i = 0; i < BLKDBG__MAX; i++) {
  814. QLIST_FOREACH_SAFE(rule, &s->rules[i], next, next) {
  815. if (rule->action == ACTION_SUSPEND &&
  816. !strcmp(rule->options.suspend.tag, tag)) {
  817. remove_rule(rule);
  818. ret = 0;
  819. }
  820. }
  821. }
  822. if (resume_req_by_tag(s, tag, true) == 0) {
  823. ret = 0;
  824. }
  825. return ret;
  826. }
  827. static bool blkdebug_debug_is_suspended(BlockDriverState *bs, const char *tag)
  828. {
  829. BDRVBlkdebugState *s = bs->opaque;
  830. BlkdebugSuspendedReq *r;
  831. QEMU_LOCK_GUARD(&s->lock);
  832. QLIST_FOREACH(r, &s->suspended_reqs, next) {
  833. if (!strcmp(r->tag, tag)) {
  834. return true;
  835. }
  836. }
  837. return false;
  838. }
  839. static int64_t coroutine_fn GRAPH_RDLOCK
  840. blkdebug_co_getlength(BlockDriverState *bs)
  841. {
  842. return bdrv_co_getlength(bs->file->bs);
  843. }
  844. static void GRAPH_RDLOCK blkdebug_refresh_filename(BlockDriverState *bs)
  845. {
  846. BDRVBlkdebugState *s = bs->opaque;
  847. const QDictEntry *e;
  848. int ret;
  849. if (!bs->file->bs->exact_filename[0]) {
  850. return;
  851. }
  852. for (e = qdict_first(bs->full_open_options); e;
  853. e = qdict_next(bs->full_open_options, e))
  854. {
  855. /* Real child options are under "image", but "x-image" may
  856. * contain a filename */
  857. if (strcmp(qdict_entry_key(e), "config") &&
  858. strcmp(qdict_entry_key(e), "image") &&
  859. strcmp(qdict_entry_key(e), "x-image") &&
  860. strcmp(qdict_entry_key(e), "driver"))
  861. {
  862. return;
  863. }
  864. }
  865. ret = snprintf(bs->exact_filename, sizeof(bs->exact_filename),
  866. "blkdebug:%s:%s",
  867. s->config_file ?: "", bs->file->bs->exact_filename);
  868. if (ret >= sizeof(bs->exact_filename)) {
  869. /* An overflow makes the filename unusable, so do not report any */
  870. bs->exact_filename[0] = 0;
  871. }
  872. }
  873. static void blkdebug_refresh_limits(BlockDriverState *bs, Error **errp)
  874. {
  875. BDRVBlkdebugState *s = bs->opaque;
  876. if (s->align) {
  877. bs->bl.request_alignment = s->align;
  878. }
  879. if (s->max_transfer) {
  880. bs->bl.max_transfer = s->max_transfer;
  881. }
  882. if (s->opt_write_zero) {
  883. bs->bl.pwrite_zeroes_alignment = s->opt_write_zero;
  884. }
  885. if (s->max_write_zero) {
  886. bs->bl.max_pwrite_zeroes = s->max_write_zero;
  887. }
  888. if (s->opt_discard) {
  889. bs->bl.pdiscard_alignment = s->opt_discard;
  890. }
  891. if (s->max_discard) {
  892. bs->bl.max_pdiscard = s->max_discard;
  893. }
  894. }
  895. static int blkdebug_reopen_prepare(BDRVReopenState *reopen_state,
  896. BlockReopenQueue *queue, Error **errp)
  897. {
  898. return 0;
  899. }
  900. static void blkdebug_child_perm(BlockDriverState *bs, BdrvChild *c,
  901. BdrvChildRole role,
  902. BlockReopenQueue *reopen_queue,
  903. uint64_t perm, uint64_t shared,
  904. uint64_t *nperm, uint64_t *nshared)
  905. {
  906. BDRVBlkdebugState *s = bs->opaque;
  907. bdrv_default_perms(bs, c, role, reopen_queue,
  908. perm, shared, nperm, nshared);
  909. *nperm |= s->take_child_perms;
  910. *nshared &= ~s->unshare_child_perms;
  911. }
  912. static const char *const blkdebug_strong_runtime_opts[] = {
  913. "config",
  914. "inject-error.",
  915. "set-state.",
  916. "align",
  917. "max-transfer",
  918. "opt-write-zero",
  919. "max-write-zero",
  920. "opt-discard",
  921. "max-discard",
  922. NULL
  923. };
  924. static BlockDriver bdrv_blkdebug = {
  925. .format_name = "blkdebug",
  926. .protocol_name = "blkdebug",
  927. .instance_size = sizeof(BDRVBlkdebugState),
  928. .is_filter = true,
  929. .bdrv_parse_filename = blkdebug_parse_filename,
  930. .bdrv_open = blkdebug_open,
  931. .bdrv_close = blkdebug_close,
  932. .bdrv_reopen_prepare = blkdebug_reopen_prepare,
  933. .bdrv_child_perm = blkdebug_child_perm,
  934. .bdrv_co_getlength = blkdebug_co_getlength,
  935. .bdrv_refresh_filename = blkdebug_refresh_filename,
  936. .bdrv_refresh_limits = blkdebug_refresh_limits,
  937. .bdrv_co_preadv = blkdebug_co_preadv,
  938. .bdrv_co_pwritev = blkdebug_co_pwritev,
  939. .bdrv_co_flush_to_disk = blkdebug_co_flush,
  940. .bdrv_co_pwrite_zeroes = blkdebug_co_pwrite_zeroes,
  941. .bdrv_co_pdiscard = blkdebug_co_pdiscard,
  942. .bdrv_co_block_status = blkdebug_co_block_status,
  943. .bdrv_co_debug_event = blkdebug_co_debug_event,
  944. .bdrv_debug_breakpoint = blkdebug_debug_breakpoint,
  945. .bdrv_debug_remove_breakpoint
  946. = blkdebug_debug_remove_breakpoint,
  947. .bdrv_debug_resume = blkdebug_debug_resume,
  948. .bdrv_debug_is_suspended = blkdebug_debug_is_suspended,
  949. .strong_runtime_opts = blkdebug_strong_runtime_opts,
  950. };
  951. static void bdrv_blkdebug_init(void)
  952. {
  953. bdrv_register(&bdrv_blkdebug);
  954. }
  955. block_init(bdrv_blkdebug_init);