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.17 2020/12/19 01:12:21 thorpej 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.17 2020/12/19 01:12:21 thorpej 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/kmem.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 #include <sys/compat_stub.h>
   47 
   48 #include <dev/biovar.h>
   49 #include <dev/sysmon/sysmonvar.h>
   50 
   51 #include "ioconf.h"
   52 
   53 struct bio_mapping {
   54         LIST_ENTRY(bio_mapping) bm_link;
   55         device_t bm_dev;
   56         int (*bm_ioctl)(device_t, u_long, void *);
   57 };
   58 
   59 static LIST_HEAD(, bio_mapping) bios = LIST_HEAD_INITIALIZER(bios);
   60 static kmutex_t bio_lock;
   61 static bool bio_lock_initialized = false;
   62 
   63 static void     bio_initialize(void);
   64 static int      bioclose(dev_t, int, int, struct lwp *);
   65 static int      bioioctl(dev_t, u_long, void *, int, struct lwp *);
   66 static int      bioopen(dev_t, int, int, struct lwp *);
   67 
   68 static int      bio_delegate_ioctl(void *, u_long, void *);
   69 static struct   bio_mapping *bio_lookup(char *);
   70 static int      bio_validate(void *);
   71 
   72 const struct cdevsw bio_cdevsw = {
   73         .d_open = bioopen,
   74         .d_close = bioclose,
   75         .d_read = noread,
   76         .d_write = nowrite,
   77         .d_ioctl = bioioctl,
   78         .d_stop = nostop,
   79         .d_tty = notty,
   80         .d_poll = nopoll,
   81         .d_mmap = nommap,
   82         .d_kqfilter = nokqfilter,
   83         .d_discard = nodiscard,
   84         .d_flag = D_OTHER | D_MPSAFE
   85 };
   86 
   87 
   88 static void
   89 bio_initialize(void)
   90 {
   91         if (bio_lock_initialized)
   92                 return;
   93 
   94         mutex_init(&bio_lock, MUTEX_DEFAULT, IPL_VM);
   95         bio_lock_initialized = true;
   96 }
   97 
   98 void
   99 bioattach(int nunits)
  100 {
  101         if (!bio_lock_initialized)
  102                 bio_initialize();
  103 }
  104 
  105 static int
  106 bioopen(dev_t dev, int flags, int mode, struct lwp *l)
  107 {
  108         return 0;
  109 }
  110 
  111 static int
  112 bioclose(dev_t dev, int flags, int mode, struct lwp *l)
  113 {
  114         return 0;
  115 }
  116 
  117 static int
  118 bioioctl(dev_t dev, u_long cmd, void *addr, int flag, struct  lwp *l)
  119 {
  120         struct bio_locate *locate;
  121         struct bio_common *common;
  122         char name[16];
  123         int error;
  124 
  125         switch(cmd) {
  126         case BIOCLOCATE:
  127         case BIOCINQ:
  128         case BIOCDISK:
  129         case BIOCDISK_NOVOL:
  130         case BIOCVOL:
  131         case OBIOCDISK:
  132         case OBIOCVOL:
  133                 error = kauth_authorize_device_passthru(l->l_cred, dev,
  134                     KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_READCONF, addr);
  135                 if (error)
  136                         return error;
  137                 break;
  138         case BIOCBLINK:
  139         case BIOCSETSTATE:
  140         case BIOCVOLOPS:
  141                 error = kauth_authorize_device_passthru(l->l_cred, dev,
  142                     KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_WRITECONF, addr);
  143                 if (error)
  144                         return error;
  145                 break;
  146         case BIOCALARM: {
  147                 struct bioc_alarm *alarm = (struct bioc_alarm *)addr;
  148                 switch (alarm->ba_opcode) {
  149                 case BIOC_SADISABLE:
  150                 case BIOC_SAENABLE:
  151                 case BIOC_SASILENCE:
  152                 case BIOC_SATEST:
  153                         error = kauth_authorize_device_passthru(l->l_cred, dev,
  154                             KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_WRITECONF, addr);
  155                         if (error)
  156                                 return error;
  157                         break;
  158                 case BIOC_GASTATUS:
  159                         error = kauth_authorize_device_passthru(l->l_cred, dev,
  160                             KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_READCONF, addr);
  161                         if (error)
  162                                 return error;
  163                         break;
  164                 default:
  165                         return EINVAL;
  166                 }
  167                 break;
  168         }
  169         default:
  170                 return ENOTTY;
  171         }
  172 
  173         switch (cmd) {
  174         case BIOCLOCATE:
  175                 locate = addr;
  176                 error = copyinstr(locate->bl_name, name, sizeof(name), NULL);
  177                 if (error != 0)
  178                         return error;
  179                 locate->bl_cookie = bio_lookup(name);
  180                 if (locate->bl_cookie == NULL)
  181                         return ENOENT;
  182                 break;
  183 
  184         default:
  185                 common = addr;
  186                 mutex_enter(&bio_lock);
  187                 if (!bio_validate(common->bc_cookie)) {
  188                         mutex_exit(&bio_lock);
  189                         return ENOENT;
  190                 }
  191                 mutex_exit(&bio_lock);
  192                 MODULE_HOOK_CALL(compat_bio_30_hook,
  193                     (common->bc_cookie, cmd, addr, bio_delegate_ioctl),
  194                     enosys(), error);
  195                 if (error == ENOSYS)
  196                         error = bio_delegate_ioctl(common->bc_cookie, cmd,
  197                             addr);
  198                 return error;
  199         }
  200         return 0;
  201 }
  202 
  203 int
  204 bio_register(device_t dev, int (*ioctl)(device_t, u_long, void *))
  205 {
  206         struct bio_mapping *bm;
  207 
  208         if (!bio_lock_initialized)
  209                 bio_initialize();
  210 
  211         bm = kmem_zalloc(sizeof(*bm), KM_SLEEP);
  212         bm->bm_dev = dev;
  213         bm->bm_ioctl = ioctl;
  214         mutex_enter(&bio_lock);
  215         LIST_INSERT_HEAD(&bios, bm, bm_link);
  216         mutex_exit(&bio_lock);
  217         return 0;
  218 }
  219 
  220 void
  221 bio_unregister(device_t dev)
  222 {
  223         struct bio_mapping *bm, *next;
  224 
  225         mutex_enter(&bio_lock);
  226         for (bm = LIST_FIRST(&bios); bm != NULL; bm = next) {
  227                 next = LIST_NEXT(bm, bm_link);
  228 
  229                 if (dev == bm->bm_dev) {
  230                         LIST_REMOVE(bm, bm_link);
  231                         kmem_free(bm, sizeof(*bm));
  232                 }
  233         }
  234         mutex_exit(&bio_lock);
  235 }
  236 
  237 static struct bio_mapping *
  238 bio_lookup(char *name)
  239 {
  240         struct bio_mapping *bm;
  241 
  242         mutex_enter(&bio_lock);
  243         LIST_FOREACH(bm, &bios, bm_link) {
  244                 if (strcmp(name, device_xname(bm->bm_dev)) == 0) {
  245                         mutex_exit(&bio_lock);
  246                         return bm;
  247                 }
  248         }
  249         mutex_exit(&bio_lock);
  250         return NULL;
  251 }
  252 
  253 static int
  254 bio_validate(void *cookie)
  255 {
  256         struct bio_mapping *bm;
  257 
  258         LIST_FOREACH(bm, &bios, bm_link)
  259                 if (bm == cookie)
  260                         return 1;
  261 
  262         return 0;
  263 }
  264 
  265 static int
  266 bio_delegate_ioctl(void *cookie, u_long cmd, void *addr)
  267 {
  268         struct bio_mapping *bm = cookie;
  269         
  270         return bm->bm_ioctl(bm->bm_dev, cmd, addr);
  271 }
  272 
  273 void
  274 bio_disk_to_envsys(envsys_data_t *edata, const struct bioc_disk *bd)
  275 {
  276         switch (bd->bd_status) {
  277         case BIOC_SDONLINE:
  278                 edata->value_cur = ENVSYS_DRIVE_ONLINE;
  279                 edata->state = ENVSYS_SVALID;
  280                 break;
  281         case BIOC_SDOFFLINE:
  282                 edata->value_cur = ENVSYS_DRIVE_OFFLINE;
  283                 edata->state = ENVSYS_SCRITICAL;
  284                 break;
  285         default:
  286                 edata->value_cur = ENVSYS_DRIVE_FAIL;
  287                 edata->state = ENVSYS_SCRITICAL;
  288                 break;
  289         }
  290 }
  291 
  292 void
  293 bio_vol_to_envsys(envsys_data_t *edata, const struct bioc_vol *bv)
  294 {
  295         switch (bv->bv_status) {
  296         case BIOC_SVOFFLINE:
  297                 edata->value_cur = ENVSYS_DRIVE_OFFLINE;
  298                 edata->state = ENVSYS_SCRITICAL;
  299                 break;
  300         case BIOC_SVDEGRADED:
  301                 edata->value_cur = ENVSYS_DRIVE_PFAIL;
  302                 edata->state = ENVSYS_SCRITICAL;
  303                 break;
  304         case BIOC_SVBUILDING:
  305                 edata->value_cur = ENVSYS_DRIVE_BUILD;
  306                 edata->state = ENVSYS_SVALID;
  307                 break;
  308         case BIOC_SVMIGRATING:
  309                 edata->value_cur = ENVSYS_DRIVE_MIGRATING;
  310                 edata->state = ENVSYS_SVALID;
  311                 break;
  312         case BIOC_SVCHECKING:
  313                 edata->value_cur = ENVSYS_DRIVE_CHECK;
  314                 edata->state = ENVSYS_SVALID;
  315                 break;
  316         case BIOC_SVREBUILD:
  317                 edata->value_cur = ENVSYS_DRIVE_REBUILD;
  318                 edata->state = ENVSYS_SCRITICAL;
  319                 break;
  320         case BIOC_SVSCRUB:
  321         case BIOC_SVONLINE:
  322                 edata->value_cur = ENVSYS_DRIVE_ONLINE;
  323                 edata->state = ENVSYS_SVALID;
  324                 break;
  325         case BIOC_SVINVALID:
  326                 /* FALLTHROUGH */
  327         default:
  328                 edata->value_cur = ENVSYS_DRIVE_EMPTY; /* unknown state */
  329                 edata->state = ENVSYS_SINVALID;
  330                 break;
  331         }
  332 }

Cache object: a67fd13c39ec6dfe0d01619cc48e008b


[ 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.