xref: /spdk/lib/blob/blob_bs_dev.c (revision 3299bf6d5a3e5dbc4fcda51ed9a15d0f870476b6)
1 /*   SPDX-License-Identifier: BSD-3-Clause
2  *   Copyright (C) 2018 Intel Corporation.
3  *   All rights reserved.
4  *   Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
5  */
6 
7 #include "spdk/stdinc.h"
8 #include "spdk/blob.h"
9 #include "spdk/log.h"
10 #include "spdk/likely.h"
11 #include "blobstore.h"
12 
13 static void
14 blob_bs_dev_write(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, void *payload,
15 		  uint64_t lba, uint32_t lba_count,
16 		  struct spdk_bs_dev_cb_args *cb_args)
17 {
18 	cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, -EPERM);
19 	assert(false);
20 }
21 
22 static void
23 blob_bs_dev_writev(struct spdk_bs_dev *dev, struct spdk_io_channel *channel,
24 		   struct iovec *iov, int iovcnt,
25 		   uint64_t lba, uint32_t lba_count,
26 		   struct spdk_bs_dev_cb_args *cb_args)
27 {
28 	cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, -EPERM);
29 	assert(false);
30 }
31 
32 static void
33 blob_bs_dev_writev_ext(struct spdk_bs_dev *dev, struct spdk_io_channel *channel,
34 		       struct iovec *iov, int iovcnt,
35 		       uint64_t lba, uint32_t lba_count,
36 		       struct spdk_bs_dev_cb_args *cb_args,
37 		       struct spdk_blob_ext_io_opts *ext_opts)
38 {
39 	cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, -EPERM);
40 	assert(false);
41 }
42 
43 static void
44 blob_bs_dev_write_zeroes(struct spdk_bs_dev *dev, struct spdk_io_channel *channel,
45 			 uint64_t lba, uint64_t lba_count,
46 			 struct spdk_bs_dev_cb_args *cb_args)
47 {
48 	cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, -EPERM);
49 	assert(false);
50 }
51 
52 static void
53 blob_bs_dev_unmap(struct spdk_bs_dev *dev, struct spdk_io_channel *channel,
54 		  uint64_t lba, uint64_t lba_count,
55 		  struct spdk_bs_dev_cb_args *cb_args)
56 {
57 	cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, -EPERM);
58 	assert(false);
59 }
60 
61 static void
62 blob_bs_dev_read_cpl(void *cb_arg, int bserrno)
63 {
64 	struct spdk_bs_dev_cb_args *cb_args = (struct spdk_bs_dev_cb_args *)cb_arg;
65 
66 	cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, bserrno);
67 }
68 
69 static inline void
70 zero_trailing_bytes(struct spdk_blob_bs_dev *b, struct iovec *iov, int iovcnt,
71 		    uint64_t lba, uint32_t *lba_count)
72 {
73 	uint32_t zero_lba_count;
74 	uint64_t zero_bytes, zero_len;
75 	uint64_t payload_bytes;
76 	uint64_t valid_bytes;
77 	void *zero_start;
78 	struct iovec *i;
79 
80 	if (spdk_likely(lba + *lba_count <= b->bs_dev.blockcnt)) {
81 		return;
82 	}
83 
84 	/* Figure out how many bytes in the payload will need to be zeroed. */
85 	zero_lba_count = spdk_min(*lba_count, lba + *lba_count - b->bs_dev.blockcnt);
86 	zero_bytes = zero_lba_count * (uint64_t)b->bs_dev.blocklen;
87 
88 	payload_bytes = *lba_count * (uint64_t)b->bs_dev.blocklen;
89 	valid_bytes = payload_bytes - zero_bytes;
90 
91 	i = iov;
92 	while (zero_bytes > 0) {
93 		if (i->iov_len > valid_bytes) {
94 			zero_start = i->iov_base + valid_bytes;
95 			zero_len = spdk_min(payload_bytes, i->iov_len - valid_bytes);
96 			memset(zero_start, 0, zero_bytes);
97 			valid_bytes = 0;
98 			zero_bytes -= zero_len;
99 		}
100 		valid_bytes -= spdk_min(valid_bytes, i->iov_len);
101 		payload_bytes -= spdk_min(payload_bytes, i->iov_len);
102 		i++;
103 	}
104 
105 	*lba_count -= zero_lba_count;
106 }
107 
108 static inline void
109 blob_bs_dev_read(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, void *payload,
110 		 uint64_t lba, uint32_t lba_count, struct spdk_bs_dev_cb_args *cb_args)
111 {
112 	struct spdk_blob_bs_dev *b = (struct spdk_blob_bs_dev *)dev;
113 	struct iovec iov;
114 
115 	iov.iov_base = payload;
116 	iov.iov_len = lba_count * b->bs_dev.blocklen;
117 	/* The backing blob may be smaller than this blob, so zero any trailing bytes. */
118 	zero_trailing_bytes(b, &iov, 1, lba, &lba_count);
119 
120 	spdk_blob_io_read(b->blob, channel, payload, lba, lba_count,
121 			  blob_bs_dev_read_cpl, cb_args);
122 }
123 
124 static inline void
125 blob_bs_dev_readv(struct spdk_bs_dev *dev, struct spdk_io_channel *channel,
126 		  struct iovec *iov, int iovcnt,
127 		  uint64_t lba, uint32_t lba_count, struct spdk_bs_dev_cb_args *cb_args)
128 {
129 	struct spdk_blob_bs_dev *b = (struct spdk_blob_bs_dev *)dev;
130 
131 	/* The backing blob may be smaller than this blob, so zero any trailing bytes. */
132 	zero_trailing_bytes(b, iov, iovcnt, lba, &lba_count);
133 
134 	spdk_blob_io_readv(b->blob, channel, iov, iovcnt, lba, lba_count,
135 			   blob_bs_dev_read_cpl, cb_args);
136 }
137 
138 static inline void
139 blob_bs_dev_readv_ext(struct spdk_bs_dev *dev, struct spdk_io_channel *channel,
140 		      struct iovec *iov, int iovcnt,
141 		      uint64_t lba, uint32_t lba_count, struct spdk_bs_dev_cb_args *cb_args,
142 		      struct spdk_blob_ext_io_opts *ext_opts)
143 {
144 	struct spdk_blob_bs_dev *b = (struct spdk_blob_bs_dev *)dev;
145 
146 	/* The backing blob may be smaller than this blob, so zero any trailing bytes. */
147 	zero_trailing_bytes(b, iov, iovcnt, lba, &lba_count);
148 
149 	spdk_blob_io_readv_ext(b->blob, channel, iov, iovcnt, lba, lba_count,
150 			       blob_bs_dev_read_cpl, cb_args, ext_opts);
151 }
152 
153 static void
154 blob_bs_dev_destroy_cpl(void *cb_arg, int bserrno)
155 {
156 	if (bserrno != 0) {
157 		SPDK_ERRLOG("Error on blob_bs_dev destroy: %d", bserrno);
158 	}
159 
160 	/* Free blob_bs_dev */
161 	free(cb_arg);
162 }
163 
164 static void
165 blob_bs_dev_destroy(struct spdk_bs_dev *bs_dev)
166 {
167 	struct spdk_blob_bs_dev *b = (struct spdk_blob_bs_dev *)bs_dev;
168 
169 	spdk_blob_close(b->blob, blob_bs_dev_destroy_cpl, b);
170 }
171 
172 static bool
173 blob_bs_is_zeroes(struct spdk_bs_dev *dev, uint64_t lba, uint64_t lba_count)
174 {
175 	struct spdk_blob_bs_dev *b = (struct spdk_blob_bs_dev *)dev;
176 	struct spdk_blob *blob = b->blob;
177 	bool is_valid_range;
178 
179 	assert(lba == bs_cluster_to_lba(blob->bs, bs_lba_to_cluster(blob->bs, lba)));
180 	assert(lba_count == bs_dev_byte_to_lba(dev, blob->bs->cluster_sz));
181 
182 	if (bs_io_unit_is_allocated(blob, lba)) {
183 		return false;
184 	}
185 
186 	assert(blob->back_bs_dev != NULL);
187 	is_valid_range = blob->back_bs_dev->is_range_valid(blob->back_bs_dev, lba, lba_count);
188 	return is_valid_range && blob->back_bs_dev->is_zeroes(blob->back_bs_dev,
189 			bs_io_unit_to_back_dev_lba(blob, lba),
190 			bs_io_unit_to_back_dev_lba(blob, lba_count));
191 }
192 
193 static bool
194 blob_bs_is_range_valid(struct spdk_bs_dev *dev, uint64_t lba, uint64_t lba_count)
195 {
196 	struct spdk_blob_bs_dev *b = (struct spdk_blob_bs_dev *)dev;
197 	struct spdk_blob *blob = b->blob;
198 	uint64_t	io_units_per_cluster;
199 
200 	/* The lba here is supposed to be the first lba of cluster. lba_count
201 	 * will typically be fixed e.g. 8192 for 4MiB cluster. */
202 	assert(lba_count == blob->bs->cluster_sz / dev->blocklen);
203 	assert(lba % lba_count == 0);
204 
205 	io_units_per_cluster = blob->bs->io_units_per_cluster;
206 
207 	/* A blob will either have:
208 	* - no backing bs_bdev (normal thick blob), or
209 	* - zeroes backing bs_bdev (thin provisioned blob), or
210 	* - blob backing bs_bdev (e.g snapshot)
211 	* It may be possible that backing bs_bdev has lesser number of clusters
212 	* than the child lvol blob because lvol blob has been expanded after
213 	* taking snapshot. In such a case, page will be outside the cluster io_unit
214 	* range of the backing dev. Always return true for zeroes backing bdev. */
215 	return lba < blob->active.num_clusters * io_units_per_cluster;
216 }
217 
218 static bool
219 blob_bs_translate_lba(struct spdk_bs_dev *dev, uint64_t lba, uint64_t *base_lba)
220 {
221 	struct spdk_blob_bs_dev *b = (struct spdk_blob_bs_dev *)dev;
222 	struct spdk_blob *blob = b->blob;
223 	bool is_valid_range;
224 
225 	assert(base_lba != NULL);
226 	if (bs_io_unit_is_allocated(blob, lba)) {
227 		*base_lba = bs_blob_io_unit_to_lba(blob, lba);
228 		return true;
229 	}
230 
231 	assert(blob->back_bs_dev != NULL);
232 	/* Since here we don't get lba_count directly, passing lba_count derived
233 	 * from cluster_sz which typically happens for other calls like is_zeroes
234 	 * in CoW path. */
235 	is_valid_range = blob->back_bs_dev->is_range_valid(blob->back_bs_dev, lba,
236 			 bs_dev_byte_to_lba(blob->back_bs_dev, blob->bs->cluster_sz));
237 	return is_valid_range && blob->back_bs_dev->translate_lba(blob->back_bs_dev,
238 			bs_io_unit_to_back_dev_lba(blob, lba),
239 			base_lba);
240 }
241 
242 static bool
243 blob_bs_is_degraded(struct spdk_bs_dev *dev)
244 {
245 	struct spdk_blob_bs_dev *b = (struct spdk_blob_bs_dev *)dev;
246 
247 	return spdk_blob_is_degraded(b->blob);
248 }
249 
250 struct spdk_bs_dev *
251 bs_create_blob_bs_dev(struct spdk_blob *blob)
252 {
253 	struct spdk_blob_bs_dev  *b;
254 
255 	b = calloc(1, sizeof(*b));
256 	if (b == NULL) {
257 		return NULL;
258 	}
259 	/* snapshot blob */
260 	b->bs_dev.blockcnt = blob->active.num_clusters * blob->bs->io_units_per_cluster;
261 	b->bs_dev.blocklen = spdk_bs_get_io_unit_size(blob->bs);
262 	b->bs_dev.create_channel = NULL;
263 	b->bs_dev.destroy_channel = NULL;
264 	b->bs_dev.destroy = blob_bs_dev_destroy;
265 	b->bs_dev.write = blob_bs_dev_write;
266 	b->bs_dev.writev = blob_bs_dev_writev;
267 	b->bs_dev.writev_ext = blob_bs_dev_writev_ext;
268 	b->bs_dev.read = blob_bs_dev_read;
269 	b->bs_dev.readv = blob_bs_dev_readv;
270 	b->bs_dev.readv_ext = blob_bs_dev_readv_ext;
271 	b->bs_dev.write_zeroes = blob_bs_dev_write_zeroes;
272 	b->bs_dev.unmap = blob_bs_dev_unmap;
273 	b->bs_dev.is_zeroes = blob_bs_is_zeroes;
274 	b->bs_dev.is_range_valid = blob_bs_is_range_valid;
275 	b->bs_dev.translate_lba = blob_bs_translate_lba;
276 	b->bs_dev.is_degraded = blob_bs_is_degraded;
277 	b->blob = blob;
278 
279 	return &b->bs_dev;
280 }
281