Skip to content

Commit

Permalink
Merge tag 'md-3.4' of git://neil.brown.name/md
Browse files Browse the repository at this point in the history
Pull md updates for 3.4 from Neil Brown:
 "Mostly tidying up code in preparation for some bigger changes next
  time.

  A few bug fixes tagged for -stable.

  Main functionality change is that some RAID10 arrays can now grow to
  use extra space that may have been made available on the individual
  devices."

Fixed up trivial conflicts with the k[un]map_atomic() cleanups in
drivers/md/bitmap.c.

* tag 'md-3.4' of git://neil.brown.name/md: (22 commits)
  md: Add judgement bb->unacked_exist in function md_ack_all_badblocks().
  md: fix clearing of the 'changed' flags for the bad blocks list.
  md/bitmap: discard CHUNK_BLOCK_SHIFT macro
  md/bitmap: remove unnecessary indirection when allocating.
  md/bitmap: remove some pointless locking.
  md/bitmap: change a 'goto' to a normal 'if' construct.
  md/bitmap: move printing of bitmap status to bitmap.c
  md/bitmap: remove some unused noise from bitmap.h
  md/raid10 - support resizing some RAID10 arrays.
  md/raid1: handle merge_bvec_fn in member devices.
  md/raid10: handle merge_bvec_fn in member devices.
  md: add proper merge_bvec handling to RAID0 and Linear.
  md: tidy up rdev_for_each usage.
  md/raid1,raid10: avoid deadlock during resync/recovery.
  md/bitmap: ensure to load bitmap when creating via sysfs.
  md: don't set md arrays to readonly on shutdown.
  md: allow re-add to failed arrays.
  md/raid5: use atomic_dec_return() instead of atomic_dec() and atomic_read().
  md: Use existed macros instead of numbers
  md/raid5: removed unused 'added_devices' variable.
  ...
  • Loading branch information
torvalds committed Mar 22, 2012
2 parents 28f23d1 + ecb178b commit 267d7b2
Show file tree
Hide file tree
Showing 14 changed files with 496 additions and 374 deletions.
152 changes: 75 additions & 77 deletions drivers/md/bitmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <linux/file.h>
#include <linux/mount.h>
#include <linux/buffer_head.h>
#include <linux/seq_file.h>
#include "md.h"
#include "bitmap.h"

Expand All @@ -34,31 +35,6 @@ static inline char *bmname(struct bitmap *bitmap)
return bitmap->mddev ? mdname(bitmap->mddev) : "mdX";
}

/*
* just a placeholder - calls kmalloc for bitmap pages
*/
static unsigned char *bitmap_alloc_page(struct bitmap *bitmap)
{
unsigned char *page;

page = kzalloc(PAGE_SIZE, GFP_NOIO);
if (!page)
printk("%s: bitmap_alloc_page FAILED\n", bmname(bitmap));
else
pr_debug("%s: bitmap_alloc_page: allocated page at %p\n",
bmname(bitmap), page);
return page;
}

/*
* for now just a placeholder -- just calls kfree for bitmap pages
*/
static void bitmap_free_page(struct bitmap *bitmap, unsigned char *page)
{
pr_debug("%s: bitmap_free_page: free page %p\n", bmname(bitmap), page);
kfree(page);
}

/*
* check a page and, if necessary, allocate it (or hijack it if the alloc fails)
*
Expand Down Expand Up @@ -96,7 +72,7 @@ __acquires(bitmap->lock)
/* this page has not been allocated yet */

spin_unlock_irq(&bitmap->lock);
mappage = bitmap_alloc_page(bitmap);
mappage = kzalloc(PAGE_SIZE, GFP_NOIO);
spin_lock_irq(&bitmap->lock);

if (mappage == NULL) {
Expand All @@ -109,7 +85,7 @@ __acquires(bitmap->lock)
} else if (bitmap->bp[page].map ||
bitmap->bp[page].hijacked) {
/* somebody beat us to getting the page */
bitmap_free_page(bitmap, mappage);
kfree(mappage);
return 0;
} else {

Expand Down Expand Up @@ -141,7 +117,7 @@ static void bitmap_checkfree(struct bitmap *bitmap, unsigned long page)
ptr = bitmap->bp[page].map;
bitmap->bp[page].map = NULL;
bitmap->missing_pages++;
bitmap_free_page(bitmap, ptr);
kfree(ptr);
}
}

Expand Down Expand Up @@ -171,7 +147,7 @@ static struct page *read_sb_page(struct mddev *mddev, loff_t offset,
did_alloc = 1;
}

list_for_each_entry(rdev, &mddev->disks, same_set) {
rdev_for_each(rdev, mddev) {
if (! test_bit(In_sync, &rdev->flags)
|| test_bit(Faulty, &rdev->flags))
continue;
Expand Down Expand Up @@ -445,18 +421,13 @@ static struct page *read_page(struct file *file, unsigned long index,
void bitmap_update_sb(struct bitmap *bitmap)
{
bitmap_super_t *sb;
unsigned long flags;

if (!bitmap || !bitmap->mddev) /* no bitmap for this array */
return;
if (bitmap->mddev->bitmap_info.external)
return;
spin_lock_irqsave(&bitmap->lock, flags);
if (!bitmap->sb_page) { /* no superblock */
spin_unlock_irqrestore(&bitmap->lock, flags);
if (!bitmap->sb_page) /* no superblock */
return;
}
spin_unlock_irqrestore(&bitmap->lock, flags);
sb = kmap_atomic(bitmap->sb_page);
sb->events = cpu_to_le64(bitmap->mddev->events);
if (bitmap->mddev->events < bitmap->events_cleared)
Expand Down Expand Up @@ -632,26 +603,28 @@ static int bitmap_read_sb(struct bitmap *bitmap)
/* keep the array size field of the bitmap superblock up to date */
sb->sync_size = cpu_to_le64(bitmap->mddev->resync_max_sectors);

if (!bitmap->mddev->persistent)
goto success;

/*
* if we have a persistent array superblock, compare the
* bitmap's UUID and event counter to the mddev's
*/
if (memcmp(sb->uuid, bitmap->mddev->uuid, 16)) {
printk(KERN_INFO "%s: bitmap superblock UUID mismatch\n",
bmname(bitmap));
goto out;
}
events = le64_to_cpu(sb->events);
if (events < bitmap->mddev->events) {
printk(KERN_INFO "%s: bitmap file is out of date (%llu < %llu) "
"-- forcing full recovery\n", bmname(bitmap), events,
(unsigned long long) bitmap->mddev->events);
sb->state |= cpu_to_le32(BITMAP_STALE);
if (bitmap->mddev->persistent) {
/*
* We have a persistent array superblock, so compare the
* bitmap's UUID and event counter to the mddev's
*/
if (memcmp(sb->uuid, bitmap->mddev->uuid, 16)) {
printk(KERN_INFO
"%s: bitmap superblock UUID mismatch\n",
bmname(bitmap));
goto out;
}
events = le64_to_cpu(sb->events);
if (events < bitmap->mddev->events) {
printk(KERN_INFO
"%s: bitmap file is out of date (%llu < %llu) "
"-- forcing full recovery\n",
bmname(bitmap), events,
(unsigned long long) bitmap->mddev->events);
sb->state |= cpu_to_le32(BITMAP_STALE);
}
}
success:

/* assign fields using values from superblock */
bitmap->mddev->bitmap_info.chunksize = chunksize;
bitmap->mddev->bitmap_info.daemon_sleep = daemon_sleep;
Expand Down Expand Up @@ -680,15 +653,10 @@ static int bitmap_mask_state(struct bitmap *bitmap, enum bitmap_state bits,
enum bitmap_mask_op op)
{
bitmap_super_t *sb;
unsigned long flags;
int old;

spin_lock_irqsave(&bitmap->lock, flags);
if (!bitmap->sb_page) { /* can't set the state */
spin_unlock_irqrestore(&bitmap->lock, flags);
if (!bitmap->sb_page) /* can't set the state */
return 0;
}
spin_unlock_irqrestore(&bitmap->lock, flags);
sb = kmap_atomic(bitmap->sb_page);
old = le32_to_cpu(sb->state) & bits;
switch (op) {
Expand Down Expand Up @@ -870,7 +838,7 @@ static void bitmap_file_set_bit(struct bitmap *bitmap, sector_t block)
unsigned long bit;
struct page *page;
void *kaddr;
unsigned long chunk = block >> CHUNK_BLOCK_SHIFT(bitmap);
unsigned long chunk = block >> bitmap->chunkshift;

if (!bitmap->filemap)
return;
Expand Down Expand Up @@ -1069,10 +1037,10 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
kunmap_atomic(paddr);
if (b) {
/* if the disk bit is set, set the memory bit */
int needed = ((sector_t)(i+1) << (CHUNK_BLOCK_SHIFT(bitmap))
int needed = ((sector_t)(i+1) << bitmap->chunkshift
>= start);
bitmap_set_memory_bits(bitmap,
(sector_t)i << CHUNK_BLOCK_SHIFT(bitmap),
(sector_t)i << bitmap->chunkshift,
needed);
bit_cnt++;
}
Expand Down Expand Up @@ -1116,7 +1084,7 @@ void bitmap_write_all(struct bitmap *bitmap)

static void bitmap_count_page(struct bitmap *bitmap, sector_t offset, int inc)
{
sector_t chunk = offset >> CHUNK_BLOCK_SHIFT(bitmap);
sector_t chunk = offset >> bitmap->chunkshift;
unsigned long page = chunk >> PAGE_COUNTER_SHIFT;
bitmap->bp[page].count += inc;
bitmap_checkfree(bitmap, page);
Expand Down Expand Up @@ -1222,7 +1190,7 @@ void bitmap_daemon_work(struct mddev *mddev)
bitmap->allclean = 0;
}
bmc = bitmap_get_counter(bitmap,
(sector_t)j << CHUNK_BLOCK_SHIFT(bitmap),
(sector_t)j << bitmap->chunkshift,
&blocks, 0);
if (!bmc)
j |= PAGE_COUNTER_MASK;
Expand All @@ -1231,7 +1199,7 @@ void bitmap_daemon_work(struct mddev *mddev)
/* we can clear the bit */
*bmc = 0;
bitmap_count_page(bitmap,
(sector_t)j << CHUNK_BLOCK_SHIFT(bitmap),
(sector_t)j << bitmap->chunkshift,
-1);

/* clear the bit */
Expand Down Expand Up @@ -1285,7 +1253,7 @@ __acquires(bitmap->lock)
* The lock must have been taken with interrupts enabled.
* If !create, we don't release the lock.
*/
sector_t chunk = offset >> CHUNK_BLOCK_SHIFT(bitmap);
sector_t chunk = offset >> bitmap->chunkshift;
unsigned long page = chunk >> PAGE_COUNTER_SHIFT;
unsigned long pageoff = (chunk & PAGE_COUNTER_MASK) << COUNTER_BYTE_SHIFT;
sector_t csize;
Expand All @@ -1295,10 +1263,10 @@ __acquires(bitmap->lock)

if (bitmap->bp[page].hijacked ||
bitmap->bp[page].map == NULL)
csize = ((sector_t)1) << (CHUNK_BLOCK_SHIFT(bitmap) +
csize = ((sector_t)1) << (bitmap->chunkshift +
PAGE_COUNTER_SHIFT - 1);
else
csize = ((sector_t)1) << (CHUNK_BLOCK_SHIFT(bitmap));
csize = ((sector_t)1) << bitmap->chunkshift;
*blocks = csize - (offset & (csize - 1));

if (err < 0)
Expand Down Expand Up @@ -1424,7 +1392,7 @@ void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long secto
set_page_attr(bitmap,
filemap_get_page(
bitmap,
offset >> CHUNK_BLOCK_SHIFT(bitmap)),
offset >> bitmap->chunkshift),
BITMAP_PAGE_PENDING);
bitmap->allclean = 0;
}
Expand Down Expand Up @@ -1512,7 +1480,7 @@ void bitmap_end_sync(struct bitmap *bitmap, sector_t offset, sector_t *blocks, i
else {
if (*bmc <= 2) {
set_page_attr(bitmap,
filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap)),
filemap_get_page(bitmap, offset >> bitmap->chunkshift),
BITMAP_PAGE_PENDING);
bitmap->allclean = 0;
}
Expand Down Expand Up @@ -1559,7 +1527,7 @@ void bitmap_cond_end_sync(struct bitmap *bitmap, sector_t sector)

bitmap->mddev->curr_resync_completed = sector;
set_bit(MD_CHANGE_CLEAN, &bitmap->mddev->flags);
sector &= ~((1ULL << CHUNK_BLOCK_SHIFT(bitmap)) - 1);
sector &= ~((1ULL << bitmap->chunkshift) - 1);
s = 0;
while (s < sector && s < bitmap->mddev->resync_max_sectors) {
bitmap_end_sync(bitmap, s, &blocks, 0);
Expand Down Expand Up @@ -1589,7 +1557,7 @@ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int n
struct page *page;
*bmc = 2 | (needed ? NEEDED_MASK : 0);
bitmap_count_page(bitmap, offset, 1);
page = filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap));
page = filemap_get_page(bitmap, offset >> bitmap->chunkshift);
set_page_attr(bitmap, page, BITMAP_PAGE_PENDING);
bitmap->allclean = 0;
}
Expand All @@ -1602,7 +1570,7 @@ void bitmap_dirty_bits(struct bitmap *bitmap, unsigned long s, unsigned long e)
unsigned long chunk;

for (chunk = s; chunk <= e; chunk++) {
sector_t sec = (sector_t)chunk << CHUNK_BLOCK_SHIFT(bitmap);
sector_t sec = (sector_t)chunk << bitmap->chunkshift;
bitmap_set_memory_bits(bitmap, sec, 1);
spin_lock_irq(&bitmap->lock);
bitmap_file_set_bit(bitmap, sec);
Expand Down Expand Up @@ -1759,11 +1727,12 @@ int bitmap_create(struct mddev *mddev)
goto error;

bitmap->daemon_lastrun = jiffies;
bitmap->chunkshift = ffz(~mddev->bitmap_info.chunksize);
bitmap->chunkshift = (ffz(~mddev->bitmap_info.chunksize)
- BITMAP_BLOCK_SHIFT);

/* now that chunksize and chunkshift are set, we can use these macros */
chunks = (blocks + CHUNK_BLOCK_RATIO(bitmap) - 1) >>
CHUNK_BLOCK_SHIFT(bitmap);
chunks = (blocks + bitmap->chunkshift - 1) >>
bitmap->chunkshift;
pages = (chunks + PAGE_COUNTER_RATIO - 1) / PAGE_COUNTER_RATIO;

BUG_ON(!pages);
Expand Down Expand Up @@ -1836,6 +1805,33 @@ int bitmap_load(struct mddev *mddev)
}
EXPORT_SYMBOL_GPL(bitmap_load);

void bitmap_status(struct seq_file *seq, struct bitmap *bitmap)
{
unsigned long chunk_kb;
unsigned long flags;

if (!bitmap)
return;

spin_lock_irqsave(&bitmap->lock, flags);
chunk_kb = bitmap->mddev->bitmap_info.chunksize >> 10;
seq_printf(seq, "bitmap: %lu/%lu pages [%luKB], "
"%lu%s chunk",
bitmap->pages - bitmap->missing_pages,
bitmap->pages,
(bitmap->pages - bitmap->missing_pages)
<< (PAGE_SHIFT - 10),
chunk_kb ? chunk_kb : bitmap->mddev->bitmap_info.chunksize,
chunk_kb ? "KB" : "B");
if (bitmap->file) {
seq_printf(seq, ", file: ");
seq_path(seq, &bitmap->file->f_path, " \t\n");
}

seq_printf(seq, "\n");
spin_unlock_irqrestore(&bitmap->lock, flags);
}

static ssize_t
location_show(struct mddev *mddev, char *page)
{
Expand Down Expand Up @@ -1904,6 +1900,8 @@ location_store(struct mddev *mddev, const char *buf, size_t len)
if (mddev->pers) {
mddev->pers->quiesce(mddev, 1);
rv = bitmap_create(mddev);
if (!rv)
rv = bitmap_load(mddev);
if (rv) {
bitmap_destroy(mddev);
mddev->bitmap_info.offset = 0;
Expand Down
22 changes: 2 additions & 20 deletions drivers/md/bitmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@
#define BITMAP_MAJOR_HI 4
#define BITMAP_MAJOR_HOSTENDIAN 3

#define BITMAP_MINOR 39

/*
* in-memory bitmap:
*
Expand Down Expand Up @@ -101,21 +99,10 @@ typedef __u16 bitmap_counter_t;
/* same, except a mask value for more efficient bitops */
#define PAGE_COUNTER_MASK (PAGE_COUNTER_RATIO - 1)

#define BITMAP_BLOCK_SIZE 512
#define BITMAP_BLOCK_SHIFT 9

/* how many blocks per chunk? (this is variable) */
#define CHUNK_BLOCK_RATIO(bitmap) ((bitmap)->mddev->bitmap_info.chunksize >> BITMAP_BLOCK_SHIFT)
#define CHUNK_BLOCK_SHIFT(bitmap) ((bitmap)->chunkshift - BITMAP_BLOCK_SHIFT)
#define CHUNK_BLOCK_MASK(bitmap) (CHUNK_BLOCK_RATIO(bitmap) - 1)

/* when hijacked, the counters and bits represent even larger "chunks" */
/* there will be 1024 chunks represented by each counter in the page pointers */
#define PAGEPTR_BLOCK_RATIO(bitmap) \
(CHUNK_BLOCK_RATIO(bitmap) << PAGE_COUNTER_SHIFT >> 1)
#define PAGEPTR_BLOCK_SHIFT(bitmap) \
(CHUNK_BLOCK_SHIFT(bitmap) + PAGE_COUNTER_SHIFT - 1)
#define PAGEPTR_BLOCK_MASK(bitmap) (PAGEPTR_BLOCK_RATIO(bitmap) - 1)

#endif

Expand Down Expand Up @@ -181,12 +168,6 @@ struct bitmap_page {
unsigned int count:31;
};

/* keep track of bitmap file pages that have pending writes on them */
struct page_list {
struct list_head list;
struct page *page;
};

/* the main bitmap structure - one per mddev */
struct bitmap {
struct bitmap_page *bp;
Expand All @@ -196,7 +177,7 @@ struct bitmap {
struct mddev *mddev; /* the md device that the bitmap is for */

/* bitmap chunksize -- how much data does each bit represent? */
unsigned long chunkshift; /* chunksize = 2^chunkshift (for bitops) */
unsigned long chunkshift; /* chunksize = 2^(chunkshift+9) (for bitops) */
unsigned long chunks; /* total number of data chunks for the array */

__u64 events_cleared;
Expand Down Expand Up @@ -245,6 +226,7 @@ void bitmap_destroy(struct mddev *mddev);

void bitmap_print_sb(struct bitmap *bitmap);
void bitmap_update_sb(struct bitmap *bitmap);
void bitmap_status(struct seq_file *seq, struct bitmap *bitmap);

int bitmap_setallbits(struct bitmap *bitmap);
void bitmap_write_all(struct bitmap *bitmap);
Expand Down
Loading

0 comments on commit 267d7b2

Please sign in to comment.