dm_target_linear.c revision 1.20 1 /* $NetBSD: dm_target_linear.c,v 1.20 2019/12/02 16:10:34 tkusumi Exp $ */
2
3 /*
4 * Copyright (c) 2008 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Adam Hamsik.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31 #include <sys/cdefs.h>
32 __KERNEL_RCSID(0, "$NetBSD: dm_target_linear.c,v 1.20 2019/12/02 16:10:34 tkusumi Exp $");
33
34 /*
35 * This file implements initial version of device-mapper dklinear target.
36 */
37
38 #include <sys/types.h>
39 #include <sys/param.h>
40
41 #include <sys/buf.h>
42 #include <sys/kmem.h>
43 #include <sys/vnode.h>
44 #include <sys/lwp.h>
45
46 #include <machine/int_fmtio.h>
47
48 #include "dm.h"
49
50 /*
51 * Allocate target specific config data, and link them to table.
52 * This function is called only when, flags is not READONLY and
53 * therefore we can add things to pdev list. This should not a
54 * problem because this routine is called only from dm_table_load_ioctl.
55 * @argv[0] is name,
56 * @argv[1] is physical data offset.
57 */
58 int
59 dm_target_linear_init(dm_dev_t * dmv, void **target_config, char *params)
60 {
61 dm_target_linear_config_t *tlc;
62 dm_pdev_t *dmp;
63
64 char **ap, *argv[3];
65
66 if (params == NULL)
67 return EINVAL;
68
69 /*
70 * Parse a string, containing tokens delimited by white space,
71 * into an argument vector
72 */
73 for (ap = argv; ap < &argv[2] &&
74 (*ap = strsep(¶ms, " \t")) != NULL;) {
75 if (**ap != '\0')
76 ap++;
77 }
78
79 aprint_debug("Linear target init function called %s--%s!!\n",
80 argv[0], argv[1]);
81
82 /* Insert dmp to global pdev list */
83 if ((dmp = dm_pdev_insert(argv[0])) == NULL)
84 return ENOENT;
85
86 tlc = kmem_alloc(sizeof(dm_target_linear_config_t), KM_SLEEP);
87 tlc->pdev = dmp;
88 tlc->offset = atoi(argv[1]);
89
90 *target_config = tlc;
91
92 return 0;
93 }
94
95 /*
96 * Status routine is called to get params string, which is target
97 * specific. When dm_table_status_ioctl is called with flag
98 * DM_STATUS_TABLE_FLAG I have to sent params string back.
99 */
100 char *
101 dm_target_linear_status(void *target_config)
102 {
103 dm_target_linear_config_t *tlc;
104 char *params;
105 tlc = target_config;
106
107 aprint_debug("Linear target status function called\n");
108
109 params = kmem_alloc(DM_MAX_PARAMS_SIZE, KM_SLEEP);
110 aprint_normal("%s %" PRIu64, tlc->pdev->name, tlc->offset);
111 snprintf(params, DM_MAX_PARAMS_SIZE, "%s %" PRIu64,
112 tlc->pdev->name, tlc->offset);
113
114 return params;
115 }
116
117 /*
118 * Do IO operation, called from dmstrategy routine.
119 */
120 int
121 dm_target_linear_strategy(dm_table_entry_t * table_en, struct buf * bp)
122 {
123 dm_target_linear_config_t *tlc;
124
125 tlc = table_en->target_config;
126
127 /* printf("Linear target read function called %" PRIu64 "!!\n",
128 tlc->offset);*/
129
130 bp->b_blkno += tlc->offset;
131
132 VOP_STRATEGY(tlc->pdev->pdev_vnode, bp);
133
134 return 0;
135
136 }
137
138 /*
139 * Sync underlying disk caches.
140 */
141 int
142 dm_target_linear_sync(dm_table_entry_t * table_en)
143 {
144 int cmd;
145 dm_target_linear_config_t *tlc;
146
147 tlc = table_en->target_config;
148
149 cmd = 1;
150
151 return VOP_IOCTL(tlc->pdev->pdev_vnode, DIOCCACHESYNC, &cmd,
152 FREAD|FWRITE, kauth_cred_get());
153 }
154
155 /*
156 * Destroy target specific data. Decrement table pdevs.
157 */
158 int
159 dm_target_linear_destroy(dm_table_entry_t * table_en)
160 {
161
162 /*
163 * Destroy function is called for every target even if it
164 * doesn't have target_config.
165 */
166 if (table_en->target_config == NULL)
167 goto out;
168
169 dm_target_linear_config_t *tlc = table_en->target_config;
170 table_en->target_config = NULL;
171
172 /* Decrement pdev ref counter if 0 remove it */
173 dm_pdev_decr(tlc->pdev);
174
175 kmem_free(tlc, sizeof(*tlc));
176
177 out:
178 /* Unbusy target so we can unload it */
179 dm_target_unbusy(table_en->target);
180 return 0;
181 }
182
183 /* Add this target pdev dependencies to prop_array_t */
184 int
185 dm_target_linear_deps(dm_table_entry_t * table_en, prop_array_t prop_array)
186 {
187 dm_target_linear_config_t *tlc;
188
189 if (table_en->target_config == NULL)
190 return ENOENT;
191
192 tlc = table_en->target_config;
193
194 prop_array_add_uint64(prop_array,
195 (uint64_t) tlc->pdev->pdev_vnode->v_rdev);
196
197 return 0;
198 }
199
200 /*
201 * Register upcall device.
202 * Linear target doesn't need any upcall devices but other targets like
203 * mirror, snapshot, multipath, stripe will use this functionality.
204 */
205 int
206 dm_target_linear_upcall(dm_table_entry_t * table_en, struct buf * bp)
207 {
208 return 0;
209 }
210
211 /*
212 * Query physical block size of this target
213 * For a linear target this is just the sector size of the underlying device
214 */
215 int
216 dm_target_linear_secsize(dm_table_entry_t * table_en, unsigned *secsizep)
217 {
218 dm_target_linear_config_t *tlc;
219 unsigned secsize;
220
221 secsize = 0;
222
223 tlc = table_en->target_config;
224 if (tlc != NULL)
225 secsize = tlc->pdev->pdev_secsize;
226
227 *secsizep = secsize;
228
229 return 0;
230 }
231
232 /*
233 * Transform char s to uint64_t offset number.
234 */
235 uint64_t
236 atoi(const char *s)
237 {
238 uint64_t n;
239 n = 0;
240
241 while (*s != '\0') {
242 if (!isdigit(*s))
243 break;
244
245 n = (10 * n) + (*s - '0');
246 s++;
247 }
248
249 return n;
250 }
251