geom_ctl.c revision 105068
1105068Sphk/*- 2105068Sphk * Copyright (c) 2002 Poul-Henning Kamp 3105068Sphk * Copyright (c) 2002 Networks Associates Technology, Inc. 4105068Sphk * All rights reserved. 5105068Sphk * 6105068Sphk * This software was developed for the FreeBSD Project by Poul-Henning Kamp 7105068Sphk * and NAI Labs, the Security Research Division of Network Associates, Inc. 8105068Sphk * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the 9105068Sphk * DARPA CHATS research program. 10105068Sphk * 11105068Sphk * Redistribution and use in source and binary forms, with or without 12105068Sphk * modification, are permitted provided that the following conditions 13105068Sphk * are met: 14105068Sphk * 1. Redistributions of source code must retain the above copyright 15105068Sphk * notice, this list of conditions and the following disclaimer. 16105068Sphk * 2. Redistributions in binary form must reproduce the above copyright 17105068Sphk * notice, this list of conditions and the following disclaimer in the 18105068Sphk * documentation and/or other materials provided with the distribution. 19105068Sphk * 3. The names of the authors may not be used to endorse or promote 20105068Sphk * products derived from this software without specific prior written 21105068Sphk * permission. 22105068Sphk * 23105068Sphk * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 24105068Sphk * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25105068Sphk * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26105068Sphk * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 27105068Sphk * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28105068Sphk * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29105068Sphk * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30105068Sphk * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31105068Sphk * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32105068Sphk * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33105068Sphk * SUCH DAMAGE. 34105068Sphk * 35105068Sphk * $FreeBSD: head/sys/geom/geom_ctl.c 105068 2002-10-13 20:33:33Z phk $ 36105068Sphk */ 37105068Sphk 38105068Sphk#include "opt_geom.h" 39105068Sphk 40105068Sphk#include <sys/param.h> 41105068Sphk#include <sys/systm.h> 42105068Sphk#include <sys/kernel.h> 43105068Sphk#include <sys/sysctl.h> 44105068Sphk#include <sys/bio.h> 45105068Sphk#include <sys/conf.h> 46105068Sphk#include <sys/disk.h> 47105068Sphk#include <sys/malloc.h> 48105068Sphk#include <sys/sysctl.h> 49105068Sphk#include <sys/stdint.h> 50105068Sphk 51105068Sphk#include <sys/lock.h> 52105068Sphk#include <sys/mutex.h> 53105068Sphk#include <geom/geom.h> 54105068Sphk#include <geom/geom_int.h> 55105068Sphk 56105068Sphkstatic g_access_t g_ctl_access; 57105068Sphkstatic g_start_t g_ctl_start; 58105068Sphkstatic void g_ctl_init(void); 59105068Sphkstatic d_ioctl_t g_ctl_ioctl; 60105068Sphk 61105068Sphkstruct g_class g_ctl_class = { 62105068Sphk "GEOMCTL", 63105068Sphk NULL, 64105068Sphk NULL, 65105068Sphk G_CLASS_INITIALIZER 66105068Sphk}; 67105068Sphk 68105068SphkDECLARE_GEOM_CLASS_INIT(g_ctl_class, g_ctl, g_ctl_init); 69105068Sphk 70105068Sphk/* 71105068Sphk * We cannot do create our geom.ctl geom/provider in g_ctl_init() because 72105068Sphk * the event thread has to finish adding our class first and that doesn't 73105068Sphk * happen until later. We know however, that the events are processed in 74105068Sphk * FIFO order, so scheduling g_ctl_init2() with g_call_me() is safe. 75105068Sphk */ 76105068Sphk 77105068Sphkstatic void 78105068Sphkg_ctl_init2(void *p __unused) 79105068Sphk{ 80105068Sphk struct g_geom *gp; 81105068Sphk struct g_provider *pp; 82105068Sphk 83105068Sphk g_topology_assert(); 84105068Sphk gp = g_new_geomf(&g_ctl_class, "geom.ctl"); 85105068Sphk gp->start = g_ctl_start; 86105068Sphk gp->access = g_ctl_access; 87105068Sphk pp = g_new_providerf(gp, "%s", gp->name); 88105068Sphk g_error_provider(pp, 0); 89105068Sphk} 90105068Sphk 91105068Sphkstatic void 92105068Sphkg_ctl_init(void) 93105068Sphk{ 94105068Sphk mtx_unlock(&Giant); 95105068Sphk g_add_class(&g_ctl_class); 96105068Sphk g_call_me(g_ctl_init2, NULL); 97105068Sphk mtx_lock(&Giant); 98105068Sphk} 99105068Sphk 100105068Sphk/* 101105068Sphk * We allow any kind of access. Access control is handled at the devfs 102105068Sphk * level. 103105068Sphk */ 104105068Sphk 105105068Sphkstatic int 106105068Sphkg_ctl_access(struct g_provider *pp, int r, int w, int e) 107105068Sphk{ 108105068Sphk int error; 109105068Sphk 110105068Sphk g_trace(G_T_ACCESS, "g_ctl_access(%s, %d, %d, %d)", 111105068Sphk pp->name, r, w, e); 112105068Sphk 113105068Sphk g_topology_assert(); 114105068Sphk error = 0; 115105068Sphk return (error); 116105068Sphk} 117105068Sphk 118105068Sphkstatic void 119105068Sphkg_ctl_start(struct bio *bp) 120105068Sphk{ 121105068Sphk struct g_ioctl *gio; 122105068Sphk int error; 123105068Sphk 124105068Sphk switch(bp->bio_cmd) { 125105068Sphk case BIO_DELETE: 126105068Sphk case BIO_READ: 127105068Sphk case BIO_WRITE: 128105068Sphk error = EOPNOTSUPP; 129105068Sphk break; 130105068Sphk case BIO_GETATTR: 131105068Sphk case BIO_SETATTR: 132105068Sphk if (strcmp(bp->bio_attribute, "GEOM::ioctl") || 133105068Sphk bp->bio_length != sizeof *gio) { 134105068Sphk error = EOPNOTSUPP; 135105068Sphk break; 136105068Sphk } 137105068Sphk gio = (struct g_ioctl *)bp->bio_data; 138105068Sphk gio->func = g_ctl_ioctl; 139105068Sphk error = EDIRIOCTL; 140105068Sphk break; 141105068Sphk default: 142105068Sphk error = EOPNOTSUPP; 143105068Sphk break; 144105068Sphk } 145105068Sphk g_io_deliver(bp, error); 146105068Sphk return; 147105068Sphk} 148105068Sphk 149105068Sphk/* 150105068Sphk * All the stuff above is really just needed to get to this one. 151105068Sphk */ 152105068Sphk 153105068Sphkstatic int 154105068Sphkg_ctl_ioctl_getconf(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td) 155105068Sphk{ 156105068Sphk struct geomgetconf *gcp; 157105068Sphk struct sbuf *sb; 158105068Sphk int error; 159105068Sphk u_int l; 160105068Sphk 161105068Sphk gcp = (struct geomgetconf *)data; 162105068Sphk sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND); 163105068Sphk sbuf_clear(sb); 164105068Sphk g_confxml(sb); 165105068Sphk l = sbuf_len(sb) + 1; 166105068Sphk if (l > gcp->len) 167105068Sphk error = ENOMEM; 168105068Sphk else 169105068Sphk error = copyout(sbuf_data(sb), gcp->ptr, l); 170105068Sphk sbuf_delete(sb); 171105068Sphk return(error); 172105068Sphk} 173105068Sphk 174105068Sphkstatic int 175105068Sphkg_ctl_ioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td) 176105068Sphk{ 177105068Sphk int error; 178105068Sphk 179105068Sphk DROP_GIANT(); 180105068Sphk g_topology_lock(); 181105068Sphk switch(cmd) { 182105068Sphk case GEOMGETCONF: 183105068Sphk error = g_ctl_ioctl_getconf(dev, cmd, data, fflag, td); 184105068Sphk break; 185105068Sphk default: 186105068Sphk error = ENOTTY; 187105068Sphk break; 188105068Sphk } 189105068Sphk g_topology_unlock(); 190105068Sphk PICKUP_GIANT(); 191105068Sphk return (error); 192105068Sphk 193105068Sphk} 194