patch-2.3.43 linux/drivers/block/linear.c
Next file: linux/drivers/block/linear.h
Previous file: linux/drivers/block/ide.c
Back to the patch index
Back to the overall index
- Lines: 353
- Date:
Tue Feb 8 11:39:00 2000
- Orig file:
v2.3.42/linux/drivers/block/linear.c
- Orig date:
Mon Aug 9 10:23:09 1999
diff -u --recursive --new-file v2.3.42/linux/drivers/block/linear.c linux/drivers/block/linear.c
@@ -1,4 +1,3 @@
-
/*
linear.c : Multiple Devices driver for Linux
Copyright (C) 1994-96 Marc ZYNGIER
@@ -19,186 +18,204 @@
#include <linux/module.h>
-#include <linux/md.h>
+#include <linux/raid/md.h>
#include <linux/malloc.h>
-#include <linux/init.h>
-#include "linear.h"
+#include <linux/raid/linear.h>
#define MAJOR_NR MD_MAJOR
#define MD_DRIVER
#define MD_PERSONALITY
-static int linear_run (int minor, struct md_dev *mddev)
-{
- int cur=0, i, size, dev0_size, nb_zone;
- struct linear_data *data;
-
- MOD_INC_USE_COUNT;
-
- mddev->private=kmalloc (sizeof (struct linear_data), GFP_KERNEL);
- data=(struct linear_data *) mddev->private;
-
- /*
- Find out the smallest device. This was previously done
- at registry time, but since it violates modularity,
- I moved it here... Any comment ? ;-)
- */
-
- data->smallest=mddev->devices;
- for (i=1; i<mddev->nb_dev; i++)
- if (data->smallest->size > mddev->devices[i].size)
- data->smallest=mddev->devices+i;
-
- nb_zone=data->nr_zones=
- md_size[minor]/data->smallest->size +
- (md_size[minor]%data->smallest->size ? 1 : 0);
-
- data->hash_table=kmalloc (sizeof (struct linear_hash)*nb_zone, GFP_KERNEL);
-
- size=mddev->devices[cur].size;
-
- i=0;
- while (cur<mddev->nb_dev)
- {
- data->hash_table[i].dev0=mddev->devices+cur;
-
- if (size>=data->smallest->size) /* If we completely fill the slot */
- {
- data->hash_table[i++].dev1=NULL;
- size-=data->smallest->size;
-
- if (!size)
- {
- if (++cur==mddev->nb_dev) continue;
- size=mddev->devices[cur].size;
- }
-
- continue;
- }
-
- if (++cur==mddev->nb_dev) /* Last dev, set dev1 as NULL */
- {
- data->hash_table[i].dev1=NULL;
- continue;
- }
-
- dev0_size=size; /* Here, we use a 2nd dev to fill the slot */
- size=mddev->devices[cur].size;
- data->hash_table[i++].dev1=mddev->devices+cur;
- size-=(data->smallest->size - dev0_size);
- }
-
- return 0;
-}
-
-static int linear_stop (int minor, struct md_dev *mddev)
-{
- struct linear_data *data=(struct linear_data *) mddev->private;
-
- kfree (data->hash_table);
- kfree (data);
-
- MOD_DEC_USE_COUNT;
-
- return 0;
-}
-
-
-static int linear_map (struct md_dev *mddev, kdev_t *rdev,
- unsigned long *rsector, unsigned long size)
+static int linear_run (mddev_t *mddev)
{
- struct linear_data *data=(struct linear_data *) mddev->private;
- struct linear_hash *hash;
- struct real_dev *tmp_dev;
- long block;
-
- block=*rsector >> 1;
- hash=data->hash_table+(block/data->smallest->size);
-
- if (block >= (hash->dev0->size + hash->dev0->offset))
- {
- if (!hash->dev1)
- {
- printk ("linear_map : hash->dev1==NULL for block %ld\n", block);
- return (-1);
- }
+ linear_conf_t *conf;
+ struct linear_hash *table;
+ mdk_rdev_t *rdev;
+ int size, i, j, nb_zone;
+ unsigned int curr_offset;
+
+ MOD_INC_USE_COUNT;
+
+ conf = kmalloc (sizeof (*conf), GFP_KERNEL);
+ if (!conf)
+ goto out;
+ mddev->private = conf;
+
+ if (md_check_ordering(mddev)) {
+ printk("linear: disks are not ordered, aborting!\n");
+ goto out;
+ }
+ /*
+ * Find the smallest device.
+ */
+
+ conf->smallest = NULL;
+ curr_offset = 0;
+ ITERATE_RDEV_ORDERED(mddev,rdev,j) {
+ dev_info_t *disk = conf->disks + j;
+
+ disk->dev = rdev->dev;
+ disk->size = rdev->size;
+ disk->offset = curr_offset;
+
+ curr_offset += disk->size;
+
+ if (!conf->smallest || (disk->size < conf->smallest->size))
+ conf->smallest = disk;
+ }
+
+ nb_zone = conf->nr_zones =
+ md_size[mdidx(mddev)] / conf->smallest->size +
+ ((md_size[mdidx(mddev)] % conf->smallest->size) ? 1 : 0);
+
+ conf->hash_table = kmalloc (sizeof (struct linear_hash) * nb_zone,
+ GFP_KERNEL);
+ if (!conf->hash_table)
+ goto out;
+
+ /*
+ * Here we generate the linear hash table
+ */
+ table = conf->hash_table;
+ i = 0;
+ size = 0;
+ for (j = 0; j < mddev->nb_dev; j++) {
+ dev_info_t *disk = conf->disks + j;
+
+ if (size < 0) {
+ table->dev1 = disk;
+ table++;
+ }
+ size += disk->size;
+
+ while (size) {
+ table->dev0 = disk;
+ size -= conf->smallest->size;
+ if (size < 0)
+ break;
+ table->dev1 = NULL;
+ table++;
+ }
+ }
+ table->dev1 = NULL;
+
+ return 0;
+
+out:
+ if (conf)
+ kfree(conf);
+ MOD_DEC_USE_COUNT;
+ return 1;
+}
+
+static int linear_stop (mddev_t *mddev)
+{
+ linear_conf_t *conf = mddev_to_conf(mddev);
+
+ kfree(conf->hash_table);
+ kfree(conf);
+
+ MOD_DEC_USE_COUNT;
+
+ return 0;
+}
+
+static int linear_make_request (mddev_t *mddev, int rw, struct buffer_head * bh)
+{
+ linear_conf_t *conf = mddev_to_conf(mddev);
+ struct linear_hash *hash;
+ dev_info_t *tmp_dev;
+ long block;
+
+ block = bh->b_blocknr * (bh->b_size >> 10);
+ hash = conf->hash_table + (block / conf->smallest->size);
+
+ if (block >= (hash->dev0->size + hash->dev0->offset)) {
+ if (!hash->dev1) {
+ printk ("linear_make_request : hash->dev1==NULL for block %ld\n",
+ block);
+ return -1;
+ }
+ tmp_dev = hash->dev1;
+ } else
+ tmp_dev = hash->dev0;
- tmp_dev=hash->dev1;
- }
- else
- tmp_dev=hash->dev0;
-
- if (block >= (tmp_dev->size + tmp_dev->offset) || block < tmp_dev->offset)
- printk ("Block %ld out of bounds on dev %s size %d offset %d\n",
- block, kdevname(tmp_dev->dev), tmp_dev->size, tmp_dev->offset);
-
- *rdev=tmp_dev->dev;
- *rsector=(block-(tmp_dev->offset)) << 1;
+ if (block >= (tmp_dev->size + tmp_dev->offset)
+ || block < tmp_dev->offset) {
+ printk ("linear_make_request: Block %ld out of bounds on dev %s size %d offset %d\n", block, kdevname(tmp_dev->dev), tmp_dev->size, tmp_dev->offset);
+ return -1;
+ }
+ bh->b_rdev = tmp_dev->dev;
+ bh->b_rsector = (block - tmp_dev->offset) << 1;
- return (0);
+ generic_make_request(rw, bh);
+ return 0;
}
-static int linear_status (char *page, int minor, struct md_dev *mddev)
+static int linear_status (char *page, mddev_t *mddev)
{
- int sz=0;
+ int sz = 0;
#undef MD_DEBUG
#ifdef MD_DEBUG
- int j;
- struct linear_data *data=(struct linear_data *) mddev->private;
+ int j;
+ linear_conf_t *conf = mddev_to_conf(mddev);
- sz+=sprintf (page+sz, " ");
- for (j=0; j<data->nr_zones; j++)
- {
- sz+=sprintf (page+sz, "[%s",
- partition_name (data->hash_table[j].dev0->dev));
-
- if (data->hash_table[j].dev1)
- sz+=sprintf (page+sz, "/%s] ",
- partition_name(data->hash_table[j].dev1->dev));
- else
- sz+=sprintf (page+sz, "] ");
- }
-
- sz+=sprintf (page+sz, "\n");
+ sz += sprintf(page+sz, " ");
+ for (j = 0; j < conf->nr_zones; j++)
+ {
+ sz += sprintf(page+sz, "[%s",
+ partition_name(conf->hash_table[j].dev0->dev));
+
+ if (conf->hash_table[j].dev1)
+ sz += sprintf(page+sz, "/%s] ",
+ partition_name(conf->hash_table[j].dev1->dev));
+ else
+ sz += sprintf(page+sz, "] ");
+ }
+ sz += sprintf(page+sz, "\n");
#endif
- sz+=sprintf (page+sz, " %dk rounding", 1<<FACTOR_SHIFT(FACTOR(mddev)));
- return sz;
+ sz += sprintf(page+sz, " %dk rounding", mddev->param.chunk_size/1024);
+ return sz;
}
-static struct md_personality linear_personality=
+static mdk_personality_t linear_personality=
{
- "linear",
- linear_map,
- NULL,
- NULL,
- linear_run,
- linear_stop,
- linear_status,
- NULL, /* no ioctls */
- 0
+ "linear",
+ NULL,
+ linear_make_request,
+ NULL,
+ linear_run,
+ linear_stop,
+ linear_status,
+ NULL,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ NULL
};
-
#ifndef MODULE
-void __init linear_init (void)
+void md__init linear_init (void)
{
- register_md_personality (LINEAR, &linear_personality);
+ register_md_personality (LINEAR, &linear_personality);
}
#else
int init_module (void)
{
- return (register_md_personality (LINEAR, &linear_personality));
+ return (register_md_personality (LINEAR, &linear_personality));
}
void cleanup_module (void)
{
- unregister_md_personality (LINEAR);
+ unregister_md_personality (LINEAR);
}
#endif
+
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)