root/drivers/block/linear.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. linear_run
  2. linear_stop
  3. linear_map
  4. linear_status
  5. linear_init
  6. init_module
  7. cleanup_module

   1 
   2 /*
   3    linear.c : Multiple Devices driver for Linux
   4               Copyright (C) 1994-96 Marc ZYNGIER
   5               <zyngier@ufr-info-p7.ibp.fr> or
   6               <maz@gloups.fdn.fr>
   7 
   8    Linear mode management functions.
   9 
  10    This program is free software; you can redistribute it and/or modify
  11    it under the terms of the GNU General Public License as published by
  12    the Free Software Foundation; either version 2, or (at your option)
  13    any later version.
  14    
  15    You should have received a copy of the GNU General Public License
  16    (for example /usr/src/linux/COPYING); if not, write to the Free
  17    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
  18 */
  19 
  20 #include <linux/module.h>
  21 
  22 #include <linux/md.h>
  23 #include <linux/linear.h>
  24 #include <linux/malloc.h>
  25 
  26 #define MAJOR_NR MD_MAJOR
  27 #define MD_DRIVER
  28 #define MD_PERSONALITY
  29 
  30 #include <linux/blk.h>
  31 
  32 static int linear_run (int minor, struct md_dev *mddev)
     /* [previous][next][first][last][top][bottom][index][help] */
  33 {
  34   int cur=0, i, size, dev0_size, nb_zone;
  35   struct linear_data *data;
  36 
  37   MOD_INC_USE_COUNT;
  38   
  39   mddev->private=kmalloc (sizeof (struct linear_data), GFP_KERNEL);
  40   data=(struct linear_data *) mddev->private;
  41 
  42   /*
  43      Find out the smallest device. This was previously done
  44      at registery time, but since it violates modularity,
  45      I moved it here... Any comment ? ;-)
  46    */
  47 
  48   data->smallest=devices[minor];
  49   for (i=1; i<mddev->nb_dev; i++)
  50     if (data->smallest->size > devices[minor][i].size)
  51       data->smallest=devices[minor]+i;
  52   
  53   nb_zone=data->nr_zones=
  54     md_size[minor]/data->smallest->size +
  55     (md_size[minor]%data->smallest->size ? 1 : 0);
  56   
  57   data->hash_table=kmalloc (sizeof (struct linear_hash)*nb_zone, GFP_KERNEL);
  58 
  59   size=devices[minor][cur].size;
  60 
  61   i=0;
  62   while (cur<mddev->nb_dev)
  63   {
  64     data->hash_table[i].dev0=devices[minor]+cur;
  65 
  66     if (size>=data->smallest->size) /* If we completly fill the slot */
  67     {
  68       data->hash_table[i++].dev1=NULL;
  69       size-=data->smallest->size;
  70 
  71       if (!size)
  72       {
  73         if (++cur==mddev->nb_dev) continue;
  74         size=devices[minor][cur].size;
  75       }
  76 
  77       continue;
  78     }
  79 
  80     if (++cur==mddev->nb_dev) /* Last dev, set dev1 as NULL */
  81     {
  82       data->hash_table[i].dev1=NULL;
  83       continue;
  84     }
  85 
  86     dev0_size=size;             /* Here, we use a 2nd dev to fill the slot */
  87     size=devices[minor][cur].size;
  88     data->hash_table[i++].dev1=devices[minor]+cur;
  89     size-=(data->smallest->size - dev0_size);
  90   }
  91 
  92   return 0;
  93 }
  94 
  95 static int linear_stop (int minor, struct md_dev *mddev)
     /* [previous][next][first][last][top][bottom][index][help] */
  96 {
  97   struct linear_data *data=(struct linear_data *) mddev->private;
  98   
  99   kfree (data->hash_table);
 100   kfree (data);
 101 
 102   MOD_DEC_USE_COUNT;
 103 
 104   return 0;
 105 }
 106 
 107 
 108 static int linear_map (int minor, struct md_dev *mddev, struct request *req)
     /* [previous][next][first][last][top][bottom][index][help] */
 109 {
 110   struct linear_data *data=(struct linear_data *) mddev->private;
 111   struct linear_hash *hash;
 112   struct real_dev *tmp_dev;
 113   long block, rblock;
 114   struct buffer_head *bh, *bh2;
 115   int queue, nblk;
 116   static struct request pending[MAX_REAL]={{0, }, };
 117 
 118   while (req->nr_sectors)
 119   {
 120     block=req->sector >> 1;
 121     hash=data->hash_table+(block/data->smallest->size);
 122     
 123     if (block >= (hash->dev0->size + hash->dev0->offset))
 124     {
 125       if (!hash->dev1)
 126         printk ("linear_map : hash->dev1==NULL for block %ld\n", block);
 127       tmp_dev=hash->dev1;
 128     }
 129     else
 130       tmp_dev=hash->dev0;
 131     
 132     if (block >= (tmp_dev->size + tmp_dev->offset) || block < tmp_dev->offset)
 133       printk ("Block %ld out of bounds on dev %04x size %d offset %d\n", block, tmp_dev->dev, tmp_dev->size, tmp_dev->offset);
 134     
 135     rblock=(block-(tmp_dev->offset));
 136     
 137     if (req->sem)                               /* This is a paging request */
 138     {
 139       req->rq_dev=tmp_dev->dev;
 140       req->sector=rblock << 1;
 141       add_request (blk_dev+MAJOR (tmp_dev->dev), req);
 142       
 143       return REDIRECTED_REQ;
 144     }
 145 
 146     queue=tmp_dev - devices[minor];
 147 
 148     for (nblk=0, bh=bh2=req->bh;
 149          bh && rblock + nblk + (bh->b_size >> 10) <= tmp_dev->size;
 150          nblk+=bh->b_size >> 10, bh2=bh, bh=bh->b_reqnext)
 151     {
 152       if (!buffer_locked(bh))
 153         printk("md%d: block %ld not locked\n", minor, bh->b_blocknr);
 154       
 155       bh->b_rdev=tmp_dev->dev;
 156     }
 157 
 158     pending[queue].rq_dev=tmp_dev->dev;
 159     pending[queue].cmd=req->cmd;
 160     pending[queue].sector=rblock << 1;
 161     pending[queue].nr_sectors=nblk << 1;
 162     pending[queue].current_nr_sectors=req->bh->b_size >> 9;
 163     pending[queue].bh=req->bh;
 164     pending[queue].bhtail=bh2;
 165     bh2->b_reqnext=NULL;
 166     
 167     req->bh=bh;
 168     req->sector+=nblk << 1;
 169     req->nr_sectors-=nblk << 1;
 170   }
 171 
 172   req->rq_status=RQ_INACTIVE;
 173   wake_up (&wait_for_request);
 174   make_md_request (pending, mddev->nb_dev);
 175   return REDIRECTED_REQ;
 176 }
 177 
 178 
 179 static int linear_status (char *page, int minor, struct md_dev *mddev)
     /* [previous][next][first][last][top][bottom][index][help] */
 180 {
 181   int sz=0;
 182 
 183 #undef MD_DEBUG
 184 #ifdef MD_DEBUG
 185   int j;
 186   struct linear_data *data=(struct linear_data *) mddev->private;
 187   
 188   sz+=sprintf (page+sz, "      ");
 189   for (j=0; j<data->nr_zones; j++)
 190   {
 191     sz+=sprintf (page+sz, "[%s",
 192                  partition_name (data->hash_table[j].dev0->dev));
 193 
 194     if (data->hash_table[j].dev1)
 195       sz+=sprintf (page+sz, "/%s] ",
 196                    partition_name(data->hash_table[j].dev1->dev));
 197     else
 198       sz+=sprintf (page+sz, "] ");
 199   }
 200 
 201   sz+=sprintf (page+sz, "\n");
 202 #endif
 203   return sz;
 204 }
 205 
 206 
 207 static struct md_personality linear_personality=
 208 {
 209   "linear",
 210   linear_map,
 211   linear_run,
 212   linear_stop,
 213   linear_status,
 214   NULL,                         /* no ioctls */
 215   0
 216 };
 217 
 218 
 219 #ifndef MODULE
 220 
 221 void linear_init (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 222 {
 223   register_md_personality (LINEAR, &linear_personality);
 224 }
 225 
 226 #else
 227 
 228 int init_module (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 229 {
 230   return (register_md_personality (LINEAR, &linear_personality));
 231 }
 232 
 233 void cleanup_module (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 234 {
 235   if (MOD_IN_USE)
 236     printk ("md linear : module still busy...\n");
 237   else
 238     unregister_md_personality (LINEAR);
 239 }
 240 
 241 #endif

/* [previous][next][first][last][top][bottom][index][help] */