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 static int linear_run (int minor, struct md_dev *mddev)
     /* [previous][next][first][last][top][bottom][index][help] */
  31 {
  32   int cur=0, i, size, dev0_size, nb_zone;
  33   struct linear_data *data;
  34 
  35   MOD_INC_USE_COUNT;
  36   
  37   mddev->private=kmalloc (sizeof (struct linear_data), GFP_KERNEL);
  38   data=(struct linear_data *) mddev->private;
  39 
  40   /*
  41      Find out the smallest device. This was previously done
  42      at registry time, but since it violates modularity,
  43      I moved it here... Any comment ? ;-)
  44    */
  45 
  46   data->smallest=devices[minor];
  47   for (i=1; i<mddev->nb_dev; i++)
  48     if (data->smallest->size > devices[minor][i].size)
  49       data->smallest=devices[minor]+i;
  50   
  51   nb_zone=data->nr_zones=
  52     md_size[minor]/data->smallest->size +
  53     (md_size[minor]%data->smallest->size ? 1 : 0);
  54   
  55   data->hash_table=kmalloc (sizeof (struct linear_hash)*nb_zone, GFP_KERNEL);
  56 
  57   size=devices[minor][cur].size;
  58 
  59   i=0;
  60   while (cur<mddev->nb_dev)
  61   {
  62     data->hash_table[i].dev0=devices[minor]+cur;
  63 
  64     if (size>=data->smallest->size) /* If we completely fill the slot */
  65     {
  66       data->hash_table[i++].dev1=NULL;
  67       size-=data->smallest->size;
  68 
  69       if (!size)
  70       {
  71         if (++cur==mddev->nb_dev) continue;
  72         size=devices[minor][cur].size;
  73       }
  74 
  75       continue;
  76     }
  77 
  78     if (++cur==mddev->nb_dev) /* Last dev, set dev1 as NULL */
  79     {
  80       data->hash_table[i].dev1=NULL;
  81       continue;
  82     }
  83 
  84     dev0_size=size;             /* Here, we use a 2nd dev to fill the slot */
  85     size=devices[minor][cur].size;
  86     data->hash_table[i++].dev1=devices[minor]+cur;
  87     size-=(data->smallest->size - dev0_size);
  88   }
  89 
  90   return 0;
  91 }
  92 
  93 static int linear_stop (int minor, struct md_dev *mddev)
     /* [previous][next][first][last][top][bottom][index][help] */
  94 {
  95   struct linear_data *data=(struct linear_data *) mddev->private;
  96   
  97   kfree (data->hash_table);
  98   kfree (data);
  99 
 100   MOD_DEC_USE_COUNT;
 101 
 102   return 0;
 103 }
 104 
 105 
 106 static int linear_map (struct md_dev *mddev, kdev_t *rdev,
     /* [previous][next][first][last][top][bottom][index][help] */
 107                        unsigned long *rsector, unsigned long size)
 108 {
 109   struct linear_data *data=(struct linear_data *) mddev->private;
 110   struct linear_hash *hash;
 111   struct real_dev *tmp_dev;
 112   long block;
 113 
 114   block=*rsector >> 1;
 115   hash=data->hash_table+(block/data->smallest->size);
 116   
 117   if (block >= (hash->dev0->size + hash->dev0->offset))
 118   {
 119     if (!hash->dev1)
 120     {
 121       printk ("linear_map : hash->dev1==NULL for block %ld\n", block);
 122       return (-1);
 123     }
 124     
 125     tmp_dev=hash->dev1;
 126   }
 127   else
 128     tmp_dev=hash->dev0;
 129     
 130   if (block >= (tmp_dev->size + tmp_dev->offset) || block < tmp_dev->offset)
 131     printk ("Block %ld out of bounds on dev %04x size %d offset %d\n", block, tmp_dev->dev, tmp_dev->size, tmp_dev->offset);
 132   
 133   *rdev=tmp_dev->dev;
 134   *rsector=(block-(tmp_dev->offset)) << 1;
 135 
 136   return (0);
 137 }
 138 
 139 static int linear_status (char *page, int minor, struct md_dev *mddev)
     /* [previous][next][first][last][top][bottom][index][help] */
 140 {
 141   int sz=0;
 142 
 143 #undef MD_DEBUG
 144 #ifdef MD_DEBUG
 145   int j;
 146   struct linear_data *data=(struct linear_data *) mddev->private;
 147   
 148   sz+=sprintf (page+sz, "      ");
 149   for (j=0; j<data->nr_zones; j++)
 150   {
 151     sz+=sprintf (page+sz, "[%s",
 152                  partition_name (data->hash_table[j].dev0->dev));
 153 
 154     if (data->hash_table[j].dev1)
 155       sz+=sprintf (page+sz, "/%s] ",
 156                    partition_name(data->hash_table[j].dev1->dev));
 157     else
 158       sz+=sprintf (page+sz, "] ");
 159   }
 160 
 161   sz+=sprintf (page+sz, "\n");
 162 #endif
 163   return sz;
 164 }
 165 
 166 
 167 static struct md_personality linear_personality=
 168 {
 169   "linear",
 170   linear_map,
 171   linear_run,
 172   linear_stop,
 173   linear_status,
 174   NULL,                         /* no ioctls */
 175   0
 176 };
 177 
 178 
 179 #ifndef MODULE
 180 
 181 void linear_init (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 182 {
 183   register_md_personality (LINEAR, &linear_personality);
 184 }
 185 
 186 #else
 187 
 188 int init_module (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 189 {
 190   return (register_md_personality (LINEAR, &linear_personality));
 191 }
 192 
 193 void cleanup_module (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 194 {
 195   if (MOD_IN_USE)
 196     printk ("md linear : module still busy...\n");
 197   else
 198     unregister_md_personality (LINEAR);
 199 }
 200 
 201 #endif

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