Author: marcus                       Date: Wed Oct 25 07:09:19 2006 GMT
Module: SOURCES                       Tag: HEAD
---- Log message:
- EVMS 2.5.5
- LVM2 from dm 1.01.05

---- Files affected:
SOURCES:
   linux-2.4.32-evms-2.5.5.patch (NONE -> 1.1)  (NEW), 
linux-2.4.28-pre4-devmapper-ioctl.patch (NONE -> 1.1)  (NEW), 
linux-2.4.22-VFS-lock.patch (NONE -> 1.1)  (NEW)

---- Diffs:

================================================================
Index: SOURCES/linux-2.4.32-evms-2.5.5.patch
diff -u /dev/null SOURCES/linux-2.4.32-evms-2.5.5.patch:1.1
--- /dev/null   Wed Oct 25 09:09:19 2006
+++ SOURCES/linux-2.4.32-evms-2.5.5.patch       Wed Oct 25 09:09:13 2006
@@ -0,0 +1,1491 @@
+BBR Target.
+
+--- diff/drivers/md/Config.in  2004-12-16 13:25:08.317323488 -0600
++++ source/drivers/md/Config.in        2004-12-16 13:25:32.576635512 -0600
+@@ -16,5 +16,8 @@
+ dep_tristate ' Logical volume manager (LVM) support' CONFIG_BLK_DEV_LVM 
$CONFIG_MD
+ dep_tristate ' Device-mapper support' CONFIG_BLK_DEV_DM $CONFIG_MD
+ dep_tristate '  Mirror (RAID-1) support' CONFIG_BLK_DEV_DM_MIRROR 
$CONFIG_BLK_DEV_DM
++if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
++   dep_tristate '  Bad Block Relocation Device Target (EXPERIMENTAL)' 
CONFIG_BLK_DEV_DM_BBR $CONFIG_BLK_DEV_DM
++fi
+ 
+ endmenu
+--- diff/drivers/md/Makefile   2004-12-16 13:25:08.326322120 -0600
++++ source/drivers/md/Makefile 2004-12-16 13:25:32.577635360 -0600
+@@ -30,6 +30,7 @@
+ 
+ obj-$(CONFIG_BLK_DEV_DM)              += dm-mod.o
+ obj-$(CONFIG_BLK_DEV_DM_MIRROR)               += dm-mirror.o
++obj-$(CONFIG_BLK_DEV_DM_BBR)          += dm-bbr.o
+ 
+ include $(TOPDIR)/Rules.make
+ 
+--- diff/drivers/md/dm-bbr.c   1969-12-31 18:00:00.000000000 -0600
++++ source/drivers/md/dm-bbr.c 2004-12-16 13:25:37.149940264 -0600
+@@ -0,0 +1,1013 @@
++/*
++ *   (C) Copyright IBM Corp. 2002, 2004
++ *
++ *   This program is free software;  you can redistribute it and/or modify
++ *   it under the terms of the GNU General Public License as published by
++ *   the Free Software Foundation; either version 2 of the License, or
++ *   (at your option) any later version.
++ *
++ *   This program is distributed in the hope that it will be useful,
++ *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
++ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
++ *   the GNU General Public License for more details.
++ *
++ *   You should have received a copy of the GNU General Public License
++ *   along with this program;  if not, write to the Free Software
++ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ * linux/drivers/md/dm-bbr.c
++ *
++ * Bad-block-relocation (BBR) target for device-mapper.
++ *
++ * The BBR target is designed to remap I/O write failures to another safe
++ * location on disk. Note that most disk drives have BBR built into them,
++ * this means that our software BBR will be only activated when all hardware
++ * BBR replacement sectors have been used.
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/blkdev.h>
++#include <linux/spinlock.h>
++#include <linux/slab.h>
++#include <linux/mempool.h>
++
++#include "dm.h"
++#include "dm-bh-list.h"
++#include "dm-bh-record.h"
++#include "dm-bbr.h"
++#include "dm-io.h"
++#include "dm-daemon.h"
++
++static struct dm_daemon bbr_daemon;
++static LIST_HEAD(bbr_daemon_list);
++static DECLARE_MUTEX(bbr_daemon_list_lock);
++static kmem_cache_t *bbr_remap_cache;
++static kmem_cache_t *bbr_io_cache;
++static mempool_t *bbr_io_pool;
++
++/**
++ * bbr_binary_tree_destroy
++ *
++ * Destroy the binary tree.
++ **/
++static void bbr_binary_tree_destroy(struct bbr_runtime_remap *root)
++{
++      struct bbr_runtime_remap **link = NULL;
++      struct bbr_runtime_remap *node = root;
++
++      while (node) {
++              if (node->left) {
++                      link = &(node->left);
++                      node = node->left;
++                      continue;
++              }
++              if (node->right) {
++                      link = &(node->right);
++                      node = node->right;
++                      continue;
++              }
++
++              kmem_cache_free(bbr_remap_cache, node);
++              if (node == root) {
++                      /* If root is deleted, we're done. */
++                      break;
++              }
++
++              /* Back to root. */
++              node = root;
++              *link = NULL;
++      }
++}
++
++static void bbr_free_remap(struct bbr_private *bbr_id)
++{
++      spin_lock_irq(&bbr_id->remap_root_lock);
++      bbr_binary_tree_destroy(bbr_id->remap_root);
++      bbr_id->remap_root = NULL;
++      spin_unlock_irq(&bbr_id->remap_root_lock);
++}
++
++static struct bbr_private *bbr_alloc_private(void)
++{
++      struct bbr_private *bbr_id;
++
++      bbr_id = kmalloc(sizeof(*bbr_id), GFP_KERNEL);
++      if (bbr_id) {
++              memset(bbr_id, 0, sizeof(*bbr_id));
++              INIT_LIST_HEAD(&bbr_id->list);
++              bbr_id->remap_root_lock = SPIN_LOCK_UNLOCKED;
++              bbr_id->remap_ios_lock = SPIN_LOCK_UNLOCKED;
++              bbr_id->in_use_replacement_blks = (atomic_t)ATOMIC_INIT(0);
++      }
++
++      return bbr_id;
++}
++
++static void bbr_free_private(struct bbr_private *bbr_id)
++{
++      if (bbr_id->bbr_table) {
++              kfree(bbr_id->bbr_table);
++      }
++      bbr_free_remap(bbr_id);
++      kfree(bbr_id);
++}
++
++static u32 crc_table[256];
++static u32 crc_table_built = 0;
++
++static void build_crc_table(void)
++{
++      u32 i, j, crc;
++
++      for (i = 0; i <= 255; i++) {
++              crc = i;
++              for (j = 8; j > 0; j--) {
++                      if (crc & 1)
++                              crc = (crc >> 1) ^ CRC_POLYNOMIAL;
++                      else
++                              crc >>= 1;
++              }
++              crc_table[i] = crc;
++      }
++      crc_table_built = 1;
++}
++
++static u32 calculate_crc(u32 crc, void *buffer, u32 buffersize)
++{
++      unsigned char *current_byte;
++      u32 temp1, temp2, i;
++
++      current_byte = (unsigned char *) buffer;
++      /* Make sure the crc table is available */
++      if (!crc_table_built)
++              build_crc_table();
++      /* Process each byte in the buffer. */
++      for (i = 0; i < buffersize; i++) {
++              temp1 = (crc >> 8) & 0x00FFFFFF;
++              temp2 = crc_table[(crc ^ (u32) * current_byte) &
++                                (u32) 0xff];
++              current_byte++;
++              crc = temp1 ^ temp2;
++      }
++      return crc;
++}
++
++/**
++ * le_bbr_table_sector_to_cpu
++ *
++ * Convert bbr meta data from on-disk (LE) format
++ * to the native cpu endian format.
++ **/
++static void le_bbr_table_sector_to_cpu(struct bbr_table *p)
++{
++      int i;
++      p->signature            = le32_to_cpup(&p->signature);
++      p->crc                  = le32_to_cpup(&p->crc);
++      p->sequence_number      = le32_to_cpup(&p->sequence_number);
++      p->in_use_cnt           = le32_to_cpup(&p->in_use_cnt);
++      for (i = 0; i < BBR_ENTRIES_PER_SECT; i++) {
++              p->entries[i].bad_sect =
++                      le64_to_cpup(&p->entries[i].bad_sect);
++              p->entries[i].replacement_sect =
++                      le64_to_cpup(&p->entries[i].replacement_sect);
++      }
++}
++
++/**
++ * cpu_bbr_table_sector_to_le
++ *
++ * Convert bbr meta data from cpu endian format to on-disk (LE) format
++ **/
++static void cpu_bbr_table_sector_to_le(struct bbr_table *p,
++                                     struct bbr_table *le)
++{
++      int i;
++      le->signature           = cpu_to_le32p(&p->signature);
++      le->crc                 = cpu_to_le32p(&p->crc);
++      le->sequence_number     = cpu_to_le32p(&p->sequence_number);
++      le->in_use_cnt          = cpu_to_le32p(&p->in_use_cnt);
++      for (i = 0; i < BBR_ENTRIES_PER_SECT; i++) {
++              le->entries[i].bad_sect =
++                      cpu_to_le64p(&p->entries[i].bad_sect);
++              le->entries[i].replacement_sect =
++                      cpu_to_le64p(&p->entries[i].replacement_sect);
++      }
++}
++
++/**
++ * validate_bbr_table_sector
++ *
++ * Check the specified BBR table sector for a valid signature and CRC. If it's
++ * valid, endian-convert the table sector.
++ **/
++static int validate_bbr_table_sector(struct bbr_table *p)
++{
++      int rc = 0;
++      int org_crc, final_crc;
++
++      if (le32_to_cpup(&p->signature) != BBR_TABLE_SIGNATURE) {
++              DMERR("BBR table signature doesn't match!");
++              DMERR("Found 0x%x. Expecting 0x%x",
++                    le32_to_cpup(&p->signature), BBR_TABLE_SIGNATURE);
++              rc = -EINVAL;
++              goto out;
++      }
++
++      if (!p->crc) {
++              DMERR("BBR table sector has no CRC!");
++              rc = -EINVAL;
++              goto out;
++      }
++
++      org_crc = le32_to_cpup(&p->crc);
++      p->crc = 0;
++      final_crc = calculate_crc(INITIAL_CRC, (void *)p, sizeof(*p));
++      if (final_crc != org_crc) {
++              DMERR("CRC failed!");
++              DMERR("Found 0x%x. Expecting 0x%x",
++                    org_crc, final_crc);
++              rc = -EINVAL;
++              goto out;
++      }
++
++      p->crc = cpu_to_le32p(&org_crc);
++      le_bbr_table_sector_to_cpu(p);
++
++out:
++      return rc;
++}
++
++/**
++ * bbr_binary_tree_insert
++ *
++ * Insert a node into the binary tree.
++ **/
++static void bbr_binary_tree_insert(struct bbr_runtime_remap **root,
++                                 struct bbr_runtime_remap *newnode)
++{
++      struct bbr_runtime_remap **node = root;
++      while (node && *node) {
++              if (newnode->remap.bad_sect > (*node)->remap.bad_sect) {
++                      node = &((*node)->right);
++              } else {
++                      node = &((*node)->left);
++              }
++      }
++
++      newnode->left = newnode->right = NULL;
++      *node = newnode;
++}
++
++/**
++ * bbr_binary_search
++ *
++ * Search for a node that contains bad_sect == lsn.
++ **/
++static struct bbr_runtime_remap *bbr_binary_search(
++      struct bbr_runtime_remap *root,
++      u64 lsn)
++{
++      struct bbr_runtime_remap *node = root;
++      while (node) {
++              if (node->remap.bad_sect == lsn) {
++                      break;
++              }
++              if (lsn > node->remap.bad_sect) {
++                      node = node->right;
++              } else {
++                      node = node->left;
++              }
++      }
++      return node;
++}
++
++/**
++ * bbr_insert_remap_entry
++ *
++ * Create a new remap entry and add it to the binary tree for this node.
++ **/
++static int bbr_insert_remap_entry(struct bbr_private *bbr_id,
++                                struct bbr_table_entry *new_bbr_entry)
++{
++      struct bbr_runtime_remap *newnode;
++
++      newnode = kmem_cache_alloc(bbr_remap_cache, GFP_NOIO);
++      if (!newnode) {
++              DMERR("Could not allocate from remap cache!");
++              return -ENOMEM;
++      }
++      newnode->remap.bad_sect  = new_bbr_entry->bad_sect;
++      newnode->remap.replacement_sect = new_bbr_entry->replacement_sect;
++      spin_lock_irq(&bbr_id->remap_root_lock);
++      bbr_binary_tree_insert(&bbr_id->remap_root, newnode);
++      spin_unlock_irq(&bbr_id->remap_root_lock);
++      return 0;
++}
++
++/**
++ * bbr_table_to_remap_list
++ *
++ * The on-disk bbr table is sorted by the replacement sector LBA. In order to
++ * improve run time performance, the in memory remap list must be sorted by
++ * the bad sector LBA. This function is called at discovery time to initialize
++ * the remap list. This function assumes that at least one copy of meta data
++ * is valid.
++ **/
++static u32 bbr_table_to_remap_list(struct bbr_private *bbr_id)
++{
++      u32 in_use_blks = 0;
++      int i, j;
++      struct bbr_table *p;
++
++      for (i = 0, p = bbr_id->bbr_table;
++           i < bbr_id->nr_sects_bbr_table;
++           i++, p++) {
++              if (!p->in_use_cnt) {
++                      break;
++              }
++              in_use_blks += p->in_use_cnt;
++              for (j = 0; j < p->in_use_cnt; j++) {
++                      bbr_insert_remap_entry(bbr_id, &p->entries[j]);
++              }
++      }
++      if (in_use_blks) {
++              DMWARN("There are %u BBR entries for device %s",
++                     in_use_blks, dm_kdevname(bbr_id->dev->dev));
++      }
++
++      return in_use_blks;
++}
++
++/**
++ * bbr_search_remap_entry
++ *
++ * Search remap entry for the specified sector. If found, return a pointer to
++ * the table entry. Otherwise, return NULL.
++ **/
++static struct bbr_table_entry *bbr_search_remap_entry(
++      struct bbr_private *bbr_id,
++      u64 lsn)
++{
++      struct bbr_runtime_remap *p;
++
++      spin_lock_irq(&bbr_id->remap_root_lock);
++      p = bbr_binary_search(bbr_id->remap_root, lsn);
++      spin_unlock_irq(&bbr_id->remap_root_lock);
++      if (p) {
++              return (&p->remap);
++      } else {
++              return NULL;
++      }
++}
++
++/**
++ * bbr_remap
++ *
++ * If *lsn is in the remap table, return TRUE and modify *lsn,
++ * else, return FALSE.
++ **/
++static inline int bbr_remap(struct bbr_private *bbr_id,
++                          u64 *lsn)
++{
++      struct bbr_table_entry *e;
++
++      if (atomic_read(&bbr_id->in_use_replacement_blks)) {
++              e = bbr_search_remap_entry(bbr_id, *lsn);
++              if (e) {
++                      *lsn = e->replacement_sect;
++                      return 1;
++              }
++      }
++      return 0;
++}
++
++/**
++ * bbr_remap_probe
++ *
++ * If any of the sectors in the range [lsn, lsn+nr_sects] are in the remap
++ * table return TRUE, Else, return FALSE.
++ **/
++static inline int bbr_remap_probe(struct bbr_private *bbr_id,
++                                u64 lsn, u64 nr_sects)
++{
++      u64 tmp, cnt;
++
++      if (atomic_read(&bbr_id->in_use_replacement_blks)) {
++              for (cnt = 0, tmp = lsn;
++                   cnt < nr_sects;
++                   cnt += bbr_id->blksize_in_sects, tmp = lsn + cnt) {
++                      if (bbr_remap(bbr_id,&tmp)) {
++                              return 1;
++                      }
++              }
++      }
++      return 0;
++}
++
++/**
++ * bbr_setup
++ *
++ * Read the remap tables from disk and set up the initial remap tree.
++ **/
++static int bbr_setup(struct bbr_private *bbr_id)
++{
++      struct bbr_table *table = bbr_id->bbr_table;
++      struct page *page;
++      struct io_region job;
++      unsigned int error, offset;
++      int i, rc = 0;
++
++      job.dev = bbr_id->dev->dev;
++      job.count = 1;
++
++      /* Read and verify each BBR table sector individually. */
++      for (i = 0; i < bbr_id->nr_sects_bbr_table; i++, table++) {
++              job.sector = bbr_id->lba_table1 + i;
++              page = virt_to_page(table);
++              offset = (unsigned long)table & ~PAGE_MASK;
++              rc = dm_io_sync(1, &job, READ, page, offset, &error);
++              if (rc && bbr_id->lba_table2) {
++                      job.sector = bbr_id->lba_table2 + i;
++                      rc = dm_io_sync(1, &job, READ, page, offset, &error);
++              }
++              if (rc) {
++                      goto out;
++              }
++
++              rc = validate_bbr_table_sector(table);
++              if (rc) {
++                      goto out;
++              }
++      }
++      atomic_set(&bbr_id->in_use_replacement_blks,
++                 bbr_table_to_remap_list(bbr_id));
++
++out:
++      if (rc) {
++              DMERR("dm-bbr: error during device setup: %d", rc);
++      }
++      return rc;
++}
++
++/**
++ * bbr_io_remap_error
++ * @bbr_id:           Private data for the BBR node.
++ * @rw:                       READ or WRITE.
++ * @starting_lsn:     Starting sector of request to remap.
++ * @count:            Number of sectors in the request.
++ * @buffer:           Data buffer for the request.
++ *
++ * For the requested range, try to write each sector individually. For each
++ * sector that fails, find the next available remap location and write the
++ * data to that new location. Then update the table and write both copies
++ * of the table to disk. Finally, update the in-memory mapping and do any
++ * other necessary bookkeeping.
++ **/
++static int bbr_io_remap_error(struct bbr_private *bbr_id,
++                            int rw,
++                            u64 starting_lsn,
++                            u64 count,
++                            char *buffer)
++{
++      struct bbr_table *bbr_table;
++      struct io_region job;
++      struct page *page;
++      unsigned long table_sector_index;
++      unsigned long table_sector_offset;
++      unsigned long index;
++      unsigned int offset_in_page, error;
++      u64 lsn, new_lsn;
++      int rc;
++
++      if (rw == READ) {
++              /* Nothing can be done about read errors. */
++              return -EIO;
++      }
++
++      job.dev = bbr_id->dev->dev;
++      job.count = 1;
++
++      /* For each sector in the request. */
++      for (lsn = 0; lsn < count; lsn++, buffer += SECTOR_SIZE) {
++              job.sector = starting_lsn + lsn;
++              page = virt_to_page(buffer);
++              offset_in_page = (unsigned long)buffer & ~PAGE_MASK;
++              rc = dm_io_sync(1, &job, rw, page, offset_in_page, &error);
++              while (rc) {
++                      /* Find the next available relocation sector. */
++                      new_lsn = atomic_read(&bbr_id->in_use_replacement_blks);
++                      if (new_lsn >= bbr_id->nr_replacement_blks) {
++                              /* No more replacement sectors available. */
++                              return -EIO;
++                      }
++                      new_lsn += bbr_id->start_replacement_sect;
++
++                      /* Write the data to its new location. */
++                      DMWARN("dm-bbr: device %s: Trying to remap bad sector 
"PFU64" to sector "PFU64,
++                             dm_kdevname(bbr_id->dev->dev),
++                             starting_lsn + lsn, new_lsn);
++                      job.sector = new_lsn;
++                      rc = dm_io_sync(1, &job, rw, page, offset_in_page, 
&error);
++                      if (rc) {
++                              /* This replacement sector is bad.
++                               * Try the next one.
++                               */
++                              DMERR("dm-bbr: device %s: replacement sector 
"PFU64" is bad. Skipping.",
++                                    dm_kdevname(bbr_id->dev->dev), new_lsn);
++                              atomic_inc(&bbr_id->in_use_replacement_blks);
++                              continue;
++                      }
++
++                      /* Add this new entry to the on-disk table. */
++                      table_sector_index = new_lsn -
++                                           bbr_id->start_replacement_sect;
++                      table_sector_offset = table_sector_index /
++                                            BBR_ENTRIES_PER_SECT;
++                      index = table_sector_index % BBR_ENTRIES_PER_SECT;
++
++                      bbr_table = &bbr_id->bbr_table[table_sector_offset];
++                      bbr_table->entries[index].bad_sect = starting_lsn + lsn;
++                      bbr_table->entries[index].replacement_sect = new_lsn;
++                      bbr_table->in_use_cnt++;
++                      bbr_table->sequence_number++;
++                      bbr_table->crc = 0;
++                      bbr_table->crc = calculate_crc(INITIAL_CRC,
++                                                     bbr_table,
++                                                     sizeof(struct 
bbr_table));
++
++                      /* Write the table to disk. */
++                      cpu_bbr_table_sector_to_le(bbr_table, bbr_table);
++                      page = virt_to_page(bbr_table);
++                      offset_in_page = (unsigned long)bbr_table & ~PAGE_MASK;
++                      if (bbr_id->lba_table1) {
++                              job.sector = bbr_id->lba_table1 + 
table_sector_offset;
++                              rc = dm_io_sync(1, &job, WRITE, page, 
offset_in_page, &error);
++                      }
++                      if (bbr_id->lba_table2) {
++                              job.sector = bbr_id->lba_table2 + 
table_sector_offset;
++                              rc |= dm_io_sync(1, &job, WRITE, page, 
offset_in_page, &error);
++                      }
++                      le_bbr_table_sector_to_cpu(bbr_table);
++
++                      if (rc) {
++                              /* Error writing one of the tables to disk. */
++                              DMERR("dm-bbr: device %s: error updating BBR 
tables on disk.",
++                                    dm_kdevname(bbr_id->dev->dev));
++                              return rc;
++                      }
++
++                      /* Insert a new entry in the remapping binary-tree. */
++                      rc = bbr_insert_remap_entry(bbr_id,
++                                                  &bbr_table->entries[index]);
++                      if (rc) {
++                              DMERR("dm-bbr: device %s: error adding new 
entry to remap tree.",
++                                    dm_kdevname(bbr_id->dev->dev));
<<Diff was trimmed, longer than 597 lines>>
_______________________________________________
pld-cvs-commit mailing list
[email protected]
http://lists.pld-linux.org/mailman/listinfo/pld-cvs-commit

Reply via email to