LCOV - code coverage report
Current view: top level - drivers - block-valve.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 252 0.0 %
Date: 2024-06-19 15:27:45 Functions: 0 30 0.0 %
Branches: 0 113 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                 :            : #ifdef HAVE_CONFIG_H
      32                 :            : #include "config.h"
      33                 :            : #endif
      34                 :            : 
      35                 :            : #include <stdlib.h>
      36                 :            : #include <stdio.h>
      37                 :            : #include <string.h>
      38                 :            : #include <unistd.h>
      39                 :            : #include <errno.h>
      40                 :            : #include <sys/socket.h>
      41                 :            : #include <sys/un.h>
      42                 :            : 
      43                 :            : #include "tapdisk.h"
      44                 :            : #include "tapdisk-driver.h"
      45                 :            : #include "tapdisk-server.h"
      46                 :            : #include "tapdisk-interface.h"
      47                 :            : #include "timeout-math.h"
      48                 :            : #include "util.h"
      49                 :            : 
      50                 :            : #include "block-valve.h"
      51                 :            : 
      52                 :            : typedef struct td_valve td_valve_t;
      53                 :            : typedef struct td_valve_request td_valve_request_t;
      54                 :            : 
      55                 :            : struct td_valve_request {
      56                 :            :         td_request_t            treq;
      57                 :            :         int                     secs;
      58                 :            : 
      59                 :            :         struct list_head        entry;
      60                 :            :         td_valve_t             *valve;
      61                 :            : };
      62                 :            : 
      63                 :            : struct td_valve_stats {
      64                 :            :         unsigned long long      stor;
      65                 :            :         unsigned long long      forw;
      66                 :            : };
      67                 :            : 
      68                 :            : struct td_valve {
      69                 :            :         char                   *brname;
      70                 :            :         unsigned long           flags;
      71                 :            : 
      72                 :            :         int                     sock;
      73                 :            :         event_id_t              sock_id;
      74                 :            : 
      75                 :            :         event_id_t              sched_id;
      76                 :            :         event_id_t              retry_id;
      77                 :            : 
      78                 :            :         unsigned int            cred;
      79                 :            :         unsigned int            need;
      80                 :            :         unsigned int            done;
      81                 :            : 
      82                 :            :         struct list_head        stor;
      83                 :            :         struct list_head        forw;
      84                 :            : 
      85                 :            :         td_valve_request_t      reqv[MAX_REQUESTS];
      86                 :            :         td_valve_request_t     *free[MAX_REQUESTS];
      87                 :            :         int                     n_free;
      88                 :            : 
      89                 :            :         struct td_valve_stats   stats;
      90                 :            : };
      91                 :            : 
      92                 :            : #define td_valve_for_each_stored_request(_req, _next, _valve)           \
      93                 :            :         list_for_each_entry_safe(_req, _next, &(_valve)->stor, entry)
      94                 :            : 
      95                 :            : #define td_valve_for_each_forwarded_request(_req, _next, _valve)        \
      96                 :            :         list_for_each_entry_safe(_req, _next, &(_valve)->forw, entry)
      97                 :            : 
      98                 :            : #define TD_VALVE_CONNECT_INTERVAL 2 /* s */
      99                 :            : 
     100                 :            : #define TD_VALVE_RDLIMIT  (1<<0)
     101                 :            : #define TD_VALVE_WRLIMIT  (1<<1)
     102                 :            : #define TD_VALVE_KILLED   (1<<31)
     103                 :            : 
     104                 :            : static void valve_schedule_retry(td_valve_t *);
     105                 :            : static void valve_conn_receive(td_valve_t *);
     106                 :            : static void valve_conn_request(td_valve_t *, unsigned long);
     107                 :            : static void valve_forward_stored_requests(td_valve_t *);
     108                 :            : static void valve_kill(td_valve_t *);
     109                 :            : 
     110                 :            : #define DBG(_f, _a...)    if (1) { tlog_syslog(TLOG_DBG, _f, ##_a); }
     111                 :            : #define INFO(_f, _a...)   tlog_syslog(TLOG_INFO, "valve: " _f, ##_a)
     112                 :            : #define WARN(_f, _a...)   tlog_syslog(TLOG_WARN, "WARNING: "_f " in %s:%d", \
     113                 :            :                                       ##_a, __func__, __LINE__)
     114                 :            : #define ERR(_f, _a...)    tlog_syslog(TLOG_WARN, "ERROR: " _f " in %s:%d", \
     115                 :            :                                       ##_a, __func__, __LINE__)
     116                 :            : #define VERR(_err, _f, _a...) tlog_syslog(TLOG_WARN,                     \
     117                 :            :                                           "ERROR: err=%d (%s), " _f ".", \
     118                 :            :                                           _err, strerror(-(_err)), ##_a)
     119                 :            : #undef  PERROR
     120                 :            : #define PERROR(_f, _a...) VERR(-errno, _f, ##_a)
     121                 :            : 
     122                 :            : #define BUG() do {                                              \
     123                 :            :                 ERR("Aborting");                              \
     124                 :            :                 td_panic();                                     \
     125                 :            :         } while (0)
     126                 :            : 
     127                 :            : #define BUG_ON(_cond)                                           \
     128                 :            :         if (unlikely(_cond)) {                                  \
     129                 :            :                 ERR("(%s) = %ld", #_cond, (long)(_cond));     \
     130                 :            :                 BUG();                                          \
     131                 :            :         }
     132                 :            : 
     133                 :            : #define WARN_ON(_cond) ({                                       \
     134                 :            :         int __cond = _cond;                                     \
     135                 :            :         if (unlikely(__cond))                                   \
     136                 :            :                 WARN("(%s) = %ld", #_cond, (long)(_cond));    \
     137                 :            :         __cond;                                         \
     138                 :            : })
     139                 :            : 
     140                 :            : #define TREQ_SIZE(_treq) ((unsigned long)(_treq.secs) << 9)
     141                 :            : 
     142                 :            : static td_valve_request_t *
     143                 :            : valve_alloc_request(td_valve_t *valve)
     144                 :            : {
     145                 :          0 :         td_valve_request_t *req = NULL;
     146                 :            : 
     147         [ #  # ]:          0 :         if (valve->n_free)
     148                 :          0 :                 req = valve->free[--valve->n_free];
     149                 :            : 
     150                 :            :         return req;
     151                 :            : }
     152                 :            : 
     153                 :            : static void
     154                 :          0 : valve_free_request(td_valve_t *valve, td_valve_request_t *req)
     155                 :            : {
     156         [ #  # ]:          0 :         BUG_ON(valve->n_free >= ARRAY_SIZE(valve->free));
     157                 :          0 :         list_del_init(&req->entry);
     158                 :          0 :         valve->free[valve->n_free++] = req;
     159                 :          0 : }
     160                 :            : 
     161                 :            : static void
     162                 :          0 : __valve_sock_event(event_id_t id, char mode, void *private)
     163                 :            : {
     164                 :          0 :         td_valve_t *valve = private;
     165                 :            : 
     166                 :          0 :         valve_conn_receive(valve);
     167                 :            : 
     168                 :          0 :         valve_forward_stored_requests(valve);
     169                 :          0 : }
     170                 :            : 
     171                 :            : static void
     172                 :          0 : valve_set_done_pending(td_valve_t *valve)
     173                 :            : {
     174         [ #  # ]:          0 :         WARN_ON(valve->done == 0);
     175                 :          0 :         tapdisk_server_mask_event(valve->sched_id, 0);
     176                 :          0 : }
     177                 :            : 
     178                 :            : static void
     179                 :          0 : valve_clear_done_pending(td_valve_t *valve)
     180                 :            : {
     181         [ #  # ]:          0 :         WARN_ON(valve->done != 0);
     182                 :          0 :         tapdisk_server_mask_event(valve->sched_id, 1);
     183                 :          0 : }
     184                 :            : 
     185                 :            : static void
     186                 :          0 : __valve_sched_event(event_id_t id, char mode, void *private)
     187                 :            : {
     188                 :          0 :         td_valve_t *valve = private;
     189                 :            : 
     190         [ #  # ]:          0 :         if (likely(valve->done > 0))
     191                 :            :                 /* flush valve->done */
     192                 :          0 :                 valve_conn_request(valve, 0);
     193                 :          0 : }
     194                 :            : 
     195                 :            : static void
     196                 :          0 : valve_sock_close(td_valve_t *valve)
     197                 :            : {
     198         [ #  # ]:          0 :         if (valve->sock >= 0) {
     199                 :          0 :                 close(valve->sock);
     200                 :          0 :                 valve->sock = -1;
     201                 :            :         }
     202                 :            : 
     203         [ #  # ]:          0 :         if (valve->sock_id >= 0) {
     204                 :          0 :                 tapdisk_server_unregister_event(valve->sock_id);
     205                 :          0 :                 valve->sock_id = -1;
     206                 :            :         }
     207                 :            : 
     208         [ #  # ]:          0 :         if (valve->sched_id >= 0) {
     209                 :          0 :                 tapdisk_server_unregister_event(valve->sched_id);
     210                 :          0 :                 valve->sched_id = -1;
     211                 :            :         }
     212                 :          0 : }
     213                 :            : 
     214                 :            : static int
     215                 :          0 : valve_sock_open(td_valve_t *valve)
     216                 :            : {
     217                 :          0 :         struct sockaddr_un addr = { .sun_family = AF_UNIX };
     218                 :            :         int s, id, err;
     219                 :            : 
     220                 :          0 :         s = socket(AF_UNIX, SOCK_STREAM, 0);
     221         [ #  # ]:          0 :         if (s < 0) {
     222                 :          0 :                 PERROR("socket");
     223                 :          0 :                 err = -errno;
     224                 :          0 :                 goto fail;
     225                 :            :         }
     226                 :            : 
     227                 :          0 :         valve->sock = s;
     228                 :            : 
     229         [ #  # ]:          0 :         if (valve->brname[0] == '/') {
     230         [ #  # ]:          0 :                 if (unlikely(strlen(valve->brname) >= sizeof(addr.sun_path))) {
     231                 :          0 :                         ERR("socket name too long: %s\n", valve->brname);
     232                 :            :                         err = -ENAMETOOLONG;
     233                 :            :                         goto fail;
     234                 :            :                 }
     235                 :          0 :                 safe_strncpy(addr.sun_path, valve->brname, sizeof(addr.sun_path));
     236                 :            :         } else
     237                 :          0 :                 snprintf(addr.sun_path, sizeof(addr.sun_path),
     238                 :            :                          "%s/%s", TD_VALVE_SOCKDIR, valve->brname);
     239                 :            : 
     240                 :          0 :         err = connect(valve->sock, &addr, sizeof(addr));
     241         [ #  # ]:          0 :         if (err) {
     242                 :          0 :                 err = -errno;
     243                 :          0 :                 goto fail;
     244                 :            :         }
     245                 :            : 
     246                 :          0 :         id = tapdisk_server_register_event(SCHEDULER_POLL_READ_FD,
     247                 :          0 :                                            valve->sock, TV_ZERO,
     248                 :            :                                            __valve_sock_event,
     249                 :            :                                            valve);
     250         [ #  # ]:          0 :         if (id < 0) {
     251                 :            :                 err = id;
     252                 :            :                 goto fail;
     253                 :            :         }
     254                 :            : 
     255                 :          0 :         valve->sock_id = id;
     256                 :            : 
     257                 :          0 :         id = tapdisk_server_register_event(SCHEDULER_POLL_TIMEOUT,
     258                 :          0 :                                            -1, TV_ZERO,
     259                 :            :                                            __valve_sched_event,
     260                 :            :                                            valve);
     261         [ #  # ]:          0 :         if (id < 0) {
     262                 :            :                 err = id;
     263                 :            :                 goto fail;
     264                 :            :         }
     265                 :            : 
     266                 :          0 :         valve->sched_id = id;
     267                 :            : 
     268                 :          0 :         INFO("Connected to %s", addr.sun_path);
     269                 :            : 
     270                 :          0 :         valve->cred = 0;
     271                 :          0 :         valve->need = 0;
     272                 :          0 :         valve->done = 0;
     273                 :            : 
     274                 :          0 :         valve_clear_done_pending(valve);
     275                 :            : 
     276                 :          0 :         return 0;
     277                 :            : 
     278                 :            : fail:
     279                 :          0 :         valve_sock_close(valve);
     280                 :            :         return err;
     281                 :            : }
     282                 :            : 
     283                 :            : static int
     284                 :          0 : valve_sock_send(td_valve_t *valve, const void *msg, size_t size)
     285                 :            : {
     286                 :            :         ssize_t n;
     287                 :            : 
     288                 :          0 :         n = send(valve->sock, msg, size, MSG_DONTWAIT);
     289         [ #  # ]:          0 :         if (n < 0)
     290                 :          0 :                 return -errno;
     291         [ #  # ]:          0 :         if (n != size)
     292                 :            :                 return -EPROTO;
     293                 :            : 
     294                 :          0 :         return 0;
     295                 :            : }
     296                 :            : 
     297                 :            : static int
     298                 :          0 : valve_sock_recv(td_valve_t *valve, void *msg, size_t size)
     299                 :            : {
     300                 :            :         ssize_t n;
     301                 :            : 
     302                 :          0 :         n = recv(valve->sock, msg, size, MSG_DONTWAIT);
     303         [ #  # ]:          0 :         if (n < 0)
     304                 :          0 :                 return -errno;
     305                 :            : 
     306                 :          0 :         return n;
     307                 :            : }
     308                 :            : 
     309                 :            : static void
     310                 :          0 : __valve_retry_timeout(event_id_t id, char mode, void *private)
     311                 :            : {
     312                 :          0 :         td_valve_t *valve = private;
     313                 :            :         int err;
     314                 :            : 
     315                 :          0 :         err = valve_sock_open(valve);
     316         [ #  # ]:          0 :         if (!err)
     317                 :          0 :                 tapdisk_server_unregister_event(valve->retry_id);
     318                 :          0 : }
     319                 :            : 
     320                 :            : static void
     321                 :          0 : valve_schedule_retry(td_valve_t *valve)
     322                 :            : {
     323                 :            :         int id;
     324                 :            : 
     325         [ #  # ]:          0 :         BUG_ON(valve->sock_id >= 0);
     326                 :            : 
     327                 :          0 :         id = tapdisk_server_register_event(SCHEDULER_POLL_TIMEOUT,
     328                 :          0 :                                            -1, TV_SECS(TD_VALVE_CONNECT_INTERVAL),
     329                 :            :                                            __valve_retry_timeout,
     330                 :            :                                            valve);
     331         [ #  # ]:          0 :         BUG_ON(id < 0);
     332                 :            : 
     333                 :          0 :         valve->retry_id = id;
     334                 :          0 : }
     335                 :            : 
     336                 :            : static void
     337                 :          0 : valve_conn_open(td_valve_t *valve)
     338                 :            : {
     339                 :            :         int err;
     340                 :            : 
     341         [ #  # ]:          0 :         BUG_ON(valve->flags & TD_VALVE_KILLED);
     342                 :            : 
     343                 :          0 :         err = valve_sock_open(valve);
     344         [ #  # ]:          0 :         if (err) {
     345                 :          0 :                 WARN("%s: %s", valve->brname, strerror(-err));
     346                 :          0 :                 valve_schedule_retry(valve);
     347                 :            :         }
     348                 :          0 : }
     349                 :            : 
     350                 :            : static void
     351                 :          0 : valve_conn_close(td_valve_t *valve, int reset)
     352                 :            : {
     353                 :            :         td_valve_request_t *req, *next;
     354                 :            : 
     355                 :          0 :         valve_sock_close(valve);
     356                 :            : 
     357         [ #  # ]:          0 :         if (reset)
     358         [ #  # ]:          0 :                 td_valve_for_each_stored_request(req, next, valve) {
     359                 :          0 :                         td_forward_request(req->treq);
     360                 :          0 :                         valve->stats.forw++;
     361                 :          0 :                         valve_free_request(valve, req);
     362                 :            :                 }
     363                 :            : 
     364         [ #  # ]:          0 :         WARN_ON(!list_empty(&valve->stor));
     365                 :          0 : }
     366                 :            : 
     367                 :            : static void
     368                 :            : valve_conn_reset(td_valve_t *valve)
     369                 :            : {
     370                 :          0 :         valve_conn_close(valve, 1);
     371                 :          0 :         valve_conn_open(valve);
     372                 :            : }
     373                 :            : 
     374                 :            : void
     375                 :          0 : valve_conn_receive(td_valve_t *valve)
     376                 :            : {
     377                 :          0 :         unsigned long buf[32], cred = 0;
     378                 :            :         ssize_t n;
     379                 :            :         int i, err;
     380                 :            : 
     381                 :          0 :         n = valve_sock_recv(valve, buf, sizeof(buf));
     382         [ #  # ]:          0 :         if (!n) {
     383                 :            :                 err = -ECONNRESET;
     384                 :            :                 goto reset;
     385                 :            :         }
     386                 :            : 
     387         [ #  # ]:          0 :         if (n < 0) {
     388                 :          0 :                 err = n;
     389         [ #  # ]:          0 :                 if (err != -EAGAIN)
     390                 :            :                         goto reset;
     391                 :            :         }
     392                 :            : 
     393         [ #  # ]:          0 :         for (i = 0; i < n / sizeof(buf[0]); i++) {
     394         [ #  # ]:          0 :                 err = WARN_ON(buf[i] >= TD_RLB_REQUEST_MAX);
     395         [ #  # ]:          0 :                 if (err)
     396                 :            :                         goto kill;
     397                 :            : 
     398                 :          0 :                 cred += buf[i];
     399                 :            :         }
     400                 :            : 
     401         [ #  # ]:          0 :         if (cred > valve->need) {
     402                 :            :                 err = -EINVAL;
     403                 :            :                 goto reset;
     404                 :            :         }
     405                 :            : 
     406                 :          0 :         valve->cred += cred;
     407                 :          0 :         valve->need -= cred;
     408                 :            : 
     409                 :          0 :         return;
     410                 :            : 
     411                 :            : reset:
     412                 :          0 :         VERR(err, "resetting connection");
     413                 :            :         valve_conn_reset(valve);
     414                 :            :         return;
     415                 :            : 
     416                 :            : kill:
     417                 :          0 :         ERR("Killing valve.");
     418                 :            :         valve_kill(valve);
     419                 :            : }
     420                 :            : 
     421                 :            : static void
     422                 :          0 : valve_conn_request(td_valve_t *valve, unsigned long size)
     423                 :            : {
     424                 :            :         struct td_valve_req _req;
     425                 :            :         int err;
     426                 :            : 
     427                 :          0 :         _req.need    = size;
     428                 :          0 :         _req.done    = valve->done;
     429                 :            : 
     430                 :          0 :         valve->need += size;
     431                 :          0 :         valve->done  = 0;
     432                 :            : 
     433                 :          0 :         valve_clear_done_pending(valve);
     434                 :            : 
     435                 :          0 :         err = valve_sock_send(valve, &_req, sizeof(_req));
     436         [ #  # ]:          0 :         if (!err)
     437                 :          0 :                 return;
     438                 :            : 
     439                 :          0 :         VERR(err, "resetting connection");
     440                 :            :         valve_conn_reset(valve);
     441                 :            : }
     442                 :            : 
     443                 :            : static int
     444                 :          0 : valve_expend_request(td_valve_t *valve, const td_request_t treq)
     445                 :            : {
     446 [ #  # ][ #  # ]:          0 :         if (valve->flags & TD_VALVE_KILLED)
     447                 :            :                 return 0;
     448                 :            : 
     449 [ #  # ][ #  # ]:          0 :         if (valve->sock < 0)
     450                 :            :                 return 0;
     451                 :            : 
     452 [ #  # ][ #  # ]:          0 :         if (valve->cred < TREQ_SIZE(treq))
     453                 :            :                 return -EAGAIN;
     454                 :            : 
     455                 :          0 :         valve->cred -= TREQ_SIZE(treq);
     456                 :            : 
     457                 :          0 :         return 0;
     458                 :            : }
     459                 :            : 
     460                 :            : static void
     461                 :          0 : __valve_complete_treq(td_request_t treq, int error)
     462                 :            : {
     463                 :          0 :         td_valve_request_t *req = treq.cb_data;
     464                 :          0 :         td_valve_t *valve = req->valve;
     465                 :            : 
     466         [ #  # ]:          0 :         BUG_ON(req->secs < treq.secs);
     467                 :          0 :         req->secs -= treq.secs;
     468                 :            : 
     469                 :          0 :         valve->done += TREQ_SIZE(treq);
     470                 :          0 :         valve_set_done_pending(valve);
     471                 :            : 
     472                 :            :         /* Respond to original callback */
     473                 :          0 :         treq.cb = req->treq.cb;
     474                 :          0 :         treq.cb_data = req->treq.cb_data;
     475                 :          0 :         td_complete_request(treq, error);
     476                 :            : 
     477         [ #  # ]:          0 :         if (!req->secs) {
     478                 :          0 :                 valve_free_request(valve, req);
     479                 :            :         }
     480                 :          0 : }
     481                 :            : 
     482                 :            : static void
     483                 :          0 : valve_forward_stored_requests(td_valve_t *valve)
     484                 :            : {
     485                 :            :         td_valve_request_t *req, *next;
     486                 :            :         td_request_t clone;
     487                 :            :         int err;
     488                 :            : 
     489         [ #  # ]:          0 :         td_valve_for_each_stored_request(req, next, valve) {
     490                 :            : 
     491                 :          0 :                 err = valve_expend_request(valve, req->treq);
     492         [ #  # ]:          0 :                 if (err)
     493                 :            :                         break;
     494                 :            : 
     495                 :          0 :                 clone         = req->treq;
     496                 :          0 :                 clone.cb      = __valve_complete_treq;
     497                 :          0 :                 clone.cb_data = req;
     498                 :            : 
     499                 :          0 :                 list_move(&req->entry, &valve->forw);
     500                 :            :                 /* 'list_move' must be run before td_forward_request.
     501                 :            :                  * 'req' may already be freed when td_forward_request returned.
     502                 :            :                  */
     503                 :          0 :                 td_forward_request(clone);
     504                 :          0 :                 valve->stats.forw++;
     505                 :            :         }
     506                 :          0 : }
     507                 :            : 
     508                 :            : static int
     509                 :          0 : valve_store_request(td_valve_t *valve, td_request_t treq)
     510                 :            : {
     511                 :            :         td_valve_request_t *req;
     512                 :            : 
     513                 :          0 :         req = valve_alloc_request(valve);
     514         [ #  # ]:          0 :         if (!req)
     515                 :            :                 return -EBUSY;
     516                 :            : 
     517                 :          0 :         valve_conn_request(valve, TREQ_SIZE(treq));
     518                 :            : 
     519                 :          0 :         req->treq = treq;
     520                 :          0 :         req->secs = treq.secs;
     521                 :            : 
     522                 :          0 :         list_add_tail(&req->entry, &valve->stor);
     523                 :          0 :         valve->stats.stor++;
     524                 :            : 
     525                 :          0 :         return 0;
     526                 :            : }
     527                 :            : 
     528                 :            : static void
     529                 :            : valve_kill(td_valve_t *valve)
     530                 :            : {
     531                 :          0 :         valve->flags |= TD_VALVE_KILLED;
     532                 :          0 :         valve_conn_close(valve, 1);
     533                 :            : }
     534                 :            : 
     535                 :            : static void
     536                 :          0 : valve_init(td_valve_t *valve, unsigned long flags)
     537                 :            : {
     538                 :            :         int i;
     539                 :            : 
     540                 :            :         memset(valve, 0, sizeof(*valve));
     541                 :            : 
     542                 :          0 :         INIT_LIST_HEAD(&valve->stor);
     543                 :          0 :         INIT_LIST_HEAD(&valve->forw);
     544                 :            : 
     545                 :          0 :         valve->sock     = -1;
     546                 :          0 :         valve->sock_id  = -1;
     547                 :            : 
     548                 :          0 :         valve->retry_id = -1;
     549                 :          0 :         valve->sched_id = -1;
     550                 :            : 
     551                 :          0 :         valve->flags    = flags;
     552                 :            : 
     553         [ #  # ]:          0 :         for (i = ARRAY_SIZE(valve->reqv) - 1; i >= 0; i--) {
     554                 :          0 :                 td_valve_request_t *req = &valve->reqv[i];
     555                 :            : 
     556                 :          0 :                 req->valve = valve;
     557                 :          0 :                 INIT_LIST_HEAD(&req->entry);
     558                 :            : 
     559                 :          0 :                 valve_free_request(valve, req);
     560                 :            :         }
     561                 :          0 : }
     562                 :            : 
     563                 :            : static int
     564                 :          0 : td_valve_close(td_driver_t *driver)
     565                 :            : {
     566                 :          0 :         td_valve_t *valve = driver->data;
     567                 :            : 
     568         [ #  # ]:          0 :         WARN_ON(!list_empty(&valve->stor));
     569         [ #  # ]:          0 :         WARN_ON(!list_empty(&valve->forw));
     570                 :            : 
     571                 :          0 :         valve_conn_close(valve, 0);
     572                 :            : 
     573         [ #  # ]:          0 :         if (valve->brname) {
     574                 :          0 :                 free(valve->brname);
     575                 :          0 :                 valve->brname = NULL;
     576                 :            :         }
     577                 :            : 
     578                 :          0 :         return 0;
     579                 :            : }
     580                 :            : 
     581                 :            : static int
     582                 :          0 : td_valve_open(td_driver_t *driver, const char *name,
     583                 :            :               struct td_vbd_encryption *encryption, td_flag_t flags)
     584                 :            : {
     585                 :          0 :         td_valve_t *valve = driver->data;
     586                 :            :         int err;
     587                 :            : 
     588                 :          0 :         valve_init(valve, TD_VALVE_WRLIMIT);
     589                 :            : 
     590                 :          0 :         valve->brname = strdup(name);
     591         [ #  # ]:          0 :         if (!valve->brname) {
     592                 :          0 :                 err = -errno;
     593                 :            :                 goto fail;
     594                 :            :         }
     595                 :            : 
     596                 :          0 :         valve_conn_open(valve);
     597                 :            : 
     598                 :          0 :         return 0;
     599                 :            : 
     600                 :            : fail:
     601                 :          0 :         td_valve_close(driver);
     602                 :          0 :         return err;
     603                 :            : }
     604                 :            : 
     605                 :            : static void
     606                 :          0 : td_valve_queue_request(td_driver_t *driver, td_request_t treq)
     607                 :            : {
     608                 :          0 :         td_valve_t *valve = driver->data;
     609                 :            :         int err;
     610                 :            : 
     611      [ #  #  # ]:          0 :         switch (treq.op) {
     612                 :            : 
     613                 :            :         case TD_OP_READ:
     614         [ #  # ]:          0 :                 if (valve->flags & TD_VALVE_RDLIMIT)
     615                 :            :                         break;
     616                 :            : 
     617                 :            :                 goto forward;
     618                 :            : 
     619                 :            :         case TD_OP_WRITE:
     620         [ #  # ]:          0 :                 if (valve->flags & TD_VALVE_WRLIMIT)
     621                 :            :                         break;
     622                 :            : 
     623                 :            :                 goto forward;
     624                 :            : 
     625                 :            :         default:
     626                 :          0 :                 BUG();
     627                 :            :         }
     628                 :            : 
     629                 :          0 :         err = valve_expend_request(valve, treq);
     630         [ #  # ]:          0 :         if (!err)
     631                 :            :                 goto forward;
     632                 :            : 
     633                 :          0 :         err = valve_store_request(valve, treq);
     634         [ #  # ]:          0 :         if (err)
     635                 :          0 :                 td_complete_request(treq, -EBUSY);
     636                 :            : 
     637                 :          0 :         return;
     638                 :            : 
     639                 :            : forward:
     640                 :          0 :         td_forward_request(treq);
     641                 :          0 :         valve->stats.forw++;
     642                 :            : }
     643                 :            : 
     644                 :            : static int
     645                 :          0 : td_valve_get_parent_id(td_driver_t *driver, td_disk_id_t *id)
     646                 :            : {
     647                 :          0 :         return -EINVAL;
     648                 :            : }
     649                 :            : 
     650                 :            : static int
     651                 :          0 : td_valve_validate_parent(td_driver_t *driver,
     652                 :            :                          td_driver_t *parent_driver, td_flag_t flags)
     653                 :            : {
     654                 :          0 :         return -EINVAL;
     655                 :            : }
     656                 :            : 
     657                 :            : static void
     658                 :          0 : td_valve_stats(td_driver_t *driver, td_stats_t *st)
     659                 :            : {
     660                 :          0 :         td_valve_t *valve = driver->data;
     661                 :            :         td_valve_request_t *req, *next;
     662                 :            :         int n_reqs;
     663                 :            : 
     664                 :          0 :         tapdisk_stats_field(st, "bridge", "d", valve->brname);
     665                 :          0 :         tapdisk_stats_field(st, "flags", "lu", valve->flags);
     666                 :            : 
     667                 :          0 :         tapdisk_stats_field(st, "cred", "d", valve->cred);
     668                 :          0 :         tapdisk_stats_field(st, "need", "d", valve->need);
     669                 :          0 :         tapdisk_stats_field(st, "done", "d", valve->done);
     670                 :            : 
     671                 :            :         /*
     672                 :            :          * stored is [ waiting, total-waits ]
     673                 :            :          */
     674                 :            : 
     675                 :          0 :         n_reqs = 0;
     676         [ #  # ]:          0 :         td_valve_for_each_stored_request(req, next, valve)
     677                 :          0 :                 n_reqs++;
     678                 :            : 
     679                 :          0 :         tapdisk_stats_field(st, "stor", "[");
     680                 :          0 :         tapdisk_stats_val(st, "d", n_reqs);
     681                 :          0 :         tapdisk_stats_val(st, "llu", valve->stats.stor);
     682                 :          0 :         tapdisk_stats_leave(st, ']');
     683                 :            : 
     684                 :            :         /*
     685                 :            :          * forwarded is [ in-flight, total-requests ]
     686                 :            :          */
     687                 :            : 
     688                 :          0 :         n_reqs = 0;
     689         [ #  # ]:          0 :         td_valve_for_each_forwarded_request(req, next, valve)
     690                 :          0 :                 n_reqs++;
     691                 :            : 
     692                 :          0 :         tapdisk_stats_field(st, "forw", "[");
     693                 :          0 :         tapdisk_stats_val(st, "d", n_reqs);
     694                 :          0 :         tapdisk_stats_val(st, "llu", valve->stats.forw);
     695                 :          0 :         tapdisk_stats_leave(st, ']');
     696                 :          0 : }
     697                 :            : 
     698                 :            : struct tap_disk tapdisk_valve = {
     699                 :            :         .disk_type                  = "tapdisk_valve",
     700                 :            :         .flags                      = 0,
     701                 :            :         .private_data_size          = sizeof(td_valve_t),
     702                 :            :         .td_open                    = td_valve_open,
     703                 :            :         .td_close                   = td_valve_close,
     704                 :            :         .td_queue_read              = td_valve_queue_request,
     705                 :            :         .td_queue_write             = td_valve_queue_request,
     706                 :            :         .td_get_parent_id           = td_valve_get_parent_id,
     707                 :            :         .td_validate_parent         = td_valve_validate_parent,
     708                 :            :         .td_stats                   = td_valve_stats,
     709                 :            : };

Generated by: LCOV version 1.13