1148382Spjd/*- 2148382Spjd * Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org> 3148382Spjd * All rights reserved. 4148382Spjd * 5148382Spjd * Redistribution and use in source and binary forms, with or without 6148382Spjd * modification, are permitted provided that the following conditions 7148382Spjd * are met: 8148382Spjd * 1. Redistributions of source code must retain the above copyright 9148382Spjd * notice, this list of conditions and the following disclaimer. 10148382Spjd * 2. Redistributions in binary form must reproduce the above copyright 11148382Spjd * notice, this list of conditions and the following disclaimer in the 12148382Spjd * documentation and/or other materials provided with the distribution. 13155174Spjd * 14148382Spjd * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 15148382Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16148382Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17148382Spjd * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 18148382Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19148382Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20148382Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21148382Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22148382Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23148382Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24148382Spjd * SUCH DAMAGE. 25148382Spjd */ 26148382Spjd 27154473Spjd#include <sys/cdefs.h> 28154473Spjd__FBSDID("$FreeBSD$"); 29154473Spjd 30148382Spjd#include <sys/param.h> 31148382Spjd#include <sys/bio.h> 32148382Spjd#include <sys/kernel.h> 33148382Spjd#include <sys/limits.h> 34148382Spjd#include <sys/malloc.h> 35148382Spjd#include <sys/queue.h> 36148382Spjd#include <sys/sysctl.h> 37148382Spjd#include <sys/systm.h> 38148382Spjd 39148382Spjd#include <geom/geom.h> 40148382Spjd 41148382Spjd 42148382Spjd#define G_ZERO_CLASS_NAME "ZERO" 43148382Spjd 44254936Smavstatic int g_zero_clear_sysctl(SYSCTL_HANDLER_ARGS); 45254936Smav 46148382SpjdSYSCTL_DECL(_kern_geom); 47227309Sedstatic SYSCTL_NODE(_kern_geom, OID_AUTO, zero, CTLFLAG_RW, 0, 48227309Sed "GEOM_ZERO stuff"); 49153251Spjdstatic int g_zero_clear = 1; 50254936SmavSYSCTL_PROC(_kern_geom_zero, OID_AUTO, clear, CTLTYPE_INT|CTLFLAG_RW, 51254936Smav &g_zero_clear, 0, g_zero_clear_sysctl, "I", "Clear read data buffer"); 52153251Spjdstatic int g_zero_byte = 0; 53153251SpjdSYSCTL_INT(_kern_geom_zero, OID_AUTO, byte, CTLFLAG_RW, &g_zero_byte, 0, 54153251Spjd "Byte (octet) value to clear the buffers with"); 55148382Spjd 56254936Smavstatic struct g_provider *gpp; 57254936Smav 58254936Smavstatic int 59254936Smavg_zero_clear_sysctl(SYSCTL_HANDLER_ARGS) 60254936Smav{ 61254936Smav int error; 62254936Smav 63254936Smav error = sysctl_handle_int(oidp, &g_zero_clear, 0, req); 64254936Smav if (error != 0 || req->newptr == NULL) 65254936Smav return (error); 66254936Smav if (gpp == NULL) 67254936Smav return (ENXIO); 68254936Smav if (g_zero_clear) 69254936Smav gpp->flags &= ~G_PF_ACCEPT_UNMAPPED; 70254936Smav else 71254936Smav gpp->flags |= G_PF_ACCEPT_UNMAPPED; 72254936Smav return (0); 73254936Smav} 74254936Smav 75148382Spjdstatic void 76148382Spjdg_zero_start(struct bio *bp) 77148382Spjd{ 78148382Spjd int error = ENXIO; 79148382Spjd 80148382Spjd switch (bp->bio_cmd) { 81148382Spjd case BIO_READ: 82254936Smav if (g_zero_clear && (bp->bio_flags & BIO_UNMAPPED) == 0) 83153251Spjd memset(bp->bio_data, g_zero_byte, bp->bio_length); 84148382Spjd /* FALLTHROUGH */ 85148382Spjd case BIO_DELETE: 86148382Spjd case BIO_WRITE: 87148382Spjd bp->bio_completed = bp->bio_length; 88148382Spjd error = 0; 89148382Spjd break; 90148382Spjd case BIO_GETATTR: 91148382Spjd default: 92148382Spjd error = EOPNOTSUPP; 93148382Spjd break; 94148382Spjd } 95148382Spjd g_io_deliver(bp, error); 96148382Spjd} 97148382Spjd 98148382Spjdstatic void 99148382Spjdg_zero_init(struct g_class *mp) 100148382Spjd{ 101148382Spjd struct g_geom *gp; 102148382Spjd struct g_provider *pp; 103148382Spjd 104148382Spjd g_topology_assert(); 105148382Spjd gp = g_new_geomf(mp, "gzero"); 106148382Spjd gp->start = g_zero_start; 107148382Spjd gp->access = g_std_access; 108254936Smav gpp = pp = g_new_providerf(gp, "%s", gp->name); 109260385Sscottl pp->flags |= G_PF_DIRECT_SEND | G_PF_DIRECT_RECEIVE; 110254936Smav if (!g_zero_clear) 111254936Smav pp->flags |= G_PF_ACCEPT_UNMAPPED; 112148382Spjd pp->mediasize = 1152921504606846976LLU; 113148382Spjd pp->sectorsize = 512; 114148382Spjd g_error_provider(pp, 0); 115148382Spjd} 116148382Spjd 117148382Spjdstatic int 118148382Spjdg_zero_destroy_geom(struct gctl_req *req __unused, struct g_class *mp __unused, 119148382Spjd struct g_geom *gp) 120148382Spjd{ 121148382Spjd struct g_provider *pp; 122148382Spjd 123148382Spjd g_topology_assert(); 124148382Spjd if (gp == NULL) 125148382Spjd return (0); 126148382Spjd pp = LIST_FIRST(&gp->provider); 127148382Spjd if (pp == NULL) 128148382Spjd return (0); 129148382Spjd if (pp->acr > 0 || pp->acw > 0 || pp->ace > 0) 130148382Spjd return (EBUSY); 131254936Smav gpp = NULL; 132148382Spjd g_wither_geom(gp, ENXIO); 133207877Sjh return (0); 134148382Spjd} 135148382Spjd 136148382Spjdstatic struct g_class g_zero_class = { 137148382Spjd .name = G_ZERO_CLASS_NAME, 138148382Spjd .version = G_VERSION, 139148382Spjd .init = g_zero_init, 140148382Spjd .destroy_geom = g_zero_destroy_geom 141148382Spjd}; 142148382Spjd 143148382SpjdDECLARE_GEOM_CLASS(g_zero_class, g_zero); 144