From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from pigeon.gentoo.org ([208.92.234.80] helo=lists.gentoo.org) by finch.gentoo.org with esmtp (Exim 4.60) (envelope-from ) id 1ODnzK-0002vE-Sw for garchives@archives.gentoo.org; Mon, 17 May 2010 00:15:19 +0000 Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id A84AAE06D6; Mon, 17 May 2010 00:15:15 +0000 (UTC) Received: from smtp.gentoo.org (smtp.gentoo.org [140.211.166.183]) by pigeon.gentoo.org (Postfix) with ESMTP id 2FF88E06D6 for ; Mon, 17 May 2010 00:15:15 +0000 (UTC) Received: from corvid.gentoo.org (corvid.gentoo.org [208.92.234.79]) (using TLSv1 with cipher DHE-RSA-CAMELLIA256-SHA (256/256 bits)) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTP id 88DD81B4005 for ; Mon, 17 May 2010 00:15:14 +0000 (UTC) Received: by corvid.gentoo.org (Postfix, from userid 2195) id 949782C5F5; Mon, 17 May 2010 00:15:13 +0000 (UTC) To: gentoo-commits@lists.gentoo.org From: "Mike Pagano (mpagano)" Subject: [gentoo-commits] linux-patches r1703 - genpatches-2.6/trunk/2.6.34 X-VCS-Repository: linux-patches X-VCS-Revision: 1703 X-VCS-Files: genpatches-2.6/trunk/2.6.34/4100_dm-bbr.patch genpatches-2.6/trunk/2.6.34/0000_README X-VCS-Directories: genpatches-2.6/trunk/2.6.34 X-VCS-Committer: mpagano X-VCS-Committer-Name: Mike Pagano Content-Type: text/plain; charset=UTF-8 Message-Id: <20100517001513.949782C5F5@corvid.gentoo.org> Date: Mon, 17 May 2010 00:15:13 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: quoted-printable X-Archives-Salt: 162b3419-e9c8-4947-97e0-eb47cfd3d933 X-Archives-Hash: e3e461cddab049931ef4eb2494a15f71 Author: mpagano Date: 2010-05-17 00:15:12 +0000 (Mon, 17 May 2010) New Revision: 1703 Removed: genpatches-2.6/trunk/2.6.34/4100_dm-bbr.patch Modified: genpatches-2.6/trunk/2.6.34/0000_README Log: Removal of patches incompatible with 2.6.34 Modified: genpatches-2.6/trunk/2.6.34/0000_README =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- genpatches-2.6/trunk/2.6.34/0000_README 2010-05-14 13:53:52 UTC (rev = 1702) +++ genpatches-2.6/trunk/2.6.34/0000_README 2010-05-17 00:15:12 UTC (rev = 1703) @@ -39,10 +39,6 @@ Individual Patch Descriptions: ------------------------------------------------------------------------= -- =20 -Patch: 4100_dm-bbr.patch -From: EVMS 2.5.2 -Desc: Bad block relocation support for LiveCD users - Patch: 4200_fbcondecor-0.9.6.patch From: http://dev.gentoo.org/~spock Desc: Bootsplash successor by Michal Januszewski Deleted: genpatches-2.6/trunk/2.6.34/4100_dm-bbr.patch =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- genpatches-2.6/trunk/2.6.34/4100_dm-bbr.patch 2010-05-14 13:53:52 UTC= (rev 1702) +++ genpatches-2.6/trunk/2.6.34/4100_dm-bbr.patch 2010-05-17 00:15:12 UTC= (rev 1703) @@ -1,1190 +0,0 @@ -BBR Target, updated by dsd@gentoo.org - -Incomplete changelog: - 2008/06/16: updated for new API in 2.6.26 - 2007/07/08: updated for new API in 2.6.22 - -Index: linux-2.6.26-gentoo/drivers/md/Kconfig -=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D ---- linux-2.6.26-gentoo.orig/drivers/md/Kconfig -+++ linux-2.6.26-gentoo/drivers/md/Kconfig -@@ -288,4 +288,15 @@ config DM_UEVENT - ---help--- - Generate udev events for DM events. -=20 -+config BLK_DEV_DM_BBR -+ tristate "Bad Block Relocation Device Target (EXPERIMENTAL)" -+ depends on BLK_DEV_DM && EXPERIMENTAL -+ ---help--- -+ Support for devices with software-based bad-block-relocation. -+ -+ To compile this as a module, choose M here: the module will be -+ called dm-bbr. -+ -+ If unsure, say N. -+ - endif # MD -Index: linux-2.6.26-gentoo/drivers/md/Makefile -=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D ---- linux-2.6.26-gentoo.orig/drivers/md/Makefile -+++ linux-2.6.26-gentoo/drivers/md/Makefile -@@ -41,6 +41,7 @@ obj-$(CONFIG_DM_MULTIPATH_RDAC) +=3D dm-rd - obj-$(CONFIG_DM_SNAPSHOT) +=3D dm-snapshot.o - obj-$(CONFIG_DM_MIRROR) +=3D dm-mirror.o dm-log.o - obj-$(CONFIG_DM_ZERO) +=3D dm-zero.o -+obj-$(CONFIG_BLK_DEV_DM_BBR) +=3D dm-bbr.o -=20 - quiet_cmd_unroll =3D UNROLL $@ - cmd_unroll =3D $(PERL) $(srctree)/$(src)/unroll.pl $(UNROLL) \ -Index: linux-2.6.26-gentoo/drivers/md/dm-bbr.c -=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D ---- /dev/null -+++ linux-2.6.26-gentoo/drivers/md/dm-bbr.c -@@ -0,0 +1,1012 @@ -+/* -+ * (C) Copyright IBM Corp. 2002, 2004 -+ * -+ * This program is free software; you can redistribute it and/or mod= ify -+ * 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-130= 7 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 sa= fe -+ * location on disk. Note that most disk drives have BBR built into the= m, -+ * this means that our software BBR will be only activated when all har= dware -+ * BBR replacement sectors have been used. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "dm.h" -+#include "dm-bio-record.h" -+#include "dm-bbr.h" -+ -+#define DM_MSG_PREFIX "bbr" -+#define SECTOR_SIZE (1 << SECTOR_SHIFT) -+ -+static struct workqueue_struct *dm_bbr_wq =3D NULL; -+static void bbr_remap_handler(struct work_struct *work); -+static struct kmem_cache *bbr_remap_cache; -+static struct kmem_cache *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 =3D NULL; -+ struct bbr_runtime_remap *node =3D root; -+ -+ while (node) { -+ if (node->left) { -+ link =3D &node->left; -+ node =3D node->left; -+ continue; -+ } -+ if (node->right) { -+ link =3D &node->right; -+ node =3D node->right; -+ continue; -+ } -+ -+ kmem_cache_free(bbr_remap_cache, node); -+ if (node =3D=3D root) { -+ /* If root is deleted, we're done. */ -+ break; -+ } -+ -+ /* Back to root. */ -+ node =3D root; -+ *link =3D 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 =3D NULL; -+ spin_unlock_irq(&bbr_id->remap_root_lock); -+} -+ -+static struct bbr_private *bbr_alloc_private(void) -+{ -+ struct bbr_private *bbr_id; -+ -+ bbr_id =3D kzalloc(sizeof(*bbr_id), GFP_KERNEL); -+ if (bbr_id =3D=3D NULL) -+ return NULL; -+ -+ INIT_WORK(&bbr_id->remap_work, bbr_remap_handler); -+ spin_lock_init(&bbr_id->remap_root_lock); -+ spin_lock_init(&bbr_id->remap_ios_lock); -+ bbr_id->in_use_replacement_blks =3D (atomic_t) ATOMIC_INIT(0); -+ -+ return bbr_id; -+} -+ -+static void bbr_free_private(struct bbr_private *bbr_id) -+{ -+ vfree(bbr_id->bbr_table); -+ bbr_free_remap(bbr_id); -+ kfree(bbr_id); -+} -+ -+static u32 crc_table[256]; -+static u32 crc_table_built =3D 0; -+ -+static void build_crc_table(void) -+{ -+ u32 i, j, crc; -+ -+ for (i =3D 0; i <=3D 255; i++) { -+ crc =3D i; -+ for (j =3D 8; j > 0; j--) { -+ if (crc & 1) -+ crc =3D (crc >> 1) ^ CRC_POLYNOMIAL; -+ else -+ crc >>=3D 1; -+ } -+ crc_table[i] =3D crc; -+ } -+ crc_table_built =3D 1; -+} -+ -+static u32 calculate_crc(u32 crc, void *buffer, u32 buffersize) -+{ -+ unsigned char *current_byte; -+ u32 temp1, temp2, i; -+ -+ current_byte =3D (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 =3D 0; i < buffersize; i++) { -+ temp1 =3D (crc >> 8) & 0x00FFFFFF; -+ temp2 =3D crc_table[(crc ^ (u32) * current_byte) & -+ (u32) 0xff]; -+ current_byte++; -+ crc =3D 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 =3D le32_to_cpup(&p->signature); -+ p->crc =3D le32_to_cpup(&p->crc); -+ p->sequence_number =3D le32_to_cpup(&p->sequence_number); -+ p->in_use_cnt =3D le32_to_cpup(&p->in_use_cnt); -+ for (i =3D 0; i < BBR_ENTRIES_PER_SECT; i++) { -+ p->entries[i].bad_sect =3D -+ le64_to_cpup(&p->entries[i].bad_sect); -+ p->entries[i].replacement_sect =3D -+ 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 =3D cpu_to_le32p(&p->signature); -+ le->crc =3D cpu_to_le32p(&p->crc); -+ le->sequence_number =3D cpu_to_le32p(&p->sequence_number); -+ le->in_use_cnt =3D cpu_to_le32p(&p->in_use_cnt); -+ for (i =3D 0; i < BBR_ENTRIES_PER_SECT; i++) { -+ le->entries[i].bad_sect =3D -+ cpu_to_le64p(&p->entries[i].bad_sect); -+ le->entries[i].replacement_sect =3D -+ 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 org_crc, final_crc; -+ -+ if (le32_to_cpup(&p->signature) !=3D 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); -+ return -EINVAL; -+ } -+ -+ if (!p->crc) { -+ DMERR("BBR table sector has no CRC!"); -+ return -EINVAL; -+ } -+ -+ org_crc =3D le32_to_cpup(&p->crc); -+ p->crc =3D 0; -+ final_crc =3D calculate_crc(INITIAL_CRC, (void *)p, sizeof(*p)); -+ if (final_crc !=3D org_crc) { -+ DMERR("CRC failed!"); -+ DMERR("Found 0x%x. Expecting 0x%x", -+ org_crc, final_crc); -+ return -EINVAL; -+ } -+ -+ p->crc =3D cpu_to_le32p(&org_crc); -+ le_bbr_table_sector_to_cpu(p); -+ -+ return 0; -+} -+ -+/** -+ * 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 =3D root; -+ while (node && *node) { -+ node =3D (newnode->remap.bad_sect > (*node)->remap.bad_sect) ? -+ &(*node)->right : &(*node)->left; -+ } -+ -+ newnode->left =3D newnode->right =3D NULL; -+ *node =3D newnode; -+} -+ -+/** -+ * bbr_binary_search -+ * -+ * Search for a node that contains bad_sect =3D=3D lsn. -+ **/ -+static struct bbr_runtime_remap *bbr_binary_search( -+ struct bbr_runtime_remap *root, -+ u64 lsn) -+{ -+ struct bbr_runtime_remap *node =3D root; -+ while (node) { -+ if (node->remap.bad_sect =3D=3D lsn) -+ break; -+ -+ node =3D (lsn > node->remap.bad_sect) ? node->right : 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 =3D kmem_cache_alloc(bbr_remap_cache, GFP_NOIO); -+ if (!newnode) { -+ DMERR("Could not allocate from remap cache!"); -+ return -ENOMEM; -+ } -+ newnode->remap.bad_sect =3D new_bbr_entry->bad_sect; -+ newnode->remap.replacement_sect =3D 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 or= der to -+ * improve run time performance, the in memory remap list must be sorte= d by -+ * the bad sector LBA. This function is called at discovery time to ini= tialize -+ * 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 =3D 0; -+ int i, j; -+ struct bbr_table *p; -+ -+ for (i =3D 0, p =3D bbr_id->bbr_table; -+ i < bbr_id->nr_sects_bbr_table; -+ i++, p++) { -+ if (!p->in_use_cnt) -+ break; -+ -+ in_use_blks +=3D p->in_use_cnt; -+ for (j =3D 0; j < p->in_use_cnt; j++) -+ bbr_insert_remap_entry(bbr_id, &p->entries[j]); -+ } -+ if (in_use_blks) { -+ char b[32]; -+ DMWARN("There are %u BBR entries for device %s", -+ in_use_blks, format_dev_t(b, bbr_id->dev->bdev->bd_dev)); -+ } -+ -+ return in_use_blks; -+} -+ -+/** -+ * bbr_search_remap_entry -+ * -+ * Search remap entry for the specified sector. If found, return a poin= ter 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 =3D bbr_binary_search(bbr_id->remap_root, lsn); -+ spin_unlock_irq(&bbr_id->remap_root_lock); -+ return (p) ? &p->remap : NULL; -+} -+ -+/** -+ * bbr_remap -+ * -+ * If *lsn is in the remap table, return TRUE and modify *lsn, -+ * else, return FALSE. -+ **/ -+static 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 =3D bbr_search_remap_entry(bbr_id, *lsn); -+ if (e) { -+ *lsn =3D 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 re= map -+ * table return TRUE, Else, return FALSE. -+ **/ -+static 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 =3D 0, tmp =3D lsn; -+ cnt < nr_sects; -+ cnt +=3D bbr_id->blksize_in_sects, tmp =3D lsn + cnt) { -+ if (bbr_remap(bbr_id,&tmp)) -+ return 1; -+ } -+ } -+ return 0; -+} -+ -+static int rw_table(struct bbr_private *bbr_id, void *vma, -+ struct dm_io_region *ptr, int rw) -+{ -+ bbr_id->vma_io_req.bi_rw =3D rw; -+ bbr_id->vma_io_req.mem.ptr.vma =3D vma; -+ bbr_id->vma_io_req.notify.fn =3D NULL; -+ -+ return dm_io(&bbr_id->vma_io_req, 1, ptr, NULL); -+} -+ -+static int io_sync(struct bbr_private *bbr_id, struct page_list *pl, -+ unsigned offset, struct dm_io_region *ptr, int rw) -+{ -+ bbr_id->page_io_req.bi_rw =3D rw; -+ bbr_id->page_io_req.mem.ptr.pl =3D pl; -+ bbr_id->page_io_req.mem.offset =3D offset; -+ bbr_id->page_io_req.notify.fn =3D NULL; -+ -+ return dm_io(&bbr_id->page_io_req, 1, ptr, NULL); -+} -+ -+/** -+ * 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 =3D bbr_id->bbr_table; -+ struct dm_io_region job; -+ int i, rc =3D 0; -+ -+ job.bdev =3D bbr_id->dev->bdev; -+ job.count =3D 1; -+ -+ /* Read and verify each BBR table sector individually. */ -+ for (i =3D 0; i < bbr_id->nr_sects_bbr_table; i++, table++) { -+ job.sector =3D bbr_id->lba_table1 + i; -+ rc =3D rw_table(bbr_id, table, &job, READ); -+ if (rc && bbr_id->lba_table2) { -+ job.sector =3D bbr_id->lba_table2 + i; -+ rc =3D rw_table(bbr_id, table, &job, READ); -+ } -+ if (rc) -+ goto out; -+ -+ rc =3D 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("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. -+ * @page: Page containing the data for the request. -+ * @offset: Byte-offset of the data within the page. -+ * -+ * 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 copi= es -+ * of the table to disk. Finally, update the in-memory mapping and do a= ny -+ * other necessary bookkeeping. -+ **/ -+static int bbr_io_remap_error(struct bbr_private *bbr_id, -+ int rw, -+ u64 starting_lsn, -+ u64 count, -+ struct page *page, -+ unsigned int offset) -+{ -+ struct bbr_table *bbr_table; -+ struct dm_io_region job; -+ struct page_list pl; -+ unsigned long table_sector_index; -+ unsigned long table_sector_offset; -+ unsigned long index; -+ u64 lsn, new_lsn; -+ char b[32]; -+ int rc; -+ -+ job.bdev =3D bbr_id->dev->bdev; -+ job.count =3D 1; -+ pl.page =3D page; -+ pl.next =3D NULL; -+ -+ /* For each sector in the request. */ -+ for (lsn =3D 0; lsn < count; lsn++, offset +=3D SECTOR_SIZE) { -+ job.sector =3D starting_lsn + lsn; -+ rc =3D io_sync(bbr_id, &pl, offset, &job, rw); -+ while (rc) { -+ /* Find the next available relocation sector. */ -+ new_lsn =3D atomic_read(&bbr_id->in_use_replacement_blks); -+ if (new_lsn >=3D bbr_id->nr_replacement_blks) { -+ /* No more replacement sectors available. */ -+ return -EIO; -+ } -+ new_lsn +=3D bbr_id->start_replacement_sect; -+ -+ /* Write the data to its new location. */ -+ DMWARN("device %s: Trying to remap bad sector "PFU64" to sector "PFU= 64, -+ format_dev_t(b, bbr_id->dev->bdev->bd_dev), -+ starting_lsn + lsn, new_lsn); -+ job.sector =3D new_lsn; -+ rc =3D io_sync(bbr_id, &pl, offset, &job, rw); -+ if (rc) { -+ /* This replacement sector is bad. -+ * Try the next one. -+ */ -+ DMERR("device %s: replacement sector "PFU64" is bad. Skipping.", -+ format_dev_t(b, bbr_id->dev->bdev->bd_dev), new_lsn); -+ atomic_inc(&bbr_id->in_use_replacement_blks); -+ continue; -+ } -+ -+ /* Add this new entry to the on-disk table. */ -+ table_sector_index =3D new_lsn - -+ bbr_id->start_replacement_sect; -+ table_sector_offset =3D table_sector_index / -+ BBR_ENTRIES_PER_SECT; -+ index =3D table_sector_index % BBR_ENTRIES_PER_SECT; -+ -+ bbr_table =3D &bbr_id->bbr_table[table_sector_offset]; -+ bbr_table->entries[index].bad_sect =3D starting_lsn + lsn; -+ bbr_table->entries[index].replacement_sect =3D new_lsn; -+ bbr_table->in_use_cnt++; -+ bbr_table->sequence_number++; -+ bbr_table->crc =3D 0; -+ bbr_table->crc =3D 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); -+ if (bbr_id->lba_table1) { -+ job.sector =3D bbr_id->lba_table1 + table_sector_offset; -+ rc =3D rw_table(bbr_id, bbr_table, &job, WRITE); -+ } -+ if (bbr_id->lba_table2) { -+ job.sector =3D bbr_id->lba_table2 + table_sector_offset; -+ rc |=3D rw_table(bbr_id, bbr_table, &job, WRITE); -+ } -+ le_bbr_table_sector_to_cpu(bbr_table); -+ -+ if (rc) { -+ /* Error writing one of the tables to disk. */ -+ DMERR("device %s: error updating BBR tables on disk.", -+ format_dev_t(b, bbr_id->dev->bdev->bd_dev)); -+ return rc; -+ } -+ -+ /* Insert a new entry in the remapping binary-tree. */ -+ rc =3D bbr_insert_remap_entry(bbr_id, -+ &bbr_table->entries[index]); -+ if (rc) { -+ DMERR("device %s: error adding new entry to remap tree.", -+ format_dev_t(b, bbr_id->dev->bdev->bd_dev)); -+ return rc; -+ } -+ -+ atomic_inc(&bbr_id->in_use_replacement_blks); -+ } -+ } -+ -+ return 0; -+} -+ -+/** -+ * bbr_io_process_request -+ * -+ * For each sector in this request, check if the sector has already -+ * been remapped. If so, process all previous sectors in the request, -+ * followed by the remapped sector. Then reset the starting lsn and -+ * count, and keep going with the rest of the request as if it were -+ * a whole new request. If any of the sync_io's return an error, -+ * call the remapper to relocate the bad sector(s). -+ * -+ * 2.5 Note: When switching over to bio's for the I/O path, we have mad= e -+ * the assumption that the I/O request described by the bio is one -+ * virtually contiguous piece of memory (even though the bio vector -+ * describes it using a series of physical page addresses). -+ **/ -+static int bbr_io_process_request(struct bbr_private *bbr_id, -+ struct bio *bio) -+{ -+ struct dm_io_region job; -+ u64 starting_lsn =3D bio->bi_sector; -+ u64 count, lsn, remapped_lsn; -+ struct page_list pl; -+ unsigned int offset; -+ int i, rw =3D bio_data_dir(bio); -+ int rc =3D 0; -+ -+ job.bdev =3D bbr_id->dev->bdev; -+ pl.next =3D NULL; -+ -+ /* Each bio can contain multiple vectors, each with a different page. -+ * Treat each vector as a separate request. -+ */ -+ /* KMC: Is this the right way to walk the bvec list? */ -+ for (i =3D 0; -+ i < bio->bi_vcnt; -+ i++, bio->bi_idx++, starting_lsn +=3D count) { -+ -+ /* Bvec info: number of sectors, page, -+ * and byte-offset within page. -+ */ -+ count =3D bio_iovec(bio)->bv_len >> SECTOR_SHIFT; -+ pl.page =3D bio_iovec(bio)->bv_page; -+ offset =3D bio_iovec(bio)->bv_offset; -+ -+ /* For each sector in this bvec, check if the sector has -+ * already been remapped. If so, process all previous sectors -+ * in this request, followed by the remapped sector. Then reset -+ * the starting lsn and count and keep going with the rest of -+ * the request as if it were a whole new request. -+ */ -+ for (lsn =3D 0; lsn < count; lsn++) { -+ remapped_lsn =3D starting_lsn + lsn; -+ rc =3D bbr_remap(bbr_id, &remapped_lsn); -+ if (!rc) { -+ /* This sector is fine. */ -+ continue; -+ } -+ -+ /* Process all sectors in the request up to this one. */ -+ if (lsn > 0) { -+ job.sector =3D starting_lsn; -+ job.count =3D lsn; -+ rc =3D io_sync(bbr_id, &pl, offset, &job, rw); -+ if (rc) { -+ /* If this I/O failed, then one of the -+ * sectors in this request needs to be -+ * relocated. -+ */ -+ rc =3D bbr_io_remap_error(bbr_id, rw, -+ starting_lsn, -+ lsn, pl.page, -+ offset); -+ if (rc) { -+ /* KMC: Return? Or continue to next bvec? */ -+ return rc; -+ } -+ } -+ offset +=3D (lsn << SECTOR_SHIFT); -+ } -+ -+ /* Process the remapped sector. */ -+ job.sector =3D remapped_lsn; -+ job.count =3D 1; -+ rc =3D io_sync(bbr_id, &pl, offset, &job, rw); -+ if (rc) { -+ /* BUGBUG - Need more processing if this caused -+ * an error. If this I/O failed, then the -+ * existing remap is now bad, and we need to -+ * find a new remap. Can't use -+ * bbr_io_remap_error(), because the existing -+ * map entry needs to be changed, not added -+ * again, and the original table entry also -+ * needs to be changed. -+ */ -+ return rc; -+ } -+ -+ starting_lsn +=3D (lsn + 1); -+ count -=3D (lsn + 1); -+ lsn =3D -1; -+ offset +=3D SECTOR_SIZE; -+ } -+ -+ /* Check for any remaining sectors after the last split. This -+ * could potentially be the whole request, but that should be a -+ * rare case because requests should only be processed by the -+ * thread if we know an error occurred or they contained one or -+ * more remapped sectors. -+ */ -+ if (count) { -+ job.sector =3D starting_lsn; -+ job.count =3D count; -+ rc =3D io_sync(bbr_id, &pl, offset, &job, rw); -+ if (rc) { -+ /* If this I/O failed, then one of the sectors -+ * in this request needs to be relocated. -+ */ -+ rc =3D bbr_io_remap_error(bbr_id, rw, starting_lsn, -+ count, pl.page, offset); -+ if (rc) { -+ /* KMC: Return? Or continue to next bvec? */ -+ return rc; -+ } -+ } -+ } -+ } -+ -+ return 0; -+} -+ -+static void bbr_io_process_requests(struct bbr_private *bbr_id, -+ struct bio *bio) -+{ -+ struct bio *next; -+ int rc; -+ -+ while (bio) { -+ next =3D bio->bi_next; -+ bio->bi_next =3D NULL; -+ -+ rc =3D bbr_io_process_request(bbr_id, bio); -+ -+ bio_endio(bio, rc); -+ -+ bio =3D next; -+ } -+} -+ -+/** -+ * bbr_remap_handler -+ * -+ * This is the handler for the bbr work-queue. -+ * -+ * I/O requests should only be sent to this handler if we know that: -+ * a) the request contains at least one remapped sector. -+ * or -+ * b) the request caused an error on the normal I/O path. -+ * -+ * This function uses synchronous I/O, so sending a request to this -+ * thread that doesn't need special processing will cause severe -+ * performance degredation. -+ **/ -+static void bbr_remap_handler(struct work_struct *work) -+{ -+ struct bbr_private *bbr_id =3D -+ container_of(work, struct bbr_private, remap_work); -+ struct bio *bio; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&bbr_id->remap_ios_lock, flags); -+ bio =3D bio_list_get(&bbr_id->remap_ios); -+ spin_unlock_irqrestore(&bbr_id->remap_ios_lock, flags); -+ -+ bbr_io_process_requests(bbr_id, bio); -+} -+ -+/** -+ * bbr_endio -+ * -+ * This is the callback for normal write requests. Check for an error -+ * during the I/O, and send to the thread for processing if necessary. -+ **/ -+static int bbr_endio(struct dm_target *ti, struct bio *bio, -+ int error, union map_info *map_context) -+{ -+ struct bbr_private *bbr_id =3D ti->private; -+ struct dm_bio_details *bbr_io =3D map_context->ptr; -+ -+ if (error && bbr_io) { -+ unsigned long flags; -+ char b[32]; -+ -+ dm_bio_restore(bbr_io, bio); -+ map_context->ptr =3D NULL; -+ -+ DMERR("device %s: I/O failure on sector %lu. " -+ "Scheduling for retry.", -+ format_dev_t(b, bbr_id->dev->bdev->bd_dev), -+ (unsigned long)bio->bi_sector); -+ -+ spin_lock_irqsave(&bbr_id->remap_ios_lock, flags); -+ bio_list_add(&bbr_id->remap_ios, bio); -+ spin_unlock_irqrestore(&bbr_id->remap_ios_lock, flags); -+ -+ queue_work(dm_bbr_wq, &bbr_id->remap_work); -+ -+ error =3D 1; -+ } -+ -+ if (bbr_io) -+ mempool_free(bbr_io, bbr_io_pool); -+ -+ return error; -+} -+ -+/** -+ * Construct a bbr mapping -+ **/ -+static int bbr_ctr(struct dm_target *ti, unsigned int argc, char **argv= ) -+{ -+ struct bbr_private *bbr_id; -+ unsigned long block_size; -+ char *end; -+ int rc =3D -EINVAL; -+ -+ if (argc !=3D 8) { -+ ti->error =3D "dm-bbr requires exactly 8 arguments: " -+ "device offset table1_lsn table2_lsn table_size start_replacemen= t nr_replacement_blks block_size"; -+ goto out1; -+ } -+ -+ bbr_id =3D bbr_alloc_private(); -+ if (!bbr_id) { -+ ti->error =3D "dm-bbr: Error allocating bbr private data."; -+ goto out1; -+ } -+ -+ bbr_id->offset =3D simple_strtoull(argv[1], &end, 10); -+ bbr_id->lba_table1 =3D simple_strtoull(argv[2], &end, 10); -+ bbr_id->lba_table2 =3D simple_strtoull(argv[3], &end, 10); -+ bbr_id->nr_sects_bbr_table =3D simple_strtoull(argv[4], &end, 10); -+ bbr_id->start_replacement_sect =3D simple_strtoull(argv[5], &end, 10); -+ bbr_id->nr_replacement_blks =3D simple_strtoull(argv[6], &end, 10); -+ block_size =3D simple_strtoul(argv[7], &end, 10); -+ bbr_id->blksize_in_sects =3D (block_size >> SECTOR_SHIFT); -+ -+ bbr_id->vma_io_req.mem.type =3D DM_IO_VMA; -+ bbr_id->vma_io_req.client =3D dm_io_client_create(1); -+ if (IS_ERR(bbr_id->vma_io_req.client)) { -+ rc =3D PTR_ERR(bbr_id->vma_io_req.client); -+ DMWARN("couldn't allocate disk VMA io client"); -+ goto out2; -+ } -+ -+ bbr_id->page_io_req.mem.type =3D DM_IO_PAGE_LIST; -+ bbr_id->page_io_req.client =3D dm_io_client_create(1); -+ if (IS_ERR(bbr_id->page_io_req.client)) { -+ rc =3D PTR_ERR(bbr_id->page_io_req.client); -+ DMWARN("couldn't allocate pagelist io client"); -+ goto out3; -+ } -+ -+ bbr_id->bbr_table =3D vmalloc(bbr_id->nr_sects_bbr_table << SECTOR_SHI= FT); -+ if (!bbr_id->bbr_table) { -+ ti->error =3D "dm-bbr: Error allocating bbr table."; -+ goto out4; -+ } -+ -+ if (dm_get_device(ti, argv[0], 0, ti->len, -+ dm_table_get_mode(ti->table), &bbr_id->dev)) { -+ ti->error =3D "dm-bbr: Device lookup failed"; -+ goto out4; -+ } -+ -+ rc =3D bbr_setup(bbr_id); -+ if (rc) { -+ ti->error =3D "dm-bbr: Device setup failed"; -+ goto out5; -+ } -+ -+ ti->private =3D bbr_id; -+ return 0; -+ -+out5: -+ dm_put_device(ti, bbr_id->dev); -+out4: -+ dm_io_client_destroy(bbr_id->page_io_req.client); -+out3: -+ dm_io_client_destroy(bbr_id->vma_io_req.client); -+out2: -+ bbr_free_private(bbr_id); -+out1: -+ return rc; -+} -+ -+static void bbr_dtr(struct dm_target *ti) -+{ -+ struct bbr_private *bbr_id =3D ti->private; -+ -+ dm_put_device(ti, bbr_id->dev); -+ dm_io_client_destroy(bbr_id->page_io_req.client); -+ dm_io_client_destroy(bbr_id->vma_io_req.client); -+ bbr_free_private(bbr_id); -+} -+ -+static int bbr_map(struct dm_target *ti, struct bio *bio, -+ union map_info *map_context) -+{ -+ struct bbr_private *bbr_id =3D ti->private; -+ struct dm_bio_details *bbr_io; -+ unsigned long flags; -+ int rc =3D 1; -+ -+ bio->bi_sector +=3D bbr_id->offset; -+ -+ if (atomic_read(&bbr_id->in_use_replacement_blks) =3D=3D 0 || -+ !bbr_remap_probe(bbr_id, bio->bi_sector, bio_sectors(bio))) { -+ /* No existing remaps or this request doesn't -+ * contain any remapped sectors. -+ */ -+ bio->bi_bdev =3D bbr_id->dev->bdev; -+ -+ bbr_io =3D mempool_alloc(bbr_io_pool, GFP_NOIO); -+ dm_bio_record(bbr_io, bio); -+ map_context->ptr =3D bbr_io; -+ } else { -+ /* This request has at least one remapped sector. -+ * Give it to the work-queue for processing. -+ */ -+ map_context->ptr =3D NULL; -+ spin_lock_irqsave(&bbr_id->remap_ios_lock, flags); -+ bio_list_add(&bbr_id->remap_ios, bio); -+ spin_unlock_irqrestore(&bbr_id->remap_ios_lock, flags); -+ -+ queue_work(dm_bbr_wq, &bbr_id->remap_work); -+ rc =3D 0; -+ } -+ -+ return rc; -+} -+ -+static int bbr_status(struct dm_target *ti, status_type_t type, -+ char *result, unsigned int maxlen) -+{ -+ struct bbr_private *bbr_id =3D ti->private; -+ char b[BDEVNAME_SIZE]; -+ -+ switch (type) { -+ case STATUSTYPE_INFO: -+ result[0] =3D '\0'; -+ break; -+ -+ case STATUSTYPE_TABLE: -+ snprintf(result, maxlen, "%s "PFU64" "PFU64" "PFU64" "PFU64" "PFU64" = "PFU64" %u", -+ format_dev_t(b, bbr_id->dev->bdev->bd_dev), -+ bbr_id->offset, bbr_id->lba_table1, bbr_id->lba_table2, -+ bbr_id->nr_sects_bbr_table, -+ bbr_id->start_replacement_sect, -+ bbr_id->nr_replacement_blks, -+ bbr_id->blksize_in_sects << SECTOR_SHIFT); -+ break; -+ } -+ return 0; -+} -+ -+static struct target_type bbr_target =3D { -+ .name =3D "bbr", -+ .version=3D {1, 0, 1}, -+ .module =3D THIS_MODULE, -+ .ctr =3D bbr_ctr, -+ .dtr =3D bbr_dtr, -+ .map =3D bbr_map, -+ .end_io =3D bbr_endio, -+ .status =3D bbr_status, -+}; -+ -+int __init dm_bbr_init(void) -+{ -+ int rc; -+ -+ rc =3D dm_register_target(&bbr_target); -+ if (rc) { -+ DMERR("error registering target."); -+ goto err1; -+ } -+ -+ bbr_remap_cache =3D kmem_cache_create("bbr-remap", -+ sizeof(struct bbr_runtime_remap), -+ 0, SLAB_HWCACHE_ALIGN, NULL); -+ if (!bbr_remap_cache) { -+ DMERR("error creating remap cache."); -+ rc =3D ENOMEM; -+ goto err2; -+ } -+ -+ bbr_io_cache =3D kmem_cache_create("bbr-io", sizeof(struct dm_bio_deta= ils), -+ 0, SLAB_HWCACHE_ALIGN, NULL); -+ if (!bbr_io_cache) { -+ DMERR("error creating io cache."); -+ rc =3D ENOMEM; -+ goto err3; -+ } -+ -+ bbr_io_pool =3D mempool_create(256, mempool_alloc_slab, -+ mempool_free_slab, bbr_io_cache); -+ if (!bbr_io_pool) { -+ DMERR("error creating io mempool."); -+ rc =3D ENOMEM; -+ goto err4; -+ } -+ -+ dm_bbr_wq =3D create_workqueue("dm-bbr"); -+ if (!dm_bbr_wq) { -+ DMERR("error creating work-queue."); -+ rc =3D ENOMEM; -+ goto err5; -+ } -+ -+ return 0; -+ -+err5: -+ mempool_destroy(bbr_io_pool); -+err4: -+ kmem_cache_destroy(bbr_io_cache); -+err3: -+ kmem_cache_destroy(bbr_remap_cache); -+err2: -+ dm_unregister_target(&bbr_target); -+err1: -+ return rc; -+} -+ -+void __exit dm_bbr_exit(void) -+{ -+ destroy_workqueue(dm_bbr_wq); -+ mempool_destroy(bbr_io_pool); -+ kmem_cache_destroy(bbr_io_cache); -+ kmem_cache_destroy(bbr_remap_cache); -+ dm_unregister_target(&bbr_target); -+} -+ -+module_init(dm_bbr_init); -+module_exit(dm_bbr_exit); -+MODULE_LICENSE("GPL"); -Index: linux-2.6.26-gentoo/drivers/md/dm-bbr.h -=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D ---- /dev/null -+++ linux-2.6.26-gentoo/drivers/md/dm-bbr.h -@@ -0,0 +1,130 @@ -+/* -+ * (C) Copyright IBM Corp. 2002, 2004 -+ * -+ * This program is free software; you can redistribute it and/or mod= ify -+ * 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-130= 7 USA -+ * -+ * linux/drivers/md/dm-bbr.h -+ * -+ * Bad-block-relocation (BBR) target for device-mapper. -+ * -+ * The BBR target is designed to remap I/O write failures to another sa= fe -+ * location on disk. Note that most disk drives have BBR built into the= m, -+ * this means that our software BBR will be only activated when all har= dware -+ * BBR replacement sectors have been used. -+ */ -+ -+#include -+ -+#define BBR_TABLE_SIGNATURE 0x42627254 /* BbrT */ -+#define BBR_ENTRIES_PER_SECT 31 -+#define INITIAL_CRC 0xFFFFFFFF -+#define CRC_POLYNOMIAL 0xEDB88320L -+ -+/** -+ * Macros to cleanly print 64-bit numbers on both 32-bit and 64-bit mac= hines. -+ * Use these in place of %Ld, %Lu, and %Lx. -+ **/ -+#if BITS_PER_LONG > 32 -+#define PFU64 "%llu" -+#else -+#define PFU64 "%Lu" -+#endif -+ -+/** -+ * struct bbr_table_entry -+ * @bad_sect: LBA of bad location. -+ * @replacement_sect: LBA of new location. -+ * -+ * Structure to describe one BBR remap. -+ **/ -+struct bbr_table_entry { -+ u64 bad_sect; -+ u64 replacement_sect; -+}; -+ -+/** -+ * struct bbr_table -+ * @signature: Signature on each BBR table sector. -+ * @crc: CRC for this table sector. -+ * @sequence_number: Used to resolve conflicts when primary and seconda= ry -+ * tables do not match. -+ * @in_use_cnt: Number of in-use table entries. -+ * @entries: Actual table of remaps. -+ * -+ * Structure to describe each sector of the metadata table. Each sector= in this -+ * table can describe 31 remapped sectors. -+ **/ -+struct bbr_table { -+ u32 signature; -+ u32 crc; -+ u32 sequence_number; -+ u32 in_use_cnt; -+ struct bbr_table_entry entries[BBR_ENTRIES_PER_SECT]; -+}; -+ -+/** -+ * struct bbr_runtime_remap -+ * -+ * Node in the binary tree used to keep track of remaps. -+ **/ -+struct bbr_runtime_remap { -+ struct bbr_table_entry remap; -+ struct bbr_runtime_remap *left; -+ struct bbr_runtime_remap *right; -+}; -+ -+/** -+ * struct bbr_private -+ * @dev: Info about underlying device. -+ * @bbr_table: Copy of metadata table. -+ * @remap_root: Binary tree containing all remaps. -+ * @remap_root_lock: Lock for the binary tree. -+ * @remap_work: For adding work items to the work-queue. -+ * @remap_ios: List of I/Os for the work-queue to handle. -+ * @remap_ios_lock: Lock for the remap_ios list. -+ * @offset: LBA of data area. -+ * @lba_table1: LBA of primary BBR table. -+ * @lba_table2: LBA of secondary BBR table. -+ * @nr_sects_bbr_table: Size of each BBR table. -+ * @nr_replacement_blks: Number of replacement blocks. -+ * @start_replacement_sect: LBA of start of replacement blocks. -+ * @blksize_in_sects: Size of each block. -+ * @in_use_replacement_blks: Current number of remapped blocks. -+ * -+ * Private data for each BBR target. -+ **/ -+struct bbr_private { -+ struct dm_dev *dev; -+ struct bbr_table *bbr_table; -+ struct bbr_runtime_remap *remap_root; -+ spinlock_t remap_root_lock; -+ -+ struct dm_io_request vma_io_req; -+ struct dm_io_request page_io_req; -+ -+ struct work_struct remap_work; -+ struct bio_list remap_ios; -+ spinlock_t remap_ios_lock; -+ -+ u64 offset; -+ u64 lba_table1; -+ u64 lba_table2; -+ u64 nr_sects_bbr_table; -+ u64 start_replacement_sect; -+ u64 nr_replacement_blks; -+ u32 blksize_in_sects; -+ atomic_t in_use_replacement_blks; -+}; -+