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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [md/] [linear.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
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/slab.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 void linear_status (struct seq_file *seq, mddev_t *mddev)
157
{
158
 
159
#undef MD_DEBUG
160
#ifdef MD_DEBUG
161
        int j;
162
        linear_conf_t *conf = mddev_to_conf(mddev);
163
 
164
        seq_printf(seq, "      ");
165
        for (j = 0; j < conf->nr_zones; j++)
166
        {
167
                seq_printf(seq, "[%s",
168
                        partition_name(conf->hash_table[j].dev0->dev));
169
 
170
                if (conf->hash_table[j].dev1)
171
                        seq_printf(seq, "/%s] ",
172
                          partition_name(conf->hash_table[j].dev1->dev));
173
                else
174
                        seq_printf(seq, "] ");
175
        }
176
        seq_printf(seq, "\n");
177
#endif
178
        seq_printf(seq, " %dk rounding", mddev->param.chunk_size/1024);
179
}
180
 
181
 
182
static mdk_personality_t linear_personality=
183
{
184
        name:           "linear",
185
        make_request:   linear_make_request,
186
        run:            linear_run,
187
        stop:           linear_stop,
188
        status:         linear_status,
189
};
190
 
191
static int md__init linear_init (void)
192
{
193
        return register_md_personality (LINEAR, &linear_personality);
194
}
195
 
196
static void linear_exit (void)
197
{
198
        unregister_md_personality (LINEAR);
199
}
200
 
201
 
202
module_init(linear_init);
203
module_exit(linear_exit);
204
MODULE_LICENSE("GPL");

powered by: WebSVN 2.1.0

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