xref: /spdk/lib/bdev/bdev_zone.c (revision 927f1fd57bd004df581518466ec4c1b8083e5d23)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright (c) Intel Corporation.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include "spdk/stdinc.h"
35 
36 #include "spdk/bdev_zone.h"
37 #include "spdk/bdev_module.h"
38 #include "spdk/likely.h"
39 
40 #include "bdev_internal.h"
41 
42 uint64_t
43 spdk_bdev_get_zone_size(const struct spdk_bdev *bdev)
44 {
45 	return bdev->zone_size;
46 }
47 
48 uint64_t
49 spdk_bdev_get_num_zones(const struct spdk_bdev *bdev)
50 {
51 	return bdev->zone_size ? bdev->blockcnt / bdev->zone_size : 0;
52 }
53 
54 uint64_t
55 spdk_bdev_get_zone_id(const struct spdk_bdev *bdev, uint64_t offset_blocks)
56 {
57 	uint64_t zslba;
58 
59 	if (spdk_likely(spdk_u64_is_pow2(bdev->zone_size))) {
60 		uint64_t zone_mask = bdev->zone_size - 1;
61 		zslba = offset_blocks & ~zone_mask;
62 	} else {
63 		/* integer division */
64 		zslba = (offset_blocks / bdev->zone_size) * bdev->zone_size;
65 	}
66 
67 	return zslba;
68 }
69 
70 uint32_t
71 spdk_bdev_get_max_zone_append_size(const struct spdk_bdev *bdev)
72 {
73 	return bdev->max_zone_append_size;
74 }
75 
76 uint32_t
77 spdk_bdev_get_max_open_zones(const struct spdk_bdev *bdev)
78 {
79 	return bdev->max_open_zones;
80 }
81 
82 uint32_t
83 spdk_bdev_get_max_active_zones(const struct spdk_bdev *bdev)
84 {
85 	return bdev->max_active_zones;
86 }
87 
88 uint32_t
89 spdk_bdev_get_optimal_open_zones(const struct spdk_bdev *bdev)
90 {
91 	return bdev->optimal_open_zones;
92 }
93 
94 int
95 spdk_bdev_get_zone_info(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
96 			uint64_t zone_id, size_t num_zones, struct spdk_bdev_zone_info *info,
97 			spdk_bdev_io_completion_cb cb, void *cb_arg)
98 {
99 	struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(desc);
100 	struct spdk_bdev_io *bdev_io;
101 	struct spdk_bdev_channel *channel = spdk_io_channel_get_ctx(ch);
102 
103 	bdev_io = bdev_channel_get_io(channel);
104 	if (!bdev_io) {
105 		return -ENOMEM;
106 	}
107 
108 	bdev_io->internal.ch = channel;
109 	bdev_io->internal.desc = desc;
110 	bdev_io->type = SPDK_BDEV_IO_TYPE_GET_ZONE_INFO;
111 	bdev_io->u.zone_mgmt.zone_id = zone_id;
112 	bdev_io->u.zone_mgmt.num_zones = num_zones;
113 	bdev_io->u.zone_mgmt.buf = info;
114 	bdev_io_init(bdev_io, bdev, cb_arg, cb);
115 
116 	bdev_io_submit(bdev_io);
117 	return 0;
118 }
119 
120 int
121 spdk_bdev_zone_management(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
122 			  uint64_t zone_id, enum spdk_bdev_zone_action action,
123 			  spdk_bdev_io_completion_cb cb, void *cb_arg)
124 {
125 	struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(desc);
126 	struct spdk_bdev_io *bdev_io;
127 	struct spdk_bdev_channel *channel = spdk_io_channel_get_ctx(ch);
128 
129 	bdev_io = bdev_channel_get_io(channel);
130 	if (!bdev_io) {
131 		return -ENOMEM;
132 	}
133 
134 	bdev_io->internal.ch = channel;
135 	bdev_io->internal.desc = desc;
136 	bdev_io->type = SPDK_BDEV_IO_TYPE_ZONE_MANAGEMENT;
137 	bdev_io->u.zone_mgmt.zone_action = action;
138 	bdev_io->u.zone_mgmt.zone_id = zone_id;
139 	bdev_io->u.zone_mgmt.num_zones = 1;
140 	bdev_io_init(bdev_io, bdev, cb_arg, cb);
141 
142 	bdev_io_submit(bdev_io);
143 	return 0;
144 }
145 
146 static int
147 zone_bdev_append_with_md(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
148 			 void *buf, void *md_buf, uint64_t zone_id, uint64_t num_blocks,
149 			 spdk_bdev_io_completion_cb cb, void *cb_arg)
150 {
151 	struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(desc);
152 	struct spdk_bdev_io *bdev_io;
153 	struct spdk_bdev_channel *channel = spdk_io_channel_get_ctx(ch);
154 
155 	bdev_io = bdev_channel_get_io(channel);
156 	if (!bdev_io) {
157 		return -ENOMEM;
158 	}
159 
160 	bdev_io->internal.ch = channel;
161 	bdev_io->internal.desc = desc;
162 	bdev_io->type = SPDK_BDEV_IO_TYPE_ZONE_APPEND;
163 	bdev_io->u.bdev.iovs = &bdev_io->iov;
164 	bdev_io->u.bdev.iovs[0].iov_base = buf;
165 	bdev_io->u.bdev.iovs[0].iov_len = num_blocks * bdev->blocklen;
166 	bdev_io->u.bdev.iovcnt = 1;
167 	bdev_io->u.bdev.md_buf = md_buf;
168 	bdev_io->u.bdev.num_blocks = num_blocks;
169 	bdev_io->u.bdev.offset_blocks = zone_id;
170 	bdev_io_init(bdev_io, bdev, cb_arg, cb);
171 
172 	bdev_io_submit(bdev_io);
173 	return 0;
174 }
175 
176 int
177 spdk_bdev_zone_append(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
178 		      void *buf, uint64_t start_lba, uint64_t num_blocks,
179 		      spdk_bdev_io_completion_cb cb, void *cb_arg)
180 {
181 	return zone_bdev_append_with_md(desc, ch, buf, NULL, start_lba, num_blocks,
182 					cb, cb_arg);
183 }
184 
185 int
186 spdk_bdev_zone_append_with_md(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
187 			      void *buf, void *md, uint64_t start_lba, uint64_t num_blocks,
188 			      spdk_bdev_io_completion_cb cb, void *cb_arg)
189 {
190 	return zone_bdev_append_with_md(desc, ch, buf, md, start_lba, num_blocks,
191 					cb, cb_arg);
192 }
193 
194 int
195 spdk_bdev_zone_appendv_with_md(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
196 			       struct iovec *iov, int iovcnt, void *md_buf, uint64_t zone_id,
197 			       uint64_t num_blocks, spdk_bdev_io_completion_cb cb,
198 			       void *cb_arg)
199 {
200 	struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(desc);
201 	struct spdk_bdev_io *bdev_io;
202 	struct spdk_bdev_channel *channel = spdk_io_channel_get_ctx(ch);
203 
204 	bdev_io = bdev_channel_get_io(channel);
205 	if (!bdev_io) {
206 		return -ENOMEM;
207 	}
208 
209 	bdev_io->internal.ch = channel;
210 	bdev_io->internal.desc = desc;
211 	bdev_io->type = SPDK_BDEV_IO_TYPE_ZONE_APPEND;
212 	bdev_io->u.bdev.iovs = iov;
213 	bdev_io->u.bdev.iovcnt = iovcnt;
214 	bdev_io->u.bdev.md_buf = md_buf;
215 	bdev_io->u.bdev.num_blocks = num_blocks;
216 	bdev_io->u.bdev.offset_blocks = zone_id;
217 	bdev_io_init(bdev_io, bdev, cb_arg, cb);
218 
219 	bdev_io_submit(bdev_io);
220 	return 0;
221 }
222 
223 int
224 spdk_bdev_zone_appendv(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
225 		       struct iovec *iovs, int iovcnt, uint64_t zone_id, uint64_t num_blocks,
226 		       spdk_bdev_io_completion_cb cb, void *cb_arg)
227 {
228 	return spdk_bdev_zone_appendv_with_md(desc, ch, iovs, iovcnt, NULL, zone_id, num_blocks,
229 					      cb, cb_arg);
230 }
231 
232 uint64_t
233 spdk_bdev_io_get_append_location(struct spdk_bdev_io *bdev_io)
234 {
235 	return bdev_io->u.bdev.offset_blocks;
236 }
237