The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/bio.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: bio.c,v 1.8 2008/04/09 05:47:19 cegger Exp $ */
    2 /*      $OpenBSD: bio.c,v 1.9 2007/03/20 02:35:55 marco Exp $   */
    3 
    4 /*
    5  * Copyright (c) 2002 Niklas Hallqvist.  All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   26  */
   27 
   28 /* A device controller ioctl tunnelling device.  */
   29 
   30 #include <sys/cdefs.h>
   31 __KERNEL_RCSID(0, "$NetBSD: bio.c,v 1.8 2008/04/09 05:47:19 cegger Exp $");
   32 
   33 #include "opt_compat_netbsd.h"
   34 
   35 #include <sys/param.h>
   36 #include <sys/conf.h>
   37 #include <sys/device.h>
   38 #include <sys/event.h>
   39 #include <sys/ioctl.h>
   40 #include <sys/malloc.h>
   41 #include <sys/queue.h>
   42 #include <sys/systm.h>
   43 #include <sys/mutex.h>
   44 #include <sys/proc.h>
   45 #include <sys/kauth.h>
   46 
   47 #include <dev/biovar.h>
   48 
   49 struct bio_mapping {
   50         LIST_ENTRY(bio_mapping) bm_link;
   51         struct device *bm_dev;
   52         int (*bm_ioctl)(struct device *, u_long, void *);
   53 };
   54 
   55 static LIST_HEAD(, bio_mapping) bios = LIST_HEAD_INITIALIZER(bios);
   56 static kmutex_t bio_lock;
   57 static bool bio_lock_initialized = false;
   58 
   59 static void     bio_initialize(void);
   60 static int      bioclose(dev_t, int, int, struct lwp *);
   61 static int      bioioctl(dev_t, u_long, void *, int, struct lwp *);
   62 static int      bioopen(dev_t, int, int, struct lwp *);
   63 
   64 static int      bio_delegate_ioctl(void *, u_long, void *);
   65 static struct   bio_mapping *bio_lookup(char *);
   66 static int      bio_validate(void *);
   67 
   68 void    bioattach(int);
   69 
   70 const struct cdevsw bio_cdevsw = {
   71         bioopen, bioclose, noread, nowrite, bioioctl,
   72         nostop, notty, nopoll, nommap, nokqfilter, D_OTHER | D_MPSAFE
   73 };
   74 
   75 
   76 static void
   77 bio_initialize(void)
   78 {
   79         if (bio_lock_initialized)
   80                 return;
   81 
   82         mutex_init(&bio_lock, MUTEX_DEFAULT, IPL_VM);
   83         bio_lock_initialized = true;
   84 }
   85 
   86 void
   87 bioattach(int nunits)
   88 {
   89         if (!bio_lock_initialized)
   90                 bio_initialize();
   91 }
   92 
   93 static int
   94 bioopen(dev_t dev, int flags, int mode, struct lwp *l)
   95 {
   96         return 0;
   97 }
   98 
   99 static int
  100 bioclose(dev_t dev, int flags, int mode, struct lwp *l)
  101 {
  102         return 0;
  103 }
  104 
  105 static int
  106 bioioctl(dev_t dev, u_long cmd, void *addr, int flag, struct  lwp *l)
  107 {
  108         struct bio_locate *locate;
  109         struct bio_common *common;
  110         char name[16];
  111         int error;
  112 
  113         switch(cmd) {
  114         case BIOCLOCATE:
  115         case BIOCINQ:
  116         case BIOCDISK:
  117         case BIOCDISK_NOVOL:
  118         case BIOCVOL:
  119 #ifdef COMPAT_30
  120         case OBIOCDISK:
  121         case OBIOCVOL:
  122 #endif
  123                 error = kauth_authorize_device_passthru(l->l_cred, dev,
  124                     KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_READCONF, addr);
  125                 if (error)
  126                         return error;
  127                 break;
  128         case BIOCBLINK:
  129         case BIOCSETSTATE:
  130         case BIOCVOLOPS:
  131                 error = kauth_authorize_device_passthru(l->l_cred, dev,
  132                     KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_WRITECONF, addr);
  133                 if (error)
  134                         return error;
  135                 break;
  136         case BIOCALARM: {
  137                 struct bioc_alarm *alarm = (struct bioc_alarm *)addr;
  138                 switch (alarm->ba_opcode) {
  139                 case BIOC_SADISABLE:
  140                 case BIOC_SAENABLE:
  141                 case BIOC_SASILENCE:
  142                 case BIOC_SATEST:
  143                         error = kauth_authorize_device_passthru(l->l_cred, dev,
  144                             KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_WRITECONF, addr);
  145                         if (error)
  146                                 return error;
  147                         break;
  148                 case BIOC_GASTATUS:
  149                         error = kauth_authorize_device_passthru(l->l_cred, dev,
  150                             KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_READCONF, addr);
  151                         if (error)
  152                                 return error;
  153                         break;
  154                 default:
  155                         return EINVAL;
  156                 }
  157                 break;
  158         }
  159         default:
  160                 return ENOTTY;
  161         }
  162 
  163         switch (cmd) {
  164         case BIOCLOCATE:
  165                 locate = addr;
  166                 error = copyinstr(locate->bl_name, name, sizeof(name), NULL);
  167                 if (error != 0)
  168                         return error;
  169                 locate->bl_cookie = bio_lookup(name);
  170                 if (locate->bl_cookie == NULL)
  171                         return ENOENT;
  172                 break;
  173 
  174         default:
  175                 common = addr;
  176                 mutex_enter(&bio_lock);
  177                 if (!bio_validate(common->bc_cookie)) {
  178                         mutex_exit(&bio_lock);
  179                         return ENOENT;
  180                 }
  181                 mutex_exit(&bio_lock);
  182 #ifdef COMPAT_30
  183                 switch (cmd) {
  184                 case OBIOCDISK: {
  185                         struct bioc_disk *bd =
  186                             malloc(sizeof(*bd), M_DEVBUF, M_WAITOK|M_ZERO);
  187 
  188                         (void)memcpy(bd, addr, sizeof(struct obioc_disk));
  189                         error = bio_delegate_ioctl(common->bc_cookie,
  190                             BIOCDISK, bd);
  191                         if (error) {
  192                                 free(bd, M_DEVBUF);
  193                                 return error;
  194                         }
  195 
  196                         (void)memcpy(addr, bd, sizeof(struct obioc_disk));
  197                         free(bd, M_DEVBUF);
  198                         return 0;
  199                 }
  200                 case OBIOCVOL: {
  201                         struct bioc_vol *bv =
  202                             malloc(sizeof(*bv), M_DEVBUF, M_WAITOK|M_ZERO);
  203 
  204                         (void)memcpy(bv, addr, sizeof(struct obioc_vol));
  205                         error = bio_delegate_ioctl(common->bc_cookie,
  206                             BIOCVOL, bv);
  207                         if (error) {
  208                                 free(bv, M_DEVBUF);
  209                                 return error;
  210                         }
  211 
  212                         (void)memcpy(addr, bv, sizeof(struct obioc_vol));
  213                         free(bv, M_DEVBUF);
  214                         return 0;
  215                 }
  216                 }
  217 #endif
  218                 error = bio_delegate_ioctl(common->bc_cookie, cmd, addr);
  219                 return error;
  220         }
  221         return 0;
  222 }
  223 
  224 int
  225 bio_register(struct device *dev, int (*ioctl)(struct device *, u_long, void *))
  226 {
  227         struct bio_mapping *bm;
  228 
  229         if (!bio_lock_initialized)
  230                 bio_initialize();
  231 
  232         bm = malloc(sizeof(*bm), M_DEVBUF, M_NOWAIT|M_ZERO);
  233         if (bm == NULL)
  234                 return ENOMEM;
  235         bm->bm_dev = dev;
  236         bm->bm_ioctl = ioctl;
  237         mutex_enter(&bio_lock);
  238         LIST_INSERT_HEAD(&bios, bm, bm_link);
  239         mutex_exit(&bio_lock);
  240         return 0;
  241 }
  242 
  243 void
  244 bio_unregister(struct device *dev)
  245 {
  246         struct bio_mapping *bm, *next;
  247 
  248         mutex_enter(&bio_lock);
  249         for (bm = LIST_FIRST(&bios); bm != NULL; bm = next) {
  250                 next = LIST_NEXT(bm, bm_link);
  251 
  252                 if (dev == bm->bm_dev) {
  253                         LIST_REMOVE(bm, bm_link);
  254                         free(bm, M_DEVBUF);
  255                 }
  256         }
  257         mutex_exit(&bio_lock);
  258 }
  259 
  260 static struct bio_mapping *
  261 bio_lookup(char *name)
  262 {
  263         struct bio_mapping *bm;
  264 
  265         mutex_enter(&bio_lock);
  266         LIST_FOREACH(bm, &bios, bm_link) {
  267                 if (strcmp(name, device_xname(bm->bm_dev)) == 0) {
  268                         mutex_exit(&bio_lock);
  269                         return bm;
  270                 }
  271         }
  272         mutex_exit(&bio_lock);
  273         return NULL;
  274 }
  275 
  276 static int
  277 bio_validate(void *cookie)
  278 {
  279         struct bio_mapping *bm;
  280 
  281         LIST_FOREACH(bm, &bios, bm_link)
  282                 if (bm == cookie)
  283                         return 1;
  284 
  285         return 0;
  286 }
  287 
  288 static int
  289 bio_delegate_ioctl(void *cookie, u_long cmd, void *addr)
  290 {
  291         struct bio_mapping *bm = cookie;
  292         
  293         return bm->bm_ioctl(bm->bm_dev, cmd, addr);
  294 }

Cache object: f22f494f9370dc3b6e8db69e2297d576


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.