LCOV - code coverage report
Current view: top level - drivers - td-ctx.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 165 0.0 %
Date: 2025-02-07 10:27:58 Functions: 0 12 0.0 %
Branches: 0 126 0.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                 :          0 :                 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                 :            :     xenevtchn_port_or_error_t port;
      92                 :            :     struct td_xenblkif *blkif;
      93                 :            :     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                 :          0 :     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                 :            :     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                 :            :         case BLKIF_PROTOCOL_NATIVE:
     162                 :            :             {
     163                 :            :                 blkif_request_t *src;
     164                 :          0 :                 src = RING_GET_REQUEST(&rings->native, idx);
     165                 :            :                 memcpy(dst, src, sizeof(blkif_request_t));
     166                 :            :                 break;
     167                 :            :             }
     168                 :            : 
     169                 :            :         case BLKIF_PROTOCOL_X86_32:
     170                 :            :             {
     171                 :            :                 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                 :            :         case BLKIF_PROTOCOL_X86_64:
     178                 :            :             {
     179                 :            :                 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                 :            :     blkif_common_back_ring_t * ring;
     210                 :            :     RING_IDX rp, rc;
     211                 :            :     unsigned int n;
     212                 :            :         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                 :            :     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                 :            :     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                 :            :     int n_reqs;
     294                 :            :     int start;
     295                 :            :     blkif_request_t **reqs;
     296                 :            :     int limit;
     297                 :            : 
     298                 :          0 :     start = blkif->n_reqs_free;
     299                 :            : 
     300         [ #  # ]:          0 :         if (unlikely(blkif->barrier.msg))
     301                 :            :                 return 0;
     302                 :            : 
     303                 :            :     /*
     304                 :            :      * In each iteration, copy as many request descriptors from the shared ring
     305                 :            :      * that can fit within the constraints.
     306                 :            :      * If there's memory available, use as many requests as available.
     307                 :            :      * If in low memory mode, don't copy any if there's some in flight.
     308                 :            :      * Otherwise, only copy one.
     309                 :            :      */
     310         [ #  # ]:          0 :         if (tapdisk_server_mem_mode() == LOW_MEMORY_MODE)
     311                 :          0 :             limit = blkif->ring_size != blkif->n_reqs_free ? 0 : 1;
     312                 :            :     else
     313                 :          0 :             limit = blkif->n_reqs_free;
     314                 :            : 
     315                 :            :     do {
     316                 :          0 :         reqs = &blkif->reqs_free[blkif->ring_size - blkif->n_reqs_free];
     317                 :            : 
     318         [ #  # ]:          0 :         ASSERT(reqs);
     319                 :            : 
     320                 :          0 :         n_reqs = xenio_blkif_get_requests(blkif, reqs, limit, final);
     321         [ #  # ]:          0 :         ASSERT(n_reqs >= 0);
     322         [ #  # ]:          0 :         if (!n_reqs)
     323                 :            :             break;
     324                 :            : 
     325                 :          0 :         blkif->n_reqs_free -= n_reqs;
     326         [ #  # ]:          0 :                 ASSERT(blkif->n_reqs_free <= blkif->ring_size);
     327                 :          0 :                 limit -= n_reqs;
     328                 :          0 :         final = 1;
     329                 :            : 
     330         [ #  # ]:          0 :                 if (unlikely(reqs[(n_reqs - 1)]->operation ==
     331                 :            :                                         BLKIF_OP_WRITE_BARRIER)) {
     332         [ #  # ]:          0 :                         ASSERT(!blkif->barrier.msg);
     333                 :          0 :                         blkif->barrier.msg = reqs[(n_reqs - 1)];
     334                 :          0 :                         blkif->barrier.io_done = false;
     335                 :          0 :                         blkif->barrier.io_err = 0;
     336                 :          0 :                         break;
     337                 :            :                 }
     338                 :            : 
     339                 :            :     } while (1);
     340                 :            : 
     341                 :          0 :     n_reqs = start - blkif->n_reqs_free;
     342                 :            : 
     343         [ #  # ]:          0 :     if (!n_reqs)
     344                 :            :                 /*
     345                 :            :                  * We got a notification but the ring is empty. This is because we had
     346                 :            :                  * previously suspended the operation of the ring because of a
     347                 :            :                  * VBD.pause but when we completed a request prior to the pause we
     348                 :            :                  * checked the ring for new requests. If there were request in the ring
     349                 :            :                  * at that time, we consumed them but we did not consume the
     350                 :            :                  * notification. This notification is the one we should have consumed,
     351                 :            :                  * and can be ignored.
     352                 :            :                  */
     353                 :            :                 return 0;
     354                 :            : 
     355         [ #  # ]:          0 :     if (blkif->in_polling)
     356                 :            :         /* We found at least one request, so keep polling some more */
     357                 :          0 :         tapdisk_xenblkif_sched_stoppolling(blkif);
     358         [ #  # ]:          0 :     else if (blkif->poll_duration)
     359                 :            :         /* We weren't polling, but polling is enabled, so let's start now */
     360                 :          0 :         tapdisk_start_polling(blkif);
     361                 :            : 
     362                 :          0 :     blkif->stats.reqs.in += n_reqs;
     363                 :            : 
     364                 :          0 :         reqs = alloca(sizeof(blkif_request_t*) * n_reqs);
     365                 :          0 :         memcpy(reqs, &blkif->reqs_free[blkif->ring_size - start],
     366                 :            :                         sizeof(blkif_request_t*) * n_reqs);
     367                 :            : 
     368                 :          0 :         tapdisk_xenblkif_queue_requests(blkif, reqs, n_reqs);
     369                 :            : 
     370                 :          0 :         return n_reqs;
     371                 :            : }
     372                 :            : 
     373                 :            : /**
     374                 :            :  * Callback executed when there is a request descriptor in the ring. Copies as
     375                 :            :  * many request descriptors as possible (limited by local buffer space) to the
     376                 :            :  * td_blkif's local request buffer and queues them to the tapdisk queue.
     377                 :            :  */
     378                 :            : static inline void
     379                 :          0 : tapdisk_xenio_ctx_ring_event(event_id_t id __attribute__((unused)),
     380                 :            :         char mode __attribute__((unused)), void *private)
     381                 :            : {
     382                 :          0 :     struct td_xenio_ctx *ctx = private;
     383                 :          0 :     struct td_xenblkif *blkif = NULL;
     384                 :            : 
     385         [ #  # ]:          0 :     ASSERT(ctx);
     386                 :            : 
     387                 :          0 :     blkif = xenio_pending_blkif(ctx);
     388         [ #  # ]:          0 :     if (!blkif) {
     389                 :            :         /* TODO log error */
     390                 :          0 :         return;
     391                 :            :     }
     392                 :            : 
     393                 :          0 :     blkif->stats.kicks.in++;
     394                 :            : 
     395                 :          0 :     tapdisk_xenio_ctx_process_ring(blkif, ctx, 0);
     396                 :            : }
     397                 :            : 
     398                 :            : /* NB. may be NULL, but then the image must be bouncing I/O */
     399                 :            : #define TD_XENBLKIF_DEFAULT_POOL "td-xenio-default"
     400                 :            : 
     401                 :            : /**
     402                 :            :  * Opens a context on the specified pool.
     403                 :            :  *
     404                 :            :  * @param pool the pool, it can either be NULL or a non-zero length string
     405                 :            :  * @returns 0 in success, -errno on error
     406                 :            :  *
     407                 :            :  * TODO The pool is ignored, we always open the default pool.
     408                 :            :  */
     409                 :            : static inline int
     410                 :          0 : tapdisk_xenio_ctx_open(const char *pool)
     411                 :            : {
     412                 :            :     struct td_xenio_ctx *ctx;
     413                 :            :     int fd, err;
     414                 :            : 
     415                 :            :     /* zero-length pool names are not allowed */
     416 [ #  # ][ #  # ]:          0 :     if (pool && !strlen(pool))
     417                 :            :         return -EINVAL;
     418                 :            : 
     419                 :          0 :     ctx = calloc(1, sizeof(*ctx));
     420         [ #  # ]:          0 :     if (!ctx) {
     421                 :          0 :         err = -errno;
     422                 :          0 :         ERROR("cannot allocate memory");
     423                 :          0 :         goto fail;
     424                 :            :     }
     425                 :            : 
     426                 :          0 :     ctx->ring_event = -1; /* TODO is there a special value? */
     427                 :          0 :     ctx->gntdev_fd = -1;
     428                 :          0 :     ctx->pool = TD_XENBLKIF_DEFAULT_POOL;
     429                 :          0 :         INIT_LIST_HEAD(&ctx->blkifs);
     430                 :          0 :     list_add(&ctx->entry, &_td_xenio_ctxs);
     431                 :            : 
     432                 :          0 :     ctx->gntdev_fd = open("/dev/xen/gntdev", O_NONBLOCK);
     433         [ #  # ]:          0 :     if (ctx->gntdev_fd == -1) {
     434                 :          0 :         err = -errno;
     435                 :          0 :         ERROR("failed to open the grant device: %s\n", strerror(-err));
     436                 :          0 :         goto fail;
     437                 :            :     }
     438                 :            : 
     439                 :          0 :     ctx->xce_handle = xenevtchn_open(NULL, 0);
     440         [ #  # ]:          0 :     if (!ctx->xce_handle) {
     441                 :          0 :         err = -errno;
     442                 :          0 :         ERROR("failed to open the event channel driver: %s\n",
     443                 :            :                 strerror(-err));
     444                 :          0 :         goto fail;
     445                 :            :     }
     446                 :            : 
     447                 :          0 :     ctx->xcg_handle = xengnttab_open(NULL, 0);
     448         [ #  # ]:          0 :     if (!ctx->xcg_handle) {
     449                 :          0 :         err = -errno;
     450                 :          0 :         ERROR("failed to open the grant table driver: %s\n",
     451                 :            :                 strerror(-err));
     452                 :          0 :         goto fail;
     453                 :            :     }
     454                 :            : 
     455                 :          0 :     fd = xenevtchn_fd(ctx->xce_handle);
     456         [ #  # ]:          0 :     if (fd < 0) {
     457                 :          0 :         err = -errno;
     458                 :          0 :         ERROR("failed to get the event channel file descriptor: %s\n",
     459                 :            :                 strerror(-err));
     460                 :          0 :         goto fail;
     461                 :            :     }
     462                 :            : 
     463                 :          0 :     ctx->ring_event = tapdisk_server_register_event(SCHEDULER_POLL_READ_FD,
     464                 :          0 :         fd, TV_ZERO, tapdisk_xenio_ctx_ring_event, ctx);
     465         [ #  # ]:          0 :     if (ctx->ring_event < 0) {
     466                 :          0 :         err = ctx->ring_event;
     467                 :          0 :         ERROR("failed to register event: %s\n", strerror(-err));
     468                 :          0 :         goto fail;
     469                 :            :     }
     470                 :            : 
     471                 :            :     return 0;
     472                 :            : 
     473                 :            : fail:
     474                 :          0 :     tapdisk_xenio_ctx_close(ctx);
     475                 :          0 :     return err;
     476                 :            : }
     477                 :            : 
     478                 :            : 
     479                 :            : /**
     480                 :            :  * Tells whether @ctx belongs to @pool.
     481                 :            :  *
     482                 :            :  * If no @pool is not specified and a default pool is set, @ctx is compared
     483                 :            :  * against the default pool. Note that NULL is valid pool name value.
     484                 :            :  */
     485                 :            : static inline int
     486                 :          0 : __td_xenio_ctx_match(struct td_xenio_ctx * ctx, const char *pool)
     487                 :            : {
     488         [ #  # ]:          0 :         if (unlikely(!pool)) {
     489                 :            :                 assert(TD_XENBLKIF_DEFAULT_POOL);
     490                 :          0 :                 return !strcmp(ctx->pool, TD_XENBLKIF_DEFAULT_POOL);
     491                 :            :         }
     492                 :            : 
     493                 :          0 :         return !strcmp(ctx->pool, pool);
     494                 :            : }
     495                 :            : 
     496                 :            : #define tapdisk_xenio_find_ctx(_ctx, _cond)     \
     497                 :            :         do {                                                                    \
     498                 :            :                 int found = 0;                                          \
     499                 :            :                 tapdisk_xenio_for_each_ctx(_ctx) {      \
     500                 :            :                         if (_cond) {                                    \
     501                 :            :                                 found = 1;                                      \
     502                 :            :                                 break;                                          \
     503                 :            :                         }                                                               \
     504                 :            :                 }                                                                       \
     505                 :            :                 if (!found)                                                     \
     506                 :            :                         _ctx = NULL;                                    \
     507                 :            :         } while (0)
     508                 :            : 
     509                 :            : int
     510                 :          0 : tapdisk_xenio_ctx_get(const char *pool, struct td_xenio_ctx ** _ctx)
     511                 :            : {
     512                 :          0 :     struct td_xenio_ctx *ctx;
     513                 :          0 :     int err = 0;
     514                 :            : 
     515                 :            :     do {
     516 [ #  # ][ #  # ]:          0 :         tapdisk_xenio_find_ctx(ctx, __td_xenio_ctx_match(ctx, pool));
                 [ #  # ]
     517         [ #  # ]:          0 :         if (ctx) {
     518                 :          0 :             *_ctx = ctx;
     519                 :          0 :             return 0;
     520                 :            :         }
     521                 :            : 
     522                 :          0 :         err = tapdisk_xenio_ctx_open(pool);
     523         [ #  # ]:          0 :     } while (!err);
     524                 :            : 
     525                 :            :     return err;
     526                 :            : }
     527                 :            : 
     528                 :            : void
     529                 :          0 : tapdisk_xenio_ctx_put(struct td_xenio_ctx * ctx)
     530                 :            : {
     531         [ #  # ]:          0 :     if (list_empty(&ctx->blkifs))
     532                 :          0 :         tapdisk_xenio_ctx_close(ctx);
     533                 :          0 : }

Generated by: LCOV version 1.13