summaryrefslogtreecommitdiffstats
path: root/drivers/md/bitmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/md/bitmap.c')
-rw-r--r--drivers/md/bitmap.c188
1 files changed, 77 insertions, 111 deletions
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index 0dc6546b77a..7878712721b 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -29,35 +29,6 @@
#include "md.h"
#include "bitmap.h"
-/* debug macros */
-
-#define DEBUG 0
-
-#if DEBUG
-/* these are for debugging purposes only! */
-
-/* define one and only one of these */
-#define INJECT_FAULTS_1 0 /* cause bitmap_alloc_page to fail always */
-#define INJECT_FAULTS_2 0 /* cause bitmap file to be kicked when first bit set*/
-#define INJECT_FAULTS_3 0 /* treat bitmap file as kicked at init time */
-#define INJECT_FAULTS_4 0 /* undef */
-#define INJECT_FAULTS_5 0 /* undef */
-#define INJECT_FAULTS_6 0
-
-/* if these are defined, the driver will fail! debug only */
-#define INJECT_FATAL_FAULT_1 0 /* fail kmalloc, causing bitmap_create to fail */
-#define INJECT_FATAL_FAULT_2 0 /* undef */
-#define INJECT_FATAL_FAULT_3 0 /* undef */
-#endif
-
-#ifndef PRINTK
-# if DEBUG > 0
-# define PRINTK(x...) printk(KERN_DEBUG x)
-# else
-# define PRINTK(x...)
-# endif
-#endif
-
static inline char *bmname(struct bitmap *bitmap)
{
return bitmap->mddev ? mdname(bitmap->mddev) : "mdX";
@@ -70,16 +41,12 @@ static unsigned char *bitmap_alloc_page(struct bitmap *bitmap)
{
unsigned char *page;
-#ifdef INJECT_FAULTS_1
- page = NULL;
-#else
page = kzalloc(PAGE_SIZE, GFP_NOIO);
-#endif
if (!page)
printk("%s: bitmap_alloc_page FAILED\n", bmname(bitmap));
else
- PRINTK("%s: bitmap_alloc_page: allocated page at %p\n",
- bmname(bitmap), page);
+ pr_debug("%s: bitmap_alloc_page: allocated page at %p\n",
+ bmname(bitmap), page);
return page;
}
@@ -88,7 +55,7 @@ static unsigned char *bitmap_alloc_page(struct bitmap *bitmap)
*/
static void bitmap_free_page(struct bitmap *bitmap, unsigned char *page)
{
- PRINTK("%s: bitmap_free_page: free page %p\n", bmname(bitmap), page);
+ pr_debug("%s: bitmap_free_page: free page %p\n", bmname(bitmap), page);
kfree(page);
}
@@ -133,8 +100,8 @@ __acquires(bitmap->lock)
spin_lock_irq(&bitmap->lock);
if (mappage == NULL) {
- PRINTK("%s: bitmap map page allocation failed, hijacking\n",
- bmname(bitmap));
+ pr_debug("%s: bitmap map page allocation failed, hijacking\n",
+ bmname(bitmap));
/* failed - set the hijacked flag so that we can use the
* pointer as a counter */
if (!bitmap->bp[page].map)
@@ -187,13 +154,13 @@ static void bitmap_checkfree(struct bitmap *bitmap, unsigned long page)
*/
/* IO operations when bitmap is stored near all superblocks */
-static struct page *read_sb_page(mddev_t *mddev, loff_t offset,
+static struct page *read_sb_page(struct mddev *mddev, loff_t offset,
struct page *page,
unsigned long index, int size)
{
/* choose a good rdev and read the page from there */
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
sector_t target;
int did_alloc = 0;
@@ -226,7 +193,7 @@ static struct page *read_sb_page(mddev_t *mddev, loff_t offset,
}
-static mdk_rdev_t *next_active_rdev(mdk_rdev_t *rdev, mddev_t *mddev)
+static struct md_rdev *next_active_rdev(struct md_rdev *rdev, struct mddev *mddev)
{
/* Iterate the disks of an mddev, using rcu to protect access to the
* linked list, and raising the refcount of devices we return to ensure
@@ -247,7 +214,7 @@ static mdk_rdev_t *next_active_rdev(mdk_rdev_t *rdev, mddev_t *mddev)
pos = &rdev->same_set;
}
list_for_each_continue_rcu(pos, &mddev->disks) {
- rdev = list_entry(pos, mdk_rdev_t, same_set);
+ rdev = list_entry(pos, struct md_rdev, same_set);
if (rdev->raid_disk >= 0 &&
!test_bit(Faulty, &rdev->flags)) {
/* this is a usable devices */
@@ -262,9 +229,9 @@ static mdk_rdev_t *next_active_rdev(mdk_rdev_t *rdev, mddev_t *mddev)
static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait)
{
- mdk_rdev_t *rdev = NULL;
+ struct md_rdev *rdev = NULL;
struct block_device *bdev;
- mddev_t *mddev = bitmap->mddev;
+ struct mddev *mddev = bitmap->mddev;
while ((rdev = next_active_rdev(rdev, mddev)) != NULL) {
int size = PAGE_SIZE;
@@ -409,8 +376,8 @@ static struct page *read_page(struct file *file, unsigned long index,
struct buffer_head *bh;
sector_t block;
- PRINTK("read bitmap file (%dB @ %llu)\n", (int)PAGE_SIZE,
- (unsigned long long)index << PAGE_SHIFT);
+ pr_debug("read bitmap file (%dB @ %llu)\n", (int)PAGE_SIZE,
+ (unsigned long long)index << PAGE_SHIFT);
page = alloc_page(GFP_KERNEL);
if (!page)
@@ -868,7 +835,8 @@ static void bitmap_file_kick(struct bitmap *bitmap)
enum bitmap_page_attr {
BITMAP_PAGE_DIRTY = 0, /* there are set bits that need to be synced */
- BITMAP_PAGE_CLEAN = 1, /* there are bits that might need to be cleared */
+ BITMAP_PAGE_PENDING = 1, /* there are bits that are being cleaned.
+ * i.e. counter is 1 or 2. */
BITMAP_PAGE_NEEDWRITE = 2, /* there are cleared bits that need to be synced */
};
@@ -919,7 +887,7 @@ static void bitmap_file_set_bit(struct bitmap *bitmap, sector_t block)
else
__set_bit_le(bit, kaddr);
kunmap_atomic(kaddr, KM_USER0);
- PRINTK("set file bit %lu page %lu\n", bit, page->index);
+ pr_debug("set file bit %lu page %lu\n", bit, page->index);
/* record page number so it gets flushed to disk when unplug occurs */
set_page_attr(bitmap, page, BITMAP_PAGE_DIRTY);
}
@@ -997,11 +965,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
BUG_ON(!file && !bitmap->mddev->bitmap_info.offset);
-#ifdef INJECT_FAULTS_3
- outofdate = 1;
-#else
outofdate = bitmap->flags & BITMAP_STALE;
-#endif
if (outofdate)
printk(KERN_INFO "%s: bitmap file is out of date, doing full "
"recovery\n", bmname(bitmap));
@@ -1111,7 +1075,6 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
(sector_t)i << CHUNK_BLOCK_SHIFT(bitmap),
needed);
bit_cnt++;
- set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
}
}
@@ -1146,6 +1109,7 @@ void bitmap_write_all(struct bitmap *bitmap)
for (i = 0; i < bitmap->file_pages; i++)
set_page_attr(bitmap, bitmap->filemap[i],
BITMAP_PAGE_NEEDWRITE);
+ bitmap->allclean = 0;
}
static void bitmap_count_page(struct bitmap *bitmap, sector_t offset, int inc)
@@ -1164,7 +1128,7 @@ static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap,
* out to disk
*/
-void bitmap_daemon_work(mddev_t *mddev)
+void bitmap_daemon_work(struct mddev *mddev)
{
struct bitmap *bitmap;
unsigned long j;
@@ -1204,17 +1168,15 @@ void bitmap_daemon_work(mddev_t *mddev)
if (page != lastpage) {
/* skip this page unless it's marked as needing cleaning */
- if (!test_page_attr(bitmap, page, BITMAP_PAGE_CLEAN)) {
+ if (!test_page_attr(bitmap, page, BITMAP_PAGE_PENDING)) {
int need_write = test_page_attr(bitmap, page,
BITMAP_PAGE_NEEDWRITE);
if (need_write)
clear_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE);
spin_unlock_irqrestore(&bitmap->lock, flags);
- if (need_write) {
+ if (need_write)
write_page(bitmap, page, 0);
- bitmap->allclean = 0;
- }
spin_lock_irqsave(&bitmap->lock, flags);
j |= (PAGE_BITS - 1);
continue;
@@ -1222,12 +1184,16 @@ void bitmap_daemon_work(mddev_t *mddev)
/* grab the new page, sync and release the old */
if (lastpage != NULL) {
- if (test_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE)) {
- clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
+ if (test_page_attr(bitmap, lastpage,
+ BITMAP_PAGE_NEEDWRITE)) {
+ clear_page_attr(bitmap, lastpage,
+ BITMAP_PAGE_NEEDWRITE);
spin_unlock_irqrestore(&bitmap->lock, flags);
write_page(bitmap, lastpage, 0);
} else {
- set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
+ set_page_attr(bitmap, lastpage,
+ BITMAP_PAGE_NEEDWRITE);
+ bitmap->allclean = 0;
spin_unlock_irqrestore(&bitmap->lock, flags);
}
} else
@@ -1249,19 +1215,17 @@ void bitmap_daemon_work(mddev_t *mddev)
}
spin_lock_irqsave(&bitmap->lock, flags);
if (!bitmap->need_sync)
- clear_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
+ clear_page_attr(bitmap, page, BITMAP_PAGE_PENDING);
+ else
+ bitmap->allclean = 0;
}
bmc = bitmap_get_counter(bitmap,
(sector_t)j << CHUNK_BLOCK_SHIFT(bitmap),
&blocks, 0);
- if (bmc) {
- if (*bmc)
- bitmap->allclean = 0;
-
- if (*bmc == 2) {
- *bmc = 1; /* maybe clear the bit next time */
- set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
- } else if (*bmc == 1 && !bitmap->need_sync) {
+ if (!bmc)
+ j |= PAGE_COUNTER_MASK;
+ else if (*bmc) {
+ if (*bmc == 1 && !bitmap->need_sync) {
/* we can clear the bit */
*bmc = 0;
bitmap_count_page(bitmap,
@@ -1275,13 +1239,16 @@ void bitmap_daemon_work(mddev_t *mddev)
paddr);
else
__clear_bit_le(
- file_page_offset(bitmap,
- j),
- paddr);
+ file_page_offset(bitmap,
+ j),
+ paddr);
kunmap_atomic(paddr, KM_USER0);
+ } else if (*bmc <= 2) {
+ *bmc = 1; /* maybe clear the bit next time */
+ set_page_attr(bitmap, page, BITMAP_PAGE_PENDING);
+ bitmap->allclean = 0;
}
- } else
- j |= PAGE_COUNTER_MASK;
+ }
}
spin_unlock_irqrestore(&bitmap->lock, flags);
@@ -1294,6 +1261,7 @@ void bitmap_daemon_work(mddev_t *mddev)
write_page(bitmap, lastpage, 0);
} else {
set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
+ bitmap->allclean = 0;
spin_unlock_irqrestore(&bitmap->lock, flags);
}
}
@@ -1359,8 +1327,8 @@ int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sect
if (bw > bitmap->behind_writes_used)
bitmap->behind_writes_used = bw;
- PRINTK(KERN_DEBUG "inc write-behind count %d/%d\n",
- bw, bitmap->max_write_behind);
+ pr_debug("inc write-behind count %d/%lu\n",
+ bw, bitmap->mddev->bitmap_info.max_write_behind);
}
while (sectors) {
@@ -1407,7 +1375,6 @@ int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sect
else
sectors = 0;
}
- bitmap->allclean = 0;
return 0;
}
EXPORT_SYMBOL(bitmap_startwrite);
@@ -1420,8 +1387,9 @@ void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long secto
if (behind) {
if (atomic_dec_and_test(&bitmap->behind_writes))
wake_up(&bitmap->behind_wait);
- PRINTK(KERN_DEBUG "dec write-behind count %d/%d\n",
- atomic_read(&bitmap->behind_writes), bitmap->max_write_behind);
+ pr_debug("dec write-behind count %d/%lu\n",
+ atomic_read(&bitmap->behind_writes),
+ bitmap->mddev->bitmap_info.max_write_behind);
}
if (bitmap->mddev->degraded)
/* Never clear bits or update events_cleared when degraded */
@@ -1453,13 +1421,14 @@ void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long secto
wake_up(&bitmap->overflow_wait);
(*bmc)--;
- if (*bmc <= 2)
+ if (*bmc <= 2) {
set_page_attr(bitmap,
filemap_get_page(
bitmap,
offset >> CHUNK_BLOCK_SHIFT(bitmap)),
- BITMAP_PAGE_CLEAN);
-
+ BITMAP_PAGE_PENDING);
+ bitmap->allclean = 0;
+ }
spin_unlock_irqrestore(&bitmap->lock, flags);
offset += blocks;
if (sectors > blocks)
@@ -1495,7 +1464,6 @@ static int __bitmap_start_sync(struct bitmap *bitmap, sector_t offset, sector_t
}
}
spin_unlock_irq(&bitmap->lock);
- bitmap->allclean = 0;
return rv;
}
@@ -1543,15 +1511,16 @@ void bitmap_end_sync(struct bitmap *bitmap, sector_t offset, sector_t *blocks, i
if (!NEEDED(*bmc) && aborted)
*bmc |= NEEDED_MASK;
else {
- if (*bmc <= 2)
+ if (*bmc <= 2) {
set_page_attr(bitmap,
filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap)),
- BITMAP_PAGE_CLEAN);
+ BITMAP_PAGE_PENDING);
+ bitmap->allclean = 0;
+ }
}
}
unlock:
spin_unlock_irqrestore(&bitmap->lock, flags);
- bitmap->allclean = 0;
}
EXPORT_SYMBOL(bitmap_end_sync);
@@ -1622,10 +1591,10 @@ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int n
*bmc = 1 | (needed ? NEEDED_MASK : 0);
bitmap_count_page(bitmap, offset, 1);
page = filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap));
- set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
+ set_page_attr(bitmap, page, BITMAP_PAGE_PENDING);
+ bitmap->allclean = 0;
}
spin_unlock_irq(&bitmap->lock);
- bitmap->allclean = 0;
}
/* dirty the memory and file bits for bitmap chunks "s" to "e" */
@@ -1649,7 +1618,7 @@ void bitmap_dirty_bits(struct bitmap *bitmap, unsigned long s, unsigned long e)
/*
* flush out any pending updates
*/
-void bitmap_flush(mddev_t *mddev)
+void bitmap_flush(struct mddev *mddev)
{
struct bitmap *bitmap = mddev->bitmap;
long sleep;
@@ -1697,7 +1666,7 @@ static void bitmap_free(struct bitmap *bitmap)
kfree(bitmap);
}
-void bitmap_destroy(mddev_t *mddev)
+void bitmap_destroy(struct mddev *mddev)
{
struct bitmap *bitmap = mddev->bitmap;
@@ -1720,7 +1689,7 @@ void bitmap_destroy(mddev_t *mddev)
* initialize the bitmap structure
* if this returns an error, bitmap_destroy must be called to do clean up
*/
-int bitmap_create(mddev_t *mddev)
+int bitmap_create(struct mddev *mddev)
{
struct bitmap *bitmap;
sector_t blocks = mddev->resync_max_sectors;
@@ -1802,11 +1771,8 @@ int bitmap_create(mddev_t *mddev)
bitmap->pages = pages;
bitmap->missing_pages = pages;
-#ifdef INJECT_FATAL_FAULT_1
- bitmap->bp = NULL;
-#else
bitmap->bp = kzalloc(pages * sizeof(*bitmap->bp), GFP_KERNEL);
-#endif
+
err = -ENOMEM;
if (!bitmap->bp)
goto error;
@@ -1824,7 +1790,7 @@ int bitmap_create(mddev_t *mddev)
return err;
}
-int bitmap_load(mddev_t *mddev)
+int bitmap_load(struct mddev *mddev)
{
int err = 0;
sector_t start = 0;
@@ -1870,7 +1836,7 @@ out:
EXPORT_SYMBOL_GPL(bitmap_load);
static ssize_t
-location_show(mddev_t *mddev, char *page)
+location_show(struct mddev *mddev, char *page)
{
ssize_t len;
if (mddev->bitmap_info.file)
@@ -1884,7 +1850,7 @@ location_show(mddev_t *mddev, char *page)
}
static ssize_t
-location_store(mddev_t *mddev, const char *buf, size_t len)
+location_store(struct mddev *mddev, const char *buf, size_t len)
{
if (mddev->pers) {
@@ -1961,7 +1927,7 @@ static struct md_sysfs_entry bitmap_location =
__ATTR(location, S_IRUGO|S_IWUSR, location_show, location_store);
static ssize_t
-timeout_show(mddev_t *mddev, char *page)
+timeout_show(struct mddev *mddev, char *page)
{
ssize_t len;
unsigned long secs = mddev->bitmap_info.daemon_sleep / HZ;
@@ -1975,7 +1941,7 @@ timeout_show(mddev_t *mddev, char *page)
}
static ssize_t
-timeout_store(mddev_t *mddev, const char *buf, size_t len)
+timeout_store(struct mddev *mddev, const char *buf, size_t len)
{
/* timeout can be set at any time */
unsigned long timeout;
@@ -2011,13 +1977,13 @@ static struct md_sysfs_entry bitmap_timeout =
__ATTR(time_base, S_IRUGO|S_IWUSR, timeout_show, timeout_store);
static ssize_t
-backlog_show(mddev_t *mddev, char *page)
+backlog_show(struct mddev *mddev, char *page)
{
return sprintf(page, "%lu\n", mddev->bitmap_info.max_write_behind);
}
static ssize_t
-backlog_store(mddev_t *mddev, const char *buf, size_t len)
+backlog_store(struct mddev *mddev, const char *buf, size_t len)
{
unsigned long backlog;
int rv = strict_strtoul(buf, 10, &backlog);
@@ -2033,13 +1999,13 @@ static struct md_sysfs_entry bitmap_backlog =
__ATTR(backlog, S_IRUGO|S_IWUSR, backlog_show, backlog_store);
static ssize_t
-chunksize_show(mddev_t *mddev, char *page)
+chunksize_show(struct mddev *mddev, char *page)
{
return sprintf(page, "%lu\n", mddev->bitmap_info.chunksize);
}
static ssize_t
-chunksize_store(mddev_t *mddev, const char *buf, size_t len)
+chunksize_store(struct mddev *mddev, const char *buf, size_t len)
{
/* Can only be changed when no bitmap is active */
int rv;
@@ -2059,13 +2025,13 @@ chunksize_store(mddev_t *mddev, const char *buf, size_t len)
static struct md_sysfs_entry bitmap_chunksize =
__ATTR(chunksize, S_IRUGO|S_IWUSR, chunksize_show, chunksize_store);
-static ssize_t metadata_show(mddev_t *mddev, char *page)
+static ssize_t metadata_show(struct mddev *mddev, char *page)
{
return sprintf(page, "%s\n", (mddev->bitmap_info.external
? "external" : "internal"));
}
-static ssize_t metadata_store(mddev_t *mddev, const char *buf, size_t len)
+static ssize_t metadata_store(struct mddev *mddev, const char *buf, size_t len)
{
if (mddev->bitmap ||
mddev->bitmap_info.file ||
@@ -2083,7 +2049,7 @@ static ssize_t metadata_store(mddev_t *mddev, const char *buf, size_t len)
static struct md_sysfs_entry bitmap_metadata =
__ATTR(metadata, S_IRUGO|S_IWUSR, metadata_show, metadata_store);
-static ssize_t can_clear_show(mddev_t *mddev, char *page)
+static ssize_t can_clear_show(struct mddev *mddev, char *page)
{
int len;
if (mddev->bitmap)
@@ -2094,7 +2060,7 @@ static ssize_t can_clear_show(mddev_t *mddev, char *page)
return len;
}
-static ssize_t can_clear_store(mddev_t *mddev, const char *buf, size_t len)
+static ssize_t can_clear_store(struct mddev *mddev, const char *buf, size_t len)
{
if (mddev->bitmap == NULL)
return -ENOENT;
@@ -2113,7 +2079,7 @@ static struct md_sysfs_entry bitmap_can_clear =
__ATTR(can_clear, S_IRUGO|S_IWUSR, can_clear_show, can_clear_store);
static ssize_t
-behind_writes_used_show(mddev_t *mddev, char *page)
+behind_writes_used_show(struct mddev *mddev, char *page)
{
if (mddev->bitmap == NULL)
return sprintf(page, "0\n");
@@ -2122,7 +2088,7 @@ behind_writes_used_show(mddev_t *mddev, char *page)
}
static ssize_t
-behind_writes_used_reset(mddev_t *mddev, const char *buf, size_t len)
+behind_writes_used_reset(struct mddev *mddev, const char *buf, size_t len)
{
if (mddev->bitmap)
mddev->bitmap->behind_writes_used = 0;