From: Chris Allen <chris@cjx.com>
To: Neil Brown <neilb@suse.de>
Cc: linux-raid@vger.kernel.org
Subject: Re: raid5 hang on get_active_stripe
Date: Tue, 14 Nov 2006 10:28:29 +0000 [thread overview]
Message-ID: <45599A4D.8090907@cjx.com> (raw)
In-Reply-To: <17706.58512.374925.103556@cse.unsw.edu.au>
You probably guessed that no matter what I did, I never, ever saw the
problem when your
trace was installed. I'd guess at some obscure timing-related problem. I
can still trigger it
consistently with a vanilla 2.6.17_SMP though, but again only when
bitmaps are turned on.
Neil Brown wrote:
> On Tuesday October 10, chris@cjx.com wrote:
>
>> Very happy to. Let me know what you'd like me to do.
>>
>
> Cool thanks.
>
> At the end is a patch against 2.6.17.11, though it should apply against
> any later 2.6.17 kernel.
> Apply this and reboot.
>
> Then run
>
> while true
> do cat /sys/block/mdX/md/stripe_cache_active
> sleep 10
> done > /dev/null
>
> (maybe write a little script or whatever). Leave this running. It
> effects the check for "has raid5 hung". Make sure to change "mdX" to
> whatever is appropriate.
>
> Occasionally look in the kernel logs for
> plug problem:
>
> if you find that, send me the surrounding text - there should be about
> a dozen lines following this one.
>
> Hopefully this will let me know which is last thing to happen: a plug
> or an unplug.
> If the last is a "plug", then the timer really should still be
> pending, but isn't (this is impossible). So I'll look more closely at
> that option.
> If the last is an "unplug", then the 'Plugged' flag should really be
> clear but it isn't (this is impossible). So I'll look more closely at
> that option.
>
> Dean is running this, but he only gets the hang every couple of
> weeks. If you get it more often, that would help me a lot.
>
> Thanks,
> NeilBrown
>
>
> diff ./.patches/orig/block/ll_rw_blk.c ./block/ll_rw_blk.c
> --- ./.patches/orig/block/ll_rw_blk.c 2006-08-21 09:52:46.000000000 +1000
> +++ ./block/ll_rw_blk.c 2006-10-05 11:33:32.000000000 +1000
> @@ -1546,6 +1546,7 @@ static int ll_merge_requests_fn(request_
> * This is called with interrupts off and no requests on the queue and
> * with the queue lock held.
> */
> +static atomic_t seq = ATOMIC_INIT(0);
> void blk_plug_device(request_queue_t *q)
> {
> WARN_ON(!irqs_disabled());
> @@ -1558,9 +1559,16 @@ void blk_plug_device(request_queue_t *q)
> return;
>
> if (!test_and_set_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags)) {
> + q->last_plug = jiffies;
> + q->plug_seq = atomic_read(&seq);
> + atomic_inc(&seq);
> mod_timer(&q->unplug_timer, jiffies + q->unplug_delay);
> blk_add_trace_generic(q, NULL, 0, BLK_TA_PLUG);
> - }
> + } else
> + q->last_plug_skip = jiffies;
> + if (!timer_pending(&q->unplug_timer) &&
> + !q->unplug_work.pending)
> + printk("Neither Timer or work are pending\n");
> }
>
> EXPORT_SYMBOL(blk_plug_device);
> @@ -1573,10 +1581,17 @@ int blk_remove_plug(request_queue_t *q)
> {
> WARN_ON(!irqs_disabled());
>
> - if (!test_and_clear_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags))
> + if (!test_and_clear_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags)) {
> + q->last_unplug_skip = jiffies;
> return 0;
> + }
>
> del_timer(&q->unplug_timer);
> + q->last_unplug = jiffies;
> + q->unplug_seq = atomic_read(&seq);
> + atomic_inc(&seq);
> + if (test_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags))
> + printk("queue still (or again) plugged\n");
> return 1;
> }
>
> @@ -1635,7 +1650,7 @@ static void blk_backing_dev_unplug(struc
> static void blk_unplug_work(void *data)
> {
> request_queue_t *q = data;
> -
> + q->last_unplug_work = jiffies;
> blk_add_trace_pdu_int(q, BLK_TA_UNPLUG_IO, NULL,
> q->rq.count[READ] + q->rq.count[WRITE]);
>
> @@ -1649,6 +1664,7 @@ static void blk_unplug_timeout(unsigned
> blk_add_trace_pdu_int(q, BLK_TA_UNPLUG_TIMER, NULL,
> q->rq.count[READ] + q->rq.count[WRITE]);
>
> + q->last_unplug_timeout = jiffies;
> kblockd_schedule_work(&q->unplug_work);
> }
>
>
> diff ./.patches/orig/drivers/md/raid1.c ./drivers/md/raid1.c
> --- ./.patches/orig/drivers/md/raid1.c 2006-08-10 17:28:01.000000000 +1000
> +++ ./drivers/md/raid1.c 2006-09-04 21:58:31.000000000 +1000
> @@ -1486,7 +1486,6 @@ static void raid1d(mddev_t *mddev)
> d = conf->raid_disks;
> d--;
> rdev = conf->mirrors[d].rdev;
> - atomic_add(s, &rdev->corrected_errors);
> if (rdev &&
> test_bit(In_sync, &rdev->flags)) {
> if (sync_page_io(rdev->bdev,
> @@ -1509,6 +1508,9 @@ static void raid1d(mddev_t *mddev)
> s<<9, conf->tmppage, READ) == 0)
> /* Well, this device is dead */
> md_error(mddev, rdev);
> + else
> + atomic_add(s, &rdev->corrected_errors);
> +
> }
> }
> } else {
>
> diff ./.patches/orig/drivers/md/raid5.c ./drivers/md/raid5.c
> --- ./.patches/orig/drivers/md/raid5.c 2006-08-10 17:28:01.000000000 +1000
> +++ ./drivers/md/raid5.c 2006-09-25 11:11:59.000000000 +1000
> @@ -93,6 +93,8 @@ static void __release_stripe(raid5_conf_
> md_wakeup_thread(conf->mddev->thread);
> }
> atomic_dec(&conf->active_stripes);
> + if (atomic_read(&conf->active_stripes) < conf->low_size)
> + conf->low_size = atomic_read(&conf->active_stripes);
> if (!test_bit(STRIPE_EXPANDING, &sh->state)) {
> list_add_tail(&sh->lru, &conf->inactive_list);
> wake_up(&conf->wait_for_stripe);
> @@ -1677,7 +1679,12 @@ static void raid5_unplug_device(request_
>
> spin_lock_irqsave(&conf->device_lock, flags);
>
> + if (conf->dotrace)
> + printk(" trace unplug_device\n");
> +
> if (blk_remove_plug(q)) {
> + if (conf->dotrace)
> + printk(" trace remove plug\n");
> conf->seq_flush++;
> raid5_activate_delayed(conf);
> }
> @@ -1721,6 +1728,8 @@ static int raid5_issue_flush(request_que
> static inline void raid5_plug_device(raid5_conf_t *conf)
> {
> spin_lock_irq(&conf->device_lock);
> + if (conf->dotrace)
> + printk(" trace plug device\n");
> blk_plug_device(conf->mddev->queue);
> spin_unlock_irq(&conf->device_lock);
> }
> @@ -2154,6 +2163,42 @@ static ssize_t
> stripe_cache_active_show(mddev_t *mddev, char *page)
> {
> raid5_conf_t *conf = mddev_to_conf(mddev);
> +
> + /* tracing */
> + if (conf->dotrace) {
> + conf->dotrace = 0;
> + printk("end trace, force unplug\n");
> + raid5_unplug_device(mddev->queue);
> + raid5_unplug_device(mddev->queue);
> + } else {
> + if (conf->last_size > conf->max_nr_stripes/2 &&
> + conf->last_size <= conf->low_size) {
> + conf->dotrace = 1;
> + printk("plug problem: low_size=%d\n", conf->low_size);
> + printk(" blk_queue_plugged = %d\n", blk_queue_plugged(mddev->queue));
> + printk(" flags = %lx\n", mddev->queue->queue_flags);
> + printk(" unplug_delay = %lu (HZ=%d)\n", mddev->queue->unplug_delay, HZ);
> + printk(" timer->expires %lu (jiffies %lu)\n",
> + mddev->queue->unplug_timer.expires, jiffies);
> + printk(" pending = %d\n", timer_pending(&mddev->queue->unplug_timer));
> + printk(" wq_pending = %lx\n", mddev->queue->unplug_work.pending);
> + printk(" wq_entry empty? %d\n", list_empty(&mddev->queue->unplug_work.entry));
> + printk(" unplug=%lu unplug_skip=%lu\n",
> + mddev->queue->last_unplug,
> + mddev->queue->last_unplug_skip);
> + printk(" plug=%lu plug_skip=%lu\n",
> + mddev->queue->last_plug,
> + mddev->queue->last_plug_skip);
> + printk(" unplug_work=%lu unplug_timeout=%lu\n",
> + mddev->queue->last_unplug_work,
> + mddev->queue->last_unplug_timeout);
> + printk(" unplug_seq=%lu plug_seq=%lu\n",
> + mddev->queue->unplug_seq,
> + mddev->queue->plug_seq);
> + }
> + conf->last_size = atomic_read(&conf->active_stripes);
> + conf->low_size = conf->last_size;
> + }
> if (conf)
> return sprintf(page, "%d\n", atomic_read(&conf->active_stripes));
> else
>
> diff ./.patches/orig/include/linux/blkdev.h ./include/linux/blkdev.h
> --- ./.patches/orig/include/linux/blkdev.h 2006-08-10 17:28:48.000000000 +1000
> +++ ./include/linux/blkdev.h 2006-09-25 11:08:27.000000000 +1000
> @@ -380,6 +380,9 @@ struct request_queue
> */
> unsigned long queue_flags;
>
> + unsigned long last_unplug, last_unplug_skip, last_plug, last_plug_skip;
> + unsigned long last_unplug_work, last_unplug_timeout;
> + unsigned long unplug_seq, plug_seq;
> /*
> * protects queue structures from reentrancy. ->__queue_lock should
> * _never_ be used directly, it is queue private. always use
>
> diff ./.patches/orig/include/linux/raid/raid5.h ./include/linux/raid/raid5.h
> --- ./.patches/orig/include/linux/raid/raid5.h 2006-08-10 17:28:53.000000000 +1000
> +++ ./include/linux/raid/raid5.h 2006-08-28 14:09:32.000000000 +1000
> @@ -245,6 +245,10 @@ struct raid5_private_data {
>
> struct page *spare_page; /* Used when checking P/Q in raid6 */
>
> + int dotrace;
> + int last_size;
> + int low_size;
> +
> /*
> * Free stripes pool
> */
>
next prev parent reply other threads:[~2006-11-14 10:28 UTC|newest]
Thread overview: 43+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-03-06 11:46 raid5 performance question Raz Ben-Jehuda(caro)
2006-03-06 11:59 ` Gordon Henderson
2006-03-06 12:56 ` Raz Ben-Jehuda(caro)
2006-03-13 22:36 ` raid5 hang on get_active_stripe Patrik Jonsson
2006-03-13 23:17 ` Neil Brown
2006-05-11 15:13 ` dean gaudet
2006-05-17 18:41 ` dean gaudet
2006-05-19 3:46 ` Neil Brown
2006-05-23 2:33 ` Neil Brown
2006-05-26 16:07 ` dean gaudet
2006-05-26 23:55 ` Neil Brown
2006-05-27 0:28 ` dean gaudet
2006-05-27 15:42 ` dean gaudet
2006-05-28 12:04 ` Neil Brown
2006-05-29 20:56 ` dean gaudet
2006-05-29 23:51 ` Neil Brown
2006-05-31 0:15 ` dean gaudet
2006-05-31 0:46 ` Neil Brown
2006-05-31 1:03 ` dean gaudet
2006-05-31 1:38 ` Neil Brown
2006-05-31 1:46 ` dean gaudet
2006-06-01 2:51 ` Neil Brown
2006-06-02 7:10 ` dean gaudet
2006-06-02 7:27 ` Neil Brown
2006-06-10 19:49 ` dean gaudet
2006-06-13 18:53 ` Bill Davidsen
2006-06-13 19:05 ` dean gaudet
2006-06-13 23:13 ` Neil Brown
2006-10-07 23:25 ` Chris Allen
2006-10-09 11:03 ` Chris Allen
2006-10-09 23:06 ` Neil Brown
2006-10-09 23:21 ` Chris Allen
2006-10-10 0:08 ` Neil Brown
2006-10-10 10:27 ` Bas van Schaik
2006-11-14 10:28 ` Chris Allen [this message]
2006-11-15 20:39 ` dean gaudet
2006-03-06 22:17 ` raid5 performance question Guy
2006-03-06 22:24 ` Neil Brown
2006-03-07 8:40 ` Raz Ben-Jehuda(caro)
2006-03-07 23:03 ` Neil Brown
2006-03-22 13:22 ` Bill Davidsen
2006-03-24 4:40 ` Neil Brown
2006-03-08 6:45 ` thunder7
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=45599A4D.8090907@cjx.com \
--to=chris@cjx.com \
--cc=linux-raid@vger.kernel.org \
--cc=neilb@suse.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.