diff options
| author | NeilBrown <neilb@suse.de> | 2006-06-26 03:27:44 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-06-26 12:58:38 -0400 |
| commit | 0b79ccf0cdd9f59e5f99017e1a5d23da336544b2 (patch) | |
| tree | 8688d9810fcba1e24abce726eaf35ff32f6b58d9 | |
| parent | d7375ab324971e7acbea9f02a0269ae7348f4147 (diff) | |
[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>
| -rw-r--r-- | drivers/md/bitmap.c | 115 | ||||
| -rw-r--r-- | include/linux/raid/bitmap.h | 6 |
2 files changed, 8 insertions, 113 deletions
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index f8ffaee20ff..814f412a410 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c | |||
| @@ -7,7 +7,6 @@ | |||
| 7 | * additions, Copyright (C) 2003-2004, Paul Clements, SteelEye Technology, Inc.: | 7 | * additions, Copyright (C) 2003-2004, Paul Clements, SteelEye Technology, Inc.: |
| 8 | * - added disk storage for bitmap | 8 | * - added disk storage for bitmap |
| 9 | * - changes to allow various bitmap chunk sizes | 9 | * - changes to allow various bitmap chunk sizes |
| 10 | * - added bitmap daemon (to asynchronously clear bitmap bits from disk) | ||
| 11 | */ | 10 | */ |
| 12 | 11 | ||
| 13 | /* | 12 | /* |
| @@ -330,14 +329,13 @@ static int write_page(struct bitmap *bitmap, struct page *page, int wait) | |||
| 330 | set_page_dirty(page); /* force it to be written out */ | 329 | set_page_dirty(page); /* force it to be written out */ |
| 331 | 330 | ||
| 332 | if (!wait) { | 331 | if (!wait) { |
| 333 | /* add to list to be waited for by daemon */ | 332 | /* add to list to be waited for */ |
| 334 | struct page_list *item = mempool_alloc(bitmap->write_pool, GFP_NOIO); | 333 | struct page_list *item = mempool_alloc(bitmap->write_pool, GFP_NOIO); |
| 335 | item->page = page; | 334 | item->page = page; |
| 336 | get_page(page); | 335 | get_page(page); |
| 337 | spin_lock(&bitmap->write_lock); | 336 | spin_lock(&bitmap->write_lock); |
| 338 | list_add(&item->list, &bitmap->complete_pages); | 337 | list_add(&item->list, &bitmap->complete_pages); |
| 339 | spin_unlock(&bitmap->write_lock); | 338 | spin_unlock(&bitmap->write_lock); |
| 340 | md_wakeup_thread(bitmap->writeback_daemon); | ||
| 341 | } | 339 | } |
| 342 | return write_one_page(page, wait); | 340 | return write_one_page(page, wait); |
| 343 | } | 341 | } |
| @@ -621,8 +619,6 @@ static void bitmap_file_unmap(struct bitmap *bitmap) | |||
| 621 | safe_put_page(sb_page); | 619 | safe_put_page(sb_page); |
| 622 | } | 620 | } |
| 623 | 621 | ||
| 624 | static void bitmap_stop_daemon(struct bitmap *bitmap); | ||
| 625 | |||
| 626 | /* dequeue the next item in a page list -- don't call from irq context */ | 622 | /* dequeue the next item in a page list -- don't call from irq context */ |
| 627 | static struct page_list *dequeue_page(struct bitmap *bitmap) | 623 | static struct page_list *dequeue_page(struct bitmap *bitmap) |
| 628 | { | 624 | { |
| @@ -648,8 +644,6 @@ static void drain_write_queues(struct bitmap *bitmap) | |||
| 648 | put_page(item->page); | 644 | put_page(item->page); |
| 649 | mempool_free(item, bitmap->write_pool); | 645 | mempool_free(item, bitmap->write_pool); |
| 650 | } | 646 | } |
| 651 | |||
| 652 | wake_up(&bitmap->write_wait); | ||
| 653 | } | 647 | } |
| 654 | 648 | ||
| 655 | static void bitmap_file_put(struct bitmap *bitmap) | 649 | static void bitmap_file_put(struct bitmap *bitmap) |
| @@ -663,8 +657,6 @@ static void bitmap_file_put(struct bitmap *bitmap) | |||
| 663 | bitmap->file = NULL; | 657 | bitmap->file = NULL; |
| 664 | spin_unlock_irqrestore(&bitmap->lock, flags); | 658 | spin_unlock_irqrestore(&bitmap->lock, flags); |
| 665 | 659 | ||
| 666 | bitmap_stop_daemon(bitmap); | ||
| 667 | |||
| 668 | drain_write_queues(bitmap); | 660 | drain_write_queues(bitmap); |
| 669 | 661 | ||
| 670 | bitmap_file_unmap(bitmap); | 662 | bitmap_file_unmap(bitmap); |
| @@ -770,6 +762,8 @@ static void bitmap_file_set_bit(struct bitmap *bitmap, sector_t block) | |||
| 770 | 762 | ||
| 771 | } | 763 | } |
| 772 | 764 | ||
| 765 | static void bitmap_writeback(struct bitmap *bitmap); | ||
| 766 | |||
| 773 | /* this gets called when the md device is ready to unplug its underlying | 767 | /* this gets called when the md device is ready to unplug its underlying |
| 774 | * (slave) device queues -- before we let any writes go down, we need to | 768 | * (slave) device queues -- before we let any writes go down, we need to |
| 775 | * sync the dirty pages of the bitmap file to disk */ | 769 | * sync the dirty pages of the bitmap file to disk */ |
| @@ -812,13 +806,9 @@ int bitmap_unplug(struct bitmap *bitmap) | |||
| 812 | } | 806 | } |
| 813 | } | 807 | } |
| 814 | if (wait) { /* if any writes were performed, we need to wait on them */ | 808 | if (wait) { /* if any writes were performed, we need to wait on them */ |
| 815 | if (bitmap->file) { | 809 | if (bitmap->file) |
| 816 | spin_lock_irq(&bitmap->write_lock); | 810 | bitmap_writeback(bitmap); |
| 817 | wait_event_lock_irq(bitmap->write_wait, | 811 | else |
| 818 | list_empty(&bitmap->complete_pages), bitmap->write_lock, | ||
| 819 | wake_up_process(bitmap->writeback_daemon->tsk)); | ||
| 820 | spin_unlock_irq(&bitmap->write_lock); | ||
| 821 | } else | ||
| 822 | md_super_wait(bitmap->mddev); | 812 | md_super_wait(bitmap->mddev); |
| 823 | } | 813 | } |
| 824 | return 0; | 814 | return 0; |
| @@ -1126,41 +1116,12 @@ int bitmap_daemon_work(struct bitmap *bitmap) | |||
| 1126 | return err; | 1116 | return err; |
| 1127 | } | 1117 | } |
| 1128 | 1118 | ||
| 1129 | static void daemon_exit(struct bitmap *bitmap, mdk_thread_t **daemon) | 1119 | static void bitmap_writeback(struct bitmap *bitmap) |
| 1130 | { | 1120 | { |
| 1131 | mdk_thread_t *dmn; | ||
| 1132 | unsigned long flags; | ||
| 1133 | |||
| 1134 | /* if no one is waiting on us, we'll free the md thread struct | ||
| 1135 | * and exit, otherwise we let the waiter clean things up */ | ||
| 1136 | spin_lock_irqsave(&bitmap->lock, flags); | ||
| 1137 | if ((dmn = *daemon)) { /* no one is waiting, cleanup and exit */ | ||
| 1138 | *daemon = NULL; | ||
| 1139 | spin_unlock_irqrestore(&bitmap->lock, flags); | ||
| 1140 | kfree(dmn); | ||
| 1141 | complete_and_exit(NULL, 0); /* do_exit not exported */ | ||
| 1142 | } | ||
| 1143 | spin_unlock_irqrestore(&bitmap->lock, flags); | ||
| 1144 | } | ||
| 1145 | |||
| 1146 | static void bitmap_writeback_daemon(mddev_t *mddev) | ||
| 1147 | { | ||
| 1148 | struct bitmap *bitmap = mddev->bitmap; | ||
| 1149 | struct page *page; | 1121 | struct page *page; |
| 1150 | struct page_list *item; | 1122 | struct page_list *item; |
| 1151 | int err = 0; | 1123 | int err = 0; |
| 1152 | 1124 | ||
| 1153 | if (signal_pending(current)) { | ||
| 1154 | printk(KERN_INFO | ||
| 1155 | "%s: bitmap writeback daemon got signal, exiting...\n", | ||
| 1156 | bmname(bitmap)); | ||
| 1157 | err = -EINTR; | ||
| 1158 | goto out; | ||
| 1159 | } | ||
| 1160 | if (bitmap == NULL) | ||
| 1161 | /* about to be stopped. */ | ||
| 1162 | return; | ||
| 1163 | |||
| 1164 | PRINTK("%s: bitmap writeback daemon woke up...\n", bmname(bitmap)); | 1125 | PRINTK("%s: bitmap writeback daemon woke up...\n", bmname(bitmap)); |
| 1165 | /* wait on bitmap page writebacks */ | 1126 | /* wait on bitmap page writebacks */ |
| 1166 | while ((item = dequeue_page(bitmap))) { | 1127 | while ((item = dequeue_page(bitmap))) { |
| @@ -1177,59 +1138,9 @@ static void bitmap_writeback_daemon(mddev_t *mddev) | |||
| 1177 | "failed (page %lu): %d\n", | 1138 | "failed (page %lu): %d\n", |
| 1178 | bmname(bitmap), page->index, err); | 1139 | bmname(bitmap), page->index, err); |
| 1179 | bitmap_file_kick(bitmap); | 1140 | bitmap_file_kick(bitmap); |
| 1180 | goto out; | 1141 | break; |
| 1181 | } | 1142 | } |
| 1182 | } | 1143 | } |
| 1183 | out: | ||
| 1184 | wake_up(&bitmap->write_wait); | ||
| 1185 | if (err) { | ||
| 1186 | printk(KERN_INFO "%s: bitmap writeback daemon exiting (%d)\n", | ||
| 1187 | bmname(bitmap), err); | ||
| 1188 | daemon_exit(bitmap, &bitmap->writeback_daemon); | ||
| 1189 | } | ||
| 1190 | } | ||
| 1191 | |||
| 1192 | static mdk_thread_t *bitmap_start_daemon(struct bitmap *bitmap, | ||
| 1193 | void (*func)(mddev_t *), char *name) | ||
| 1194 | { | ||
| 1195 | mdk_thread_t *daemon; | ||
| 1196 | char namebuf[32]; | ||
| 1197 | |||
| 1198 | #ifdef INJECT_FATAL_FAULT_2 | ||
| 1199 | daemon = NULL; | ||
| 1200 | #else | ||
| 1201 | sprintf(namebuf, "%%s_%s", name); | ||
| 1202 | daemon = md_register_thread(func, bitmap->mddev, namebuf); | ||
| 1203 | #endif | ||
| 1204 | if (!daemon) { | ||
| 1205 | printk(KERN_ERR "%s: failed to start bitmap daemon\n", | ||
| 1206 | bmname(bitmap)); | ||
| 1207 | return ERR_PTR(-ECHILD); | ||
| 1208 | } | ||
| 1209 | |||
| 1210 | md_wakeup_thread(daemon); /* start it running */ | ||
| 1211 | |||
| 1212 | PRINTK("%s: %s daemon (pid %d) started...\n", | ||
| 1213 | bmname(bitmap), name, daemon->tsk->pid); | ||
| 1214 | |||
| 1215 | return daemon; | ||
| 1216 | } | ||
| 1217 | |||
| 1218 | static void bitmap_stop_daemon(struct bitmap *bitmap) | ||
| 1219 | { | ||
| 1220 | /* the daemon can't stop itself... it'll just exit instead... */ | ||
| 1221 | if (bitmap->writeback_daemon && ! IS_ERR(bitmap->writeback_daemon) && | ||
| 1222 | current->pid != bitmap->writeback_daemon->tsk->pid) { | ||
| 1223 | mdk_thread_t *daemon; | ||
| 1224 | unsigned long flags; | ||
| 1225 | |||
| 1226 | spin_lock_irqsave(&bitmap->lock, flags); | ||
| 1227 | daemon = bitmap->writeback_daemon; | ||
| 1228 | bitmap->writeback_daemon = NULL; | ||
| 1229 | spin_unlock_irqrestore(&bitmap->lock, flags); | ||
| 1230 | if (daemon && ! IS_ERR(daemon)) | ||
| 1231 | md_unregister_thread(daemon); /* destroy the thread */ | ||
| 1232 | } | ||
| 1233 | } | 1144 | } |
| 1234 | 1145 | ||
| 1235 | static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap, | 1146 | static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap, |
| @@ -1553,7 +1464,6 @@ int bitmap_create(mddev_t *mddev) | |||
| 1553 | 1464 | ||
| 1554 | spin_lock_init(&bitmap->write_lock); | 1465 | spin_lock_init(&bitmap->write_lock); |
| 1555 | INIT_LIST_HEAD(&bitmap->complete_pages); | 1466 | INIT_LIST_HEAD(&bitmap->complete_pages); |
| 1556 | init_waitqueue_head(&bitmap->write_wait); | ||
| 1557 | bitmap->write_pool = mempool_create_kmalloc_pool(WRITE_POOL_SIZE, | 1467 | bitmap->write_pool = mempool_create_kmalloc_pool(WRITE_POOL_SIZE, |
| 1558 | sizeof(struct page_list)); | 1468 | sizeof(struct page_list)); |
| 1559 | err = -ENOMEM; | 1469 | err = -ENOMEM; |
| @@ -1613,15 +1523,6 @@ int bitmap_create(mddev_t *mddev) | |||
| 1613 | 1523 | ||
| 1614 | mddev->bitmap = bitmap; | 1524 | mddev->bitmap = bitmap; |
| 1615 | 1525 | ||
| 1616 | if (file) | ||
| 1617 | /* kick off the bitmap writeback daemon */ | ||
| 1618 | bitmap->writeback_daemon = | ||
| 1619 | bitmap_start_daemon(bitmap, | ||
| 1620 | bitmap_writeback_daemon, | ||
| 1621 | "bitmap_wb"); | ||
| 1622 | |||
| 1623 | if (IS_ERR(bitmap->writeback_daemon)) | ||
| 1624 | return PTR_ERR(bitmap->writeback_daemon); | ||
| 1625 | mddev->thread->timeout = bitmap->daemon_sleep * HZ; | 1526 | mddev->thread->timeout = bitmap->daemon_sleep * HZ; |
| 1626 | 1527 | ||
| 1627 | return bitmap_update_sb(bitmap); | 1528 | return bitmap_update_sb(bitmap); |
diff --git a/include/linux/raid/bitmap.h b/include/linux/raid/bitmap.h index 899437802ae..9c8907ca60a 100644 --- a/include/linux/raid/bitmap.h +++ b/include/linux/raid/bitmap.h | |||
| @@ -244,13 +244,7 @@ struct bitmap { | |||
| 244 | unsigned long daemon_lastrun; /* jiffies of last run */ | 244 | unsigned long daemon_lastrun; /* jiffies of last run */ |
| 245 | unsigned long daemon_sleep; /* how many seconds between updates? */ | 245 | unsigned long daemon_sleep; /* how many seconds between updates? */ |
| 246 | 246 | ||
| 247 | /* | ||
| 248 | * bitmap_writeback_daemon waits for file-pages that have been written, | ||
| 249 | * as there is no way to get a call-back when a page write completes. | ||
| 250 | */ | ||
| 251 | mdk_thread_t *writeback_daemon; | ||
| 252 | spinlock_t write_lock; | 247 | spinlock_t write_lock; |
| 253 | wait_queue_head_t write_wait; | ||
| 254 | struct list_head complete_pages; | 248 | struct list_head complete_pages; |
| 255 | mempool_t *write_pool; | 249 | mempool_t *write_pool; |
| 256 | }; | 250 | }; |
