aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorLars Ellenberg <lars.ellenberg@linbit.com>2010-09-06 06:30:25 -0400
committerPhilipp Reisner <philipp.reisner@linbit.com>2010-10-14 12:38:33 -0400
commit435f07402b3165b90592073bc0f8c6f8fa160ff9 (patch)
treecef4df9cde79857ad5590358c5f155c2f8bd84a2 /drivers/block
parent76d2e7eca8e7675c6d7a6592f9e747b121cc8a87 (diff)
drbd: don't count sendpage()d pages only referenced by tcp as in use
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com> Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/drbd/drbd_int.h8
-rw-r--r--drivers/block/drbd/drbd_main.c1
-rw-r--r--drivers/block/drbd/drbd_receiver.c26
-rw-r--r--drivers/block/drbd/drbd_worker.c4
4 files changed, 27 insertions, 12 deletions
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index 79b877db9a39..eb1273d04caf 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -1077,7 +1077,8 @@ struct drbd_conf {
1077 int next_barrier_nr; 1077 int next_barrier_nr;
1078 struct hlist_head *app_reads_hash; /* is proteced by req_lock */ 1078 struct hlist_head *app_reads_hash; /* is proteced by req_lock */
1079 struct list_head resync_reads; 1079 struct list_head resync_reads;
1080 atomic_t pp_in_use; 1080 atomic_t pp_in_use; /* allocated from page pool */
1081 atomic_t pp_in_use_by_net; /* sendpage()d, still referenced by tcp */
1081 wait_queue_head_t ee_wait; 1082 wait_queue_head_t ee_wait;
1082 struct page *md_io_page; /* one page buffer for md_io */ 1083 struct page *md_io_page; /* one page buffer for md_io */
1083 struct page *md_io_tmpp; /* for logical_block_size != 512 */ 1084 struct page *md_io_tmpp; /* for logical_block_size != 512 */
@@ -1555,7 +1556,10 @@ extern struct drbd_epoch_entry *drbd_alloc_ee(struct drbd_conf *mdev,
1555 sector_t sector, 1556 sector_t sector,
1556 unsigned int data_size, 1557 unsigned int data_size,
1557 gfp_t gfp_mask) __must_hold(local); 1558 gfp_t gfp_mask) __must_hold(local);
1558extern void drbd_free_ee(struct drbd_conf *mdev, struct drbd_epoch_entry *e); 1559extern void drbd_free_some_ee(struct drbd_conf *mdev, struct drbd_epoch_entry *e,
1560 int is_net);
1561#define drbd_free_ee(m,e) drbd_free_some_ee(m, e, 0)
1562#define drbd_free_net_ee(m,e) drbd_free_some_ee(m, e, 1)
1559extern void drbd_wait_ee_list_empty(struct drbd_conf *mdev, 1563extern void drbd_wait_ee_list_empty(struct drbd_conf *mdev,
1560 struct list_head *head); 1564 struct list_head *head);
1561extern void _drbd_wait_ee_list_empty(struct drbd_conf *mdev, 1565extern void _drbd_wait_ee_list_empty(struct drbd_conf *mdev,
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index 1827cf073c2e..981cfd178b09 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -2753,6 +2753,7 @@ void drbd_init_set_defaults(struct drbd_conf *mdev)
2753 atomic_set(&mdev->net_cnt, 0); 2753 atomic_set(&mdev->net_cnt, 0);
2754 atomic_set(&mdev->packet_seq, 0); 2754 atomic_set(&mdev->packet_seq, 0);
2755 atomic_set(&mdev->pp_in_use, 0); 2755 atomic_set(&mdev->pp_in_use, 0);
2756 atomic_set(&mdev->pp_in_use_by_net, 0);
2756 atomic_set(&mdev->rs_sect_in, 0); 2757 atomic_set(&mdev->rs_sect_in, 0);
2757 atomic_set(&mdev->rs_sect_ev, 0); 2758 atomic_set(&mdev->rs_sect_ev, 0);
2758 2759
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index e96fbb04ea4d..2c3edf0ac5ca 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -241,7 +241,7 @@ static void drbd_kick_lo_and_reclaim_net(struct drbd_conf *mdev)
241 spin_unlock_irq(&mdev->req_lock); 241 spin_unlock_irq(&mdev->req_lock);
242 242
243 list_for_each_entry_safe(e, t, &reclaimed, w.list) 243 list_for_each_entry_safe(e, t, &reclaimed, w.list)
244 drbd_free_ee(mdev, e); 244 drbd_free_net_ee(mdev, e);
245} 245}
246 246
247/** 247/**
@@ -298,9 +298,11 @@ static struct page *drbd_pp_alloc(struct drbd_conf *mdev, unsigned number, bool
298 * Is also used from inside an other spin_lock_irq(&mdev->req_lock); 298 * Is also used from inside an other spin_lock_irq(&mdev->req_lock);
299 * Either links the page chain back to the global pool, 299 * Either links the page chain back to the global pool,
300 * or returns all pages to the system. */ 300 * or returns all pages to the system. */
301static void drbd_pp_free(struct drbd_conf *mdev, struct page *page) 301static void drbd_pp_free(struct drbd_conf *mdev, struct page *page, int is_net)
302{ 302{
303 atomic_t *a = is_net ? &mdev->pp_in_use_by_net : &mdev->pp_in_use;
303 int i; 304 int i;
305
304 if (drbd_pp_vacant > (DRBD_MAX_SEGMENT_SIZE/PAGE_SIZE)*minor_count) 306 if (drbd_pp_vacant > (DRBD_MAX_SEGMENT_SIZE/PAGE_SIZE)*minor_count)
305 i = page_chain_free(page); 307 i = page_chain_free(page);
306 else { 308 else {
@@ -311,10 +313,10 @@ static void drbd_pp_free(struct drbd_conf *mdev, struct page *page)
311 drbd_pp_vacant += i; 313 drbd_pp_vacant += i;
312 spin_unlock(&drbd_pp_lock); 314 spin_unlock(&drbd_pp_lock);
313 } 315 }
314 atomic_sub(i, &mdev->pp_in_use); 316 i = atomic_sub_return(i, a);
315 i = atomic_read(&mdev->pp_in_use);
316 if (i < 0) 317 if (i < 0)
317 dev_warn(DEV, "ASSERTION FAILED: pp_in_use: %d < 0\n", i); 318 dev_warn(DEV, "ASSERTION FAILED: %s: %d < 0\n",
319 is_net ? "pp_in_use_by_net" : "pp_in_use", i);
318 wake_up(&drbd_pp_wait); 320 wake_up(&drbd_pp_wait);
319} 321}
320 322
@@ -374,11 +376,11 @@ struct drbd_epoch_entry *drbd_alloc_ee(struct drbd_conf *mdev,
374 return NULL; 376 return NULL;
375} 377}
376 378
377void drbd_free_ee(struct drbd_conf *mdev, struct drbd_epoch_entry *e) 379void drbd_free_some_ee(struct drbd_conf *mdev, struct drbd_epoch_entry *e, int is_net)
378{ 380{
379 if (e->flags & EE_HAS_DIGEST) 381 if (e->flags & EE_HAS_DIGEST)
380 kfree(e->digest); 382 kfree(e->digest);
381 drbd_pp_free(mdev, e->pages); 383 drbd_pp_free(mdev, e->pages, is_net);
382 D_ASSERT(atomic_read(&e->pending_bios) == 0); 384 D_ASSERT(atomic_read(&e->pending_bios) == 0);
383 D_ASSERT(hlist_unhashed(&e->colision)); 385 D_ASSERT(hlist_unhashed(&e->colision));
384 mempool_free(e, drbd_ee_mempool); 386 mempool_free(e, drbd_ee_mempool);
@@ -389,13 +391,14 @@ int drbd_release_ee(struct drbd_conf *mdev, struct list_head *list)
389 LIST_HEAD(work_list); 391 LIST_HEAD(work_list);
390 struct drbd_epoch_entry *e, *t; 392 struct drbd_epoch_entry *e, *t;
391 int count = 0; 393 int count = 0;
394 int is_net = list == &mdev->net_ee;
392 395
393 spin_lock_irq(&mdev->req_lock); 396 spin_lock_irq(&mdev->req_lock);
394 list_splice_init(list, &work_list); 397 list_splice_init(list, &work_list);
395 spin_unlock_irq(&mdev->req_lock); 398 spin_unlock_irq(&mdev->req_lock);
396 399
397 list_for_each_entry_safe(e, t, &work_list, w.list) { 400 list_for_each_entry_safe(e, t, &work_list, w.list) {
398 drbd_free_ee(mdev, e); 401 drbd_free_some_ee(mdev, e, is_net);
399 count++; 402 count++;
400 } 403 }
401 return count; 404 return count;
@@ -424,7 +427,7 @@ static int drbd_process_done_ee(struct drbd_conf *mdev)
424 spin_unlock_irq(&mdev->req_lock); 427 spin_unlock_irq(&mdev->req_lock);
425 428
426 list_for_each_entry_safe(e, t, &reclaimed, w.list) 429 list_for_each_entry_safe(e, t, &reclaimed, w.list)
427 drbd_free_ee(mdev, e); 430 drbd_free_net_ee(mdev, e);
428 431
429 /* possible callbacks here: 432 /* possible callbacks here:
430 * e_end_block, and e_end_resync_block, e_send_discard_ack. 433 * e_end_block, and e_end_resync_block, e_send_discard_ack.
@@ -1460,7 +1463,7 @@ static int drbd_drain_block(struct drbd_conf *mdev, int data_size)
1460 data_size -= rr; 1463 data_size -= rr;
1461 } 1464 }
1462 kunmap(page); 1465 kunmap(page);
1463 drbd_pp_free(mdev, page); 1466 drbd_pp_free(mdev, page, 0);
1464 return rv; 1467 return rv;
1465} 1468}
1466 1469
@@ -3879,6 +3882,9 @@ static void drbd_disconnect(struct drbd_conf *mdev)
3879 i = drbd_release_ee(mdev, &mdev->net_ee); 3882 i = drbd_release_ee(mdev, &mdev->net_ee);
3880 if (i) 3883 if (i)
3881 dev_info(DEV, "net_ee not empty, killed %u entries\n", i); 3884 dev_info(DEV, "net_ee not empty, killed %u entries\n", i);
3885 i = atomic_read(&mdev->pp_in_use_by_net);
3886 if (i)
3887 dev_info(DEV, "pp_in_use_by_net = %d, expected 0\n", i);
3882 i = atomic_read(&mdev->pp_in_use); 3888 i = atomic_read(&mdev->pp_in_use);
3883 if (i) 3889 if (i)
3884 dev_info(DEV, "pp_in_use = %d, expected 0\n", i); 3890 dev_info(DEV, "pp_in_use = %d, expected 0\n", i);
diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c
index 0e5bf8c98293..01743193f321 100644
--- a/drivers/block/drbd/drbd_worker.c
+++ b/drivers/block/drbd/drbd_worker.c
@@ -914,9 +914,13 @@ static void move_to_net_ee_or_free(struct drbd_conf *mdev, struct drbd_epoch_ent
914{ 914{
915 if (drbd_ee_has_active_page(e)) { 915 if (drbd_ee_has_active_page(e)) {
916 /* This might happen if sendpage() has not finished */ 916 /* This might happen if sendpage() has not finished */
917 int i = DIV_ROUND_UP(e->size, PAGE_SIZE);
918 atomic_add(i, &mdev->pp_in_use_by_net);
919 atomic_sub(i, &mdev->pp_in_use);
917 spin_lock_irq(&mdev->req_lock); 920 spin_lock_irq(&mdev->req_lock);
918 list_add_tail(&e->w.list, &mdev->net_ee); 921 list_add_tail(&e->w.list, &mdev->net_ee);
919 spin_unlock_irq(&mdev->req_lock); 922 spin_unlock_irq(&mdev->req_lock);
923 wake_up(&drbd_pp_wait);
920 } else 924 } else
921 drbd_free_ee(mdev, e); 925 drbd_free_ee(mdev, e);
922} 926}