[PATCH] md/bitmap: remove bitmap writeback daemon

md/bitmap currently has a separate thread to wait for writes to the bitmap
file to complete (as we cannot get a callback on that action).

However this isn't needed as bitmap_unplug is called from process context and
waits for the writeback thread to do it's work.  The same result can be
achieved by doing the waiting directly in bitmap_unplug.

Signed-off-by: Neil Brown <neilb@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
NeilBrown 2006-06-26 00:27:44 -07:00 committed by Linus Torvalds
parent d7375ab324
commit 0b79ccf0cd
2 changed files with 8 additions and 113 deletions

View File

@ -7,7 +7,6 @@
* additions, Copyright (C) 2003-2004, Paul Clements, SteelEye Technology, Inc.: * additions, Copyright (C) 2003-2004, Paul Clements, SteelEye Technology, Inc.:
* - added disk storage for bitmap * - added disk storage for bitmap
* - changes to allow various bitmap chunk sizes * - changes to allow various bitmap chunk sizes
* - added bitmap daemon (to asynchronously clear bitmap bits from disk)
*/ */
/* /*
@ -330,14 +329,13 @@ static int write_page(struct bitmap *bitmap, struct page *page, int wait)
set_page_dirty(page); /* force it to be written out */ set_page_dirty(page); /* force it to be written out */
if (!wait) { if (!wait) {
/* add to list to be waited for by daemon */ /* add to list to be waited for */
struct page_list *item = mempool_alloc(bitmap->write_pool, GFP_NOIO); struct page_list *item = mempool_alloc(bitmap->write_pool, GFP_NOIO);
item->page = page; item->page = page;
get_page(page); get_page(page);
spin_lock(&bitmap->write_lock); spin_lock(&bitmap->write_lock);
list_add(&item->list, &bitmap->complete_pages); list_add(&item->list, &bitmap->complete_pages);
spin_unlock(&bitmap->write_lock); spin_unlock(&bitmap->write_lock);
md_wakeup_thread(bitmap->writeback_daemon);
} }
return write_one_page(page, wait); return write_one_page(page, wait);
} }
@ -621,8 +619,6 @@ static void bitmap_file_unmap(struct bitmap *bitmap)
safe_put_page(sb_page); safe_put_page(sb_page);
} }
static void bitmap_stop_daemon(struct bitmap *bitmap);
/* dequeue the next item in a page list -- don't call from irq context */ /* dequeue the next item in a page list -- don't call from irq context */
static struct page_list *dequeue_page(struct bitmap *bitmap) static struct page_list *dequeue_page(struct bitmap *bitmap)
{ {
@ -648,8 +644,6 @@ static void drain_write_queues(struct bitmap *bitmap)
put_page(item->page); put_page(item->page);
mempool_free(item, bitmap->write_pool); mempool_free(item, bitmap->write_pool);
} }
wake_up(&bitmap->write_wait);
} }
static void bitmap_file_put(struct bitmap *bitmap) static void bitmap_file_put(struct bitmap *bitmap)
@ -663,8 +657,6 @@ static void bitmap_file_put(struct bitmap *bitmap)
bitmap->file = NULL; bitmap->file = NULL;
spin_unlock_irqrestore(&bitmap->lock, flags); spin_unlock_irqrestore(&bitmap->lock, flags);
bitmap_stop_daemon(bitmap);
drain_write_queues(bitmap); drain_write_queues(bitmap);
bitmap_file_unmap(bitmap); bitmap_file_unmap(bitmap);
@ -770,6 +762,8 @@ static void bitmap_file_set_bit(struct bitmap *bitmap, sector_t block)
} }
static void bitmap_writeback(struct bitmap *bitmap);
/* this gets called when the md device is ready to unplug its underlying /* this gets called when the md device is ready to unplug its underlying
* (slave) device queues -- before we let any writes go down, we need to * (slave) device queues -- before we let any writes go down, we need to
* sync the dirty pages of the bitmap file to disk */ * sync the dirty pages of the bitmap file to disk */
@ -812,13 +806,9 @@ int bitmap_unplug(struct bitmap *bitmap)
} }
} }
if (wait) { /* if any writes were performed, we need to wait on them */ if (wait) { /* if any writes were performed, we need to wait on them */
if (bitmap->file) { if (bitmap->file)
spin_lock_irq(&bitmap->write_lock); bitmap_writeback(bitmap);
wait_event_lock_irq(bitmap->write_wait, else
list_empty(&bitmap->complete_pages), bitmap->write_lock,
wake_up_process(bitmap->writeback_daemon->tsk));
spin_unlock_irq(&bitmap->write_lock);
} else
md_super_wait(bitmap->mddev); md_super_wait(bitmap->mddev);
} }
return 0; return 0;
@ -1126,41 +1116,12 @@ int bitmap_daemon_work(struct bitmap *bitmap)
return err; return err;
} }
static void daemon_exit(struct bitmap *bitmap, mdk_thread_t **daemon) static void bitmap_writeback(struct bitmap *bitmap)
{ {
mdk_thread_t *dmn;
unsigned long flags;
/* if no one is waiting on us, we'll free the md thread struct
* and exit, otherwise we let the waiter clean things up */
spin_lock_irqsave(&bitmap->lock, flags);
if ((dmn = *daemon)) { /* no one is waiting, cleanup and exit */
*daemon = NULL;
spin_unlock_irqrestore(&bitmap->lock, flags);
kfree(dmn);
complete_and_exit(NULL, 0); /* do_exit not exported */
}
spin_unlock_irqrestore(&bitmap->lock, flags);
}
static void bitmap_writeback_daemon(mddev_t *mddev)
{
struct bitmap *bitmap = mddev->bitmap;
struct page *page; struct page *page;
struct page_list *item; struct page_list *item;
int err = 0; int err = 0;
if (signal_pending(current)) {
printk(KERN_INFO
"%s: bitmap writeback daemon got signal, exiting...\n",
bmname(bitmap));
err = -EINTR;
goto out;
}
if (bitmap == NULL)
/* about to be stopped. */
return;
PRINTK("%s: bitmap writeback daemon woke up...\n", bmname(bitmap)); PRINTK("%s: bitmap writeback daemon woke up...\n", bmname(bitmap));
/* wait on bitmap page writebacks */ /* wait on bitmap page writebacks */
while ((item = dequeue_page(bitmap))) { while ((item = dequeue_page(bitmap))) {
@ -1177,59 +1138,9 @@ static void bitmap_writeback_daemon(mddev_t *mddev)
"failed (page %lu): %d\n", "failed (page %lu): %d\n",
bmname(bitmap), page->index, err); bmname(bitmap), page->index, err);
bitmap_file_kick(bitmap); bitmap_file_kick(bitmap);
goto out; break;
} }
} }
out:
wake_up(&bitmap->write_wait);
if (err) {
printk(KERN_INFO "%s: bitmap writeback daemon exiting (%d)\n",
bmname(bitmap), err);
daemon_exit(bitmap, &bitmap->writeback_daemon);
}
}
static mdk_thread_t *bitmap_start_daemon(struct bitmap *bitmap,
void (*func)(mddev_t *), char *name)
{
mdk_thread_t *daemon;
char namebuf[32];
#ifdef INJECT_FATAL_FAULT_2
daemon = NULL;
#else
sprintf(namebuf, "%%s_%s", name);
daemon = md_register_thread(func, bitmap->mddev, namebuf);
#endif
if (!daemon) {
printk(KERN_ERR "%s: failed to start bitmap daemon\n",
bmname(bitmap));
return ERR_PTR(-ECHILD);
}
md_wakeup_thread(daemon); /* start it running */
PRINTK("%s: %s daemon (pid %d) started...\n",
bmname(bitmap), name, daemon->tsk->pid);
return daemon;
}
static void bitmap_stop_daemon(struct bitmap *bitmap)
{
/* the daemon can't stop itself... it'll just exit instead... */
if (bitmap->writeback_daemon && ! IS_ERR(bitmap->writeback_daemon) &&
current->pid != bitmap->writeback_daemon->tsk->pid) {
mdk_thread_t *daemon;
unsigned long flags;
spin_lock_irqsave(&bitmap->lock, flags);
daemon = bitmap->writeback_daemon;
bitmap->writeback_daemon = NULL;
spin_unlock_irqrestore(&bitmap->lock, flags);
if (daemon && ! IS_ERR(daemon))
md_unregister_thread(daemon); /* destroy the thread */
}
} }
static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap, static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap,
@ -1553,7 +1464,6 @@ int bitmap_create(mddev_t *mddev)
spin_lock_init(&bitmap->write_lock); spin_lock_init(&bitmap->write_lock);
INIT_LIST_HEAD(&bitmap->complete_pages); INIT_LIST_HEAD(&bitmap->complete_pages);
init_waitqueue_head(&bitmap->write_wait);
bitmap->write_pool = mempool_create_kmalloc_pool(WRITE_POOL_SIZE, bitmap->write_pool = mempool_create_kmalloc_pool(WRITE_POOL_SIZE,
sizeof(struct page_list)); sizeof(struct page_list));
err = -ENOMEM; err = -ENOMEM;
@ -1613,15 +1523,6 @@ int bitmap_create(mddev_t *mddev)
mddev->bitmap = bitmap; mddev->bitmap = bitmap;
if (file)
/* kick off the bitmap writeback daemon */
bitmap->writeback_daemon =
bitmap_start_daemon(bitmap,
bitmap_writeback_daemon,
"bitmap_wb");
if (IS_ERR(bitmap->writeback_daemon))
return PTR_ERR(bitmap->writeback_daemon);
mddev->thread->timeout = bitmap->daemon_sleep * HZ; mddev->thread->timeout = bitmap->daemon_sleep * HZ;
return bitmap_update_sb(bitmap); return bitmap_update_sb(bitmap);

View File

@ -244,13 +244,7 @@ struct bitmap {
unsigned long daemon_lastrun; /* jiffies of last run */ unsigned long daemon_lastrun; /* jiffies of last run */
unsigned long daemon_sleep; /* how many seconds between updates? */ unsigned long daemon_sleep; /* how many seconds between updates? */
/*
* bitmap_writeback_daemon waits for file-pages that have been written,
* as there is no way to get a call-back when a page write completes.
*/
mdk_thread_t *writeback_daemon;
spinlock_t write_lock; spinlock_t write_lock;
wait_queue_head_t write_wait;
struct list_head complete_pages; struct list_head complete_pages;
mempool_t *write_pool; mempool_t *write_pool;
}; };