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