[DRBD-cvs] svn commit by phil - r2105 - trunk/drbd - * Fixed an
SMP/preemption lockup. We need to take the d
drbd-cvs at lists.linbit.com
drbd-cvs at lists.linbit.com
Wed Mar 8 11:40:25 CET 2006
Author: phil
Date: 2006-03-08 11:40:24 +0100 (Wed, 08 Mar 2006)
New Revision: 2105
Modified:
trunk/drbd/drbd_receiver.c
trunk/drbd/drbd_worker.c
Log:
* Fixed an SMP/preemption lockup. We need to take the drbd_pp_lock IRQ
save in drbd_pp_alloc(), becuase we call drbd_pp_free() from IRQ
context later on.
* Fixed the counting of the epoch_size on the receiver, grumbl. Lars!
Modified: trunk/drbd/drbd_receiver.c
===================================================================
--- trunk/drbd/drbd_receiver.c 2006-03-07 13:26:14 UTC (rev 2104)
+++ trunk/drbd/drbd_receiver.c 2006-03-08 10:40:24 UTC (rev 2105)
@@ -125,6 +125,7 @@
*/
STATIC struct page * drbd_pp_alloc(drbd_dev *mdev, unsigned int gfp_mask)
{
+ unsigned long flags=0;
struct page *page;
DEFINE_WAIT(wait);
@@ -133,13 +134,14 @@
* not make sense.
*/
- /* first, use our pool. */
- spin_lock(&drbd_pp_lock);
+ spin_lock_irqsave(&drbd_pp_lock,flags);
+ /* This lock needs to be IRQ save because we might call drdb_pp_free()
+ from IRQ context. */
if ( (page = drbd_pp_pool) ) {
drbd_pp_pool = (struct page*)page->U_PRIVATE;
drbd_pp_vacant--;
}
- spin_unlock(&drbd_pp_lock);
+ spin_unlock_irqrestore(&drbd_pp_lock,flags);
if (page) goto got_page;
drbd_kick_lo(mdev);
@@ -148,12 +150,12 @@
prepare_to_wait(&drbd_pp_wait, &wait, TASK_INTERRUPTIBLE);
/* try the pool again, maybe the drbd_kick_log set some free */
- spin_lock(&drbd_pp_lock);
+ spin_lock_irqsave(&drbd_pp_lock,flags);
if ( (page = drbd_pp_pool) ) {
drbd_pp_pool = (struct page*)page->U_PRIVATE;
drbd_pp_vacant--;
}
- spin_unlock(&drbd_pp_lock);
+ spin_unlock_irqrestore(&drbd_pp_lock,flags);
if (page) break;
@@ -188,18 +190,24 @@
STATIC void drbd_pp_free(drbd_dev *mdev,struct page *page)
{
- spin_lock(&drbd_pp_lock);
+ unsigned long flags=0;
+ int free_it;
+
+ spin_lock_irqsave(&drbd_pp_lock,flags);
if (drbd_pp_vacant > (DRBD_MAX_SEGMENT_SIZE/PAGE_SIZE)*minor_count) {
- __free_page(page);
+ free_it = 1;
} else {
page->U_PRIVATE = (unsigned long)drbd_pp_pool;
drbd_pp_pool = page;
drbd_pp_vacant++;
+ free_it = 0;
}
- spin_unlock(&drbd_pp_lock);
+ spin_unlock_irqrestore(&drbd_pp_lock,flags);
atomic_dec(&mdev->pp_in_use);
+ if(free_it) __free_page(page);
+
/*
* FIXME
* typically there are no waiters.
Modified: trunk/drbd/drbd_worker.c
===================================================================
--- trunk/drbd/drbd_worker.c 2006-03-07 13:26:14 UTC (rev 2104)
+++ trunk/drbd/drbd_worker.c 2006-03-08 10:40:24 UTC (rev 2105)
@@ -102,6 +102,7 @@
struct Tl_epoch_entry *e=NULL;
struct Drbd_Conf* mdev;
int do_wake;
+ int is_syncer_req;
e = bio->bi_private;
mdev = e->mdev;
@@ -113,11 +114,13 @@
D_ASSERT(e->block_id != ID_VACANT);
spin_lock_irqsave(&mdev->ee_lock,flags);
- mdev->epoch_size++;
+ is_syncer_req = is_syncer_block_id(e->block_id);
list_del(&e->w.list);
list_add_tail(&e->w.list,&mdev->done_ee);
- do_wake = is_syncer_block_id(e->block_id)
+ if(!is_syncer_req) mdev->epoch_size++;
+
+ do_wake = is_syncer_req
? list_empty(&mdev->sync_ee)
: list_empty(&mdev->active_ee);
@@ -371,7 +374,7 @@
inc_rs_pending(mdev);
if(!drbd_send_drequest(mdev,RSDataRequest,
sector,size,ID_SYNCER)) {
- ERR("drbd_send_drequest() failed, aborting...");
+ ERR("drbd_send_drequest() failed, aborting...\n");
dec_rs_pending(mdev);
return 0; // FAILED. worker will abort!
}
More information about the drbd-cvs
mailing list