~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/md/linear.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2    linear.c : Multiple Devices driver for Linux
  3               Copyright (C) 1994-96 Marc ZYNGIER
  4               <zyngier@ufr-info-p7.ibp.fr> or
  5               <maz@gloups.fdn.fr>
  6 
  7    Linear mode management functions.
  8 
  9    This program is free software; you can redistribute it and/or modify
 10    it under the terms of the GNU General Public License as published by
 11    the Free Software Foundation; either version 2, or (at your option)
 12    any later version.
 13    
 14    You should have received a copy of the GNU General Public License
 15    (for example /usr/src/linux/COPYING); if not, write to the Free
 16    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
 17 */
 18 
 19 #include <linux/module.h>
 20 
 21 #include <linux/raid/md.h>
 22 #include <linux/malloc.h>
 23 
 24 #include <linux/raid/linear.h>
 25 
 26 #define MAJOR_NR MD_MAJOR
 27 #define MD_DRIVER
 28 #define MD_PERSONALITY
 29 
 30 static int linear_run (mddev_t *mddev)
 31 {
 32         linear_conf_t *conf;
 33         struct linear_hash *table;
 34         mdk_rdev_t *rdev;
 35         int size, i, j, nb_zone;
 36         unsigned int curr_offset;
 37 
 38         MOD_INC_USE_COUNT;
 39 
 40         conf = kmalloc (sizeof (*conf), GFP_KERNEL);
 41         if (!conf)
 42                 goto out;
 43         mddev->private = conf;
 44 
 45         if (md_check_ordering(mddev)) {
 46                 printk("linear: disks are not ordered, aborting!\n");
 47                 goto out;
 48         }
 49         /*
 50          * Find the smallest device.
 51          */
 52 
 53         conf->smallest = NULL;
 54         curr_offset = 0;
 55         ITERATE_RDEV_ORDERED(mddev,rdev,j) {
 56                 dev_info_t *disk = conf->disks + j;
 57 
 58                 disk->dev = rdev->dev;
 59                 disk->size = rdev->size;
 60                 disk->offset = curr_offset;
 61 
 62                 curr_offset += disk->size;
 63 
 64                 if (!conf->smallest || (disk->size < conf->smallest->size))
 65                         conf->smallest = disk;
 66         }
 67 
 68         nb_zone = conf->nr_zones =
 69                 md_size[mdidx(mddev)] / conf->smallest->size +
 70                 ((md_size[mdidx(mddev)] % conf->smallest->size) ? 1 : 0);
 71   
 72         conf->hash_table = kmalloc (sizeof (struct linear_hash) * nb_zone,
 73                                         GFP_KERNEL);
 74         if (!conf->hash_table)
 75                 goto out;
 76 
 77         /*
 78          * Here we generate the linear hash table
 79          */
 80         table = conf->hash_table;
 81         i = 0;
 82         size = 0;
 83         for (j = 0; j < mddev->nb_dev; j++) {
 84                 dev_info_t *disk = conf->disks + j;
 85 
 86                 if (size < 0) {
 87                         table[-1].dev1 = disk;
 88                 }
 89                 size += disk->size;
 90 
 91                 while (size>0) {
 92                         table->dev0 = disk;
 93                         table->dev1 = NULL;
 94                         size -= conf->smallest->size;
 95                         table++;
 96                 }
 97         }
 98         if (table-conf->hash_table != nb_zone)
 99                 BUG();
100 
101         return 0;
102 
103 out:
104         if (conf)
105                 kfree(conf);
106         MOD_DEC_USE_COUNT;
107         return 1;
108 }
109 
110 static int linear_stop (mddev_t *mddev)
111 {
112         linear_conf_t *conf = mddev_to_conf(mddev);
113   
114         kfree(conf->hash_table);
115         kfree(conf);
116 
117         MOD_DEC_USE_COUNT;
118 
119         return 0;
120 }
121 
122 static int linear_make_request (mddev_t *mddev,
123                         int rw, struct buffer_head * bh)
124 {
125         linear_conf_t *conf = mddev_to_conf(mddev);
126         struct linear_hash *hash;
127         dev_info_t *tmp_dev;
128         long block;
129 
130         block = bh->b_rsector >> 1;
131         hash = conf->hash_table + (block / conf->smallest->size);
132   
133         if (block >= (hash->dev0->size + hash->dev0->offset)) {
134                 if (!hash->dev1) {
135                         printk ("linear_make_request : hash->dev1==NULL for block %ld\n",
136                                                 block);
137                         buffer_IO_error(bh);
138                         return 0;
139                 }
140                 tmp_dev = hash->dev1;
141         } else
142                 tmp_dev = hash->dev0;
143     
144         if (block >= (tmp_dev->size + tmp_dev->offset)
145                                 || block < tmp_dev->offset) {
146                 printk ("linear_make_request: Block %ld out of bounds on dev %s size %ld offset %ld\n", block, kdevname(tmp_dev->dev), tmp_dev->size, tmp_dev->offset);
147                 buffer_IO_error(bh);
148                 return 0;
149         }
150         bh->b_rdev = tmp_dev->dev;
151         bh->b_rsector = bh->b_rsector - (tmp_dev->offset << 1);
152 
153         return 1;
154 }
155 
156 static int linear_status (char *page, mddev_t *mddev)
157 {
158         int sz = 0;
159 
160 #undef MD_DEBUG
161 #ifdef MD_DEBUG
162         int j;
163         linear_conf_t *conf = mddev_to_conf(mddev);
164   
165         sz += sprintf(page+sz, "      ");
166         for (j = 0; j < conf->nr_zones; j++)
167         {
168                 sz += sprintf(page+sz, "[%s",
169                         partition_name(conf->hash_table[j].dev0->dev));
170 
171                 if (conf->hash_table[j].dev1)
172                         sz += sprintf(page+sz, "/%s] ",
173                           partition_name(conf->hash_table[j].dev1->dev));
174                 else
175                         sz += sprintf(page+sz, "] ");
176         }
177         sz += sprintf(page+sz, "\n");
178 #endif
179         sz += sprintf(page+sz, " %dk rounding", mddev->param.chunk_size/1024);
180         return sz;
181 }
182 
183 
184 static mdk_personality_t linear_personality=
185 {
186         name:           "linear",
187         make_request:   linear_make_request,
188         run:            linear_run,
189         stop:           linear_stop,
190         status:         linear_status,
191 };
192 
193 static int md__init linear_init (void)
194 {
195         return register_md_personality (LINEAR, &linear_personality);
196 }
197 
198 static void linear_exit (void)
199 {
200         unregister_md_personality (LINEAR);
201 }
202 
203 
204 module_init(linear_init);
205 module_exit(linear_exit);
206 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.