examples/vhost_blk: use common macro for minimum
[dpdk.git] / examples / vhost_blk / vhost_blk_compat.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2019 Intel Corporation
3  */
4
5 #ifndef _VHOST_BLK_COMPAT_H_
6 #define _VHOST_BLK_COMPAT_H_
7
8 #include <sys/uio.h>
9 #include <stdint.h>
10 #include <linux/virtio_blk.h>
11 #include <linux/virtio_ring.h>
12
13 #include <rte_vhost.h>
14 #include "vhost_blk.h"
15 #include "blk_spec.h"
16
17 #define VHOST_MAX_VQUEUES       256
18 #define SPDK_VHOST_MAX_VQ_SIZE  1024
19
20 #define VHOST_USER_GET_CONFIG   24
21 #define VHOST_USER_SET_CONFIG   25
22
23 static int
24 vhost_blk_get_config(struct vhost_block_dev *bdev, uint8_t *config,
25                           uint32_t len)
26 {
27         struct virtio_blk_config blkcfg;
28         uint32_t blk_size;
29         uint64_t blkcnt;
30
31         if (bdev == NULL) {
32                 /* We can't just return -1 here as this GET_CONFIG message might
33                  * be caused by a QEMU VM reboot. Returning -1 will indicate an
34                  * error to QEMU, who might then decide to terminate itself.
35                  * We don't want that. A simple reboot shouldn't break the
36                  * system.
37                  *
38                  * Presenting a block device with block size 0 and block count 0
39                  * doesn't cause any problems on QEMU side and the virtio-pci
40                  * device is even still available inside the VM, but there will
41                  * be no block device created for it - the kernel drivers will
42                  * silently reject it.
43                  */
44                 blk_size = 0;
45                 blkcnt = 0;
46         } else {
47                 blk_size = bdev->blocklen;
48                 blkcnt = bdev->blockcnt;
49         }
50
51         memset(&blkcfg, 0, sizeof(blkcfg));
52         blkcfg.blk_size = blk_size;
53         /* minimum I/O size in blocks */
54         blkcfg.min_io_size = 1;
55         /* expressed in 512 Bytes sectors */
56         blkcfg.capacity = (blkcnt * blk_size) / 512;
57         /* QEMU can overwrite this value when started */
58         blkcfg.num_queues = VHOST_MAX_VQUEUES;
59
60         fprintf(stdout, "block device:blk_size = %d, blkcnt = %"PRIx64"\n",
61                 blk_size, blkcnt);
62
63         memcpy(config, &blkcfg, RTE_MIN(len, sizeof(blkcfg)));
64
65         return 0;
66 }
67
68 static enum rte_vhost_msg_result
69 extern_vhost_pre_msg_handler(int vid, void *_msg)
70 {
71         char path[PATH_MAX];
72         struct vhost_blk_ctrlr *ctrlr;
73         struct vhost_user_msg *msg = _msg;
74         int ret;
75
76         ret = rte_vhost_get_ifname(vid, path, PATH_MAX);
77         if (ret) {
78                 fprintf(stderr, "Cannot get socket name\n");
79                 return -1;
80         }
81
82         ctrlr = vhost_blk_ctrlr_find(path);
83         if (!ctrlr) {
84                 fprintf(stderr, "Controller is not ready\n");
85                 return -1;
86         }
87
88         switch ((int)msg->request) {
89         case VHOST_USER_GET_VRING_BASE:
90         case VHOST_USER_SET_VRING_BASE:
91         case VHOST_USER_SET_VRING_ADDR:
92         case VHOST_USER_SET_VRING_NUM:
93         case VHOST_USER_SET_VRING_KICK:
94         case VHOST_USER_SET_VRING_CALL:
95         case VHOST_USER_SET_MEM_TABLE:
96                 break;
97         case VHOST_USER_GET_CONFIG: {
98                 int rc = 0;
99
100                 rc = vhost_blk_get_config(ctrlr->bdev,
101                                           msg->payload.cfg.region,
102                                           msg->payload.cfg.size);
103                 if (rc != 0)
104                         msg->size = 0;
105
106                 return RTE_VHOST_MSG_RESULT_REPLY;
107         }
108         case VHOST_USER_SET_CONFIG:
109         default:
110                 break;
111         }
112
113         return RTE_VHOST_MSG_RESULT_NOT_HANDLED;
114 }
115
116 static enum rte_vhost_msg_result
117 extern_vhost_post_msg_handler(int vid, void *_msg)
118 {
119         char path[PATH_MAX];
120         struct vhost_blk_ctrlr *ctrlr;
121         struct vhost_user_msg *msg = _msg;
122         int ret;
123
124         ret = rte_vhost_get_ifname(vid, path, PATH_MAX);
125         if (ret) {
126                 fprintf(stderr, "Cannot get socket name\n");
127                 return -1;
128         }
129
130         ctrlr = vhost_blk_ctrlr_find(path);
131         if (!ctrlr) {
132                 fprintf(stderr, "Controller is not ready\n");
133                 return -1;
134         }
135
136         switch (msg->request) {
137         case VHOST_USER_SET_FEATURES:
138         case VHOST_USER_SET_VRING_KICK:
139         default:
140                 break;
141         }
142
143         return RTE_VHOST_MSG_RESULT_NOT_HANDLED;
144 }
145
146 struct rte_vhost_user_extern_ops g_extern_vhost_ops = {
147         .pre_msg_handle = extern_vhost_pre_msg_handler,
148         .post_msg_handle = extern_vhost_post_msg_handler,
149 };
150
151 void
152 vhost_session_install_rte_compat_hooks(uint32_t vid)
153 {
154         int rc;
155
156         rc = rte_vhost_extern_callback_register(vid, &g_extern_vhost_ops, NULL);
157         if (rc != 0)
158                 fprintf(stderr,
159                         "rte_vhost_extern_callback_register() failed for vid = %d\n",
160                         vid);
161 }
162
163 void
164 vhost_dev_install_rte_compat_hooks(const char *path)
165 {
166         uint64_t protocol_features = 0;
167
168         rte_vhost_driver_get_protocol_features(path, &protocol_features);
169         protocol_features |= (1ULL << VHOST_USER_PROTOCOL_F_CONFIG);
170         protocol_features |= (1ULL << VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD);
171         rte_vhost_driver_set_protocol_features(path, protocol_features);
172 }
173
174 #endif