1163048Sru/*- 2330449Seadler * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3330449Seadler * 4163048Sru * Copyright (c) 2006 Ruslan Ermilov <ru@FreeBSD.org> 5163048Sru * All rights reserved. 6163048Sru * 7163048Sru * Redistribution and use in source and binary forms, with or without 8163048Sru * modification, are permitted provided that the following conditions 9163048Sru * are met: 10163048Sru * 1. Redistributions of source code must retain the above copyright 11163048Sru * notice, this list of conditions and the following disclaimer. 12163048Sru * 2. Redistributions in binary form must reproduce the above copyright 13163048Sru * notice, this list of conditions and the following disclaimer in the 14163048Sru * documentation and/or other materials provided with the distribution. 15163048Sru * 16163048Sru * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17163048Sru * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18163048Sru * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19163048Sru * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20163048Sru * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21163048Sru * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22163048Sru * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23163048Sru * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24163048Sru * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25163048Sru * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26163048Sru * SUCH DAMAGE. 27163048Sru */ 28163048Sru 29163048Sru#include <sys/cdefs.h> 30163048Sru__FBSDID("$FreeBSD: stable/11/sbin/geom/class/cache/geom_cache.c 330726 2018-03-10 02:15:45Z asomers $"); 31163048Sru 32163048Sru#include <errno.h> 33163048Sru#include <stdio.h> 34163048Sru#include <stdint.h> 35163048Sru#include <string.h> 36163048Sru#include <strings.h> 37163048Sru#include <libgeom.h> 38163048Sru#include <geom/cache/g_cache.h> 39163048Sru 40163048Sru#include "core/geom.h" 41163048Sru#include "misc/subr.h" 42163048Sru 43163048Sru 44163048Sruuint32_t lib_version = G_LIB_VERSION; 45163048Sruuint32_t version = G_CACHE_VERSION; 46163048Sru 47212554Spjd#define GCACHE_BLOCKSIZE "65536" 48212554Spjd#define GCACHE_SIZE "100" 49163048Sru 50163048Srustatic void cache_main(struct gctl_req *req, unsigned flags); 51163048Srustatic void cache_clear(struct gctl_req *req); 52163048Srustatic void cache_dump(struct gctl_req *req); 53163048Srustatic void cache_label(struct gctl_req *req); 54163048Sru 55163048Srustruct g_command class_commands[] = { 56212554Spjd { "clear", G_FLAG_VERBOSE, cache_main, G_NULL_OPTS, 57163048Sru "[-v] prov ..." 58163048Sru }, 59163048Sru { "configure", G_FLAG_VERBOSE, NULL, 60163048Sru { 61212554Spjd { 'b', "blocksize", "0", G_TYPE_NUMBER }, 62212554Spjd { 's', "size", "0", G_TYPE_NUMBER }, 63163048Sru G_OPT_SENTINEL 64163048Sru }, 65212554Spjd "[-v] [-b blocksize] [-s size] name" 66163048Sru }, 67163048Sru { "create", G_FLAG_VERBOSE | G_FLAG_LOADKLD, NULL, 68163048Sru { 69212554Spjd { 'b', "blocksize", GCACHE_BLOCKSIZE, G_TYPE_NUMBER }, 70212554Spjd { 's', "size", GCACHE_SIZE, G_TYPE_NUMBER }, 71163048Sru G_OPT_SENTINEL 72163048Sru }, 73212554Spjd "[-v] [-b blocksize] [-s size] name prov" 74163048Sru }, 75163048Sru { "destroy", G_FLAG_VERBOSE, NULL, 76163048Sru { 77163887Spjd { 'f', "force", NULL, G_TYPE_BOOL }, 78163048Sru G_OPT_SENTINEL 79163048Sru }, 80212554Spjd "[-fv] name ..." 81163048Sru }, 82212554Spjd { "dump", 0, cache_main, G_NULL_OPTS, 83163048Sru "prov ..." 84163048Sru }, 85163048Sru { "label", G_FLAG_VERBOSE | G_FLAG_LOADKLD, cache_main, 86163048Sru { 87212554Spjd { 'b', "blocksize", GCACHE_BLOCKSIZE, G_TYPE_NUMBER }, 88212554Spjd { 's', "size", GCACHE_SIZE, G_TYPE_NUMBER }, 89163048Sru G_OPT_SENTINEL 90163048Sru }, 91212554Spjd "[-v] [-b blocksize] [-s size] name prov" 92163048Sru }, 93212554Spjd { "reset", G_FLAG_VERBOSE, NULL, G_NULL_OPTS, 94163048Sru "[-v] name ..." 95163048Sru }, 96163048Sru { "stop", G_FLAG_VERBOSE, NULL, 97163048Sru { 98163887Spjd { 'f', "force", NULL, G_TYPE_BOOL }, 99163048Sru G_OPT_SENTINEL 100163048Sru }, 101212554Spjd "[-fv] name ..." 102163048Sru }, 103163048Sru G_CMD_SENTINEL 104163048Sru}; 105163048Sru 106163048Srustatic int verbose = 0; 107163048Sru 108163048Srustatic void 109163048Srucache_main(struct gctl_req *req, unsigned flags) 110163048Sru{ 111163048Sru const char *name; 112163048Sru 113163048Sru if ((flags & G_FLAG_VERBOSE) != 0) 114163048Sru verbose = 1; 115163048Sru 116163048Sru name = gctl_get_ascii(req, "verb"); 117163048Sru if (name == NULL) { 118163048Sru gctl_error(req, "No '%s' argument.", "verb"); 119163048Sru return; 120163048Sru } 121163048Sru if (strcmp(name, "label") == 0) 122163048Sru cache_label(req); 123163048Sru else if (strcmp(name, "clear") == 0) 124163048Sru cache_clear(req); 125163048Sru else if (strcmp(name, "dump") == 0) 126163048Sru cache_dump(req); 127163048Sru else 128163048Sru gctl_error(req, "Unknown command: %s.", name); 129163048Sru} 130163048Sru 131163048Srustatic void 132163048Srucache_label(struct gctl_req *req) 133163048Sru{ 134163048Sru struct g_cache_metadata md; 135163048Sru u_char sector[512]; 136163048Sru const char *name; 137163048Sru int error, nargs; 138163048Sru intmax_t val; 139163048Sru 140330726Sasomers bzero(sector, sizeof(sector)); 141163048Sru nargs = gctl_get_int(req, "nargs"); 142163048Sru if (nargs != 2) { 143163048Sru gctl_error(req, "Invalid number of arguments."); 144163048Sru return; 145163048Sru } 146163048Sru 147163048Sru strlcpy(md.md_magic, G_CACHE_MAGIC, sizeof(md.md_magic)); 148163048Sru md.md_version = G_CACHE_VERSION; 149163048Sru name = gctl_get_ascii(req, "arg0"); 150163048Sru strlcpy(md.md_name, name, sizeof(md.md_name)); 151163048Sru val = gctl_get_intmax(req, "blocksize"); 152163048Sru md.md_bsize = val; 153163048Sru val = gctl_get_intmax(req, "size"); 154163048Sru md.md_size = val; 155163048Sru 156163048Sru name = gctl_get_ascii(req, "arg1"); 157163048Sru md.md_provsize = g_get_mediasize(name); 158163048Sru if (md.md_provsize == 0) { 159163048Sru fprintf(stderr, "Can't get mediasize of %s: %s.\n", 160163048Sru name, strerror(errno)); 161163048Sru gctl_error(req, "Not fully done."); 162163048Sru return; 163163048Sru } 164163048Sru cache_metadata_encode(&md, sector); 165163048Sru error = g_metadata_store(name, sector, sizeof(sector)); 166163048Sru if (error != 0) { 167163048Sru fprintf(stderr, "Can't store metadata on %s: %s.\n", 168163048Sru name, strerror(error)); 169163048Sru gctl_error(req, "Not fully done."); 170163048Sru return; 171163048Sru } 172163048Sru if (verbose) 173163048Sru printf("Metadata value stored on %s.\n", name); 174163048Sru} 175163048Sru 176163048Srustatic void 177163048Srucache_clear(struct gctl_req *req) 178163048Sru{ 179163048Sru const char *name; 180163048Sru int error, i, nargs; 181163048Sru 182163048Sru nargs = gctl_get_int(req, "nargs"); 183163048Sru if (nargs < 1) { 184163048Sru gctl_error(req, "Too few arguments."); 185163048Sru return; 186163048Sru } 187163048Sru 188163048Sru for (i = 0; i < nargs; i++) { 189163048Sru name = gctl_get_ascii(req, "arg%d", i); 190163048Sru error = g_metadata_clear(name, G_CACHE_MAGIC); 191163048Sru if (error != 0) { 192163048Sru fprintf(stderr, "Can't clear metadata on %s: %s.\n", 193163048Sru name, strerror(error)); 194163048Sru gctl_error(req, "Not fully done."); 195163048Sru continue; 196163048Sru } 197163048Sru if (verbose) 198163048Sru printf("Metadata cleared on %s.\n", name); 199163048Sru } 200163048Sru} 201163048Sru 202163048Srustatic void 203163048Srucache_metadata_dump(const struct g_cache_metadata *md) 204163048Sru{ 205163048Sru 206163048Sru printf(" Magic string: %s\n", md->md_magic); 207163048Sru printf(" Metadata version: %u\n", (u_int)md->md_version); 208163048Sru printf(" Device name: %s\n", md->md_name); 209163048Sru printf(" Block size: %u\n", (u_int)md->md_bsize); 210163048Sru printf(" Cache size: %u\n", (u_int)md->md_size); 211163048Sru printf(" Provider size: %ju\n", (uintmax_t)md->md_provsize); 212163048Sru} 213163048Sru 214163048Srustatic void 215163048Srucache_dump(struct gctl_req *req) 216163048Sru{ 217163048Sru struct g_cache_metadata md, tmpmd; 218163048Sru const char *name; 219163048Sru int error, i, nargs; 220163048Sru 221163048Sru nargs = gctl_get_int(req, "nargs"); 222163048Sru if (nargs < 1) { 223163048Sru gctl_error(req, "Too few arguments."); 224163048Sru return; 225163048Sru } 226163048Sru 227163048Sru for (i = 0; i < nargs; i++) { 228163048Sru name = gctl_get_ascii(req, "arg%d", i); 229163048Sru error = g_metadata_read(name, (u_char *)&tmpmd, sizeof(tmpmd), 230163048Sru G_CACHE_MAGIC); 231163048Sru if (error != 0) { 232163048Sru fprintf(stderr, "Can't read metadata from %s: %s.\n", 233163048Sru name, strerror(error)); 234163048Sru gctl_error(req, "Not fully done."); 235163048Sru continue; 236163048Sru } 237163048Sru cache_metadata_decode((u_char *)&tmpmd, &md); 238163048Sru printf("Metadata on %s:\n", name); 239163048Sru cache_metadata_dump(&md); 240163048Sru printf("\n"); 241163048Sru } 242163048Sru} 243