xref: /spdk/lib/bdev/bdev_zone.c (revision 877573897ad52be4fa8989f7617bd655b87e05c4)
1  /*   SPDX-License-Identifier: BSD-3-Clause
2   *   Copyright (C) 2019 Intel Corporation.
3   *   All rights reserved.
4   */
5  
6  #include "spdk/stdinc.h"
7  
8  #include "spdk/bdev_zone.h"
9  #include "spdk/bdev_module.h"
10  #include "spdk/likely.h"
11  
12  #include "bdev_internal.h"
13  
14  uint64_t
15  spdk_bdev_get_zone_size(const struct spdk_bdev *bdev)
16  {
17  	return bdev->zone_size;
18  }
19  
20  uint64_t
21  spdk_bdev_get_num_zones(const struct spdk_bdev *bdev)
22  {
23  	return bdev->zone_size ? bdev->blockcnt / bdev->zone_size : 0;
24  }
25  
26  uint64_t
27  spdk_bdev_get_zone_id(const struct spdk_bdev *bdev, uint64_t offset_blocks)
28  {
29  	uint64_t zslba;
30  
31  	if (spdk_likely(spdk_u64_is_pow2(bdev->zone_size))) {
32  		uint64_t zone_mask = bdev->zone_size - 1;
33  		zslba = offset_blocks & ~zone_mask;
34  	} else {
35  		/* integer division */
36  		zslba = (offset_blocks / bdev->zone_size) * bdev->zone_size;
37  	}
38  
39  	return zslba;
40  }
41  
42  uint32_t
43  spdk_bdev_get_max_zone_append_size(const struct spdk_bdev *bdev)
44  {
45  	return bdev->max_zone_append_size;
46  }
47  
48  uint32_t
49  spdk_bdev_get_max_open_zones(const struct spdk_bdev *bdev)
50  {
51  	return bdev->max_open_zones;
52  }
53  
54  uint32_t
55  spdk_bdev_get_max_active_zones(const struct spdk_bdev *bdev)
56  {
57  	return bdev->max_active_zones;
58  }
59  
60  uint32_t
61  spdk_bdev_get_optimal_open_zones(const struct spdk_bdev *bdev)
62  {
63  	return bdev->optimal_open_zones;
64  }
65  
66  int
67  spdk_bdev_get_zone_info(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
68  			uint64_t zone_id, size_t num_zones, struct spdk_bdev_zone_info *info,
69  			spdk_bdev_io_completion_cb cb, void *cb_arg)
70  {
71  	struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(desc);
72  	struct spdk_bdev_io *bdev_io;
73  	struct spdk_bdev_channel *channel = spdk_io_channel_get_ctx(ch);
74  
75  	bdev_io = bdev_channel_get_io(channel);
76  	if (!bdev_io) {
77  		return -ENOMEM;
78  	}
79  
80  	bdev_io->internal.ch = channel;
81  	bdev_io->internal.desc = desc;
82  	bdev_io->type = SPDK_BDEV_IO_TYPE_GET_ZONE_INFO;
83  	bdev_io->u.zone_mgmt.zone_id = zone_id;
84  	bdev_io->u.zone_mgmt.num_zones = num_zones;
85  	bdev_io->u.zone_mgmt.buf = info;
86  	bdev_io_init(bdev_io, bdev, cb_arg, cb);
87  
88  	bdev_io_submit(bdev_io);
89  	return 0;
90  }
91  
92  int
93  spdk_bdev_zone_management(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
94  			  uint64_t zone_id, enum spdk_bdev_zone_action action,
95  			  spdk_bdev_io_completion_cb cb, void *cb_arg)
96  {
97  	struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(desc);
98  	struct spdk_bdev_io *bdev_io;
99  	struct spdk_bdev_channel *channel = spdk_io_channel_get_ctx(ch);
100  
101  	bdev_io = bdev_channel_get_io(channel);
102  	if (!bdev_io) {
103  		return -ENOMEM;
104  	}
105  
106  	bdev_io->internal.ch = channel;
107  	bdev_io->internal.desc = desc;
108  	bdev_io->type = SPDK_BDEV_IO_TYPE_ZONE_MANAGEMENT;
109  	bdev_io->u.zone_mgmt.zone_action = action;
110  	bdev_io->u.zone_mgmt.zone_id = zone_id;
111  	bdev_io->u.zone_mgmt.num_zones = 1;
112  	bdev_io_init(bdev_io, bdev, cb_arg, cb);
113  
114  	bdev_io_submit(bdev_io);
115  	return 0;
116  }
117  
118  static int
119  zone_bdev_append_with_md(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
120  			 void *buf, void *md_buf, uint64_t zone_id, uint64_t num_blocks,
121  			 spdk_bdev_io_completion_cb cb, void *cb_arg)
122  {
123  	struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(desc);
124  	struct spdk_bdev_io *bdev_io;
125  	struct spdk_bdev_channel *channel = spdk_io_channel_get_ctx(ch);
126  
127  	bdev_io = bdev_channel_get_io(channel);
128  	if (!bdev_io) {
129  		return -ENOMEM;
130  	}
131  
132  	bdev_io->internal.ch = channel;
133  	bdev_io->internal.desc = desc;
134  	bdev_io->type = SPDK_BDEV_IO_TYPE_ZONE_APPEND;
135  	bdev_io->u.bdev.iovs = &bdev_io->iov;
136  	bdev_io->u.bdev.iovs[0].iov_base = buf;
137  	bdev_io->u.bdev.iovs[0].iov_len = num_blocks * bdev->blocklen;
138  	bdev_io->u.bdev.iovcnt = 1;
139  	bdev_io->u.bdev.md_buf = md_buf;
140  	bdev_io->u.bdev.num_blocks = num_blocks;
141  	bdev_io->u.bdev.offset_blocks = zone_id;
142  	bdev_io_init(bdev_io, bdev, cb_arg, cb);
143  
144  	bdev_io_submit(bdev_io);
145  	return 0;
146  }
147  
148  int
149  spdk_bdev_zone_append(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
150  		      void *buf, uint64_t start_lba, uint64_t num_blocks,
151  		      spdk_bdev_io_completion_cb cb, void *cb_arg)
152  {
153  	return zone_bdev_append_with_md(desc, ch, buf, NULL, start_lba, num_blocks,
154  					cb, cb_arg);
155  }
156  
157  int
158  spdk_bdev_zone_append_with_md(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
159  			      void *buf, void *md, uint64_t start_lba, uint64_t num_blocks,
160  			      spdk_bdev_io_completion_cb cb, void *cb_arg)
161  {
162  	return zone_bdev_append_with_md(desc, ch, buf, md, start_lba, num_blocks,
163  					cb, cb_arg);
164  }
165  
166  int
167  spdk_bdev_zone_appendv_with_md(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
168  			       struct iovec *iov, int iovcnt, void *md_buf, uint64_t zone_id,
169  			       uint64_t num_blocks, spdk_bdev_io_completion_cb cb,
170  			       void *cb_arg)
171  {
172  	struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(desc);
173  	struct spdk_bdev_io *bdev_io;
174  	struct spdk_bdev_channel *channel = spdk_io_channel_get_ctx(ch);
175  
176  	bdev_io = bdev_channel_get_io(channel);
177  	if (!bdev_io) {
178  		return -ENOMEM;
179  	}
180  
181  	bdev_io->internal.ch = channel;
182  	bdev_io->internal.desc = desc;
183  	bdev_io->type = SPDK_BDEV_IO_TYPE_ZONE_APPEND;
184  	bdev_io->u.bdev.iovs = iov;
185  	bdev_io->u.bdev.iovcnt = iovcnt;
186  	bdev_io->u.bdev.md_buf = md_buf;
187  	bdev_io->u.bdev.num_blocks = num_blocks;
188  	bdev_io->u.bdev.offset_blocks = zone_id;
189  	bdev_io_init(bdev_io, bdev, cb_arg, cb);
190  
191  	bdev_io_submit(bdev_io);
192  	return 0;
193  }
194  
195  int
196  spdk_bdev_zone_appendv(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
197  		       struct iovec *iovs, int iovcnt, uint64_t zone_id, uint64_t num_blocks,
198  		       spdk_bdev_io_completion_cb cb, void *cb_arg)
199  {
200  	return spdk_bdev_zone_appendv_with_md(desc, ch, iovs, iovcnt, NULL, zone_id, num_blocks,
201  					      cb, cb_arg);
202  }
203  
204  uint64_t
205  spdk_bdev_io_get_append_location(struct spdk_bdev_io *bdev_io)
206  {
207  	return bdev_io->u.bdev.offset_blocks;
208  }
209