Import 2.3.18pre1
[davej-history.git] / drivers / block / linear.c
blob3993417d077f1f7a4134b63aa63a0fb1c6d39d62
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>
8 Linear mode management functions.
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.
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.
20 #include <linux/module.h>
22 #include <linux/md.h>
23 #include <linux/malloc.h>
24 #include <linux/init.h>
26 #include "linear.h"
28 #define MAJOR_NR MD_MAJOR
29 #define MD_DRIVER
30 #define MD_PERSONALITY
32 static int linear_run (int minor, struct md_dev *mddev)
34 int cur=0, i, size, dev0_size, nb_zone;
35 struct linear_data *data;
37 MOD_INC_USE_COUNT;
39 mddev->private=kmalloc (sizeof (struct linear_data), GFP_KERNEL);
40 data=(struct linear_data *) mddev->private;
43 Find out the smallest device. This was previously done
44 at registry time, but since it violates modularity,
45 I moved it here... Any comment ? ;-)
48 data->smallest=mddev->devices;
49 for (i=1; i<mddev->nb_dev; i++)
50 if (data->smallest->size > mddev->devices[i].size)
51 data->smallest=mddev->devices+i;
53 nb_zone=data->nr_zones=
54 md_size[minor]/data->smallest->size +
55 (md_size[minor]%data->smallest->size ? 1 : 0);
57 data->hash_table=kmalloc (sizeof (struct linear_hash)*nb_zone, GFP_KERNEL);
59 size=mddev->devices[cur].size;
61 i=0;
62 while (cur<mddev->nb_dev)
64 data->hash_table[i].dev0=mddev->devices+cur;
66 if (size>=data->smallest->size) /* If we completely fill the slot */
68 data->hash_table[i++].dev1=NULL;
69 size-=data->smallest->size;
71 if (!size)
73 if (++cur==mddev->nb_dev) continue;
74 size=mddev->devices[cur].size;
77 continue;
80 if (++cur==mddev->nb_dev) /* Last dev, set dev1 as NULL */
82 data->hash_table[i].dev1=NULL;
83 continue;
86 dev0_size=size; /* Here, we use a 2nd dev to fill the slot */
87 size=mddev->devices[cur].size;
88 data->hash_table[i++].dev1=mddev->devices+cur;
89 size-=(data->smallest->size - dev0_size);
92 return 0;
95 static int linear_stop (int minor, struct md_dev *mddev)
97 struct linear_data *data=(struct linear_data *) mddev->private;
99 kfree (data->hash_table);
100 kfree (data);
102 MOD_DEC_USE_COUNT;
104 return 0;
108 static int linear_map (struct md_dev *mddev, kdev_t *rdev,
109 unsigned long *rsector, unsigned long size)
111 struct linear_data *data=(struct linear_data *) mddev->private;
112 struct linear_hash *hash;
113 struct real_dev *tmp_dev;
114 long block;
116 block=*rsector >> 1;
117 hash=data->hash_table+(block/data->smallest->size);
119 if (block >= (hash->dev0->size + hash->dev0->offset))
121 if (!hash->dev1)
123 printk ("linear_map : hash->dev1==NULL for block %ld\n", block);
124 return (-1);
127 tmp_dev=hash->dev1;
129 else
130 tmp_dev=hash->dev0;
132 if (block >= (tmp_dev->size + tmp_dev->offset) || block < tmp_dev->offset)
133 printk ("Block %ld out of bounds on dev %s size %d offset %d\n",
134 block, kdevname(tmp_dev->dev), tmp_dev->size, tmp_dev->offset);
136 *rdev=tmp_dev->dev;
137 *rsector=(block-(tmp_dev->offset)) << 1;
139 return (0);
142 static int linear_status (char *page, int minor, struct md_dev *mddev)
144 int sz=0;
146 #undef MD_DEBUG
147 #ifdef MD_DEBUG
148 int j;
149 struct linear_data *data=(struct linear_data *) mddev->private;
151 sz+=sprintf (page+sz, " ");
152 for (j=0; j<data->nr_zones; j++)
154 sz+=sprintf (page+sz, "[%s",
155 partition_name (data->hash_table[j].dev0->dev));
157 if (data->hash_table[j].dev1)
158 sz+=sprintf (page+sz, "/%s] ",
159 partition_name(data->hash_table[j].dev1->dev));
160 else
161 sz+=sprintf (page+sz, "] ");
164 sz+=sprintf (page+sz, "\n");
165 #endif
166 sz+=sprintf (page+sz, " %dk rounding", 1<<FACTOR_SHIFT(FACTOR(mddev)));
167 return sz;
171 static struct md_personality linear_personality=
173 "linear",
174 linear_map,
175 NULL,
176 NULL,
177 linear_run,
178 linear_stop,
179 linear_status,
180 NULL, /* no ioctls */
185 #ifndef MODULE
187 void __init linear_init (void)
189 register_md_personality (LINEAR, &linear_personality);
192 #else
194 int init_module (void)
196 return (register_md_personality (LINEAR, &linear_personality));
199 void cleanup_module (void)
201 unregister_md_personality (LINEAR);
204 #endif