Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/lib/geom/cache/geom_cache.c
35068 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2006 Ruslan Ermilov <[email protected]>
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
* 1. Redistributions of source code must retain the above copyright
11
* notice, this list of conditions and the following disclaimer.
12
* 2. Redistributions in binary form must reproduce the above copyright
13
* notice, this list of conditions and the following disclaimer in the
14
* documentation and/or other materials provided with the distribution.
15
*
16
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26
* SUCH DAMAGE.
27
*/
28
29
#include <sys/cdefs.h>
30
#include <errno.h>
31
#include <stdio.h>
32
#include <stdint.h>
33
#include <string.h>
34
#include <strings.h>
35
#include <libgeom.h>
36
#include <geom/cache/g_cache.h>
37
38
#include "core/geom.h"
39
#include "misc/subr.h"
40
41
42
uint32_t lib_version = G_LIB_VERSION;
43
uint32_t version = G_CACHE_VERSION;
44
45
#define GCACHE_BLOCKSIZE "65536"
46
#define GCACHE_SIZE "100"
47
48
static void cache_main(struct gctl_req *req, unsigned flags);
49
static void cache_clear(struct gctl_req *req);
50
static void cache_dump(struct gctl_req *req);
51
static void cache_label(struct gctl_req *req);
52
53
struct g_command class_commands[] = {
54
{ "clear", G_FLAG_VERBOSE, cache_main, G_NULL_OPTS,
55
"[-v] prov ..."
56
},
57
{ "configure", G_FLAG_VERBOSE, NULL,
58
{
59
{ 'b', "blocksize", "0", G_TYPE_NUMBER },
60
{ 's', "size", "0", G_TYPE_NUMBER },
61
G_OPT_SENTINEL
62
},
63
"[-v] [-b blocksize] [-s size] name"
64
},
65
{ "create", G_FLAG_VERBOSE | G_FLAG_LOADKLD, NULL,
66
{
67
{ 'b', "blocksize", GCACHE_BLOCKSIZE, G_TYPE_NUMBER },
68
{ 's', "size", GCACHE_SIZE, G_TYPE_NUMBER },
69
G_OPT_SENTINEL
70
},
71
"[-v] [-b blocksize] [-s size] name prov"
72
},
73
{ "destroy", G_FLAG_VERBOSE, NULL,
74
{
75
{ 'f', "force", NULL, G_TYPE_BOOL },
76
G_OPT_SENTINEL
77
},
78
"[-fv] name ..."
79
},
80
{ "dump", 0, cache_main, G_NULL_OPTS,
81
"prov ..."
82
},
83
{ "label", G_FLAG_VERBOSE | G_FLAG_LOADKLD, cache_main,
84
{
85
{ 'b', "blocksize", GCACHE_BLOCKSIZE, G_TYPE_NUMBER },
86
{ 's', "size", GCACHE_SIZE, G_TYPE_NUMBER },
87
G_OPT_SENTINEL
88
},
89
"[-v] [-b blocksize] [-s size] name prov"
90
},
91
{ "reset", G_FLAG_VERBOSE, NULL, G_NULL_OPTS,
92
"[-v] name ..."
93
},
94
{ "stop", G_FLAG_VERBOSE, NULL,
95
{
96
{ 'f', "force", NULL, G_TYPE_BOOL },
97
G_OPT_SENTINEL
98
},
99
"[-fv] name ..."
100
},
101
G_CMD_SENTINEL
102
};
103
104
static int verbose = 0;
105
106
static void
107
cache_main(struct gctl_req *req, unsigned flags)
108
{
109
const char *name;
110
111
if ((flags & G_FLAG_VERBOSE) != 0)
112
verbose = 1;
113
114
name = gctl_get_ascii(req, "verb");
115
if (name == NULL) {
116
gctl_error(req, "No '%s' argument.", "verb");
117
return;
118
}
119
if (strcmp(name, "label") == 0)
120
cache_label(req);
121
else if (strcmp(name, "clear") == 0)
122
cache_clear(req);
123
else if (strcmp(name, "dump") == 0)
124
cache_dump(req);
125
else
126
gctl_error(req, "Unknown command: %s.", name);
127
}
128
129
static void
130
cache_label(struct gctl_req *req)
131
{
132
struct g_cache_metadata md;
133
u_char sector[512];
134
const char *name;
135
int error, nargs;
136
intmax_t val;
137
138
bzero(sector, sizeof(sector));
139
nargs = gctl_get_int(req, "nargs");
140
if (nargs != 2) {
141
gctl_error(req, "Invalid number of arguments.");
142
return;
143
}
144
145
strlcpy(md.md_magic, G_CACHE_MAGIC, sizeof(md.md_magic));
146
md.md_version = G_CACHE_VERSION;
147
name = gctl_get_ascii(req, "arg0");
148
strlcpy(md.md_name, name, sizeof(md.md_name));
149
val = gctl_get_intmax(req, "blocksize");
150
md.md_bsize = val;
151
val = gctl_get_intmax(req, "size");
152
md.md_size = val;
153
154
name = gctl_get_ascii(req, "arg1");
155
md.md_provsize = g_get_mediasize(name);
156
if (md.md_provsize == 0) {
157
fprintf(stderr, "Can't get mediasize of %s: %s.\n",
158
name, strerror(errno));
159
gctl_error(req, "Not fully done.");
160
return;
161
}
162
cache_metadata_encode(&md, sector);
163
error = g_metadata_store(name, sector, sizeof(sector));
164
if (error != 0) {
165
fprintf(stderr, "Can't store metadata on %s: %s.\n",
166
name, strerror(error));
167
gctl_error(req, "Not fully done.");
168
return;
169
}
170
if (verbose)
171
printf("Metadata value stored on %s.\n", name);
172
}
173
174
static void
175
cache_clear(struct gctl_req *req)
176
{
177
const char *name;
178
int error, i, nargs;
179
180
nargs = gctl_get_int(req, "nargs");
181
if (nargs < 1) {
182
gctl_error(req, "Too few arguments.");
183
return;
184
}
185
186
for (i = 0; i < nargs; i++) {
187
name = gctl_get_ascii(req, "arg%d", i);
188
error = g_metadata_clear(name, G_CACHE_MAGIC);
189
if (error != 0) {
190
fprintf(stderr, "Can't clear metadata on %s: %s.\n",
191
name, strerror(error));
192
gctl_error(req, "Not fully done.");
193
continue;
194
}
195
if (verbose)
196
printf("Metadata cleared on %s.\n", name);
197
}
198
}
199
200
static void
201
cache_metadata_dump(const struct g_cache_metadata *md)
202
{
203
204
printf(" Magic string: %s\n", md->md_magic);
205
printf(" Metadata version: %u\n", (u_int)md->md_version);
206
printf(" Device name: %s\n", md->md_name);
207
printf(" Block size: %u\n", (u_int)md->md_bsize);
208
printf(" Cache size: %u\n", (u_int)md->md_size);
209
printf(" Provider size: %ju\n", (uintmax_t)md->md_provsize);
210
}
211
212
static void
213
cache_dump(struct gctl_req *req)
214
{
215
struct g_cache_metadata md, tmpmd;
216
const char *name;
217
int error, i, nargs;
218
219
nargs = gctl_get_int(req, "nargs");
220
if (nargs < 1) {
221
gctl_error(req, "Too few arguments.");
222
return;
223
}
224
225
for (i = 0; i < nargs; i++) {
226
name = gctl_get_ascii(req, "arg%d", i);
227
error = g_metadata_read(name, (u_char *)&tmpmd, sizeof(tmpmd),
228
G_CACHE_MAGIC);
229
if (error != 0) {
230
fprintf(stderr, "Can't read metadata from %s: %s.\n",
231
name, strerror(error));
232
gctl_error(req, "Not fully done.");
233
continue;
234
}
235
cache_metadata_decode((u_char *)&tmpmd, &md);
236
printf("Metadata on %s:\n", name);
237
cache_metadata_dump(&md);
238
printf("\n");
239
}
240
}
241
242