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

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)