[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <AANLkTin3wXWwA-HXhjx6wvzznp3p57Pg6fee8YNkZB79@mail.gmail.com>
Date: Tue, 19 Oct 2010 10:43:31 +0200
From: Torsten Kaiser <just.for.lkml@...glemail.com>
To: Neil Brown <neilb@...e.de>
Cc: Wu Fengguang <fengguang.wu@...el.com>,
Rik van Riel <riel@...hat.com>,
Andrew Morton <akpm@...ux-foundation.org>,
KOSAKI Motohiro <kosaki.motohiro@...fujitsu.com>,
KAMEZAWA Hiroyuki <kamezawa.hiroyu@...fujitsu.com>,
"linux-kernel@...r.kernel.org" <linux-kernel@...r.kernel.org>,
"linux-mm@...ck.org" <linux-mm@...ck.org>,
Li Shaohua <shaohua.li@...el.com>
Subject: Re: Deadlock possibly caused by too_many_isolated.
On Tue, Oct 19, 2010 at 1:11 AM, Neil Brown <neilb@...e.de> wrote:
> On Mon, 18 Oct 2010 12:58:17 +0200
> Torsten Kaiser <just.for.lkml@...glemail.com> wrote:
>
>> On Mon, Oct 18, 2010 at 6:14 AM, Neil Brown <neilb@...e.de> wrote:
>> > Testing shows that this patch seems to work.
>> > The test load (essentially kernbench) doesn't deadlock any more, though it
>> > does get bogged down thrashing in swap so it doesn't make a lot more
>> > progress :-) I guess that is to be expected.
>>
>> I just noticed this thread, as your mail from today pushed it up.
>>
>> In your original mail you wrote: " I recently had a customer (running
>> 2.6.32) report a deadlock during very intensive IO with lots of
>> processes. " and " Some threads that are blocked there, hold some IO
>> lock (probably in the filesystem) and are trying to allocate memory
>> inside the block device (md/raid1 to be precise) which is allocating
>> with GFP_NOIO and has a mempool to fall back on."
>>
>> I recently had the same problem (intense IO due to swapstorm created
>> by 20 gcc processes hung my system) and after initially blaming the
>> workqueue changes in 2.6.36 Tejun Heo determined that my problem was
>> not the workqueues getting locked up, but that it was cause by an
>> exhausted mempool:
>> http://marc.info/?l=linux-kernel&m=128655737012549&w=2
>>
>> Instrumenting mm/mempool.c and retrying my workload showed that
>> fs_bio_set from fs/bio.c looked like the mempool to blame and the code
>> in drivers/md/raid1.c to be the misuser:
>> http://marc.info/?l=linux-kernel&m=128671179817823&w=2
>>
>> I was even able to reproduce this hang with only using a normal RAID1
>> md device as swapspace and then using dd to fill a tmpfs until
>> swapping was needed:
>> http://marc.info/?l=linux-raid&m=128699402805191&w=2
>>
>> Looking back in the history of raid1.c and bio.c I found the following
>> interesting parts:
>>
>> * the change to allocate more then one bio via bio_clone() is from
>> 2005, but it looks like it was OK back then, because at that point the
>> fs_bio_set was allocation 256 entries
>> * in 2007 the size of the mempool was changed from 256 to only 2
>> entries (5972511b77809cb7c9ccdb79b825c54921c5c546 "A single unit is
>> enough, lets scale it down to 2 just to be on the safe side.")
>> * only in 2009 the comment "To make this work, callers must never
>> allocate more than 1 bio at the time from this pool. Callers that need
>> to allocate more than 1 bio must always submit the previously allocate
>> bio for IO before attempting to allocate a new one. Failure to do so
>> can cause livelocks under memory pressure." was added to bio_alloc()
>> that is the base from my reasoning that raid1.c is broken. (And such a
>> comment was not added to bio_clone() although both calls use the same
>> mempool)
>>
>> So could please look someone into raid1.c to confirm or deny that
>> using multiple bio_clone() (one per drive) before submitting them
>> together could also cause such deadlocks?
>>
>> Thank for looking
>>
>> Torsten
>
> Yes, thanks for the report.
> This is a real bug exactly as you describe.
>
> This is how I think I will fix it, though it needs a bit of review and
> testing before I can be certain.
> Also I need to check raid10 etc to see if they can suffer too.
>
> If you can test it I would really appreciate it.
I did test it, but while it seemed to fix the deadlock, the system
still got unusable.
The still running "vmstat 1" showed that the swapout was still
progressing, but at a rate of ~20k sized bursts every 5 to 20 seconds.
I also tried to additionally add Wu's patch:
--- linux-next.orig/mm/vmscan.c 2010-10-13 12:35:14.000000000 +0800
+++ linux-next/mm/vmscan.c 2010-10-19 00:13:04.000000000 +0800
@@ -1163,6 +1163,13 @@ static int too_many_isolated(struct zone
isolated = zone_page_state(zone, NR_ISOLATED_ANON);
}
+ /*
+ * GFP_NOIO/GFP_NOFS callers are allowed to isolate more pages, so that
+ * they won't get blocked by normal ones and form circular deadlock.
+ */
+ if ((sc->gfp_mask & GFP_IOFS) == GFP_IOFS)
+ inactive >>= 3;
+
return isolated > inactive;
Either it did help somewhat, or I was more lucky on my second try, but
this time I needed ~5 tries instead of only 2 to get the system mostly
stuck again. On the testrun with Wu's patch the writeout pattern was
more stable, a burst of ~80kb each 20 seconds. But I would suspect
that the size of the burst is rather random.
I do have a complete SysRq+T dump from the first run, I can send that
to anyone how wants it.
(It's 190k so I don't want not spam it to the list)
Torsten
> diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
> index d44a50f..8122dde 100644
> --- a/drivers/md/raid1.c
> +++ b/drivers/md/raid1.c
> @@ -784,7 +784,6 @@ static int make_request(mddev_t *mddev, struct bio * bio)
> int i, targets = 0, disks;
> struct bitmap *bitmap;
> unsigned long flags;
> - struct bio_list bl;
> struct page **behind_pages = NULL;
> const int rw = bio_data_dir(bio);
> const unsigned long do_sync = (bio->bi_rw & REQ_SYNC);
> @@ -892,13 +891,6 @@ static int make_request(mddev_t *mddev, struct bio * bio)
> * bios[x] to bio
> */
> disks = conf->raid_disks;
> -#if 0
> - { static int first=1;
> - if (first) printk("First Write sector %llu disks %d\n",
> - (unsigned long long)r1_bio->sector, disks);
> - first = 0;
> - }
> -#endif
> retry_write:
> blocked_rdev = NULL;
> rcu_read_lock();
> @@ -956,14 +948,15 @@ static int make_request(mddev_t *mddev, struct bio * bio)
> (behind_pages = alloc_behind_pages(bio)) != NULL)
> set_bit(R1BIO_BehindIO, &r1_bio->state);
>
> - atomic_set(&r1_bio->remaining, 0);
> + atomic_set(&r1_bio->remaining, targets);
> atomic_set(&r1_bio->behind_remaining, 0);
>
> do_barriers = bio->bi_rw & REQ_HARDBARRIER;
> if (do_barriers)
> set_bit(R1BIO_Barrier, &r1_bio->state);
>
> - bio_list_init(&bl);
> + bitmap_startwrite(bitmap, bio->bi_sector, r1_bio->sectors,
> + test_bit(R1BIO_BehindIO, &r1_bio->state));
> for (i = 0; i < disks; i++) {
> struct bio *mbio;
> if (!r1_bio->bios[i])
> @@ -995,30 +988,18 @@ static int make_request(mddev_t *mddev, struct bio * bio)
> atomic_inc(&r1_bio->behind_remaining);
> }
>
> - atomic_inc(&r1_bio->remaining);
> -
> - bio_list_add(&bl, mbio);
> + spin_lock_irqsave(&conf->device_lock, flags);
> + bio_list_add(&conf->pending_bio_list, mbio);
> + blk_plug_device(mddev->queue);
> + spin_unlock_irqrestore(&conf->device_lock, flags);
> }
> kfree(behind_pages); /* the behind pages are attached to the bios now */
>
> - bitmap_startwrite(bitmap, bio->bi_sector, r1_bio->sectors,
> - test_bit(R1BIO_BehindIO, &r1_bio->state));
> - spin_lock_irqsave(&conf->device_lock, flags);
> - bio_list_merge(&conf->pending_bio_list, &bl);
> - bio_list_init(&bl);
> -
> - blk_plug_device(mddev->queue);
> - spin_unlock_irqrestore(&conf->device_lock, flags);
> -
> /* In case raid1d snuck into freeze_array */
> wake_up(&conf->wait_barrier);
>
> if (do_sync)
> md_wakeup_thread(mddev->thread);
> -#if 0
> - while ((bio = bio_list_pop(&bl)) != NULL)
> - generic_make_request(bio);
> -#endif
>
> return 0;
> }
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@...r.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
>
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists