xref: /openbmc/qemu/block/export/export.c (revision 6370d13c62c300826f8eb80e4ed9d2e67bad3fa7)
1  /*
2   * Common block export infrastructure
3   *
4   * Copyright (c) 2012, 2020 Red Hat, Inc.
5   *
6   * Authors:
7   * Paolo Bonzini <pbonzini@redhat.com>
8   * Kevin Wolf <kwolf@redhat.com>
9   *
10   * This work is licensed under the terms of the GNU GPL, version 2 or
11   * later.  See the COPYING file in the top-level directory.
12   */
13  
14  #include "qemu/osdep.h"
15  
16  #include "block/block.h"
17  #include "sysemu/block-backend.h"
18  #include "sysemu/iothread.h"
19  #include "block/export.h"
20  #include "block/fuse.h"
21  #include "block/nbd.h"
22  #include "qapi/error.h"
23  #include "qapi/qapi-commands-block-export.h"
24  #include "qapi/qapi-events-block-export.h"
25  #include "qemu/id.h"
26  #ifdef CONFIG_VHOST_USER_BLK_SERVER
27  #include "vhost-user-blk-server.h"
28  #endif
29  #ifdef CONFIG_VDUSE_BLK_EXPORT
30  #include "vduse-blk.h"
31  #endif
32  
33  static const BlockExportDriver *blk_exp_drivers[] = {
34      &blk_exp_nbd,
35  #ifdef CONFIG_VHOST_USER_BLK_SERVER
36      &blk_exp_vhost_user_blk,
37  #endif
38  #ifdef CONFIG_FUSE
39      &blk_exp_fuse,
40  #endif
41  #ifdef CONFIG_VDUSE_BLK_EXPORT
42      &blk_exp_vduse_blk,
43  #endif
44  };
45  
46  /* Only accessed from the main thread */
47  static QLIST_HEAD(, BlockExport) block_exports =
48      QLIST_HEAD_INITIALIZER(block_exports);
49  
blk_exp_find(const char * id)50  BlockExport *blk_exp_find(const char *id)
51  {
52      BlockExport *exp;
53  
54      QLIST_FOREACH(exp, &block_exports, next) {
55          if (strcmp(id, exp->id) == 0) {
56              return exp;
57          }
58      }
59  
60      return NULL;
61  }
62  
blk_exp_find_driver(BlockExportType type)63  static const BlockExportDriver *blk_exp_find_driver(BlockExportType type)
64  {
65      int i;
66  
67      for (i = 0; i < ARRAY_SIZE(blk_exp_drivers); i++) {
68          if (blk_exp_drivers[i]->type == type) {
69              return blk_exp_drivers[i];
70          }
71      }
72      return NULL;
73  }
74  
blk_exp_add(BlockExportOptions * export,Error ** errp)75  BlockExport *blk_exp_add(BlockExportOptions *export, Error **errp)
76  {
77      bool fixed_iothread = export->has_fixed_iothread && export->fixed_iothread;
78      const BlockExportDriver *drv;
79      BlockExport *exp = NULL;
80      BlockDriverState *bs;
81      BlockBackend *blk = NULL;
82      AioContext *ctx;
83      uint64_t perm;
84      int ret;
85  
86      GLOBAL_STATE_CODE();
87  
88      if (!id_wellformed(export->id)) {
89          error_setg(errp, "Invalid block export id");
90          return NULL;
91      }
92      if (blk_exp_find(export->id)) {
93          error_setg(errp, "Block export id '%s' is already in use", export->id);
94          return NULL;
95      }
96  
97      drv = blk_exp_find_driver(export->type);
98      if (!drv) {
99          error_setg(errp, "No driver found for the requested export type");
100          return NULL;
101      }
102  
103      bs = bdrv_lookup_bs(NULL, export->node_name, errp);
104      if (!bs) {
105          return NULL;
106      }
107  
108      if (!export->has_writable) {
109          export->writable = false;
110      }
111      if (bdrv_is_read_only(bs) && export->writable) {
112          error_setg(errp, "Cannot export read-only node as writable");
113          return NULL;
114      }
115  
116      ctx = bdrv_get_aio_context(bs);
117  
118      if (export->iothread) {
119          IOThread *iothread;
120          AioContext *new_ctx;
121          Error **set_context_errp;
122  
123          iothread = iothread_by_id(export->iothread);
124          if (!iothread) {
125              error_setg(errp, "iothread \"%s\" not found", export->iothread);
126              goto fail;
127          }
128  
129          new_ctx = iothread_get_aio_context(iothread);
130  
131          /* Ignore errors with fixed-iothread=false */
132          set_context_errp = fixed_iothread ? errp : NULL;
133          ret = bdrv_try_change_aio_context(bs, new_ctx, NULL, set_context_errp);
134          if (ret == 0) {
135              ctx = new_ctx;
136          } else if (fixed_iothread) {
137              goto fail;
138          }
139      }
140  
141      /*
142       * Block exports are used for non-shared storage migration. Make sure
143       * that BDRV_O_INACTIVE is cleared and the image is ready for write
144       * access since the export could be available before migration handover.
145       * ctx was acquired in the caller.
146       */
147      bdrv_graph_rdlock_main_loop();
148      bdrv_activate(bs, NULL);
149      bdrv_graph_rdunlock_main_loop();
150  
151      perm = BLK_PERM_CONSISTENT_READ;
152      if (export->writable) {
153          perm |= BLK_PERM_WRITE;
154      }
155  
156      blk = blk_new(ctx, perm, BLK_PERM_ALL);
157  
158      if (!fixed_iothread) {
159          blk_set_allow_aio_context_change(blk, true);
160      }
161  
162      ret = blk_insert_bs(blk, bs, errp);
163      if (ret < 0) {
164          goto fail;
165      }
166  
167      if (!export->has_writethrough) {
168          export->writethrough = false;
169      }
170      blk_set_enable_write_cache(blk, !export->writethrough);
171  
172      assert(drv->instance_size >= sizeof(BlockExport));
173      exp = g_malloc0(drv->instance_size);
174      *exp = (BlockExport) {
175          .drv        = drv,
176          .refcount   = 1,
177          .user_owned = true,
178          .id         = g_strdup(export->id),
179          .ctx        = ctx,
180          .blk        = blk,
181      };
182  
183      ret = drv->create(exp, export, errp);
184      if (ret < 0) {
185          goto fail;
186      }
187  
188      assert(exp->blk != NULL);
189  
190      QLIST_INSERT_HEAD(&block_exports, exp, next);
191      return exp;
192  
193  fail:
194      if (blk) {
195          blk_set_dev_ops(blk, NULL, NULL);
196          blk_unref(blk);
197      }
198      if (exp) {
199          g_free(exp->id);
200          g_free(exp);
201      }
202      return NULL;
203  }
204  
blk_exp_ref(BlockExport * exp)205  void blk_exp_ref(BlockExport *exp)
206  {
207      assert(qatomic_read(&exp->refcount) > 0);
208      qatomic_inc(&exp->refcount);
209  }
210  
211  /* Runs in the main thread */
blk_exp_delete_bh(void * opaque)212  static void blk_exp_delete_bh(void *opaque)
213  {
214      BlockExport *exp = opaque;
215  
216      assert(exp->refcount == 0);
217      QLIST_REMOVE(exp, next);
218      exp->drv->delete(exp);
219      blk_set_dev_ops(exp->blk, NULL, NULL);
220      blk_unref(exp->blk);
221      qapi_event_send_block_export_deleted(exp->id);
222      g_free(exp->id);
223      g_free(exp);
224  }
225  
blk_exp_unref(BlockExport * exp)226  void blk_exp_unref(BlockExport *exp)
227  {
228      assert(qatomic_read(&exp->refcount) > 0);
229      if (qatomic_fetch_dec(&exp->refcount) == 1) {
230          /* Touch the block_exports list only in the main thread */
231          aio_bh_schedule_oneshot(qemu_get_aio_context(), blk_exp_delete_bh,
232                                  exp);
233      }
234  }
235  
236  /*
237   * Drops the user reference to the export and requests that all client
238   * connections and other internally held references start to shut down. When
239   * the function returns, there may still be active references while the export
240   * is in the process of shutting down.
241   */
blk_exp_request_shutdown(BlockExport * exp)242  void blk_exp_request_shutdown(BlockExport *exp)
243  {
244      /*
245       * If the user doesn't own the export any more, it is already shutting
246       * down. We must not call .request_shutdown and decrease the refcount a
247       * second time.
248       */
249      if (!exp->user_owned) {
250          return;
251      }
252  
253      exp->drv->request_shutdown(exp);
254  
255      assert(exp->user_owned);
256      exp->user_owned = false;
257      blk_exp_unref(exp);
258  }
259  
260  /*
261   * Returns whether a block export of the given type exists.
262   * type == BLOCK_EXPORT_TYPE__MAX checks for an export of any type.
263   */
blk_exp_has_type(BlockExportType type)264  static bool blk_exp_has_type(BlockExportType type)
265  {
266      BlockExport *exp;
267  
268      if (type == BLOCK_EXPORT_TYPE__MAX) {
269          return !QLIST_EMPTY(&block_exports);
270      }
271  
272      QLIST_FOREACH(exp, &block_exports, next) {
273          if (exp->drv->type == type) {
274              return true;
275          }
276      }
277  
278      return false;
279  }
280  
281  /* type == BLOCK_EXPORT_TYPE__MAX for all types */
blk_exp_close_all_type(BlockExportType type)282  void blk_exp_close_all_type(BlockExportType type)
283  {
284      BlockExport *exp, *next;
285  
286      assert(in_aio_context_home_thread(qemu_get_aio_context()));
287  
288      QLIST_FOREACH_SAFE(exp, &block_exports, next, next) {
289          if (type != BLOCK_EXPORT_TYPE__MAX && exp->drv->type != type) {
290              continue;
291          }
292          blk_exp_request_shutdown(exp);
293      }
294  
295      AIO_WAIT_WHILE_UNLOCKED(NULL, blk_exp_has_type(type));
296  }
297  
blk_exp_close_all(void)298  void blk_exp_close_all(void)
299  {
300      blk_exp_close_all_type(BLOCK_EXPORT_TYPE__MAX);
301  }
302  
qmp_block_export_add(BlockExportOptions * export,Error ** errp)303  void qmp_block_export_add(BlockExportOptions *export, Error **errp)
304  {
305      blk_exp_add(export, errp);
306  }
307  
qmp_block_export_del(const char * id,bool has_mode,BlockExportRemoveMode mode,Error ** errp)308  void qmp_block_export_del(const char *id,
309                            bool has_mode, BlockExportRemoveMode mode,
310                            Error **errp)
311  {
312      ERRP_GUARD();
313      BlockExport *exp;
314  
315      exp = blk_exp_find(id);
316      if (exp == NULL) {
317          error_setg(errp, "Export '%s' is not found", id);
318          return;
319      }
320      if (!exp->user_owned) {
321          error_setg(errp, "Export '%s' is already shutting down", id);
322          return;
323      }
324  
325      if (!has_mode) {
326          mode = BLOCK_EXPORT_REMOVE_MODE_SAFE;
327      }
328      if (mode == BLOCK_EXPORT_REMOVE_MODE_SAFE &&
329          qatomic_read(&exp->refcount) > 1) {
330          error_setg(errp, "export '%s' still in use", exp->id);
331          error_append_hint(errp, "Use mode='hard' to force client "
332                            "disconnect\n");
333          return;
334      }
335  
336      blk_exp_request_shutdown(exp);
337  }
338  
qmp_query_block_exports(Error ** errp)339  BlockExportInfoList *qmp_query_block_exports(Error **errp)
340  {
341      BlockExportInfoList *head = NULL, **tail = &head;
342      BlockExport *exp;
343  
344      QLIST_FOREACH(exp, &block_exports, next) {
345          BlockExportInfo *info = g_new(BlockExportInfo, 1);
346          *info = (BlockExportInfo) {
347              .id             = g_strdup(exp->id),
348              .type           = exp->drv->type,
349              .node_name      = g_strdup(bdrv_get_node_name(blk_bs(exp->blk))),
350              .shutting_down  = !exp->user_owned,
351          };
352  
353          QAPI_LIST_APPEND(tail, info);
354      }
355  
356      return head;
357  }
358