LCOV - code coverage report
Current view: top level - drivers - td-ctx.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 187 0
Test Date: 2026-06-26 00:00:00 Functions: 0.0 % 11 0
Branches: 0.0 % 116 0

             Branch data     Line data    Source code
       1                 :             : /*
       2                 :             :  * Copyright (c) 2016, Citrix Systems, Inc.
       3                 :             :  *
       4                 :             :  * All rights reserved.
       5                 :             :  *
       6                 :             :  * Redistribution and use in source and binary forms, with or without
       7                 :             :  * modification, are permitted provided that the following conditions are met:
       8                 :             :  * 
       9                 :             :  *  1. Redistributions of source code must retain the above copyright
      10                 :             :  *     notice, this list of conditions and the following disclaimer.
      11                 :             :  *  2. Redistributions in binary form must reproduce the above copyright
      12                 :             :  *     notice, this list of conditions and the following disclaimer in the
      13                 :             :  *     documentation and/or other materials provided with the distribution.
      14                 :             :  *  3. Neither the name of the copyright holder nor the names of its 
      15                 :             :  *     contributors may be used to endorse or promote products derived from 
      16                 :             :  *     this software without specific prior written permission.
      17                 :             :  *
      18                 :             :  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      19                 :             :  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      20                 :             :  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
      21                 :             :  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
      22                 :             :  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
      23                 :             :  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
      24                 :             :  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
      25                 :             :  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
      26                 :             :  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
      27                 :             :  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
      28                 :             :  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      29                 :             :  */
      30                 :             : 
      31                 :             : #include <assert.h>
      32                 :             : #include <errno.h>
      33                 :             : #include <stdlib.h>
      34                 :             : #include <unistd.h>
      35                 :             : #include <sys/types.h>
      36                 :             : #include <sys/stat.h>
      37                 :             : #include <fcntl.h>
      38                 :             : #include <alloca.h>
      39                 :             : 
      40                 :             : #include "blktap-xenif.h"
      41                 :             : #include "debug.h"
      42                 :             : #include "tapdisk-server.h"
      43                 :             : #include "td-ctx.h"
      44                 :             : #include "tapdisk-log.h"
      45                 :             : #include "timeout-math.h"
      46                 :             : 
      47                 :             : #define ERROR(_f, _a...)           tlog_syslog(TLOG_WARN, "td-ctx: " _f, ##_a)
      48                 :             : 
      49                 :             : struct list_head _td_xenio_ctxs = LIST_HEAD_INIT(_td_xenio_ctxs);
      50                 :             : 
      51                 :             : /**
      52                 :             :  * TODO releases a pool?
      53                 :             :  */
      54                 :             : static void
      55                 :           0 : tapdisk_xenio_ctx_close(struct td_xenio_ctx * const ctx)
      56                 :             : {
      57         [ #  # ]:           0 :         if (!ctx)
      58                 :             :                 return;
      59                 :             : 
      60         [ #  # ]:           0 :     if (ctx->ring_event >= 0) {
      61                 :           0 :         tapdisk_server_unregister_event(ctx->ring_event);
      62                 :           0 :         ctx->ring_event = -1;
      63                 :             :     }
      64                 :             : 
      65         [ #  # ]:           0 :     if (ctx->xce_handle) {
      66                 :           0 :         xenevtchn_close(ctx->xce_handle);
      67                 :           0 :         ctx->xce_handle = NULL;
      68                 :             :     }
      69                 :             : 
      70         [ #  # ]:           0 :     if (ctx->xcg_handle) {
      71                 :           0 :         xengnttab_close(ctx->xcg_handle);
      72                 :           0 :         ctx->xcg_handle = NULL;
      73                 :             :     }
      74                 :             : 
      75         [ #  # ]:           0 :     if (ctx->gntdev_fd != -1) {
      76                 :           0 :         close(ctx->gntdev_fd);
      77                 :           0 :         ctx->gntdev_fd = -1;
      78                 :             :     }
      79                 :             : 
      80                 :           0 :     list_del(&ctx->entry);
      81                 :             : 
      82                 :           0 :         free(ctx);
      83                 :             : }
      84                 :             : 
      85                 :             : /*
      86                 :             :  * XXX only called by tapdisk_xenio_ctx_ring_event
      87                 :             :  */
      88                 :             : static inline struct td_xenblkif *
      89                 :           0 : xenio_pending_blkif(struct td_xenio_ctx * const ctx)
      90                 :             : {
      91                 :           0 :     xenevtchn_port_or_error_t port;
      92                 :           0 :     struct td_xenblkif *blkif;
      93                 :           0 :     int err;
      94                 :             : 
      95         [ #  # ]:           0 :     ASSERT(ctx);
      96                 :             : 
      97                 :             :     /*
      98                 :             :      * Get the local port for which there is a pending event.
      99                 :             :      */
     100                 :           0 :     port = xenevtchn_pending(ctx->xce_handle);
     101         [ #  # ]:           0 :     if (port == -1) {
     102                 :             :         /* TODO log error */
     103                 :             :         return NULL;
     104                 :             :     }
     105                 :             : 
     106                 :             :     /*
     107                 :             :      * Find the block interface with that local port.
     108                 :             :      */
     109   [ #  #  #  #  :           0 :     tapdisk_xenio_ctx_find_blkif(ctx, blkif,
             #  #  #  # ]
     110                 :             :             blkif->port == port);
     111                 :           0 :     if (blkif) {
     112                 :           0 :         err = xenevtchn_unmask(ctx->xce_handle, port);
     113         [ #  # ]:           0 :         if (err) {
     114                 :             :             /* TODO log error */
     115                 :             :             return NULL;
     116                 :             :         }
     117                 :             :     }
     118                 :             :     /*
     119                 :             :      * TODO Is it possible to have an pending event channel but no block
     120                 :             :      * interface associated with it?
     121                 :             :      */
     122                 :             : 
     123                 :             :     return blkif;
     124                 :             : }
     125                 :             : 
     126                 :             : #define blkif_get_req(dst, src)                 \
     127                 :             : {                                               \
     128                 :             :     int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST;  \
     129                 :             :     dst->operation = src->operation;            \
     130                 :             :     dst->nr_segments = src->nr_segments;        \
     131                 :             :     dst->handle = src->handle;                  \
     132                 :             :     dst->id = src->id;                          \
     133                 :             :     dst->sector_number = src->sector_number;    \
     134                 :             :     xen_rmb();                                  \
     135                 :             :     if (n > dst->nr_segments)                   \
     136                 :             :         n = dst->nr_segments;                   \
     137                 :             :     for (i = 0; i < n; i++)                     \
     138                 :             :         dst->seg[i] = src->seg[i];              \
     139                 :             : }
     140                 :             : 
     141                 :             : /**
     142                 :             :  * Utility function that retrieves a request using @idx as the ring index,
     143                 :             :  * copying it to the @dst in a H/W independent way.
     144                 :             :  *
     145                 :             :  * @param blkif the block interface
     146                 :             :  * @param dst address that receives the request
     147                 :             :  * @param rc the index of the request in the ring
     148                 :             :  */
     149                 :             : static inline void
     150                 :           0 : xenio_blkif_get_request(struct td_xenblkif * const blkif,
     151                 :             :         blkif_request_t *const dst, const RING_IDX idx)
     152                 :             : {
     153                 :           0 :     blkif_back_rings_t * rings;
     154                 :             : 
     155         [ #  # ]:           0 :     ASSERT(blkif);
     156         [ #  # ]:           0 :     ASSERT(dst);
     157                 :             : 
     158                 :           0 :     rings = &blkif->rings;
     159                 :             : 
     160   [ #  #  #  # ]:           0 :     switch (blkif->proto) {
     161                 :           0 :         case BLKIF_PROTOCOL_NATIVE:
     162                 :             :             {
     163                 :           0 :                 blkif_request_t *src;
     164                 :           0 :                 src = RING_GET_REQUEST(&rings->native, idx);
     165                 :           0 :                 memcpy(dst, src, sizeof(blkif_request_t));
     166                 :           0 :                 break;
     167                 :             :             }
     168                 :             : 
     169                 :           0 :         case BLKIF_PROTOCOL_X86_32:
     170                 :             :             {
     171                 :           0 :                 blkif_x86_32_request_t *src;
     172                 :           0 :                 src = RING_GET_REQUEST(&rings->x86_32, idx);
     173         [ #  # ]:           0 :                 blkif_get_req(dst, src);
     174                 :             :                 break;
     175                 :             :             }
     176                 :             : 
     177                 :           0 :         case BLKIF_PROTOCOL_X86_64:
     178                 :             :             {
     179                 :           0 :                 blkif_x86_64_request_t *src;
     180                 :           0 :                 src = RING_GET_REQUEST(&rings->x86_64, idx);
     181         [ #  # ]:           0 :                 blkif_get_req(dst, src);
     182                 :             :                 break;
     183                 :             :             }
     184                 :             : 
     185                 :             :         default:
     186                 :             :             /*
     187                 :             :              * TODO log error
     188                 :             :              */
     189                 :           0 :             ASSERT(0);
     190                 :             :     }
     191                 :           0 : }
     192                 :             : 
     193                 :             : /**
     194                 :             :  * Retrieves at most @count request descriptors from the ring, up to the
     195                 :             :  * first barrier request, copying them to @reqs.
     196                 :             :  *
     197                 :             :  * @param blkif the block interface
     198                 :             :  * @param reqs array of pointers where each element points to sufficient memory
     199                 :             :  * space that receives each request descriptor
     200                 :             :  * @param count retrieve at most that many request descriptors
     201                 :             :  * @returns the number of retrieved request descriptors
     202                 :             :  *
     203                 :             :  *  XXX only called by xenio_blkif_get_requests
     204                 :             :  */
     205                 :             : static inline int
     206                 :           0 : __xenio_blkif_get_requests(struct td_xenblkif * const blkif,
     207                 :             :         blkif_request_t *reqs[], const unsigned int count)
     208                 :             : {
     209                 :           0 :     blkif_common_back_ring_t * ring;
     210                 :           0 :     RING_IDX rp, rc;
     211                 :           0 :     unsigned int n;
     212                 :           0 :         bool barrier;
     213                 :             : 
     214         [ #  # ]:           0 :     ASSERT(blkif);
     215         [ #  # ]:           0 :     ASSERT(reqs);
     216                 :             : 
     217         [ #  # ]:           0 :     if (!count)
     218                 :             :         return 0;
     219                 :             : 
     220                 :           0 :     ring = &blkif->rings.common;
     221                 :             : 
     222                 :           0 :     rp = ring->sring->req_prod;
     223                 :           0 :     xen_rmb(); /* TODO why? */
     224                 :             : 
     225                 :           0 :     for (rc = ring->req_cons, n = 0, barrier = false;
     226   [ #  #  #  # ]:           0 :                         rc != rp && n < count && !barrier;
     227                 :           0 :                         rc++, n++) {
     228                 :             : 
     229                 :           0 :         blkif_request_t *dst = reqs[n];
     230                 :             : 
     231                 :           0 :         xenio_blkif_get_request(blkif, dst, rc);
     232                 :             : 
     233         [ #  # ]:           0 :                 if (unlikely(dst->operation == BLKIF_OP_WRITE_BARRIER))
     234                 :           0 :                         barrier = true;
     235                 :             :     }
     236                 :             : 
     237                 :           0 :     ring->req_cons = rc;
     238                 :             : 
     239                 :           0 :     return n;
     240                 :             : }
     241                 :             : 
     242                 :             : /**
     243                 :             :  * Retrieves at most @count request descriptors.
     244                 :             :  *
     245                 :             :  * @param blkif the block interface
     246                 :             :  * @param reqs array of pointers where each pointer points to sufficient
     247                 :             :  * memory to hold a request descriptor
     248                 :             :  * @count maximum number of request descriptors to retrieve
     249                 :             :  * @param final re-enable notifications before it stops reading
     250                 :             :  * @returns the number of request descriptors retrieved
     251                 :             :  *
     252                 :             :  * TODO change name
     253                 :             :  */
     254                 :             : static inline int
     255                 :           0 : xenio_blkif_get_requests(struct td_xenblkif * const blkif,
     256                 :             :         blkif_request_t *reqs[], const int count, const int final)
     257                 :             : {
     258                 :           0 :     blkif_common_back_ring_t * ring;
     259                 :           0 :     int n = 0;
     260                 :           0 :     int work = 0;
     261                 :             : 
     262         [ #  # ]:           0 :     ASSERT(blkif);
     263         [ #  # ]:           0 :     ASSERT(reqs);
     264                 :             : 
     265                 :             :     ring = &blkif->rings.common;
     266                 :             : 
     267                 :           0 :     do {
     268         [ #  # ]:           0 :         if (final)
     269         [ #  # ]:           0 :             RING_FINAL_CHECK_FOR_REQUESTS(ring, work);
     270                 :             :         else
     271                 :           0 :             work = RING_HAS_UNCONSUMED_REQUESTS(ring);
     272                 :             : 
     273         [ #  # ]:           0 :         if (!work)
     274                 :             :             break;
     275                 :             : 
     276         [ #  # ]:           0 :         if (n >= count)
     277                 :             :             break;
     278                 :             : 
     279                 :           0 :         n += __xenio_blkif_get_requests(blkif, reqs + n, count - n);
     280                 :             : 
     281   [ #  #  #  # ]:           0 :                 if (unlikely(n && reqs[(n - 1)]->operation == BLKIF_OP_WRITE_BARRIER))
     282                 :             :                         break;
     283                 :             : 
     284                 :             :     } while (1);
     285                 :             : 
     286                 :           0 :     return n;
     287                 :             : }
     288                 :             : 
     289                 :             : int
     290                 :           0 : tapdisk_xenio_ctx_process_ring(struct td_xenblkif *blkif,
     291                 :             :                                struct td_xenio_ctx *ctx, int final)
     292                 :             : {
     293                 :           0 :     int n_reqs;
     294                 :           0 :     int start;
     295                 :           0 :     blkif_request_t **reqs;
     296                 :           0 :     int limit;
     297                 :             : 
     298                 :           0 :     start = blkif->n_reqs_free;
     299                 :             : 
     300         [ #  # ]:           0 :         if (unlikely(blkif->barrier.msg))
     301                 :             :                 return 0;
     302                 :             : 
     303                 :             :         limit = blkif->n_reqs_free;
     304                 :             : 
     305                 :           0 :     do {
     306                 :           0 :         reqs = &blkif->reqs_free[blkif->ring_size - blkif->n_reqs_free];
     307                 :             : 
     308         [ #  # ]:           0 :         ASSERT(reqs);
     309                 :             : 
     310                 :           0 :         n_reqs = xenio_blkif_get_requests(blkif, reqs, limit, final);
     311         [ #  # ]:           0 :         ASSERT(n_reqs >= 0);
     312         [ #  # ]:           0 :         if (!n_reqs)
     313                 :             :             break;
     314                 :             : 
     315                 :           0 :         blkif->n_reqs_free -= n_reqs;
     316         [ #  # ]:           0 :                 ASSERT(blkif->n_reqs_free <= blkif->ring_size);
     317                 :           0 :                 limit -= n_reqs;
     318                 :           0 :         final = 1;
     319                 :             : 
     320         [ #  # ]:           0 :                 if (unlikely(reqs[(n_reqs - 1)]->operation ==
     321                 :             :                                         BLKIF_OP_WRITE_BARRIER)) {
     322         [ #  # ]:           0 :                         ASSERT(!blkif->barrier.msg);
     323                 :           0 :                         blkif->barrier.msg = reqs[(n_reqs - 1)];
     324                 :           0 :                         blkif->barrier.io_done = false;
     325                 :           0 :                         blkif->barrier.io_err = 0;
     326                 :           0 :                         break;
     327                 :             :                 }
     328                 :             : 
     329                 :             :     } while (1);
     330                 :             : 
     331                 :           0 :     n_reqs = start - blkif->n_reqs_free;
     332                 :             : 
     333         [ #  # ]:           0 :     if (!n_reqs)
     334                 :             :                 /*
     335                 :             :                  * We got a notification but the ring is empty. This is because we had
     336                 :             :                  * previously suspended the operation of the ring because of a
     337                 :             :                  * VBD.pause but when we completed a request prior to the pause we
     338                 :             :                  * checked the ring for new requests. If there were request in the ring
     339                 :             :                  * at that time, we consumed them but we did not consume the
     340                 :             :                  * notification. This notification is the one we should have consumed,
     341                 :             :                  * and can be ignored.
     342                 :             :                  */
     343                 :             :                 return 0;
     344                 :             : 
     345         [ #  # ]:           0 :     if (blkif->in_polling)
     346                 :             :         /* We found at least one request, so keep polling some more */
     347                 :           0 :         tapdisk_xenblkif_sched_stoppolling(blkif);
     348         [ #  # ]:           0 :     else if (blkif->poll_duration)
     349                 :             :         /* We weren't polling, but polling is enabled, so let's start now */
     350                 :           0 :         tapdisk_start_polling(blkif);
     351                 :             : 
     352                 :           0 :     blkif->stats.reqs.in += n_reqs;
     353                 :             : 
     354                 :           0 :         reqs = alloca(sizeof(blkif_request_t*) * n_reqs);
     355                 :           0 :         memcpy(reqs, &blkif->reqs_free[blkif->ring_size - start],
     356                 :             :                         sizeof(blkif_request_t*) * n_reqs);
     357                 :             : 
     358                 :           0 :         tapdisk_xenblkif_queue_requests(blkif, reqs, n_reqs);
     359                 :             : 
     360                 :           0 :         return n_reqs;
     361                 :             : }
     362                 :             : 
     363                 :             : /**
     364                 :             :  * Callback executed when there is a request descriptor in the ring. Copies as
     365                 :             :  * many request descriptors as possible (limited by local buffer space) to the
     366                 :             :  * td_blkif's local request buffer and queues them to the tapdisk queue.
     367                 :             :  */
     368                 :             : static inline void
     369                 :           0 : tapdisk_xenio_ctx_ring_event(event_id_t id __attribute__((unused)),
     370                 :             :         char mode __attribute__((unused)), void *private)
     371                 :             : {
     372                 :           0 :     struct td_xenio_ctx *ctx = private;
     373                 :           0 :     struct td_xenblkif *blkif = NULL;
     374                 :             : 
     375         [ #  # ]:           0 :     ASSERT(ctx);
     376                 :             : 
     377                 :           0 :     blkif = xenio_pending_blkif(ctx);
     378         [ #  # ]:           0 :     if (!blkif) {
     379                 :             :         /* TODO log error */
     380                 :             :         return;
     381                 :             :     }
     382                 :             : 
     383                 :           0 :     blkif->stats.kicks.in++;
     384                 :             : 
     385                 :           0 :     tapdisk_xenio_ctx_process_ring(blkif, ctx, 0);
     386                 :             : }
     387                 :             : 
     388                 :             : /* NB. may be NULL, but then the image must be bouncing I/O */
     389                 :             : #define TD_XENBLKIF_DEFAULT_POOL "td-xenio-default"
     390                 :             : 
     391                 :             : /**
     392                 :             :  * Opens a context on the specified pool.
     393                 :             :  *
     394                 :             :  * @param pool the pool, it can either be NULL or a non-zero length string
     395                 :             :  * @returns 0 in success, -errno on error
     396                 :             :  *
     397                 :             :  * TODO The pool is ignored, we always open the default pool.
     398                 :             :  */
     399                 :             : static inline int
     400                 :           0 : tapdisk_xenio_ctx_open(const char *pool)
     401                 :             : {
     402                 :           0 :     struct td_xenio_ctx *ctx;
     403                 :           0 :     int fd, err;
     404                 :             : 
     405                 :             :     /* zero-length pool names are not allowed */
     406   [ #  #  #  # ]:           0 :     if (pool && !strlen(pool))
     407                 :           0 :         return -EINVAL;
     408                 :             : 
     409                 :           0 :     ctx = calloc(1, sizeof(*ctx));
     410         [ #  # ]:           0 :     if (!ctx) {
     411                 :           0 :         err = -errno;
     412                 :           0 :         ERROR("cannot allocate memory");
     413                 :           0 :         goto fail;
     414                 :             :     }
     415                 :             : 
     416                 :           0 :     ctx->ring_event = -1; /* TODO is there a special value? */
     417                 :           0 :     ctx->gntdev_fd = -1;
     418                 :           0 :     ctx->pool = TD_XENBLKIF_DEFAULT_POOL;
     419                 :           0 :         INIT_LIST_HEAD(&ctx->blkifs);
     420                 :           0 :     list_add(&ctx->entry, &_td_xenio_ctxs);
     421                 :             : 
     422                 :           0 :     ctx->gntdev_fd = open("/dev/xen/gntdev", O_NONBLOCK);
     423         [ #  # ]:           0 :     if (ctx->gntdev_fd == -1) {
     424                 :           0 :         err = -errno;
     425                 :           0 :         ERROR("failed to open the grant device: %s\n", strerror(-err));
     426                 :           0 :         goto fail;
     427                 :             :     }
     428                 :             : 
     429                 :           0 :     ctx->xce_handle = xenevtchn_open(NULL, 0);
     430         [ #  # ]:           0 :     if (!ctx->xce_handle) {
     431                 :           0 :         err = -errno;
     432                 :           0 :         ERROR("failed to open the event channel driver: %s\n",
     433                 :             :                 strerror(-err));
     434                 :           0 :         goto fail;
     435                 :             :     }
     436                 :             : 
     437                 :           0 :     ctx->xcg_handle = xengnttab_open(NULL, 0);
     438         [ #  # ]:           0 :     if (!ctx->xcg_handle) {
     439                 :           0 :         err = -errno;
     440                 :           0 :         ERROR("failed to open the grant table driver: %s\n",
     441                 :             :                 strerror(-err));
     442                 :           0 :         goto fail;
     443                 :             :     }
     444                 :             : 
     445                 :           0 :     fd = xenevtchn_fd(ctx->xce_handle);
     446         [ #  # ]:           0 :     if (fd < 0) {
     447                 :           0 :         err = -errno;
     448                 :           0 :         ERROR("failed to get the event channel file descriptor: %s\n",
     449                 :             :                 strerror(-err));
     450                 :           0 :         goto fail;
     451                 :             :     }
     452                 :             : 
     453                 :           0 :     ctx->ring_event = tapdisk_server_register_event(SCHEDULER_POLL_READ_FD,
     454                 :           0 :         fd, TV_ZERO, tapdisk_xenio_ctx_ring_event, ctx);
     455         [ #  # ]:           0 :     if (ctx->ring_event < 0) {
     456                 :           0 :         err = ctx->ring_event;
     457                 :           0 :         ERROR("failed to register event: %s\n", strerror(-err));
     458                 :           0 :         goto fail;
     459                 :             :     }
     460                 :             : 
     461                 :             :     return 0;
     462                 :             : 
     463                 :           0 : fail:
     464                 :           0 :     tapdisk_xenio_ctx_close(ctx);
     465                 :             :     return err;
     466                 :             : }
     467                 :             : 
     468                 :             : 
     469                 :             : /**
     470                 :             :  * Tells whether @ctx belongs to @pool.
     471                 :             :  *
     472                 :             :  * If no @pool is not specified and a default pool is set, @ctx is compared
     473                 :             :  * against the default pool. Note that NULL is valid pool name value.
     474                 :             :  */
     475                 :             : static inline int
     476                 :           0 : __td_xenio_ctx_match(struct td_xenio_ctx * ctx, const char *pool)
     477                 :             : {
     478         [ #  # ]:           0 :         if (unlikely(!pool)) {
     479                 :           0 :                 assert(TD_XENBLKIF_DEFAULT_POOL);
     480                 :           0 :                 return !strcmp(ctx->pool, TD_XENBLKIF_DEFAULT_POOL);
     481                 :             :         }
     482                 :             : 
     483                 :           0 :         return !strcmp(ctx->pool, pool);
     484                 :             : }
     485                 :             : 
     486                 :             : #define tapdisk_xenio_find_ctx(_ctx, _cond)     \
     487                 :             :         do {                                                                    \
     488                 :             :                 int found = 0;                                          \
     489                 :             :                 tapdisk_xenio_for_each_ctx(_ctx) {      \
     490                 :             :                         if (_cond) {                                    \
     491                 :             :                                 found = 1;                                      \
     492                 :             :                                 break;                                          \
     493                 :             :                         }                                                               \
     494                 :             :                 }                                                                       \
     495                 :             :                 if (!found)                                                     \
     496                 :             :                         _ctx = NULL;                                    \
     497                 :             :         } while (0)
     498                 :             : 
     499                 :             : int
     500                 :           0 : tapdisk_xenio_ctx_get(const char *pool, struct td_xenio_ctx ** _ctx)
     501                 :             : {
     502                 :           0 :     struct td_xenio_ctx *ctx;
     503                 :           0 :     int err = 0;
     504                 :             : 
     505                 :           0 :     do {
     506   [ #  #  #  #  :           0 :         tapdisk_xenio_find_ctx(ctx, __td_xenio_ctx_match(ctx, pool));
                   #  # ]
     507                 :           0 :         if (ctx) {
     508                 :           0 :             *_ctx = ctx;
     509                 :           0 :             return 0;
     510                 :             :         }
     511                 :             : 
     512                 :           0 :         err = tapdisk_xenio_ctx_open(pool);
     513         [ #  # ]:           0 :     } while (!err);
     514                 :             : 
     515                 :             :     return err;
     516                 :             : }
     517                 :             : 
     518                 :             : void
     519                 :           0 : tapdisk_xenio_ctx_put(struct td_xenio_ctx * ctx)
     520                 :             : {
     521         [ #  # ]:           0 :     if (list_empty(&ctx->blkifs))
     522                 :           0 :         tapdisk_xenio_ctx_close(ctx);
     523                 :           0 : }
        

Generated by: LCOV version 2.0-1