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/scsi/rz_disk_bbr.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 /* 
    2  * Mach Operating System
    3  * Copyright (c) 1991,1990 Carnegie Mellon University
    4  * All Rights Reserved.
    5  * 
    6  * Permission to use, copy, modify and distribute this software and its
    7  * documentation is hereby granted, provided that both the copyright
    8  * notice and this permission notice appear in all copies of the
    9  * software, derivative works or modified versions, and any portions
   10  * thereof, and that both notices appear in supporting documentation.
   11  * 
   12  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
   13  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
   14  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   15  * 
   16  * Carnegie Mellon requests users of this software to return to
   17  * 
   18  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   19  *  School of Computer Science
   20  *  Carnegie Mellon University
   21  *  Pittsburgh PA 15213-3890
   22  * 
   23  * any improvements or extensions that they make and grant Carnegie Mellon
   24  * the rights to redistribute these changes.
   25  */
   26 /*
   27  * HISTORY
   28  * $Log:        rz_disk_bbr.c,v $
   29  * Revision 2.11  93/05/10  21:22:38  rvb
   30  *      Removed depends on DEV_BSIZE.
   31  *      [93/05/06  10:09:46  af]
   32  * 
   33  * Revision 2.10  92/08/03  17:53:51  jfriedl
   34  *      removed silly prototypes
   35  *      [92/08/02            jfriedl]
   36  * 
   37  * Revision 2.9  92/05/22  15:51:13  jfriedl
   38  *      Blooper, unterminated comment took away some (working, I swear)
   39  *      code.  Found by Jeff Friedl.
   40  *      [92/05/17            af]
   41  * 
   42  * Revision 2.8  92/05/21  17:23:40  jfriedl
   43  *      Cleanup to quiet gcc warnings.
   44  *      [92/05/18            jfriedl]
   45  * 
   46  * Revision 2.7  92/02/23  22:44:25  elf
   47  *      Changed the interface of a number of functions not to
   48  *      require the scsi_softc pointer any longer.  It was
   49  *      mostly unused, now it can be found via tgt->masterno.
   50  *      [92/02/22  19:30:35  af]
   51  * 
   52  * Revision 2.6  91/08/24  12:27:58  af
   53  *      Fixed includes.
   54  *      [91/08/02  03:45:46  af]
   55  * 
   56  * Revision 2.5  91/07/09  23:22:33  danner
   57  *      Upgraded to new label technology.
   58  *      [91/07/09  11:16:12  danner]
   59  * 
   60  * Revision 2.4  91/06/19  11:57:06  rvb
   61  *      File moved here from mips/PMAX since it is now "MI" code, also
   62  *      used by Vax3100 and soon -- the omron luna88k.
   63  *      [91/06/04            rvb]
   64  * 
   65  * Revision 2.3  91/05/14  17:26:42  mrt
   66  *      Correcting copyright
   67  * 
   68  * Revision 2.2  91/05/13  06:04:29  af
   69  *      Created.
   70  *      [91/04/30            af]
   71  * 
   72  */
   73 /*
   74  *      File: rz_disk_bbr.c
   75  *      Author: Alessandro Forin, Carnegie Mellon University
   76  *      Date:   4/91
   77  *
   78  *      Top layer of the SCSI driver: interface with the MI.
   79  *      This file contains bad-block management functions
   80  *      (retry, replace) for disk-like devices.
   81  */
   82 
   83 #include <mach/std_types.h>
   84 #include <scsi/compat_30.h>
   85 
   86 #include <scsi/scsi.h>
   87 #include <scsi/scsi_defs.h>
   88 #include <scsi/rz.h>
   89 
   90 
   91 
   92 int     scsi_bbr_retries = 10;
   93 
   94 #define BBR_ACTION_COMPLETE     1
   95 #define BBR_ACTION_RETRY_READ   2
   96 #define BBR_ACTION_REASSIGN     3
   97 #define BBR_ACTION_COPY         4
   98 #define BBR_ACTION_VERIFY       5
   99 
  100 static void make_msf(); /* forward */
  101 
  102 /*
  103  * Bad block replacement routine, invoked on
  104  * unrecovereable disk read/write errors.
  105  */
  106 boolean_t
  107 scdisk_bad_block_repl(tgt, blockno)
  108         target_info_t           *tgt;
  109         unsigned int            blockno;
  110 {
  111         register io_req_t       ior = tgt->ior;
  112 
  113         if (scsi_no_automatic_bbr || (ior->io_op & IO_INTERNAL))
  114                 return FALSE;
  115 
  116         /* signal we took over */
  117         tgt->flags |= TGT_BBR_ACTIVE;
  118 
  119         printf("%s", "Attempting bad block replacement..");
  120 
  121         tgt->dev_info.disk.b.badblockno = blockno;
  122         tgt->dev_info.disk.b.retry_count = 0;
  123 
  124         tgt->dev_info.disk.b.save_rec   = ior->io_recnum;
  125         tgt->dev_info.disk.b.save_addr  = ior->io_data;
  126         tgt->dev_info.disk.b.save_count = ior->io_count;
  127         tgt->dev_info.disk.b.save_resid = ior->io_residual;
  128 
  129         /*
  130          * On a write all we need is to rewire the offending block.
  131          * Note that the sense data identified precisely which 512 sector
  132          * is bad.  At the end we'll retry the entire write, so if there
  133          * is more than one bad sector involved they will be handled one
  134          * at a time.
  135          */
  136         if ((ior->io_op & IO_READ) == 0) {
  137                 char msf[sizeof(int)];
  138                 ior->io_temporary = BBR_ACTION_COMPLETE;
  139                 printf("%s", "just reassign..");
  140                 make_msf(msf,blockno);
  141                 scsi_reassign_blocks( tgt, msf, 1, ior);
  142         } else
  143         /*
  144          * This is more complicated.  We asked for N bytes, and somewhere
  145          * in there there is a chunk of bad data.  First off, we should retry
  146          * at least a couple of times to retrieve that data [yes the drive
  147          * should have done its best already so what].  If that fails we
  148          * should recover as much good data as possible (before the bad one).
  149          */
  150         {
  151                 ior->io_temporary = BBR_ACTION_RETRY_READ;
  152                 printf("%s", "retry read..");
  153                 ior->io_residual = 0;
  154                 scdisk_start_rw(tgt, ior);
  155         }
  156 
  157         return TRUE;
  158 }
  159 
  160 static
  161 void make_msf(buf,val)
  162         unsigned char   *buf;
  163         unsigned int    val;
  164 {
  165         *buf++ = val >> 24;
  166         *buf++ = val >> 16;
  167         *buf++ = val >>  8;
  168         *buf++ = val >>  0;
  169 }
  170 
  171 /*
  172  * This effectively replaces the strategy routine during bbr.
  173  */
  174 void scdisk_bbr_start( tgt, done)
  175         target_info_t           *tgt;
  176         boolean_t               done;
  177 {
  178         register io_req_t       ior = tgt->ior;
  179         char                    *msg;
  180 
  181         switch (ior->io_temporary) {
  182 
  183         case BBR_ACTION_COMPLETE:
  184 
  185                 /* all done, either way */
  186 fin:
  187                 tgt->flags &= ~TGT_BBR_ACTIVE;
  188                 ior->io_recnum   = tgt->dev_info.disk.b.save_rec;
  189                 ior->io_data     = tgt->dev_info.disk.b.save_addr;
  190                 ior->io_count    = tgt->dev_info.disk.b.save_count;
  191                 ior->io_residual = tgt->dev_info.disk.b.save_resid;
  192 
  193                 if (tgt->done == SCSI_RET_SUCCESS) {
  194                         /* restart normal life */
  195                         register unsigned int   xferred;
  196                         if (xferred = ior->io_residual) {
  197                                 ior->io_data -= xferred;
  198                                 ior->io_count += xferred;
  199                                 ior->io_recnum -= xferred / tgt->block_size;
  200                                 ior->io_residual = 0;
  201                         }
  202                         /* from the beginning */
  203                         ior->io_error = 0;
  204                         msg = "done, restarting.";
  205                 } else {
  206                         /* we could not fix it.  Tell user and give up */
  207                         tgt->ior = ior->io_next;
  208                         iodone(ior);
  209                         msg = "done, but could not recover.";
  210                 }
  211 
  212                 printf("%s\n", msg);
  213                 scdisk_start( tgt, FALSE);
  214                 return;
  215 
  216         case BBR_ACTION_RETRY_READ:
  217 
  218                 /* see if retry worked, if not do it again */
  219                 if (tgt->done == SCSI_RET_SUCCESS) {
  220                         char msf[sizeof(int)];
  221 
  222                         /* whew, retry worked.  Now rewire that bad block
  223                          * and don't forget to copy the good data over */
  224 
  225                         tgt->dev_info.disk.b.retry_count = 0;
  226                         printf("%s", "ok now, reassign..");
  227                         ior->io_temporary = BBR_ACTION_COPY;
  228                         make_msf(msf, tgt->dev_info.disk.b.badblockno);
  229                         scsi_reassign_blocks( tgt, msf, 1, ior);
  230                         return;
  231                 }
  232                 if (tgt->dev_info.disk.b.retry_count++ < scsi_bbr_retries) {
  233                         scdisk_start_rw( tgt, ior);
  234                         return;
  235                 }
  236                 /* retrying was hopeless. Leave the bad block there for maintainance */
  237                 /* because we do not know what to write on it */
  238                 printf("%s%d%s", "failed after ", scsi_bbr_retries, " retries..");
  239                 goto fin;
  240 
  241 
  242         case BBR_ACTION_COPY:
  243 
  244                 /* retrying succeded and we rewired the bad block. */
  245                 if (tgt->done == SCSI_RET_SUCCESS) {
  246                         unsigned int tmp;
  247 
  248                         printf("%s", "ok, rewrite..");
  249 
  250                         /* writeback only the bad sector */
  251 
  252                         /* map blockno back to partition offset */
  253                         tmp = rzpartition(ior->io_unit);
  254                         tmp = tgt->dev_info.disk.b.badblockno - 
  255                               tgt->dev_info.disk.l.d_partitions[tmp].p_offset;
  256                         ior->io_data += (tmp - ior->io_recnum) * tgt->block_size;
  257                         ior->io_recnum = tmp;
  258                         ior->io_count = tgt->block_size;
  259                         ior->io_op &= ~IO_READ;
  260 
  261                         ior->io_temporary = BBR_ACTION_VERIFY;
  262                         scdisk_start_rw( tgt, ior);
  263                 } else {
  264 
  265                         /* either unsupported command, or repl table full */
  266                         printf("%s", "reassign failed (really needs reformatting), ");
  267                         ior->io_error = 0;
  268                         goto fin;
  269                 }
  270                 break;
  271 
  272         case BBR_ACTION_VERIFY:
  273 
  274                 if (tgt->done == SCSI_RET_SUCCESS) {
  275                         ior->io_op |= IO_READ;
  276                         goto fin;
  277                 }
  278 
  279                 if (tgt->dev_info.disk.b.retry_count++ > scsi_bbr_retries) {
  280                         printf("%s%d%s", "failed after ",
  281                                 scsi_bbr_retries, " retries..");
  282                         ior->io_op |= IO_READ;
  283                         goto fin;
  284                 }
  285 
  286                 /* retry, we are *this* close to success.. */
  287                 scdisk_start_rw( tgt, ior);
  288 
  289                 break;
  290 
  291         case BBR_ACTION_REASSIGN:
  292 
  293                 /* if we wanted to issue the reassign multiple times */
  294                 /* XXX unimplemented XXX */
  295 
  296         default:        /* snafu */
  297                 panic("scdisk_bbr_start");
  298         }
  299 }

Cache object: ad994858165055c9e015d766d25146c3


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