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/vinum/vinumdaemon.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 /* daemon.c: kernel part of Vinum daemon */
    2 
    3 #include <sys/cdefs.h>
    4 __FBSDID("$FreeBSD$");
    5 /*-
    6  * Copyright (c) 1997, 1998
    7  *      Nan Yang Computer Services Limited.  All rights reserved.
    8  *
    9  *  This software is distributed under the so-called ``Berkeley
   10  *  License'':
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 3. All advertising materials mentioning features or use of this software
   21  *    must display the following acknowledgement:
   22  *      This product includes software developed by Nan Yang Computer
   23  *      Services Limited.
   24  * 4. Neither the name of the Company nor the names of its contributors
   25  *    may be used to endorse or promote products derived from this software
   26  *    without specific prior written permission.
   27  *
   28  * This software is provided ``as is'', and any express or implied
   29  * warranties, including, but not limited to, the implied warranties of
   30  * merchantability and fitness for a particular purpose are disclaimed.
   31  * In no event shall the company or contributors be liable for any
   32  * direct, indirect, incidental, special, exemplary, or consequential
   33  * damages (including, but not limited to, procurement of substitute
   34  * goods or services; loss of use, data, or profits; or business
   35  * interruption) however caused and on any theory of liability, whether
   36  * in contract, strict liability, or tort (including negligence or
   37  * otherwise) arising in any way out of the use of this software, even if
   38  * advised of the possibility of such damage.
   39  *
   40  * $Id: vinumdaemon.c,v 1.8 2000/01/03 05:22:03 grog Exp grog $
   41  */
   42 
   43 #include <dev/vinum/vinumhdr.h>
   44 #include <dev/vinum/request.h>
   45 
   46 #ifdef VINUMDEBUG
   47 #include <sys/reboot.h>
   48 #endif
   49 
   50 /* declarations */
   51 void recover_io(struct request *rq);
   52 
   53 int daemon_options = 0;                                     /* options */
   54 int daemonpid;                                              /* PID of daemon */
   55 struct daemonq *daemonq;                                    /* daemon's work queue */
   56 struct daemonq *dqend;                                      /* and the end of the queue */
   57 
   58 /*
   59  * We normally call Malloc to get a queue element.  In interrupt
   60  * context, we can't guarantee that we'll get one, since we're not
   61  * allowed to wait.  If malloc fails, use one of these elements.
   62  */
   63 
   64 #define INTQSIZE 4
   65 struct daemonq intq[INTQSIZE];                              /* queue elements for interrupt context */
   66 struct daemonq *intqp;                                      /* and pointer in it */
   67 
   68 void
   69 vinum_daemon(void)
   70 {
   71     int s;
   72     struct daemonq *request;
   73 
   74     PROC_LOCK(curproc);
   75     curproc->p_flag |= P_SYSTEM;                            /* we're a system process */
   76     mtx_lock_spin(&sched_lock);
   77     curproc->p_sflag |= PS_INMEM;
   78     mtx_unlock_spin(&sched_lock);
   79     PROC_UNLOCK(curproc);
   80     daemon_save_config();                                   /* start by saving the configuration */
   81     daemonpid = curproc->p_pid;                             /* mark our territory */
   82     while (1) {
   83         tsleep(&vinum_daemon, PRIBIO, "vinum", 0);          /* wait for something to happen */
   84 
   85         /*
   86          * It's conceivable that, as the result of an
   87          * I/O error, we'll be out of action long
   88          * enough that another daemon gets started.
   89          * That's OK, just give up gracefully.
   90          */
   91         if (curproc->p_pid != daemonpid) {                  /* we've been ousted in our sleep */
   92             if (daemon_options & daemon_verbose)
   93                 log(LOG_INFO, "vinum: abdicating\n");
   94             return;
   95         }
   96         while (daemonq != NULL) {                           /* we have work to do, */
   97             s = splhigh();                                  /* don't get interrupted here */
   98             request = daemonq;                              /* get the request */
   99             daemonq = daemonq->next;                        /* and detach it */
  100             if (daemonq == NULL)                            /* got to the end, */
  101                 dqend = NULL;                               /* no end any more */
  102             splx(s);
  103 
  104             switch (request->type) {
  105                 /*
  106                  * We had an I/O error on a request.  Go through the
  107                  * request and try to salvage it
  108                  */
  109             case daemonrq_ioerror:
  110                 if (daemon_options & daemon_verbose) {
  111                     struct request *rq = request->info.rq;
  112 
  113                     log(LOG_WARNING,
  114                         "vinum: recovering I/O request: %p\n%s dev %d.%d, offset 0x%llx, length %ld\n",
  115                         rq,
  116                         rq->bp->b_iocmd == BIO_READ ? "Read" : "Write",
  117                         major(rq->bp->b_dev),
  118                         minor(rq->bp->b_dev),
  119                         (long long)rq->bp->b_blkno,
  120                         rq->bp->b_bcount);
  121                 }
  122                 recover_io(request->info.rq);               /* the failed request */
  123                 break;
  124 
  125                 /*
  126                  * Write the config to disk.  We could end up with
  127                  * quite a few of these in a row.  Only honour the
  128                  * last one
  129                  */
  130             case daemonrq_saveconfig:
  131                 if ((daemonq == NULL)                       /* no more requests */
  132                 ||(daemonq->type != daemonrq_saveconfig)) { /* or the next isn't the same */
  133                     if (((daemon_options & daemon_noupdate) == 0) /* we're allowed to do it */
  134                     &&((vinum_conf.flags & VF_READING_CONFIG) == 0)) { /* and we're not building the config now */
  135                         /*
  136                            * We obviously don't want to save a
  137                            * partial configuration.  Less obviously,
  138                            * we don't need to do anything if we're
  139                            * asked to write the config when we're
  140                            * building it up, because we save it at
  141                            * the end.
  142                          */
  143                         if (daemon_options & daemon_verbose)
  144                             log(LOG_INFO, "vinum: saving config\n");
  145                         daemon_save_config();               /* save it */
  146                     }
  147                 }
  148                 break;
  149 
  150             case daemonrq_return:                           /* been told to stop */
  151                 if (daemon_options & daemon_verbose)
  152                     log(LOG_INFO, "vinum: stopping\n");
  153                 daemon_options |= daemon_stopped;           /* note that we've stopped */
  154                 Free(request);
  155                 while (daemonq != NULL) {                   /* backed up requests, */
  156                     request = daemonq;                      /* get the request */
  157                     daemonq = daemonq->next;                /* and detach it */
  158                     Free(request);                          /* then free it */
  159                 }
  160                 wakeup(&vinumclose);                        /* and wake any waiting vinum(8)s */
  161                 return;
  162 
  163             case daemonrq_ping:                             /* tell the caller we're here */
  164                 if (daemon_options & daemon_verbose)
  165                     log(LOG_INFO, "vinum: ping reply\n");
  166                 wakeup(&vinum_finddaemon);                  /* wake up the caller */
  167                 break;
  168 
  169             case daemonrq_closedrive:                       /* close a drive */
  170                 close_drive(request->info.drive);           /* do it */
  171                 break;
  172 
  173             case daemonrq_init:                             /* initialize a plex */
  174                 /* XXX */
  175             case daemonrq_revive:                           /* revive a subdisk */
  176                 /* XXX */
  177                 /* FALLTHROUGH */
  178             default:
  179                 log(LOG_WARNING, "Invalid request\n");
  180                 break;
  181             }
  182             if (request->privateinuse)                      /* one of ours, */
  183                 request->privateinuse = 0;                  /* no longer in use */
  184             else
  185                 Free(request);                              /* return it */
  186         }
  187     }
  188 }
  189 
  190 /*
  191  * Recover a failed I/O operation.
  192  *
  193  * The correct way to do this is to examine the request and determine
  194  * how to recover each individual failure.  In the case of a write,
  195  * this could be as simple as doing nothing: the defective drives may
  196  * already be down, and there may be nothing else to do.  In case of
  197  * a read, it will be necessary to retry if there are alternative
  198  * copies of the data.
  199  *
  200  * The easy way (here) is just to reissue the request.  This will take
  201  * a little longer, but nothing like as long as the failure will have
  202  * taken.
  203  *
  204  */
  205 void
  206 recover_io(struct request *rq)
  207 {
  208     /*
  209      * This should read:
  210      *
  211      *     vinumstrategy(rq->bp);
  212      *
  213      * Negotiate with phk to get it fixed.
  214      */
  215     DEV_STRATEGY(rq->bp);                                   /* reissue the command */
  216 }
  217 
  218 /* Functions called to interface with the daemon */
  219 
  220 /* queue a request for the daemon */
  221 void
  222 queue_daemon_request(enum daemonrq type, union daemoninfo info)
  223 {
  224     int s;
  225 
  226     struct daemonq *qelt = (struct daemonq *) Malloc(sizeof(struct daemonq));
  227 
  228     if (qelt == NULL) {                                     /* malloc failed, we're prepared for that */
  229         /*
  230          * Take one of our spares.  Give up if it's still in use; the only
  231          * message we're likely to get here is a 'drive failed' message,
  232          * and that'll come by again if we miss it.
  233          */
  234         if (intqp->privateinuse)                            /* still in use? */
  235             return;                                         /* yes, give up */
  236         qelt = intqp++;
  237         if (intqp == &intq[INTQSIZE])                       /* got to the end, */
  238             intqp = intq;                                   /* wrap around */
  239         qelt->privateinuse = 1;                             /* it's ours, and it's in use */
  240     } else
  241         qelt->privateinuse = 0;
  242 
  243     qelt->next = NULL;                                      /* end of the chain */
  244     qelt->type = type;
  245     qelt->info = info;
  246     s = splhigh();
  247     if (daemonq) {                                          /* something queued already */
  248         dqend->next = qelt;
  249         dqend = qelt;
  250     } else {                                                /* queue is empty, */
  251         daemonq = qelt;                                     /* this is the whole queue */
  252         dqend = qelt;
  253     }
  254     splx(s);
  255     wakeup(&vinum_daemon);                                  /* and give the dæmon a kick */
  256 }
  257 
  258 /*
  259  * see if the daemon is running.  Return 0 (no error)
  260  * if it is, ESRCH otherwise
  261  */
  262 int
  263 vinum_finddaemon()
  264 {
  265     int result;
  266 
  267     if (daemonpid != 0) {                                   /* we think we have a daemon, */
  268         queue_daemon_request(daemonrq_ping, (union daemoninfo) 0); /* queue a ping */
  269         result = tsleep(&vinum_finddaemon, PUSER, "reap", 2 * hz);
  270         if (result == 0)                                    /* yup, the daemon's up and running */
  271             return 0;
  272     }
  273     /* no daemon, or we couldn't talk to it: start it */
  274     vinum_daemon();                                         /* start the daemon */
  275     return 0;
  276 }
  277 
  278 int
  279 vinum_setdaemonopts(int options)
  280 {
  281     daemon_options = options;
  282     return 0;
  283 }

Cache object: 557df65dbd530207938bb2a573305716


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