Linux RAID subsystem development
 help / color / mirror / Atom feed
* Re: Fwd: Installing Linux directly onto RAID6 Array...........
From: Mikael Abrahamsson @ 2015-05-26  8:06 UTC (permalink / raw)
  To: Another Sillyname; +Cc: linux-raid
In-Reply-To: <CAOS+5GEBJ8dxF4s91dGmF7jx36LyNnu40UQZjLAmK2xVhqLAHw@mail.gmail.com>

On Tue, 26 May 2015, Another Sillyname wrote:

> Not bothered about raiding the swap thanks, my way will suffice as it
> gives me maximum flexibility and resilience......I'm not really
> performance driven on this project.

I don't see how running swap natively on the drives gives "maximum 
resilience". Higher resilience is gained by running raid1 for swap.

-- 
Mikael Abrahamsson    email: swmike@swm.pp.se

^ permalink raw reply

* Re: Fwd: Installing Linux directly onto RAID6 Array...........
From: Another Sillyname @ 2015-05-26  7:08 UTC (permalink / raw)
  To: linux-raid
In-Reply-To: <5563AE50.4090806@youngman.org.uk>

Not bothered about raiding the swap thanks, my way will suffice as it
gives me maximum flexibility and resilience......I'm not really
performance driven on this project.

On 26 May 2015 at 00:20, Wols Lists <antlists@youngman.org.uk> wrote:
> On 25/05/15 22:03, Another Sillyname wrote:
>> My workaround, found on the web and re hashed, is to instead create a
>> 4GB swap partition on each drive then using the following script
>> automount the swaps at boot time using a systemd script.
>>
>> #!/bin/bash
>>
>> #  Script for service that autodetects and starts swap partitions
>>
>> for f in $(fdisk -l | grep "Linux swap" | sort | cut -d' ' -f1 | tr
>> '\n' ' '); do swapon $f; done
>>
>> as it only 'finds' swaps on active partitions it prevents boot
>> problems in the case of a dead drive.
>
> Do you want linux to raid 0 your swap for you? ime your script will use
> just one disk for swap until it overflows before bringing the next into
> use, etc etc.
>
> If you want swap striped, I think you'll need to use "swapon -p=1" or
> whatever number. Otherwise I think you'll find all your swaps are
> assigned different priorities. Of course, that may be what you want,
> depending on how your disks are laid out.
>
> Cheers,
> Wol

^ permalink raw reply

* Re: [PATCH] Fix reversed logic in drivers/md/md.c
From: NeilBrown @ 2015-05-26  4:58 UTC (permalink / raw)
  To: Eddie Kovsky; +Cc: linux-raid, linux-kernel
In-Reply-To: <20150526043624.GA24890@athena>

[-- Attachment #1: Type: text/plain, Size: 1547 bytes --]

On Mon, 25 May 2015 22:36:24 -0600 Eddie Kovsky <ewk@edkovsky.org> wrote:

> Fixes the following compiler warning in next-20150525 using gcc 5.1.0:
> 
> drivers/md/md.c: In function ‘update_array_info’:
> drivers/md/md.c:6394:26: warning: logical not is only applied to the
> left hand side of comparison [-Wlogical-not-parentheses]
>       !mddev->persistent  != info->not_persistent||
> 
> Signed-off-by: Eddie Kovsky <ewk@edkovsky.org>
> ---
>  drivers/md/md.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/md/md.c b/drivers/md/md.c
> index eb27b2a74492..b0f98b5b8985 100644
> --- a/drivers/md/md.c
> +++ b/drivers/md/md.c
> @@ -6391,7 +6391,7 @@ static int update_array_info(struct mddev *mddev, mdu_array_info_t *info)
>  	    mddev->ctime         != info->ctime         ||
>  	    mddev->level         != info->level         ||
>  /*	    mddev->layout        != info->layout        || */
> -	    !mddev->persistent	 != info->not_persistent||
> +	    mddev->persistent	 == info->not_persistent||
>  	    mddev->chunk_sectors != info->chunk_size >> 9 ||
>  	    /* ignore bottom 8 bits of state, and allow SB_BITMAP_PRESENT to change */
>  	    ((state^info->state) & 0xfffffe00)

Thanks... but I'd rather gcc was fixed. :-(  There is nothing wrong with the
code and it does not deserve a warning.

I really like the column of "!=" and I don't want to change that.

I *might* be able to access
    (!mddev->persistent)   !=  info->not_persistent

Thanks,
NeilBrown

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 811 bytes --]

^ permalink raw reply

* [PATCH] Fix reversed logic in drivers/md/md.c
From: Eddie Kovsky @ 2015-05-26  4:36 UTC (permalink / raw)
  To: neilb; +Cc: linux-raid, linux-kernel

Fixes the following compiler warning in next-20150525 using gcc 5.1.0:

drivers/md/md.c: In function ‘update_array_info’:
drivers/md/md.c:6394:26: warning: logical not is only applied to the
left hand side of comparison [-Wlogical-not-parentheses]
      !mddev->persistent  != info->not_persistent||

Signed-off-by: Eddie Kovsky <ewk@edkovsky.org>
---
 drivers/md/md.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/md/md.c b/drivers/md/md.c
index eb27b2a74492..b0f98b5b8985 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -6391,7 +6391,7 @@ static int update_array_info(struct mddev *mddev, mdu_array_info_t *info)
 	    mddev->ctime         != info->ctime         ||
 	    mddev->level         != info->level         ||
 /*	    mddev->layout        != info->layout        || */
-	    !mddev->persistent	 != info->not_persistent||
+	    mddev->persistent	 == info->not_persistent||
 	    mddev->chunk_sectors != info->chunk_size >> 9 ||
 	    /* ignore bottom 8 bits of state, and allow SB_BITMAP_PRESENT to change */
 	    ((state^info->state) & 0xfffffe00)
-- 
2.4.1

--
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 related

* Re: Fwd: Installing Linux directly onto RAID6 Array...........
From: Wols Lists @ 2015-05-25 23:20 UTC (permalink / raw)
  To: Another Sillyname, linux-raid
In-Reply-To: <CAOS+5GHz-4J_n7UAU1xVLWp3h7CRTuuSHdmP9rbL6=8=qx30CQ@mail.gmail.com>

On 25/05/15 22:03, Another Sillyname wrote:
> My workaround, found on the web and re hashed, is to instead create a
> 4GB swap partition on each drive then using the following script
> automount the swaps at boot time using a systemd script.
> 
> #!/bin/bash
> 
> #  Script for service that autodetects and starts swap partitions
> 
> for f in $(fdisk -l | grep "Linux swap" | sort | cut -d' ' -f1 | tr
> '\n' ' '); do swapon $f; done
> 
> as it only 'finds' swaps on active partitions it prevents boot
> problems in the case of a dead drive.

Do you want linux to raid 0 your swap for you? ime your script will use
just one disk for swap until it overflows before bringing the next into
use, etc etc.

If you want swap striped, I think you'll need to use "swapon -p=1" or
whatever number. Otherwise I think you'll find all your swaps are
assigned different priorities. Of course, that may be what you want,
depending on how your disks are laid out.

Cheers,
Wol

^ permalink raw reply

* Re: Problems with bdev_write_page().
From: Charles Bertsch @ 2015-05-25 21:19 UTC (permalink / raw)
  To: NeilBrown; +Cc: Matthew Wilcox, linux-raid, lkml, BertschC@acm.org
In-Reply-To: <Uv2G1q00k0LXzhv01v2JnY>

[-- Attachment #1: Type: text/plain, Size: 405 bytes --]

On 05/17/2015 12:02 AM, NeilBrown wrote:
>
>
> Hi Matthew,
>   I've just been looking at bdev_write_page().
> You can read about why here:
>
>    http://marc.info/?t=142984068300001&r=1&w=2
....
>
> Can you propose a fix for Charles, who can trigger this bug and nicely
> bisected it for us - thanks Charles!!!
>
This problem still occurs with 4.1.0-rc5 -- three stack traces attached.

Charles Bertsch



[-- Attachment #2: linprob.stktrace.0525a.4.1-rc5.txt --]
[-- Type: text/plain, Size: 10612 bytes --]

# date
Mon May 25 13:23:04 MST 2015
# 
# cat /proc/version
Linux version 4.1.0-rc5 (cbertsch@haxe) (gcc version 4.8.2 (GCC) ) #1 SMP Mon May 25 13:00:21 MST 2015
# 
# cat /etc/zerv*
1.1.10x 2015-May-25 13:07
# 
# cat /proc/partitions
major minor  #blocks  name

   1        0      81920 ram0
   1        1      81920 ram1
   1        2      81920 ram2
   1        3      81920 ram3
   3        0  156290904 hda
   8        0  312571224 sda
   8       16     126976 sdb
   8       17     126852 sdb1
   8       48  156290904 sdd
   8       49  156289927 sdd1
   8       32 2930266584 sdc
   8       33 2930265591 sdc1
   8       64 2930266584 sde
   9        0 3086293374 md0
# 
# df
Filesystem     1K-blocks   Used Available Use% Mounted on
/dev/root          35328  35328         0 100% /
devtmpfs         1002560      0   1002560   0% /dev
/dev/ram1           7745    347      7398   5% /hd
tmpfs            1021248      0   1021248   0% /dev/shm
/dev/sdb1         122708 107784     14924  88% /flash
# 
# cat /proc/mdstat
Personalities : [linear] 
md0 : active linear sdc1[0] sdd1[1]
      3086293374 blocks super 1.2 0k rounding
      
unused devices: <none>
# 
# 
# dd bs=16384 if=/dev/zero of=/dev/md0 count=32M &
# 
# monirw 10 md0 sdc sdd
/sbin/monirw sec=10 file=/proc/diskstats itemset=md0 sdc sdd
md0,41,112499,0,sdc,122,112492,1,sdd,68,0,0,1432585456,2015-05-25,13:24:16
md0,0,133651,0,sdc,0,133657,0,sdd,0,0,0,1432585466,2015-05-25,13:24:26
md0,0,132249,0,sdc,0,132243,1,sdd,0,0,0,1432585476,2015-05-25,13:24:36
md0,0,131897,0,sdc,0,131897,1,sdd,0,0,0,1432585486,2015-05-25,13:24:46
md0,0,131974,0,sdc,0,131974,1,sdd,0,0,0,1432585497,2015-05-25,13:24:57
md0,0,132486,0,sdc,0,132486,1,sdd,0,0,0,1432585507,2015-05-25,13:25:07
md0,0,131968,0,sdc,0,131968,1,sdd,0,0,0,1432585517,2015-05-25,13:25:17
md0,0,132051,0,sdc,0,132051,1,sdd,0,0,0,1432585527,2015-05-25,13:25:27
md0,0,131788,0,sdc,0,131788,1,sdd,0,0,0,1432585537,2015-05-25,13:25:37
md0,0,131404,0,sdc,0,131404,1,sdd,0,0,0,1432585547,2015-05-25,13:25:47
md0,0,131968,0,sdc,0,131968,1,sdd,0,0,0,1432585557,2015-05-25,13:25:57
md0,0,131705,0,sdc,0,131705,1,sdd,0,0,0,1432585567,2015-05-25,13:26:07
md0,0,131552,0,sdc,0,131552,1,sdd,0,0,0,1432585577,2015-05-25,13:26:17
md0,0,131680,0,sdc,0,131680,1,sdd,0,0,0,1432585587,2015-05-25,13:26:27
md0,0,131328,0,sdc,0,131328,1,sdd,0,0,0,1432585597,2015-05-25,13:26:37
md0,0,131532,0,sdc,0,131532,1,sdd,0,0,0,1432585607,2015-05-25,13:26:47
md0,0,131577,0,sdc,0,131577,1,sdd,0,0,0,1432585617,2015-05-25,13:26:57
md0,0,131289,0,sdc,0,131296,0,sdd,0,0,0,1432585627,2015-05-25,13:27:07
md0,0,131398,0,sdc,0,131398,0,sdd,0,0,0,1432585637,2015-05-25,13:27:17
md0,0,131200,0,sdc,0,131193,1,sdd,0,0,0,1432585647,2015-05-25,13:27:27
md0,0,131276,0,sdc,0,131276,1,sdd,0,0,0,1432585658,2015-05-25,13:27:38
md0,0,131360,0,sdc,0,131366,0,sdd,0,0,0,1432585668,2015-05-25,13:27:48
md0,0,131142,0,sdc,0,131136,1,sdd,0,0,0,1432585678,2015-05-25,13:27:58
md0,0,131379,0,sdc,0,131379,1,sdd,0,0,0,1432585688,2015-05-25,13:28:08
md0,0,131571,0,sdc,0,131571,1,sdd,0,0,0,1432585698,2015-05-25,13:28:18
md0,0,131328,0,sdc,0,131328,1,sdd,0,0,0,1432585708,2015-05-25,13:28:28
md0,0,131136,0,sdc,0,131136,1,sdd,0,0,0,1432585718,2015-05-25,13:28:38
md0,0,130924,0,sdc,0,130924,1,sdd,0,0,0,1432585728,2015-05-25,13:28:48
md0,0,131315,0,sdc,0,131315,1,sdd,0,0,0,1432585738,2015-05-25,13:28:58
md0,0,131091,0,sdc,0,131091,1,sdd,0,0,0,1432585748,2015-05-25,13:29:08
md0,0,131008,0,sdc,0,131008,1,sdd,0,0,0,1432585758,2015-05-25,13:29:18
md0,0,130963,0,sdc,0,130963,1,sdd,0,0,0,1432585768,2015-05-25,13:29:28
md0,0,130950,0,sdc,0,130950,1,sdd,0,0,0,1432585778,2015-05-25,13:29:38
md0,0,130950,0,sdc,0,130950,1,sdd,0,0,0,1432585788,2015-05-25,13:29:48
md0,0,130636,0,sdc,0,130636,1,sdd,0,0,0,1432585798,2015-05-25,13:29:58
------------[ cut here ]------------
kernel BUG at /home/cbertsch/NZdev/nz218/othersrc/linux-git/fs/buffer.c:3220!
invalid opcode: 0000 [#1] SMP 
Modules linked in: linear md_mod ipv6 nfsd auth_rpcgss oid_registry exportfs lockd grace sunrpc af_packet sd_mod ide_gd_mod ata_generic pata_amd sata_nv libata i2c_dev amd74xx k8temp ide_pci_generic forcedeth ide_core skge ehci_pci ohci_pci ehci_hcd ohci_hcd i2c_nforce2 rtc_cmos
CPU: 0 PID: 1162 Comm: kworker/u8:0 Not tainted 4.1.0-rc5 #1
Hardware name: BIOSTAR Group N61PB-M2S/N61PB-M2S, BIOS 6.00 PG 02/27/2009
Workqueue: writeback bdi_writeback_workfn (flush-1:1)
task: ffff88007ea7a890 ti: ffff88000f384000 task.ti: ffff88000f384000
RIP: 0010:[<ffffffff8112109f>]  [<ffffffff8112109f>] try_to_free_buffers+0xaf/0xc0
RSP: 0018:ffff88000f3878f8  EFLAGS: 00010246
RAX: 001000000000086c RBX: ffffea00019e59a0 RCX: ffff88007a352160
RDX: 0000000000000004 RSI: 0000000000000001 RDI: ffffea00019e59a0
RBP: ffff88007d4818b0 R08: 0000000000000000 R09: 0000000000017448
R10: ffff88007cc47600 R11: 000000000000001a R12: ffffea00019e59a0
R13: 0000000000001000 R14: ffff88000f387b78 R15: 0000000000001034
FS:  00007f427c084740(0000) GS:ffff88007ca00000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
CR2: 00007ff515a600a8 CR3: 000000007eb3f000 CR4: 00000000000006f0
Stack:
 0000000000000000 0000000000000000 0000000000000000 ffff88007a003040
 ffffea00019e59a0 ffffffff8112a277 0000000400000000 ffff880000000004
 0000000000000004 0000000000000000 ffff88000f387c50 ffff88007d4818b0
Call Trace:
 [<ffffffff8112a277>] ? __mpage_writepage+0x4f7/0x5f0
 [<ffffffff810e0234>] ? rmap_walk+0xe4/0x230
 [<ffffffff810e04e3>] ? page_mkclean+0x63/0x80
 [<ffffffff810df250>] ? page_referenced_one+0xb0/0xb0
 [<ffffffff8111903a>] ? inode_to_bdi+0x1a/0x60
 [<ffffffff810bf51c>] ? write_cache_pages+0x1cc/0x390
 [<ffffffff81129d80>] ? clean_buffers+0x60/0x60
 [<ffffffff8116d1f0>] ? ext2_get_blocks+0x990/0x990
 [<ffffffff81129ce3>] ? mpage_writepages+0x53/0x90
 [<ffffffff8116d1f0>] ? ext2_get_blocks+0x990/0x990
 [<ffffffff8111933a>] ? __writeback_single_inode+0x2a/0x180
 [<ffffffff811197ab>] ? writeback_sb_inodes+0x1ab/0x3f0
 [<ffffffff81119a7e>] ? __writeback_inodes_wb+0x8e/0xc0
 [<ffffffff81119c7b>] ? wb_writeback+0x1cb/0x1e0
 [<ffffffff8110c005>] ? get_nr_inodes+0x45/0x60
 [<ffffffff810bf98d>] ? global_dirty_limits+0xd/0xf0
 [<ffffffff8111a1f8>] ? bdi_writeback_workfn+0x158/0x340
 [<ffffffff8105ab44>] ? process_one_work+0x124/0x320
 [<ffffffff8105ae56>] ? worker_thread+0x116/0x460
 [<ffffffff8105ad40>] ? process_one_work+0x320/0x320
 [<ffffffff81060255>] ? kthread+0xc5/0xe0
 [<ffffffff81060190>] ? kthread_create_on_node+0x170/0x170
 [<ffffffff813efc12>] ? ret_from_fork+0x42/0x70
 [<ffffffff81060190>] ? kthread_create_on_node+0x170/0x170
Code: 04 72 09 eb c6 0f 1f 80 00 00 00 00 48 89 ee 48 89 df e8 05 e1 f9 ff eb b2 0f 1f 00 48 8d 74 24 08 e8 d6 ea ff ff 41 89 c4 eb a5 <0f> 0b 66 66 66 66 66 66 2e 0f 1f 84 00 00 00 00 00 48 8b 07 53 
RIP  [<ffffffff8112109f>] try_to_free_buffers+0xaf/0xc0
 RSP <ffff88000f3878f8>
---[ end trace 83b8fe6acbe88f4a ]---
BUG: unable to handle kernel paging request at ffffffffffffffd8
IP: [<ffffffff81060747>] kthread_data+0x7/0x10
PGD 160c067 PUD 160e067 PMD 0 
Oops: 0000 [#2] SMP 
Modules linked in: linear md_mod ipv6 nfsd auth_rpcgss oid_registry exportfs lockd grace sunrpc af_packet sd_mod ide_gd_mod ata_generic pata_amd sata_nv libata i2c_dev amd74xx k8temp ide_pci_generic forcedeth ide_core skge ehci_pci ohci_pci ehci_hcd ohci_hcd i2c_nforce2 rtc_cmos
CPU: 0 PID: 1162 Comm: kworker/u8:0 Tainted: G      D         4.1.0-rc5 #1
Hardware name: BIOSTAR Group N61PB-M2S/N61PB-M2S, BIOS 6.00 PG 02/27/2009
task: ffff88007ea7a890 ti: ffff88000f384000 task.ti: ffff88000f384000
RIP: 0010:[<ffffffff81060747>]  [<ffffffff81060747>] kthread_data+0x7/0x10
RSP: 0018:ffff88000f387680  EFLAGS: 00010002
RAX: 0000000000000000 RBX: 0000000000000000 RCX: 00000012fcbcb79f
RDX: ffffffffffd23940 RSI: 0000000000000000 RDI: ffff88007ea7a890
RBP: ffff88007ea7a890 R08: ffff88007eaa7550 R09: 0000000000000001
R10: ffffffff81904f04 R11: 000000000000001a R12: ffff88007ea7b078
R13: 0000000000000000 R14: 0000000000014480 R15: 0000000000000000
FS:  00007f427c084740(0000) GS:ffff88007ca00000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
CR2: 0000000000000028 CR3: 000000007eb3f000 CR4: 00000000000006f0
Stack:
 ffffffff8105b8c8 ffff88007ca14480 ffffffff813ec6e3 ffff88007ea7a890
 0000000000000000 ffff88007ea7a890 ffff88000f388000 ffff88007ea7af70
 ffff88000f387728 0000000000000000 ffff88007c3aab30 ffff88007ea7a890
Call Trace:
 [<ffffffff8105b8c8>] ? wq_worker_sleeping+0x8/0x90
 [<ffffffff813ec6e3>] ? __schedule+0x343/0x750
 [<ffffffff813ecb1a>] ? schedule+0x2a/0x80
 [<ffffffff81048384>] ? do_exit+0x664/0xa80
 [<ffffffff81005bc7>] ? oops_end+0x67/0xa0
 [<ffffffff81002c8b>] ? do_error_trap+0x6b/0xd0
 [<ffffffff8112109f>] ? try_to_free_buffers+0xaf/0xc0
 [<ffffffff81230b0c>] ? percpu_counter_set+0x5c/0x80
 [<ffffffff813f0a68>] ? invalid_op+0x18/0x20
 [<ffffffff8112109f>] ? try_to_free_buffers+0xaf/0xc0
 [<ffffffff81123bb8>] ? bdev_write_page+0x68/0xa0
 [<ffffffff8112a277>] ? __mpage_writepage+0x4f7/0x5f0
 [<ffffffff810e0234>] ? rmap_walk+0xe4/0x230
 [<ffffffff810e04e3>] ? page_mkclean+0x63/0x80
 [<ffffffff810df250>] ? page_referenced_one+0xb0/0xb0
 [<ffffffff8111903a>] ? inode_to_bdi+0x1a/0x60
 [<ffffffff810bf51c>] ? write_cache_pages+0x1cc/0x390
 [<ffffffff81129d80>] ? clean_buffers+0x60/0x60
 [<ffffffff8116d1f0>] ? ext2_get_blocks+0x990/0x990
 [<ffffffff81129ce3>] ? mpage_writepages+0x53/0x90
 [<ffffffff8116d1f0>] ? ext2_get_blocks+0x990/0x990
 [<ffffffff8111933a>] ? __writeback_single_inode+0x2a/0x180
 [<ffffffff811197ab>] ? writeback_sb_inodes+0x1ab/0x3f0
 [<ffffffff81119a7e>] ? __writeback_inodes_wb+0x8e/0xc0
 [<ffffffff81119c7b>] ? wb_writeback+0x1cb/0x1e0
 [<ffffffff8110c005>] ? get_nr_inodes+0x45/0x60
 [<ffffffff810bf98d>] ? global_dirty_limits+0xd/0xf0
 [<ffffffff8111a1f8>] ? bdi_writeback_workfn+0x158/0x340
 [<ffffffff8105ab44>] ? process_one_work+0x124/0x320
 [<ffffffff8105ae56>] ? worker_thread+0x116/0x460
 [<ffffffff8105ad40>] ? process_one_work+0x320/0x320
 [<ffffffff81060255>] ? kthread+0xc5/0xe0
 [<ffffffff81060190>] ? kthread_create_on_node+0x170/0x170
 [<ffffffff813efc12>] ? ret_from_fork+0x42/0x70
 [<ffffffff81060190>] ? kthread_create_on_node+0x170/0x170
Code: 00 00 00 00 65 48 8b 04 25 00 a9 00 00 48 8b 80 90 07 00 00 48 8b 40 c8 48 c1 e8 02 83 e0 01 c3 0f 1f 40 00 48 8b 87 90 07 00 00 <48> 8b 40 d8 c3 0f 1f 40 00 48 83 ec 18 48 8b b7 90 07 00 00 ba 
RIP  [<ffffffff81060747>] kthread_data+0x7/0x10
 RSP <ffff88000f387680>
CR2: ffffffffffffffd8
---[ end trace 83b8fe6acbe88f4b ]---
Fixing recursive fault but reboot is needed!

[-- Attachment #3: linprob.stktrace.0525b.4.1-rc5.txt --]
[-- Type: text/plain, Size: 10813 bytes --]


# 
# date
Mon May 25 13:35:21 MST 2015
# 
# cat /proc/version
Linux version 4.1.0-rc5 (cbertsch@haxe) (gcc version 4.8.2 (GCC) ) #1 SMP Mon May 25 13:00:21 MST 2015
# 
# cat /etc/zerv*
1.1.10x 2015-May-25 13:07
# 
# cat /proc/partitions
major minor  #blocks  name

   1        0      81920 ram0
   1        1      81920 ram1
   1        2      81920 ram2
   1        3      81920 ram3
   3        0  156290904 hda
   8        0  312571224 sda
   8       16     126976 sdb
   8       17     126852 sdb1
   8       48  156290904 sdd
   8       49  156289927 sdd1
   8       32 2930266584 sdc
   8       33 2930265591 sdc1
   8       64 2930266584 sde
   9        0 3086293374 md0
# 
# df
Filesystem     1K-blocks   Used Available Use% Mounted on
/dev/root          35328  35328         0 100% /
devtmpfs         1002560      0   1002560   0% /dev
/dev/ram1           7745    343      7402   5% /hd
tmpfs            1021248      0   1021248   0% /dev/shm
/dev/sdb1         122708 107784     14924  88% /flash
# 
# cat /proc/mdstat
Personalities : [linear] 
md0 : active linear sdc1[0] sdd1[1]
      3086293374 blocks super 1.2 0k rounding
      
unused devices: <none>
# 
# dd bs=16384 if=/dev/zero of=/dev/md0 count=32M &
# 
# monirw 10 md0 sdc sdd
/sbin/monirw sec=10 file=/proc/diskstats itemset=md0 sdc sdd
md0,41,102201,0,sdc,121,102201,0,sdd,68,0,0,1432586189,2015-05-25,13:36:29
md0,0,131808,0,sdc,0,131801,1,sdd,0,0,0,1432586199,2015-05-25,13:36:39
md0,0,131980,0,sdc,0,131987,0,sdd,0,0,0,1432586209,2015-05-25,13:36:49
md0,0,131795,0,sdc,0,131788,1,sdd,0,0,0,1432586219,2015-05-25,13:36:59
md0,0,131206,0,sdc,0,131206,1,sdd,0,0,0,1432586229,2015-05-25,13:37:09
md0,0,131315,0,sdc,0,131315,1,sdd,0,0,0,1432586239,2015-05-25,13:37:19
md0,0,131238,0,sdc,0,131238,1,sdd,0,0,0,1432586250,2015-05-25,13:37:30
md0,0,131404,0,sdc,0,131404,1,sdd,0,0,0,1432586260,2015-05-25,13:37:40
md0,0,130828,0,sdc,0,130828,1,sdd,0,0,0,1432586270,2015-05-25,13:37:50
md0,0,130611,0,sdc,0,130611,1,sdd,0,0,0,1432586280,2015-05-25,13:38:00
md0,0,130694,0,sdc,0,130694,1,sdd,0,0,0,1432586290,2015-05-25,13:38:10
md0,0,130560,0,sdc,0,130560,1,sdd,0,0,0,1432586300,2015-05-25,13:38:20
md0,0,130329,0,sdc,0,130329,1,sdd,0,0,0,1432586310,2015-05-25,13:38:30
md0,0,130579,0,sdc,0,130579,1,sdd,0,0,0,1432586320,2015-05-25,13:38:40
md0,0,130195,0,sdc,0,130195,1,sdd,0,0,0,1432586330,2015-05-25,13:38:50
md0,0,130566,0,sdc,0,130566,1,sdd,0,0,0,1432586340,2015-05-25,13:39:00
md0,0,130201,0,sdc,0,130201,1,sdd,0,0,0,1432586350,2015-05-25,13:39:10
md0,0,130278,0,sdc,0,130284,0,sdd,0,0,0,1432586360,2015-05-25,13:39:20
md0,0,130675,0,sdc,0,130668,1,sdd,0,0,0,1432586370,2015-05-25,13:39:30
md0,0,130636,0,sdc,0,130636,1,sdd,0,0,0,1432586380,2015-05-25,13:39:40
md0,0,130220,0,sdc,0,130220,1,sdd,0,0,0,1432586390,2015-05-25,13:39:50
md0,0,130201,0,sdc,0,130201,1,sdd,0,0,0,1432586400,2015-05-25,13:40:00
md0,0,130310,0,sdc,0,130310,1,sdd,0,0,0,1432586411,2015-05-25,13:40:11
md0,0,130464,0,sdc,0,130464,1,sdd,0,0,0,1432586421,2015-05-25,13:40:21
md0,0,129734,0,sdc,0,129734,1,sdd,0,0,0,1432586431,2015-05-25,13:40:31
md0,0,130214,0,sdc,0,130220,0,sdd,0,0,0,1432586441,2015-05-25,13:40:41
md0,0,130163,0,sdc,0,130156,1,sdd,0,0,0,1432586451,2015-05-25,13:40:51
md0,0,130252,0,sdc,0,130252,1,sdd,0,0,0,1432586461,2015-05-25,13:41:01
md0,0,129792,0,sdc,0,129792,1,sdd,0,0,0,1432586471,2015-05-25,13:41:11
md0,0,130227,0,sdc,0,130227,1,sdd,0,0,0,1432586481,2015-05-25,13:41:21
md0,0,130144,0,sdc,0,130144,1,sdd,0,0,0,1432586491,2015-05-25,13:41:31
md0,0,129984,0,sdc,0,129984,1,sdd,0,0,0,1432586501,2015-05-25,13:41:41
md0,0,129689,0,sdc,0,129689,1,sdd,0,0,0,1432586511,2015-05-25,13:41:51
md0,0,130022,0,sdc,0,130022,1,sdd,0,0,0,1432586521,2015-05-25,13:42:01
md0,0,129830,0,sdc,0,129830,1,sdd,0,0,0,1432586531,2015-05-25,13:42:11
------------[ cut here ]------------
kernel BUG at /home/cbertsch/NZdev/nz218/othersrc/linux-git/fs/buffer.c:3220!
invalid opcode: 0000 [#1] SMP 
Modules linked in: linear md_mod ipv6 nfsd auth_rpcgss oid_registry exportfs lockd grace sunrpc af_packet sd_mod ide_gd_mod ata_generic pata_amd sata_nv libata i2c_dev amd74xx k8temp ide_pci_generic forcedeth ide_core skge ehci_pci ohci_pci ehci_hcd ohci_hcd i2c_nforce2 rtc_cmos
CPU: 0 PID: 139 Comm: kworker/u8:2 Not tainted 4.1.0-rc5 #1
Hardware name: BIOSTAR Group N61PB-M2S/N61PB-M2S, BIOS 6.00 PG 02/27/2009
Workqueue: writeback bdi_writeback_workfn (flush-1:1)
task: ffff88007975c110 ti: ffff880077498000 task.ti: ffff880077498000
RIP: 0010:[<ffffffff8112109f>]  [<ffffffff8112109f>] try_to_free_buffers+0xaf/0xc0
RSP: 0018:ffff88007749b8f8  EFLAGS: 00010246
RAX: 001000000000086c RBX: ffffea0001b3f090 RCX: ffff880073e0dec8
RDX: 0000000000000004 RSI: 0000000000000001 RDI: ffffea0001b3f090
RBP: ffff88007a309e70 R08: 0000000000000002 R09: 0000000000017448
R10: ffff88007cc47600 R11: 000000000000001a R12: ffffea0001b3f090
R13: 0000000000001000 R14: ffff88007749bb78 R15: 0000000000002838
FS:  00007fa82f7e6740(0000) GS:ffff88007ca00000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
CR2: 00007fd1cdf0dffc CR3: 000000007972a000 CR4: 00000000000006f0
Stack:
 0000000000000000 0000000000000000 0000000000000000 ffff88007a003040
 ffffea0001b3f090 ffffffff8112a277 0000000400000002 ffff880000000004
 0000000000000004 0000000000000000 ffff88007749bc50 ffff88007a309e70
Call Trace:
 [<ffffffff8112a277>] ? __mpage_writepage+0x4f7/0x5f0
 [<ffffffff810e0234>] ? rmap_walk+0xe4/0x230
 [<ffffffff810e04e3>] ? page_mkclean+0x63/0x80
 [<ffffffff810df250>] ? page_referenced_one+0xb0/0xb0
 [<ffffffff8111903a>] ? inode_to_bdi+0x1a/0x60
 [<ffffffff810bf51c>] ? write_cache_pages+0x1cc/0x390
 [<ffffffff81129d80>] ? clean_buffers+0x60/0x60
 [<ffffffff811213cb>] ? __getblk_gfp+0x1b/0x50
 [<ffffffff8116d1f0>] ? ext2_get_blocks+0x990/0x990
 [<ffffffff81129ce3>] ? mpage_writepages+0x53/0x90
 [<ffffffff8116d1f0>] ? ext2_get_blocks+0x990/0x990
 [<ffffffff8111933a>] ? __writeback_single_inode+0x2a/0x180
 [<ffffffff811197ab>] ? writeback_sb_inodes+0x1ab/0x3f0
 [<ffffffff81119a7e>] ? __writeback_inodes_wb+0x8e/0xc0
 [<ffffffff81119c7b>] ? wb_writeback+0x1cb/0x1e0
 [<ffffffff8110c005>] ? get_nr_inodes+0x45/0x60
 [<ffffffff810bf98d>] ? global_dirty_limits+0xd/0xf0
 [<ffffffff8111a1f8>] ? bdi_writeback_workfn+0x158/0x340
 [<ffffffff8105ab44>] ? process_one_work+0x124/0x320
 [<ffffffff8105ae56>] ? worker_thread+0x116/0x460
 [<ffffffff8105ad40>] ? process_one_work+0x320/0x320
 [<ffffffff81060255>] ? kthread+0xc5/0xe0
 [<ffffffff81060190>] ? kthread_create_on_node+0x170/0x170
 [<ffffffff813efc12>] ? ret_from_fork+0x42/0x70
 [<ffffffff81060190>] ? kthread_create_on_node+0x170/0x170
Code: 04 72 09 eb c6 0f 1f 80 00 00 00 00 48 89 ee 48 89 df e8 05 e1 f9 ff eb b2 0f 1f 00 48 8d 74 24 08 e8 d6 ea ff ff 41 89 c4 eb a5 <0f> 0b 66 66 66 66 66 66 2e 0f 1f 84 00 00 00 00 00 48 8b 07 53 
RIP  [<ffffffff8112109f>] try_to_free_buffers+0xaf/0xc0
 RSP <ffff88007749b8f8>
---[ end trace 02a1bb501c316a0b ]---
May 25 13:42:19 ZigZag kernel: kernel BUG at /home/cbertsch/NZdev/nz218/othersrc/linux-git/fs/buffer.c:3220!
BUG: unable to handle kernel paging request at ffffffffffffffd8
IP: [<ffffffff81060747>] kthread_data+0x7/0x10
PGD 160c067 PUD 160e067 PMD 0 
Oops: 0000 [#2] SMP 
Modules linked in: linear md_mod ipv6 nfsd auth_rpcgss oid_registry exportfs lockd grace sunrpc af_packet sd_mod ide_gd_mod ata_generic pata_amd sata_nv libata i2c_dev amd74xx k8temp ide_pci_generic forcedeth ide_core skge ehci_pci ohci_pci ehci_hcd ohci_hcd i2c_nforce2 rtc_cmos
CPU: 0 PID: 139 Comm: kworker/u8:2 Tainted: G      D         4.1.0-rc5 #1
Hardware name: BIOSTAR Group N61PB-M2S/N61PB-M2S, BIOS 6.00 PG 02/27/2009
task: ffff88007975c110 ti: ffff880077498000 task.ti: ffff880077498000
RIP: 0010:[<ffffffff81060747>]  [<ffffffff81060747>] kthread_data+0x7/0x10
RSP: 0018:ffff88007749b680  EFLAGS: 00010002
RAX: 0000000000000000 RBX: 0000000000000000 RCX: 000000135064379a
RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff88007975c110
RBP: ffff88007975c110 R08: ffff8800774888d0 R09: 0000000000000001
R10: 0000000000000001 R11: 000000000000001a R12: ffff88007975c8f8
R13: 0000000000000000 R14: 0000000000014480 R15: 0000000000000000
FS:  00007fa82f7e6740(0000) GS:ffff88007ca00000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
CR2: 0000000000000028 CR3: 000000007972a000 CR4: 00000000000006f0
Stack:
 ffffffff8105b8c8 ffff88007ca14480 ffffffff813ec6e3 ffff88007975c110
 0000000000000000 ffff88007975c110 ffff88007749c000 ffff88007975c7f0
 ffff88007749b728 0000000000000000 ffff88007c3aab30 ffff88007975c110
Call Trace:
 [<ffffffff8105b8c8>] ? wq_worker_sleeping+0x8/0x90
 [<ffffffff813ec6e3>] ? __schedule+0x343/0x750
 [<ffffffff813ecb1a>] ? schedule+0x2a/0x80
 [<ffffffff81048384>] ? do_exit+0x664/0xa80
 [<ffffffff81005bc7>] ? oops_end+0x67/0xa0
 [<ffffffff81002c8b>] ? do_error_trap+0x6b/0xd0
 [<ffffffff8112109f>] ? try_to_free_buffers+0xaf/0xc0
 [<ffffffff81216cbb>] ? radix_tree_insert+0x2b/0xe0
 [<ffffffff813f0a68>] ? invalid_op+0x18/0x20
 [<ffffffff8112109f>] ? try_to_free_buffers+0xaf/0xc0
 [<ffffffff81123bb8>] ? bdev_write_page+0x68/0xa0
 [<ffffffff8112a277>] ? __mpage_writepage+0x4f7/0x5f0
 [<ffffffff810e0234>] ? rmap_walk+0xe4/0x230
 [<ffffffff810e04e3>] ? page_mkclean+0x63/0x80
 [<ffffffff810df250>] ? page_referenced_one+0xb0/0xb0
 [<ffffffff8111903a>] ? inode_to_bdi+0x1a/0x60
 [<ffffffff810bf51c>] ? write_cache_pages+0x1cc/0x390
 [<ffffffff81129d80>] ? clean_buffers+0x60/0x60
 [<ffffffff811213cb>] ? __getblk_gfp+0x1b/0x50
 [<ffffffff8116d1f0>] ? ext2_get_blocks+0x990/0x990
 [<ffffffff81129ce3>] ? mpage_writepages+0x53/0x90
 [<ffffffff8116d1f0>] ? ext2_get_blocks+0x990/0x990
 [<ffffffff8111933a>] ? __writeback_single_inode+0x2a/0x180
 [<ffffffff811197ab>] ? writeback_sb_inodes+0x1ab/0x3f0
 [<ffffffff81119a7e>] ? __writeback_inodes_wb+0x8e/0xc0
 [<ffffffff81119c7b>] ? wb_writeback+0x1cb/0x1e0
 [<ffffffff8110c005>] ? get_nr_inodes+0x45/0x60
 [<ffffffff810bf98d>] ? global_dirty_limits+0xd/0xf0
 [<ffffffff8111a1f8>] ? bdi_writeback_workfn+0x158/0x340
 [<ffffffff8105ab44>] ? process_one_work+0x124/0x320
 [<ffffffff8105ae56>] ? worker_thread+0x116/0x460
 [<ffffffff8105ad40>] ? process_one_work+0x320/0x320
 [<ffffffff81060255>] ? kthread+0xc5/0xe0
 [<ffffffff81060190>] ? kthread_create_on_node+0x170/0x170
 [<ffffffff813efc12>] ? ret_from_fork+0x42/0x70
 [<ffffffff81060190>] ? kthread_create_on_node+0x170/0x170
Code: 00 00 00 00 65 48 8b 04 25 00 a9 00 00 48 8b 80 90 07 00 00 48 8b 40 c8 48 c1 e8 02 83 e0 01 c3 0f 1f 40 00 48 8b 87 90 07 00 00 <48> 8b 40 d8 c3 0f 1f 40 00 48 83 ec 18 48 8b b7 90 07 00 00 ba 
RIP  [<ffffffff81060747>] kthread_data+0x7/0x10
 RSP <ffff88007749b680>
CR2: ffffffffffffffd8
---[ end trace 02a1bb501c316a0c ]---
Fixing recursive fault but reboot is needed!

[-- Attachment #4: linprob.stktrace.0525c.4.1-rc5.txt --]
[-- Type: text/plain, Size: 8671 bytes --]


# 
# date
Mon May 25 13:46:02 MST 2015
# 
# cat /proc/zerv\b \b \b\b \b \b\b \b \b\b \b \bversion
Linux version 4.1.0-rc5 (cbertsch@haxe) (gcc version 4.8.2 (GCC) ) #1 SMP Mon May 25 13:00:21 MST 2015
# 
# cat /etc/zerv*
1.1.10x 2015-May-25 13:07
# 
# cat /proc/partitions
major minor  #blocks  name

   1        0      81920 ram0
   1        1      81920 ram1
   1        2      81920 ram2
   1        3      81920 ram3
   3        0  156290904 hda
   8        0  312571224 sda
   8       16     126976 sdb
   8       17     126852 sdb1
   8       48  156290904 sdd
   8       49  156289927 sdd1
   8       32 2930266584 sdc
   8       33 2930265591 sdc1
   8       64 2930266584 sde
   9        0 3086293374 md0
# 
# df
Filesystem     1K-blocks   Used Available Use% Mounted on
/dev/root          35328  35328         0 100% /
devtmpfs         1002560      0   1002560   0% /dev
/dev/ram1           7745    343      7402   5% /hd
tmpfs            1021248      0   1021248   0% /dev/shm
/dev/sdb1         122708 107784     14924  88% /flash
# 
# cat /proc/mdstat
Personalities : [linear] 
md0 : active linear sdc1[0] sdd1[1]
      3086293374 blocks super 1.2 0k rounding
      
unused devices: <none>
# 
# 
# dd bs=16384 if=/dev/zero of=/dev/md0 count=32M &
# 
# 
# ps
  PID TTY          TIME CMD
  193 ttyS0    00:00:00 sh
  832 ttyS0    00:00:00 dd
  833 ttyS0    00:00:00 ps
# 
# #### do not run monirw to monitor disk activity .....
# 
# date
Mon May 25 13:47:30 MST 2015
# 
# date
Mon May 25 13:48:13 MST 2015
# 
# 
# date
Mon May 25 13:51:02 MST 2015
# 
# 
# date
Mon May 25 13:53:36 MST 2015
# 
# ------------[ cut here ]------------
kernel BUG at /home/cbertsch/NZdev/nz218/othersrc/linux-git/fs/buffer.c:3220!
invalid opcode: 0000 [#1] SMP 
Modules linked in: linear md_mod ipv6 nfsd auth_rpcgss oid_registry exportfs lockd grace sunrpc af_packet sd_mod ide_gd_mod ata_generic pata_amd sata_nv libata i2c_dev amd74xx k8temp ide_pci_generic forcedeth ide_core skge ehci_pci ohci_pci ehci_hcd ohci_hcd i2c_nforce2 rtc_cmos
CPU: 0 PID: 148 Comm: kworker/u8:2 Not tainted 4.1.0-rc5 #1
Hardware name: BIOSTAR Group N61PB-M2S/N61PB-M2S, BIOS 6.00 PG 02/27/2009
Workqueue: writeback bdi_writeback_workfn (flush-1:1)
task: ffff8800774881d0 ti: ffff8800775a8000 task.ti: ffff8800775a8000
RIP: 0010:[<ffffffff8112109f>]  [<ffffffff8112109f>] try_to_free_buffers+0xaf/0xc0
RSP: 0018:ffff8800775ab8f8  EFLAGS: 00010246
RAX: 001000000000086c RBX: ffffea0001148a80 RCX: ffff88004f740230
RDX: 0000000000000004 RSI: 0000000000000001 RDI: ffffea0001148a80
RBP: ffff88007d0a38b0 R08: 0000000000000002 R09: 0000000000017448
R10: ffff88007cc47600 R11: 000000000000001a R12: ffffea0001148a80
R13: 0000000000001000 R14: ffff8800775abb78 R15: 0000000000000c5a
FS:  00007fb059391740(0000) GS:ffff88007ca00000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
CR2: 00007f87330b4ffc CR3: 000000007e8c7000 CR4: 00000000000006f0
Stack:
 0000000000000000 0000000000000000 0000000000000000 ffff88007a003040
 ffffea0001148a80 ffffffff8112a277 0000000400000002 ffff880000000004
 0000000000000004 0000000000000000 ffff8800775abc50 ffff88007d0a38b0
Call Trace:
 [<ffffffff8112a277>] ? __mpage_writepage+0x4f7/0x5f0
 [<ffffffff810e0234>] ? rmap_walk+0xe4/0x230
 [<ffffffff810e04e3>] ? page_mkclean+0x63/0x80
 [<ffffffff810df250>] ? page_referenced_one+0xb0/0xb0
 [<ffffffff8111903a>] ? inode_to_bdi+0x1a/0x60
 [<ffffffff810bf51c>] ? write_cache_pages+0x1cc/0x390
 [<ffffffff81129d80>] ? clean_buffers+0x60/0x60
 [<ffffffff811f4673>] ? blk_flush_plug_list+0xe3/0x260
 [<ffffffff8116d1f0>] ? ext2_get_blocks+0x990/0x990
 [<ffffffff81129ce3>] ? mpage_writepages+0x53/0x90
 [<ffffffff8116d1f0>] ? ext2_get_blocks+0x990/0x990
 [<ffffffff8111933a>] ? __writeback_single_inode+0x2a/0x180
 [<ffffffff811197ab>] ? writeback_sb_inodes+0x1ab/0x3f0
 [<ffffffff81119a7e>] ? __writeback_inodes_wb+0x8e/0xc0
 [<ffffffff81119c7b>] ? wb_writeback+0x1cb/0x1e0
 [<ffffffff8110c005>] ? get_nr_inodes+0x45/0x60
 [<ffffffff810bf98d>] ? global_dirty_limits+0xd/0xf0
 [<ffffffff8111a1f8>] ? bdi_writeback_workfn+0x158/0x340
 [<ffffffff8105ab44>] ? process_one_work+0x124/0x320
 [<ffffffff8105ae56>] ? worker_thread+0x116/0x460
 [<ffffffff8105ad40>] ? process_one_work+0x320/0x320
 [<ffffffff81060255>] ? kthread+0xc5/0xe0
 [<ffffffff81060190>] ? kthread_create_on_node+0x170/0x170
 [<ffffffff813efc12>] ? ret_from_fork+0x42/0x70
 [<ffffffff81060190>] ? kthread_create_on_node+0x170/0x170
Code: 04 72 09 eb c6 0f 1f 80 00 00 00 00 48 89 ee 48 89 df e8 05 e1 f9 ff eb b2 0f 1f 00 48 8d 74 24 08 e8 d6 ea ff ff 41 89 c4 eb a5 <0f> 0b 66 66 66 66 66 66 2e 0f 1f 84 00 00 00 00 00 48 8b 07 53 
RIP  [<ffffffff8112109f>] try_to_free_buffers+0xaf/0xc0
 RSP <ffff8800775ab8f8>
---[ end trace bc092d5328429ae1 ]---
May 25 13:54:19 ZigZag kernel: kernel BUG at /home/cbertsch/NZdev/nz218/othersrc/linux-git/fs/buffer.c:3220!
BUG: unable to handle kernel paging request at ffffffffffffffd8
IP: [<ffffffff81060747>] kthread_data+0x7/0x10
PGD 160c067 PUD 160e067 PMD 0 
Oops: 0000 [#2] SMP 
Modules linked in: linear md_mod ipv6 nfsd auth_rpcgss oid_registry exportfs lockd grace sunrpc af_packet sd_mod ide_gd_mod ata_generic pata_amd sata_nv libata i2c_dev amd74xx k8temp ide_pci_generic forcedeth ide_core skge ehci_pci ohci_pci ehci_hcd ohci_hcd i2c_nforce2 rtc_cmos
CPU: 0 PID: 148 Comm: kworker/u8:2 Tainted: G      D         4.1.0-rc5 #1
Hardware name: BIOSTAR Group N61PB-M2S/N61PB-M2S, BIOS 6.00 PG 02/27/2009
task: ffff8800774881d0 ti: ffff8800775a8000 task.ti: ffff8800775a8000
RIP: 0010:[<ffffffff81060747>]  [<ffffffff81060747>] kthread_data+0x7/0x10
RSP: 0018:ffff8800775ab680  EFLAGS: 00010002
RAX: 0000000000000000 RBX: 0000000000000000 RCX: 00000016382baaed
RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff8800774881d0
RBP: ffff8800774881d0 R08: ffff8800774da990 R09: 0000000000000001
R10: 0000000000000001 R11: 000000000000001a R12: ffff8800774889b8
R13: 0000000000000000 R14: 0000000000014480 R15: 0000000000000000
FS:  00007fb059391740(0000) GS:ffff88007ca00000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
CR2: 0000000000000028 CR3: 000000007e8c7000 CR4: 00000000000006f0
Stack:
 ffffffff8105b8c8 ffff88007ca14480 ffffffff813ec6e3 ffff8800774881d0
 0000000000000000 ffff8800774881d0 ffff8800775ac000 ffff8800774888b0
 ffff8800775ab728 0000000000000000 ffff88007c3aab30 ffff8800774881d0
Call Trace:
 [<ffffffff8105b8c8>] ? wq_worker_sleeping+0x8/0x90
 [<ffffffff813ec6e3>] ? __schedule+0x343/0x750
 [<ffffffff813ecb1a>] ? schedule+0x2a/0x80
 [<ffffffff81048384>] ? do_exit+0x664/0xa80
 [<ffffffff81005bc7>] ? oops_end+0x67/0xa0
 [<ffffffff81002c8b>] ? do_error_trap+0x6b/0xd0
 [<ffffffff8112109f>] ? try_to_free_buffers+0xaf/0xc0
 [<ffffffff8106c690>] ? update_curr+0x50/0xb0
 [<ffffffff81216cbb>] ? radix_tree_insert+0x2b/0xe0
 [<ffffffff813f0a68>] ? invalid_op+0x18/0x20
 [<ffffffff8112109f>] ? try_to_free_buffers+0xaf/0xc0
 [<ffffffff81123bb8>] ? bdev_write_page+0x68/0xa0
 [<ffffffff8112a277>] ? __mpage_writepage+0x4f7/0x5f0
 [<ffffffff810e0234>] ? rmap_walk+0xe4/0x230
 [<ffffffff810e04e3>] ? page_mkclean+0x63/0x80
 [<ffffffff810df250>] ? page_referenced_one+0xb0/0xb0
 [<ffffffff8111903a>] ? inode_to_bdi+0x1a/0x60
 [<ffffffff810bf51c>] ? write_cache_pages+0x1cc/0x390
 [<ffffffff81129d80>] ? clean_buffers+0x60/0x60
 [<ffffffff811f4673>] ? blk_flush_plug_list+0xe3/0x260
 [<ffffffff8116d1f0>] ? ext2_get_blocks+0x990/0x990
 [<ffffffff81129ce3>] ? mpage_writepages+0x53/0x90
 [<ffffffff8116d1f0>] ? ext2_get_blocks+0x990/0x990
 [<ffffffff8111933a>] ? __writeback_single_inode+0x2a/0x180
 [<ffffffff811197ab>] ? writeback_sb_inodes+0x1ab/0x3f0
 [<ffffffff81119a7e>] ? __writeback_inodes_wb+0x8e/0xc0
 [<ffffffff81119c7b>] ? wb_writeback+0x1cb/0x1e0
 [<ffffffff8110c005>] ? get_nr_inodes+0x45/0x60
 [<ffffffff810bf98d>] ? global_dirty_limits+0xd/0xf0
 [<ffffffff8111a1f8>] ? bdi_writeback_workfn+0x158/0x340
 [<ffffffff8105ab44>] ? process_one_work+0x124/0x320
 [<ffffffff8105ae56>] ? worker_thread+0x116/0x460
 [<ffffffff8105ad40>] ? process_one_work+0x320/0x320
 [<ffffffff81060255>] ? kthread+0xc5/0xe0
 [<ffffffff81060190>] ? kthread_create_on_node+0x170/0x170
 [<ffffffff813efc12>] ? ret_from_fork+0x42/0x70
 [<ffffffff81060190>] ? kthread_create_on_node+0x170/0x170
Code: 00 00 00 00 65 48 8b 04 25 00 a9 00 00 48 8b 80 90 07 00 00 48 8b 40 c8 48 c1 e8 02 83 e0 01 c3 0f 1f 40 00 48 8b 87 90 07 00 00 <48> 8b 40 d8 c3 0f 1f 40 00 48 83 ec 18 48 8b b7 90 07 00 00 ba 
RIP  [<ffffffff81060747>] kthread_data+0x7/0x10
 RSP <ffff8800775ab680>
CR2: ffffffffffffffd8
---[ end trace bc092d5328429ae2 ]---
Fixing recursive fault but reboot is needed!

^ permalink raw reply

* Re: Fwd: Installing Linux directly onto RAID6 Array...........
From: Another Sillyname @ 2015-05-25 21:03 UTC (permalink / raw)
  To: linux-raid
In-Reply-To: <alpine.DEB.2.02.1505241654580.9487@uplift.swm.pp.se>

Well the swap thing was an easy fix/decision.....

I agree that putting swap into an array seems a bit of overkill,
however one of the things that can be a problem is mounting swap files
into /etc/fstab and then the drive with the swap fails......

My workaround, found on the web and re hashed, is to instead create a
4GB swap partition on each drive then using the following script
automount the swaps at boot time using a systemd script.

#!/bin/bash

#  Script for service that autodetects and starts swap partitions

for f in $(fdisk -l | grep "Linux swap" | sort | cut -d' ' -f1 | tr
'\n' ' '); do swapon $f; done

as it only 'finds' swaps on active partitions it prevents boot
problems in the case of a dead drive.

Due to time constraints I've had to build this using bios_boot and
RAID1 /boot/efi and RAID1 /boot partitions for now and the RAID6
partition is currently syncing with a projected finish around 15 hours
from now.  However given what I've learnt I'm convinced that using
initramfs on pre-existing created partitions is the way to
go.....RAID6 for all the arrays, including /boot and /boot/efi.  Once
I've got this migration out of the way and another test box to use I
intend to take this a stage further and make it work.

Thanks for everyones help and ideas, much appreciated.

Tony



On 24 May 2015 at 15:57, Mikael Abrahamsson <swmike@swm.pp.se> wrote:
> On Sun, 24 May 2015, Wols Lists wrote:
>
>> On 24/05/15 15:06, Mikael Abrahamsson wrote:
>>>
>>> On Sun, 24 May 2015, Wols Lists wrote:
>>>
>>>> And if you get read errors, well, aiui, raid won't help here either -
>>>> especially with mirrored raid, you just get a read failure. Raid does
>>>> NOT give you error recovery unless the drive physically fails, and if
>>>> it's a bad block it gets fixed at the disk or disk driver level - well
>>>> below the raid driver.
>>>
>>>
>>> You're wrong. In case of a read error from the physical drive on RAID1,
>>> RAID5 or RAID6 then the information will be re-created from another
>>> drive, and written to the drive that threw a read error. This is the
>>> whole point of RAID with parity information.
>>>
>> Except raid 1 isn't parity ... :-)
>
>
> RAID1 means every drive will have the same information, it's mirrored
> between the member disks. What do you think RAID1 is?
>
>> Personally, I still don't think "raid"ing swap is worth it, though.
>> Horses for courses, ram is cheap, and in my circumstances I don't think
>> I'd gain anything.
>
>
> You're welcome to believe anything you want, but if you're publically
> telling people things that are just not true then you should expect to be
> told so.
>
> You're welcome to tell people to not use SWAP at all, but telling people
> RAID1 has no benefit for SWAP because it won't protect you from read erorrs
> is just wrong.
>
>
> --
> Mikael Abrahamsson    email: swmike@swm.pp.se

^ permalink raw reply

* [PATCH V2] md-cluster: avoid deadlock on MESSAGE lock resource
From: Abhijit Bhopatkar @ 2015-05-25 16:34 UTC (permalink / raw)
  To: linux-raid, Lidong Zhong, Goldwyn Rodrigues; +Cc: Reese Faucette (rfaucett)


Every receiver has CR lock on MESSAGE while processing the message. When
every receiver releases ACK lock and for some reason fails to grab EX on
MESSAGE resource in time, a waiting sender could queue an EX on MESSAGE
instead. Now when receiver queues its up convert request on MESSAGE it
will end up in a deadlock situation.

Setting HEADQUE flag on MESSAGE lock resource while grabbing the EX on
MESSAGE on receiver will avoid this deadlock. Any queued request by
sender will be processed only after all receivers have released their
EX on MESSAGE.

Signed-off-by: Abhijit Bhopatkar <abhopatk@cisco.com>
---
Version 2 changes from v1: Made receiver HEADQUE rather than
making sender NOQUEUE, also get rid of goto pollution  

Minimaly tested on three node cluster, operations create,assemble
tested on two a shared raid disks.

 drivers/md/md-cluster.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/drivers/md/md-cluster.c b/drivers/md/md-cluster.c
index fcfc4b9..cb76c0f 100644
--- a/drivers/md/md-cluster.c
+++ b/drivers/md/md-cluster.c
@@ -480,8 +480,17 @@ static void recv_daemon(struct md_thread *thread)
 
 	/*release CR on ack_lockres*/
 	dlm_unlock_sync(ack_lockres);
-	/*up-convert to EX on message_lockres*/
+
+	/* up-convert to EX on message_lockres
+	 * Since another sender might already be ready to send data.
+	 * Use DLM_LKF_HEADQUE to move this lock request ahead of
+	 * that sender.
+	 */
+
+	message_lockres->flags |= DLM_LKF_HEADQUE;
 	dlm_lock_sync(message_lockres, DLM_LOCK_EX);
+	message_lockres->flags &= ~DLM_LKF_HEADQUE;
+
 	/*get CR on ack_lockres again*/
 	dlm_lock_sync(ack_lockres, DLM_LOCK_CR);
 	/*release CR on message_lockres*/
-- 
2.1.0

^ permalink raw reply related

* Re: [PATCH v4 08/11] block: kill merge_bvec_fn() completely
From: Alex Elder @ 2015-05-25 15:35 UTC (permalink / raw)
  To: Ilya Dryomov, Christoph Hellwig
  Cc: Ming Lin, linux-kernel@vger.kernel.org, Kent Overstreet,
	Jens Axboe, Dongsu Park, Lars Ellenberg, drbd-user, Jiri Kosina,
	Yehuda Sadeh, Sage Weil, Alex Elder, Ceph Development,
	Alasdair Kergon, Mike Snitzer, dm-devel, Neil Brown, linux-raid,
	Christoph Hellwig, Martin K. Petersen
In-Reply-To: <CAOi1vP8vNEXw2e1eWa4LqKD14SA7XtSQ_C8+4d_sz20t4nfEng@mail.gmail.com>

On 05/25/2015 10:02 AM, Ilya Dryomov wrote:
> On Mon, May 25, 2015 at 5:04 PM, Christoph Hellwig <hch@lst.de> wrote:
>> On Fri, May 22, 2015 at 11:18:40AM -0700, Ming Lin 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.
>>
>> It might be good to replace patch 1 and this one by a patch per driver
>> to remove the merge_bvec_fn instance and add the blk_queue_split call
>> for all those drivers that actually had a ->merge_bvec_fn.  As some
>> of them were non-trivial attention from the maintainers would be helpful,
>> and a patch per driver might help with that.
>>
>>> -/* 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)
>>
>>
>> This just checks the lower device, so it looks obviously fine.
>>
>>> -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;
>>> -}
>>
>> As mentioned in the comment pkt_make_request will split the bio so pkt
>> looks fine.
>>
>>> diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
>>> index ec6c5c6..f50edb3 100644
>>> --- a/drivers/block/rbd.c
>>> +++ b/drivers/block/rbd.c
>>> @@ -3440,52 +3440,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)
>>
>> It seems rbd handles requests spanning objects just fine, so I don't
>> really understand why rbd_merge_bvec even exists.  Getting some form
>> of ACK from the ceph folks would be useful.
> 
> I'm not Alex, but yeah, we have all the clone/split machinery and so we
> can handle a spanning case just fine.  I think rbd_merge_bvec() exists
> to make sure we don't have to do that unless it's really necessary -
> like when a single page gets submitted at an inconvenient offset.

I am Alex.  This is something I never removed.  I haven't
looked at it closely now, but it seems to me that after I
created a function that split stuff properly up *before*
the BIO layer got to it (which has since been replaced by
code related to Kent's immutable BIO work), there has been
no need for this function.  Removing this was on a long-ago
to-do list--but I didn't want to do it without spending some
time ensuring it wouldn't break anything.

If you want me to work through it in more detail so I can
give a more certain response, let me know and I will do so.

					-Alex

> I have a patch that adds a blk_queue_chunk_sectors(object_size) call to
> rbd_init_disk() but I haven't had a chance to play with it yet.  In any
> case, we should be fine with getting rid of rbd_merge_bvec().  If this
> ends up a per-driver patchset, I can make rbd_merge_bvec() ->
> blk_queue_chunk_sectors() a single patch and push it through
> ceph-client.git.
> 
> Thanks,
> 
>                 Ilya
> 


^ permalink raw reply

* Re: [PATCH v4 08/11] block: kill merge_bvec_fn() completely
From: Ilya Dryomov @ 2015-05-25 15:19 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Ming Lin, linux-kernel@vger.kernel.org, Kent Overstreet,
	Jens Axboe, Dongsu Park, Lars Ellenberg, drbd-user, Jiri Kosina,
	Yehuda Sadeh, Sage Weil, Alex Elder, Ceph Development,
	Alasdair Kergon, Mike Snitzer, dm-devel, Neil Brown, linux-raid,
	Martin K. Petersen, Alex Elder
In-Reply-To: <20150525150827.GA27012@lst.de>

On Mon, May 25, 2015 at 6:08 PM, Christoph Hellwig <hch@lst.de> wrote:
> On Mon, May 25, 2015 at 06:02:30PM +0300, Ilya Dryomov wrote:
>> I'm not Alex, but yeah, we have all the clone/split machinery and so we
>> can handle a spanning case just fine.  I think rbd_merge_bvec() exists
>> to make sure we don't have to do that unless it's really necessary -
>> like when a single page gets submitted at an inconvenient offset.
>>
>> I have a patch that adds a blk_queue_chunk_sectors(object_size) call to
>> rbd_init_disk() but I haven't had a chance to play with it yet.  In any
>> case, we should be fine with getting rid of rbd_merge_bvec().  If this
>> ends up a per-driver patchset, I can make rbd_merge_bvec() ->
>> blk_queue_chunk_sectors() a single patch and push it through
>> ceph-client.git.
>
> Hmm, looks like the new blk_queue_split_bio ignore the chunk_sectors
> value, another thing that needs updating.  I forgot how many weird
> merging hacks we had to add for nvme..
>
> While I'd like to see per-driver patches we'd still need to merge
> them together through the block tree.  Note that with this series
> there won't be any benefit of using blk_queue_chunk_sectors over just
> doing the split in rbd.  Maybe we can even remove it again and do
> that work in the drivers in the future.

OK, I'll drop it, especially if it's potentially on its way out.  With
the fancy striping support, which I'll hopefully get to sometime, the
striping pattern will become much more complicated anyway, so relying
on rbd doing bio splitting is right in the long run as well.

Thanks,

                Ilya

^ permalink raw reply

* Re: [PATCH v4 08/11] block: kill merge_bvec_fn() completely
From: Christoph Hellwig @ 2015-05-25 15:08 UTC (permalink / raw)
  To: Ilya Dryomov
  Cc: Ming Lin, linux-kernel@vger.kernel.org, Kent Overstreet,
	Jens Axboe, Dongsu Park, Lars Ellenberg, drbd-user, Jiri Kosina,
	Yehuda Sadeh, Sage Weil, Alex Elder, Ceph Development,
	Alasdair Kergon, Mike Snitzer, dm-devel, Neil Brown, linux-raid,
	Martin K. Petersen, Alex Elder
In-Reply-To: <CAOi1vP8vNEXw2e1eWa4LqKD14SA7XtSQ_C8+4d_sz20t4nfEng@mail.gmail.com>

On Mon, May 25, 2015 at 06:02:30PM +0300, Ilya Dryomov wrote:
> I'm not Alex, but yeah, we have all the clone/split machinery and so we
> can handle a spanning case just fine.  I think rbd_merge_bvec() exists
> to make sure we don't have to do that unless it's really necessary -
> like when a single page gets submitted at an inconvenient offset.
> 
> I have a patch that adds a blk_queue_chunk_sectors(object_size) call to
> rbd_init_disk() but I haven't had a chance to play with it yet.  In any
> case, we should be fine with getting rid of rbd_merge_bvec().  If this
> ends up a per-driver patchset, I can make rbd_merge_bvec() ->
> blk_queue_chunk_sectors() a single patch and push it through
> ceph-client.git.

Hmm, looks like the new blk_queue_split_bio ignore the chunk_sectors
value, another thing that needs updating.  I forgot how many weird
merging hacks we had to add for nvme..

While I'd like to see per-driver patches we'd still need to merge
them together through the block tree.  Note that with this series
there won't be any benefit of using blk_queue_chunk_sectors over just
doing the split in rbd.  Maybe we can even remove it again and do
that work in the drivers in the future.

^ permalink raw reply

* Re: [PATCH v4 08/11] block: kill merge_bvec_fn() completely
From: Ilya Dryomov @ 2015-05-25 15:02 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Ming Lin, linux-kernel@vger.kernel.org, Kent Overstreet,
	Jens Axboe, Dongsu Park, Lars Ellenberg, drbd-user, Jiri Kosina,
	Yehuda Sadeh, Sage Weil, Alex Elder, Ceph Development,
	Alasdair Kergon, Mike Snitzer, dm-devel, Neil Brown, linux-raid,
	Christoph Hellwig, Martin K. Petersen, Alex Elder
In-Reply-To: <20150525140413.GA26065@lst.de>

On Mon, May 25, 2015 at 5:04 PM, Christoph Hellwig <hch@lst.de> wrote:
> On Fri, May 22, 2015 at 11:18:40AM -0700, Ming Lin 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.
>
> It might be good to replace patch 1 and this one by a patch per driver
> to remove the merge_bvec_fn instance and add the blk_queue_split call
> for all those drivers that actually had a ->merge_bvec_fn.  As some
> of them were non-trivial attention from the maintainers would be helpful,
> and a patch per driver might help with that.
>
>> -/* 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)
>
>
> This just checks the lower device, so it looks obviously fine.
>
>> -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;
>> -}
>
> As mentioned in the comment pkt_make_request will split the bio so pkt
> looks fine.
>
>> diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
>> index ec6c5c6..f50edb3 100644
>> --- a/drivers/block/rbd.c
>> +++ b/drivers/block/rbd.c
>> @@ -3440,52 +3440,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)
>
> It seems rbd handles requests spanning objects just fine, so I don't
> really understand why rbd_merge_bvec even exists.  Getting some form
> of ACK from the ceph folks would be useful.

I'm not Alex, but yeah, we have all the clone/split machinery and so we
can handle a spanning case just fine.  I think rbd_merge_bvec() exists
to make sure we don't have to do that unless it's really necessary -
like when a single page gets submitted at an inconvenient offset.

I have a patch that adds a blk_queue_chunk_sectors(object_size) call to
rbd_init_disk() but I haven't had a chance to play with it yet.  In any
case, we should be fine with getting rid of rbd_merge_bvec().  If this
ends up a per-driver patchset, I can make rbd_merge_bvec() ->
blk_queue_chunk_sectors() a single patch and push it through
ceph-client.git.

Thanks,

                Ilya

^ permalink raw reply

* Re: [PATCH] md-cluster: avoid deadlock on MESSAGE lock resource
From: Abhijit Bhopatkar @ 2015-05-25 14:26 UTC (permalink / raw)
  To: Goldwyn Rodrigues, linux-raid, Lidong Zhong; +Cc: Reese Faucette (rfaucett)
In-Reply-To: <5557AF81.30304@suse.de>

On 17/05/15 2:28 am, Goldwyn Rodrigues wrote:
> 
> 
> On 05/08/2015 08:14 AM, Abhijit Bhopatkar wrote:
>> On 08/05/15 6:40 pm, Abhijit Bhopatkar wrote:
>>>
>>> Every receiver has CR lock on MESSAGE while processing the message. When
>>> every receiver releases ACK lock and for some reason fails to grab EX on
>>> MESSAGE resource in time, a waiting sender could queue an EX on MESSAGE
>>> instead. Now when receiver queues its up convert request on MESSAGE it
>>> will end up in a deadlock situation.
>>>
>>> Setting NOQUEUE flag on MESSAGE lock resource while grabbing the EX on
>>> MESSAGE on sender will avoid this deadlock. If sender can not grab
>>> MESSAGE lock immediately it should retry until the lock is granted.
>>>
>>> Signed-off-by: Abhijit Bhopatkar <abhopatk@cisco.com>
>>> ---
>>> This has been minimally tested on a three node cluster.
>>>
>>
>> I have tested standard mdadm operations (create, assemble etc).
>> What more testing would you want me to do on this before its considered
>> ready?
> 
> I am not sure how using LKF_NOQUEUE will help in this situation here. LKF_NOQUEUE primarily means do not queue if you can't grant it right away. Besides, I don't like the idea of goto loop.
> 
> The sender can still creep in between the ack and the message locks. A situation would be where the "disrupting" sender is the lock owner of all the locks and hence will not have to pay communication costs and will manage to attain the locks faster.
> 
> Perhaps DLM_LKF_HEADQUEUE or DLM_LKF_NOORDER is what you are looking for, but that again is not the complete solution.
> 
> Another idea I could think of is for the sender to downconvert TOKEN to a shared lock such as CR  halfway in the communication (say after message CR), and all receivers take the TOKEN in CR mode and release it once the communication is finally over.
> 
> Regards,
> 
> 
I agree about the goto pollution and yes converting receivers to use DLM_LKF_HEADQUEUE will solve the problem gracefully. Will send the new patch shortly.

However I do not understand why this is incomplete solution. The "disruptive sender" as you have called it, is already "TOKEN" owner and otherwise it will compete for TOKEN lock as usual with other senders with equal priority. Not gaining any priority over others. The changes simply make sender stall for all _receivers_ to complete their serialization and wait till all receivers convert MESSAGE lock from CR to EX to NL, nothing else changes.

Regards,

>>
>> Regards,
>> Abhijit

<snip>

^ permalink raw reply

* Re: [PATCH v4 06/11] md/raid5: get rid of bio_fits_rdev()
From: Christoph Hellwig @ 2015-05-25 14:17 UTC (permalink / raw)
  To: NeilBrown
  Cc: Ming Lin, lkml, Christoph Hellwig, Kent Overstreet, Jens Axboe,
	Dongsu Park, linux-raid
In-Reply-To: <20150525175414.6a1fc33d@notabene.brown>

On Mon, May 25, 2015 at 05:54:14PM +1000, NeilBrown wrote:
> Did I write that?  I guess I did :-(
> I meant *after*.   Don't get rid of bio_fits_rdev until split_bio is in
> chunk_aligned_read().

I suspect the whole series could use some reordering.

patch 1:

 add ->bio_split and blk_queue_split

patch 2..n:

 one for each non-trivial driver that implements ->merge_bvec_fn to
 remove it and instead split bios in ->make_request.  The md patch
 to do the right thing in chunk_aligned_read goes into the general
 md patch here.  The bcache patch also goes into this series.

patch n+1:

 - add blk_queue_split calls for remaining trivial drivers

patch n+2:

 - remove ->merge_bvec_fn and checking of max_sectors a for all
   drivers, simplify bio_add_page

patch n+2:

 - remove splitting in blkdev_issue_discard

patch n+3

 - remove bio_fits_rdev

patch n+4

 - remove bio_get_nr_vecs

patch n+4

 - use bio_add_page

patch n+5

 - update documentation

^ permalink raw reply

* Re: [PATCH v4 08/11] block: kill merge_bvec_fn() completely
From: Christoph Hellwig @ 2015-05-25 14:04 UTC (permalink / raw)
  To: Ming Lin
  Cc: linux-kernel, Christoph Hellwig, Kent Overstreet, Jens Axboe,
	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, Alex Elder
In-Reply-To: <1432318723-18829-9-git-send-email-mlin@kernel.org>

On Fri, May 22, 2015 at 11:18:40AM -0700, Ming Lin 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.

It might be good to replace patch 1 and this one by a patch per driver
to remove the merge_bvec_fn instance and add the blk_queue_split call
for all those drivers that actually had a ->merge_bvec_fn.  As some
of them were non-trivial attention from the maintainers would be helpful,
and a patch per driver might help with that.

> -/* 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)


This just checks the lower device, so it looks obviously fine.

> -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;
> -}

As mentioned in the comment pkt_make_request will split the bio so pkt
looks fine.

> diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
> index ec6c5c6..f50edb3 100644
> --- a/drivers/block/rbd.c
> +++ b/drivers/block/rbd.c
> @@ -3440,52 +3440,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)

It seems rbd handles requests spanning objects just fine, so I don't
really understand why rbd_merge_bvec even exists.  Getting some form
of ACK from the ceph folks would be useful.

> -/*
> - * 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)
> -{

DM seems to have the most complex merge functions of all drivers, so
I'd really love to see an ACK from Mike.


^ permalink raw reply

* Re: [PATCH v4 06/11] md/raid5: get rid of bio_fits_rdev()
From: NeilBrown @ 2015-05-25  7:54 UTC (permalink / raw)
  To: Ming Lin
  Cc: lkml, Christoph Hellwig, Kent Overstreet, Jens Axboe, Dongsu Park,
	linux-raid
In-Reply-To: <CAF1ivSY+ky5PD=m34KXU4z9gE_v4uztaFT=MuU4g69DtXD9vWA@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 4137 bytes --]

On Mon, 25 May 2015 00:03:20 -0700 Ming Lin <mlin@kernel.org> wrote:

> On Sun, May 24, 2015 at 10:48 PM, NeilBrown <neilb@suse.de> wrote:
> > On Fri, 22 May 2015 11:18:38 -0700 Ming Lin <mlin@kernel.org> wrote:
> >
> >> 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.
> >
> > Surely this patch should come *before*
> >   [PATCH v4 07/11] md/raid5: split bio for chunk_aligned_read
> 
> PATCH 6, then PATCH 7, isn't it already *before*?

Did I write that?  I guess I did :-(
I meant *after*.   Don't get rid of bio_fits_rdev until split_bio is in
chunk_aligned_read().

Sorry.

> 
> >
> > and the comment says ->merge_bvec_fn() has gone, but that isn't until
> >   [PATCH v4 08/11] block: kill merge_bvec_fn() completely
> >
> >
> > If those issues are resolved, then
> 
> How about this?
> 
> PATCH 6: md/raid5: split bio for chunk_aligned_read
> PATCH 7: block: kill merge_bvec_fn() completely
> PATCH 8: md/raid5: get rid of bio_fits_rdev()

Yes for "get rid of bio_fits_rdev()" after "split bio for chunk_aligned_read".

For the other issue, you could do was you suggest, or you could just change
the comment.
  Remove bio_fits_rdev() as sufficient merge_bvec_fn() handling is now
  performed by blk_queue_split() in md_make_request().

Up to you.

Thanks,
NeilBrown


> 
> Thanks.
> 
> >
> >   Acked-by: NeilBrown <neilb@suse.de>
> >
> > Thanks,
> > NeilBrown
> >
> >
> >>
> >> 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 <dpark@posteo.net>
> >> 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 1ba97fd..b303ded 100644
> >> --- a/drivers/md/raid5.c
> >> +++ b/drivers/md/raid5.c
> >> @@ -4743,25 +4743,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;
> >> @@ -4815,11 +4796,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;
> >
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 811 bytes --]

^ permalink raw reply

* Re: [PATCH v4 06/11] md/raid5: get rid of bio_fits_rdev()
From: Ming Lin @ 2015-05-25  7:03 UTC (permalink / raw)
  To: NeilBrown
  Cc: lkml, Christoph Hellwig, Kent Overstreet, Jens Axboe, Dongsu Park,
	linux-raid
In-Reply-To: <20150525154829.4330f149@notabene.brown>

On Sun, May 24, 2015 at 10:48 PM, NeilBrown <neilb@suse.de> wrote:
> On Fri, 22 May 2015 11:18:38 -0700 Ming Lin <mlin@kernel.org> wrote:
>
>> 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.
>
> Surely this patch should come *before*
>   [PATCH v4 07/11] md/raid5: split bio for chunk_aligned_read

PATCH 6, then PATCH 7, isn't it already *before*?

>
> and the comment says ->merge_bvec_fn() has gone, but that isn't until
>   [PATCH v4 08/11] block: kill merge_bvec_fn() completely
>
>
> If those issues are resolved, then

How about this?

PATCH 6: md/raid5: split bio for chunk_aligned_read
PATCH 7: block: kill merge_bvec_fn() completely
PATCH 8: md/raid5: get rid of bio_fits_rdev()

Thanks.

>
>   Acked-by: NeilBrown <neilb@suse.de>
>
> Thanks,
> NeilBrown
>
>
>>
>> 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 <dpark@posteo.net>
>> 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 1ba97fd..b303ded 100644
>> --- a/drivers/md/raid5.c
>> +++ b/drivers/md/raid5.c
>> @@ -4743,25 +4743,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;
>> @@ -4815,11 +4796,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;
>

^ permalink raw reply

* Re: [PATCH v4 08/11] block: kill merge_bvec_fn() completely
From: NeilBrown @ 2015-05-25  5:49 UTC (permalink / raw)
  To: Ming Lin
  Cc: linux-kernel, Christoph Hellwig, Kent Overstreet, Jens Axboe,
	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: <1432318723-18829-9-git-send-email-mlin@kernel.org>

[-- Attachment #1: Type: text/plain, Size: 58095 bytes --]

On Fri, 22 May 2015 11:18:40 -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.
> 
> 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 <dpark@posteo.net>
> Signed-off-by: Ming Lin <mlin@kernel.org>

Acked-by: NeilBrown <neilb@suse.de> (for the 'md' bits)

Very happy to see this happening!

Thanks,
NeilBrown


> ---
>  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 dc14255..25cafb8 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, bvprv;
>  	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;
>  
>  		/*
> 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 ec6c5c6..f50edb3 100644
> --- a/drivers/block/rbd.c
> +++ b/drivers/block/rbd.c
> @@ -3440,52 +3440,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;
> @@ -3784,7 +3738,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 5503e43..d13f330 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 34f6063..f732a7a 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.
> @@ -1717,60 +1716,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.
> @@ -2477,59 +2422,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,
> @@ -2538,7 +2430,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);
>  
> @@ -2564,17 +2455,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);
>  
> @@ -2852,7 +2737,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 046b3c9..f101981 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 6a68ef5..1440bd4 100644
> --- a/drivers/md/raid0.c
> +++ b/drivers/md/raid0.c
> @@ -192,9 +192,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++;
> @@ -351,58 +348,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, &sector_offset);
> -	rdev = map_sector(mddev, zone, sector, &sector_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;
> @@ -725,7 +670,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 b6c6ace..18d2b23 100644
> --- a/drivers/md/raid5.c
> +++ b/drivers/md/raid5.c
> @@ -4625,35 +4625,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);
> @@ -7722,7 +7693,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 =
>  {
> @@ -7746,7 +7716,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 =
> @@ -7771,7 +7740,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;


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 811 bytes --]

^ permalink raw reply

* Re: [PATCH v4 06/11] md/raid5: get rid of bio_fits_rdev()
From: NeilBrown @ 2015-05-25  5:48 UTC (permalink / raw)
  To: Ming Lin
  Cc: linux-kernel, Christoph Hellwig, Kent Overstreet, Jens Axboe,
	Dongsu Park, linux-raid
In-Reply-To: <1432318723-18829-7-git-send-email-mlin@kernel.org>

[-- Attachment #1: Type: text/plain, Size: 2470 bytes --]

On Fri, 22 May 2015 11:18:38 -0700 Ming Lin <mlin@kernel.org> wrote:

> 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.

Surely this patch should come *before* 
  [PATCH v4 07/11] md/raid5: split bio for chunk_aligned_read

and the comment says ->merge_bvec_fn() has gone, but that isn't until
  [PATCH v4 08/11] block: kill merge_bvec_fn() completely


If those issues are resolved, then

  Acked-by: NeilBrown <neilb@suse.de>

Thanks,
NeilBrown


> 
> 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 <dpark@posteo.net>
> 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 1ba97fd..b303ded 100644
> --- a/drivers/md/raid5.c
> +++ b/drivers/md/raid5.c
> @@ -4743,25 +4743,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;
> @@ -4815,11 +4796,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;


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 811 bytes --]

^ permalink raw reply

* Re: Massive data corruption on replace + fail + rebuild
From: NeilBrown @ 2015-05-25  5:22 UTC (permalink / raw)
  To: James J; +Cc: linux-raid
In-Reply-To: <555CF034.8050303@shiftmail.org>

[-- Attachment #1: Type: text/plain, Size: 4287 bytes --]

On Wed, 20 May 2015 22:36:04 +0200 James J <james.j@shiftmail.org> wrote:

> Hello all,
> I wrote some days ago to the ML with subject "MD RAID hot-replace wants 
> to rewrite to the source! (and fails, and kicks)"
> The problem went much worse than that and ended with massive data 
> corruption on the replacement drive sdm.
> 
> In this report I will use the same letters as in previous email: sdl for 
> the failing drive, sdm for the replacement drive.
> This report is for raid5 on kernel 3.4.34 .

Bug was fixed in 3.4.56

   0761d079bbc2 ("md/raid5: fix interaction of 'replace' and 'recovery'.")

and  3.11

   f94c0b6658c7 ("md/raid5: fix interaction of 'replace' and 'recovery'.")


> Bad blocks list is not enabled.
> Bitmap is enabled
> See previous post for details, mdstat and dmesg log.
> 
> It seems that the following series of events deeply corrupts the 
> replacement drive:
> 1) drive sdl is flaky, so the user initiates replacement process 
> (want_replacement) to the spare drive sdm
> 2) the disk sdl has read errors on some sectors. MD performs reconstruct 
> read and then rewrite for those sectors. Currently MD wants to rewrite 
> the source drive sdl, instead of just to the replacement drive sdm which 
> I would much prefer.

It probably makes sense to avoid repairing read errors of a drive being
replaced.  I've put it on my todo list, but I'm afraid I haven't looked at
that much lately.

However any writes to the array would have to be written to both drives.
If we only ever wrote to the replacement drive, it would be very hard to keep
track of where to read from.
So if you have a device that cannot survive being written to, then you would
need to avoid writing to the array completely.

NeilBrown




> 3) sdl unfortunately is too flaky to receive rewrites, so it fails on 
> the rewrites and is kicked by MD. The array is now degraded
> 4) At this point, MD apparently continues the rebuild process 
> transforming the replacement into a full rebuild, but continuing from 
> the point where sdl was kicked, and not from the start. This seems 
> smart, however I guess there is a bug in doing this, maybe an off-by-N 
> error. In the previous post you can see the dmesg line "[865031.586650] 
> md: resuming recovery of md54 from checkpoint."
> 
> At the end of the rebuild, when MD starts using sdm as a member drive, 
> an enormous amount of errors appear on the filesystems located on that 
> array.
> 
> In fact, I performed a check afterwards, and this was the mismatch_cnt:
> 
>    root@server:/sys/block/md54/md# cat mismatch_cnt
>    5296438776
> 
> This is on a 5x3TB array so about 90.4% of it has mismatches, if my math 
> is correct.
> 
> The drive sdl was kicked at about 1% of the replacement process, so this 
> 90.4% would not match, should have been 99%, but considering that many 
> stripes could be zeroes, an 8.5% could be parities on zeroes which match 
> just by chance.
> 
> So I suppose there is a problem in the handover between the replacement 
> and the rebuild. I would bet on an off-by-N problem, i.e. a shifting of 
> the data. Maybe the sources start a reconstruct-read from the beginning 
> of the array while the destination continues writing from the point of 
> the handover, or vice versa.
> 
> Currently I have "solved" the problem already, by artificially failing 
> the drive sdm, and introducing another disk as spare to perform a clean 
> rebuild from scratch. After failing sdm and dropping the caches, before 
> inserting the new spare, the filesystems were readable again, so I was 
> optimistic, and in fact at the end of the clean rebuild this appears to 
> have recovered our data and mismatch_cnt is now zero. However I was 
> lucky to have immediately understood what happened, otherwise we would 
> have probably lost all our data, so please look into this.
> 
> Thanks for your work
> PS: I would appreciate if you can also make MD not rewrite to the source 
> during replacement :-)
> JJ
> 
> --
> 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


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 811 bytes --]

^ permalink raw reply

* Re: [PATCH V3 00/11] mdadm tool: add the support for cluster-md
From: NeilBrown @ 2015-05-25  5:03 UTC (permalink / raw)
  To: Guoqing Jiang; +Cc: linux-raid, rgoldwyn
In-Reply-To: <1432092043-24220-1-git-send-email-gqjiang@suse.com>

[-- Attachment #1: Type: text/plain, Size: 3501 bytes --]

On Wed, 20 May 2015 11:20:32 +0800 Guoqing Jiang <gqjiang@suse.com> wrote:

> V3 changes:
> 1. re-orgnize some codes to ensure mdadm compiles after each patch is applied
> 2. change the code for super1.c for first patch since it has side effect for
> non-cluster condition
> 
> V2 changes:
> 1. re-arrange the squence of patches
> 2. add some memembers into sb_le_to_cpu
> 3. handle some logic change and comments from Neil
> 
> Basic background for Cluster MD: Cluster MD is a shared-device RAID for a
> cluster, currently, the implementation is limited to RAID1 but with further
> work (and some positive feedback), it could be extend to other RAID levels.
> 
> The kernel part code of cluster-md has been sent to maillist several month
> ago by Goldywyn, and to make cluster-md works, the mdadm tools also need to
> do some changes accordingly.
> 
> This patch set extends mdadm tool to aware cluster MD scenario, and handle
> related cluster-md scenario.
> 
> 1. the first part (0001-0007) comes from Goldwyn, which add initial
> support for cluster-md, those changes included make mdadm awares nodes,
> home-cluster and n bitmaps for clustered mode, also let mdadm can 
> confirm disk which is added by another node.
> 
> 
> 2. the second part is for support change cluster-name and node nums under
> assemble mode. Which extend write-bitmap to handle above cases, and also
> use the extended write_bitmap for update uuid. [PATCH V2 10/10] is just compiled
> test only.
> 
> BTW: this series is based on commit "72a457 IMSM: Count arrays per orom".
> 
> Some reltated links:
> [1] http://marc.info/?l=linux-raid&m=141891941330336&w=2
> [2] http://marc.info/?l=linux-raid&m=141935561418770&w=2
> 
> Guoqing Jiang (11):
>   Create n bitmaps for clustered mode
>   Add nodes option while creating md
>   home-cluster while creating an array
>   Show all bitmaps while examining bitmap
>   Add a new clustered disk
>   Convert a bitmap=none device to clustered
>   Skip clustered devices in incremental
>   mdadm: add the ability to change cluster name
>   mdadm: change the num of cluster node
>   Reuse calc_bitmap_size to reduce code size
>   Reuse the write_bitmap for update uuid
> 
>  Assemble.c    |  14 ++++--
>  Create.c      |   5 +-
>  Grow.c        |  22 +++++++--
>  Incremental.c |   5 ++
>  Makefile      |   1 +
>  Manage.c      |  33 +++++++++++--
>  ReadMe.c      |   3 ++
>  bitmap.c      |  94 ++++++++++++++++++++++---------------
>  bitmap.h      |   7 ++-
>  config.c      |  27 ++++++++++-
>  md_p.h        |   7 +++
>  md_u.h        |   1 +
>  mdadm.8.in    |  28 +++++++++++-
>  mdadm.c       |  69 +++++++++++++++++++++++++++-
>  mdadm.h       |  20 +++++++-
>  super0.c      |   4 +-
>  super1.c      | 145 +++++++++++++++++++++++++++++++++++++++++++++++-----------
>  util.c        |  60 ++++++++++++++++++++++++
>  18 files changed, 458 insertions(+), 87 deletions(-)
> 


Thanks.  This looked like it is getting close.  Most of the things I have
commented on a fairly minor and should be easy to fix.
Hopefully the next time you post I have just add all the patched to my git
tree and we can take incremental patches from there.

I hope to make a 3.3.3 release of mdadm soonish, and then I'll target 3.4 to
primarily just add the clustering stuff.
If I get the next patchset before I've released 3.3.3, I'll just put it in a
separate branch and merge it later.

Thanks,
NeilBrown


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 811 bytes --]

^ permalink raw reply

* Re: [PATCH V3 11/11] Reuse the write_bitmap for update uuid
From: NeilBrown @ 2015-05-25  4:59 UTC (permalink / raw)
  To: Guoqing Jiang; +Cc: linux-raid, rgoldwyn
In-Reply-To: <1432092043-24220-12-git-send-email-gqjiang@suse.com>

[-- Attachment #1: Type: text/plain, Size: 3280 bytes --]

On Wed, 20 May 2015 11:20:43 +0800 Guoqing Jiang <gqjiang@suse.com> wrote:

> Since write_bitmap is extended for handle different sistuations,
> then it also could possible to support change the uuid of bitmap,
> and remove bitmap_update_uuid accordingly.
> 
> Q: is the write_bitmap0 also impacted?

Yes.  You would need to add UUIDUpdate handling to write_bitmap0 too.

Thanks,
NeilBrown



> 
> Signed-off-by: Guoqing Jiang <gqjiang@suse.com>
> ---
>  Assemble.c |  5 ++---
>  bitmap.c   | 20 --------------------
>  mdadm.h    |  2 +-
>  super1.c   |  4 ++++
>  4 files changed, 7 insertions(+), 24 deletions(-)
> 
> diff --git a/Assemble.c b/Assemble.c
> index 9ff546b..fabca5c 100644
> --- a/Assemble.c
> +++ b/Assemble.c
> @@ -664,9 +664,8 @@ static int load_devices(struct devs *devices, char *devmap,
>  
>  			if (strcmp(c->update, "uuid")==0 &&
>  			    ident->bitmap_fd >= 0 && !bitmap_done) {
> -				if (bitmap_update_uuid(ident->bitmap_fd,
> -						       content->uuid,
> -						       tst->ss->swapuuid) != 0)
> +				copy_uuid(tst->devs->uuid, content->uuid, tst->ss->swapuuid);
> +				if (tst->ss->write_bitmap(tst, dfd, UUIDUpdate))
>  					pr_err("Could not update uuid on external bitmap.\n");
>  				else
>  					bitmap_done = 1;
> diff --git a/bitmap.c b/bitmap.c
> index bccc67c..7df296e 100644
> --- a/bitmap.c
> +++ b/bitmap.c
> @@ -462,23 +462,3 @@ out:
>  		unlink(filename); /* possibly corrupted, better get rid of it */
>  	return rv;
>  }
> -
> -int bitmap_update_uuid(int fd, int *uuid, int swap)
> -{
> -	struct bitmap_super_s bm;
> -	if (lseek(fd, 0, 0) != 0)
> -		return 1;
> -	if (read(fd, &bm, sizeof(bm)) != sizeof(bm))
> -		return 1;
> -	if (bm.magic != __cpu_to_le32(BITMAP_MAGIC))
> -		return 1;
> -	copy_uuid(bm.uuid, uuid, swap);
> -	if (lseek(fd, 0, 0) != 0)
> -		return 2;
> -	if (write(fd, &bm, sizeof(bm)) != sizeof(bm)) {
> -		lseek(fd, 0, 0);
> -		return 2;
> -	}
> -	lseek(fd, 0, 0);
> -	return 0;
> -}
> diff --git a/mdadm.h b/mdadm.h
> index 97892e6..7b9bb28 100644
> --- a/mdadm.h
> +++ b/mdadm.h
> @@ -358,6 +358,7 @@ enum bitmap_update {
>      NoUpdate,
>      NameUpdate,
>      NodeNumUpdate,
> +    UUIDUpdate,
>  };
>  
>  /* structures read from config file */
> @@ -1273,7 +1274,6 @@ extern int CreateBitmap(char *filename, int force, char uuid[16],
>  			int major);
>  extern int ExamineBitmap(char *filename, int brief, struct supertype *st);
>  extern int Write_rules(char *rule_name);
> -extern int bitmap_update_uuid(int fd, int *uuid, int swap);
>  extern unsigned long bitmap_sectors(struct bitmap_super_s *bsb);
>  extern int Dump_metadata(char *dev, char *dir, struct context *c,
>  			 struct supertype *st);
> diff --git a/super1.c b/super1.c
> index b36b702..75e1081 100644
> --- a/super1.c
> +++ b/super1.c
> @@ -2250,6 +2250,10 @@ static int write_bitmap1(struct supertype *st, int fd, enum bitmap_update update
>  
>  	    bms->nodes = __cpu_to_le32(st->nodes);
>  	    break;
> +	case UUIDUpdate:
> +	    memset((char *)bms->uuid, 0, sizeof(bms->uuid));
> +	    strncpy((char *)bms->uuid, (char *)st->devs->uuid, sizeof(bms->uuid));
> +	    break;
>  	case NoUpdate:
>  	default:
>  	    break;


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 811 bytes --]

^ permalink raw reply

* Re: [PATCH V3 09/11] mdadm: change the num of cluster node
From: NeilBrown @ 2015-05-25  4:56 UTC (permalink / raw)
  To: Guoqing Jiang; +Cc: linux-raid, rgoldwyn
In-Reply-To: <1432092043-24220-10-git-send-email-gqjiang@suse.com>

[-- Attachment #1: Type: text/plain, Size: 4936 bytes --]

On Wed, 20 May 2015 11:20:41 +0800 Guoqing Jiang <gqjiang@suse.com> wrote:

> This extends nodes option for assemble mode, make the num of
> cluster node could be change by user.
> 
> Before that, it is necessary to ensure there are enough space
> for those nodes, calc_bitmap_size is introduced to calculate
> the bitmap size of each node.
> 
> Signed-off-by: Guoqing Jiang <gqjiang@suse.com>
> ---
>  Assemble.c |  4 ++++
>  ReadMe.c   |  2 +-
>  mdadm.c    |  3 +++
>  mdadm.h    |  1 +
>  super1.c   | 37 +++++++++++++++++++++++++++++++++++++
>  5 files changed, 46 insertions(+), 1 deletion(-)
> 
> diff --git a/Assemble.c b/Assemble.c
> index e1b846c..9ff546b 100644
> --- a/Assemble.c
> +++ b/Assemble.c
> @@ -626,6 +626,10 @@ static int load_devices(struct devs *devices, char *devmap,
>  
>  			if (strcmp(c->update, "byteorder") == 0)
>  				err = 0;
> +			else if (strcmp(c->update, "nodes") == 0) {
> +				tst->nodes = c->nodes;
> +				err = tst->ss->write_bitmap(tst, dfd, NodeNumUpdate);
> +			}
>  			else
>  				err = tst->ss->update_super(tst, content, c->update,
>  							    devname, c->verbose,
> diff --git a/ReadMe.c b/ReadMe.c
> index c854cd5..d1830e1 100644
> --- a/ReadMe.c
> +++ b/ReadMe.c
> @@ -140,7 +140,7 @@ struct option long_options[] = {
>      {"homehost",  1, 0,  HomeHost},
>      {"symlinks",  1, 0,  Symlinks},
>      {"data-offset",1, 0, DataOffset},
> -    {"nodes",1, 0, Nodes},
> +    {"nodes",1, 0, Nodes}, /* also for --assemble */
>      {"home-cluster",1, 0, ClusterName},
>  
>      /* For assemble */
> diff --git a/mdadm.c b/mdadm.c
> index 22f4fc7..87c572d 100644
> --- a/mdadm.c
> +++ b/mdadm.c
> @@ -589,6 +589,7 @@ int main(int argc, char *argv[])
>  			}
>  			ident.raid_disks = s.raiddisks;
>  			continue;
> +		case O(ASSEMBLE, Nodes):
>  		case O(CREATE, Nodes):
>  			c.nodes = parse_num(optarg);
>  			if (c.nodes <= 0) {
> @@ -744,6 +745,8 @@ int main(int argc, char *argv[])
>  				continue;
>  			if (strcmp(c.update, "home-cluster")==0)
>  				continue;
> +			if (strcmp(c.update, "nodes")==0)
> +				continue;
>  			if (strcmp(c.update, "devicesize")==0)
>  				continue;
>  			if (strcmp(c.update, "no-bitmap")==0)
> diff --git a/mdadm.h b/mdadm.h
> index d8b0749..97892e6 100644
> --- a/mdadm.h
> +++ b/mdadm.h
> @@ -357,6 +357,7 @@ enum prefix_standard {
>  enum bitmap_update {
>      NoUpdate,
>      NameUpdate,
> +    NodeNumUpdate,
>  };
>  
>  /* structures read from config file */
> diff --git a/super1.c b/super1.c
> index 07944d4..fe12e81 100644
> --- a/super1.c
> +++ b/super1.c
> @@ -134,6 +134,20 @@ struct misc_dev_info {
>  					|MD_FEATURE_NEW_OFFSET		\
>  					)
>  
> +/* return how many bytes are needed for bitmap, for cluster-md each node
> + * should have it's own bitmap */
> +static unsigned int calc_bitmap_size(bitmap_super_t *bms, unsigned int boundary)
> +{
> +	unsigned long long bits, bytes;
> +
> +	bits = __le64_to_cpu(bms->sync_size) / (__le32_to_cpu(bms->chunksize)>>9);
> +	bytes = (bits+7) >> 3;
> +	bytes += sizeof(bitmap_super_t);
> +	bytes = ROUND_UP(bytes, boundary);
> +
> +	return bytes;
> +}
> +
>  static unsigned int calc_sb_1_csum(struct mdp_superblock_1 * sb)
>  {
>  	unsigned int disk_csum, csum;
> @@ -2201,6 +2215,7 @@ static int write_bitmap1(struct supertype *st, int fd, enum bitmap_update update
>  	struct align_fd afd;
>  	unsigned int i = 0;
>  	char *new_name;
> +	unsigned long long total_bm_space, bm_space_per_node;
>  
>  	switch (update) {
>  	case NameUpdate:
> @@ -2217,6 +2232,28 @@ static int write_bitmap1(struct supertype *st, int fd, enum bitmap_update update
>  
>  	    free(new_name);
>  	    break;
> +	case NodeNumUpdate:
> +	    /* cluster md only supports superblock 1.2 now */
> +	    if (st->minor_version != 2) {
> +		pr_err("Warning: cluster md only works with superblock 1.2\n");
> +		return -EINVAL;
> +	    }
> +
> +	    /* Each node has an independent bitmap, it is necessary to calculate the
> +	     * space is enough or not, first get how many bytes for the total bitmap */
> +	    bm_space_per_node = calc_bitmap_size(bms, 4096);
> +
> +	    total_bm_space = 512 * (__le64_to_cpu(sb->data_offset) - __le64_to_cpu(sb->super_offset));
> +	    total_bm_space = total_bm_space - 4096; /* leave another 4k for superblock */
> +
> +	    if (bm_space_per_node * st->nodes > total_bm_space) {
> +		pr_err("Warning: The max num of nodes can't exceed %llu\n",
> +			total_bm_space / bm_space_per_node);
> +		return -ENOMEM;
> +	    }
> +
> +	    bms->nodes = __cpu_to_le32(st->nodes);
> +	    break;
>  	case NoUpdate:
>  	default:
>  	    break;


Again, missing documentation for the new --update option.
And indents should be tabs, not "4 spaces".  That "switch(update)"
has wrong indents - I didn't notice before.

Thanks,
NeilBrown.

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 811 bytes --]

^ permalink raw reply

* Re: [PATCH V3 08/11] mdadm: add the ability to change cluster name
From: NeilBrown @ 2015-05-25  4:53 UTC (permalink / raw)
  To: Guoqing Jiang; +Cc: linux-raid, rgoldwyn
In-Reply-To: <1432092043-24220-9-git-send-email-gqjiang@suse.com>

[-- Attachment #1: Type: text/plain, Size: 7103 bytes --]

On Wed, 20 May 2015 11:20:40 +0800 Guoqing Jiang <gqjiang@suse.com> wrote:

> To support change the cluster name, the commit do the followings:
> 
> 1. extend original write_bitmap function for new scenario.
> 2. add the scenarion to handle the modification of cluster's name
>    in write_bitmap1.
> 3. make update_super1 can change the name in mdp_superblock_1.

You haven't documented --update=home-cluster in mdadm.8.in, or at

			fprintf(outf, "Valid --update options are:\n"

Also, I just realised that you are storing the cluster name in the array
name.  I don't think that is a clever idea.
The cluster name can be 64 chars.  The array name can only be 32.

I think leave homehost and homecluster completely out of the array name when
the array is clustered.

and
> +	    new_name = xmalloc(sizeof(sb->set_name));

is really unnecessary.  Just do "char new_name[32];".
But you are probably going to remove that code anyway.

NeilBrown



> 
> Signed-off-by: Guoqing Jiang <gqjiang@suse.com>
> ---
>  Assemble.c |  5 +++++
>  Grow.c     |  2 +-
>  mdadm.c    |  3 +++
>  mdadm.h    |  7 ++++++-
>  super0.c   |  4 ++--
>  super1.c   | 43 ++++++++++++++++++++++++++++++++++++++++---
>  6 files changed, 57 insertions(+), 7 deletions(-)
> 
> diff --git a/Assemble.c b/Assemble.c
> index 25a103d..e1b846c 100644
> --- a/Assemble.c
> +++ b/Assemble.c
> @@ -644,6 +644,11 @@ static int load_devices(struct devs *devices, char *devmap,
>  				*stp = st;
>  				return -1;
>  			}
> +			if (strcmp(c->update, "home-cluster") == 0) {
> +				err = tst->ss->update_super(tst, content, c->update,
> +							    devname, 0, 0, c->homecluster);
> +				tst->ss->write_bitmap(tst, dfd, NameUpdate);
> +			}
>  			if (strcmp(c->update, "uuid")==0 &&
>  			    !ident->uuid_set) {
>  				ident->uuid_set = 1;
> diff --git a/Grow.c b/Grow.c
> index 1122cec..bf44e66 100644
> --- a/Grow.c
> +++ b/Grow.c
> @@ -420,7 +420,7 @@ int Grow_addbitmap(char *devname, int fd, struct context *c, struct shape *s)
>  						    bitmapsize, offset_setable,
>  						    major)
>  						)
> -						st->ss->write_bitmap(st, fd2);
> +						st->ss->write_bitmap(st, fd2, NoUpdate);
>  					else {
>  						pr_err("failed to create internal bitmap - chunksize problem.\n");
>  						close(fd2);
> diff --git a/mdadm.c b/mdadm.c
> index 56fdeb7..22f4fc7 100644
> --- a/mdadm.c
> +++ b/mdadm.c
> @@ -598,6 +598,7 @@ int main(int argc, char *argv[])
>  			}
>  			continue;
>  		case O(CREATE, ClusterName):
> +		case O(ASSEMBLE, ClusterName):
>  			c.homecluster = optarg;
>  			if (strlen(c.homecluster) > 64) {
>  				pr_err("Cluster name too big.\n");
> @@ -741,6 +742,8 @@ int main(int argc, char *argv[])
>  				continue;
>  			if (strcmp(c.update, "homehost")==0)
>  				continue;
> +			if (strcmp(c.update, "home-cluster")==0)
> +				continue;
>  			if (strcmp(c.update, "devicesize")==0)
>  				continue;
>  			if (strcmp(c.update, "no-bitmap")==0)
> diff --git a/mdadm.h b/mdadm.h
> index 00c726e..d8b0749 100644
> --- a/mdadm.h
> +++ b/mdadm.h
> @@ -354,6 +354,11 @@ enum prefix_standard {
>  	IEC
>  };
>  
> +enum bitmap_update {
> +    NoUpdate,
> +    NameUpdate,
> +};
> +
>  /* structures read from config file */
>  /* List of mddevice names and identifiers
>   * Identifiers can be:
> @@ -850,7 +855,7 @@ extern struct superswitch {
>  	/* if add_internal_bitmap succeeded for existing array, this
>  	 * writes it out.
>  	 */
> -	int (*write_bitmap)(struct supertype *st, int fd);
> +	int (*write_bitmap)(struct supertype *st, int fd, enum bitmap_update update);
>  	/* Free the superblock and any other allocated data */
>  	void (*free_super)(struct supertype *st);
>  
> diff --git a/super0.c b/super0.c
> index deb5999..6ad9d39 100644
> --- a/super0.c
> +++ b/super0.c
> @@ -900,7 +900,7 @@ static int write_init_super0(struct supertype *st)
>  		rv = store_super0(st, di->fd);
>  
>  		if (rv == 0 && (sb->state & (1<<MD_SB_BITMAP_PRESENT)))
> -			rv = st->ss->write_bitmap(st, di->fd);
> +			rv = st->ss->write_bitmap(st, di->fd, NoUpdate);
>  
>  		if (rv)
>  			pr_err("failed to write superblock to %s\n",
> @@ -1175,7 +1175,7 @@ static void locate_bitmap0(struct supertype *st, int fd)
>  	lseek64(fd, offset, 0);
>  }
>  
> -static int write_bitmap0(struct supertype *st, int fd)
> +static int write_bitmap0(struct supertype *st, int fd, enum bitmap_update update)
>  {
>  	unsigned long long dsize;
>  	unsigned long long offset;
> diff --git a/super1.c b/super1.c
> index fd728d2..07944d4 100644
> --- a/super1.c
> +++ b/super1.c
> @@ -1073,7 +1073,23 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
>  		info->name[32] = 0;
>  	}
>  
> -	if (strcmp(update, "force-one")==0) {
> +	if (strcmp(update, "home-cluster") == 0 &&
> +	    homehost) {
> +		/* Note that 'home-cluster' is to change the name of cluster,
> +		 * it is another "name" update.
> +		 */
> +		char *new_name = xmalloc(sizeof(sb->set_name));
> +		if (strrchr(sb->set_name, ':')) {
> +			strcpy(new_name, strchr(sb->set_name, ':'));
> +		}
> +
> +		memset(sb->set_name, 0, sizeof(sb->set_name));
> +		strcpy(sb->set_name, homehost);
> +		if (new_name)
> +			strcat(sb->set_name, new_name);
> +
> +		free(new_name);
> +	} else if (strcmp(update, "force-one")==0) {
>  		/* Not enough devices for a working array,
>  		 * so bring this one up-to-date
>  		 */
> @@ -1691,7 +1707,7 @@ static int write_init_super1(struct supertype *st)
>  		sb->sb_csum = calc_sb_1_csum(sb);
>  		rv = store_super1(st, di->fd);
>  		if (rv == 0 && (__le32_to_cpu(sb->feature_map) & 1))
> -			rv = st->ss->write_bitmap(st, di->fd);
> +			rv = st->ss->write_bitmap(st, di->fd, NoUpdate);
>  		close(di->fd);
>  		di->fd = -1;
>  		if (rv)
> @@ -2175,7 +2191,7 @@ static void locate_bitmap1(struct supertype *st, int fd)
>  	lseek64(fd, offset<<9, 0);
>  }
>  
> -static int write_bitmap1(struct supertype *st, int fd)
> +static int write_bitmap1(struct supertype *st, int fd, enum bitmap_update update)
>  {
>  	struct mdp_superblock_1 *sb = st->sb;
>  	bitmap_super_t *bms = (bitmap_super_t*)(((char*)sb)+MAX_SB_SIZE);
> @@ -2184,6 +2200,27 @@ static int write_bitmap1(struct supertype *st, int fd)
>  	int towrite, n;
>  	struct align_fd afd;
>  	unsigned int i = 0;
> +	char *new_name;
> +
> +	switch (update) {
> +	case NameUpdate:
> +	    new_name = xmalloc(sizeof(sb->set_name));
> +
> +	    strncpy(new_name, sb->set_name, sizeof(sb->set_name));
> +	    memset((char *)bms->cluster_name, 0, sizeof(bms->cluster_name));
> +
> +	    if (strtok(new_name, ":"))
> +		strncpy((char *)bms->cluster_name, new_name, strlen(sb->set_name));
> +	    else
> +		/* In case the original set_name doesn't like aaa:md* */
> +		strncpy((char *)bms->cluster_name, sb->set_name, strlen(sb->set_name));
> +
> +	    free(new_name);
> +	    break;
> +	case NoUpdate:
> +	default:
> +	    break;
> +	}
>  
>  	init_afd(&afd, fd);
>  


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 811 bytes --]

^ permalink raw reply

* Re: [PATCH V3 06/11] Convert a bitmap=none device to clustered
From: NeilBrown @ 2015-05-25  4:40 UTC (permalink / raw)
  To: Guoqing Jiang; +Cc: linux-raid, rgoldwyn
In-Reply-To: <1432092043-24220-7-git-send-email-gqjiang@suse.com>

[-- Attachment #1: Type: text/plain, Size: 2943 bytes --]

On Wed, 20 May 2015 11:20:38 +0800 Guoqing Jiang <gqjiang@suse.com> wrote:

> This adds the ability to convert a regular md without bitmap
> (--bitmap=none) to a clustered device (--bitmap=clustered).
> 
> To convert a device with --bitmap=internal or --bitmap=external,
> you have to convert to --bitmap=none and then re-execute the
> command with --bitmap=clustered.
> 
> Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com>
> Signed-off-by: Guoqing Jiang <gqjiang@suse.com>
> ---
>  Grow.c | 20 ++++++++++++++++----
>  1 file changed, 16 insertions(+), 4 deletions(-)
> 
> diff --git a/Grow.c b/Grow.c
> index 9a573fd..1122cec 100644
> --- a/Grow.c
> +++ b/Grow.c
> @@ -330,9 +330,16 @@ int Grow_addbitmap(char *devname, int fd, struct context *c, struct shape *s)
>  			}
>  			return 0;
>  		}
> -		pr_err("Internal bitmap already present on %s\n",
> -			devname);
> -		return 1;
> +		if ((strcmp(s->bitmap_file, "clustered")==0) && (array.state & (1<<MD_SB_CLUSTERED))) {
> +			pr_err("Clustered bitmap already present on %s\n",
> +					devname);
> +			return 1;
> +		}
> +		if ((strcmp(s->bitmap_file, "internal")==0) && (!(array.state & (1<<MD_SB_CLUSTERED)))) {
> +			pr_err("Internal bitmap already present on %s\n",
> +					devname);
> +			return 1;
> +		}

You shouldn't be checking the value of s->bitmap_file here.  No matter what
value it has, there is some sort of bitmap present and you should report what
sort and return.


>  	}
>  
>  	if (strcmp(s->bitmap_file, "none") == 0) {
> @@ -375,7 +382,8 @@ int Grow_addbitmap(char *devname, int fd, struct context *c, struct shape *s)
>  		free(st);
>  		return 1;
>  	}
> -	if (strcmp(s->bitmap_file, "internal") == 0) {
> +	if ((strcmp(s->bitmap_file, "internal") == 0) ||
> +		(strcmp(s->bitmap_file, "clustered") == 0)) {

Indentation is wrong.  It should be:

   if ((strcmp(......) == 0) ||
       (strcmp(......) == 0)) {

except that the extra parentheses are not needed. so

   if (strcmp(......) == 0 ||
       strcmp(......) == 0) {


Thanks,
NeilBrown

>  		int rv;
>  		int d;
>  		int offset_setable = 0;
> @@ -384,6 +392,8 @@ int Grow_addbitmap(char *devname, int fd, struct context *c, struct shape *s)
>  			pr_err("Internal bitmaps not supported with %s metadata\n", st->ss->name);
>  			return 1;
>  		}
> +		st->nodes = c->nodes;
> +		st->cluster_name = c->homecluster;
>  		mdi = sysfs_read(fd, NULL, GET_BITMAP_LOCATION);
>  		if (mdi)
>  			offset_setable = 1;
> @@ -426,6 +436,8 @@ int Grow_addbitmap(char *devname, int fd, struct context *c, struct shape *s)
>  			rv = sysfs_set_num_signed(mdi, NULL, "bitmap/location",
>  						  mdi->bitmap_offset);
>  		} else {
> +			if (strcmp(s->bitmap_file, "clustered") == 0)
> +				array.state |= (1<<MD_SB_CLUSTERED);
>  			array.state |= (1<<MD_SB_BITMAP_PRESENT);
>  			rv = ioctl(fd, SET_ARRAY_INFO, &array);
>  		}


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 811 bytes --]

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox