* Re: RAID5 Performance
From: Peter Grandi @ 2016-08-03 21:23 UTC (permalink / raw)
To: Linux RAID
In-Reply-To: <36cb010d-0b77-964e-fae5-5494e5f7766b@websitemanagers.com.au>
[ ... ]
> However, I can't get the budget for those really awesome
> drives up the top of the list, that would require around
> $20k... or more.
> For now, I've got 16 x 545s TB drives, and have replaced the
> first half (ie, all drives in one server). Now I can see that
> the drives themselves don't seem to be the bottleneck (the
> drives don't run at 100% util, while the DRBD device does run
> at 100%).
The "%util" number is not that easy to interpret, especially for
flash SSD and in some situations which probably include this
one:
https://brooker.co.za/blog/2014/07/04/iostat-pct.html
> Hopefully that will line up right !
It is hard to read, and I don't understand what the numbers are,
but it does not matter a lot.
> So I can only presume the new drives are much better than the
> 530 series, but still not as good as the 520 series.
The 540s have an SLC write buffer as I mentioned previously,
which should help.
> However, the point of note is that DRBD devices are showing
> high util levels much more frequently than the underlying
> devices, so I can only assume that the current limitation is
> caused by DRBD rather than the drives.
I like guessing, but this assumptions seems to me a bit
excessive.
> From my understanding, the times these settings can cause a
> problem: [ ... ]
If you don't have reliable sync barriers at all levels (not just
DRBD) *any* crash (e.g. bug crash, mistake-crash, memory-full
crash, not just power crash) is going to cause massive trouble,
especially in a mostly-write workload where what is being
written is cache spill. Some interesting pages:
http://blog.2ndquadrant.com/intel_ssd_now_off_the_sherr_sh/
http://wiki.postgresql.org/wiki/Reliable_Writes
http://archive.is/WTeAE
https://news.ycombinator.com/item?id=6973179
http://lkcl.net/reports/ssd_analysis.html
>>> Do you have any other suggestions or ideas that might
>>> assist?
Another one that would likely give a bit of relief as you can't
budget for write-optimized "enterprise" flash SSDs is a SATA/SAS
host adapter with a very large battery-backed RAM buffer. As the
tests that I previously mentioned show, longer writes result in
much improved write rates on "consumer" flash SSD devices, and
hopefully the large buffer results in:
#1 When the large write buffer flushes, *hopefully* much longer
writes to the flash SSD will happen on average.
#2 Thanks to the battery backing, writes are reporte completed
to the OS when they reach the host adapter's buffer, rather
than the flash SSD layer.
If #1 does not happen #2 won't help much if writes are at the
flash SSD saturation level, only if they are bursty and on
average below it.
>> * Smaller RAID5 stripes, as in 4+1 or 2+1, are cheaper in
>> space than RAID10 and enormously raise the chances that a
>> full stripe-write can happen (it still has the write-hole
>> problem of parity RAID).
> I was planning to upgrade to the 4.4.x kernel, which would
> kind of solve this, [ ... ]
The write hole workaround in MD RAID relies on a mostly-write
journal device like for DRBD.
>> * Make sure the DRBD journal is also on a separate device
>> that allows fast small sync writes.
> I think this would be the next option to investigate.
> Currently the DRBD journal is on the same devices.
That means that every sync'ed write becomes two writes to the
same device.
> 2 x P3700 400GB is probably around $2500,
The Samsung SM863 I ahve already mentioned are write-optimized
too and much cheaper, at around $300-350 for the 480GB model.
> while 12 x 545s 1000GB is around $4800, [ ... ]
Many people try to use "consumer" drives to build manager wowing
systems that have huge capacity and low cost, but vendors are not
stupid, and make sure that premium priced "enteprise" drives have
some critical advantage for at least some important workloads
(usually write heavy, guessing that "enterprise" workloads that
can command premium prices are transactional); sometimes like for
SSDs the advantages are based on real stuff, capacitors and
overprovisioning, which do cost money, sometimes artificial like
disabling SCT/ERC control.
^ permalink raw reply
* Re: Inactive arrays
From: Daniel Sanabria @ 2016-08-03 19:18 UTC (permalink / raw)
To: Wols Lists; +Cc: linux-raid
In-Reply-To: <CAHscji0BQuyKQbLYZ9Ah16hHday_seTaajm8LOn6+HRFqinTyQ@mail.gmail.com>
Ok,
Unfortunately the PSU replacement didn't help and I could be facing a
failed motherboard/cpu :( My question now is, is it possible to
restore the arrays in a new machine?
Daniel
On 2 August 2016 at 11:45, Daniel Sanabria <sanabria.d@gmail.com> wrote:
> Thanks very much for the response Wol.
>
> It looks like the PSU is dead (server automatically powers off a few
> seconds after power on).
>
> I'm planning to order a PSU replacement to resume troubleshooting so
> please bear with me; maybe the PSU was degraded and couldn't power
> some of drives?
>
> Cheers,
>
> Daniel
>
> On 2 August 2016 at 11:17, Wols Lists <antlists@youngman.org.uk> wrote:
>> Just a quick first response. I see md128 and md129 are both down, and
>> are both listed as one drive, raid0. Bit odd, that ...
>>
>> What version of mdadm are you using? One of them had a bug (3.2.3 era?)
>> that would split an array in two. Is it possible that you should have
>> one raid0 array with sdf1 and sdf2? But that's a bit of a weird setup...
>>
>> I notice also that md126 is raid10 across two drives. That's odd, too.
>>
>> How much do you know about what the setup should be, and why it was set
>> up that way?
>>
>> Download lspci by Phil Turmel (it requires python2.7, if your machine is
>> python3 a quick fix to the shebang at the start should get it to work).
>> Post the output from that here.
>>
>> Cheers,
>> Wol
>>
>> On 02/08/16 08:36, Daniel Sanabria wrote:
>>> Hi All,
>>>
>>> I have a box that I believe was not powered down correctly and after
>>> transporting it to a different location it doesn't boot anymore
>>> stopping at BIOS check "Verifying DMI Pool Data".
>>>
>>> The box have 6 drives and after instructing the BIOS to boot from the
>>> first drive I managed to boot the OS (Fedora 23) after commenting out
>>> 2 /etc/fstab entries , output for "uname -a; cat /etc/fstab" follows:
>>>
>>> [root@lamachine ~]# uname -a; cat /etc/fstab
>>> Linux lamachine 4.3.3-303.fc23.x86_64 #1 SMP Tue Jan 19 18:31:55 UTC
>>> 2016 x86_64 x86_64 x86_64 GNU/Linux
>>>
>>> #
>>> # /etc/fstab
>>> # Created by anaconda on Tue Mar 24 19:31:21 2015
>>> #
>>> # Accessible filesystems, by reference, are maintained under '/dev/disk'
>>> # See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
>>> #
>>> /dev/mapper/vg_bigblackbox-LogVol_root / ext4
>>> defaults 1 1
>>> UUID=4e51f903-37ca-4479-9197-fac7b2280557 /boot ext4
>>> defaults 1 2
>>> /dev/mapper/vg_bigblackbox-LogVol_opt /opt ext4
>>> defaults 1 2
>>> /dev/mapper/vg_bigblackbox-LogVol_tmp /tmp ext4
>>> defaults 1 2
>>> /dev/mapper/vg_bigblackbox-LogVol_var /var ext4
>>> defaults 1 2
>>> UUID=9194f492-881a-4fc3-ac09-ca4e1cc2985a swap swap
>>> defaults 0 0
>>> /dev/md2 /home ext4 defaults 1 2
>>> #/dev/vg_media/lv_media /mnt/media ext4 defaults 1 2
>>> #/dev/vg_virt_dir/lv_virt_dir1 /mnt/guest_images/ ext4 defaults 1 2
>>> [root@lamachine ~]#
>>>
>>> When checking mdstat I can see that 2 of the arrays are showing up as
>>> inactive, but not sure how to safely activate these so looking for
>>> some knowledgeable advice on how to proceed here.
>>>
>>> Thanks in advance,
>>>
>>> Daniel
>>>
>>> Below some more relevant outputs:
>>>
>>> [root@lamachine ~]# cat /proc/mdstat
>>> Personalities : [raid10] [raid6] [raid5] [raid4] [raid0]
>>> md127 : active raid0 sda5[0] sdc5[2] sdb5[1]
>>> 94367232 blocks super 1.2 512k chunks
>>>
>>> md2 : active raid5 sda3[0] sdc2[2] sdb2[1]
>>> 511999872 blocks level 5, 64k chunk, algorithm 2 [3/3] [UUU]
>>>
>>> md128 : inactive sdf1[3](S)
>>> 2147352576 blocks super 1.2
>>>
>>> md129 : inactive sdf2[2](S)
>>> 524156928 blocks super 1.2
>>>
>>> md126 : active raid10 sda2[0] sdc1[1]
>>> 30719936 blocks 2 near-copies [2/2] [UU]
>>>
>>> unused devices: <none>
>>> [root@lamachine ~]# cat /etc/mdadm.conf
>>> # mdadm.conf written out by anaconda
>>> MAILADDR root
>>> AUTO +imsm +1.x -all
>>> ARRAY /dev/md2 level=raid5 num-devices=3
>>> UUID=2cff15d1:e411447b:fd5d4721:03e44022
>>> ARRAY /dev/md126 level=raid10 num-devices=2
>>> UUID=9af006ca:8845bbd3:bfe78010:bc810f04
>>> ARRAY /dev/md127 level=raid0 num-devices=3
>>> UUID=acd5374f:72628c93:6a906c4b:5f675ce5
>>> ARRAY /dev/md128 metadata=1.2 spares=1 name=lamachine:128
>>> UUID=f2372cb9:d3816fd6:ce86d826:882ec82e
>>> ARRAY /dev/md129 metadata=1.2 name=lamachine:129
>>> UUID=895dae98:d1a496de:4f590b8b:cb8ac12a
>>> [root@lamachine ~]# mdadm --detail /dev/md1*
>>> /dev/md126:
>>> Version : 0.90
>>> Creation Time : Thu Dec 3 22:12:12 2009
>>> Raid Level : raid10
>>> Array Size : 30719936 (29.30 GiB 31.46 GB)
>>> Used Dev Size : 30719936 (29.30 GiB 31.46 GB)
>>> Raid Devices : 2
>>> Total Devices : 2
>>> Preferred Minor : 126
>>> Persistence : Superblock is persistent
>>>
>>> Update Time : Tue Aug 2 07:46:39 2016
>>> State : clean
>>> Active Devices : 2
>>> Working Devices : 2
>>> Failed Devices : 0
>>> Spare Devices : 0
>>>
>>> Layout : near=2
>>> Chunk Size : 64K
>>>
>>> UUID : 9af006ca:8845bbd3:bfe78010:bc810f04
>>> Events : 0.264152
>>>
>>> Number Major Minor RaidDevice State
>>> 0 8 2 0 active sync set-A /dev/sda2
>>> 1 8 33 1 active sync set-B /dev/sdc1
>>> /dev/md127:
>>> Version : 1.2
>>> Creation Time : Tue Jul 26 19:00:28 2011
>>> Raid Level : raid0
>>> Array Size : 94367232 (90.00 GiB 96.63 GB)
>>> Raid Devices : 3
>>> Total Devices : 3
>>> Persistence : Superblock is persistent
>>>
>>> Update Time : Tue Jul 26 19:00:28 2011
>>> State : clean
>>> Active Devices : 3
>>> Working Devices : 3
>>> Failed Devices : 0
>>> Spare Devices : 0
>>>
>>> Chunk Size : 512K
>>>
>>> Name : reading.homeunix.com:3
>>> UUID : acd5374f:72628c93:6a906c4b:5f675ce5
>>> Events : 0
>>>
>>> Number Major Minor RaidDevice State
>>> 0 8 5 0 active sync /dev/sda5
>>> 1 8 21 1 active sync /dev/sdb5
>>> 2 8 37 2 active sync /dev/sdc5
>>> /dev/md128:
>>> Version : 1.2
>>> Raid Level : raid0
>>> Total Devices : 1
>>> Persistence : Superblock is persistent
>>>
>>> State : inactive
>>>
>>> Name : lamachine:128 (local to host lamachine)
>>> UUID : f2372cb9:d3816fd6:ce86d826:882ec82e
>>> Events : 4154
>>>
>>> Number Major Minor RaidDevice
>>>
>>> - 8 81 - /dev/sdf1
>>> /dev/md129:
>>> Version : 1.2
>>> Raid Level : raid0
>>> Total Devices : 1
>>> Persistence : Superblock is persistent
>>>
>>> State : inactive
>>>
>>> Name : lamachine:129 (local to host lamachine)
>>> UUID : 895dae98:d1a496de:4f590b8b:cb8ac12a
>>> Events : 0
>>>
>>> Number Major Minor RaidDevice
>>>
>>> - 8 82 - /dev/sdf2
>>> [root@lamachine ~]# mdadm --detail /dev/md2
>>> /dev/md2:
>>> Version : 0.90
>>> Creation Time : Mon Feb 11 07:54:36 2013
>>> Raid Level : raid5
>>> Array Size : 511999872 (488.28 GiB 524.29 GB)
>>> Used Dev Size : 255999936 (244.14 GiB 262.14 GB)
>>> Raid Devices : 3
>>> Total Devices : 3
>>> Preferred Minor : 2
>>> Persistence : Superblock is persistent
>>>
>>> Update Time : Mon Aug 1 20:24:23 2016
>>> State : clean
>>> Active Devices : 3
>>> Working Devices : 3
>>> Failed Devices : 0
>>> Spare Devices : 0
>>>
>>> Layout : left-symmetric
>>> Chunk Size : 64K
>>>
>>> UUID : 2cff15d1:e411447b:fd5d4721:03e44022 (local to host lamachine)
>>> Events : 0.611
>>>
>>> Number Major Minor RaidDevice State
>>> 0 8 3 0 active sync /dev/sda3
>>> 1 8 18 1 active sync /dev/sdb2
>>> 2 8 34 2 active sync /dev/sdc2
>>> [root@lamachine ~]#
>>> --
>>> To unsubscribe from this list: send the line "unsubscribe linux-raid" in
>>> the body of a message to majordomo@vger.kernel.org
>>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>>>
>>
^ permalink raw reply
* Re: [PATCH 42/45] block, fs, drivers: remove REQ_OP compat defs and related code
From: Mike Christie @ 2016-08-03 17:28 UTC (permalink / raw)
To: Ross Zwisler, axboe, Ross Zwisler
Cc: linux-bcache, linux-block, XFS Developers, ocfs2-devel,
linux-scsi, konrad.wilk, LKML, philipp.reisner, linux-f2fs-devel,
linux-raid, dm-devel, target-devel, linux-mtd, osd-dev,
linux-fsdevel, lars.ellenberg, linux-ext4, linux-btrfs, drbd-dev
In-Reply-To: <CAOxpaSVzkR+9anramDg7nHxjb5hp0q_oKGRdEpiU07jWM=tzdQ@mail.gmail.com>
On 08/03/2016 11:25 AM, Ross Zwisler wrote:
> run fstests generic/008 at 2016-08-03 09:54:56
> page:ffffea0017af04c0 count:3 mapcount:0 mapping:ffff8805eb059200 index:0x0
> flags: 0x3fff8000002828(uptodate|lru|private|writeback)
> page dumped because: VM_BUG_ON_PAGE(!PageLocked(page))
> page->mem_cgroup:ffff8806098e0800
> ------------[ cut here ]------------
> kernel BUG at mm/filemap.c:833!
> invalid opcode: 0000 [#1] SMP
> Modules linked in: brd dax_pmem nd_pmem dax nd_btt nd_e820 libnvdimm
> CPU: 0 PID: 2522 Comm: xfs_io Not tainted 4.7.0-rc2-00042-g4e1b2d52 #18
> Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS
> rel-1.9.1-0-gb3ef39f-prebuilt.qemu-project.org 04/01/2014
> task: ffff8805ebae4ec0 ti: ffff8805eba3c000 task.ti: ffff8805eba3c000
> RIP: 0010:[<ffffffff811de115>] [<ffffffff811de115>] unlock_page+0xa5/0xb0
> RSP: 0018:ffff8805eba3fa60 EFLAGS: 00010282
> RAX: 0000000000000021 RBX: 0000000000000000 RCX: 0000000000000006
> RDX: 0000000000000000 RSI: 0000000000000001 RDI: ffff8806109ce200
> RBP: ffff8805eba3fa60 R08: 0000000000000001 R09: 0000000000000001
> R10: ffff8805ebae4ec0 R11: 0000000000000001 R12: ffffea0017af04c0
> R13: 0000000000028000 R14: ffffffffa00202c0 R15: ffff88060eff1200
> FS: 00007f87a31cf700(0000) GS:ffff880610800000(0000) knlGS:0000000000000000
> CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> CR2: 00007f87a31e6000 CR3: 000000060da31000 CR4: 00000000001406f0
> Stack:
> ffff8805eba3fa98 ffffffff812bd782 ffff8805eba3fdb0 0000000000001000
> ffffea0017af04c0 0000000000000000 0000000000000088 ffff8805eba3fbe0
> ffffffff812c3ff1 ffff8805eba3fd00 0000000000028000 0000000c00000000
> Call Trace:
> [<ffffffff812bd782>] bdev_write_page+0xb2/0xe0 fs/block_dev.c:462
> [<ffffffff812c3ff1>] __mpage_writepage+0x5c1/0x750 fs/mpage.c:604
> [<ffffffff811eedbd>] write_cache_pages+0x20d/0x5f0 mm/page-writeback.c:2261
> [<ffffffff812c3955>] mpage_writepages+0x75/0xe0 fs/mpage.c:703
> [<ffffffff8137951b>] ext2_writepages+0x3b/0x40 fs/ext2/inode.c:887
> [<ffffffff811f27a1>] do_writepages+0x21/0x30 mm/page-writeback.c:2361
> [<ffffffff811e1396>] __filemap_fdatawrite_range+0xc6/0x100 mm/filemap.c:300
> [<ffffffff811e1514>] filemap_write_and_wait_range+0x44/0x90 mm/filemap.c:490
> [<ffffffff812a7707>] __generic_file_fsync+0x27/0x90 fs/libfs.c:937
> [<ffffffff812a7789>] generic_file_fsync+0x19/0x40 fs/libfs.c:974
> [<ffffffff81377e9e>] ext2_fsync+0x2e/0x70 fs/ext2/file.c:149
> [<ffffffff812b549b>] vfs_fsync_range+0x4b/0xb0 fs/sync.c:195
> [< inline >] vfs_fsync fs/sync.c:209
> [<ffffffff812b555d>] do_fsync+0x3d/0x70 fs/sync.c:219
> [< inline >] SYSC_fsync fs/sync.c:227
> [<ffffffff812b5810>] SyS_fsync+0x10/0x20 fs/sync.c:225
> [<ffffffff81acd33c>] entry_SYSCALL_64_fastpath+0x1f/0xbd
> arch/x86/entry/entry_64.S:207
> Code: 00 00 48 d3 ea 89 d2 48 8d 0c 92 48 8d 14 4a 48 8d 3c d0 31 d2
> e8 bc fc f1 ff 5d c3 48 c7 c6 20 1d ec 81 4c 89 c7 e8 bb 8d 03 00 <0f>
> 0b 66 0f 1f 84 00 00 00 00 00 66 66 66 66 90 55 b9 08 00 00
> RIP [<ffffffff811de115>] unlock_page+0xa5/0xb0 mm/filemap.c:833
> RSP <ffff8805eba3fa60>
> ---[ end trace d419bf59bba263fb ]---
Thanks for testing and the detailed bug report. Looks like I missed the
rw_page callback. Testing a patch right now. Should be done in a couple
of hours.
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply
* Re: [PATCH 42/45] block, fs, drivers: remove REQ_OP compat defs and related code
From: Ross Zwisler @ 2016-08-03 16:25 UTC (permalink / raw)
To: mchristi, axboe, Ross Zwisler
Cc: linux-bcache, linux-block, XFS Developers, ocfs2-devel,
linux-scsi, konrad.wilk, LKML, philipp.reisner, linux-f2fs-devel,
linux-raid, dm-devel, target-devel, linux-mtd, osd-dev,
linux-fsdevel, lars.ellenberg, linux-ext4, linux-btrfs, drbd-dev
In-Reply-To: <1465155145-10812-43-git-send-email-mchristi@redhat.com>
On Sun, Jun 5, 2016 at 1:32 PM, <mchristi@redhat.com> wrote:
> From: Mike Christie <mchristi@redhat.com>
>
> This patch drops the compat definition of req_op where it matches
> the rq_flag_bits definitions, and drops the related old and compat
> code that allowed users to set either the op or flags for the operation.
>
> We also then store the operation in the bi_rw/cmd_flags field similar
> to how we used to store the bio ioprio where it sat in the upper bits
> of the field.
>
> Signed-off-by: Mike Christie <mchristi@redhat.com>
I was doing some xfstests testing yesterday using linux/master, and
hit a kernel BUG that bisected to this change. The failing test is
generic/008 + ext2, without DAX. This BUG reproduces with this test
100% as of this change, and 0% with the previous commit.
Here's the kernel commit that I bisected to:
commit 4e1b2d52a80d79296a5d899d73249748dea71a53
Author: Mike Christie <mchristi@redhat.com>
Date: Sun Jun 5 14:32:22 2016 -0500
block, fs, drivers: remove REQ_OP compat defs and related code
Here are the steps to reproduce the BUG using a pair of 1 GiB BRD ramdisks:
SCRATCH_DEV=/dev/ram0
TEST_DEV=/dev/ram1
mkfs.ext2 -F $SCRATCH_DEV
mkfs.ext2 -F $TEST_DEV
cd ~/xfstests
./check generic/008
Here is the BUG output for that commit, passed through
kasan_symbolize.py. The line numbers are for the commit listed above,
not for linux/master:
run fstests generic/008 at 2016-08-03 09:54:56
page:ffffea0017af04c0 count:3 mapcount:0 mapping:ffff8805eb059200 index:0x0
flags: 0x3fff8000002828(uptodate|lru|private|writeback)
page dumped because: VM_BUG_ON_PAGE(!PageLocked(page))
page->mem_cgroup:ffff8806098e0800
------------[ cut here ]------------
kernel BUG at mm/filemap.c:833!
invalid opcode: 0000 [#1] SMP
Modules linked in: brd dax_pmem nd_pmem dax nd_btt nd_e820 libnvdimm
CPU: 0 PID: 2522 Comm: xfs_io Not tainted 4.7.0-rc2-00042-g4e1b2d52 #18
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS
rel-1.9.1-0-gb3ef39f-prebuilt.qemu-project.org 04/01/2014
task: ffff8805ebae4ec0 ti: ffff8805eba3c000 task.ti: ffff8805eba3c000
RIP: 0010:[<ffffffff811de115>] [<ffffffff811de115>] unlock_page+0xa5/0xb0
RSP: 0018:ffff8805eba3fa60 EFLAGS: 00010282
RAX: 0000000000000021 RBX: 0000000000000000 RCX: 0000000000000006
RDX: 0000000000000000 RSI: 0000000000000001 RDI: ffff8806109ce200
RBP: ffff8805eba3fa60 R08: 0000000000000001 R09: 0000000000000001
R10: ffff8805ebae4ec0 R11: 0000000000000001 R12: ffffea0017af04c0
R13: 0000000000028000 R14: ffffffffa00202c0 R15: ffff88060eff1200
FS: 00007f87a31cf700(0000) GS:ffff880610800000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f87a31e6000 CR3: 000000060da31000 CR4: 00000000001406f0
Stack:
ffff8805eba3fa98 ffffffff812bd782 ffff8805eba3fdb0 0000000000001000
ffffea0017af04c0 0000000000000000 0000000000000088 ffff8805eba3fbe0
ffffffff812c3ff1 ffff8805eba3fd00 0000000000028000 0000000c00000000
Call Trace:
[<ffffffff812bd782>] bdev_write_page+0xb2/0xe0 fs/block_dev.c:462
[<ffffffff812c3ff1>] __mpage_writepage+0x5c1/0x750 fs/mpage.c:604
[<ffffffff811eedbd>] write_cache_pages+0x20d/0x5f0 mm/page-writeback.c:2261
[<ffffffff812c3955>] mpage_writepages+0x75/0xe0 fs/mpage.c:703
[<ffffffff8137951b>] ext2_writepages+0x3b/0x40 fs/ext2/inode.c:887
[<ffffffff811f27a1>] do_writepages+0x21/0x30 mm/page-writeback.c:2361
[<ffffffff811e1396>] __filemap_fdatawrite_range+0xc6/0x100 mm/filemap.c:300
[<ffffffff811e1514>] filemap_write_and_wait_range+0x44/0x90 mm/filemap.c:490
[<ffffffff812a7707>] __generic_file_fsync+0x27/0x90 fs/libfs.c:937
[<ffffffff812a7789>] generic_file_fsync+0x19/0x40 fs/libfs.c:974
[<ffffffff81377e9e>] ext2_fsync+0x2e/0x70 fs/ext2/file.c:149
[<ffffffff812b549b>] vfs_fsync_range+0x4b/0xb0 fs/sync.c:195
[< inline >] vfs_fsync fs/sync.c:209
[<ffffffff812b555d>] do_fsync+0x3d/0x70 fs/sync.c:219
[< inline >] SYSC_fsync fs/sync.c:227
[<ffffffff812b5810>] SyS_fsync+0x10/0x20 fs/sync.c:225
[<ffffffff81acd33c>] entry_SYSCALL_64_fastpath+0x1f/0xbd
arch/x86/entry/entry_64.S:207
Code: 00 00 48 d3 ea 89 d2 48 8d 0c 92 48 8d 14 4a 48 8d 3c d0 31 d2
e8 bc fc f1 ff 5d c3 48 c7 c6 20 1d ec 81 4c 89 c7 e8 bb 8d 03 00 <0f>
0b 66 0f 1f 84 00 00 00 00 00 66 66 66 66 90 55 b9 08 00 00
RIP [<ffffffff811de115>] unlock_page+0xa5/0xb0 mm/filemap.c:833
RSP <ffff8805eba3fa60>
---[ end trace d419bf59bba263fb ]---
I'm happy to provide any additional info you need, or to test fixes.
Thanks,
- Ross
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply
* [PATCH][RESEND] md: Prevent IO hold during accessing to faulty raid5 array
From: Alexey Obitotskiy @ 2016-08-03 8:02 UTC (permalink / raw)
To: shli; +Cc: linux-raid
After array enters in faulty state (e.g. number of failed drives
becomes more then accepted for raid5 level) it sets error flags
(one of this flags is MD_CHANGE_PENDING). For internal metadata
arrays MD_CHANGE_PENDING cleared into md_update_sb, but not for
external metadata arrays. MD_CHANGE_PENDING flag set prevents to
finish all new or non-finished IOs to array and hold them in
pending state. In some cases this can leads to deadlock situation.
For example, we have faulty array (2 of 4 drives failed) and
udev handle array state changes and blkid started (or other
userspace application that used array to read/write) but unable
to finish reads due to IO hold. At the same time we unable to get
exclusive access to array (to stop array in our case) because
another external application still use this array.
Fix makes possible to return IO with errors immediately.
So external application can finish working with array and
give exclusive access to other applications to perform
required management actions with array.
Signed-off-by: Alexey Obitotskiy <aleksey.obitotskiy@intel.com>
---
drivers/md/raid5.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 6c1149d..99471b6 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -4692,7 +4692,9 @@ finish:
}
if (!bio_list_empty(&s.return_bi)) {
- if (test_bit(MD_CHANGE_PENDING, &conf->mddev->flags)) {
+ if (test_bit(MD_CHANGE_PENDING, &conf->mddev->flags) &&
+ (s.failed <= conf->max_degraded ||
+ conf->mddev->external == 0)) {
spin_lock_irq(&conf->device_lock);
bio_list_merge(&conf->return_bi, &s.return_bi);
spin_unlock_irq(&conf->device_lock);
--
2.7.4
^ permalink raw reply related
* Re: [PATCH] raid5: fix incorrectly counter of conf->empty_inactive_list_nr
From: liuzhengyuan @ 2016-08-03 5:51 UTC (permalink / raw)
To: NeilBrown; +Cc: shli, liuzhengyuang521, linux-raid, linux-kernel
Thanks for you replay.
I think it may be on the temp inactive list. An active sh was handled
and put to temp inactive list firstly, then moved to inactive list.
If sh is on the temp inactive list, sh->count is zero too.
------------------ Original ------------------
From: "NeilBrown"<neilb@suse.com>;
Date: Wed, Aug 3, 2016 08:44 AM
To: "ZhengYuan Liu"<liuzhengyuan@kylinos.cn>;
Cc: "shli"<shli@kernel.org>; "liuzhengyuang521"<liuzhengyuang521@gmail.com>; "linux-raid"<linux-raid@vger.kernel.org>; "linux-kernel"<linux-kernel@vger.kernel.org>; "ZhengYuan Liu"<liuzhengyuan@kylinos.cn>;
Subject: Re: [PATCH] raid5: fix incorrectly counter of conf->empty_inactive_list_nr
On Thu, Jul 28 2016, ZhengYuan Liu wrote:
> The counter conf->empty_inactive_list_nr is only used for determine if the
> raid5 is congested which is deal with in function raid5_congested().
> It was increased in get_free_stripe() when conf->inactive_list got to be
> empty and decreased in release_inactive_stripe_list() when splice
> temp_inactive_list to conf->inactive_list. However, this may have a
> problem when raid5_get_active_stripe or stripe_add_to_batch_list was called,
> because these two functions may call list_del_init(&sh->lru) to delete sh from
> "conf->inactive_list + hash" which may cause "conf->inactive_list + hash" to
> be empty when atomic_inc_not_zero(&sh->count) got false. So a check should be
> done at these two point and increase empty_inactive_list_nr accordingly.
> Otherwise the counter may get to be negative number which would influence
> async readahead from VFS.
>
> Signed-off-by: ZhengYuan Liu <liuzhengyuan@kylinos.cn>
> ---
> drivers/md/raid5.c | 11 +++++++++++
> 1 file changed, 11 insertions(+)
>
> diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
> index 7c53861..1656c44 100644
> --- a/drivers/md/raid5.c
> +++ b/drivers/md/raid5.c
> @@ -659,6 +659,7 @@ raid5_get_active_stripe(struct r5conf *conf, sector_t sector,
> {
> struct stripe_head *sh;
> int hash = stripe_hash_locks_hash(sector);
> + int inc_empty_inactive_list_flag;
>
> pr_debug("get_stripe, sector %llu\n", (unsigned long long)sector);
>
> @@ -703,7 +704,12 @@ raid5_get_active_stripe(struct r5conf *conf, sector_t sector,
> atomic_inc(&conf->active_stripes);
> BUG_ON(list_empty(&sh->lru) &&
> !test_bit(STRIPE_EXPANDING, &sh->state));
> + inc_empty_inactive_list_flag = 0;
> + if (!list_empty(conf->inactive_list + hash))
> + inc_empty_inactive_list_flag = 1;
> list_del_init(&sh->lru);
> + if (list_empty(conf->inactive_list + hash) && inc_empty_inactive_list_flag)
> + atomic_inc(&conf->empty_inactive_list_nr);
Maybe I'm forgetting an important detail, but this seems more
complicated than it needs to be.
The code just just confirmed that sh->count is zero, so sh must be on
the inactive list, mustn't it?
So inc_empty_inactive_list_flag can never be set to 1.
What am I missing? Could sh not be on the inactive list at this point?
Same for the code below.
NeilBrown
> if (sh->group) {
> sh->group->stripes_cnt--;
> sh->group = NULL;
> @@ -762,6 +768,7 @@ static void stripe_add_to_batch_list(struct r5conf *conf, struct stripe_head *sh
> sector_t head_sector, tmp_sec;
> int hash;
> int dd_idx;
> + int inc_empty_inactive_list_flag;
>
> if (!stripe_can_batch(sh))
> return;
> @@ -781,7 +788,11 @@ static void stripe_add_to_batch_list(struct r5conf *conf, struct stripe_head *sh
> atomic_inc(&conf->active_stripes);
> BUG_ON(list_empty(&head->lru) &&
> !test_bit(STRIPE_EXPANDING, &head->state));
> + if (!list_empty(conf->inactive_list + hash))
> + inc_empty_inactive_list_flag = 1;
> list_del_init(&head->lru);
> + if (list_empty(conf->inactive_list + hash) && inc_empty_inactive_list_flag)
> + atomic_inc(&conf->empty_inactive_list_nr);
> if (head->group) {
> head->group->stripes_cnt--;
> head->group = NULL;
> --
> 1.9.1
^ permalink raw reply
* AW: [PATCH 0/4] Add AVX512 optimized gen_syndrome and recovery functions
From: Markus Stockhausen @ 2016-08-03 5:44 UTC (permalink / raw)
To: Gayatri Kammela, linux-raid@vger.kernel.org
Cc: shli@kernel.org, linux-kernel@vger.kernel.org, hpa@zytor.com,
james.t.kukunas@linux.intel.com, fenghua.yu@intel.com,
megha.dey@linux.intel.com, ravi.v.shankar@intel.com
In-Reply-To: <1470180539-7417-1-git-send-email-gayatri.kammela@intel.com>
[-- Attachment #1: Type: text/plain, Size: 1585 bytes --]
> Von: linux-raid-owner@vger.kernel.org [linux-raid-owner@vger.kernel.org]" im Auftrag von "Gayatri Kammela [gayatri.kammela@intel.com]
> Gesendet: Mittwoch, 3. August 2016 01:28
> An: linux-raid@vger.kernel.org
> Cc: shli@kernel.org; linux-kernel@vger.kernel.org; hpa@zytor.com; james.t.kukunas@linux.intel.com; fenghua.yu@intel.com; megha.dey@linux.intel.com; ravi.v.shankar@intel.com; Gayatri Kammela
> Betreff: [PATCH 0/4] Add AVX512 optimized gen_syndrome and recovery functions
>
> This is the patch set for adding AVX512 optimized gen_syndrome
> and recovery functions.
>
> Optimization of RAID6 using AVX512 instructions should improve the
> RAID6 performance.These patches are tested and observed the improvement
> in performance.
Hi Gayatri,
as you already implemented the gen_syndrome() functions it should be a piece
of cake to add the xor_syndrome() ones. Only if these are implemented we can
make use of Read-Modify-Write operations if the kernel chooses an processor
optimized algorithm. They are already in the SSE2 path but are still missing from
the current AVX2 implementation.
More infos here:
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=fe5cbc6e06c7d8b3a86f6f5491d74766bb5c2827
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=a582564b24bec0443b5c5ff43ee6d1258f8bd658
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=0e833e697bcf4c2f3f7fb9fce39d08cd4439e5d7
It would give the final touch to the patches.
Best regards.
Markus
=
[-- Attachment #2: InterScan_Disclaimer.txt --]
[-- Type: text/plain, Size: 1650 bytes --]
****************************************************************************
Diese E-Mail enthält vertrauliche und/oder rechtlich geschützte
Informationen. Wenn Sie nicht der richtige Adressat sind oder diese E-Mail
irrtümlich erhalten haben, informieren Sie bitte sofort den Absender und
vernichten Sie diese Mail. Das unerlaubte Kopieren sowie die unbefugte
Weitergabe dieser Mail ist nicht gestattet.
Ãber das Internet versandte E-Mails können unter fremden Namen erstellt oder
manipuliert werden. Deshalb ist diese als E-Mail verschickte Nachricht keine
rechtsverbindliche Willenserklärung.
Collogia
Unternehmensberatung AG
Ubierring 11
D-50678 Köln
Vorstand:
Kadir Akin
Dr. Michael Höhnerbach
Vorsitzender des Aufsichtsrates:
Hans Kristian Langva
Registergericht: Amtsgericht Köln
Registernummer: HRB 52 497
This e-mail may contain confidential and/or privileged information. If you
are not the intended recipient (or have received this e-mail in error)
please notify the sender immediately and destroy this e-mail. Any
unauthorized copying, disclosure or distribution of the material in this
e-mail is strictly forbidden.
e-mails sent over the internet may have been written under a wrong name or
been manipulated. That is why this message sent as an e-mail is not a
legally binding declaration of intention.
Collogia
Unternehmensberatung AG
Ubierring 11
D-50678 Köln
executive board:
Kadir Akin
Dr. Michael Höhnerbach
President of the supervisory board:
Hans Kristian Langva
Registry office: district court Cologne
Register number: HRB 52 497
****************************************************************************
^ permalink raw reply
* Re: [PATCH 3/3] MD: hold mddev lock for md-cluster receive thread
From: Guoqing Jiang @ 2016-08-03 3:42 UTC (permalink / raw)
To: NeilBrown, Guoqing Jiang, Shaohua Li; +Cc: linux-raid
In-Reply-To: <87shumpvbd.fsf@notabene.neil.brown.name>
On 08/03/2016 08:09 AM, NeilBrown wrote:
> On Tue, Aug 02 2016, Guoqing Jiang wrote:
>>> Does it work if we move the mddev lock to
>>> process_recvd_msg?
>> I tried that, but It still have lock issue, eg, when node B and C have
>> status
>> as "resync=PENDING", then try to stop the resyncing array in node A.
>>
> Maybe the reconfig_mutex locking needs to go down in
> process_suspend_info() ?? That is the only part that calls quiesce.
Yes, but with this change, I still have lock issue for below steps:
1. create a resyning array in nodeA
2. Assemble the array in node B and nodeC
I can see A can't continue perform resync while C can't assemble
array successfully.
Thanks,
Guoqing
^ permalink raw reply
* Re: [PATCH 3/3] MD: hold mddev lock for md-cluster receive thread
From: Guoqing Jiang @ 2016-08-03 3:18 UTC (permalink / raw)
To: Shaohua Li; +Cc: linux-raid, NeilBrown
In-Reply-To: <20160802224456.GD98613@kernel.org>
On 08/03/2016 06:44 AM, Shaohua Li wrote:
> On Tue, Aug 02, 2016 at 05:52:41PM +0800, Guoqing Jiang wrote:
>>
>> On 08/02/2016 05:45 AM, Shaohua Li wrote:
>>> On Mon, Aug 01, 2016 at 04:38:59PM +0800, Guoqing Jiang wrote:
>>>> Hi,
>>>>
>>>> On 07/31/2016 07:54 AM, shli@kernel.org wrote:
>>>>> From: Shaohua Li <shli@fb.com>
>>>>>
>>>>> md-cluster receive thread calls .quiesce too, let it hold mddev lock.
>>>> I'd suggest hold on for the patchset, I can find lock problem easily with
>>>> the patchset applied. Take a resyncing clusteed raid1 as example.
>>>>
>>>> md127_raid1 thread held reconfig_mutex then update sb, so it needs dlm
>>>> token lock. Meanwhile md127_resync thread got token lock and wants
>>>> EX on ack lock but recv_daemon can't release ack lock since recv_daemon
>>>> doesn't get reconfig_mutex.
>>> Thansk, I'll drop this one. Other two patches are still safe for md-cluster,
>>> right?
>> From the latest test, I can't find lock issues with the first two patches,
>> but I doubt it would have side effect for the performance of resync.
> That's not need to be worried. The .quiesce() call is way heavier than
> hold/release the mutex.
>
>>> I really hope to have consistent locking for .quiesce. For the
>>> process_recvd_msg, I'm wondering what's protecting the datas? for example,
>>> md-cluster uses md_find_rdev_nr_rcu, which access the disks list without
>>> locking. Is there a race?
>> Yes, it should be protected by rcu lock, I will post a patch for it, thanks
>> for reminder.
>>
>>> Does it work if we move the mddev lock to
>>> process_recvd_msg?
>> I tried that, but It still have lock issue, eg, when node B and C have
>> status
>> as "resync=PENDING", then try to stop the resyncing array in node A.
> can you elaborate it?
I am not lucky enough to do the same test as yesterday, but I even
can't assemble clustered raid1 in other nodes.
1. node135: mdadm --create md0 --bitmap=clustered --raid-devices=2
--level=mirror /dev/vdb /dev/vdc
2. Then node240 and node244 try to assemble it, but both of them would hang.
betalinux135:~ # cat /proc/mdstat
Personalities : [raid1]
md127 : active raid1 vdc[1] vdb[0]
2095104 blocks super 1.2 [2/2] [UU]
[=>...................] resync = 6.2% (130816/2095104)
finish=1.5min speed=21802K/sec
bitmap: 1/1 pages [4KB], 65536KB chunk
unused devices: <none>
betalinux135:~ # ssh betalinux240
Last login: Wed Aug 3 11:11:47 2016 from 192.168.100.1
betalinux240:~ # ps aux|grep md|grep D
root 1901 0.0 0.2 20896 2592 pts/0 D+ 11:12 0:00 mdadm
--assemble md0 /dev/vdb /dev/vdc
root 1914 0.0 0.2 19852 2032 ? S 11:12 0:00
/sbin/mdadm --incremental --export /dev/vdb --offroot ${DEVLINKS}
root 1915 0.0 0.1 19852 1940 ? S 11:12 0:00
/sbin/mdadm --incremental --export /dev/vdc --offroot ${DEVLINKS}
betalinux240:~ # cat /proc/1901/stack
[<ffffffffa069d4cb>] dlm_lock_sync+0x6b/0x80 [md_cluster]
[<ffffffffa069e7e6>] join+0x286/0x430 [md_cluster]
[<ffffffffa068a9f4>] bitmap_create+0x5f4/0x980 [md_mod]
[<ffffffffa0682f35>] md_run+0x595/0xa60 [md_mod]
[<ffffffffa06834cf>] do_md_run+0xf/0xb0 [md_mod]
[<ffffffffa0686781>] md_ioctl+0x11b1/0x1680 [md_mod]
[<ffffffff812ed158>] blkdev_ioctl+0x258/0x920
[<ffffffff8122f81d>] block_ioctl+0x3d/0x40
[<ffffffff8120ac0d>] do_vfs_ioctl+0x2cd/0x4a0
[<ffffffff8120ae54>] SyS_ioctl+0x74/0x80
[<ffffffff815e936e>] entry_SYSCALL_64_fastpath+0x12/0x6d
[<ffffffffffffffff>] 0xffffffffffffffff
betalinux240:~ # exit
logout
Connection to betalinux240 closed.
betalinux135:~ # ssh betalinux244
Last login: Wed Aug 3 11:11:49 2016 from 192.168.100.1
betalinux244:~ # ps aux|grep md|grep D
root 1903 0.0 0.2 20896 2660 pts/0 D+ 11:12 0:00 mdadm
--assemble md0 /dev/vdb /dev/vdc
root 1923 0.0 0.2 19852 2112 ? S 11:12 0:00
/sbin/mdadm --incremental --export /dev/vdc --offroot ${DEVLINKS}
root 1928 0.0 0.2 19852 2092 ? S 11:12 0:00
/sbin/mdadm --incremental --export /dev/vdb --offroot ${DEVLINKS}
root 1938 0.0 0.0 0 0 ? D 11:12 0:00
[md0_cluster_rec]
betalinux244:~ # cat /proc/1903/stack
[<ffffffffa06904cb>] dlm_lock_sync+0x6b/0x80 [md_cluster]
[<ffffffffa06904fb>] lock_token+0x1b/0x50 [md_cluster]
[<ffffffffa06905fd>] metadata_update_start+0x3d/0xb0 [md_cluster]
[<ffffffffa06751ee>] md_update_sb.part.50+0x8e/0x810 [md_mod]
[<ffffffffa067646e>] md_allow_write+0x6e/0xc0 [md_mod]
[<ffffffffa0676505>] do_md_run+0x45/0xb0 [md_mod]
[<ffffffffa0679781>] md_ioctl+0x11b1/0x1680 [md_mod]
[<ffffffff812ed158>] blkdev_ioctl+0x258/0x920
[<ffffffff8122f81d>] block_ioctl+0x3d/0x40
[<ffffffff8120ac0d>] do_vfs_ioctl+0x2cd/0x4a0
[<ffffffff8120ae54>] SyS_ioctl+0x74/0x80
[<ffffffff815e936e>] entry_SYSCALL_64_fastpath+0x12/0x6d
[<ffffffffffffffff>] 0xffffffffffffffff
betalinux244:~ # cat /proc/1938/stack
[<ffffffffa0691d90>] recv_daemon+0xc0/0x4a0 [md_cluster]
[<ffffffffa0670d30>] md_thread+0x130/0x150 [md_mod]
[<ffffffff810995ed>] kthread+0xbd/0xe0
[<ffffffff815e96bf>] ret_from_fork+0x3f/0x70
[<ffffffff81099530>] kthread+0x0/0xe0
[<ffffffffffffffff>] 0xffffffffffffffff
> For the raid5-cache issue, ignoring the md-cluster .quiesce() call is fine
> currently as we don't support raid5 cluster. We probably should add another
> parameter for .quiesce to indicate if the mddev lock is hold in the future.
Pls update me with the change in future, since it may have huge influence
for md-cluster.
Thanks,
GUoqing
^ permalink raw reply
* Re: WARNING: CPU: 4 PID: 10512 at drivers/md/raid5-cache.c:728 r5l_do_reclaim+0x415/0x430 [raid456]
From: Guoqing Jiang @ 2016-08-03 2:46 UTC (permalink / raw)
To: yizhan, linux-raid
In-Reply-To: <bd2bb3a9-f970-7726-00b7-1956d2223ef1@redhat.com>
On 08/02/2016 09:31 PM, yizhan wrote:
>
>> I tried with latest Linus's tree
>> (731c7d3a205ba89b475b2aa71b5f13dd6ae3de56), but still can't find the
>> warning.
>>
>> linux241:~ # uname -r
>> 4.7.0-11-default+
>> linux241:~ # mdadm --version
>> mdadm - v3.4-41-gf96b130 - 30th March 2016
>>
>> The biggest difference is that I am using VM machine while you were
>> testing with real hardware, though I am not
>> sure it was caused by hardware or not. Do you always see the
>> "couldn't update array info" info during test? If so,
>> pls try to make it disappear.
>>
>> Thanks,
>> Guoqing
> May be it's env related, I have tried on another PC which with the
> same kernel/mdadm version and cannot reproduce it.
I guess you can check the difference of hardware about why it can't be
happen with another PC.
Regards,
Guoqing
^ permalink raw reply
* Re: [PATCH 4/8] md-cluster: introduce dlm_lock_sync_interruptible to fix tasks hang
From: Guoqing Jiang @ 2016-08-03 2:39 UTC (permalink / raw)
To: Shaohua Li; +Cc: linux-raid
In-Reply-To: <20160802223631.GC98613@kernel.org>
On 08/03/2016 06:36 AM, Shaohua Li wrote:
> On Mon, Aug 01, 2016 at 11:24:34PM -0400, Guoqing Jiang wrote:
>>
>> On 08/01/2016 06:20 PM, Shaohua Li wrote:
>>> On Thu, Jul 28, 2016 at 02:16:48AM -0400, Guoqing Jiang wrote:
>>>> When some node leaves cluster, then it's bitmap need to be
>>>> synced by another node, so "md*_recover" thread is triggered
>>>> for the purpose. However, with below steps. we can find tasks
>>>> hang happened either in B or C.
>>>>
>>>> 1. Node A create a resyncing cluster raid1, assemble it in
>>>> other two nodes (B and C).
>>>> 2. stop array in B and C.
>>>> 3. stop array in A.
>>>>
>>>> linux44:~ # ps aux|grep md|grep D
>>>> root 5938 0.0 0.1 19852 1964 pts/0 D+ 14:52 0:00 mdadm -S md0
>>>> root 5939 0.0 0.0 0 0 ? D 14:52 0:00 [md0_recover]
>>>>
>>>> linux44:~ # cat /proc/5939/stack
>>>> [<ffffffffa04cf321>] dlm_lock_sync+0x71/0x90 [md_cluster]
>>>> [<ffffffffa04d0705>] recover_bitmaps+0x125/0x220 [md_cluster]
>>>> [<ffffffffa052105d>] md_thread+0x16d/0x180 [md_mod]
>>>> [<ffffffff8107ad94>] kthread+0xb4/0xc0
>>>> [<ffffffff8152a518>] ret_from_fork+0x58/0x90
>>>>
>>>> linux44:~ # cat /proc/5938/stack
>>>> [<ffffffff8107afde>] kthread_stop+0x6e/0x120
>>>> [<ffffffffa0519da0>] md_unregister_thread+0x40/0x80 [md_mod]
>>>> [<ffffffffa04cfd20>] leave+0x70/0x120 [md_cluster]
>>>> [<ffffffffa0525e24>] md_cluster_stop+0x14/0x30 [md_mod]
>>>> [<ffffffffa05269ab>] bitmap_free+0x14b/0x150 [md_mod]
>>>> [<ffffffffa0523f3b>] do_md_stop+0x35b/0x5a0 [md_mod]
>>>> [<ffffffffa0524e83>] md_ioctl+0x873/0x1590 [md_mod]
>>>> [<ffffffff81288464>] blkdev_ioctl+0x214/0x7d0
>>>> [<ffffffff811dd3dd>] block_ioctl+0x3d/0x40
>>>> [<ffffffff811b92d4>] do_vfs_ioctl+0x2d4/0x4b0
>>>> [<ffffffff811b9538>] SyS_ioctl+0x88/0xa0
>>>> [<ffffffff8152a5c9>] system_call_fastpath+0x16/0x1b
>>>>
>>>> The problem is caused by recover_bitmaps can't reliably abort
>>>> when the thread is unregistered. So dlm_lock_sync_interruptible
>>>> is introduced to detect the thread's situation to fix the problem.
>>>>
>>>> Reviewed-by: NeilBrown <neilb@suse.com>
>>>> Signed-off-by: Guoqing Jiang <gqjiang@suse.com>
>>>> ---
>>>> drivers/md/md-cluster.c | 38 +++++++++++++++++++++++++++++++++++++-
>>>> 1 file changed, 37 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/drivers/md/md-cluster.c b/drivers/md/md-cluster.c
>>>> index ea2699e..f3d584e 100644
>>>> --- a/drivers/md/md-cluster.c
>>>> +++ b/drivers/md/md-cluster.c
>>>> @@ -10,6 +10,8 @@
>>>> #include <linux/module.h>
>>>> +#include <linux/completion.h>
>>>> +#include <linux/kthread.h>
>>>> #include <linux/dlm.h>
>>>> #include <linux/sched.h>
>>>> #include <linux/raid/md_p.h>
>>>> @@ -141,6 +143,40 @@ static int dlm_unlock_sync(struct dlm_lock_resource *res)
>>>> return dlm_lock_sync(res, DLM_LOCK_NL);
>>>> }
>>>> +/* An variation of dlm_lock_sync, which make lock request could
>>>> + * be interrupted */
>>>> +static int dlm_lock_sync_interruptible(struct dlm_lock_resource *res, int mode,
>>>> + struct mddev *mddev)
>>>> +{
>>>> + int ret = 0;
>>>> +
>>>> + ret = dlm_lock(res->ls, mode, &res->lksb,
>>>> + res->flags, res->name, strlen(res->name),
>>>> + 0, sync_ast, res, res->bast);
>>>> + if (ret)
>>>> + return ret;
>>>> +
>>>> + wait_event(res->completion.wait,
>>>> + res->completion.done || kthread_should_stop());
>>> can you convert it to a waitq? Directly using the .wait/.done of completion is
>>> really intrusive.
>> Maybe, but we still need completion for dlm_lock_resource otherwise there
>> are different types of dlm_lock_resource, we also need to keep align with
>> sync_ast as dlm_lock_sync did.
> Yes, we need a waitq and variable like completion.done to indicate the event is
> done, and convert the completion API to waitq API in other places like
> sync_ast. The point is not using the opaque data structure of 'struct
> completion'. Diving into implementation details of a unrelated data structure
> (completion here) is really intrusive.
I don't want to argue about the intrusive, but we have to create something
which could be achieved by the existed thing.
OTOH, convert completion to waitqueue should be done in a new patch,
and it is a big change though achieveable, we need to do full test for it.
Thanks,
Guoqing
^ permalink raw reply
* [PATCH V2 1/8] md-cluster: call md_kick_rdev_from_array once ack failed
From: Guoqing Jiang @ 2016-08-03 2:26 UTC (permalink / raw)
To: shli; +Cc: linux-raid, Guoqing Jiang
In-Reply-To: <1469686612-16126-1-git-send-email-gqjiang@suse.com>
The new_disk_ack could return failure if WAITING_FOR_NEWDISK
is not set, so we need to kick the dev from array in case
failure happened.
And we missed to check err before call new_disk_ack othwise
we could kick a rdev which isn't in array, thanks for the
reminder from Shaohua.
Reviewed-by: NeilBrown <neilb@suse.com>
Signed-off-by: Guoqing Jiang <gqjiang@suse.com>
---
Changes:
1. add the check for "err" before call new_disk_ack.
drivers/md/md.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 2c3ab6f..e6eb66b 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -6102,7 +6102,11 @@ static int add_new_disk(struct mddev *mddev, mdu_disk_info_t *info)
if (mddev_is_clustered(mddev)) {
if (info->state & (1 << MD_DISK_CANDIDATE))
- md_cluster_ops->new_disk_ack(mddev, (err == 0));
+ if (!err) {
+ err = md_cluster_ops->new_disk_ack(mddev, (err == 0));
+ if (err)
+ md_kick_rdev_from_array(rdev);
+ }
else {
if (err)
md_cluster_ops->add_new_disk_cancel(mddev);
--
2.6.2
^ permalink raw reply related
* Re: [PATCH 1/8] md-cluster: call md_kick_rdev_from_array once ack failed
From: Guoqing Jiang @ 2016-08-03 2:15 UTC (permalink / raw)
To: Shaohua Li; +Cc: linux-raid
In-Reply-To: <20160802221708.GB98613@kernel.org>
On 08/03/2016 06:17 AM, Shaohua Li wrote:
> On Mon, Aug 01, 2016 at 09:29:21PM -0400, Guoqing Jiang wrote:
>>
>> On 08/01/2016 05:58 PM, Shaohua Li wrote:
>>> On Thu, Jul 28, 2016 at 02:16:45AM -0400, Guoqing Jiang wrote:
>>>> The new_disk_ack could return failure if WAITING_FOR_NEWDISK
>>>> is not set, so we need to kick the dev from array in case
>>>> failure happened.
>>>>
>>>> Reviewed-by: NeilBrown <neilb@suse.com>
>>>> Signed-off-by: Guoqing Jiang <gqjiang@suse.com>
>>>> ---
>>>> drivers/md/md.c | 8 +++++---
>>>> 1 file changed, 5 insertions(+), 3 deletions(-)
>>>>
>>>> diff --git a/drivers/md/md.c b/drivers/md/md.c
>>>> index 2ed547f..743cd21 100644
>>>> --- a/drivers/md/md.c
>>>> +++ b/drivers/md/md.c
>>>> @@ -6092,9 +6092,11 @@ static int add_new_disk(struct mddev *mddev, mdu_disk_info_t *info)
>>>> export_rdev(rdev);
>>>> if (mddev_is_clustered(mddev)) {
>>>> - if (info->state & (1 << MD_DISK_CANDIDATE))
>>>> - md_cluster_ops->new_disk_ack(mddev, (err == 0));
>>>> - else {
>>>> + if (info->state & (1 << MD_DISK_CANDIDATE)) {
>>> if err != 0, we already do export_rdev, do we need to do md_kick_rdev_from_array in that case?
>> I suppose you mean the export_rdev before new_disk_ack, it doesn't need to
>> call md_kick_rdev_from_array
>> since we don't bind rdev to array successfully.
>>
>> err = bind_rdev_to_array(rdev, mddev);
>>
>> if (err)
>> *export_rdev*(rdev);
> Let's assume bind_rdev_to_array fails, err != 0, we export_rdev
>> if (mddev_is_clustered(mddev)) {
>> if (info->state & (1 << MD_DISK_CANDIDATE))
>> md_cluster_ops->new_disk_ack(mddev, (err == 0));
>
> we don't check err here, so we could call ->new_disk_ack, then if
> new_disk_ack() fails, we will call md_kick_rdev_from_array(rdev) again with
> your patch. we are kicking out rdev which isn't bound yet in this case.
Thanks, we should also check err before new_disk_ack for the case.
I will send a new patch for it.
Regards,
Guoqing
^ permalink raw reply
* Re: [PATCH] raid5: fix incorrectly counter of conf->empty_inactive_list_nr
From: NeilBrown @ 2016-08-03 0:44 UTC (permalink / raw)
Cc: shli, liuzhengyuang521, linux-raid, linux-kernel, ZhengYuan Liu
In-Reply-To: <1469686934-1937-1-git-send-email-liuzhengyuan@kylinos.cn>
[-- Attachment #1: Type: text/plain, Size: 3372 bytes --]
On Thu, Jul 28 2016, ZhengYuan Liu wrote:
> The counter conf->empty_inactive_list_nr is only used for determine if the
> raid5 is congested which is deal with in function raid5_congested().
> It was increased in get_free_stripe() when conf->inactive_list got to be
> empty and decreased in release_inactive_stripe_list() when splice
> temp_inactive_list to conf->inactive_list. However, this may have a
> problem when raid5_get_active_stripe or stripe_add_to_batch_list was called,
> because these two functions may call list_del_init(&sh->lru) to delete sh from
> "conf->inactive_list + hash" which may cause "conf->inactive_list + hash" to
> be empty when atomic_inc_not_zero(&sh->count) got false. So a check should be
> done at these two point and increase empty_inactive_list_nr accordingly.
> Otherwise the counter may get to be negative number which would influence
> async readahead from VFS.
>
> Signed-off-by: ZhengYuan Liu <liuzhengyuan@kylinos.cn>
> ---
> drivers/md/raid5.c | 11 +++++++++++
> 1 file changed, 11 insertions(+)
>
> diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
> index 7c53861..1656c44 100644
> --- a/drivers/md/raid5.c
> +++ b/drivers/md/raid5.c
> @@ -659,6 +659,7 @@ raid5_get_active_stripe(struct r5conf *conf, sector_t sector,
> {
> struct stripe_head *sh;
> int hash = stripe_hash_locks_hash(sector);
> + int inc_empty_inactive_list_flag;
>
> pr_debug("get_stripe, sector %llu\n", (unsigned long long)sector);
>
> @@ -703,7 +704,12 @@ raid5_get_active_stripe(struct r5conf *conf, sector_t sector,
> atomic_inc(&conf->active_stripes);
> BUG_ON(list_empty(&sh->lru) &&
> !test_bit(STRIPE_EXPANDING, &sh->state));
> + inc_empty_inactive_list_flag = 0;
> + if (!list_empty(conf->inactive_list + hash))
> + inc_empty_inactive_list_flag = 1;
> list_del_init(&sh->lru);
> + if (list_empty(conf->inactive_list + hash) && inc_empty_inactive_list_flag)
> + atomic_inc(&conf->empty_inactive_list_nr);
Maybe I'm forgetting an important detail, but this seems more
complicated than it needs to be.
The code just just confirmed that sh->count is zero, so sh must be on
the inactive list, mustn't it?
So inc_empty_inactive_list_flag can never be set to 1.
What am I missing? Could sh not be on the inactive list at this point?
Same for the code below.
NeilBrown
> if (sh->group) {
> sh->group->stripes_cnt--;
> sh->group = NULL;
> @@ -762,6 +768,7 @@ static void stripe_add_to_batch_list(struct r5conf *conf, struct stripe_head *sh
> sector_t head_sector, tmp_sec;
> int hash;
> int dd_idx;
> + int inc_empty_inactive_list_flag;
>
> if (!stripe_can_batch(sh))
> return;
> @@ -781,7 +788,11 @@ static void stripe_add_to_batch_list(struct r5conf *conf, struct stripe_head *sh
> atomic_inc(&conf->active_stripes);
> BUG_ON(list_empty(&head->lru) &&
> !test_bit(STRIPE_EXPANDING, &head->state));
> + if (!list_empty(conf->inactive_list + hash))
> + inc_empty_inactive_list_flag = 1;
> list_del_init(&head->lru);
> + if (list_empty(conf->inactive_list + hash) && inc_empty_inactive_list_flag)
> + atomic_inc(&conf->empty_inactive_list_nr);
> if (head->group) {
> head->group->stripes_cnt--;
> head->group = NULL;
> --
> 1.9.1
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 818 bytes --]
^ permalink raw reply
* Re: [PATCH 3/3] MD: hold mddev lock for md-cluster receive thread
From: NeilBrown @ 2016-08-03 0:09 UTC (permalink / raw)
To: Guoqing Jiang, Shaohua Li; +Cc: linux-raid
In-Reply-To: <57A06D69.2040703@suse.com>
[-- Attachment #1: Type: text/plain, Size: 416 bytes --]
On Tue, Aug 02 2016, Guoqing Jiang wrote:
>
>> Does it work if we move the mddev lock to
>> process_recvd_msg?
>
> I tried that, but It still have lock issue, eg, when node B and C have
> status
> as "resync=PENDING", then try to stop the resyncing array in node A.
>
Maybe the reconfig_mutex locking needs to go down in
process_suspend_info() ?? That is the only part that calls quiesce.
NeilBrown
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 818 bytes --]
^ permalink raw reply
* Re: [PATCH 2/3] MD: hold mddev lock to change bitmap location
From: NeilBrown @ 2016-08-03 0:03 UTC (permalink / raw)
To: shli, linux-raid; +Cc: Shaohua Li
In-Reply-To: <13390282c96961ddd675199c2826f36a44bfa8aa.1469922791.git.shli@fb.com>
[-- Attachment #1: Type: text/plain, Size: 3257 bytes --]
On Sun, Jul 31 2016, shli@kernel.org wrote:
> From: Shaohua Li <shli@fb.com>
>
> Changing the location changes a lot of things. Holding the lock to avoid race.
> This makes the .quiesce called with mddev lock hold too.
>
> Cc: NeilBrown <neilb@suse.com>
> Signed-off-by: Shaohua Li <shli@fb.com>
Acked-by: NeilBrown <neilb@suse.com>
Yes, I think this is justified. As you say, location_store is a fairly
significant change.
Thanks,
NeilBrown
> ---
> drivers/md/bitmap.c | 47 +++++++++++++++++++++++++++++++++--------------
> 1 file changed, 33 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
> index 6fff794..13041ee 100644
> --- a/drivers/md/bitmap.c
> +++ b/drivers/md/bitmap.c
> @@ -2183,19 +2183,29 @@ location_show(struct mddev *mddev, char *page)
> static ssize_t
> location_store(struct mddev *mddev, const char *buf, size_t len)
> {
> + int rv;
>
> + rv = mddev_lock(mddev);
> + if (rv)
> + return rv;
> if (mddev->pers) {
> - if (!mddev->pers->quiesce)
> - return -EBUSY;
> - if (mddev->recovery || mddev->sync_thread)
> - return -EBUSY;
> + if (!mddev->pers->quiesce) {
> + rv = -EBUSY;
> + goto out;
> + }
> + if (mddev->recovery || mddev->sync_thread) {
> + rv = -EBUSY;
> + goto out;
> + }
> }
>
> if (mddev->bitmap || mddev->bitmap_info.file ||
> mddev->bitmap_info.offset) {
> /* bitmap already configured. Only option is to clear it */
> - if (strncmp(buf, "none", 4) != 0)
> - return -EBUSY;
> + if (strncmp(buf, "none", 4) != 0) {
> + rv = -EBUSY;
> + goto out;
> + }
> if (mddev->pers) {
> mddev->pers->quiesce(mddev, 1);
> bitmap_destroy(mddev);
> @@ -2214,21 +2224,25 @@ location_store(struct mddev *mddev, const char *buf, size_t len)
> /* nothing to be done */;
> else if (strncmp(buf, "file:", 5) == 0) {
> /* Not supported yet */
> - return -EINVAL;
> + rv = -EINVAL;
> + goto out;
> } else {
> - int rv;
> if (buf[0] == '+')
> rv = kstrtoll(buf+1, 10, &offset);
> else
> rv = kstrtoll(buf, 10, &offset);
> if (rv)
> - return rv;
> - if (offset == 0)
> - return -EINVAL;
> + goto out;
> + if (offset == 0) {
> + rv = -EINVAL;
> + goto out;
> + }
> if (mddev->bitmap_info.external == 0 &&
> mddev->major_version == 0 &&
> - offset != mddev->bitmap_info.default_offset)
> - return -EINVAL;
> + offset != mddev->bitmap_info.default_offset) {
> + rv = -EINVAL;
> + goto out;
> + }
> mddev->bitmap_info.offset = offset;
> if (mddev->pers) {
> struct bitmap *bitmap;
> @@ -2245,7 +2259,7 @@ location_store(struct mddev *mddev, const char *buf, size_t len)
> mddev->pers->quiesce(mddev, 0);
> if (rv) {
> bitmap_destroy(mddev);
> - return rv;
> + goto out;
> }
> }
> }
> @@ -2257,6 +2271,11 @@ location_store(struct mddev *mddev, const char *buf, size_t len)
> set_bit(MD_CHANGE_DEVS, &mddev->flags);
> md_wakeup_thread(mddev->thread);
> }
> + rv = 0;
> +out:
> + mddev_unlock(mddev);
> + if (rv)
> + return rv;
> return len;
> }
>
> --
> 2.7.4
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 818 bytes --]
^ permalink raw reply
* Re: [PATCH 1/3] MD: hold mddev lock for .quiesce in md_do_sync
From: NeilBrown @ 2016-08-02 23:47 UTC (permalink / raw)
To: shli, linux-raid; +Cc: Shaohua Li
In-Reply-To: <515fa68e5c4784b08f2ce99c082c923f6b02a3c9.1469922791.git.shli@fb.com>
[-- Attachment #1: Type: text/plain, Size: 1465 bytes --]
On Sun, Jul 31 2016, shli@kernel.org wrote:
> From: Shaohua Li <shli@fb.com>
>
> .quiesce is called with mddev lock hold at most places. There are few
> exceptions. Calling .quesce without the lock hold could create races. For
> example, the .quesce of raid1 can't be recursively. The purpose of the patches
> is to fix a race in raid5-cache. The raid5-cache .quesce will write md
> superblock and should be called with mddev lock hold.
>
> Cc: NeilBrown <neilb@suse.com>
> Signed-off-by: Shaohua Li <shli@fb.com>
Acked-by: NeilBrown <neilb@suse.com>
This should be safe but I'm not sure I really like it.
The raid1 quiesce could be changed so that it can be called recursively.
The raid5-cache situation would be harder to get right and maybe this is
the best solution... It's just that 'quiesce' should be a fairly
light-weight operation, just waiting for pending requests to flush. It
shouldn't really *need* a lock.
NeilBrown
> ---
> drivers/md/md.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/drivers/md/md.c b/drivers/md/md.c
> index 2c3ab6f..0550445 100644
> --- a/drivers/md/md.c
> +++ b/drivers/md/md.c
> @@ -7945,8 +7945,10 @@ void md_do_sync(struct md_thread *thread)
> * region.
> */
> if (mddev->bitmap) {
> + mddev_lock_nointr(mddev);
> mddev->pers->quiesce(mddev, 1);
> mddev->pers->quiesce(mddev, 0);
> + mddev_unlock(mddev);
> }
> }
>
> --
> 2.7.4
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 818 bytes --]
^ permalink raw reply
* [PATCH 4/4] (DO NOT APPLY) lib/raid6: Add unroll by 8 to AVX512 optimized gen_syndrome functions
From: Gayatri Kammela @ 2016-08-02 23:32 UTC (permalink / raw)
To: linux-raid
Cc: shli, linux-kernel, hpa, james.t.kukunas, fenghua.yu, megha.dey,
ravi.v.shankar, Gayatri Kammela
Optimize RAID6 gen_syndrome functions by further unrolling by 8 to take
advantage of all the 32 ZMM registers.
Note: In theory avx512 unroll by 8 gen_syndrome function should perfom
better than the rest of gen_syndrome functions, but it is outperformed
by avx512 unroll by 4 gen_syndrome function when tested in user as well
as kernel space.
This is posted for reference only, to allow others to make their own
experiments.
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Jim Kukunas <james.t.kukunas@linux.intel.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Signed-off-by: Gayatri Kammela <gayatri.kammela@intel.com>
---
include/linux/raid/pq.h | 1 +
lib/raid6/algos.c | 1 +
lib/raid6/avx512.c | 172 ++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 174 insertions(+)
diff --git a/include/linux/raid/pq.h b/include/linux/raid/pq.h
index 1abd895..b4db38e 100644
--- a/include/linux/raid/pq.h
+++ b/include/linux/raid/pq.h
@@ -105,6 +105,7 @@ extern const struct raid6_calls raid6_avx2x4;
extern const struct raid6_calls raid6_avx512x1;
extern const struct raid6_calls raid6_avx512x2;
extern const struct raid6_calls raid6_avx512x4;
+extern const struct raid6_calls raid6_avx512x8;
extern const struct raid6_calls raid6_tilegx8;
struct raid6_recov_calls {
diff --git a/lib/raid6/algos.c b/lib/raid6/algos.c
index 149d947..85ba18a 100644
--- a/lib/raid6/algos.c
+++ b/lib/raid6/algos.c
@@ -67,6 +67,7 @@ const struct raid6_calls * const raid6_algos[] = {
&raid6_avx512x1,
&raid6_avx512x2,
&raid6_avx512x4,
+ &raid6_avx512x8,
#endif
#endif
#ifdef CONFIG_ALTIVEC
diff --git a/lib/raid6/avx512.c b/lib/raid6/avx512.c
index b1188a6..6a74327 100644
--- a/lib/raid6/avx512.c
+++ b/lib/raid6/avx512.c
@@ -289,6 +289,178 @@ const struct raid6_calls raid6_avx512x4 = {
"avx512x4",
1 /* Has cache hints */
};
+
+/*
+ * Unrolled-by-8 AVX512 implementation
+ */
+static void raid6_avx5128_gen_syndrome(int disks, size_t bytes, void **ptrs)
+{
+ u8 **dptr = (u8 **)ptrs;
+ u8 *p, *q;
+ int d, z, z0;
+
+ z0 = disks - 3; /* Highest data disk */
+ p = dptr[z0+1]; /* XOR parity */
+ q = dptr[z0+2]; /* RS syndrome */
+
+ kernel_fpu_begin();
+
+ asm volatile("vmovdqa64 %0,%%zmm0\n\t"
+ "vpxorq %%zmm1,%%zmm1,%%zmm1\n\t" /* Zero temp */
+ "vpxorq %%zmm2,%%zmm2,%%zmm2\n\t" /* P[0] */
+ "vpxorq %%zmm3,%%zmm3,%%zmm3\n\t" /* P[1] */
+ "vpxorq %%zmm4,%%zmm4,%%zmm4\n\t" /* Q[0] */
+ "vpxorq %%zmm6,%%zmm6,%%zmm6\n\t" /* Q[1] */
+ "vpxorq %%zmm10,%%zmm10,%%zmm10\n\t" /* P[2] */
+ "vpxorq %%zmm11,%%zmm11,%%zmm11\n\t" /* P[3] */
+ "vpxorq %%zmm12,%%zmm12,%%zmm12\n\t" /* Q[2] */
+ "vpxorq %%zmm14,%%zmm14,%%zmm14\n\t" /* Q[3] */
+ "vpxorq %%zmm16,%%zmm16,%%zmm16\n\t" /* P[4] */
+ "vpxorq %%zmm18,%%zmm18,%%zmm18\n\t" /* P[5] */
+ "vpxorq %%zmm20,%%zmm20,%%zmm20\n\t" /* Q[4] */
+ "vpxorq %%zmm22,%%zmm22,%%zmm22\n\t" /* Q[5] */
+ "vpxorq %%zmm24,%%zmm24,%%zmm24\n\t" /* P[6] */
+ "vpxorq %%zmm26,%%zmm26,%%zmm26\n\t" /* P[7] */
+ "vpxorq %%zmm28,%%zmm28,%%zmm28\n\t" /* Q[6] */
+ "vpxorq %%zmm30,%%zmm30,%%zmm30" /* Q[7] */
+ :
+ : "m" (raid6_avx512_constants.x1d[0]));
+
+ for (d = 0; d < bytes; d += 512) {
+ for (z = z0; z >= 0; z--) {
+ asm volatile("prefetchnta %0\n\t"
+ "prefetchnta %1\n\t"
+ "prefetchnta %2\n\t"
+ "prefetchnta %3\n\t"
+ "vpcmpgtb %%zmm4,%%zmm1,%%k1\n\t"
+ "vpcmpgtb %%zmm6,%%zmm1,%%k2\n\t"
+ "vpcmpgtb %%zmm12,%%zmm1,%%k3\n\t"
+ "vpcmpgtb %%zmm14,%%zmm1,%%k4\n\t"
+ "vpmovm2b %%k1,%%zmm5\n\t"
+ "vpmovm2b %%k2,%%zmm7\n\t"
+ "vpmovm2b %%k3,%%zmm13\n\t"
+ "vpmovm2b %%k4,%%zmm15\n\t"
+ "vpaddb %%zmm4,%%zmm4,%%zmm4\n\t"
+ "vpaddb %%zmm6,%%zmm6,%%zmm6\n\t"
+ "vpaddb %%zmm12,%%zmm12,%%zmm12\n\t"
+ "vpaddb %%zmm14,%%zmm14,%%zmm14\n\t"
+ "vpandd %%zmm0,%%zmm5,%%zmm5\n\t"
+ "vpandd %%zmm0,%%zmm7,%%zmm7\n\t"
+ "vpandd %%zmm0,%%zmm13,%%zmm13\n\t"
+ "vpandd %%zmm0,%%zmm15,%%zmm15\n\t"
+ "vpxorq %%zmm5,%%zmm4,%%zmm4\n\t"
+ "vpxorq %%zmm7,%%zmm6,%%zmm6\n\t"
+ "vpxorq %%zmm13,%%zmm12,%%zmm12\n\t"
+ "vpxorq %%zmm15,%%zmm14,%%zmm14\n\t"
+ "vmovdqa64 %0,%%zmm5\n\t"
+ "vmovdqa64 %1,%%zmm7\n\t"
+ "vmovdqa64 %2,%%zmm13\n\t"
+ "vmovdqa64 %3,%%zmm15\n\t"
+ "vpxorq %%zmm5,%%zmm2,%%zmm2\n\t"
+ "vpxorq %%zmm7,%%zmm3,%%zmm3\n\t"
+ "vpxorq %%zmm13,%%zmm10,%%zmm10\n\t"
+ "vpxorq %%zmm15,%%zmm11,%%zmm11\n\t"
+ "vpxorq %%zmm5,%%zmm4,%%zmm4\n\t"
+ "vpxorq %%zmm7,%%zmm6,%%zmm6\n\t"
+ "vpxorq %%zmm13,%%zmm12,%%zmm12\n\t"
+ "vpxorq %%zmm15,%%zmm14,%%zmm14\n\t"
+ "prefetchnta %4\n\t"
+ "prefetchnta %5\n\t"
+ "prefetchnta %6\n\t"
+ "prefetchnta %7\n\t"
+ "vpcmpgtb %%zmm20,%%zmm1,%%k5\n\t"
+ "vpcmpgtb %%zmm22,%%zmm1,%%k6\n\t"
+ "vpcmpgtb %%zmm28,%%zmm1,%%k7\n\t"
+ "vpcmpgtb %%zmm30,%%zmm1,%%k1\n\t"
+ "vpmovm2b %%k5,%%zmm21\n\t"
+ "vpmovm2b %%k6,%%zmm23\n\t"
+ "vpmovm2b %%k7,%%zmm29\n\t"
+ "vpmovm2b %%k1,%%zmm31\n\t"
+ "vpaddb %%zmm20,%%zmm20,%%zmm20\n\t"
+ "vpaddb %%zmm22,%%zmm22,%%zmm22\n\t"
+ "vpaddb %%zmm28,%%zmm28,%%zmm28\n\t"
+ "vpaddb %%zmm30,%%zmm30,%%zmm30\n\t"
+ "vpandd %%zmm0,%%zmm21,%%zmm21\n\t"
+ "vpandd %%zmm0,%%zmm23,%%zmm23\n\t"
+ "vpandd %%zmm0,%%zmm29,%%zmm29\n\t"
+ "vpandd %%zmm0,%%zmm31,%%zmm31\n\t"
+ "vpxorq %%zmm21,%%zmm20,%%zmm20\n\t"
+ "vpxorq %%zmm23,%%zmm22,%%zmm22\n\t"
+ "vpxorq %%zmm29,%%zmm28,%%zmm28\n\t"
+ "vpxorq %%zmm31,%%zmm30,%%zmm30\n\t"
+ "vmovdqa64 %4,%%zmm21\n\t"
+ "vmovdqa64 %5,%%zmm23\n\t"
+ "vmovdqa64 %6,%%zmm29\n\t"
+ "vmovdqa64 %7,%%zmm31\n\t"
+ "vpxorq %%zmm21,%%zmm16,%%zmm16\n\t"
+ "vpxorq %%zmm23,%%zmm18,%%zmm18\n\t"
+ "vpxorq %%zmm29,%%zmm24,%%zmm24\n\t"
+ "vpxorq %%zmm31,%%zmm26,%%zmm26\n\t"
+ "vpxorq %%zmm21,%%zmm20,%%zmm20\n\t"
+ "vpxorq %%zmm23,%%zmm22,%%zmm22\n\t"
+ "vpxorq %%zmm29,%%zmm28,%%zmm28\n\t"
+ "vpxorq %%zmm31,%%zmm30,%%zmm30"
+ :
+ : "m" (dptr[z][d]), "m" (dptr[z][d+64]),
+ "m" (dptr[z][d+128]),
+ "m" (dptr[z][d+192]),
+ "m" (dptr[z][d+256]),
+ "m" (dptr[z][d+320]),
+ "m" (dptr[z][d+384]),
+ "m" (dptr[z][d+448]));
+ }
+ asm volatile("vmovntdq %%zmm2,%0\n\t"
+ "vpxorq %%zmm2,%%zmm2,%%zmm2\n\t"
+ "vmovntdq %%zmm3,%1\n\t"
+ "vpxorq %%zmm3,%%zmm3,%%zmm3\n\t"
+ "vmovntdq %%zmm10,%2\n\t"
+ "vpxorq %%zmm10,%%zmm10,%%zmm10\n\t"
+ "vmovntdq %%zmm11,%3\n\t"
+ "vpxorq %%zmm11,%%zmm11,%%zmm11\n\t"
+ "vmovntdq %%zmm4,%4\n\t"
+ "vpxorq %%zmm4,%%zmm4,%%zmm4\n\t"
+ "vmovntdq %%zmm6,%5\n\t"
+ "vpxorq %%zmm6,%%zmm6,%%zmm6\n\t"
+ "vmovntdq %%zmm12,%6\n\t"
+ "vpxorq %%zmm12,%%zmm12,%%zmm12\n\t"
+ "vmovntdq %%zmm14,%7\n\t"
+ "vpxorq %%zmm14,%%zmm14,%%zmm14\n\t"
+ "vmovntdq %%zmm16,%8\n\t"
+ "vpxorq %%zmm16,%%zmm16,%%zmm16\n\t"
+ "vmovntdq %%zmm18,%9\n\t"
+ "vpxorq %%zmm18,%%zmm18,%%zmm18\n\t"
+ "vmovntdq %%zmm24,%10\n\t"
+ "vpxorq %%zmm24,%%zmm24,%%zmm24\n\t"
+ "vmovntdq %%zmm26,%11\n\t"
+ "vpxorq %%zmm26,%%zmm26,%%zmm26\n\t"
+ "vmovntdq %%zmm20,%12\n\t"
+ "vpxorq %%zmm20,%%zmm20,%%zmm20\n\t"
+ "vmovntdq %%zmm22,%13\n\t"
+ "vpxorq %%zmm22,%%zmm22,%%zmm22\n\t"
+ "vmovntdq %%zmm28,%14\n\t"
+ "vpxorq %%zmm28,%%zmm28,%%zmm28\n\t"
+ "vmovntdq %%zmm30,%15\n\t"
+ "vpxorq %%zmm30,%%zmm30,%%zmm30"
+ :
+ : "m" (p[d]), "m" (p[d+64]), "m" (p[d+128]),
+ "m" (p[d+192]), "m" (q[d]), "m" (q[d+64]),
+ "m" (q[d+128]), "m" (q[d+192]), "m" (p[d+256]),
+ "m" (p[d+320]), "m" (p[d+384]), "m" (p[d+448]),
+ "m" (q[d+256]), "m" (q[d+320]), "m" (q[d+384]),
+ "m" (q[d+448]));
+ }
+
+ asm volatile("sfence" : : : "memory");
+ kernel_fpu_end();
+}
+
+const struct raid6_calls raid6_avx512x8 = {
+ raid6_avx5128_gen_syndrome,
+ NULL, /* XOR not yet implemented */
+ raid6_have_avx512,
+ "avx512x8",
+ 1 /* Has cache hints */
+};
#endif
#endif /* CONFIG_AS_AVX512 */
--
1.9.1
^ permalink raw reply related
* [PATCH 3/4] lib/raid6/test/Makefile: Add avx512 gen_syndrome and recovery functions
From: Gayatri Kammela @ 2016-08-02 23:31 UTC (permalink / raw)
To: linux-raid
Cc: shli, linux-kernel, hpa, james.t.kukunas, fenghua.yu, megha.dey,
ravi.v.shankar, Gayatri Kammela
Adding avx512 gen_syndrome and recovery functions so as to allow code to
be compiled and tested successfully in userspace.
This patch is tested in userspace and improvement in performace is
observed.
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Jim Kukunas <james.t.kukunas@linux.intel.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Signed-off-by: Megha Dey <megha.dey@linux.intel.com>
Signed-off-by: Gayatri Kammela <gayatri.kammela@intel.com>
---
lib/raid6/test/Makefile | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/lib/raid6/test/Makefile b/lib/raid6/test/Makefile
index 29090f3..2c7b60e 100644
--- a/lib/raid6/test/Makefile
+++ b/lib/raid6/test/Makefile
@@ -32,10 +32,13 @@ ifeq ($(ARCH),arm64)
endif
ifeq ($(IS_X86),yes)
- OBJS += mmx.o sse1.o sse2.o avx2.o recov_ssse3.o recov_avx2.o
+ OBJS += mmx.o sse1.o sse2.o avx2.o recov_ssse3.o recov_avx2.o avx512.o recov_avx512.o
CFLAGS += $(shell echo "vpbroadcastb %xmm0, %ymm1" | \
gcc -c -x assembler - >&/dev/null && \
rm ./-.o && echo -DCONFIG_AS_AVX2=1)
+ CFLAGS += $(shell echo "vpmovm2b %k1, %zmm5" | \
+ gcc -c -x assembler - >&/dev/null && \
+ rm ./-.o && echo -DCONFIG_AS_AVX512=1)
else ifeq ($(HAS_NEON),yes)
OBJS += neon.o neon1.o neon2.o neon4.o neon8.o
CFLAGS += -DCONFIG_KERNEL_MODE_NEON=1
--
1.9.1
^ permalink raw reply related
* [PATCH 2/4] lib/raid6: Add AVX512 optimized recovery functions
From: Gayatri Kammela @ 2016-08-02 23:30 UTC (permalink / raw)
To: linux-raid
Cc: shli, linux-kernel, hpa, james.t.kukunas, fenghua.yu, megha.dey,
ravi.v.shankar, Gayatri Kammela
Optimize RAID6 recovery functions to take advantage of
the 512-bit ZMM integer instructions introduced in AVX512.
AVX512 optimized recovery functions, which is simply based
on recov_avx2.c written by Jim Kukunas
This patch was tested and benchmarked before submission on
a hardware that has AVX512 flags to support such instructions
Cc: Jim Kukunas <james.t.kukunas@linux.intel.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Signed-off-by: Megha Dey <megha.dey@linux.intel.com>
Signed-off-by: Gayatri Kammela <gayatri.kammela@intel.com>
---
include/linux/raid/pq.h | 1 +
lib/raid6/Makefile | 2 +-
lib/raid6/algos.c | 3 +
lib/raid6/recov_avx512.c | 335 +++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 340 insertions(+), 1 deletion(-)
create mode 100644 lib/raid6/recov_avx512.c
diff --git a/include/linux/raid/pq.h b/include/linux/raid/pq.h
index 0c529a5..1abd895 100644
--- a/include/linux/raid/pq.h
+++ b/include/linux/raid/pq.h
@@ -118,6 +118,7 @@ struct raid6_recov_calls {
extern const struct raid6_recov_calls raid6_recov_intx1;
extern const struct raid6_recov_calls raid6_recov_ssse3;
extern const struct raid6_recov_calls raid6_recov_avx2;
+extern const struct raid6_recov_calls raid6_recov_avx512;
extern const struct raid6_calls raid6_neonx1;
extern const struct raid6_calls raid6_neonx2;
diff --git a/lib/raid6/Makefile b/lib/raid6/Makefile
index 8948268..cd05ee1 100644
--- a/lib/raid6/Makefile
+++ b/lib/raid6/Makefile
@@ -3,7 +3,7 @@ obj-$(CONFIG_RAID6_PQ) += raid6_pq.o
raid6_pq-y += algos.o recov.o tables.o int1.o int2.o int4.o \
int8.o int16.o int32.o
-raid6_pq-$(CONFIG_X86) += recov_ssse3.o recov_avx2.o mmx.o sse1.o sse2.o avx2.o avx512.o
+raid6_pq-$(CONFIG_X86) += recov_ssse3.o recov_avx2.o mmx.o sse1.o sse2.o avx2.o avx512.o recov_avx512.o
raid6_pq-$(CONFIG_ALTIVEC) += altivec1.o altivec2.o altivec4.o altivec8.o
raid6_pq-$(CONFIG_KERNEL_MODE_NEON) += neon.o neon1.o neon2.o neon4.o neon8.o
raid6_pq-$(CONFIG_TILEGX) += tilegx8.o
diff --git a/lib/raid6/algos.c b/lib/raid6/algos.c
index f5f090c..149d947 100644
--- a/lib/raid6/algos.c
+++ b/lib/raid6/algos.c
@@ -98,6 +98,9 @@ void (*raid6_datap_recov)(int, size_t, int, void **);
EXPORT_SYMBOL_GPL(raid6_datap_recov);
const struct raid6_recov_calls *const raid6_recov_algos[] = {
+#ifdef CONFIG_AS_AVX512
+ &raid6_recov_avx512,
+#endif
#ifdef CONFIG_AS_AVX2
&raid6_recov_avx2,
#endif
diff --git a/lib/raid6/recov_avx512.c b/lib/raid6/recov_avx512.c
new file mode 100644
index 0000000..3e00f34
--- /dev/null
+++ b/lib/raid6/recov_avx512.c
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2012 Intel Corporation
+ *
+ * Author: Megha Dey <megha.dey@linux.intel.com>
+ * Author: Gayatri Kammela <gayatri.kammela@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#ifdef CONFIG_AS_AVX512
+
+#include <linux/raid/pq.h>
+#include "x86.h"
+
+static int raid6_has_avx512(void)
+{
+ return boot_cpu_has(X86_FEATURE_AVX2) &&
+ boot_cpu_has(X86_FEATURE_AVX) &&
+ boot_cpu_has(X86_FEATURE_AVX512F) &&
+ boot_cpu_has(X86_FEATURE_AVX512BW) &&
+ boot_cpu_has(X86_FEATURE_AVX512VL) &&
+ boot_cpu_has(X86_FEATURE_AVX512DQ);
+}
+
+static void raid6_2data_recov_avx512(int disks, size_t bytes, int faila,
+ int failb, void **ptrs)
+{
+ u8 *p, *q, *dp, *dq;
+ const u8 *pbmul; /* P multiplier table for B data */
+ const u8 *qmul; /* Q multiplier table (for both) */
+ const u8 x0f = 0x0f;
+
+ p = (u8 *)ptrs[disks-2];
+ q = (u8 *)ptrs[disks-1];
+
+ /*
+ * Compute syndrome with zero for the missing data pages
+ * Use the dead data pages as temporary storage for
+ * delta p and delta q
+ */
+
+ dp = (u8 *)ptrs[faila];
+ ptrs[faila] = (void *)raid6_empty_zero_page;
+ ptrs[disks-2] = dp;
+ dq = (u8 *)ptrs[failb];
+ ptrs[failb] = (void *)raid6_empty_zero_page;
+ ptrs[disks-1] = dq;
+
+ raid6_call.gen_syndrome(disks, bytes, ptrs);
+
+ /* Restore pointer table */
+ ptrs[faila] = dp;
+ ptrs[failb] = dq;
+ ptrs[disks-2] = p;
+ ptrs[disks-1] = q;
+
+ /* Now, pick the proper data tables */
+ pbmul = raid6_vgfmul[raid6_gfexi[failb-faila]];
+ qmul = raid6_vgfmul[raid6_gfinv[raid6_gfexp[faila] ^
+ raid6_gfexp[failb]]];
+
+ kernel_fpu_begin();
+
+ /* zmm0 = x0f[16] */
+ asm volatile("vpbroadcastb %0, %%zmm7" : : "m" (x0f));
+
+ while (bytes) {
+#ifdef CONFIG_X86_64
+ asm volatile("vmovdqa64 %0, %%zmm1" : : "m" (q[0]));
+ asm volatile("vmovdqa64 %0, %%zmm9" : : "m" (q[64]));
+ asm volatile("vmovdqa64 %0, %%zmm0" : : "m" (p[0]));
+ asm volatile("vmovdqa64 %0, %%zmm8" : : "m" (p[64]));
+ asm volatile("vpxorq %0, %%zmm1, %%zmm1" : : "m" (dq[0]));
+ asm volatile("vpxorq %0, %%zmm9, %%zmm9" : : "m" (dq[64]));
+ asm volatile("vpxorq %0, %%zmm0, %%zmm0" : : "m" (dp[0]));
+ asm volatile("vpxorq %0, %%zmm8, %%zmm8" : : "m" (dp[64]));
+
+ /*
+ * 1 = dq[0] ^ q[0]
+ * 9 = dq[64] ^ q[64]
+ * 0 = dp[0] ^ p[0]
+ * 8 = dp[64] ^ p[64]
+ */
+
+ asm volatile("vbroadcasti64x2 %0, %%zmm4" : : "m" (qmul[0]));
+ asm volatile("vbroadcasti64x2 %0, %%zmm5" : : "m" (qmul[16]));
+
+ asm volatile("vpsraw $4, %zmm1, %zmm3");
+ asm volatile("vpsraw $4, %zmm9, %zmm12");
+ asm volatile("vpandq %zmm7, %zmm1, %zmm1");
+ asm volatile("vpandq %zmm7, %zmm9, %zmm9");
+ asm volatile("vpandq %zmm7, %zmm3, %zmm3");
+ asm volatile("vpandq %zmm7, %zmm12, %zmm12");
+ asm volatile("vpshufb %zmm9, %zmm4, %zmm14");
+ asm volatile("vpshufb %zmm1, %zmm4, %zmm4");
+ asm volatile("vpshufb %zmm12, %zmm5, %zmm15");
+ asm volatile("vpshufb %zmm3, %zmm5, %zmm5");
+ asm volatile("vpxorq %zmm14, %zmm15, %zmm15");
+ asm volatile("vpxorq %zmm4, %zmm5, %zmm5");
+
+ /*
+ * 5 = qx[0]
+ * 15 = qx[64]
+ */
+
+ asm volatile("vbroadcasti64x2 %0, %%zmm4" : : "m" (pbmul[0]));
+ asm volatile("vbroadcasti64x2 %0, %%zmm1" : : "m" (pbmul[16]));
+ asm volatile("vpsraw $4, %zmm0, %zmm2");
+ asm volatile("vpsraw $4, %zmm8, %zmm6");
+ asm volatile("vpandq %zmm7, %zmm0, %zmm3");
+ asm volatile("vpandq %zmm7, %zmm8, %zmm14");
+ asm volatile("vpandq %zmm7, %zmm2, %zmm2");
+ asm volatile("vpandq %zmm7, %zmm6, %zmm6");
+ asm volatile("vpshufb %zmm14, %zmm4, %zmm12");
+ asm volatile("vpshufb %zmm3, %zmm4, %zmm4");
+ asm volatile("vpshufb %zmm6, %zmm1, %zmm13");
+ asm volatile("vpshufb %zmm2, %zmm1, %zmm1");
+ asm volatile("vpxorq %zmm4, %zmm1, %zmm1");
+ asm volatile("vpxorq %zmm12, %zmm13, %zmm13");
+
+ /*
+ * 1 = pbmul[px[0]]
+ * 13 = pbmul[px[64]]
+ */
+ asm volatile("vpxorq %zmm5, %zmm1, %zmm1");
+ asm volatile("vpxorq %zmm15, %zmm13, %zmm13");
+
+ /*
+ * 1 = db = DQ
+ * 13 = db[64] = DQ[64]
+ */
+ asm volatile("vmovdqa64 %%zmm1, %0" : "=m" (dq[0]));
+ asm volatile("vmovdqa64 %%zmm13,%0" : "=m" (dq[64]));
+ asm volatile("vpxorq %zmm1, %zmm0, %zmm0");
+ asm volatile("vpxorq %zmm13, %zmm8, %zmm8");
+
+ asm volatile("vmovdqa64 %%zmm0, %0" : "=m" (dp[0]));
+ asm volatile("vmovdqa64 %%zmm8, %0" : "=m" (dp[64]));
+
+ bytes -= 128;
+ p += 128;
+ q += 128;
+ dp += 128;
+ dq += 128;
+#else
+ asm volatile("vmovdqa64 %0, %%zmm1" : : "m" (*q));
+ asm volatile("vmovdqa64 %0, %%zmm0" : : "m" (*p));
+ asm volatile("vpxorq %0, %%zmm1, %%zmm1" : : "m" (*dq));
+ asm volatile("vpxorq %0, %%zmm0, %%zmm0" : : "m" (*dp));
+
+ /* 1 = dq ^ q; 0 = dp ^ p */
+
+ asm volatile("vbroadcasti64x2 %0, %%zmm4" : : "m" (qmul[0]));
+ asm volatile("vbroadcasti64x2 %0, %%zmm5" : : "m" (qmul[16]));
+
+ /*
+ * 1 = dq ^ q
+ * 3 = dq ^ p >> 4
+ */
+ asm volatile("vpsraw $4, %zmm1, %zmm3");
+ asm volatile("vpandq %zmm7, %zmm1, %zmm1");
+ asm volatile("vpandq %zmm7, %zmm3, %zmm3");
+ asm volatile("vpshufb %zmm1, %zmm4, %zmm4");
+ asm volatile("vpshufb %zmm3, %zmm5, %zmm5");
+ asm volatile("vpxorq %zmm4, %zmm5, %zmm5");
+
+ /* 5 = qx */
+
+ asm volatile("vbroadcasti64x2 %0, %%zmm4" : : "m" (pbmul[0]));
+ asm volatile("vbroadcasti64x2 %0, %%zmm1" : : "m" (pbmul[16]));
+
+ asm volatile("vpsraw $4, %zmm0, %zmm2");
+ asm volatile("vpandq %zmm7, %zmm0, %zmm3");
+ asm volatile("vpandq %zmm7, %zmm2, %zmm2");
+ asm volatile("vpshufb %zmm3, %zmm4, %zmm4");
+ asm volatile("vpshufb %zmm2, %zmm1, %zmm1");
+ asm volatile("vpxorq %zmm4, %zmm1, %zmm1");
+
+ /* 1 = pbmul[px] */
+ asm volatile("vpxorq %zmm5, %zmm1, %zmm1");
+ /* 1 = db = DQ */
+ asm volatile("vmovdqa64 %%zmm1, %0" : "=m" (dq[0]));
+
+ asm volatile("vpxorq %zmm1, %zmm0, %zmm0");
+ asm volatile("vmovdqa64 %%zmm0, %0" : "=m" (dp[0]));
+
+ bytes -= 64;
+ p += 64;
+ q += 64;
+ dp += 64;
+ dq += 64;
+#endif
+ }
+
+ kernel_fpu_end();
+}
+
+static void raid6_datap_recov_avx512(int disks, size_t bytes, int faila,
+ void **ptrs)
+{
+ u8 *p, *q, *dq;
+ const u8 *qmul; /* Q multiplier table */
+ const u8 x0f = 0x0f;
+
+ p = (u8 *)ptrs[disks-2];
+ q = (u8 *)ptrs[disks-1];
+
+ /*
+ * Compute syndrome with zero for the missing data page
+ * Use the dead data page as temporary storage for delta q
+ */
+
+ dq = (u8 *)ptrs[faila];
+ ptrs[faila] = (void *)raid6_empty_zero_page;
+ ptrs[disks-1] = dq;
+
+ raid6_call.gen_syndrome(disks, bytes, ptrs);
+
+ /* Restore pointer table */
+ ptrs[faila] = dq;
+ ptrs[disks-1] = q;
+
+ /* Now, pick the proper data tables */
+ qmul = raid6_vgfmul[raid6_gfinv[raid6_gfexp[faila]]];
+
+ kernel_fpu_begin();
+
+ asm volatile("vpbroadcastb %0, %%zmm7" : : "m" (x0f));
+
+ while (bytes) {
+#ifdef CONFIG_X86_64
+ asm volatile("vmovdqa64 %0, %%zmm3" : : "m" (dq[0]));
+ asm volatile("vmovdqa64 %0, %%zmm8" : : "m" (dq[64]));
+ asm volatile("vpxorq %0, %%zmm3, %%zmm3" : : "m" (q[0]));
+ asm volatile("vpxorq %0, %%zmm8, %%zmm8" : : "m" (q[64]));
+
+ /*
+ * 3 = q[0] ^ dq[0]
+ * 8 = q[64] ^ dq[64]
+ */
+ asm volatile("vbroadcasti64x2 %0, %%zmm0" : : "m" (qmul[0]));
+ asm volatile("vmovapd %zmm0, %zmm13");
+ asm volatile("vbroadcasti64x2 %0, %%zmm1" : : "m" (qmul[16]));
+ asm volatile("vmovapd %zmm1, %zmm14");
+
+ asm volatile("vpsraw $4, %zmm3, %zmm6");
+ asm volatile("vpsraw $4, %zmm8, %zmm12");
+ asm volatile("vpandq %zmm7, %zmm3, %zmm3");
+ asm volatile("vpandq %zmm7, %zmm8, %zmm8");
+ asm volatile("vpandq %zmm7, %zmm6, %zmm6");
+ asm volatile("vpandq %zmm7, %zmm12, %zmm12");
+ asm volatile("vpshufb %zmm3, %zmm0, %zmm0");
+ asm volatile("vpshufb %zmm8, %zmm13, %zmm13");
+ asm volatile("vpshufb %zmm6, %zmm1, %zmm1");
+ asm volatile("vpshufb %zmm12, %zmm14, %zmm14");
+ asm volatile("vpxorq %zmm0, %zmm1, %zmm1");
+ asm volatile("vpxorq %zmm13, %zmm14, %zmm14");
+
+ /*
+ * 1 = qmul[q[0] ^ dq[0]]
+ * 14 = qmul[q[64] ^ dq[64]]
+ */
+ asm volatile("vmovdqa64 %0, %%zmm2" : : "m" (p[0]));
+ asm volatile("vmovdqa64 %0, %%zmm12" : : "m" (p[64]));
+ asm volatile("vpxorq %zmm1, %zmm2, %zmm2");
+ asm volatile("vpxorq %zmm14, %zmm12, %zmm12");
+
+ /*
+ * 2 = p[0] ^ qmul[q[0] ^ dq[0]]
+ * 12 = p[64] ^ qmul[q[64] ^ dq[64]]
+ */
+
+ asm volatile("vmovdqa64 %%zmm1, %0" : "=m" (dq[0]));
+ asm volatile("vmovdqa64 %%zmm14, %0" : "=m" (dq[64]));
+ asm volatile("vmovdqa64 %%zmm2, %0" : "=m" (p[0]));
+ asm volatile("vmovdqa64 %%zmm12,%0" : "=m" (p[64]));
+
+ bytes -= 128;
+ p += 128;
+ q += 128;
+ dq += 128;
+#else
+ asm volatile("vmovdqa64 %0, %%zmm3" : : "m" (dq[0]));
+ asm volatile("vpxorq %0, %%zmm3, %%zmm3" : : "m" (q[0]));
+
+ /* 3 = q ^ dq */
+
+ asm volatile("vbroadcasti64x2 %0, %%zmm0" : : "m" (qmul[0]));
+ asm volatile("vbroadcasti64x2 %0, %%zmm1" : : "m" (qmul[16]));
+
+ asm volatile("vpsraw $4, %zmm3, %zmm6");
+ asm volatile("vpandq %zmm7, %zmm3, %zmm3");
+ asm volatile("vpandq %zmm7, %zmm6, %zmm6");
+ asm volatile("vpshufb %zmm3, %zmm0, %zmm0");
+ asm volatile("vpshufb %zmm6, %zmm1, %zmm1");
+ asm volatile("vpxorq %zmm0, %zmm1, %zmm1");
+
+ /* 1 = qmul[q ^ dq] */
+
+ asm volatile("vmovdqa64 %0, %%zmm2" : : "m" (p[0]));
+ asm volatile("vpxorq %zmm1, %zmm2, %zmm2");
+
+ /* 2 = p ^ qmul[q ^ dq] */
+
+ asm volatile("vmovdqa64 %%zmm1, %0" : "=m" (dq[0]));
+ asm volatile("vmovdqa64 %%zmm2, %0" : "=m" (p[0]));
+
+ bytes -= 64;
+ p += 64;
+ q += 64;
+ dq += 64;
+#endif
+ }
+
+ kernel_fpu_end();
+}
+
+const struct raid6_recov_calls raid6_recov_avx512 = {
+ .data2 = raid6_2data_recov_avx512,
+ .datap = raid6_datap_recov_avx512,
+ .valid = raid6_has_avx512,
+#ifdef CONFIG_X86_64
+ .name = "avx512x2",
+#else
+ .name = "avx512x1",
+#endif
+ .priority = 3,
+};
+
+#else
+#warning "your version of binutils lacks AVX512 support"
+#endif
--
1.9.1
^ permalink raw reply related
* [PATCH 1/4] lib/raid6: Add AVX512 optimized gen_syndrome functions
From: Gayatri Kammela @ 2016-08-02 23:29 UTC (permalink / raw)
To: linux-raid
Cc: shli, linux-kernel, hpa, james.t.kukunas, fenghua.yu, megha.dey,
ravi.v.shankar, Gayatri Kammela
Optimize RAID6 gen_syndrom functions to take advantage of
the 512-bit ZMM integer instructions introduced in AVX512.
AVX512 optimized gen_syndrom functions, which is simply based
on avx2.c written by Yuanhan Liu and sse2.c written by hpa.
The patch was tested and benchmarked before submission on
a hardware that has AVX512 flags to support such instructions
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Jim Kukunas <james.t.kukunas@linux.intel.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Signed-off-by: Megha Dey <megha.dey@linux.intel.com>
Signed-off-by: Gayatri Kammela <gayatri.kammela@intel.com>
---
arch/x86/Makefile | 5 +-
include/linux/raid/pq.h | 3 +
lib/raid6/Makefile | 2 +-
lib/raid6/algos.c | 9 ++
lib/raid6/avx512.c | 294 ++++++++++++++++++++++++++++++++++++++++++++++++
lib/raid6/x86.h | 10 ++
6 files changed, 320 insertions(+), 3 deletions(-)
create mode 100644 lib/raid6/avx512.c
diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index 6fce7f0..3fd807b 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -171,11 +171,12 @@ asinstr += $(call as-instr,pshufb %xmm0$(comma)%xmm0,-DCONFIG_AS_SSSE3=1)
asinstr += $(call as-instr,crc32l %eax$(comma)%eax,-DCONFIG_AS_CRC32=1)
avx_instr := $(call as-instr,vxorps %ymm0$(comma)%ymm1$(comma)%ymm2,-DCONFIG_AS_AVX=1)
avx2_instr :=$(call as-instr,vpbroadcastb %xmm0$(comma)%ymm1,-DCONFIG_AS_AVX2=1)
+avx512_instr :=$(call as-instr,vpmovm2b %k1$(comma)%zmm5,-DCONFIG_AS_AVX512=1)
sha1_ni_instr :=$(call as-instr,sha1msg1 %xmm0$(comma)%xmm1,-DCONFIG_AS_SHA1_NI=1)
sha256_ni_instr :=$(call as-instr,sha256msg1 %xmm0$(comma)%xmm1,-DCONFIG_AS_SHA256_NI=1)
-KBUILD_AFLAGS += $(cfi) $(cfi-sigframe) $(cfi-sections) $(asinstr) $(avx_instr) $(avx2_instr) $(sha1_ni_instr) $(sha256_ni_instr)
-KBUILD_CFLAGS += $(cfi) $(cfi-sigframe) $(cfi-sections) $(asinstr) $(avx_instr) $(avx2_instr) $(sha1_ni_instr) $(sha256_ni_instr)
+KBUILD_AFLAGS += $(cfi) $(cfi-sigframe) $(cfi-sections) $(asinstr) $(avx_instr) $(avx2_instr) $(avx512_instr) $(sha1_ni_instr) $(sha256_ni_instr)
+KBUILD_CFLAGS += $(cfi) $(cfi-sigframe) $(cfi-sections) $(asinstr) $(avx_instr) $(avx2_instr) $(avx512_instr) $(sha1_ni_instr) $(sha256_ni_instr)
LDFLAGS := -m elf_$(UTS_MACHINE)
diff --git a/include/linux/raid/pq.h b/include/linux/raid/pq.h
index a0118d5..0c529a5 100644
--- a/include/linux/raid/pq.h
+++ b/include/linux/raid/pq.h
@@ -102,6 +102,9 @@ extern const struct raid6_calls raid6_altivec8;
extern const struct raid6_calls raid6_avx2x1;
extern const struct raid6_calls raid6_avx2x2;
extern const struct raid6_calls raid6_avx2x4;
+extern const struct raid6_calls raid6_avx512x1;
+extern const struct raid6_calls raid6_avx512x2;
+extern const struct raid6_calls raid6_avx512x4;
extern const struct raid6_calls raid6_tilegx8;
struct raid6_recov_calls {
diff --git a/lib/raid6/Makefile b/lib/raid6/Makefile
index 3b10a48..8948268 100644
--- a/lib/raid6/Makefile
+++ b/lib/raid6/Makefile
@@ -3,7 +3,7 @@ obj-$(CONFIG_RAID6_PQ) += raid6_pq.o
raid6_pq-y += algos.o recov.o tables.o int1.o int2.o int4.o \
int8.o int16.o int32.o
-raid6_pq-$(CONFIG_X86) += recov_ssse3.o recov_avx2.o mmx.o sse1.o sse2.o avx2.o
+raid6_pq-$(CONFIG_X86) += recov_ssse3.o recov_avx2.o mmx.o sse1.o sse2.o avx2.o avx512.o
raid6_pq-$(CONFIG_ALTIVEC) += altivec1.o altivec2.o altivec4.o altivec8.o
raid6_pq-$(CONFIG_KERNEL_MODE_NEON) += neon.o neon1.o neon2.o neon4.o neon8.o
raid6_pq-$(CONFIG_TILEGX) += tilegx8.o
diff --git a/lib/raid6/algos.c b/lib/raid6/algos.c
index 975c6e0..f5f090c 100644
--- a/lib/raid6/algos.c
+++ b/lib/raid6/algos.c
@@ -49,6 +49,10 @@ const struct raid6_calls * const raid6_algos[] = {
&raid6_avx2x1,
&raid6_avx2x2,
#endif
+#ifdef CONFIG_AS_AVX512
+ &raid6_avx512x1,
+ &raid6_avx512x2,
+#endif
#endif
#if defined(__x86_64__) && !defined(__arch_um__)
&raid6_sse2x1,
@@ -59,6 +63,11 @@ const struct raid6_calls * const raid6_algos[] = {
&raid6_avx2x2,
&raid6_avx2x4,
#endif
+#ifdef CONFIG_AS_AVX512
+ &raid6_avx512x1,
+ &raid6_avx512x2,
+ &raid6_avx512x4,
+#endif
#endif
#ifdef CONFIG_ALTIVEC
&raid6_altivec1,
diff --git a/lib/raid6/avx512.c b/lib/raid6/avx512.c
new file mode 100644
index 0000000..b1188a6
--- /dev/null
+++ b/lib/raid6/avx512.c
@@ -0,0 +1,294 @@
+/* -*- linux-c -*- --------------------------------------------------------
+ *
+ * Copyright (C) 2016 Intel Corporation
+ *
+ * Author: Gayatri Kammela <gayatri.kammela@intel.com>
+ * Author: Megha Dey <megha.dey@linux.intel.com>
+ *
+ * Based on avx2.c: Copyright 2012 Yuanhan Liu All Rights Reserved
+ * Based on sse2.c: Copyright 2002 H. Peter Anvin - All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+ * Boston MA 02111-1307, USA; either version 2 of the License, or
+ * (at your option) any later version; incorporated herein by reference.
+ *
+ * -----------------------------------------------------------------------
+ */
+
+/*
+ * AVX512 implementation of RAID-6 syndrome functions
+ *
+ */
+
+#ifdef CONFIG_AS_AVX512
+
+#include <linux/raid/pq.h>
+#include "x86.h"
+
+static const struct raid6_avx512_constants {
+ u64 x1d[8];
+} raid6_avx512_constants __aligned(512) = {
+ { 0x1d1d1d1d1d1d1d1dULL, 0x1d1d1d1d1d1d1d1dULL,
+ 0x1d1d1d1d1d1d1d1dULL, 0x1d1d1d1d1d1d1d1dULL,
+ 0x1d1d1d1d1d1d1d1dULL, 0x1d1d1d1d1d1d1d1dULL,
+ 0x1d1d1d1d1d1d1d1dULL, 0x1d1d1d1d1d1d1d1dULL,},
+};
+
+static int raid6_have_avx512(void)
+{
+ return boot_cpu_has(X86_FEATURE_AVX2) &&
+ boot_cpu_has(X86_FEATURE_AVX) &&
+ boot_cpu_has(X86_FEATURE_AVX512F) &&
+ boot_cpu_has(X86_FEATURE_AVX512BW) &&
+ boot_cpu_has(X86_FEATURE_AVX512VL) &&
+ boot_cpu_has(X86_FEATURE_AVX512DQ);
+}
+
+static void raid6_avx5121_gen_syndrome(int disks, size_t bytes, void **ptrs)
+{
+ u8 **dptr = (u8 **)ptrs;
+ u8 *p, *q;
+ int d, z, z0;
+
+ z0 = disks - 3; /* Highest data disk */
+ p = dptr[z0+1]; /* XOR parity */
+ q = dptr[z0+2]; /* RS syndrome */
+
+ kernel_fpu_begin();
+
+ asm volatile("vmovdqa64 %0,%%zmm0\n\t"
+ "vpxorq %%zmm1,%%zmm1,%%zmm1" /* Zero temp */
+ :
+ : "m" (raid6_avx512_constants.x1d[0]));
+
+ for (d = 0; d < bytes; d += 64) {
+ asm volatile("prefetchnta %0\n\t"
+ "vmovdqa64 %0,%%zmm2\n\t" /* P[0] */
+ "prefetchnta %1\n\t"
+ "vmovdqa64 %%zmm2,%%zmm4\n\t" /* Q[0] */
+ "vmovdqa64 %1,%%zmm6"
+ :
+ : "m" (dptr[z0][d]), "m" (dptr[z0-1][d]));
+ for (z = z0-2; z >= 0; z--) {
+ asm volatile("prefetchnta %0\n\t"
+ "vpcmpgtb %%zmm4,%%zmm1,%%k1\n\t"
+ "vpmovm2b %%k1,%%zmm5\n\t"
+ "vpaddb %%zmm4,%%zmm4,%%zmm4\n\t"
+ "vpandq %%zmm0,%%zmm5,%%zmm5\n\t"
+ "vpxorq %%zmm5,%%zmm4,%%zmm4\n\t"
+ "vpxorq %%zmm6,%%zmm2,%%zmm2\n\t"
+ "vpxorq %%zmm6,%%zmm4,%%zmm4\n\t"
+ "vmovdqa64 %0,%%zmm6"
+ :
+ : "m" (dptr[z][d]));
+ }
+ asm volatile("vpcmpgtb %%zmm4,%%zmm1,%%k1\n\t"
+ "vpmovm2b %%k1,%%zmm5\n\t"
+ "vpaddb %%zmm4,%%zmm4,%%zmm4\n\t"
+ "vpandq %%zmm0,%%zmm5,%%zmm5\n\t"
+ "vpxorq %%zmm5,%%zmm4,%%zmm4\n\t"
+ "vpxorq %%zmm6,%%zmm2,%%zmm2\n\t"
+ "vpxorq %%zmm6,%%zmm4,%%zmm4\n\t"
+ "vmovntdq %%zmm2,%0\n\t"
+ "vpxorq %%zmm2,%%zmm2,%%zmm2\n\t"
+ "vmovntdq %%zmm4,%1\n\t"
+ "vpxorq %%zmm4,%%zmm4,%%zmm4"
+ :
+ : "m" (p[d]), "m" (q[d]));
+ }
+
+ asm volatile("sfence" : : : "memory");
+ kernel_fpu_end();
+}
+
+const struct raid6_calls raid6_avx512x1 = {
+ raid6_avx5121_gen_syndrome,
+ NULL, /* XOR not yet implemented */
+ raid6_have_avx512,
+ "avx512x1",
+ 1 /* Has cache hints */
+};
+
+/*
+ * Unrolled-by-2 AVX512 implementation
+ */
+static void raid6_avx5122_gen_syndrome(int disks, size_t bytes, void **ptrs)
+{
+ u8 **dptr = (u8 **)ptrs;
+ u8 *p, *q;
+ int d, z, z0;
+
+ z0 = disks - 3; /* Highest data disk */
+ p = dptr[z0+1]; /* XOR parity */
+ q = dptr[z0+2]; /* RS syndrome */
+
+ kernel_fpu_begin();
+
+ asm volatile("vmovdqa64 %0,%%zmm0\n\t"
+ "vpxorq %%zmm1,%%zmm1,%%zmm1" /* Zero temp */
+ :
+ : "m" (raid6_avx512_constants.x1d[0]));
+
+ /* We uniformly assume a single prefetch covers at least 64 bytes */
+ for (d = 0; d < bytes; d += 128) {
+ asm volatile("prefetchnta %0\n\t"
+ "prefetchnta %1\n\t"
+ "vmovdqa64 %0,%%zmm2\n\t" /* P[0] */
+ "vmovdqa64 %1,%%zmm3\n\t" /* P[1] */
+ "vmovdqa64 %%zmm2,%%zmm4\n\t" /* Q[0] */
+ "vmovdqa64 %%zmm3,%%zmm6" /* Q[1] */
+ :
+ : "m" (dptr[z0][d]), "m" (dptr[z0][d+64]));
+ for (z = z0-1; z >= 0; z--) {
+ asm volatile("prefetchnta %0\n\t"
+ "prefetchnta %1\n\t"
+ "vpcmpgtb %%zmm4,%%zmm1,%%k1\n\t"
+ "vpcmpgtb %%zmm6,%%zmm1,%%k2\n\t"
+ "vpmovm2b %%k1,%%zmm5\n\t"
+ "vpmovm2b %%k2,%%zmm7\n\t"
+ "vpaddb %%zmm4,%%zmm4,%%zmm4\n\t"
+ "vpaddb %%zmm6,%%zmm6,%%zmm6\n\t"
+ "vpandq %%zmm0,%%zmm5,%%zmm5\n\t"
+ "vpandq %%zmm0,%%zmm7,%%zmm7\n\t"
+ "vpxorq %%zmm5,%%zmm4,%%zmm4\n\t"
+ "vpxorq %%zmm7,%%zmm6,%%zmm6\n\t"
+ "vmovdqa64 %0,%%zmm5\n\t"
+ "vmovdqa64 %1,%%zmm7\n\t"
+ "vpxorq %%zmm5,%%zmm2,%%zmm2\n\t"
+ "vpxorq %%zmm7,%%zmm3,%%zmm3\n\t"
+ "vpxorq %%zmm5,%%zmm4,%%zmm4\n\t"
+ "vpxorq %%zmm7,%%zmm6,%%zmm6"
+ :
+ : "m" (dptr[z][d]), "m" (dptr[z][d+64]));
+ }
+ asm volatile("vmovntdq %%zmm2,%0\n\t"
+ "vmovntdq %%zmm3,%1\n\t"
+ "vmovntdq %%zmm4,%2\n\t"
+ "vmovntdq %%zmm6,%3"
+ :
+ : "m" (p[d]), "m" (p[d+64]), "m" (q[d]),
+ "m" (q[d+64]));
+ }
+
+ asm volatile("sfence" : : : "memory");
+ kernel_fpu_end();
+}
+
+const struct raid6_calls raid6_avx512x2 = {
+ raid6_avx5122_gen_syndrome,
+ NULL, /* XOR not yet implemented */
+ raid6_have_avx512,
+ "avx512x2",
+ 1 /* Has cache hints */
+};
+
+#ifdef CONFIG_X86_64
+
+/*
+ * Unrolled-by-4 AVX2 implementation
+ */
+static void raid6_avx5124_gen_syndrome(int disks, size_t bytes, void **ptrs)
+{
+ u8 **dptr = (u8 **)ptrs;
+ u8 *p, *q;
+ int d, z, z0;
+
+ z0 = disks - 3; /* Highest data disk */
+ p = dptr[z0+1]; /* XOR parity */
+ q = dptr[z0+2]; /* RS syndrome */
+
+ kernel_fpu_begin();
+
+ asm volatile("vmovdqa64 %0,%%zmm0\n\t"
+ "vpxorq %%zmm1,%%zmm1,%%zmm1\n\t" /* Zero temp */
+ "vpxorq %%zmm2,%%zmm2,%%zmm2\n\t" /* P[0] */
+ "vpxorq %%zmm3,%%zmm3,%%zmm3\n\t" /* P[1] */
+ "vpxorq %%zmm4,%%zmm4,%%zmm4\n\t" /* Q[0] */
+ "vpxorq %%zmm6,%%zmm6,%%zmm6\n\t" /* Q[1] */
+ "vpxorq %%zmm10,%%zmm10,%%zmm10\n\t" /* P[2] */
+ "vpxorq %%zmm11,%%zmm11,%%zmm11\n\t" /* P[3] */
+ "vpxorq %%zmm12,%%zmm12,%%zmm12\n\t" /* Q[2] */
+ "vpxorq %%zmm14,%%zmm14,%%zmm14" /* Q[3] */
+ :
+ : "m" (raid6_avx512_constants.x1d[0]));
+
+ for (d = 0; d < bytes; d += 256) {
+ for (z = z0; z >= 0; z--) {
+ asm volatile("prefetchnta %0\n\t"
+ "prefetchnta %1\n\t"
+ "prefetchnta %2\n\t"
+ "prefetchnta %3\n\t"
+ "vpcmpgtb %%zmm4,%%zmm1,%%k1\n\t"
+ "vpcmpgtb %%zmm6,%%zmm1,%%k2\n\t"
+ "vpcmpgtb %%zmm12,%%zmm1,%%k3\n\t"
+ "vpcmpgtb %%zmm14,%%zmm1,%%k4\n\t"
+ "vpmovm2b %%k1,%%zmm5\n\t"
+ "vpmovm2b %%k2,%%zmm7\n\t"
+ "vpmovm2b %%k3,%%zmm13\n\t"
+ "vpmovm2b %%k4,%%zmm15\n\t"
+ "vpaddb %%zmm4,%%zmm4,%%zmm4\n\t"
+ "vpaddb %%zmm6,%%zmm6,%%zmm6\n\t"
+ "vpaddb %%zmm12,%%zmm12,%%zmm12\n\t"
+ "vpaddb %%zmm14,%%zmm14,%%zmm14\n\t"
+ "vpandq %%zmm0,%%zmm5,%%zmm5\n\t"
+ "vpandq %%zmm0,%%zmm7,%%zmm7\n\t"
+ "vpandq %%zmm0,%%zmm13,%%zmm13\n\t"
+ "vpandq %%zmm0,%%zmm15,%%zmm15\n\t"
+ "vpxorq %%zmm5,%%zmm4,%%zmm4\n\t"
+ "vpxorq %%zmm7,%%zmm6,%%zmm6\n\t"
+ "vpxorq %%zmm13,%%zmm12,%%zmm12\n\t"
+ "vpxorq %%zmm15,%%zmm14,%%zmm14\n\t"
+ "vmovdqa64 %0,%%zmm5\n\t"
+ "vmovdqa64 %1,%%zmm7\n\t"
+ "vmovdqa64 %2,%%zmm13\n\t"
+ "vmovdqa64 %3,%%zmm15\n\t"
+ "vpxorq %%zmm5,%%zmm2,%%zmm2\n\t"
+ "vpxorq %%zmm7,%%zmm3,%%zmm3\n\t"
+ "vpxorq %%zmm13,%%zmm10,%%zmm10\n\t"
+ "vpxorq %%zmm15,%%zmm11,%%zmm11\n"
+ "vpxorq %%zmm5,%%zmm4,%%zmm4\n\t"
+ "vpxorq %%zmm7,%%zmm6,%%zmm6\n\t"
+ "vpxorq %%zmm13,%%zmm12,%%zmm12\n\t"
+ "vpxorq %%zmm15,%%zmm14,%%zmm14"
+ :
+ : "m" (dptr[z][d]), "m" (dptr[z][d+64]),
+ "m" (dptr[z][d+128]), "m" (dptr[z][d+192]));
+ }
+ asm volatile("vmovntdq %%zmm2,%0\n\t"
+ "vpxorq %%zmm2,%%zmm2,%%zmm2\n\t"
+ "vmovntdq %%zmm3,%1\n\t"
+ "vpxorq %%zmm3,%%zmm3,%%zmm3\n\t"
+ "vmovntdq %%zmm10,%2\n\t"
+ "vpxorq %%zmm10,%%zmm10,%%zmm10\n\t"
+ "vmovntdq %%zmm11,%3\n\t"
+ "vpxorq %%zmm11,%%zmm11,%%zmm11\n\t"
+ "vmovntdq %%zmm4,%4\n\t"
+ "vpxorq %%zmm4,%%zmm4,%%zmm4\n\t"
+ "vmovntdq %%zmm6,%5\n\t"
+ "vpxorq %%zmm6,%%zmm6,%%zmm6\n\t"
+ "vmovntdq %%zmm12,%6\n\t"
+ "vpxorq %%zmm12,%%zmm12,%%zmm12\n\t"
+ "vmovntdq %%zmm14,%7\n\t"
+ "vpxorq %%zmm14,%%zmm14,%%zmm14"
+ :
+ : "m" (p[d]), "m" (p[d+64]), "m" (p[d+128]),
+ "m" (p[d+192]), "m" (q[d]), "m" (q[d+64]),
+ "m" (q[d+128]), "m" (q[d+192]));
+ }
+
+ asm volatile("sfence" : : : "memory");
+ kernel_fpu_end();
+}
+
+const struct raid6_calls raid6_avx512x4 = {
+ raid6_avx5124_gen_syndrome,
+ NULL, /* XOR not yet implemented */
+ raid6_have_avx512,
+ "avx512x4",
+ 1 /* Has cache hints */
+};
+#endif
+
+#endif /* CONFIG_AS_AVX512 */
diff --git a/lib/raid6/x86.h b/lib/raid6/x86.h
index 8fe9d96..834d268 100644
--- a/lib/raid6/x86.h
+++ b/lib/raid6/x86.h
@@ -46,6 +46,16 @@ static inline void kernel_fpu_end(void)
#define X86_FEATURE_SSSE3 (4*32+ 9) /* Supplemental SSE-3 */
#define X86_FEATURE_AVX (4*32+28) /* Advanced Vector Extensions */
#define X86_FEATURE_AVX2 (9*32+ 5) /* AVX2 instructions */
+#define X86_FEATURE_AVX512F (9*32+16) /* AVX-512 Foundation */
+#define X86_FEATURE_AVX512DQ (9*32+17) /* AVX-512 DQ (Double/Quad granular)
+ * Instructions
+ */
+#define X86_FEATURE_AVX512BW (9*32+30) /* AVX-512 BW (Byte/Word granular)
+ * Instructions
+ */
+#define X86_FEATURE_AVX512VL (9*32+31) /* AVX-512 VL (128/256 Vector Length)
+ * Extensions
+ */
#define X86_FEATURE_MMXEXT (1*32+22) /* AMD MMX extensions */
/* Should work well enough on modern CPUs for testing */
--
1.9.1
^ permalink raw reply related
* [PATCH 0/4] Add AVX512 optimized gen_syndrome and recovery functions
From: Gayatri Kammela @ 2016-08-02 23:28 UTC (permalink / raw)
To: linux-raid
Cc: shli, linux-kernel, hpa, james.t.kukunas, fenghua.yu, megha.dey,
ravi.v.shankar, Gayatri Kammela
This is the patch set for adding AVX512 optimized gen_syndrome
and recovery functions.
Optimization of RAID6 using AVX512 instructions should improve the
RAID6 performance.These patches are tested and observed the improvement
in performance.
Gayatri Kammela (4):
lib/raid6: Add AVX512 optimized gen_syndrome functions
lib/raid6: Add AVX512 optimized recovery functions
lib/raid6/test/Makefile: Add avx512 gen_syndrome and recovery
functions
(DO NOT APPLY) lib/raid6: Add unroll by 8 to AVX512 optimized
gen_syndrome functions
arch/x86/Makefile | 5 +-
include/linux/raid/pq.h | 5 +
lib/raid6/Makefile | 2 +-
lib/raid6/algos.c | 13 ++
lib/raid6/avx512.c | 466 +++++++++++++++++++++++++++++++++++++++++++++++
lib/raid6/recov_avx512.c | 335 ++++++++++++++++++++++++++++++++++
lib/raid6/test/Makefile | 5 +-
lib/raid6/x86.h | 10 +
8 files changed, 837 insertions(+), 4 deletions(-)
create mode 100644 lib/raid6/avx512.c
create mode 100644 lib/raid6/recov_avx512.c
--
1.9.1
^ permalink raw reply
* Re: [PATCH 3/3] MD: hold mddev lock for md-cluster receive thread
From: Shaohua Li @ 2016-08-02 22:44 UTC (permalink / raw)
To: Guoqing Jiang; +Cc: linux-raid, NeilBrown
In-Reply-To: <57A06D69.2040703@suse.com>
On Tue, Aug 02, 2016 at 05:52:41PM +0800, Guoqing Jiang wrote:
>
>
> On 08/02/2016 05:45 AM, Shaohua Li wrote:
> >On Mon, Aug 01, 2016 at 04:38:59PM +0800, Guoqing Jiang wrote:
> >>Hi,
> >>
> >>On 07/31/2016 07:54 AM, shli@kernel.org wrote:
> >>>From: Shaohua Li <shli@fb.com>
> >>>
> >>>md-cluster receive thread calls .quiesce too, let it hold mddev lock.
> >>I'd suggest hold on for the patchset, I can find lock problem easily with
> >>the patchset applied. Take a resyncing clusteed raid1 as example.
> >>
> >>md127_raid1 thread held reconfig_mutex then update sb, so it needs dlm
> >>token lock. Meanwhile md127_resync thread got token lock and wants
> >>EX on ack lock but recv_daemon can't release ack lock since recv_daemon
> >>doesn't get reconfig_mutex.
> >Thansk, I'll drop this one. Other two patches are still safe for md-cluster,
> >right?
>
> From the latest test, I can't find lock issues with the first two patches,
> but I doubt it would have side effect for the performance of resync.
That's not need to be worried. The .quiesce() call is way heavier than
hold/release the mutex.
> >I really hope to have consistent locking for .quiesce. For the
> >process_recvd_msg, I'm wondering what's protecting the datas? for example,
> >md-cluster uses md_find_rdev_nr_rcu, which access the disks list without
> >locking. Is there a race?
>
> Yes, it should be protected by rcu lock, I will post a patch for it, thanks
> for reminder.
>
> >Does it work if we move the mddev lock to
> >process_recvd_msg?
>
> I tried that, but It still have lock issue, eg, when node B and C have
> status
> as "resync=PENDING", then try to stop the resyncing array in node A.
can you elaborate it?
For the raid5-cache issue, ignoring the md-cluster .quiesce() call is fine
currently as we don't support raid5 cluster. We probably should add another
parameter for .quiesce to indicate if the mddev lock is hold in the future.
Thanks,
Shaohua
^ permalink raw reply
* Re: [PATCH 4/8] md-cluster: introduce dlm_lock_sync_interruptible to fix tasks hang
From: Shaohua Li @ 2016-08-02 22:36 UTC (permalink / raw)
To: Guoqing Jiang; +Cc: linux-raid
In-Reply-To: <57A01272.4010209@suse.com>
On Mon, Aug 01, 2016 at 11:24:34PM -0400, Guoqing Jiang wrote:
>
>
> On 08/01/2016 06:20 PM, Shaohua Li wrote:
> >On Thu, Jul 28, 2016 at 02:16:48AM -0400, Guoqing Jiang wrote:
> >>When some node leaves cluster, then it's bitmap need to be
> >>synced by another node, so "md*_recover" thread is triggered
> >>for the purpose. However, with below steps. we can find tasks
> >>hang happened either in B or C.
> >>
> >>1. Node A create a resyncing cluster raid1, assemble it in
> >> other two nodes (B and C).
> >>2. stop array in B and C.
> >>3. stop array in A.
> >>
> >>linux44:~ # ps aux|grep md|grep D
> >>root 5938 0.0 0.1 19852 1964 pts/0 D+ 14:52 0:00 mdadm -S md0
> >>root 5939 0.0 0.0 0 0 ? D 14:52 0:00 [md0_recover]
> >>
> >>linux44:~ # cat /proc/5939/stack
> >>[<ffffffffa04cf321>] dlm_lock_sync+0x71/0x90 [md_cluster]
> >>[<ffffffffa04d0705>] recover_bitmaps+0x125/0x220 [md_cluster]
> >>[<ffffffffa052105d>] md_thread+0x16d/0x180 [md_mod]
> >>[<ffffffff8107ad94>] kthread+0xb4/0xc0
> >>[<ffffffff8152a518>] ret_from_fork+0x58/0x90
> >>
> >>linux44:~ # cat /proc/5938/stack
> >>[<ffffffff8107afde>] kthread_stop+0x6e/0x120
> >>[<ffffffffa0519da0>] md_unregister_thread+0x40/0x80 [md_mod]
> >>[<ffffffffa04cfd20>] leave+0x70/0x120 [md_cluster]
> >>[<ffffffffa0525e24>] md_cluster_stop+0x14/0x30 [md_mod]
> >>[<ffffffffa05269ab>] bitmap_free+0x14b/0x150 [md_mod]
> >>[<ffffffffa0523f3b>] do_md_stop+0x35b/0x5a0 [md_mod]
> >>[<ffffffffa0524e83>] md_ioctl+0x873/0x1590 [md_mod]
> >>[<ffffffff81288464>] blkdev_ioctl+0x214/0x7d0
> >>[<ffffffff811dd3dd>] block_ioctl+0x3d/0x40
> >>[<ffffffff811b92d4>] do_vfs_ioctl+0x2d4/0x4b0
> >>[<ffffffff811b9538>] SyS_ioctl+0x88/0xa0
> >>[<ffffffff8152a5c9>] system_call_fastpath+0x16/0x1b
> >>
> >>The problem is caused by recover_bitmaps can't reliably abort
> >>when the thread is unregistered. So dlm_lock_sync_interruptible
> >>is introduced to detect the thread's situation to fix the problem.
> >>
> >>Reviewed-by: NeilBrown <neilb@suse.com>
> >>Signed-off-by: Guoqing Jiang <gqjiang@suse.com>
> >>---
> >> drivers/md/md-cluster.c | 38 +++++++++++++++++++++++++++++++++++++-
> >> 1 file changed, 37 insertions(+), 1 deletion(-)
> >>
> >>diff --git a/drivers/md/md-cluster.c b/drivers/md/md-cluster.c
> >>index ea2699e..f3d584e 100644
> >>--- a/drivers/md/md-cluster.c
> >>+++ b/drivers/md/md-cluster.c
> >>@@ -10,6 +10,8 @@
> >> #include <linux/module.h>
> >>+#include <linux/completion.h>
> >>+#include <linux/kthread.h>
> >> #include <linux/dlm.h>
> >> #include <linux/sched.h>
> >> #include <linux/raid/md_p.h>
> >>@@ -141,6 +143,40 @@ static int dlm_unlock_sync(struct dlm_lock_resource *res)
> >> return dlm_lock_sync(res, DLM_LOCK_NL);
> >> }
> >>+/* An variation of dlm_lock_sync, which make lock request could
> >>+ * be interrupted */
> >>+static int dlm_lock_sync_interruptible(struct dlm_lock_resource *res, int mode,
> >>+ struct mddev *mddev)
> >>+{
> >>+ int ret = 0;
> >>+
> >>+ ret = dlm_lock(res->ls, mode, &res->lksb,
> >>+ res->flags, res->name, strlen(res->name),
> >>+ 0, sync_ast, res, res->bast);
> >>+ if (ret)
> >>+ return ret;
> >>+
> >>+ wait_event(res->completion.wait,
> >>+ res->completion.done || kthread_should_stop());
> >can you convert it to a waitq? Directly using the .wait/.done of completion is
> >really intrusive.
>
> Maybe, but we still need completion for dlm_lock_resource otherwise there
> are different types of dlm_lock_resource, we also need to keep align with
> sync_ast as dlm_lock_sync did.
Yes, we need a waitq and variable like completion.done to indicate the event is
done, and convert the completion API to waitq API in other places like
sync_ast. The point is not using the opaque data structure of 'struct
completion'. Diving into implementation details of a unrelated data structure
(completion here) is really intrusive.
Thanks,
Shaohua
^ permalink raw reply
* Re: [PATCH 1/8] md-cluster: call md_kick_rdev_from_array once ack failed
From: Shaohua Li @ 2016-08-02 22:17 UTC (permalink / raw)
To: Guoqing Jiang; +Cc: linux-raid
In-Reply-To: <579FF771.4060007@suse.com>
On Mon, Aug 01, 2016 at 09:29:21PM -0400, Guoqing Jiang wrote:
>
>
> On 08/01/2016 05:58 PM, Shaohua Li wrote:
> >On Thu, Jul 28, 2016 at 02:16:45AM -0400, Guoqing Jiang wrote:
> >>The new_disk_ack could return failure if WAITING_FOR_NEWDISK
> >>is not set, so we need to kick the dev from array in case
> >>failure happened.
> >>
> >>Reviewed-by: NeilBrown <neilb@suse.com>
> >>Signed-off-by: Guoqing Jiang <gqjiang@suse.com>
> >>---
> >> drivers/md/md.c | 8 +++++---
> >> 1 file changed, 5 insertions(+), 3 deletions(-)
> >>
> >>diff --git a/drivers/md/md.c b/drivers/md/md.c
> >>index 2ed547f..743cd21 100644
> >>--- a/drivers/md/md.c
> >>+++ b/drivers/md/md.c
> >>@@ -6092,9 +6092,11 @@ static int add_new_disk(struct mddev *mddev, mdu_disk_info_t *info)
> >> export_rdev(rdev);
> >> if (mddev_is_clustered(mddev)) {
> >>- if (info->state & (1 << MD_DISK_CANDIDATE))
> >>- md_cluster_ops->new_disk_ack(mddev, (err == 0));
> >>- else {
> >>+ if (info->state & (1 << MD_DISK_CANDIDATE)) {
> >if err != 0, we already do export_rdev, do we need to do md_kick_rdev_from_array in that case?
>
> I suppose you mean the export_rdev before new_disk_ack, it doesn't need to
> call md_kick_rdev_from_array
> since we don't bind rdev to array successfully.
>
> err = bind_rdev_to_array(rdev, mddev);
>
> if (err)
> *export_rdev*(rdev);
Let's assume bind_rdev_to_array fails, err != 0, we export_rdev
> if (mddev_is_clustered(mddev)) {
> if (info->state & (1 << MD_DISK_CANDIDATE))
> md_cluster_ops->new_disk_ack(mddev, (err == 0));
we don't check err here, so we could call ->new_disk_ack, then if
new_disk_ack() fails, we will call md_kick_rdev_from_array(rdev) again with
your patch. we are kicking out rdev which isn't bound yet in this case.
Thanks,
Shaohua
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox