1565bc101SPawel Jakub Dawidek /*- 2565bc101SPawel Jakub Dawidek * Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org> 3565bc101SPawel Jakub Dawidek * All rights reserved. 4565bc101SPawel Jakub Dawidek * 5565bc101SPawel Jakub Dawidek * Redistribution and use in source and binary forms, with or without 6565bc101SPawel Jakub Dawidek * modification, are permitted provided that the following conditions 7565bc101SPawel Jakub Dawidek * are met: 8565bc101SPawel Jakub Dawidek * 1. Redistributions of source code must retain the above copyright 9565bc101SPawel Jakub Dawidek * notice, this list of conditions and the following disclaimer. 10565bc101SPawel Jakub Dawidek * 2. Redistributions in binary form must reproduce the above copyright 11565bc101SPawel Jakub Dawidek * notice, this list of conditions and the following disclaimer in the 12565bc101SPawel Jakub Dawidek * documentation and/or other materials provided with the distribution. 13565bc101SPawel Jakub Dawidek * 14565bc101SPawel Jakub Dawidek * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 15565bc101SPawel Jakub Dawidek * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16565bc101SPawel Jakub Dawidek * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17565bc101SPawel Jakub Dawidek * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 18565bc101SPawel Jakub Dawidek * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19565bc101SPawel Jakub Dawidek * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20565bc101SPawel Jakub Dawidek * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21565bc101SPawel Jakub Dawidek * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22565bc101SPawel Jakub Dawidek * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23565bc101SPawel Jakub Dawidek * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24565bc101SPawel Jakub Dawidek * SUCH DAMAGE. 25565bc101SPawel Jakub Dawidek */ 26565bc101SPawel Jakub Dawidek 27a1c10dcbSPawel Jakub Dawidek #include <sys/cdefs.h> 28a1c10dcbSPawel Jakub Dawidek __FBSDID("$FreeBSD$"); 29a1c10dcbSPawel Jakub Dawidek 30565bc101SPawel Jakub Dawidek #include <sys/param.h> 31565bc101SPawel Jakub Dawidek #include <sys/bio.h> 32565bc101SPawel Jakub Dawidek #include <sys/kernel.h> 33565bc101SPawel Jakub Dawidek #include <sys/limits.h> 34565bc101SPawel Jakub Dawidek #include <sys/malloc.h> 35565bc101SPawel Jakub Dawidek #include <sys/queue.h> 36565bc101SPawel Jakub Dawidek #include <sys/sysctl.h> 37565bc101SPawel Jakub Dawidek #include <sys/systm.h> 38565bc101SPawel Jakub Dawidek 39565bc101SPawel Jakub Dawidek #include <geom/geom.h> 40565bc101SPawel Jakub Dawidek 41565bc101SPawel Jakub Dawidek 42565bc101SPawel Jakub Dawidek #define G_ZERO_CLASS_NAME "ZERO" 43565bc101SPawel Jakub Dawidek 443843eba8SAlexander Motin static int g_zero_clear_sysctl(SYSCTL_HANDLER_ARGS); 453843eba8SAlexander Motin 46565bc101SPawel Jakub Dawidek SYSCTL_DECL(_kern_geom); 476472ac3dSEd Schouten static SYSCTL_NODE(_kern_geom, OID_AUTO, zero, CTLFLAG_RW, 0, 486472ac3dSEd Schouten "GEOM_ZERO stuff"); 4924e1fdcdSPawel Jakub Dawidek static int g_zero_clear = 1; 503843eba8SAlexander Motin SYSCTL_PROC(_kern_geom_zero, OID_AUTO, clear, CTLTYPE_INT|CTLFLAG_RW, 513843eba8SAlexander Motin &g_zero_clear, 0, g_zero_clear_sysctl, "I", "Clear read data buffer"); 5224e1fdcdSPawel Jakub Dawidek static int g_zero_byte = 0; 5324e1fdcdSPawel Jakub Dawidek SYSCTL_INT(_kern_geom_zero, OID_AUTO, byte, CTLFLAG_RW, &g_zero_byte, 0, 5424e1fdcdSPawel Jakub Dawidek "Byte (octet) value to clear the buffers with"); 55565bc101SPawel Jakub Dawidek 563843eba8SAlexander Motin static struct g_provider *gpp; 573843eba8SAlexander Motin 583843eba8SAlexander Motin static int 593843eba8SAlexander Motin g_zero_clear_sysctl(SYSCTL_HANDLER_ARGS) 603843eba8SAlexander Motin { 613843eba8SAlexander Motin int error; 623843eba8SAlexander Motin 633843eba8SAlexander Motin error = sysctl_handle_int(oidp, &g_zero_clear, 0, req); 643843eba8SAlexander Motin if (error != 0 || req->newptr == NULL) 653843eba8SAlexander Motin return (error); 663843eba8SAlexander Motin if (gpp == NULL) 673843eba8SAlexander Motin return (ENXIO); 683843eba8SAlexander Motin if (g_zero_clear) 693843eba8SAlexander Motin gpp->flags &= ~G_PF_ACCEPT_UNMAPPED; 703843eba8SAlexander Motin else 713843eba8SAlexander Motin gpp->flags |= G_PF_ACCEPT_UNMAPPED; 723843eba8SAlexander Motin return (0); 733843eba8SAlexander Motin } 743843eba8SAlexander Motin 75565bc101SPawel Jakub Dawidek static void 76565bc101SPawel Jakub Dawidek g_zero_start(struct bio *bp) 77565bc101SPawel Jakub Dawidek { 78565bc101SPawel Jakub Dawidek int error = ENXIO; 79565bc101SPawel Jakub Dawidek 80565bc101SPawel Jakub Dawidek switch (bp->bio_cmd) { 81565bc101SPawel Jakub Dawidek case BIO_READ: 823843eba8SAlexander Motin if (g_zero_clear && (bp->bio_flags & BIO_UNMAPPED) == 0) 8324e1fdcdSPawel Jakub Dawidek memset(bp->bio_data, g_zero_byte, bp->bio_length); 84565bc101SPawel Jakub Dawidek /* FALLTHROUGH */ 85565bc101SPawel Jakub Dawidek case BIO_DELETE: 86565bc101SPawel Jakub Dawidek case BIO_WRITE: 87565bc101SPawel Jakub Dawidek bp->bio_completed = bp->bio_length; 88565bc101SPawel Jakub Dawidek error = 0; 89565bc101SPawel Jakub Dawidek break; 90565bc101SPawel Jakub Dawidek case BIO_GETATTR: 91565bc101SPawel Jakub Dawidek default: 92565bc101SPawel Jakub Dawidek error = EOPNOTSUPP; 93565bc101SPawel Jakub Dawidek break; 94565bc101SPawel Jakub Dawidek } 95565bc101SPawel Jakub Dawidek g_io_deliver(bp, error); 96565bc101SPawel Jakub Dawidek } 97565bc101SPawel Jakub Dawidek 98565bc101SPawel Jakub Dawidek static void 99565bc101SPawel Jakub Dawidek g_zero_init(struct g_class *mp) 100565bc101SPawel Jakub Dawidek { 101565bc101SPawel Jakub Dawidek struct g_geom *gp; 102565bc101SPawel Jakub Dawidek struct g_provider *pp; 103565bc101SPawel Jakub Dawidek 104565bc101SPawel Jakub Dawidek g_topology_assert(); 105565bc101SPawel Jakub Dawidek gp = g_new_geomf(mp, "gzero"); 106565bc101SPawel Jakub Dawidek gp->start = g_zero_start; 107565bc101SPawel Jakub Dawidek gp->access = g_std_access; 1083843eba8SAlexander Motin gpp = pp = g_new_providerf(gp, "%s", gp->name); 109*40ea77a0SAlexander Motin pp->flags |= G_PF_DIRECT_SEND | G_PF_DIRECT_RECEIVE; 1103843eba8SAlexander Motin if (!g_zero_clear) 1113843eba8SAlexander Motin pp->flags |= G_PF_ACCEPT_UNMAPPED; 112565bc101SPawel Jakub Dawidek pp->mediasize = 1152921504606846976LLU; 113565bc101SPawel Jakub Dawidek pp->sectorsize = 512; 114565bc101SPawel Jakub Dawidek g_error_provider(pp, 0); 115565bc101SPawel Jakub Dawidek } 116565bc101SPawel Jakub Dawidek 117565bc101SPawel Jakub Dawidek static int 118565bc101SPawel Jakub Dawidek g_zero_destroy_geom(struct gctl_req *req __unused, struct g_class *mp __unused, 119565bc101SPawel Jakub Dawidek struct g_geom *gp) 120565bc101SPawel Jakub Dawidek { 121565bc101SPawel Jakub Dawidek struct g_provider *pp; 122565bc101SPawel Jakub Dawidek 123565bc101SPawel Jakub Dawidek g_topology_assert(); 124565bc101SPawel Jakub Dawidek if (gp == NULL) 125565bc101SPawel Jakub Dawidek return (0); 126565bc101SPawel Jakub Dawidek pp = LIST_FIRST(&gp->provider); 127565bc101SPawel Jakub Dawidek if (pp == NULL) 128565bc101SPawel Jakub Dawidek return (0); 129565bc101SPawel Jakub Dawidek if (pp->acr > 0 || pp->acw > 0 || pp->ace > 0) 130565bc101SPawel Jakub Dawidek return (EBUSY); 1313843eba8SAlexander Motin gpp = NULL; 132565bc101SPawel Jakub Dawidek g_wither_geom(gp, ENXIO); 1335a279fc5SJaakko Heinonen return (0); 134565bc101SPawel Jakub Dawidek } 135565bc101SPawel Jakub Dawidek 136565bc101SPawel Jakub Dawidek static struct g_class g_zero_class = { 137565bc101SPawel Jakub Dawidek .name = G_ZERO_CLASS_NAME, 138565bc101SPawel Jakub Dawidek .version = G_VERSION, 139565bc101SPawel Jakub Dawidek .init = g_zero_init, 140565bc101SPawel Jakub Dawidek .destroy_geom = g_zero_destroy_geom 141565bc101SPawel Jakub Dawidek }; 142565bc101SPawel Jakub Dawidek 143565bc101SPawel Jakub Dawidek DECLARE_GEOM_CLASS(g_zero_class, g_zero); 144