* Re: Help needed recovering from raid failure
From: NeilBrown @ 2015-04-28 22:26 UTC (permalink / raw)
To: Peter van Es; +Cc: linux-raid
In-Reply-To: <4D8713B5-39E7-4EE2-898C-35DC0948B4CA@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 4049 bytes --]
On Mon, 27 Apr 2015 11:35:09 +0200 Peter van Es <vanes.peter@gmail.com> wrote:
> Sorry for the long post...
>
> I am running Ubuntu LTS 14.04.02 Server edition, 64 bits, with 4x 2.0TB drives in a raid-5 array.
>
> The 4th drive was beginning to show read errors. Because it was weekend, I could not go out
> and buy a spare 2TB drive to replace the one that was beginning to fail.
>
> I first got a fail event:
>
> This is an automatically generated mail message from mdadm
> running on bali
>
> A Fail event had been detected on md device /dev/md/1.
>
> It could be related to component device /dev/sdd2.
>
> Faithfully yours, etc.
>
> P.S. The /proc/mdstat file currently contains the following:
>
> Personalities : [linear] [multipath] [raid0] [raid1] [raid6] [raid5] [raid4] [raid10]
> md1 : active raid5 sdc2[2] sdb2[1] sda2[0] sdd2[3](F)
> 5854290432 blocks super 1.2 level 5, 512k chunk, algorithm 2 [4/3] [UUU_]
>
> md0 : active raid5 sdc1[2] sdd1[3] sdb1[1] sda1[0]
> 5850624 blocks super 1.2 level 5, 512k chunk, algorithm 2 [4/4] [UUUU]
>
> unused devices: <none>
>
> And then subsequently, around 18 hours later:
>
> This is an automatically generated mail message from mdadm
> running on bali
>
> A DegradedArray event had been detected on md device /dev/md/1.
This isn't really reporting anything new.
There is probably a daily cron job which reports all degraded arrays. This
message is reported by that job.
>
> Faithfully yours, etc.
>
> P.S. The /proc/mdstat file currently contains the following:
>
> Personalities : [linear] [multipath] [raid0] [raid1] [raid6] [raid5] [raid4] [raid10]
> md1 : active raid5 sdc2[2] sdb2[1] sda2[0] sdd2[3](F)
> 5854290432 blocks super 1.2 level 5, 512k chunk, algorithm 2 [4/3] [UUU_]
>
> md0 : active raid5 sdc1[2] sdd1[3] sdb1[1] sda1[0]
> 5850624 blocks super 1.2 level 5, 512k chunk, algorithm 2 [4/4] [UUUU]
>
> unused devices: <none>
>
> The server had taken the array off line at that point.
Why do you think the array is off-line? The above message doesn't suggest
that.
>
> Needless to say, I can't boot the system anymore as the boot drive is /dev/md0, and GRUB can't
> get at it. I do need to recover data (I know, but there's stuf on there I have no backup for--yet).
You boot off a RAID5? Does grub support that? I didn't know.
But md0 hasn't failed, has it?
Confused.
>
> I booted Linux from a USB stick (which is on /dev/sdc1 hence changing the numbering),
> in recovery mode. Below is the output of /proc/mdstat and
> mdadm --examine. It looks like somehow the /dev/sdd2 and /dev/sde2 drives took on the
> super block of the /dev/md127 device (my swap file). May that have been done by the boot from
> the Ubuntu USB stick?
There is something VERY sick here. I suggest that you tread very carefully.
All your '1' partitions should be about 2GB and the '2' parititions about 2TB
But the --examine output suggests sda2 and sdb2 are 2TB, while sdd2 and sde2
are 2GB.
That really really shouldn't happen. Maybe check your partition table
(fdisk).
I really cannot see how this would happen.
>
> My plan... assemble a degraded array, with /dev/sde2 (the 4th drive, formerly known as /dev/sdd2) not in it.
> Because the fail event put the file system in RO mode, I expect /dev/sdd2 (formerly /dev/sdc2) to be ok.
> Then insert new 2TB drive in slot 4. Let system resync and recover.
>
> I'm running xfs on the /dev/md1 device.
>
> Questions:
>
> 1. is this the wise course of action ?
> 2. how exactly do I reassemble the array (/etc/mdadm.conf is inaccessible in recovery mode)
> 3. what command line options do I use exactly from the --examine output below without screwing things up
>
> And help or pointers gratefully accepted
Can you
mdadm -Ss
to stop all the arrays, then
fdisk -l /dev/sd?
then
mdadm -Esvv
and post all of that. Hopefully some of it will make sense.
NeilBrown
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 811 bytes --]
^ permalink raw reply
* Re: [PATCH 07/10] block: kill merge_bvec_fn() completely
From: NeilBrown @ 2015-04-28 22:09 UTC (permalink / raw)
To: Ming Lin
Cc: linux-kernel, Christoph Hellwig, Jens Axboe, Kent Overstreet,
Dongsu Park, Lars Ellenberg, drbd-user, Jiri Kosina, Yehuda Sadeh,
Sage Weil, Alex Elder, ceph-devel, Alasdair Kergon, Mike Snitzer,
dm-devel, linux-raid, Christoph Hellwig, Martin K. Petersen
In-Reply-To: <1430203717-13307-8-git-send-email-mlin@kernel.org>
[-- Attachment #1: Type: text/plain, Size: 723 bytes --]
On Mon, 27 Apr 2015 23:48:34 -0700 Ming Lin <mlin@kernel.org> wrote:
> From: Kent Overstreet <kent.overstreet@gmail.com>
>
> As generic_make_request() is now able to handle arbitrarily sized bios,
> it's no longer necessary for each individual block driver to define its
> own ->merge_bvec_fn() callback. Remove every invocation completely.
This patch it just a little premature I think.
md/raid5 still assumes read requests will mostly fit within a single chunk
(which merge_bvec_fn encourages) so they can be serviced without using the
stripe-cache.
You've just broken that assumption.
I think 'chunk_aligned_read' needs to get a loop using bio_split, a bit like
raid0, first.
Thanks,
NeilBrown
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 811 bytes --]
^ permalink raw reply
* Re: Massive RAID-1 desync
From: NeilBrown @ 2015-04-28 21:39 UTC (permalink / raw)
To: Jean-Baptiste Thomas; +Cc: linux-raid
In-Reply-To: <824955940.20886272.1430038117467.JavaMail.zimbra@laposte.net>
[-- Attachment #1: Type: text/plain, Size: 1708 bytes --]
On Sun, 26 Apr 2015 10:48:37 +0200 (CEST) Jean-Baptiste Thomas
<cau2jeaf1honoq@laposte.net> wrote:
> On 2015-04-25 17:25 +1000, NeilBrown wrote:
>
> > Perfectly normal. Metadata is at the end, at least 64K from the end
> > and 64K aligned.
>
> Yes. Format 0.90.
>
> > And what were those messages about sda?
>
> The actual messages have been displaced by lockd's rambling but as I
> remember, it was this sort of thing :
>
> ata1.00: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x0
> ata1.00: BMDMA stat 0x4
> ata1.00: failed command: READ DMA EXT
> ata1.00: cmd 25/00:80:a9:54:70/00:00:74:00:00/e0 tag 0 dma 65536 in
> res 51/40:00:25:55:70/40:00:74:00:00/e0 Emask 0x9 (media error)
> ata1.00: status: { DRDY ERR }
> ata1.00: error: { UNC }
> ata1.00: configured for UDMA/133
> ata1: EH complete
A clean "media error" on READ should involve the block being written and if
that fails, the drive ejected. I wonder if the controller got confused.
>
> I ran e2fsck on copies of sda1 and sdc1. They are both heavily damaged,
> not just sdc1.
That is rather sad. I'm having trouble imagining any scenario that would
result in the symptoms you are seeing. Very odd.
>
> Looks like I'm going to have to replace a disk and see. I'd like to
> avoid replacing two, though. Or going through more crashes. Does
> MD have a paranoid mode in which reading a sector from a RAID-1
> device would not return successfully until it got matching data
> from at least two components ?
As mentioned separately: no.
If it were me, I'd probably be feeling suspicious of the controller at this
point. If it is a cheap one, maybe replace it.
NeilBrown
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 811 bytes --]
^ permalink raw reply
* Re: [PATCH -stable] block: destroy bdi before blockdev is unregistered.
From: NeilBrown @ 2015-04-28 21:25 UTC (permalink / raw)
To: Mike Snitzer
Cc: Jens Axboe, Azat Khuzhin, Christoph Hellwig,
Kernel.org-Linux-RAID, Guoqing Jiang, Tejun Heo, Jan Kara, lkml,
device-mapper development
In-Reply-To: <CAMM=eLf2aFFH29xeDVrS7beFj6T8kqUQRh=4KB1YO0kWGa7Rog@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 8089 bytes --]
On Tue, 28 Apr 2015 12:41:18 -0400 Mike Snitzer <snitzer@redhat.com> wrote:
> On Mon, Apr 27, 2015 at 12:12 AM, NeilBrown <neilb@suse.de> wrote:
> >
> > Because of the peculiar way that md devices are created (automatically
> > when the device node is opened), a new device can be created and
> > registered immediately after the
> > blk_unregister_region(disk_devt(disk), disk->minors);
> > call in del_gendisk().
> >
> > Therefore it is important that all visible artifacts of the previous
> > device are removed before this call. In particular, the 'bdi'.
> >
> > Since:
> > commit c4db59d31e39ea067c32163ac961e9c80198fd37
> > Author: Christoph Hellwig <hch@lst.de>
> > fs: don't reassign dirty inodes to default_backing_dev_info
> >
> > moved the
> > device_unregister(bdi->dev);
> > call from bdi_unregister() to bdi_destroy() it has been quite easy to
> > lose a race and have a new (e.g.) "md127" be created after the
> > blk_unregister_region() call and before bdi_destroy() is ultimately
> > called by the final 'put_disk', which must come after del_gendisk().
> >
> > The new device finds that the bdi name is already registered in sysfs
> > and complains
> >
> >> [ 9627.630029] WARNING: CPU: 18 PID: 3330 at fs/sysfs/dir.c:31 sysfs_warn_dup+0x5a/0x70()
> >> [ 9627.630032] sysfs: cannot create duplicate filename '/devices/virtual/bdi/9:127'
> >
> > We can fix this by moving the bdi_destroy() call out of
> > blk_release_queue() (which can happen very late when a refcount
> > reaches zero) and into blk_cleanup_queue() - which happens exactly when the md
> > device driver calls it.
> >
> > Then it is only necessary for md to call blk_cleanup_queue() before
> > del_gendisk(). As loop.c devices are also created on demand by
> > opening the device node, we make the same change there.
> >
> > Fixes: c4db59d31e39ea067c32163ac961e9c80198fd37
> > Reported-by: Azat Khuzhin <a3at.mail@gmail.com>
> > Cc: Christoph Hellwig <hch@lst.de>
> > Cc: stable@vger.kernel.org (v4.0)
> > Signed-off-by: NeilBrown <neilb@suse.de>
> >
> > --
> > Hi Jens,
> > if you could check this and forward on to Linus I'd really appreciate it.
> >
> > Thanks,
> > NeilBrown
> >
> >
> > diff --git a/block/blk-core.c b/block/blk-core.c
> > index fd154b94447a..7871603f0a29 100644
> > --- a/block/blk-core.c
> > +++ b/block/blk-core.c
> > @@ -552,6 +552,8 @@ void blk_cleanup_queue(struct request_queue *q)
> > q->queue_lock = &q->__queue_lock;
> > spin_unlock_irq(lock);
> >
> > + bdi_destroy(&q->backing_dev_info);
> > +
> > /* @q is and will stay empty, shutdown and put */
> > blk_put_queue(q);
> > }
> > diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
> > index faaf36ade7eb..2b8fd302f677 100644
> > --- a/block/blk-sysfs.c
> > +++ b/block/blk-sysfs.c
> > @@ -522,8 +522,6 @@ static void blk_release_queue(struct kobject *kobj)
> >
> > blk_trace_shutdown(q);
> >
> > - bdi_destroy(&q->backing_dev_info);
> > -
> > ida_simple_remove(&blk_queue_ida, q->id);
> > call_rcu(&q->rcu_head, blk_free_queue_rcu);
> > }
> > diff --git a/drivers/block/loop.c b/drivers/block/loop.c
> > index ae3fcb4199e9..d7173cb1ea76 100644
> > --- a/drivers/block/loop.c
> > +++ b/drivers/block/loop.c
> > @@ -1620,8 +1620,8 @@ out:
> >
> > static void loop_remove(struct loop_device *lo)
> > {
> > - del_gendisk(lo->lo_disk);
> > blk_cleanup_queue(lo->lo_queue);
> > + del_gendisk(lo->lo_disk);
> > blk_mq_free_tag_set(&lo->tag_set);
> > put_disk(lo->lo_disk);
> > kfree(lo);
> > diff --git a/drivers/md/md.c b/drivers/md/md.c
> > index d4f31e195e26..593a02476c78 100644
> > --- a/drivers/md/md.c
> > +++ b/drivers/md/md.c
> > @@ -4818,12 +4818,12 @@ static void md_free(struct kobject *ko)
> > if (mddev->sysfs_state)
> > sysfs_put(mddev->sysfs_state);
> >
> > + if (mddev->queue)
> > + blk_cleanup_queue(mddev->queue);
> > if (mddev->gendisk) {
> > del_gendisk(mddev->gendisk);
> > put_disk(mddev->gendisk);
> > }
> > - if (mddev->queue)
> > - blk_cleanup_queue(mddev->queue);
> >
> > kfree(mddev);
> > }
>
> I've taken this patch into consideration relative to DM, please see:
> http://git.kernel.org/cgit/linux/kernel/git/snitzer/linux.git/commit/?h=wip&id=5dac86fb79697e93297edb6a316b429236d00137
>
> Point is in my private snitzer/wip branch DM now calls
> blk_cleanup_queue() before del_gendisk().
>
> With your patch:
> 1) blk_cleanup_queue -> bdi_destroy -> bdi->dev = NULL;
> 2) del_gendisk -> bdi_unregister -> WARN_ON_ONCE(!bdi->dev)
>
> So, in testing with DM I'm hitting bdi_unregister's WARN_ON(), are you
> seeing this WARN_ON?
Hmmm. Yes I am. I wonder how I missed that. Thanks!
As bdi_set_min_ratio doesn't touch bdi->dev, there seems to be no need for
the test, or the warning.
I wonder if it would make sense to move the bdi_set_min_ratio() call to
bdi_destroy, and discard bdi_unregister??
There is a comment which suggests bdi_unregister might be of use later, but
it might be best to have a clean slate in which to add whatever might be
needed??
NeilBrown
diff --git a/block/genhd.c b/block/genhd.c
index e351fc521053..1d4435478e8a 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -657,7 +657,6 @@ void del_gendisk(struct gendisk *disk)
disk->flags &= ~GENHD_FL_UP;
sysfs_remove_link(&disk_to_dev(disk)->kobj, "bdi");
- bdi_unregister(&disk->queue->backing_dev_info);
blk_unregister_queue(disk);
blk_unregister_region(disk_devt(disk), disk->minors);
diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h
index aff923ae8c4b..d87d8eced064 100644
--- a/include/linux/backing-dev.h
+++ b/include/linux/backing-dev.h
@@ -116,7 +116,6 @@ __printf(3, 4)
int bdi_register(struct backing_dev_info *bdi, struct device *parent,
const char *fmt, ...);
int bdi_register_dev(struct backing_dev_info *bdi, dev_t dev);
-void bdi_unregister(struct backing_dev_info *bdi);
int __must_check bdi_setup_and_register(struct backing_dev_info *, char *);
void bdi_start_writeback(struct backing_dev_info *bdi, long nr_pages,
enum wb_reason reason);
diff --git a/include/trace/events/writeback.h b/include/trace/events/writeback.h
index 880dd7437172..c178d13d6f4c 100644
--- a/include/trace/events/writeback.h
+++ b/include/trace/events/writeback.h
@@ -250,7 +250,6 @@ DEFINE_EVENT(writeback_class, name, \
DEFINE_WRITEBACK_EVENT(writeback_nowork);
DEFINE_WRITEBACK_EVENT(writeback_wake_background);
DEFINE_WRITEBACK_EVENT(writeback_bdi_register);
-DEFINE_WRITEBACK_EVENT(writeback_bdi_unregister);
DECLARE_EVENT_CLASS(wbc_class,
TP_PROTO(struct writeback_control *wbc, struct backing_dev_info *bdi),
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index 6dc4580df2af..000e7b3b9896 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -359,23 +359,6 @@ static void bdi_wb_shutdown(struct backing_dev_info *bdi)
flush_delayed_work(&bdi->wb.dwork);
}
-/*
- * Called when the device behind @bdi has been removed or ejected.
- *
- * We can't really do much here except for reducing the dirty ratio at
- * the moment. In the future we should be able to set a flag so that
- * the filesystem can handle errors at mark_inode_dirty time instead
- * of only at writeback time.
- */
-void bdi_unregister(struct backing_dev_info *bdi)
-{
- if (WARN_ON_ONCE(!bdi->dev))
- return;
-
- bdi_set_min_ratio(bdi, 0);
-}
-EXPORT_SYMBOL(bdi_unregister);
-
static void bdi_wb_init(struct bdi_writeback *wb, struct backing_dev_info *bdi)
{
memset(wb, 0, sizeof(*wb));
@@ -443,6 +426,7 @@ void bdi_destroy(struct backing_dev_info *bdi)
int i;
bdi_wb_shutdown(bdi);
+ bdi_set_min_ratio(bdi, 0);
WARN_ON(!list_empty(&bdi->work_list));
WARN_ON(delayed_work_pending(&bdi->wb.dwork));
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 811 bytes --]
^ permalink raw reply related
* Re: [PATCH 07/10] block: kill merge_bvec_fn() completely
From: Alasdair G Kergon @ 2015-04-28 17:31 UTC (permalink / raw)
To: Ming Lin
Cc: linux-kernel, Christoph Hellwig, Jens Axboe, Kent Overstreet,
Dongsu Park, Lars Ellenberg, drbd-user, Jiri Kosina, Yehuda Sadeh,
Sage Weil, Alex Elder, ceph-devel, Alasdair Kergon, Mike Snitzer,
dm-devel, Neil Brown, linux-raid, Christoph Hellwig,
Martin K. Petersen, Dave Chinner
In-Reply-To: <1430203717-13307-8-git-send-email-mlin@kernel.org>
On Mon, Apr 27, 2015 at 11:48:34PM -0700, Ming Lin wrote:
> As generic_make_request() is now able to handle arbitrarily sized bios,
> it's no longer necessary for each individual block driver to define its
> own ->merge_bvec_fn() callback. Remove every invocation completely.
merge_bvec_fn is also about telling the code building up bios what optimum
maximum size to use.
Have you got some test data to demonstrate that we won't find some situations
where performance is now lost by code building up bios that are far too big
and are always going to have to be split up later?
Alasdair
^ permalink raw reply
* Re: [PATCH -stable] block: destroy bdi before blockdev is unregistered.
From: Mike Snitzer @ 2015-04-28 16:41 UTC (permalink / raw)
To: NeilBrown
Cc: Jens Axboe, Azat Khuzhin, Christoph Hellwig,
Kernel.org-Linux-RAID, Guoqing Jiang, Tejun Heo, Jan Kara, lkml,
device-mapper development
In-Reply-To: <20150427141222.5dac22f1@notabene.brown>
On Mon, Apr 27, 2015 at 12:12 AM, NeilBrown <neilb@suse.de> wrote:
>
> Because of the peculiar way that md devices are created (automatically
> when the device node is opened), a new device can be created and
> registered immediately after the
> blk_unregister_region(disk_devt(disk), disk->minors);
> call in del_gendisk().
>
> Therefore it is important that all visible artifacts of the previous
> device are removed before this call. In particular, the 'bdi'.
>
> Since:
> commit c4db59d31e39ea067c32163ac961e9c80198fd37
> Author: Christoph Hellwig <hch@lst.de>
> fs: don't reassign dirty inodes to default_backing_dev_info
>
> moved the
> device_unregister(bdi->dev);
> call from bdi_unregister() to bdi_destroy() it has been quite easy to
> lose a race and have a new (e.g.) "md127" be created after the
> blk_unregister_region() call and before bdi_destroy() is ultimately
> called by the final 'put_disk', which must come after del_gendisk().
>
> The new device finds that the bdi name is already registered in sysfs
> and complains
>
>> [ 9627.630029] WARNING: CPU: 18 PID: 3330 at fs/sysfs/dir.c:31 sysfs_warn_dup+0x5a/0x70()
>> [ 9627.630032] sysfs: cannot create duplicate filename '/devices/virtual/bdi/9:127'
>
> We can fix this by moving the bdi_destroy() call out of
> blk_release_queue() (which can happen very late when a refcount
> reaches zero) and into blk_cleanup_queue() - which happens exactly when the md
> device driver calls it.
>
> Then it is only necessary for md to call blk_cleanup_queue() before
> del_gendisk(). As loop.c devices are also created on demand by
> opening the device node, we make the same change there.
>
> Fixes: c4db59d31e39ea067c32163ac961e9c80198fd37
> Reported-by: Azat Khuzhin <a3at.mail@gmail.com>
> Cc: Christoph Hellwig <hch@lst.de>
> Cc: stable@vger.kernel.org (v4.0)
> Signed-off-by: NeilBrown <neilb@suse.de>
>
> --
> Hi Jens,
> if you could check this and forward on to Linus I'd really appreciate it.
>
> Thanks,
> NeilBrown
>
>
> diff --git a/block/blk-core.c b/block/blk-core.c
> index fd154b94447a..7871603f0a29 100644
> --- a/block/blk-core.c
> +++ b/block/blk-core.c
> @@ -552,6 +552,8 @@ void blk_cleanup_queue(struct request_queue *q)
> q->queue_lock = &q->__queue_lock;
> spin_unlock_irq(lock);
>
> + bdi_destroy(&q->backing_dev_info);
> +
> /* @q is and will stay empty, shutdown and put */
> blk_put_queue(q);
> }
> diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
> index faaf36ade7eb..2b8fd302f677 100644
> --- a/block/blk-sysfs.c
> +++ b/block/blk-sysfs.c
> @@ -522,8 +522,6 @@ static void blk_release_queue(struct kobject *kobj)
>
> blk_trace_shutdown(q);
>
> - bdi_destroy(&q->backing_dev_info);
> -
> ida_simple_remove(&blk_queue_ida, q->id);
> call_rcu(&q->rcu_head, blk_free_queue_rcu);
> }
> diff --git a/drivers/block/loop.c b/drivers/block/loop.c
> index ae3fcb4199e9..d7173cb1ea76 100644
> --- a/drivers/block/loop.c
> +++ b/drivers/block/loop.c
> @@ -1620,8 +1620,8 @@ out:
>
> static void loop_remove(struct loop_device *lo)
> {
> - del_gendisk(lo->lo_disk);
> blk_cleanup_queue(lo->lo_queue);
> + del_gendisk(lo->lo_disk);
> blk_mq_free_tag_set(&lo->tag_set);
> put_disk(lo->lo_disk);
> kfree(lo);
> diff --git a/drivers/md/md.c b/drivers/md/md.c
> index d4f31e195e26..593a02476c78 100644
> --- a/drivers/md/md.c
> +++ b/drivers/md/md.c
> @@ -4818,12 +4818,12 @@ static void md_free(struct kobject *ko)
> if (mddev->sysfs_state)
> sysfs_put(mddev->sysfs_state);
>
> + if (mddev->queue)
> + blk_cleanup_queue(mddev->queue);
> if (mddev->gendisk) {
> del_gendisk(mddev->gendisk);
> put_disk(mddev->gendisk);
> }
> - if (mddev->queue)
> - blk_cleanup_queue(mddev->queue);
>
> kfree(mddev);
> }
I've taken this patch into consideration relative to DM, please see:
http://git.kernel.org/cgit/linux/kernel/git/snitzer/linux.git/commit/?h=wip&id=5dac86fb79697e93297edb6a316b429236d00137
Point is in my private snitzer/wip branch DM now calls
blk_cleanup_queue() before del_gendisk().
With your patch:
1) blk_cleanup_queue -> bdi_destroy -> bdi->dev = NULL;
2) del_gendisk -> bdi_unregister -> WARN_ON_ONCE(!bdi->dev)
So, in testing with DM I'm hitting bdi_unregister's WARN_ON(), are you
seeing this WARN_ON?
[ 385.134474] WARNING: CPU: 3 PID: 11231 at mm/backing-dev.c:372
bdi_unregister+0x36/0x40()
[ 385.143593] Modules linked in: dm_service_time dm_multipath
target_core_iblock tcm_loop target_core_mod sg iscsi_tcp libiscsi_tcp
libiscsi scsi_transport_iscsi core
temp kvm_intel kvm ixgbe igb crct10dif_pclmul crc32_pclmul
crc32c_intel ghash_clmulni_intel mdio aesni_intel ptp pps_core
glue_helper ipmi_si i7core_edac iTCO_wdt lrw
dca iTCO_vendor_support edac_core i2c_i801 pcspkr gf128mul
ipmi_msghandler acpi_power_meter shpchp lpc_ich ablk_helper cryptd
mfd_core acpi_cpufreq xfs libcrc32c sr_mo
d cdrom mgag200 syscopyarea sysfillrect sysimgblt i2c_algo_bit
drm_kms_helper ata_generic ttm pata_acpi sd_mod ata_piix drm
iomemory_vsl(POE) libata megaraid_sas i2c_c
ore skd dm_mirror dm_region_hash dm_log dm_mod
[ 385.213736] CPU: 3 PID: 11231 Comm: dmsetup Tainted: P IOE
4.1.0-rc1.snitm+ #55
[ 385.222958] Hardware name: FUJITSU
PRIMERGY RX300 S6 /D2619, BIOS 6.00 Rev. 1.10.2619.N1
05/24/2011
[ 385.237602] 0000000000000000 000000006cf7a5f2 ffff88031bfcfb68
ffffffff8167b7e6
[ 385.245897] 0000000000000000 0000000000000000 ffff88031bfcfba8
ffffffff8107bd5a
[ 385.254193] 0000000000000000 ffff88032c4b6c00 0000000000000000
0000000000000000
[ 385.262488] Call Trace:
[ 385.265218] [<ffffffff8167b7e6>] dump_stack+0x45/0x57
[ 385.270955] [<ffffffff8107bd5a>] warn_slowpath_common+0x8a/0xc0
[ 385.277660] [<ffffffff8107be8a>] warn_slowpath_null+0x1a/0x20
[ 385.284171] [<ffffffff8119e216>] bdi_unregister+0x36/0x40
[ 385.290295] [<ffffffff812fb8c1>] del_gendisk+0x131/0x2b0
[ 385.296326] [<ffffffffa0000eba>] cleanup_mapped_device+0xda/0x130 [dm_mod]
[ 385.304101] [<ffffffffa000283b>] __dm_destroy+0x19b/0x260 [dm_mod]
[ 385.311099] [<ffffffffa00040c3>] dm_destroy+0x13/0x20 [dm_mod]
[ 385.317709] [<ffffffffa0009d0e>] dev_remove+0x11e/0x180 [dm_mod]
[ 385.324516] [<ffffffffa0009bf0>] ? dev_suspend+0x250/0x250 [dm_mod]
[ 385.331614] [<ffffffffa000a3e5>] ctl_ioctl+0x255/0x500 [dm_mod]
[ 385.338319] [<ffffffff8128c8d8>] ? SYSC_semtimedop+0x298/0xea0
[ 385.344931] [<ffffffffa000a6a3>] dm_ctl_ioctl+0x13/0x20 [dm_mod]
[ 385.351733] [<ffffffff8120d038>] do_vfs_ioctl+0x2f8/0x4f0
[ 385.357857] [<ffffffff811207e4>] ? __audit_syscall_entry+0xb4/0x110
[ 385.364950] [<ffffffff8102367c>] ? do_audit_syscall_entry+0x6c/0x70
[ 385.372041] [<ffffffff8120d2b1>] SyS_ioctl+0x81/0xa0
[ 385.377679] [<ffffffff81025046>] ? syscall_trace_leave+0xc6/0x120
[ 385.384578] [<ffffffff81682f2e>] system_call_fastpath+0x12/0x71
[ 385.391282] ---[ end trace af60d8ac7157d319 ]---
^ permalink raw reply
* Re: [PATCH 1/3] wait: introduce wait_event_cmd_exclusive
From: Peter Zijlstra @ 2015-04-28 14:13 UTC (permalink / raw)
To: Yuanhan Liu; +Cc: neilb, linux-raid, linux-kernel, Ingo Molnar
In-Reply-To: <1430110263-23977-1-git-send-email-yuanhan.liu@linux.intel.com>
On Mon, Apr 27, 2015 at 12:51:01PM +0800, Yuanhan Liu wrote:
> It's just a variant of wait_event_cmd, with exclusive flag being set.
>
> For cases like RAID5, which puts many processes to sleep until 1/4
> resources are free, a wake_up wakes up all processes to run, but
> there is one process being able to get the resource as it's protected
> by a spin lock. That ends up introducing heavy lock contentions, and
> hurts performance badly.
>
> Here introduce wait_event_cmd_exclusive to relieve the lock contention
> naturally by letting wake_up() just wake up one process.
>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: Peter Zijlstra <peterz@infradead.org>
> Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
> ---
> include/linux/wait.h | 14 +++++++++++---
> 1 file changed, 11 insertions(+), 3 deletions(-)
>
> diff --git a/include/linux/wait.h b/include/linux/wait.h
> index 2db8334..6c3b4de 100644
> --- a/include/linux/wait.h
> +++ b/include/linux/wait.h
> @@ -358,10 +358,18 @@ do { \
> __ret; \
> })
>
> -#define __wait_event_cmd(wq, condition, cmd1, cmd2) \
> - (void)___wait_event(wq, condition, TASK_UNINTERRUPTIBLE, 0, 0, \
> +#define __wait_event_cmd(wq, condition, cmd1, cmd2, exclusive) \
> + (void)___wait_event(wq, condition, TASK_UNINTERRUPTIBLE, exclusive, 0, \
> cmd1; schedule(); cmd2)
>
> +
> +#define wait_event_cmd_exclusive(wq, condition, cmd1, cmd2) \
> +do { \
> + if (condition) \
> + break; \
> + __wait_event_cmd(wq, condition, cmd1, cmd2, 1); \
> +} while (0)
> +
> /**
> * wait_event_cmd - sleep until a condition gets true
> * @wq: the waitqueue to wait on
> @@ -380,7 +388,7 @@ do { \
> do { \
> if (condition) \
> break; \
> - __wait_event_cmd(wq, condition, cmd1, cmd2); \
> + __wait_event_cmd(wq, condition, cmd1, cmd2, 0); \
> } while (0)
>
No, that's wrong, its assumed that wait*() and __wait*() have the same
arguments.
^ permalink raw reply
* [PATCH 09/10] md/raid10: make sync_request_write() call bio_copy_data()
From: Ming Lin @ 2015-04-28 6:48 UTC (permalink / raw)
To: linux-kernel
Cc: Christoph Hellwig, Jens Axboe, Kent Overstreet, Dongsu Park,
Ming Lin, Christoph Hellwig, Neil Brown, linux-raid
In-Reply-To: <1430203717-13307-1-git-send-email-mlin@kernel.org>
From: Kent Overstreet <kent.overstreet@gmail.com>
Refactor sync_request_write() of md/raid10 to use bio_copy_data()
instead of open coding bio_vec iterations.
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Neil Brown <neilb@suse.de>
Cc: linux-raid@vger.kernel.org
Reviewed-by: Christoph Hellwig <hch@lst.de>
Acked-by: NeilBrown <neilb@suse.de>
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
[dpark: add more description in commit message]
Signed-off-by: Dongsu Park <dongsu.park@profitbricks.com>
Signed-off-by: Ming Lin <mlin@kernel.org>
---
drivers/md/raid10.c | 18 ++++--------------
1 file changed, 4 insertions(+), 14 deletions(-)
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index a46c402..6ea6f5f 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -1989,17 +1989,10 @@ static void sync_request_write(struct mddev *mddev, struct r10bio *r10_bio)
tbio->bi_rw = WRITE;
tbio->bi_private = r10_bio;
tbio->bi_iter.bi_sector = r10_bio->devs[i].addr;
-
- for (j=0; j < vcnt ; j++) {
- tbio->bi_io_vec[j].bv_offset = 0;
- tbio->bi_io_vec[j].bv_len = PAGE_SIZE;
-
- memcpy(page_address(tbio->bi_io_vec[j].bv_page),
- page_address(fbio->bi_io_vec[j].bv_page),
- PAGE_SIZE);
- }
tbio->bi_end_io = end_sync_write;
+ bio_copy_data(tbio, fbio);
+
d = r10_bio->devs[i].devnum;
atomic_inc(&conf->mirrors[d].rdev->nr_pending);
atomic_inc(&r10_bio->remaining);
@@ -2014,17 +2007,14 @@ static void sync_request_write(struct mddev *mddev, struct r10bio *r10_bio)
* that are active
*/
for (i = 0; i < conf->copies; i++) {
- int j, d;
+ int d;
tbio = r10_bio->devs[i].repl_bio;
if (!tbio || !tbio->bi_end_io)
continue;
if (r10_bio->devs[i].bio->bi_end_io != end_sync_write
&& r10_bio->devs[i].bio != fbio)
- for (j = 0; j < vcnt; j++)
- memcpy(page_address(tbio->bi_io_vec[j].bv_page),
- page_address(fbio->bi_io_vec[j].bv_page),
- PAGE_SIZE);
+ bio_copy_data(tbio, fbio);
d = r10_bio->devs[i].devnum;
atomic_inc(&r10_bio->remaining);
md_sync_acct(conf->mirrors[d].replacement->bdev,
--
1.9.1
^ permalink raw reply related
* [PATCH 07/10] block: kill merge_bvec_fn() completely
From: Ming Lin @ 2015-04-28 6:48 UTC (permalink / raw)
To: linux-kernel
Cc: Christoph Hellwig, Jens Axboe, Kent Overstreet, Dongsu Park,
Ming Lin, Lars Ellenberg, drbd-user, Jiri Kosina, Yehuda Sadeh,
Sage Weil, Alex Elder, ceph-devel, Alasdair Kergon, Mike Snitzer,
dm-devel, Neil Brown, linux-raid, Christoph Hellwig,
Martin K. Petersen
In-Reply-To: <1430203717-13307-1-git-send-email-mlin@kernel.org>
From: Kent Overstreet <kent.overstreet@gmail.com>
As generic_make_request() is now able to handle arbitrarily sized bios,
it's no longer necessary for each individual block driver to define its
own ->merge_bvec_fn() callback. Remove every invocation completely.
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Lars Ellenberg <drbd-dev@lists.linbit.com>
Cc: drbd-user@lists.linbit.com
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Yehuda Sadeh <yehuda@inktank.com>
Cc: Sage Weil <sage@inktank.com>
Cc: Alex Elder <elder@kernel.org>
Cc: ceph-devel@vger.kernel.org
Cc: Alasdair Kergon <agk@redhat.com>
Cc: Mike Snitzer <snitzer@redhat.com>
Cc: dm-devel@redhat.com
Cc: Neil Brown <neilb@suse.de>
Cc: linux-raid@vger.kernel.org
Cc: Christoph Hellwig <hch@infradead.org>
Cc: "Martin K. Petersen" <martin.petersen@oracle.com>
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
[dpark: also remove ->merge_bvec_fn() in dm-thin as well as
dm-era-target, and resolve merge conflicts]
Signed-off-by: Dongsu Park <dongsu.park@profitbricks.com>
Signed-off-by: Ming Lin <mlin@kernel.org>
---
block/blk-merge.c | 17 +-----
block/blk-settings.c | 22 --------
drivers/block/drbd/drbd_int.h | 1 -
drivers/block/drbd/drbd_main.c | 1 -
drivers/block/drbd/drbd_req.c | 35 ------------
drivers/block/pktcdvd.c | 21 -------
drivers/block/rbd.c | 47 ----------------
drivers/md/dm-cache-target.c | 21 -------
drivers/md/dm-crypt.c | 16 ------
drivers/md/dm-era-target.c | 15 -----
drivers/md/dm-flakey.c | 16 ------
drivers/md/dm-linear.c | 16 ------
drivers/md/dm-log-writes.c | 16 ------
drivers/md/dm-snap.c | 15 -----
drivers/md/dm-stripe.c | 21 -------
drivers/md/dm-table.c | 8 ---
drivers/md/dm-thin.c | 31 -----------
drivers/md/dm-verity.c | 16 ------
drivers/md/dm.c | 120 +---------------------------------------
drivers/md/dm.h | 2 -
drivers/md/linear.c | 43 ---------------
drivers/md/md.c | 26 ---------
drivers/md/md.h | 12 ----
drivers/md/multipath.c | 21 -------
drivers/md/raid0.c | 56 -------------------
drivers/md/raid0.h | 2 -
drivers/md/raid1.c | 58 +-------------------
drivers/md/raid10.c | 121 +----------------------------------------
drivers/md/raid5.c | 32 -----------
include/linux/blkdev.h | 10 ----
include/linux/device-mapper.h | 4 --
31 files changed, 9 insertions(+), 833 deletions(-)
diff --git a/block/blk-merge.c b/block/blk-merge.c
index 322f495..9d565a0 100644
--- a/block/blk-merge.c
+++ b/block/blk-merge.c
@@ -69,24 +69,13 @@ static struct bio *blk_bio_segment_split(struct request_queue *q,
struct bio *split;
struct bio_vec bv = { 0 }, bvprv = { 0 };
struct bvec_iter iter;
- unsigned seg_size = 0, nsegs = 0;
+ unsigned seg_size = 0, nsegs = 0, sectors = 0;
int prev = 0;
- struct bvec_merge_data bvm = {
- .bi_bdev = bio->bi_bdev,
- .bi_sector = bio->bi_iter.bi_sector,
- .bi_size = 0,
- .bi_rw = bio->bi_rw,
- };
-
bio_for_each_segment(bv, bio, iter) {
- if (q->merge_bvec_fn &&
- q->merge_bvec_fn(q, &bvm, &bv) < (int) bv.bv_len)
- goto split;
-
- bvm.bi_size += bv.bv_len;
+ sectors += bv.bv_len >> 9;
- if (bvm.bi_size >> 9 > queue_max_sectors(q))
+ if (sectors > queue_max_sectors(q))
goto split;
if (prev && blk_queue_cluster(q)) {
diff --git a/block/blk-settings.c b/block/blk-settings.c
index 12600bf..e90d477 100644
--- a/block/blk-settings.c
+++ b/block/blk-settings.c
@@ -53,28 +53,6 @@ void blk_queue_unprep_rq(struct request_queue *q, unprep_rq_fn *ufn)
}
EXPORT_SYMBOL(blk_queue_unprep_rq);
-/**
- * blk_queue_merge_bvec - set a merge_bvec function for queue
- * @q: queue
- * @mbfn: merge_bvec_fn
- *
- * Usually queues have static limitations on the max sectors or segments that
- * we can put in a request. Stacking drivers may have some settings that
- * are dynamic, and thus we have to query the queue whether it is ok to
- * add a new bio_vec to a bio at a given offset or not. If the block device
- * has such limitations, it needs to register a merge_bvec_fn to control
- * the size of bio's sent to it. Note that a block device *must* allow a
- * single page to be added to an empty bio. The block device driver may want
- * to use the bio_split() function to deal with these bio's. By default
- * no merge_bvec_fn is defined for a queue, and only the fixed limits are
- * honored.
- */
-void blk_queue_merge_bvec(struct request_queue *q, merge_bvec_fn *mbfn)
-{
- q->merge_bvec_fn = mbfn;
-}
-EXPORT_SYMBOL(blk_queue_merge_bvec);
-
void blk_queue_softirq_done(struct request_queue *q, softirq_done_fn *fn)
{
q->softirq_done_fn = fn;
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index b905e98..63ce2b0 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -1449,7 +1449,6 @@ extern void do_submit(struct work_struct *ws);
extern void __drbd_make_request(struct drbd_device *, struct bio *, unsigned long);
extern void drbd_make_request(struct request_queue *q, struct bio *bio);
extern int drbd_read_remote(struct drbd_device *device, struct drbd_request *req);
-extern int drbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bvm, struct bio_vec *bvec);
extern int is_valid_ar_handle(struct drbd_request *, sector_t);
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index 81fde9e..771e68c 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -2774,7 +2774,6 @@ enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsig
This triggers a max_bio_size message upon first attach or connect */
blk_queue_max_hw_sectors(q, DRBD_MAX_BIO_SIZE_SAFE >> 8);
blk_queue_bounce_limit(q, BLK_BOUNCE_ANY);
- blk_queue_merge_bvec(q, drbd_merge_bvec);
q->queue_lock = &resource->req_lock;
device->md_io.page = alloc_page(GFP_KERNEL);
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
index a6265bc..7523f00 100644
--- a/drivers/block/drbd/drbd_req.c
+++ b/drivers/block/drbd/drbd_req.c
@@ -1510,41 +1510,6 @@ void drbd_make_request(struct request_queue *q, struct bio *bio)
__drbd_make_request(device, bio, start_jif);
}
-/* This is called by bio_add_page().
- *
- * q->max_hw_sectors and other global limits are already enforced there.
- *
- * We need to call down to our lower level device,
- * in case it has special restrictions.
- *
- * We also may need to enforce configured max-bio-bvecs limits.
- *
- * As long as the BIO is empty we have to allow at least one bvec,
- * regardless of size and offset, so no need to ask lower levels.
- */
-int drbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bvm, struct bio_vec *bvec)
-{
- struct drbd_device *device = (struct drbd_device *) q->queuedata;
- unsigned int bio_size = bvm->bi_size;
- int limit = DRBD_MAX_BIO_SIZE;
- int backing_limit;
-
- if (bio_size && get_ldev(device)) {
- unsigned int max_hw_sectors = queue_max_hw_sectors(q);
- struct request_queue * const b =
- device->ldev->backing_bdev->bd_disk->queue;
- if (b->merge_bvec_fn) {
- bvm->bi_bdev = device->ldev->backing_bdev;
- backing_limit = b->merge_bvec_fn(b, bvm, bvec);
- limit = min(limit, backing_limit);
- }
- put_ldev(device);
- if ((limit >> 9) > max_hw_sectors)
- limit = max_hw_sectors << 9;
- }
- return limit;
-}
-
void request_timer_fn(unsigned long data)
{
struct drbd_device *device = (struct drbd_device *) data;
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index ea10bd9..85eac23 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -2505,26 +2505,6 @@ end_io:
-static int pkt_merge_bvec(struct request_queue *q, struct bvec_merge_data *bmd,
- struct bio_vec *bvec)
-{
- struct pktcdvd_device *pd = q->queuedata;
- sector_t zone = get_zone(bmd->bi_sector, pd);
- int used = ((bmd->bi_sector - zone) << 9) + bmd->bi_size;
- int remaining = (pd->settings.size << 9) - used;
- int remaining2;
-
- /*
- * A bio <= PAGE_SIZE must be allowed. If it crosses a packet
- * boundary, pkt_make_request() will split the bio.
- */
- remaining2 = PAGE_SIZE - bmd->bi_size;
- remaining = max(remaining, remaining2);
-
- BUG_ON(remaining < 0);
- return remaining;
-}
-
static void pkt_init_queue(struct pktcdvd_device *pd)
{
struct request_queue *q = pd->disk->queue;
@@ -2532,7 +2512,6 @@ static void pkt_init_queue(struct pktcdvd_device *pd)
blk_queue_make_request(q, pkt_make_request);
blk_queue_logical_block_size(q, CD_FRAMESIZE);
blk_queue_max_hw_sectors(q, PACKET_MAX_SECTORS);
- blk_queue_merge_bvec(q, pkt_merge_bvec);
q->queuedata = pd;
}
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 8125233..b1cb499 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -3435,52 +3435,6 @@ static int rbd_queue_rq(struct blk_mq_hw_ctx *hctx,
return BLK_MQ_RQ_QUEUE_OK;
}
-/*
- * a queue callback. Makes sure that we don't create a bio that spans across
- * multiple osd objects. One exception would be with a single page bios,
- * which we handle later at bio_chain_clone_range()
- */
-static int rbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bmd,
- struct bio_vec *bvec)
-{
- struct rbd_device *rbd_dev = q->queuedata;
- sector_t sector_offset;
- sector_t sectors_per_obj;
- sector_t obj_sector_offset;
- int ret;
-
- /*
- * Find how far into its rbd object the partition-relative
- * bio start sector is to offset relative to the enclosing
- * device.
- */
- sector_offset = get_start_sect(bmd->bi_bdev) + bmd->bi_sector;
- sectors_per_obj = 1 << (rbd_dev->header.obj_order - SECTOR_SHIFT);
- obj_sector_offset = sector_offset & (sectors_per_obj - 1);
-
- /*
- * Compute the number of bytes from that offset to the end
- * of the object. Account for what's already used by the bio.
- */
- ret = (int) (sectors_per_obj - obj_sector_offset) << SECTOR_SHIFT;
- if (ret > bmd->bi_size)
- ret -= bmd->bi_size;
- else
- ret = 0;
-
- /*
- * Don't send back more than was asked for. And if the bio
- * was empty, let the whole thing through because: "Note
- * that a block device *must* allow a single page to be
- * added to an empty bio."
- */
- rbd_assert(bvec->bv_len <= PAGE_SIZE);
- if (ret > (int) bvec->bv_len || !bmd->bi_size)
- ret = (int) bvec->bv_len;
-
- return ret;
-}
-
static void rbd_free_disk(struct rbd_device *rbd_dev)
{
struct gendisk *disk = rbd_dev->disk;
@@ -3779,7 +3733,6 @@ static int rbd_init_disk(struct rbd_device *rbd_dev)
q->limits.max_discard_sectors = segment_size / SECTOR_SIZE;
q->limits.discard_zeroes_data = 1;
- blk_queue_merge_bvec(q, rbd_merge_bvec);
disk->queue = q;
q->queuedata = rbd_dev;
diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c
index 7755af3..2e47e35 100644
--- a/drivers/md/dm-cache-target.c
+++ b/drivers/md/dm-cache-target.c
@@ -3289,26 +3289,6 @@ static int cache_iterate_devices(struct dm_target *ti,
return r;
}
-/*
- * We assume I/O is going to the origin (which is the volume
- * more likely to have restrictions e.g. by being striped).
- * (Looking up the exact location of the data would be expensive
- * and could always be out of date by the time the bio is submitted.)
- */
-static int cache_bvec_merge(struct dm_target *ti,
- struct bvec_merge_data *bvm,
- struct bio_vec *biovec, int max_size)
-{
- struct cache *cache = ti->private;
- struct request_queue *q = bdev_get_queue(cache->origin_dev->bdev);
-
- if (!q->merge_bvec_fn)
- return max_size;
-
- bvm->bi_bdev = cache->origin_dev->bdev;
- return min(max_size, q->merge_bvec_fn(q, bvm, biovec));
-}
-
static void set_discard_limits(struct cache *cache, struct queue_limits *limits)
{
/*
@@ -3352,7 +3332,6 @@ static struct target_type cache_target = {
.status = cache_status,
.message = cache_message,
.iterate_devices = cache_iterate_devices,
- .merge = cache_bvec_merge,
.io_hints = cache_io_hints,
};
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 9eeea19..1c53beb 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -2017,21 +2017,6 @@ error:
return -EINVAL;
}
-static int crypt_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
- struct bio_vec *biovec, int max_size)
-{
- struct crypt_config *cc = ti->private;
- struct request_queue *q = bdev_get_queue(cc->dev->bdev);
-
- if (!q->merge_bvec_fn)
- return max_size;
-
- bvm->bi_bdev = cc->dev->bdev;
- bvm->bi_sector = cc->start + dm_target_offset(ti, bvm->bi_sector);
-
- return min(max_size, q->merge_bvec_fn(q, bvm, biovec));
-}
-
static int crypt_iterate_devices(struct dm_target *ti,
iterate_devices_callout_fn fn, void *data)
{
@@ -2052,7 +2037,6 @@ static struct target_type crypt_target = {
.preresume = crypt_preresume,
.resume = crypt_resume,
.message = crypt_message,
- .merge = crypt_merge,
.iterate_devices = crypt_iterate_devices,
};
diff --git a/drivers/md/dm-era-target.c b/drivers/md/dm-era-target.c
index ad913cd..0119ebf 100644
--- a/drivers/md/dm-era-target.c
+++ b/drivers/md/dm-era-target.c
@@ -1673,20 +1673,6 @@ static int era_iterate_devices(struct dm_target *ti,
return fn(ti, era->origin_dev, 0, get_dev_size(era->origin_dev), data);
}
-static int era_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
- struct bio_vec *biovec, int max_size)
-{
- struct era *era = ti->private;
- struct request_queue *q = bdev_get_queue(era->origin_dev->bdev);
-
- if (!q->merge_bvec_fn)
- return max_size;
-
- bvm->bi_bdev = era->origin_dev->bdev;
-
- return min(max_size, q->merge_bvec_fn(q, bvm, biovec));
-}
-
static void era_io_hints(struct dm_target *ti, struct queue_limits *limits)
{
struct era *era = ti->private;
@@ -1717,7 +1703,6 @@ static struct target_type era_target = {
.status = era_status,
.message = era_message,
.iterate_devices = era_iterate_devices,
- .merge = era_merge,
.io_hints = era_io_hints
};
diff --git a/drivers/md/dm-flakey.c b/drivers/md/dm-flakey.c
index b257e46..d955b3e 100644
--- a/drivers/md/dm-flakey.c
+++ b/drivers/md/dm-flakey.c
@@ -387,21 +387,6 @@ static int flakey_ioctl(struct dm_target *ti, unsigned int cmd, unsigned long ar
return r ? : __blkdev_driver_ioctl(dev->bdev, dev->mode, cmd, arg);
}
-static int flakey_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
- struct bio_vec *biovec, int max_size)
-{
- struct flakey_c *fc = ti->private;
- struct request_queue *q = bdev_get_queue(fc->dev->bdev);
-
- if (!q->merge_bvec_fn)
- return max_size;
-
- bvm->bi_bdev = fc->dev->bdev;
- bvm->bi_sector = flakey_map_sector(ti, bvm->bi_sector);
-
- return min(max_size, q->merge_bvec_fn(q, bvm, biovec));
-}
-
static int flakey_iterate_devices(struct dm_target *ti, iterate_devices_callout_fn fn, void *data)
{
struct flakey_c *fc = ti->private;
@@ -419,7 +404,6 @@ static struct target_type flakey_target = {
.end_io = flakey_end_io,
.status = flakey_status,
.ioctl = flakey_ioctl,
- .merge = flakey_merge,
.iterate_devices = flakey_iterate_devices,
};
diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c
index 53e848c..7dd5fc8 100644
--- a/drivers/md/dm-linear.c
+++ b/drivers/md/dm-linear.c
@@ -130,21 +130,6 @@ static int linear_ioctl(struct dm_target *ti, unsigned int cmd,
return r ? : __blkdev_driver_ioctl(dev->bdev, dev->mode, cmd, arg);
}
-static int linear_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
- struct bio_vec *biovec, int max_size)
-{
- struct linear_c *lc = ti->private;
- struct request_queue *q = bdev_get_queue(lc->dev->bdev);
-
- if (!q->merge_bvec_fn)
- return max_size;
-
- bvm->bi_bdev = lc->dev->bdev;
- bvm->bi_sector = linear_map_sector(ti, bvm->bi_sector);
-
- return min(max_size, q->merge_bvec_fn(q, bvm, biovec));
-}
-
static int linear_iterate_devices(struct dm_target *ti,
iterate_devices_callout_fn fn, void *data)
{
@@ -162,7 +147,6 @@ static struct target_type linear_target = {
.map = linear_map,
.status = linear_status,
.ioctl = linear_ioctl,
- .merge = linear_merge,
.iterate_devices = linear_iterate_devices,
};
diff --git a/drivers/md/dm-log-writes.c b/drivers/md/dm-log-writes.c
index 93e0844..4325808 100644
--- a/drivers/md/dm-log-writes.c
+++ b/drivers/md/dm-log-writes.c
@@ -728,21 +728,6 @@ static int log_writes_ioctl(struct dm_target *ti, unsigned int cmd,
return r ? : __blkdev_driver_ioctl(dev->bdev, dev->mode, cmd, arg);
}
-static int log_writes_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
- struct bio_vec *biovec, int max_size)
-{
- struct log_writes_c *lc = ti->private;
- struct request_queue *q = bdev_get_queue(lc->dev->bdev);
-
- if (!q->merge_bvec_fn)
- return max_size;
-
- bvm->bi_bdev = lc->dev->bdev;
- bvm->bi_sector = dm_target_offset(ti, bvm->bi_sector);
-
- return min(max_size, q->merge_bvec_fn(q, bvm, biovec));
-}
-
static int log_writes_iterate_devices(struct dm_target *ti,
iterate_devices_callout_fn fn,
void *data)
@@ -796,7 +781,6 @@ static struct target_type log_writes_target = {
.end_io = normal_end_io,
.status = log_writes_status,
.ioctl = log_writes_ioctl,
- .merge = log_writes_merge,
.message = log_writes_message,
.iterate_devices = log_writes_iterate_devices,
.io_hints = log_writes_io_hints,
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index f83a0f3..274cbec 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -2331,20 +2331,6 @@ static void origin_status(struct dm_target *ti, status_type_t type,
}
}
-static int origin_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
- struct bio_vec *biovec, int max_size)
-{
- struct dm_origin *o = ti->private;
- struct request_queue *q = bdev_get_queue(o->dev->bdev);
-
- if (!q->merge_bvec_fn)
- return max_size;
-
- bvm->bi_bdev = o->dev->bdev;
-
- return min(max_size, q->merge_bvec_fn(q, bvm, biovec));
-}
-
static int origin_iterate_devices(struct dm_target *ti,
iterate_devices_callout_fn fn, void *data)
{
@@ -2363,7 +2349,6 @@ static struct target_type origin_target = {
.resume = origin_resume,
.postsuspend = origin_postsuspend,
.status = origin_status,
- .merge = origin_merge,
.iterate_devices = origin_iterate_devices,
};
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c
index f8b37d4..09bb2fe 100644
--- a/drivers/md/dm-stripe.c
+++ b/drivers/md/dm-stripe.c
@@ -412,26 +412,6 @@ static void stripe_io_hints(struct dm_target *ti,
blk_limits_io_opt(limits, chunk_size * sc->stripes);
}
-static int stripe_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
- struct bio_vec *biovec, int max_size)
-{
- struct stripe_c *sc = ti->private;
- sector_t bvm_sector = bvm->bi_sector;
- uint32_t stripe;
- struct request_queue *q;
-
- stripe_map_sector(sc, bvm_sector, &stripe, &bvm_sector);
-
- q = bdev_get_queue(sc->stripe[stripe].dev->bdev);
- if (!q->merge_bvec_fn)
- return max_size;
-
- bvm->bi_bdev = sc->stripe[stripe].dev->bdev;
- bvm->bi_sector = sc->stripe[stripe].physical_start + bvm_sector;
-
- return min(max_size, q->merge_bvec_fn(q, bvm, biovec));
-}
-
static struct target_type stripe_target = {
.name = "striped",
.version = {1, 5, 1},
@@ -443,7 +423,6 @@ static struct target_type stripe_target = {
.status = stripe_status,
.iterate_devices = stripe_iterate_devices,
.io_hints = stripe_io_hints,
- .merge = stripe_merge,
};
int __init dm_stripe_init(void)
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index d9b00b8..19c9b01 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -440,14 +440,6 @@ static int dm_set_device_limits(struct dm_target *ti, struct dm_dev *dev,
q->limits.alignment_offset,
(unsigned long long) start << SECTOR_SHIFT);
- /*
- * Check if merge fn is supported.
- * If not we'll force DM to use PAGE_SIZE or
- * smaller I/O, just to be safe.
- */
- if (dm_queue_merge_is_compulsory(q) && !ti->type->merge)
- blk_limits_max_hw_sectors(limits,
- (unsigned int) (PAGE_SIZE >> 9));
return 0;
}
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
index 921aafd..03552fe 100644
--- a/drivers/md/dm-thin.c
+++ b/drivers/md/dm-thin.c
@@ -3562,20 +3562,6 @@ static int pool_iterate_devices(struct dm_target *ti,
return fn(ti, pt->data_dev, 0, ti->len, data);
}
-static int pool_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
- struct bio_vec *biovec, int max_size)
-{
- struct pool_c *pt = ti->private;
- struct request_queue *q = bdev_get_queue(pt->data_dev->bdev);
-
- if (!q->merge_bvec_fn)
- return max_size;
-
- bvm->bi_bdev = pt->data_dev->bdev;
-
- return min(max_size, q->merge_bvec_fn(q, bvm, biovec));
-}
-
static void set_discard_limits(struct pool_c *pt, struct queue_limits *limits)
{
struct pool *pool = pt->pool;
@@ -3667,7 +3653,6 @@ static struct target_type pool_target = {
.resume = pool_resume,
.message = pool_message,
.status = pool_status,
- .merge = pool_merge,
.iterate_devices = pool_iterate_devices,
.io_hints = pool_io_hints,
};
@@ -3992,21 +3977,6 @@ err:
DMEMIT("Error");
}
-static int thin_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
- struct bio_vec *biovec, int max_size)
-{
- struct thin_c *tc = ti->private;
- struct request_queue *q = bdev_get_queue(tc->pool_dev->bdev);
-
- if (!q->merge_bvec_fn)
- return max_size;
-
- bvm->bi_bdev = tc->pool_dev->bdev;
- bvm->bi_sector = dm_target_offset(ti, bvm->bi_sector);
-
- return min(max_size, q->merge_bvec_fn(q, bvm, biovec));
-}
-
static int thin_iterate_devices(struct dm_target *ti,
iterate_devices_callout_fn fn, void *data)
{
@@ -4041,7 +4011,6 @@ static struct target_type thin_target = {
.presuspend = thin_presuspend,
.postsuspend = thin_postsuspend,
.status = thin_status,
- .merge = thin_merge,
.iterate_devices = thin_iterate_devices,
};
diff --git a/drivers/md/dm-verity.c b/drivers/md/dm-verity.c
index 66616db..3b85460 100644
--- a/drivers/md/dm-verity.c
+++ b/drivers/md/dm-verity.c
@@ -648,21 +648,6 @@ static int verity_ioctl(struct dm_target *ti, unsigned cmd,
cmd, arg);
}
-static int verity_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
- struct bio_vec *biovec, int max_size)
-{
- struct dm_verity *v = ti->private;
- struct request_queue *q = bdev_get_queue(v->data_dev->bdev);
-
- if (!q->merge_bvec_fn)
- return max_size;
-
- bvm->bi_bdev = v->data_dev->bdev;
- bvm->bi_sector = verity_map_sector(v, bvm->bi_sector);
-
- return min(max_size, q->merge_bvec_fn(q, bvm, biovec));
-}
-
static int verity_iterate_devices(struct dm_target *ti,
iterate_devices_callout_fn fn, void *data)
{
@@ -995,7 +980,6 @@ static struct target_type verity_target = {
.map = verity_map,
.status = verity_status,
.ioctl = verity_ioctl,
- .merge = verity_merge,
.iterate_devices = verity_iterate_devices,
.io_hints = verity_io_hints,
};
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index a2d07e7..15b7a3e 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -121,9 +121,8 @@ EXPORT_SYMBOL_GPL(dm_get_rq_mapinfo);
#define DMF_FREEING 3
#define DMF_DELETING 4
#define DMF_NOFLUSH_SUSPENDING 5
-#define DMF_MERGE_IS_OPTIONAL 6
-#define DMF_DEFERRED_REMOVE 7
-#define DMF_SUSPENDED_INTERNALLY 8
+#define DMF_DEFERRED_REMOVE 6
+#define DMF_SUSPENDED_INTERNALLY 7
/*
* A dummy definition to make RCU happy.
@@ -1709,60 +1708,6 @@ static void __split_and_process_bio(struct mapped_device *md,
* CRUD END
*---------------------------------------------------------------*/
-static int dm_merge_bvec(struct request_queue *q,
- struct bvec_merge_data *bvm,
- struct bio_vec *biovec)
-{
- struct mapped_device *md = q->queuedata;
- struct dm_table *map = dm_get_live_table_fast(md);
- struct dm_target *ti;
- sector_t max_sectors;
- int max_size = 0;
-
- if (unlikely(!map))
- goto out;
-
- ti = dm_table_find_target(map, bvm->bi_sector);
- if (!dm_target_is_valid(ti))
- goto out;
-
- /*
- * Find maximum amount of I/O that won't need splitting
- */
- max_sectors = min(max_io_len(bvm->bi_sector, ti),
- (sector_t) queue_max_sectors(q));
- max_size = (max_sectors << SECTOR_SHIFT) - bvm->bi_size;
- if (unlikely(max_size < 0)) /* this shouldn't _ever_ happen */
- max_size = 0;
-
- /*
- * merge_bvec_fn() returns number of bytes
- * it can accept at this offset
- * max is precomputed maximal io size
- */
- if (max_size && ti->type->merge)
- max_size = ti->type->merge(ti, bvm, biovec, max_size);
- /*
- * If the target doesn't support merge method and some of the devices
- * provided their merge_bvec method (we know this by looking for the
- * max_hw_sectors that dm_set_device_limits may set), then we can't
- * allow bios with multiple vector entries. So always set max_size
- * to 0, and the code below allows just one page.
- */
- else if (queue_max_hw_sectors(q) <= PAGE_SIZE >> 9)
- max_size = 0;
-
-out:
- dm_put_live_table_fast(md);
- /*
- * Always allow an entire first page
- */
- if (max_size <= biovec->bv_len && !(bvm->bi_size >> SECTOR_SHIFT))
- max_size = biovec->bv_len;
-
- return max_size;
-}
-
/*
* The request function that just remaps the bio built up by
* dm_merge_bvec.
@@ -2469,59 +2414,6 @@ static void __set_size(struct mapped_device *md, sector_t size)
}
/*
- * Return 1 if the queue has a compulsory merge_bvec_fn function.
- *
- * If this function returns 0, then the device is either a non-dm
- * device without a merge_bvec_fn, or it is a dm device that is
- * able to split any bios it receives that are too big.
- */
-int dm_queue_merge_is_compulsory(struct request_queue *q)
-{
- struct mapped_device *dev_md;
-
- if (!q->merge_bvec_fn)
- return 0;
-
- if (q->make_request_fn == dm_make_request) {
- dev_md = q->queuedata;
- if (test_bit(DMF_MERGE_IS_OPTIONAL, &dev_md->flags))
- return 0;
- }
-
- return 1;
-}
-
-static int dm_device_merge_is_compulsory(struct dm_target *ti,
- struct dm_dev *dev, sector_t start,
- sector_t len, void *data)
-{
- struct block_device *bdev = dev->bdev;
- struct request_queue *q = bdev_get_queue(bdev);
-
- return dm_queue_merge_is_compulsory(q);
-}
-
-/*
- * Return 1 if it is acceptable to ignore merge_bvec_fn based
- * on the properties of the underlying devices.
- */
-static int dm_table_merge_is_optional(struct dm_table *table)
-{
- unsigned i = 0;
- struct dm_target *ti;
-
- while (i < dm_table_get_num_targets(table)) {
- ti = dm_table_get_target(table, i++);
-
- if (ti->type->iterate_devices &&
- ti->type->iterate_devices(ti, dm_device_merge_is_compulsory, NULL))
- return 0;
- }
-
- return 1;
-}
-
-/*
* Returns old map, which caller must destroy.
*/
static struct dm_table *__bind(struct mapped_device *md, struct dm_table *t,
@@ -2530,7 +2422,6 @@ static struct dm_table *__bind(struct mapped_device *md, struct dm_table *t,
struct dm_table *old_map;
struct request_queue *q = md->queue;
sector_t size;
- int merge_is_optional;
size = dm_table_get_size(t);
@@ -2556,17 +2447,11 @@ static struct dm_table *__bind(struct mapped_device *md, struct dm_table *t,
__bind_mempools(md, t);
- merge_is_optional = dm_table_merge_is_optional(t);
-
old_map = rcu_dereference_protected(md->map, lockdep_is_held(&md->suspend_lock));
rcu_assign_pointer(md->map, t);
md->immutable_target_type = dm_table_get_immutable_target_type(t);
dm_table_set_restrictions(t, q, limits);
- if (merge_is_optional)
- set_bit(DMF_MERGE_IS_OPTIONAL, &md->flags);
- else
- clear_bit(DMF_MERGE_IS_OPTIONAL, &md->flags);
if (old_map)
dm_sync_table(md);
@@ -2847,7 +2732,6 @@ int dm_setup_md_queue(struct mapped_device *md)
case DM_TYPE_BIO_BASED:
dm_init_old_md_queue(md);
blk_queue_make_request(md->queue, dm_make_request);
- blk_queue_merge_bvec(md->queue, dm_merge_bvec);
break;
}
diff --git a/drivers/md/dm.h b/drivers/md/dm.h
index 6123c2b..7d61cca 100644
--- a/drivers/md/dm.h
+++ b/drivers/md/dm.h
@@ -77,8 +77,6 @@ bool dm_table_mq_request_based(struct dm_table *t);
void dm_table_free_md_mempools(struct dm_table *t);
struct dm_md_mempools *dm_table_get_md_mempools(struct dm_table *t);
-int dm_queue_merge_is_compulsory(struct request_queue *q);
-
void dm_lock_md_type(struct mapped_device *md);
void dm_unlock_md_type(struct mapped_device *md);
void dm_set_md_type(struct mapped_device *md, unsigned type);
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index fa7d577..8721ef9 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -52,48 +52,6 @@ static inline struct dev_info *which_dev(struct mddev *mddev, sector_t sector)
return conf->disks + lo;
}
-/**
- * linear_mergeable_bvec -- tell bio layer if two requests can be merged
- * @q: request queue
- * @bvm: properties of new bio
- * @biovec: the request that could be merged to it.
- *
- * Return amount of bytes we can take at this offset
- */
-static int linear_mergeable_bvec(struct mddev *mddev,
- struct bvec_merge_data *bvm,
- struct bio_vec *biovec)
-{
- struct dev_info *dev0;
- unsigned long maxsectors, bio_sectors = bvm->bi_size >> 9;
- sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev);
- int maxbytes = biovec->bv_len;
- struct request_queue *subq;
-
- dev0 = which_dev(mddev, sector);
- maxsectors = dev0->end_sector - sector;
- subq = bdev_get_queue(dev0->rdev->bdev);
- if (subq->merge_bvec_fn) {
- bvm->bi_bdev = dev0->rdev->bdev;
- bvm->bi_sector -= dev0->end_sector - dev0->rdev->sectors;
- maxbytes = min(maxbytes, subq->merge_bvec_fn(subq, bvm,
- biovec));
- }
-
- if (maxsectors < bio_sectors)
- maxsectors = 0;
- else
- maxsectors -= bio_sectors;
-
- if (maxsectors <= (PAGE_SIZE >> 9 ) && bio_sectors == 0)
- return maxbytes;
-
- if (maxsectors > (maxbytes >> 9))
- return maxbytes;
- else
- return maxsectors << 9;
-}
-
static int linear_congested(struct mddev *mddev, int bits)
{
struct linear_conf *conf;
@@ -338,7 +296,6 @@ static struct md_personality linear_personality =
.size = linear_size,
.quiesce = linear_quiesce,
.congested = linear_congested,
- .mergeable_bvec = linear_mergeable_bvec,
};
static int __init linear_init (void)
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 5349f76..19fd331 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -352,29 +352,6 @@ static int md_congested(void *data, int bits)
return mddev_congested(mddev, bits);
}
-static int md_mergeable_bvec(struct request_queue *q,
- struct bvec_merge_data *bvm,
- struct bio_vec *biovec)
-{
- struct mddev *mddev = q->queuedata;
- int ret;
- rcu_read_lock();
- if (mddev->suspended) {
- /* Must always allow one vec */
- if (bvm->bi_size == 0)
- ret = biovec->bv_len;
- else
- ret = 0;
- } else {
- struct md_personality *pers = mddev->pers;
- if (pers && pers->mergeable_bvec)
- ret = pers->mergeable_bvec(mddev, bvm, biovec);
- else
- ret = biovec->bv_len;
- }
- rcu_read_unlock();
- return ret;
-}
/*
* Generic flush handling for md
*/
@@ -5165,7 +5142,6 @@ int md_run(struct mddev *mddev)
if (mddev->queue) {
mddev->queue->backing_dev_info.congested_data = mddev;
mddev->queue->backing_dev_info.congested_fn = md_congested;
- blk_queue_merge_bvec(mddev->queue, md_mergeable_bvec);
}
if (pers->sync_request) {
if (mddev->kobj.sd &&
@@ -5293,7 +5269,6 @@ static void md_clean(struct mddev *mddev)
mddev->changed = 0;
mddev->degraded = 0;
mddev->safemode = 0;
- mddev->merge_check_needed = 0;
mddev->bitmap_info.offset = 0;
mddev->bitmap_info.default_offset = 0;
mddev->bitmap_info.default_space = 0;
@@ -5489,7 +5464,6 @@ static int do_md_stop(struct mddev *mddev, int mode,
__md_stop_writes(mddev);
__md_stop(mddev);
- mddev->queue->merge_bvec_fn = NULL;
mddev->queue->backing_dev_info.congested_fn = NULL;
/* tell userspace to handle 'inactive' */
diff --git a/drivers/md/md.h b/drivers/md/md.h
index 4046a6c..cf7141a 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -133,10 +133,6 @@ enum flag_bits {
Bitmap_sync, /* ..actually, not quite In_sync. Need a
* bitmap-based recovery to get fully in sync
*/
- Unmerged, /* device is being added to array and should
- * be considerred for bvec_merge_fn but not
- * yet for actual IO
- */
WriteMostly, /* Avoid reading if at all possible */
AutoDetected, /* added by auto-detect */
Blocked, /* An error occurred but has not yet
@@ -373,10 +369,6 @@ struct mddev {
int degraded; /* whether md should consider
* adding a spare
*/
- int merge_check_needed; /* at least one
- * member device
- * has a
- * merge_bvec_fn */
atomic_t recovery_active; /* blocks scheduled, but not written */
wait_queue_head_t recovery_wait;
@@ -531,10 +523,6 @@ struct md_personality
/* congested implements bdi.congested_fn().
* Will not be called while array is 'suspended' */
int (*congested)(struct mddev *mddev, int bits);
- /* mergeable_bvec is use to implement ->merge_bvec_fn */
- int (*mergeable_bvec)(struct mddev *mddev,
- struct bvec_merge_data *bvm,
- struct bio_vec *biovec);
};
struct md_sysfs_entry {
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index ac3ede2..7ee27fb 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -257,18 +257,6 @@ static int multipath_add_disk(struct mddev *mddev, struct md_rdev *rdev)
disk_stack_limits(mddev->gendisk, rdev->bdev,
rdev->data_offset << 9);
- /* as we don't honour merge_bvec_fn, we must never risk
- * violating it, so limit ->max_segments to one, lying
- * within a single page.
- * (Note: it is very unlikely that a device with
- * merge_bvec_fn will be involved in multipath.)
- */
- if (q->merge_bvec_fn) {
- blk_queue_max_segments(mddev->queue, 1);
- blk_queue_segment_boundary(mddev->queue,
- PAGE_CACHE_SIZE - 1);
- }
-
spin_lock_irq(&conf->device_lock);
mddev->degraded--;
rdev->raid_disk = path;
@@ -432,15 +420,6 @@ static int multipath_run (struct mddev *mddev)
disk_stack_limits(mddev->gendisk, rdev->bdev,
rdev->data_offset << 9);
- /* as we don't honour merge_bvec_fn, we must never risk
- * violating it, not that we ever expect a device with
- * a merge_bvec_fn to be involved in multipath */
- if (rdev->bdev->bd_disk->queue->merge_bvec_fn) {
- blk_queue_max_segments(mddev->queue, 1);
- blk_queue_segment_boundary(mddev->queue,
- PAGE_CACHE_SIZE - 1);
- }
-
if (!test_bit(Faulty, &rdev->flags))
working_disks++;
}
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index 2cb59a6..b69661f 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -191,9 +191,6 @@ static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf)
disk_stack_limits(mddev->gendisk, rdev1->bdev,
rdev1->data_offset << 9);
- if (rdev1->bdev->bd_disk->queue->merge_bvec_fn)
- conf->has_merge_bvec = 1;
-
if (!smallest || (rdev1->sectors < smallest->sectors))
smallest = rdev1;
cnt++;
@@ -350,58 +347,6 @@ static struct md_rdev *map_sector(struct mddev *mddev, struct strip_zone *zone,
+ sector_div(sector, zone->nb_dev)];
}
-/**
- * raid0_mergeable_bvec -- tell bio layer if two requests can be merged
- * @mddev: the md device
- * @bvm: properties of new bio
- * @biovec: the request that could be merged to it.
- *
- * Return amount of bytes we can accept at this offset
- */
-static int raid0_mergeable_bvec(struct mddev *mddev,
- struct bvec_merge_data *bvm,
- struct bio_vec *biovec)
-{
- struct r0conf *conf = mddev->private;
- sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev);
- sector_t sector_offset = sector;
- int max;
- unsigned int chunk_sectors = mddev->chunk_sectors;
- unsigned int bio_sectors = bvm->bi_size >> 9;
- struct strip_zone *zone;
- struct md_rdev *rdev;
- struct request_queue *subq;
-
- if (is_power_of_2(chunk_sectors))
- max = (chunk_sectors - ((sector & (chunk_sectors-1))
- + bio_sectors)) << 9;
- else
- max = (chunk_sectors - (sector_div(sector, chunk_sectors)
- + bio_sectors)) << 9;
- if (max < 0)
- max = 0; /* bio_add cannot handle a negative return */
- if (max <= biovec->bv_len && bio_sectors == 0)
- return biovec->bv_len;
- if (max < biovec->bv_len)
- /* too small already, no need to check further */
- return max;
- if (!conf->has_merge_bvec)
- return max;
-
- /* May need to check subordinate device */
- sector = sector_offset;
- zone = find_zone(mddev->private, §or_offset);
- rdev = map_sector(mddev, zone, sector, §or_offset);
- subq = bdev_get_queue(rdev->bdev);
- if (subq->merge_bvec_fn) {
- bvm->bi_bdev = rdev->bdev;
- bvm->bi_sector = sector_offset + zone->dev_start +
- rdev->data_offset;
- return min(max, subq->merge_bvec_fn(subq, bvm, biovec));
- } else
- return max;
-}
-
static sector_t raid0_size(struct mddev *mddev, sector_t sectors, int raid_disks)
{
sector_t array_sectors = 0;
@@ -724,7 +669,6 @@ static struct md_personality raid0_personality=
.takeover = raid0_takeover,
.quiesce = raid0_quiesce,
.congested = raid0_congested,
- .mergeable_bvec = raid0_mergeable_bvec,
};
static int __init raid0_init (void)
diff --git a/drivers/md/raid0.h b/drivers/md/raid0.h
index 05539d9..7127a62 100644
--- a/drivers/md/raid0.h
+++ b/drivers/md/raid0.h
@@ -12,8 +12,6 @@ struct r0conf {
struct md_rdev **devlist; /* lists of rdevs, pointed to
* by strip_zone->dev */
int nr_strip_zones;
- int has_merge_bvec; /* at least one member has
- * a merge_bvec_fn */
};
#endif
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 9157a29..478878f 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -557,7 +557,6 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect
rdev = rcu_dereference(conf->mirrors[disk].rdev);
if (r1_bio->bios[disk] == IO_BLOCKED
|| rdev == NULL
- || test_bit(Unmerged, &rdev->flags)
|| test_bit(Faulty, &rdev->flags))
continue;
if (!test_bit(In_sync, &rdev->flags) &&
@@ -708,38 +707,6 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect
return best_disk;
}
-static int raid1_mergeable_bvec(struct mddev *mddev,
- struct bvec_merge_data *bvm,
- struct bio_vec *biovec)
-{
- struct r1conf *conf = mddev->private;
- sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev);
- int max = biovec->bv_len;
-
- if (mddev->merge_check_needed) {
- int disk;
- rcu_read_lock();
- for (disk = 0; disk < conf->raid_disks * 2; disk++) {
- struct md_rdev *rdev = rcu_dereference(
- conf->mirrors[disk].rdev);
- if (rdev && !test_bit(Faulty, &rdev->flags)) {
- struct request_queue *q =
- bdev_get_queue(rdev->bdev);
- if (q->merge_bvec_fn) {
- bvm->bi_sector = sector +
- rdev->data_offset;
- bvm->bi_bdev = rdev->bdev;
- max = min(max, q->merge_bvec_fn(
- q, bvm, biovec));
- }
- }
- }
- rcu_read_unlock();
- }
- return max;
-
-}
-
static int raid1_congested(struct mddev *mddev, int bits)
{
struct r1conf *conf = mddev->private;
@@ -1268,8 +1235,7 @@ read_again:
break;
}
r1_bio->bios[i] = NULL;
- if (!rdev || test_bit(Faulty, &rdev->flags)
- || test_bit(Unmerged, &rdev->flags)) {
+ if (!rdev || test_bit(Faulty, &rdev->flags)) {
if (i < conf->raid_disks)
set_bit(R1BIO_Degraded, &r1_bio->state);
continue;
@@ -1614,7 +1580,6 @@ static int raid1_add_disk(struct mddev *mddev, struct md_rdev *rdev)
struct raid1_info *p;
int first = 0;
int last = conf->raid_disks - 1;
- struct request_queue *q = bdev_get_queue(rdev->bdev);
if (mddev->recovery_disabled == conf->recovery_disabled)
return -EBUSY;
@@ -1622,11 +1587,6 @@ static int raid1_add_disk(struct mddev *mddev, struct md_rdev *rdev)
if (rdev->raid_disk >= 0)
first = last = rdev->raid_disk;
- if (q->merge_bvec_fn) {
- set_bit(Unmerged, &rdev->flags);
- mddev->merge_check_needed = 1;
- }
-
for (mirror = first; mirror <= last; mirror++) {
p = conf->mirrors+mirror;
if (!p->rdev) {
@@ -1658,19 +1618,6 @@ static int raid1_add_disk(struct mddev *mddev, struct md_rdev *rdev)
break;
}
}
- if (err == 0 && test_bit(Unmerged, &rdev->flags)) {
- /* Some requests might not have seen this new
- * merge_bvec_fn. We must wait for them to complete
- * before merging the device fully.
- * First we make sure any code which has tested
- * our function has submitted the request, then
- * we wait for all outstanding requests to complete.
- */
- synchronize_sched();
- freeze_array(conf, 0);
- unfreeze_array(conf);
- clear_bit(Unmerged, &rdev->flags);
- }
md_integrity_add_rdev(rdev, mddev);
if (mddev->queue && blk_queue_discard(bdev_get_queue(rdev->bdev)))
queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
@@ -2807,8 +2754,6 @@ static struct r1conf *setup_conf(struct mddev *mddev)
goto abort;
disk->rdev = rdev;
q = bdev_get_queue(rdev->bdev);
- if (q->merge_bvec_fn)
- mddev->merge_check_needed = 1;
disk->head_position = 0;
disk->seq_start = MaxSector;
@@ -3173,7 +3118,6 @@ static struct md_personality raid1_personality =
.quiesce = raid1_quiesce,
.takeover = raid1_takeover,
.congested = raid1_congested,
- .mergeable_bvec = raid1_mergeable_bvec,
};
static int __init raid_init(void)
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index e793ab6..a46c402 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -672,93 +672,6 @@ static sector_t raid10_find_virt(struct r10conf *conf, sector_t sector, int dev)
return (vchunk << geo->chunk_shift) + offset;
}
-/**
- * raid10_mergeable_bvec -- tell bio layer if a two requests can be merged
- * @mddev: the md device
- * @bvm: properties of new bio
- * @biovec: the request that could be merged to it.
- *
- * Return amount of bytes we can accept at this offset
- * This requires checking for end-of-chunk if near_copies != raid_disks,
- * and for subordinate merge_bvec_fns if merge_check_needed.
- */
-static int raid10_mergeable_bvec(struct mddev *mddev,
- struct bvec_merge_data *bvm,
- struct bio_vec *biovec)
-{
- struct r10conf *conf = mddev->private;
- sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev);
- int max;
- unsigned int chunk_sectors;
- unsigned int bio_sectors = bvm->bi_size >> 9;
- struct geom *geo = &conf->geo;
-
- chunk_sectors = (conf->geo.chunk_mask & conf->prev.chunk_mask) + 1;
- if (conf->reshape_progress != MaxSector &&
- ((sector >= conf->reshape_progress) !=
- conf->mddev->reshape_backwards))
- geo = &conf->prev;
-
- if (geo->near_copies < geo->raid_disks) {
- max = (chunk_sectors - ((sector & (chunk_sectors - 1))
- + bio_sectors)) << 9;
- if (max < 0)
- /* bio_add cannot handle a negative return */
- max = 0;
- if (max <= biovec->bv_len && bio_sectors == 0)
- return biovec->bv_len;
- } else
- max = biovec->bv_len;
-
- if (mddev->merge_check_needed) {
- struct {
- struct r10bio r10_bio;
- struct r10dev devs[conf->copies];
- } on_stack;
- struct r10bio *r10_bio = &on_stack.r10_bio;
- int s;
- if (conf->reshape_progress != MaxSector) {
- /* Cannot give any guidance during reshape */
- if (max <= biovec->bv_len && bio_sectors == 0)
- return biovec->bv_len;
- return 0;
- }
- r10_bio->sector = sector;
- raid10_find_phys(conf, r10_bio);
- rcu_read_lock();
- for (s = 0; s < conf->copies; s++) {
- int disk = r10_bio->devs[s].devnum;
- struct md_rdev *rdev = rcu_dereference(
- conf->mirrors[disk].rdev);
- if (rdev && !test_bit(Faulty, &rdev->flags)) {
- struct request_queue *q =
- bdev_get_queue(rdev->bdev);
- if (q->merge_bvec_fn) {
- bvm->bi_sector = r10_bio->devs[s].addr
- + rdev->data_offset;
- bvm->bi_bdev = rdev->bdev;
- max = min(max, q->merge_bvec_fn(
- q, bvm, biovec));
- }
- }
- rdev = rcu_dereference(conf->mirrors[disk].replacement);
- if (rdev && !test_bit(Faulty, &rdev->flags)) {
- struct request_queue *q =
- bdev_get_queue(rdev->bdev);
- if (q->merge_bvec_fn) {
- bvm->bi_sector = r10_bio->devs[s].addr
- + rdev->data_offset;
- bvm->bi_bdev = rdev->bdev;
- max = min(max, q->merge_bvec_fn(
- q, bvm, biovec));
- }
- }
- }
- rcu_read_unlock();
- }
- return max;
-}
-
/*
* This routine returns the disk from which the requested read should
* be done. There is a per-array 'next expected sequential IO' sector
@@ -821,12 +734,10 @@ retry:
disk = r10_bio->devs[slot].devnum;
rdev = rcu_dereference(conf->mirrors[disk].replacement);
if (rdev == NULL || test_bit(Faulty, &rdev->flags) ||
- test_bit(Unmerged, &rdev->flags) ||
r10_bio->devs[slot].addr + sectors > rdev->recovery_offset)
rdev = rcu_dereference(conf->mirrors[disk].rdev);
if (rdev == NULL ||
- test_bit(Faulty, &rdev->flags) ||
- test_bit(Unmerged, &rdev->flags))
+ test_bit(Faulty, &rdev->flags))
continue;
if (!test_bit(In_sync, &rdev->flags) &&
r10_bio->devs[slot].addr + sectors > rdev->recovery_offset)
@@ -1326,11 +1237,9 @@ retry_write:
blocked_rdev = rrdev;
break;
}
- if (rdev && (test_bit(Faulty, &rdev->flags)
- || test_bit(Unmerged, &rdev->flags)))
+ if (rdev && (test_bit(Faulty, &rdev->flags)))
rdev = NULL;
- if (rrdev && (test_bit(Faulty, &rrdev->flags)
- || test_bit(Unmerged, &rrdev->flags)))
+ if (rrdev && (test_bit(Faulty, &rrdev->flags)))
rrdev = NULL;
r10_bio->devs[i].bio = NULL;
@@ -1777,7 +1686,6 @@ static int raid10_add_disk(struct mddev *mddev, struct md_rdev *rdev)
int mirror;
int first = 0;
int last = conf->geo.raid_disks - 1;
- struct request_queue *q = bdev_get_queue(rdev->bdev);
if (mddev->recovery_cp < MaxSector)
/* only hot-add to in-sync arrays, as recovery is
@@ -1790,11 +1698,6 @@ static int raid10_add_disk(struct mddev *mddev, struct md_rdev *rdev)
if (rdev->raid_disk >= 0)
first = last = rdev->raid_disk;
- if (q->merge_bvec_fn) {
- set_bit(Unmerged, &rdev->flags);
- mddev->merge_check_needed = 1;
- }
-
if (rdev->saved_raid_disk >= first &&
conf->mirrors[rdev->saved_raid_disk].rdev == NULL)
mirror = rdev->saved_raid_disk;
@@ -1833,19 +1736,6 @@ static int raid10_add_disk(struct mddev *mddev, struct md_rdev *rdev)
rcu_assign_pointer(p->rdev, rdev);
break;
}
- if (err == 0 && test_bit(Unmerged, &rdev->flags)) {
- /* Some requests might not have seen this new
- * merge_bvec_fn. We must wait for them to complete
- * before merging the device fully.
- * First we make sure any code which has tested
- * our function has submitted the request, then
- * we wait for all outstanding requests to complete.
- */
- synchronize_sched();
- freeze_array(conf, 0);
- unfreeze_array(conf);
- clear_bit(Unmerged, &rdev->flags);
- }
md_integrity_add_rdev(rdev, mddev);
if (mddev->queue && blk_queue_discard(bdev_get_queue(rdev->bdev)))
queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
@@ -2404,7 +2294,6 @@ static void fix_read_error(struct r10conf *conf, struct mddev *mddev, struct r10
d = r10_bio->devs[sl].devnum;
rdev = rcu_dereference(conf->mirrors[d].rdev);
if (rdev &&
- !test_bit(Unmerged, &rdev->flags) &&
test_bit(In_sync, &rdev->flags) &&
is_badblock(rdev, r10_bio->devs[sl].addr + sect, s,
&first_bad, &bad_sectors) == 0) {
@@ -2458,7 +2347,6 @@ static void fix_read_error(struct r10conf *conf, struct mddev *mddev, struct r10
d = r10_bio->devs[sl].devnum;
rdev = rcu_dereference(conf->mirrors[d].rdev);
if (!rdev ||
- test_bit(Unmerged, &rdev->flags) ||
!test_bit(In_sync, &rdev->flags))
continue;
@@ -3652,8 +3540,6 @@ static int run(struct mddev *mddev)
disk->rdev = rdev;
}
q = bdev_get_queue(rdev->bdev);
- if (q->merge_bvec_fn)
- mddev->merge_check_needed = 1;
diff = (rdev->new_data_offset - rdev->data_offset);
if (!mddev->reshape_backwards)
diff = -diff;
@@ -4706,7 +4592,6 @@ static struct md_personality raid10_personality =
.start_reshape = raid10_start_reshape,
.finish_reshape = raid10_finish_reshape,
.congested = raid10_congested,
- .mergeable_bvec = raid10_mergeable_bvec,
};
static int __init raid_init(void)
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 7f4a717..e42b624 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -4620,35 +4620,6 @@ static int raid5_congested(struct mddev *mddev, int bits)
return 0;
}
-/* We want read requests to align with chunks where possible,
- * but write requests don't need to.
- */
-static int raid5_mergeable_bvec(struct mddev *mddev,
- struct bvec_merge_data *bvm,
- struct bio_vec *biovec)
-{
- sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev);
- int max;
- unsigned int chunk_sectors = mddev->chunk_sectors;
- unsigned int bio_sectors = bvm->bi_size >> 9;
-
- /*
- * always allow writes to be mergeable, read as well if array
- * is degraded as we'll go through stripe cache anyway.
- */
- if ((bvm->bi_rw & 1) == WRITE || mddev->degraded)
- return biovec->bv_len;
-
- if (mddev->new_chunk_sectors < mddev->chunk_sectors)
- chunk_sectors = mddev->new_chunk_sectors;
- max = (chunk_sectors - ((sector & (chunk_sectors - 1)) + bio_sectors)) << 9;
- if (max < 0) max = 0;
- if (max <= biovec->bv_len && bio_sectors == 0)
- return biovec->bv_len;
- else
- return max;
-}
-
static int in_chunk_boundary(struct mddev *mddev, struct bio *bio)
{
sector_t sector = bio->bi_iter.bi_sector + get_start_sect(bio->bi_bdev);
@@ -7678,7 +7649,6 @@ static struct md_personality raid6_personality =
.quiesce = raid5_quiesce,
.takeover = raid6_takeover,
.congested = raid5_congested,
- .mergeable_bvec = raid5_mergeable_bvec,
};
static struct md_personality raid5_personality =
{
@@ -7702,7 +7672,6 @@ static struct md_personality raid5_personality =
.quiesce = raid5_quiesce,
.takeover = raid5_takeover,
.congested = raid5_congested,
- .mergeable_bvec = raid5_mergeable_bvec,
};
static struct md_personality raid4_personality =
@@ -7727,7 +7696,6 @@ static struct md_personality raid4_personality =
.quiesce = raid5_quiesce,
.takeover = raid4_takeover,
.congested = raid5_congested,
- .mergeable_bvec = raid5_mergeable_bvec,
};
static int __init raid5_init(void)
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 93b81a2..6927b76 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -239,14 +239,6 @@ typedef int (prep_rq_fn) (struct request_queue *, struct request *);
typedef void (unprep_rq_fn) (struct request_queue *, struct request *);
struct bio_vec;
-struct bvec_merge_data {
- struct block_device *bi_bdev;
- sector_t bi_sector;
- unsigned bi_size;
- unsigned long bi_rw;
-};
-typedef int (merge_bvec_fn) (struct request_queue *, struct bvec_merge_data *,
- struct bio_vec *);
typedef void (softirq_done_fn)(struct request *);
typedef int (dma_drain_needed_fn)(struct request *);
typedef int (lld_busy_fn) (struct request_queue *q);
@@ -331,7 +323,6 @@ struct request_queue {
make_request_fn *make_request_fn;
prep_rq_fn *prep_rq_fn;
unprep_rq_fn *unprep_rq_fn;
- merge_bvec_fn *merge_bvec_fn;
softirq_done_fn *softirq_done_fn;
rq_timed_out_fn *rq_timed_out_fn;
dma_drain_needed_fn *dma_drain_needed;
@@ -1041,7 +1032,6 @@ extern void blk_queue_lld_busy(struct request_queue *q, lld_busy_fn *fn);
extern void blk_queue_segment_boundary(struct request_queue *, unsigned long);
extern void blk_queue_prep_rq(struct request_queue *, prep_rq_fn *pfn);
extern void blk_queue_unprep_rq(struct request_queue *, unprep_rq_fn *ufn);
-extern void blk_queue_merge_bvec(struct request_queue *, merge_bvec_fn *);
extern void blk_queue_dma_alignment(struct request_queue *, int);
extern void blk_queue_update_dma_alignment(struct request_queue *, int);
extern void blk_queue_softirq_done(struct request_queue *, softirq_done_fn *);
diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h
index 51cc1de..76d23fa 100644
--- a/include/linux/device-mapper.h
+++ b/include/linux/device-mapper.h
@@ -82,9 +82,6 @@ typedef int (*dm_message_fn) (struct dm_target *ti, unsigned argc, char **argv);
typedef int (*dm_ioctl_fn) (struct dm_target *ti, unsigned int cmd,
unsigned long arg);
-typedef int (*dm_merge_fn) (struct dm_target *ti, struct bvec_merge_data *bvm,
- struct bio_vec *biovec, int max_size);
-
/*
* These iteration functions are typically used to check (and combine)
* properties of underlying devices.
@@ -160,7 +157,6 @@ struct target_type {
dm_status_fn status;
dm_message_fn message;
dm_ioctl_fn ioctl;
- dm_merge_fn merge;
dm_busy_fn busy;
dm_iterate_devices_fn iterate_devices;
dm_io_hints_fn io_hints;
--
1.9.1
^ permalink raw reply related
* [PATCH 06/10] md/raid5: get rid of bio_fits_rdev()
From: Ming Lin @ 2015-04-28 6:48 UTC (permalink / raw)
To: linux-kernel
Cc: Christoph Hellwig, Jens Axboe, Kent Overstreet, Dongsu Park,
Ming Lin, Neil Brown, linux-raid
In-Reply-To: <1430203717-13307-1-git-send-email-mlin@kernel.org>
From: Kent Overstreet <kent.overstreet@gmail.com>
Remove bio_fits_rdev() completely, because ->merge_bvec_fn() has now
gone. There's no point in calling bio_fits_rdev() only for ensuring
aligned read from rdev.
Cc: Neil Brown <neilb@suse.de>
Cc: linux-raid@vger.kernel.org
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
[dpark: add more description in commit message]
Signed-off-by: Dongsu Park <dongsu.park@profitbricks.com>
Signed-off-by: Ming Lin <mlin@kernel.org>
---
drivers/md/raid5.c | 23 +----------------------
1 file changed, 1 insertion(+), 22 deletions(-)
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 77dfd72..7f4a717 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -4738,25 +4738,6 @@ static void raid5_align_endio(struct bio *bi, int error)
add_bio_to_retry(raid_bi, conf);
}
-static int bio_fits_rdev(struct bio *bi)
-{
- struct request_queue *q = bdev_get_queue(bi->bi_bdev);
-
- if (bio_sectors(bi) > queue_max_sectors(q))
- return 0;
- blk_recount_segments(q, bi);
- if (bi->bi_phys_segments > queue_max_segments(q))
- return 0;
-
- if (q->merge_bvec_fn)
- /* it's too hard to apply the merge_bvec_fn at this stage,
- * just just give up
- */
- return 0;
-
- return 1;
-}
-
static int chunk_aligned_read(struct mddev *mddev, struct bio * raid_bio)
{
struct r5conf *conf = mddev->private;
@@ -4810,11 +4791,9 @@ static int chunk_aligned_read(struct mddev *mddev, struct bio * raid_bio)
align_bi->bi_bdev = rdev->bdev;
__clear_bit(BIO_SEG_VALID, &align_bi->bi_flags);
- if (!bio_fits_rdev(align_bi) ||
- is_badblock(rdev, align_bi->bi_iter.bi_sector,
+ if (is_badblock(rdev, align_bi->bi_iter.bi_sector,
bio_sectors(align_bi),
&first_bad, &bad_sectors)) {
- /* too big in some way, or has a known bad block */
bio_put(align_bi);
rdev_dec_pending(rdev, mddev);
return 0;
--
1.9.1
^ permalink raw reply related
* Re: BUG?: RAID6 reshape hung in reshape_request
From: David Wahler @ 2015-04-27 17:20 UTC (permalink / raw)
To: NeilBrown; +Cc: linux-raid
In-Reply-To: <20150427165926.6128d59b@notabene.brown>
On Mon, Apr 27, 2015 at 1:59 AM, NeilBrown <neilb@suse.de> wrote:
> On Sun, 26 Apr 2015 20:56:58 -0500 David Wahler <dwahler@gmail.com> wrote:
>
>> [oops, forgot to cc the list]
>>
>> On Sun, Apr 26, 2015 at 8:20 PM, NeilBrown <neilb@suse.de> wrote:
>> > Anyway:
>> >
>> > Bad Block Log : 512 entries available at offset 72 sectors - bad blocks present.
>> >
>> > that is the only thing that looks at all interesting. Particularly the last
>> > 3 words.
>> > What does
>> > mdadm --examine-badblocks /dev/sd[cde]1
>> > show?
>>
>> root@ceres:~# mdadm --examine-badblocks /dev/sd[cde]1
>> Bad-blocks on /dev/sdc1:
>> 3699640928 for 32 sectors
>> Bad-blocks on /dev/sdd1:
>> 3699640928 for 32 sectors
>> Bad-blocks on /dev/sde1:
>> 3699640928 for 32 sectors
>>
>> Hmm, that seems kind of odd to me. For what it's worth, all four
>> drives passed a SMART self-test, and "dd > /dev/null" completed
>> without errors on all of them. I just read about the "badblocks" tool
>> and I'm running it now.
>
> The array is reshaping a RAID6 from 4->5 devices, so that is 2 data disks to
> 3 data disks.
>
> Reshape pos'n : 5548735488 (5291.69 GiB 5681.91 GB)
>
> so it is about 5.3TB through the array, so it has read about 2.6TB from the
> devices and written about 1.7TB to the devices.
>
> 3699640928 sectors is about 1.8TB. That seems a little too close to be a co-incidence.
>
> Maybe when reshape write to somewhere that is a bad-block, it gets confused.
>
> On the other hand, when it copies from the 1.8TB address to the 1.2TB address
> it should have record that it was bad-blocks that were being copied. It
> doesn't seem like it did.
>
> I'll have to look at the code and try to figure out what is happening.
>
> I don't think there is anything useful you can do in the mean time...
>
> NeilBrown
>
Thanks, I appreciate you taking the time to look at this.
GDB tells me that the address where the reshape is getting stuck
corresponds to drivers/md/raid5.c:4933. I also noticed that there's a
kernel thread "md127_raid6" occupying 100% of a CPU core. Here's a
representative stack for that thread (with line numbers added by me):
[<ffffffffa06aeb20>] raid_run_ops+0xbe0/0x1170 [raid456]
arch/x86/include/asm/bitops.h:311
[<ffffffffa06ab277>] ops_run_io+0x27/0x970 [raid456] drivers/md/raid5.c:742
[<ffffffffa06a9940>] ops_complete_reconstruct+0x0/0x1c0 [raid456]
drivers/md/raid5.c:1433
[<ffffffffa06b2a00>] handle_stripe+0xbd0/0x2650 [raid456]
drivers/md/raid5.c:4099
[<ffffffff810a3162>] pick_next_task_fair+0x652/0x850 kernel/sched/fair.c:5047
[<ffffffffa06b463d>] handle_active_stripes.isra.41+0x1bd/0x4b0
[raid456] drivers/md/raid5.c:5248
[<ffffffff810115eb>] __switch_to+0x14b/0x5d0 arch/x86/include/asm/paravirt.h:276
[<ffffffffa06b4d7c>] raid5d+0x44c/0x5b0 [raid456] drivers/md/raid5.c:5340
[<ffffffffa0760c56>] md_thread+0x126/0x130 [md_mod]
[<ffffffff810a86f0>] autoremove_wake_function+0x0/0x30
[<ffffffffa0760b30>] md_thread+0x0/0x130 [md_mod]
[<ffffffff81089403>] kthread+0xd3/0xf0
[<ffffffff81089330>] kthread+0x0/0xf0
[<ffffffff81560598>] ret_from_fork+0x58/0x90
[<ffffffff81089330>] kthread+0x0/0xf0
[<ffffffffffffffff>] 0xffffffffffffffff
And the output of running "perf record" for a few seconds followed by
"perf report":
# ========
# captured on: Mon Apr 27 12:07:01 2015
# hostname : ceres
# os release : 4.0.0
# perf version : 4.0.g39a880
# arch : x86_64
# nrcpus online : 4
# nrcpus avail : 4
# cpudesc : Intel(R) Core(TM) i3-4160 CPU @ 3.60GHz
# cpuid : GenuineIntel,6,60,3
# total memory : 16112348 kB
# cmdline : /home/david/software/linux/tools/perf/perf record -p 508
# event : name = cycles, type = 0, config = 0x0, config1 = 0x0,
config2 = 0x0, excl_usr = 0, excl_kern = 0, excl_host = 0, excl_guest
= 1, precise_ip = 0, attr_mmap2 = 1, attr_mmap = 1, attr_mmap_data =
0
# HEADER_CPU_TOPOLOGY info available, use -I to display
# HEADER_NUMA_TOPOLOGY info available, use -I to display
# pmu mappings: cpu = 4, software = 1, power = 6, uncore_imc = 7,
tracepoint = 2, breakpoint = 5
# ========
#
# Samples: 84K of event 'cycles'
# Event count (approx.): 76131836770
#
# Overhead Command Shared Object Symbol
# ........ ........... .................
...........................................
#
41.90% md127_raid6 [raid6_pq] [k] raid6_avx24_gen_syndrome
19.31% md127_raid6 [raid456] [k] analyse_stripe
8.48% md127_raid6 [raid456] [k] ops_run_i
4.05% md127_raid6 [raid456] [k] handle_stripe
3.72% md127_raid6 [raid456] [k] ops_complete_reconstruct
3.30% md127_raid6 [kernel.kallsyms] [k] __kernel_fpu_end
3.07% md127_raid6 [raid456] [k] schedule_reconstruction
3.01% md127_raid6 [raid456] [k] raid5_compute_sector
1.42% md127_raid6 [raid456] [k] handle_active_stripes.isra.41
1.33% md127_raid6 [kernel.kallsyms] [k] __kernel_fpu_begin
1.33% md127_raid6 [raid456] [k] do_release_stripe
1.16% md127_raid6 [raid456] [k] raid_run_ops
1.14% md127_raid6 [md_mod] [k] md_is_badblock
1.12% md127_raid6 [raid456] [k] set_syndrome_sources
1.07% md127_raid6 [kernel.kallsyms] [k] _raw_spin_lock_irqsave
0.93% md127_raid6 [async_pq] [k] async_gen_syndrome
0.69% md127_raid6 [raid456] [k] release_stripe
0.64% md127_raid6 [md_mod] [k] md_wakeup_thread
0.54% md127_raid6 [raid456] [k] __release_stripe
0.40% md127_raid6 [kernel.kallsyms] [k] _raw_spin_unlock_irqrestore
0.22% md127_raid6 [raid456] [k] release_stripe_list
0.20% md127_raid6 [kernel.kallsyms] [k] __wake_up_common
0.17% md127_raid6 [raid456] [k] release_inactive_stripe_list
0.16% md127_raid6 [kernel.kallsyms] [k] __wake_up
0.13% md127_raid6 [raid456] [k] raid5d
0.11% md127_raid6 [kernel.kallsyms] [k] _raw_spin_lock_irq
0.10% md127_raid6 [raid456] [k] return_io
[...etc...]
I don't urgently need this array up and running, so I'm happy to leave
it in its current state for the next few days in case there's anything
else I can do to help track this down.
-- David
^ permalink raw reply
* Re: [PATCH -stable] block: destroy bdi before blockdev is unregistered.
From: Jens Axboe @ 2015-04-27 16:27 UTC (permalink / raw)
To: NeilBrown
Cc: Azat Khuzhin, Christoph Hellwig, Kernel.org-Linux-RAID,
Guoqing Jiang, Tejun Heo, Jan Kara, lkml
In-Reply-To: <20150427141222.5dac22f1@notabene.brown>
On 04/26/2015 10:12 PM, NeilBrown wrote:
>
> Because of the peculiar way that md devices are created (automatically
> when the device node is opened), a new device can be created and
> registered immediately after the
> blk_unregister_region(disk_devt(disk), disk->minors);
> call in del_gendisk().
>
> Therefore it is important that all visible artifacts of the previous
> device are removed before this call. In particular, the 'bdi'.
>
> Since:
> commit c4db59d31e39ea067c32163ac961e9c80198fd37
> Author: Christoph Hellwig <hch@lst.de>
> fs: don't reassign dirty inodes to default_backing_dev_info
>
> moved the
> device_unregister(bdi->dev);
> call from bdi_unregister() to bdi_destroy() it has been quite easy to
> lose a race and have a new (e.g.) "md127" be created after the
> blk_unregister_region() call and before bdi_destroy() is ultimately
> called by the final 'put_disk', which must come after del_gendisk().
>
> The new device finds that the bdi name is already registered in sysfs
> and complains
>
>> [ 9627.630029] WARNING: CPU: 18 PID: 3330 at fs/sysfs/dir.c:31 sysfs_warn_dup+0x5a/0x70()
>> [ 9627.630032] sysfs: cannot create duplicate filename '/devices/virtual/bdi/9:127'
>
> We can fix this by moving the bdi_destroy() call out of
> blk_release_queue() (which can happen very late when a refcount
> reaches zero) and into blk_cleanup_queue() - which happens exactly when the md
> device driver calls it.
>
> Then it is only necessary for md to call blk_cleanup_queue() before
> del_gendisk(). As loop.c devices are also created on demand by
> opening the device node, we make the same change there.
>
> Fixes: c4db59d31e39ea067c32163ac961e9c80198fd37
> Reported-by: Azat Khuzhin <a3at.mail@gmail.com>
> Cc: Christoph Hellwig <hch@lst.de>
> Cc: stable@vger.kernel.org (v4.0)
> Signed-off-by: NeilBrown <neilb@suse.de>
>
> --
> Hi Jens,
> if you could check this and forward on to Linus I'd really appreciate it.
Yup, I added it. BTW, that line needs 3 '-', otherwise git am will pick
up the comments below :-)
Thanks Neil.
--
Jens Axboe
^ permalink raw reply
* Re: Paranoid mode for RAID-1 ?
From: Wols Lists @ 2015-04-27 16:15 UTC (permalink / raw)
To: Jean-Baptiste Thomas; +Cc: NeilBrown, linux-raid
In-Reply-To: <1670710921.23079769.1430131923662.JavaMail.zimbra@laposte.net>
On 27/04/15 11:52, Jean-Baptiste Thomas wrote:
> On 2015-04-27 16:49 +1000, NeilBrown wrote:
>> On Mon, 27 Apr 2015 08:37:59 +0200 (CEST) Jean-Baptiste Thomas
>> <cau2jeaf1honoq@laposte.net> wrote:
>> ·
>>> I'm looking for a way to get MD to operate in a mode in which
>>> reading a sector from a RAID-1 device would not succeed until it
>>> got matching data from at least two components.
>> ·
>> No, there is no such thing.
>
> Thanks, now I can move on to working on plan B.
>
>> There "should" be no circumstance which would make it worth while.
>> A drive may well report an error, but it should *never* report
>> incorrect data as though it were correct. That is horribly
>> broken.
>
> Isn't it. <g>
>
>> The cost of running in a "safe" mode would be high, and the
>> likely benefit extremely low. So it is unlikely that anyone
>> would use it for long. So implementing it seems rather
>> pointless.
>
> How high would the cost be ?
>
> Seems to me that a 4-component RAID-1 with a 2-component quorum
> would incur no more I/O or CPU overhead than, say, a 4-component
> RAID-6. Less, in fact, unless parity computation is faster than
> memcmp().
>
> Given the choice between that sort of cost and the possibility
> of massive data corruption because one drive had a hiccup, I
> would not even THINK about running without it.
Well, I've already mentioned the Pr1me technique, but imho that belongs
in the layer that actually writes to the disk. Snag is, it doubles the
required disk space so I don't know how it would fit ...
And I don't remember the maths so I can't tell you *how* it did it, but
for each byte of data it created a parity byte (which is why it doubles
the disk requirement). From that, a single-bit error was guaranteed to
tell you whether the data byte or the parity byte was wrong. If the data
was wrong, you could reconstruct it from the parity. If there was a
two-bit error, you stood a 95% chance or thereabouts of recovery.
So this isn't raid, it won't protect you against disk failure (unless
you put data and parity on separate disks, which then costs a
double-read instead), but at least a read can then return e_data_error
if something goes wrong. But you're looking at only 25% of your disk
space being "usable" for a fast mirror if you do this.
>
>> That said: if someone were to provide an implementation I
>> would certainly consider reviewing it and adding it to md.
>
> Great. Don't think it'll be me, though. :-/
Nor me neither. I'd love to try, but time is not my friend at the moment.
Cheers,
Wol
--
To unsubscribe from this list: send the line "unsubscribe linux-raid" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: Paranoid mode for RAID-1 ?
From: David Brown @ 2015-04-27 13:46 UTC (permalink / raw)
To: Jean-Baptiste Thomas; +Cc: linux-raid
In-Reply-To: <1441590395.23298447.1430138211592.JavaMail.zimbra@laposte.net>
On 27/04/15 14:36, Jean-Baptiste Thomas wrote:
> On 2015-04-27 12:54 +0200, David Brown wrote:
>
>> The problem with all of these is that they /might/ be right -
>> but they /might/ be wrong and make matters worse. Even if you
>> have 3 copies of the sector, and get two matches and one
>> different, there is no way to determine that the odd one is
>> wrong. Perhaps a common bus or connector fault caused the
>> other two to be wrong. Picking the "majority vote" may
>> decrease your chances of losing data (but may not - it depends
>> on the cause of the fault), but it certainly does not avoid
>> the worst case scenario.
>
> So Neil's objection is that it's too paranoid and yours is that
> it's not paranoid enough ? :-)
It's both - it's unlikely to be needed, and in cases where it is needed,
it's unlikely to help.
Neil has written articles about this before, which are worth reading:
<http://neil.brown.name/blog/20110227114201>
<http://neil.brown.name/blog/20100211050355>
>
>> Perhaps the best choice during normal usage (as distinct from
>> recovery or rebuild, when the drive is not mounted) is to
>> simply report a failure to the layers higher up - that way you
>> won't make matters worse by giving returning data.
>
> You may be right. The main points I think are that
> a) the inconsistency be caught and reported and
> b) writes be disabled before the propagation of errors buggers
> up the whole file system.
Yes, that all makes sense.
^ permalink raw reply
* Re: [PATCH -stable] block: destroy bdi before blockdev is unregistered.
From: Christoph Hellwig @ 2015-04-27 13:03 UTC (permalink / raw)
To: NeilBrown
Cc: Jens Axboe, Azat Khuzhin, Christoph Hellwig,
Kernel.org-Linux-RAID, Guoqing Jiang, Tejun Heo, Jan Kara, lkml
In-Reply-To: <20150427141222.5dac22f1@notabene.brown>
Looks good,
Reviewed-by: Christoph Hellwig <hch@lst.de>
^ permalink raw reply
* Re: Paranoid mode for RAID-1 ?
From: Jean-Baptiste Thomas @ 2015-04-27 12:36 UTC (permalink / raw)
To: David Brown; +Cc: linux-raid
In-Reply-To: <553E1559.2010305@hesbynett.no>
On 2015-04-27 12:54 +0200, David Brown wrote:
> The problem with all of these is that they /might/ be right -
> but they /might/ be wrong and make matters worse. Even if you
> have 3 copies of the sector, and get two matches and one
> different, there is no way to determine that the odd one is
> wrong. Perhaps a common bus or connector fault caused the
> other two to be wrong. Picking the "majority vote" may
> decrease your chances of losing data (but may not - it depends
> on the cause of the fault), but it certainly does not avoid
> the worst case scenario.
So Neil's objection is that it's too paranoid and yours is that
it's not paranoid enough ? :-)
> Perhaps the best choice during normal usage (as distinct from
> recovery or rebuild, when the drive is not mounted) is to
> simply report a failure to the layers higher up - that way you
> won't make matters worse by giving returning data.
You may be right. The main points I think are that
a) the inconsistency be caught and reported and
b) writes be disabled before the propagation of errors buggers
up the whole file system.
^ permalink raw reply
* Re: Help needed recovering from raid failure
From: Mikael Abrahamsson @ 2015-04-27 11:07 UTC (permalink / raw)
To: Peter van Es; +Cc: linux-raid
In-Reply-To: <4D8713B5-39E7-4EE2-898C-35DC0948B4CA@gmail.com>
> I booted Linux from a USB stick (which is on /dev/sdc1 hence changing the numbering),
> in recovery mode. Below is the output of /proc/mdstat and
> mdadm --examine. It looks like somehow the /dev/sdd2 and /dev/sde2 drives took on the
> super block of the /dev/md127 device (my swap file). May that have been done by the boot from
> the Ubuntu USB stick?
Your event counters are strange, 2 drives are showing 18014, and two
drives are showing event count of 26. Two drives show an update time of
the 26:th, two show update time on the 27:th of April. This doesn't make
much sense.
If I were you, I would try to make really really sure that I had unplugged
the drive that first went offline, then I would use "mdadm --assemble
--force <md> <component drives>" to get the array up in degraded mode, I
would then mount it read-only and try to copy the most important
information onto some other disk. After that you can try to add the new
drive you bought and let it re-sync. Most likely this will not work as you
most likely have read errors on at least one other drive. You can use
"smartctl" from "smartmontolls" to verify. Most likely you will have
"pending sectors" which are sectors that can't be read on at least one
other drive.
Also, I recommend you do this:
for x in /sys/block/sd[a-z] ; do
echo 180 > $x/device/timeout
done
echo 4096 > /sys/block/md0/md/stripe_cache_size
Change md0 above to your md-device. This will increase your kernel
timeouts and lessen the risk that drives will be considered dead when they
are only having problems reading a block.
--
Mikael Abrahamsson email: swmike@swm.pp.se
^ permalink raw reply
* Re: <DKIM> Re: Paranoid mode for RAID-1 ?
From: David Brown @ 2015-04-27 10:54 UTC (permalink / raw)
To: Jean-Baptiste Thomas, Pieter De Wit; +Cc: linux-raid
In-Reply-To: <743316986.23005258.1430129889889.JavaMail.zimbra@laposte.net>
On 27/04/15 12:18, Jean-Baptiste Thomas wrote:
> On 2015-04-27 20:45 +1200, Pieter De Wit wrote:
>
>> Sorry for jumping in late - but let's say it does "work" and a
>> drive returns an error, is that data lost ? Or which drive is
>> "right"?
>
> (Assuming that by "returns an error", you mean succeeds but the
> data does not no match what the other(s) returned.)
The alternative interpretation here is that the drive returns an error
message saying it couldn't read the sector - then it's just standard
RAID (get the data from the other disks). So we are looking here at the
extremely rare situation where there is an error but the drive (or
controller) does not detect it.
>
> Let's say there is a setting for how many components must agree.
> If they're not unanimous, read all the other components and look
> for a majority. The components in the minority are flagged
> faulty and the array is degraded but the read succeeds.
>
> If there is no majority, retry a few times. If a majority is
> found, all components which ever were in the minority are
> flagged faulty and the array is degraded but the read succeeds.
>
> If no majority is found, degrade all components, fail the read
> and stop the array. Or whatever is needed to prevent all further
> writes to this array and let the user investigate.
The problem with all of these is that they /might/ be right - but they
/might/ be wrong and make matters worse. Even if you have 3 copies of
the sector, and get two matches and one different, there is no way to
determine that the odd one is wrong. Perhaps a common bus or connector
fault caused the other two to be wrong. Picking the "majority vote" may
decrease your chances of losing data (but may not - it depends on the
cause of the fault), but it certainly does not avoid the worst case
scenario. Perhaps the best choice during normal usage (as distinct from
recovery or rebuild, when the drive is not mounted) is to simply report
a failure to the layers higher up - that way you won't make matters
worse by giving returning data.
Note that the checksum method (used by btrfs and zfs) is different in
that it lets the system know exactly which copy was bad even if the
drive (and bus and controller) think it was good.
^ permalink raw reply
* Re: Paranoid mode for RAID-1 ?
From: Jean-Baptiste Thomas @ 2015-04-27 10:52 UTC (permalink / raw)
To: NeilBrown; +Cc: linux-raid
In-Reply-To: <20150427164924.2aee3831@notabene.brown>
On 2015-04-27 16:49 +1000, NeilBrown wrote:
> On Mon, 27 Apr 2015 08:37:59 +0200 (CEST) Jean-Baptiste Thomas
> <cau2jeaf1honoq@laposte.net> wrote:
>·
> > I'm looking for a way to get MD to operate in a mode in which
> > reading a sector from a RAID-1 device would not succeed until it
> > got matching data from at least two components.
>·
> No, there is no such thing.
Thanks, now I can move on to working on plan B.
> There "should" be no circumstance which would make it worth while.
> A drive may well report an error, but it should *never* report
> incorrect data as though it were correct. That is horribly
> broken.
Isn't it. <g>
> The cost of running in a "safe" mode would be high, and the
> likely benefit extremely low. So it is unlikely that anyone
> would use it for long. So implementing it seems rather
> pointless.
How high would the cost be ?
Seems to me that a 4-component RAID-1 with a 2-component quorum
would incur no more I/O or CPU overhead than, say, a 4-component
RAID-6. Less, in fact, unless parity computation is faster than
memcmp().
Given the choice between that sort of cost and the possibility
of massive data corruption because one drive had a hiccup, I
would not even THINK about running without it.
> That said: if someone were to provide an implementation I
> would certainly consider reviewing it and adding it to md.
Great. Don't think it'll be me, though. :-/
--
To unsubscribe from this list: send the line "unsubscribe linux-raid" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: <DKIM> Re: Paranoid mode for RAID-1 ?
From: Jean-Baptiste Thomas @ 2015-04-27 10:18 UTC (permalink / raw)
To: Pieter De Wit; +Cc: linux-raid
In-Reply-To: <4ADD42F9-407A-4266-A1FC-B92F3D46C36F@insync.za.net>
On 2015-04-27 20:45 +1200, Pieter De Wit wrote:
> Sorry for jumping in late - but let's say it does "work" and a
> drive returns an error, is that data lost ? Or which drive is
> "right"?
(Assuming that by "returns an error", you mean succeeds but the
data does not no match what the other(s) returned.)
Let's say there is a setting for how many components must agree.
If they're not unanimous, read all the other components and look
for a majority. The components in the minority are flagged
faulty and the array is degraded but the read succeeds.
If there is no majority, retry a few times. If a majority is
found, all components which ever were in the minority are
flagged faulty and the array is degraded but the read succeeds.
If no majority is found, degrade all components, fail the read
and stop the array. Or whatever is needed to prevent all further
writes to this array and let the user investigate.
^ permalink raw reply
* Help needed recovering from raid failure
From: Peter van Es @ 2015-04-27 9:35 UTC (permalink / raw)
To: linux-raid
Sorry for the long post...
I am running Ubuntu LTS 14.04.02 Server edition, 64 bits, with 4x 2.0TB drives in a raid-5 array.
The 4th drive was beginning to show read errors. Because it was weekend, I could not go out
and buy a spare 2TB drive to replace the one that was beginning to fail.
I first got a fail event:
This is an automatically generated mail message from mdadm
running on bali
A Fail event had been detected on md device /dev/md/1.
It could be related to component device /dev/sdd2.
Faithfully yours, etc.
P.S. The /proc/mdstat file currently contains the following:
Personalities : [linear] [multipath] [raid0] [raid1] [raid6] [raid5] [raid4] [raid10]
md1 : active raid5 sdc2[2] sdb2[1] sda2[0] sdd2[3](F)
5854290432 blocks super 1.2 level 5, 512k chunk, algorithm 2 [4/3] [UUU_]
md0 : active raid5 sdc1[2] sdd1[3] sdb1[1] sda1[0]
5850624 blocks super 1.2 level 5, 512k chunk, algorithm 2 [4/4] [UUUU]
unused devices: <none>
And then subsequently, around 18 hours later:
This is an automatically generated mail message from mdadm
running on bali
A DegradedArray event had been detected on md device /dev/md/1.
Faithfully yours, etc.
P.S. The /proc/mdstat file currently contains the following:
Personalities : [linear] [multipath] [raid0] [raid1] [raid6] [raid5] [raid4] [raid10]
md1 : active raid5 sdc2[2] sdb2[1] sda2[0] sdd2[3](F)
5854290432 blocks super 1.2 level 5, 512k chunk, algorithm 2 [4/3] [UUU_]
md0 : active raid5 sdc1[2] sdd1[3] sdb1[1] sda1[0]
5850624 blocks super 1.2 level 5, 512k chunk, algorithm 2 [4/4] [UUUU]
unused devices: <none>
The server had taken the array off line at that point.
Needless to say, I can't boot the system anymore as the boot drive is /dev/md0, and GRUB can't
get at it. I do need to recover data (I know, but there's stuf on there I have no backup for--yet).
I booted Linux from a USB stick (which is on /dev/sdc1 hence changing the numbering),
in recovery mode. Below is the output of /proc/mdstat and
mdadm --examine. It looks like somehow the /dev/sdd2 and /dev/sde2 drives took on the
super block of the /dev/md127 device (my swap file). May that have been done by the boot from
the Ubuntu USB stick?
My plan... assemble a degraded array, with /dev/sde2 (the 4th drive, formerly known as /dev/sdd2) not in it.
Because the fail event put the file system in RO mode, I expect /dev/sdd2 (formerly /dev/sdc2) to be ok.
Then insert new 2TB drive in slot 4. Let system resync and recover.
I'm running xfs on the /dev/md1 device.
Questions:
1. is this the wise course of action ?
2. how exactly do I reassemble the array (/etc/mdadm.conf is inaccessible in recovery mode)
3. what command line options do I use exactly from the --examine output below without screwing things up
And help or pointers gratefully accepted
Peter van Es
/proc/mdstat (in recovery)
Personalities : [raid6] [raid5] [raid4] [linear] [multipath] [raid0] [raid1] [raid10]
md126 : inactive sdb2[1](S) sda2[0](S)
3902861312 blocks super 1.2
md127 : active raid5 sde2[5](S) sde1[3] sdb1[1] sda1[0] sdd1[2] sdd2[4](S)
5850624 blocks super 1.2 level 5, 512k chunk, algorithm 2 [4/4] [UUUU]
unused devices: <none>
mdadm --examine /dev/sd[abde]2
/dev/sda2:
Magic : a92b4efc
Version : 1.2
Feature Map : 0x0
Array UUID : 1f28f7bb:7b3ecd41:ca0fa5d1:ccd008df
Name : ubuntu:1 (local to host ubuntu)
Creation Time : Wed Apr 1 22:27:58 2015
Raid Level : raid5
Raid Devices : 4
Avail Dev Size : 3902861312 (1861.03 GiB 1998.26 GB)
Array Size : 5854290432 (5583.09 GiB 5994.79 GB)
Used Dev Size : 3902860288 (1861.03 GiB 1998.26 GB)
Data Offset : 262144 sectors
Super Offset : 8 sectors
State : clean
Device UUID : 713e556d:ca104217:785db68a:d820a57b
Update Time : Sun Apr 26 05:59:13 2015
Checksum : fda151f9 - correct
Events : 18014
Layout : left-symmetric
Chunk Size : 512K
Device Role : Active device 0
Array State : AA.. ('A' == active, '.' == missing)
/dev/sdb2:
Magic : a92b4efc
Version : 1.2
Feature Map : 0x0
Array UUID : 1f28f7bb:7b3ecd41:ca0fa5d1:ccd008df
Name : ubuntu:1 (local to host ubuntu)
Creation Time : Wed Apr 1 22:27:58 2015
Raid Level : raid5
Raid Devices : 4
Avail Dev Size : 3902861312 (1861.03 GiB 1998.26 GB)
Array Size : 5854290432 (5583.09 GiB 5994.79 GB)
Used Dev Size : 3902860288 (1861.03 GiB 1998.26 GB)
Data Offset : 262144 sectors
Super Offset : 8 sectors
State : clean
Device UUID : f1e79609:79b7ac23:55197f70:e8fbfd58
Update Time : Sun Apr 26 05:59:13 2015
Checksum : 696f4e76 - correct
Events : 18014
Layout : left-symmetric
Chunk Size : 512K
Device Role : Active device 1
Array State : AA.. ('A' == active, '.' == missing)
/dev/sdd2:
Magic : a92b4efc
Version : 1.2
Feature Map : 0x0
Array UUID : dbe238a3:c7a528c1:a1b78589:276ecfcf
Name : ubuntu:0 (local to host ubuntu)
Creation Time : Wed Apr 1 22:27:42 2015
Raid Level : raid5
Raid Devices : 4
Avail Dev Size : 3903121408 (1861.15 GiB 1998.40 GB)
Array Size : 5850624 (5.58 GiB 5.99 GB)
Used Dev Size : 3900416 (1904.82 MiB 1997.01 MB)
Data Offset : 2048 sectors
Super Offset : 8 sectors
State : clean
Device UUID : 0f3f2b91:09cbb344:e52c4c4b:722d65c4
Update Time : Mon Apr 27 08:37:15 2015
Checksum : 7e241855 - correct
Events : 26
Layout : left-symmetric
Chunk Size : 512K
Device Role : spare
Array State : AAAA ('A' == active, '.' == missing)
/dev/sde2:
Magic : a92b4efc
Version : 1.2
Feature Map : 0x0
Array UUID : dbe238a3:c7a528c1:a1b78589:276ecfcf
Name : ubuntu:0 (local to host ubuntu)
Creation Time : Wed Apr 1 22:27:42 2015
Raid Level : raid5
Raid Devices : 4
Avail Dev Size : 3903121408 (1861.15 GiB 1998.40 GB)
Array Size : 5850624 (5.58 GiB 5.99 GB)
Used Dev Size : 3900416 (1904.82 MiB 1997.01 MB)
Data Offset : 2048 sectors
Super Offset : 8 sectors
State : clean
Device UUID : cdae3287:91168194:942ba99d:1a85c466
Update Time : Mon Apr 27 08:37:15 2015
Checksum : b8b529f3 - correct
Events : 26
Layout : left-symmetric
Chunk Size : 512K
Device Role : spare
Array State : AAAA ('A' == active, '.' == missing)
^ permalink raw reply
* Re: Paranoid mode for RAID-1 ?
From: Roman Mamedov @ 2015-04-27 9:15 UTC (permalink / raw)
To: Adam Goryachev; +Cc: Mikael Abrahamsson, David Brown, linux-raid
In-Reply-To: <553DF0F1.8060608@websitemanagers.com.au>
[-- Attachment #1: Type: text/plain, Size: 930 bytes --]
On Mon, 27 Apr 2015 18:18:57 +1000
Adam Goryachev <mailinglists@websitemanagers.com.au> wrote:
> Speaking of which, I'm not convinced that we should spend that developer
> time on each and every FS (eg, duplicated effort for btrfs, zfs, and any
> others that do the same)
There isn't "each and every" FS, depending on whom you ask there's just one FS
that you should use. :) The filesystem can also do checksums in a smarter way,
e.g. not checksum the free space. And developers of those filesystems aren't
going to abandon their checksum support or plans to add that just because the
underlying block device MIGHT be an MD RAID array of a new weird type.
However one place where adding corruption resilience to MD can be extremely
interesting and possible almost "for free" (with no disk format change, for
example), is a constant full verification and corruption-healing RAID6.
--
With respect,
Roman
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply
* Re: Paranoid mode for RAID-1 ?
From: Pieter De Wit @ 2015-04-27 8:45 UTC (permalink / raw)
To: linux-raid@vger.kernel.org
In-Reply-To: <972437107.22507366.1430116679975.JavaMail.zimbra@laposte.net>
Sorry for jumping in late - but let's say it does "work" and a drive returns an error, is that data lost ? Or which drive is "right"?
Sent from my iPhone
> On 27/04/2015, at 18:37, Jean-Baptiste Thomas <cau2jeaf1honoq@laposte.net> wrote:
>
> I'm looking for a way to get MD to operate in a mode in which
> reading a sector from a RAID-1 device would not succeed until it
> got matching data from at least two components.
>
> Recent experience[1] suggests that a transient problem in one
> disk can completely hose a four way RAID-1 array, which is
> otherwise supposed to still be fine after a triple total
> failure. I'm hoping that a paranoid mode would have prevented
> that.
>
> If there is such a thing, PLEASE tell me. If not, please tell me
> so I don't waste any more time looking for it.
>
> [1] "Massive RAID-1 desync"
> http://www.spinics.net/lists/raid/msg48681.html
> http://marc.info/?l=linux-raid&m=143003812706563&w=2
> --
> To unsubscribe from this list: send the line "unsubscribe linux-raid" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: Paranoid mode for RAID-1 ? MD-RAID checksums
From: Pasi Kärkkäinen @ 2015-04-27 8:34 UTC (permalink / raw)
To: Adam Goryachev; +Cc: Mikael Abrahamsson, David Brown, linux-raid
In-Reply-To: <553DF0F1.8060608@websitemanagers.com.au>
On Mon, Apr 27, 2015 at 06:18:57PM +1000, Adam Goryachev wrote:
> On 27/04/15 17:35, Mikael Abrahamsson wrote:
> >On Mon, 27 Apr 2015, David Brown wrote:
> >
> >>btrfs has data checksums like that. Like Neil, I question the
> >>necessity for harddisks, but such checksums are lower cost than
> >>reading the data twice from two disks (as they are stored as
> >>part of the metadata that you already read), and can offer some
> >>protection against serious hardware problems. (Checksums like
> >>this cannot easily be implemented in a transparent block device
> >>such as md raid - it is more practical to have them as part of
> >>the filesystem, as done with btrfs.)
> >
> >Only way I can imagine this being done would be for instance to
> >add a 4KiB block for every 128KiB chunk or something like that,
> >and perhaps have a smaller checksum for each 4KiB block within
> >that 128KiB chunk.
> >
> >I doubt anyone would be interested in putting efforts into
> >creating this though as it would have "interesting" performance
> >drawbacks, and that work is probably better spent by making sure
> >that btrfs and/or zfs gets more development/testing than it is to
> >put that effort into md. I personally prefer md to be fairly
> >"simple" so we have as few bugs as possible in it, I'd say that md
> >generally works and the number of developers working heroically on
> >its current incarnation is barely enough to make sure that the
> >codebase works as well as it must considering the critical
> >function it serves for a lot of us.
> >
> >This has been discussed before and nobody has shown interest in
> >actually developing code for it, so we're still at the feature
> >request and "brainstorming about design" state, and without actual
> >coder(s) willing to actually implement, it's not going to get
> >further than this stage.
> >
> Speaking of which, I'm not convinced that we should spend that
> developer time on each and every FS (eg, duplicated effort for
> btrfs, zfs, and any others that do the same). It also means you must
> remove MD Raid, to allow the FS to directly access each of the
> underlying devices. Obviously, there are advantages in both methods.
>
Yeah, having checksums support in MD-RAID would be very welcome!
> As you and others said, without someone willing to implement/write
> this feature, then it isn't going to happen.
>
Yeah this is the problem, someone actually needs to do it :)
There actually IS a proof-of-concept checksums support for MD-RAID,
but it was never upstreamed, and it was a quick and 'naive' implementation.
http://pages.cs.wisc.edu/~bpkroth/cs736/md-checksums/md-checksums-paper.pdf
http://pages.cs.wisc.edu/~bpkroth/cs736/md-checksums/
> Regards,
> Adam
>
-- Pasi
^ permalink raw reply
* Re: Paranoid mode for RAID-1 ?
From: Adam Goryachev @ 2015-04-27 8:18 UTC (permalink / raw)
To: Mikael Abrahamsson, David Brown; +Cc: linux-raid
In-Reply-To: <alpine.DEB.2.02.1504270925480.16871@uplift.swm.pp.se>
On 27/04/15 17:35, Mikael Abrahamsson wrote:
> On Mon, 27 Apr 2015, David Brown wrote:
>
>> btrfs has data checksums like that. Like Neil, I question the
>> necessity for harddisks, but such checksums are lower cost than
>> reading the data twice from two disks (as they are stored as part of
>> the metadata that you already read), and can offer some protection
>> against serious hardware problems. (Checksums like this cannot
>> easily be implemented in a transparent block device such as md raid -
>> it is more practical to have them as part of the filesystem, as done
>> with btrfs.)
>
> Only way I can imagine this being done would be for instance to add a
> 4KiB block for every 128KiB chunk or something like that, and perhaps
> have a smaller checksum for each 4KiB block within that 128KiB chunk.
>
> I doubt anyone would be interested in putting efforts into creating
> this though as it would have "interesting" performance drawbacks, and
> that work is probably better spent by making sure that btrfs and/or
> zfs gets more development/testing than it is to put that effort into
> md. I personally prefer md to be fairly "simple" so we have as few
> bugs as possible in it, I'd say that md generally works and the number
> of developers working heroically on its current incarnation is barely
> enough to make sure that the codebase works as well as it must
> considering the critical function it serves for a lot of us.
>
> This has been discussed before and nobody has shown interest in
> actually developing code for it, so we're still at the feature request
> and "brainstorming about design" state, and without actual coder(s)
> willing to actually implement, it's not going to get further than this
> stage.
>
Speaking of which, I'm not convinced that we should spend that developer
time on each and every FS (eg, duplicated effort for btrfs, zfs, and any
others that do the same). It also means you must remove MD Raid, to
allow the FS to directly access each of the underlying devices.
Obviously, there are advantages in both methods.
As you and others said, without someone willing to implement/write this
feature, then it isn't going to happen.
Regards,
Adam
--
Adam Goryachev Website Managers www.websitemanagers.com.au
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox