OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [drivers/] [block/] [raid0.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1626 jcastillo
 
2
/*
3
   raid0.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
   RAID-0 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
#include <linux/md.h>
22
#include <linux/raid0.h>
23
#include <linux/malloc.h>
24
 
25
#define MAJOR_NR MD_MAJOR
26
#define MD_DRIVER
27
#define MD_PERSONALITY
28
 
29
static int create_strip_zones (int minor, struct md_dev *mddev)
30
{
31
  int i, j, c=0;
32
  int current_offset=0;
33
  struct real_dev *smallest_by_zone;
34
  struct raid0_data *data=(struct raid0_data *) mddev->private;
35
 
36
  data->nr_strip_zones=1;
37
 
38
  for (i=1; i<mddev->nb_dev; i++)
39
  {
40
    for (j=0; j<i; j++)
41
      if (mddev->devices[i].size==mddev->devices[j].size)
42
      {
43
        c=1;
44
        break;
45
      }
46
 
47
    if (!c)
48
      data->nr_strip_zones++;
49
 
50
    c=0;
51
  }
52
 
53
  if ((data->strip_zone=vmalloc(sizeof(struct strip_zone)*data->nr_strip_zones)) == NULL)
54
    return 1;
55
 
56
  data->smallest=NULL;
57
 
58
  for (i=0; i<data->nr_strip_zones; i++)
59
  {
60
    data->strip_zone[i].dev_offset=current_offset;
61
    smallest_by_zone=NULL;
62
    c=0;
63
 
64
    for (j=0; j<mddev->nb_dev; j++)
65
      if (mddev->devices[j].size>current_offset)
66
      {
67
        data->strip_zone[i].dev[c++]=mddev->devices+j;
68
        if (!smallest_by_zone ||
69
            smallest_by_zone->size > mddev->devices[j].size)
70
          smallest_by_zone=mddev->devices+j;
71
      }
72
 
73
    data->strip_zone[i].nb_dev=c;
74
    data->strip_zone[i].size=(smallest_by_zone->size-current_offset)*c;
75
 
76
    if (!data->smallest ||
77
        data->smallest->size > data->strip_zone[i].size)
78
      data->smallest=data->strip_zone+i;
79
 
80
    data->strip_zone[i].zone_offset=i ? (data->strip_zone[i-1].zone_offset+
81
                                           data->strip_zone[i-1].size) : 0;
82
    current_offset=smallest_by_zone->size;
83
  }
84
  return 0;
85
}
86
 
87
static int raid0_run (int minor, struct md_dev *mddev)
88
{
89
  int cur=0, i=0, size, zone0_size, nb_zone;
90
  struct raid0_data *data;
91
 
92
  MOD_INC_USE_COUNT;
93
 
94
  if ((mddev->private=vmalloc (sizeof (struct raid0_data))) == NULL) return 1;
95
  data=(struct raid0_data *) mddev->private;
96
 
97
  if (create_strip_zones (minor, mddev)) return 1;
98
 
99
  nb_zone=data->nr_zones=
100
    md_size[minor]/data->smallest->size +
101
    (md_size[minor]%data->smallest->size ? 1 : 0);
102
 
103
  printk ("raid0 : Allocating %d bytes for hash.\n",sizeof(struct raid0_hash)*nb_zone);
104
  if ((data->hash_table=vmalloc (sizeof (struct raid0_hash)*nb_zone)) == NULL)
105
    return 1;
106
 
107
  size=data->strip_zone[cur].size;
108
 
109
  i=0;
110
  while (cur<data->nr_strip_zones)
111
  {
112
    data->hash_table[i].zone0=data->strip_zone+cur;
113
 
114
    if (size>=data->smallest->size)/* If we completely fill the slot */
115
    {
116
      data->hash_table[i++].zone1=NULL;
117
      size-=data->smallest->size;
118
 
119
      if (!size)
120
      {
121
        if (++cur==data->nr_strip_zones) continue;
122
        size=data->strip_zone[cur].size;
123
      }
124
 
125
      continue;
126
    }
127
 
128
    if (++cur==data->nr_strip_zones) /* Last dev, set unit1 as NULL */
129
    {
130
      data->hash_table[i].zone1=NULL;
131
      continue;
132
    }
133
 
134
    zone0_size=size;            /* Here, we use a 2nd dev to fill the slot */
135
    size=data->strip_zone[cur].size;
136
    data->hash_table[i++].zone1=data->strip_zone+cur;
137
    size-=(data->smallest->size - zone0_size);
138
  }
139
 
140
  return (0);
141
}
142
 
143
 
144
static int raid0_stop (int minor, struct md_dev *mddev)
145
{
146
  struct raid0_data *data=(struct raid0_data *) mddev->private;
147
 
148
  vfree (data->hash_table);
149
  vfree (data->strip_zone);
150
  vfree (data);
151
 
152
  MOD_DEC_USE_COUNT;
153
  return 0;
154
}
155
 
156
/*
157
 * FIXME - We assume some things here :
158
 * - requested buffers NEVER bigger than chunk size,
159
 * - requested buffers NEVER cross stripes limits.
160
 * Of course, those facts may not be valid anymore (and surely won't...)
161
 * Hey guys, there's some work out there ;-)
162
 */
163
static int raid0_map (struct md_dev *mddev, kdev_t *rdev,
164
                      unsigned long *rsector, unsigned long size)
165
{
166
  struct raid0_data *data=(struct raid0_data *) mddev->private;
167
  static struct raid0_hash *hash;
168
  struct strip_zone *zone;
169
  struct real_dev *tmp_dev;
170
  int blk_in_chunk, factor, chunk, chunk_size;
171
  long block, rblock;
172
 
173
  factor=FACTOR(mddev);
174
  chunk_size=(1UL << FACTOR_SHIFT(factor));
175
  block=*rsector >> 1;
176
  hash=data->hash_table+(block/data->smallest->size);
177
 
178
  /* Sanity check */
179
  if ((chunk_size*2)<(*rsector % (chunk_size*2))+size)
180
  {
181
    printk ("raid0_convert : can't convert block across chunks or bigger than %dk %ld %ld\n", chunk_size, *rsector, size);
182
    return (-1);
183
  }
184
 
185
  if (block >= (hash->zone0->size +
186
                hash->zone0->zone_offset))
187
  {
188
    if (!hash->zone1)
189
    {
190
      printk ("raid0_convert : hash->zone1==NULL for block %ld\n", block);
191
      return (-1);
192
    }
193
 
194
    zone=hash->zone1;
195
  }
196
  else
197
    zone=hash->zone0;
198
 
199
  blk_in_chunk=block & (chunk_size -1);
200
  chunk=(block - zone->zone_offset) / (zone->nb_dev<<FACTOR_SHIFT(factor));
201
  tmp_dev=zone->dev[(block >> FACTOR_SHIFT(factor)) % zone->nb_dev];
202
  rblock=(chunk << FACTOR_SHIFT(factor)) + blk_in_chunk + zone->dev_offset;
203
 
204
  *rdev=tmp_dev->dev;
205
  *rsector=rblock<<1;
206
 
207
  return (0);
208
}
209
 
210
 
211
static int raid0_status (char *page, int minor, struct md_dev *mddev)
212
{
213
  int sz=0;
214
#undef MD_DEBUG
215
#ifdef MD_DEBUG
216
  int j, k;
217
  struct raid0_data *data=(struct raid0_data *) mddev->private;
218
 
219
  sz+=sprintf (page+sz, "      ");
220
  for (j=0; j<data->nr_zones; j++)
221
  {
222
    sz+=sprintf (page+sz, "[z%d",
223
                 data->hash_table[j].zone0-data->strip_zone);
224
    if (data->hash_table[j].zone1)
225
      sz+=sprintf (page+sz, "/z%d] ",
226
                   data->hash_table[j].zone1-data->strip_zone);
227
    else
228
      sz+=sprintf (page+sz, "] ");
229
  }
230
 
231
  sz+=sprintf (page+sz, "\n");
232
 
233
  for (j=0; j<data->nr_strip_zones; j++)
234
  {
235
    sz+=sprintf (page+sz, "      z%d=[", j);
236
    for (k=0; k<data->strip_zone[j].nb_dev; k++)
237
      sz+=sprintf (page+sz, "%s/",
238
                   partition_name(data->strip_zone[j].dev[k]->dev));
239
    sz--;
240
    sz+=sprintf (page+sz, "] zo=%d do=%d s=%d\n",
241
                 data->strip_zone[j].zone_offset,
242
                 data->strip_zone[j].dev_offset,
243
                 data->strip_zone[j].size);
244
  }
245
#endif
246
  sz+=sprintf (page+sz, " %dk chunks", 1<<FACTOR_SHIFT(FACTOR(mddev)));
247
  return sz;
248
}
249
 
250
 
251
static struct md_personality raid0_personality=
252
{
253
  "raid0",
254
  raid0_map,
255
  NULL,                         /* no special make_request */
256
  NULL,                         /* no special end_request */
257
  raid0_run,
258
  raid0_stop,
259
  raid0_status,
260
  NULL,                         /* no ioctls */
261
  0,
262
  NULL,                         /* no error_handler */
263
};
264
 
265
 
266
#ifndef MODULE
267
 
268
void raid0_init (void)
269
{
270
  register_md_personality (RAID0, &raid0_personality);
271
}
272
 
273
#else
274
 
275
int init_module (void)
276
{
277
  return (register_md_personality (RAID0, &raid0_personality));
278
}
279
 
280
void cleanup_module (void)
281
{
282
  unregister_md_personality (RAID0);
283
}
284
 
285
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.