dm-writecache patches
Subsystems (6)
Mikulas Patocka
maintainercover dm-writecache patches
Hi
Here I'm sending the dm-writecache patches.
The first patch optimizes x86 memcpy_flushcache for small constant size. It increases dm-writecache throughput by about 2%. It should be already in Dan Williams' tree.
The second patch exports __prepare_to_swait and __finish_swait.
The third patch is dm-writecache that is already in Mike's tree.
The fourth patch converts it to use the new API. The pmem_* API is at the beginning of the file dm-writecache.c - it may be moved to system include files.
Mikulas
Mikulas Patocka
maintainerPATCH 1/4 x86: optimize memcpy_flushcache
I use memcpy_flushcache in my persistent memory driver for metadata updates and it turns out that the overhead of memcpy_flushcache causes 2% performance degradation compared to "movnti" instruction explicitly coded using inline assembler.
This patch recognizes memcpy_flushcache calls with constant short length and turns them into inline assembler - so that I don't have to use inline assembler in the driver.
--- arch/x86/include/asm/string_64.h | 20 +++++++++++++++++++- arch/x86/lib/usercopy_64.c | 4 ++-- 2 files changed, 21 insertions(+), 3 deletions(-)
arch/x86/include/asm/string_64.h +19 -1
@@ -147,7 +147,25 @@ memcpy_mcsafe(void *dst, const void *src#ifdef CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE #define __HAVE_ARCH_MEMCPY_FLUSHCACHE 1 -void memcpy_flushcache (void *dst,const void *src,size_t cnt); +void __memcpy_flushcache (void *dst,const void *src,size_t cnt); +static __always_inline void memcpy_flushcache(void *dst, const void *src, size_t cnt) +{ +if (__builtin_constant_p (cnt)) { +switch (cnt) { +case 4 : + asm ("movntil %1, %0" :"=m" (*(u32 *)dst) :"r" (*(u32 *)src)); +return ; +case 8 : + asm ("movntiq %1, %0" :"=m" (*(u64 *)dst) :"r" (*(u64 *)src)); +return ; +case 16 : + asm ("movntiq %1, %0" :"=m" (*(u64 *)dst) :"r" (*(u64 *)src)); + asm ("movntiq %1, %0" :"=m" (*(u64 *)(dst +8 )) :"r" (*(u64 *)(src +8 ))); +return ; + } + } +__memcpy_flushcache (dst, src, cnt); +}#endif #endif /* __KERNEL__ */
arch/x86/lib/usercopy_64.c +2 -2
@@ -133,7 +133,7 @@ long __copy_user_flushcache(void *dst, creturn rc; } -void memcpy_flushcache (void *_dst,const void *_src,size_t size) +void __memcpy_flushcache (void *_dst,const void *_src,size_t size) {unsigned long dest = (unsigned long ) _dst;unsigned long source = (unsigned long ) _src;
@@ -196,7 +196,7 @@ void memcpy_flushcache(void *_dst, constclean_cache_range ((void *) dest, size); } } -EXPORT_SYMBOL_GPL (memcpy_flushcache); +EXPORT_SYMBOL_GPL (__memcpy_flushcache);void memcpy_page_flushcache (char *to,struct page *page,size_t offset,size_t len)
Re: [patch 1/4] x86: optimize memcpy_flushcache
[ add x86 folks for their review / ack ]
Quoted 70 lines · Mikulas Patocka
I use
memcpy_flushcachein my persistent memory driver for metadata updates and it turns out that the overhead ofmemcpy_flushcachecauses 2% performance degradation compared to "movnti" instruction explicitly coded using inline assembler.This patch recognizes
memcpy_flushcachecalls with constant short length and turns them into inline assembler - so that I don't have to use inline assembler in the driver.Signed-off-by Mikulas Patocka <[email protected]>--- arch/x86/include/asm/string_64.h | 20 +++++++++++++++++++- arch/x86/lib/usercopy_64.c | 4 ++-- 2 files changed, 21 insertions(+), 3 deletions(-)Index:
linux-2.6/arch/x86/include/asm/string_64.h
===================================================================arch/x86/include/asm/string_64.h 2018-05-18 21:21:15.000000000 +0200 renamed from arch/x86/include/asm/string_64.h 2018-05-18 21:21:15.000000000 +0200 +19
-1@@ -147,7 +147,25 @@ memcpy_mcsafe(void *dst, const void *src #ifdef CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE #define __HAVE_ARCH_MEMCPY_FLUSHCACHE 1 -void memcpy_flushcache(void *dst, const void *src, size_t cnt); +void __memcpy_flushcache(void *dst, const void *src, size_t cnt); +static __always_inline void memcpy_flushcache(void *dst, const void *src, size_t cnt) +{ + if (__builtin_constant_p(cnt)) { + switch (cnt) { + case 4: + asm ("movntil %1, %0" : "=m"(*(u32 *)dst) : "r"(*(u32 *)src)); + return; + case 8: + asm ("movntiq %1, %0" : "=m"(*(u64 *)dst) : "r"(*(u64 *)src)); + return; + case 16: + asm ("movntiq %1, %0" : "=m"(*(u64 *)dst) : "r"(*(u64 *)src)); + asm ("movntiq %1, %0" : "=m"(*(u64 *)(dst + 8)) : "r"(*(u64 *)(src + 8))); + return; + } + } + __memcpy_flushcache(dst, src, cnt); +} #endif #endif /* __KERNEL__ */Index:
linux-2.6/arch/x86/lib/usercopy_64.c
===================================================================arch/x86/lib/usercopy_64.c 2018-05-18 22:09:49.000000000 +0200 renamed from arch/x86/lib/usercopy_64.c 2018-05-18 21:21:15.000000000 +0200 +2
-2@@ -133,7 +133,7 @@ long __copy_user_flushcache(void *dst, c return rc; } -void memcpy_flushcache(void *_dst, const void *_src, size_t size) +void __memcpy_flushcache(void *_dst, const void *_src, size_t size) { unsigned long dest = (unsigned long) _dst; unsigned long source = (unsigned long) _src;@@ -196,7 +196,7 @@ void memcpy_flushcache(void *_dst, const clean_cache_range((void *) dest, size); } } -EXPORT_SYMBOL_GPL(memcpy_flushcache); +EXPORT_SYMBOL_GPL(__memcpy_flushcache); void memcpy_page_flushcache(char *to, struct page *page, size_t offset, size_t len)
PATCH v2 1/1 x86: optimize memcpy_flushcache
[v2: revised header, reformatted asm, reduced indent in switch statement. Ingo or Thomas: please review and consider picking this up for 4.18]
From: Mikulas Patocka <[email protected]>
Subject: [PATCH v2] x86: optimize memcpy_flushcache
In the context of constant short length stores to persistent memory, memcpy_flushcache suffers from a 2% performance degradation compared to explicitly using the "movnti" instruction.
Optimize 4, 8, and 16 byte memcpy_flushcache calls to explicitly use the movnti instruction with inline assembler.
--- arch/x86/include/asm/string_64.h | 28 +++++++++++++++++++++++++++- arch/x86/lib/usercopy_64.c | 4 ++-- 2 files changed, 29 insertions(+), 3 deletions(-)
arch/x86/include/asm/string_64.h +27 -1
@@ -147,7 +147,33 @@ memcpy_mcsafe(void *dst, const void *src, size_t cnt)#ifdef CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE #define __HAVE_ARCH_MEMCPY_FLUSHCACHE 1 -void memcpy_flushcache (void *dst,const void *src,size_t cnt); +void __memcpy_flushcache (void *dst,const void *src,size_t cnt); +static __always_inline void memcpy_flushcache(void *dst, const void *src, size_t cnt) +{ +if (__builtin_constant_p (cnt)) { +switch (cnt) { +case 4 : + asmvolatile ("movntil %1, %0" + :"=m" (*(u32 *)dst) + :"r" (*(u32 *)src)); +return ; +case 8 : + asmvolatile ("movntiq %1, %0" + :"=m" (*(u64 *)dst) + :"r" (*(u64 *)src)); +return ; +case 16 : + asmvolatile ("movntiq %1, %0" + :"=m" (*(u64 *)dst) + :"r" (*(u64 *)src)); + asmvolatile ("movntiq %1, %0" + :"=m" (*(u64 *)(dst +8 )) + :"r" (*(u64 *)(src +8 ))); +return ; + } + } +__memcpy_flushcache (dst, src, cnt); +}#endif #endif /* __KERNEL__ */
arch/x86/lib/usercopy_64.c +2 -2
@@ -133,7 +133,7 @@ long __copy_user_flushcache(void *dst, const void __user *src, unsigned size)return rc; } -void memcpy_flushcache (void *_dst,const void *_src,size_t size) +void __memcpy_flushcache (void *_dst,const void *_src,size_t size) {unsigned long dest = (unsigned long ) _dst;unsigned long source = (unsigned long ) _src;
@@ -196,7 +196,7 @@ void memcpy_flushcache(void *_dst, const void *_src, size_t size)clean_cache_range ((void *) dest, size); } } -EXPORT_SYMBOL_GPL (memcpy_flushcache); +EXPORT_SYMBOL_GPL (__memcpy_flushcache);void memcpy_page_flushcache (char *to,struct page *page,size_t offset,size_t len)
Signature · 1 line
2.15.0
PATCH RESEND v2 1/1 x86: optimize memcpy_flushcache
From: Mikulas Patocka <[email protected]>
Subject: [PATCH v2] x86: optimize memcpy_flushcache
In the context of constant short length stores to persistent memory, memcpy_flushcache suffers from a 2% performance degradation compared to explicitly using the "movnti" instruction.
Optimize 4, 8, and 16 byte memcpy_flushcache calls to explicitly use the movnti instruction with inline assembler.
--- arch/x86/include/asm/string_64.h | 28 +++++++++++++++++++++++++++- arch/x86/lib/usercopy_64.c | 4 ++-- 2 files changed, 29 insertions(+), 3 deletions(-)
arch/x86/include/asm/string_64.h +27 -1
@@ -147,7 +147,33 @@ memcpy_mcsafe(void *dst, const void *src, size_t cnt)#ifdef CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE #define __HAVE_ARCH_MEMCPY_FLUSHCACHE 1 -void memcpy_flushcache (void *dst,const void *src,size_t cnt); +void __memcpy_flushcache (void *dst,const void *src,size_t cnt); +static __always_inline void memcpy_flushcache(void *dst, const void *src, size_t cnt) +{ +if (__builtin_constant_p (cnt)) { +switch (cnt) { +case 4 : + asmvolatile ("movntil %1, %0" + :"=m" (*(u32 *)dst) + :"r" (*(u32 *)src)); +return ; +case 8 : + asmvolatile ("movntiq %1, %0" + :"=m" (*(u64 *)dst) + :"r" (*(u64 *)src)); +return ; +case 16 : + asmvolatile ("movntiq %1, %0" + :"=m" (*(u64 *)dst) + :"r" (*(u64 *)src)); + asmvolatile ("movntiq %1, %0" + :"=m" (*(u64 *)(dst +8 )) + :"r" (*(u64 *)(src +8 ))); +return ; + } + } +__memcpy_flushcache (dst, src, cnt); +}#endif #endif /* __KERNEL__ */
arch/x86/lib/usercopy_64.c +2 -2
@@ -133,7 +133,7 @@ long __copy_user_flushcache(void *dst, const void __user *src, unsigned size)return rc; } -void memcpy_flushcache (void *_dst,const void *_src,size_t size) +void __memcpy_flushcache (void *_dst,const void *_src,size_t size) {unsigned long dest = (unsigned long ) _dst;unsigned long source = (unsigned long ) _src;
@@ -196,7 +196,7 @@ void memcpy_flushcache(void *_dst, const void *_src, size_t size)clean_cache_range ((void *) dest, size); } } -EXPORT_SYMBOL_GPL (memcpy_flushcache); +EXPORT_SYMBOL_GPL (__memcpy_flushcache);void memcpy_page_flushcache (char *to,struct page *page,size_t offset,size_t len)
Signature · 1 line
2.15.0
Re: [PATCH v2 RESEND] x86: optimize memcpy_flushcache
Quoted 9 lines · Mike Snitzer
From: Mikulas Patocka <[email protected]>
Subject: [PATCH v2] x86: optimizememcpy_flushcacheIn the context of constant short length stores to persistent memory,
memcpy_flushcachesuffers from a 2% performance degradation compared to explicitly using the "movnti" instruction.Optimize 4, 8, and 16 byte
memcpy_flushcachecalls to explicitly use the movnti instruction with inline assembler.
Linus requested asm optimizations to include actual benchmarks, so it would be nice to describe how this was tested, on what hardware, and what the before/after numbers are.
Thanks,
Ingo
Mikulas Patocka
maintainerRe: [PATCH v2 RESEND] x86: optimize memcpy_flushcache
Quoted 13 lines · Ingo Molnar
Quoted 9 lines · Mike Snitzer
From: Mikulas Patocka <[email protected]>
Subject: [PATCH v2] x86: optimizememcpy_flushcacheIn the context of constant short length stores to persistent memory,
memcpy_flushcachesuffers from a 2% performance degradation compared to explicitly using the "movnti" instruction.Optimize 4, 8, and 16 byte
memcpy_flushcachecalls to explicitly use the movnti instruction with inline assembler.
Quoted 7 lines
Linus requested asm optimizations to include actual benchmarks, so it would be nice to describe how this was tested, on what hardware, and what the before/after numbers are.
Thanks,
Ingo
It was tested on 4-core skylake machine with persistent memory being emulated using the memmap kernel option. The dm-writecache target used the emulated persistent memory as a cache and sata SSD as a backing device. The patch results in 2% improved throughput when writing data using dd.
I don't have access to the machine anymore.
Mikulas
Re: [PATCH v2 RESEND] x86: optimize memcpy_flushcache
Quoted 21 lines · Mikulas Patocka
Quoted 19 lines · Ingo Molnar
Quoted 9 lines · Mike Snitzer
From: Mikulas Patocka <[email protected]>
Subject: [PATCH v2] x86: optimizememcpy_flushcacheIn the context of constant short length stores to persistent memory,
memcpy_flushcachesuffers from a 2% performance degradation compared to explicitly using the "movnti" instruction.Optimize 4, 8, and 16 byte
memcpy_flushcachecalls to explicitly use the movnti instruction with inline assembler.Linus requested asm optimizations to include actual benchmarks, so it would be nice to describe how this was tested, on what hardware, and what the before/after numbers are.
Thanks,
Quoted 8 lines
Quoted 1 line
Ingo
It was tested on 4-core skylake machine with persistent memory being emulated using the memmap kernel option. The dm-writecache target used the emulated persistent memory as a cache and sata SSD as a backing device. The patch results in 2% improved throughput when writing data using dd.
I don't have access to the machine anymore.
I think this information is enough, but do we know how well memmap emulation represents true persistent memory speed and cache management characteristics? It might be representative - but I don't know for sure, nor probably most readers of the changelog.
So could you please put all this into an updated changelog, and also add a short description that outlines exactly which codepaths end up using this method in a typical persistent memory setup? All filesystem ops - or only reads, etc?
Thanks,
Ingo
Mikulas Patocka
maintainerPATCH RESEND v3 1/1 x86: optimize memcpy_flushcache
Quoted 38 lines · Ingo Molnar
Quoted 21 lines · Mikulas Patocka
Quoted 19 lines · Ingo Molnar
Quoted 9 lines · Mike Snitzer
From: Mikulas Patocka <[email protected]>
Subject: [PATCH v2] x86: optimizememcpy_flushcacheIn the context of constant short length stores to persistent memory,
memcpy_flushcachesuffers from a 2% performance degradation compared to explicitly using the "movnti" instruction.Optimize 4, 8, and 16 byte
memcpy_flushcachecalls to explicitly use the movnti instruction with inline assembler.Linus requested asm optimizations to include actual benchmarks, so it would be nice to describe how this was tested, on what hardware, and what the before/after numbers are.
Thanks,
Quoted 8 lines
Quoted 1 line
Ingo
It was tested on 4-core skylake machine with persistent memory being emulated using the memmap kernel option. The dm-writecache target used the emulated persistent memory as a cache and sata SSD as a backing device. The patch results in 2% improved throughput when writing data using dd.
I don't have access to the machine anymore.
I think this information is enough, but do we know how well memmap emulation represents true persistent memory speed and cache management characteristics? It might be representative - but I don't know for sure, nor probably most readers of the changelog.
Quoted 7 lines
So could you please put all this into an updated changelog, and also add a short description that outlines exactly which codepaths end up using this method in a typical persistent memory setup? All filesystem ops - or only reads, etc?
Thanks,
Ingo
Here I resend it:
From: Mikulas Patocka <[email protected]>
Subject: [PATCH] x86: optimize memcpy_flushcache
I use memcpy_flushcache in my persistent memory driver for metadata updates, there are many 8-byte and 16-byte updates and it turns out that the overhead of memcpy_flushcache causes 2% performance degradation compared to "movnti" instruction explicitly coded using inline assembler.
The tests were done on a Skylake processor with persistent memory emulated using the "memmap" kernel parameter. dd was used to copy data to the dm-writecache target.
This patch recognizes memcpy_flushcache calls with constant short length and turns them into inline assembler - so that I don't have to use inline assembler in the driver.
--- arch/x86/include/asm/string_64.h | 20 +++++++++++++++++++- arch/x86/lib/usercopy_64.c | 4 ++-- 2 files changed, 21 insertions(+), 3 deletions(-)
arch/x86/include/asm/string_64.h +19 -1
@@ -149,7 +149,25 @@ memcpy_mcsafe(void *dst, const void *src#ifdef CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE #define __HAVE_ARCH_MEMCPY_FLUSHCACHE 1 -void memcpy_flushcache (void *dst,const void *src,size_t cnt); +void __memcpy_flushcache (void *dst,const void *src,size_t cnt); +static __always_inline void memcpy_flushcache(void *dst, const void *src, size_t cnt) +{ +if (__builtin_constant_p (cnt)) { +switch (cnt) { +case 4 : + asm ("movntil %1, %0" :"=m" (*(u32 *)dst) :"r" (*(u32 *)src)); +return ; +case 8 : + asm ("movntiq %1, %0" :"=m" (*(u64 *)dst) :"r" (*(u64 *)src)); +return ; +case 16 : + asm ("movntiq %1, %0" :"=m" (*(u64 *)dst) :"r" (*(u64 *)src)); + asm ("movntiq %1, %0" :"=m" (*(u64 *)(dst +8 )) :"r" (*(u64 *)(src +8 ))); +return ; + } + } +__memcpy_flushcache (dst, src, cnt); +}#endif #endif /* __KERNEL__ */
arch/x86/lib/usercopy_64.c +2 -2
@@ -153,7 +153,7 @@ long __copy_user_flushcache(void *dst, creturn rc; } -void memcpy_flushcache (void *_dst,const void *_src,size_t size) +void __memcpy_flushcache (void *_dst,const void *_src,size_t size) {unsigned long dest = (unsigned long ) _dst;unsigned long source = (unsigned long ) _src;
@@ -216,7 +216,7 @@ void memcpy_flushcache(void *_dst, constclean_cache_range ((void *) dest, size); } } -EXPORT_SYMBOL_GPL (memcpy_flushcache); +EXPORT_SYMBOL_GPL (__memcpy_flushcache);void memcpy_page_flushcache (char *to,struct page *page,size_t offset,size_t len)
Ingo Molnar
AppliedRe: [PATCH v3 RESEND] x86: optimize memcpy_flushcache
Quoted 19 lines · Mikulas Patocka
Here I resend it:
From: Mikulas Patocka <[email protected]>
Subject: [PATCH] x86: optimizememcpy_flushcacheI use
memcpy_flushcachein my persistent memory driver for metadata updates, there are many 8-byte and 16-byte updates and it turns out that the overhead ofmemcpy_flushcachecauses 2% performance degradation compared to "movnti" instruction explicitly coded using inline assembler.The tests were done on a Skylake processor with persistent memory emulated using the "memmap" kernel parameter. dd was used to copy data to the dm-writecache target.
This patch recognizes
memcpy_flushcachecalls with constant short length and turns them into inline assembler - so that I don't have to use inline assembler in the driver.
Quoted 6 lines
Signed-off-by Mikulas Patocka <[email protected]>--- arch/x86/include/asm/string_64.h | 20 +++++++++++++++++++- arch/x86/lib/usercopy_64.c | 4 ++-- 2 files changed, 21 insertions(+), 3 deletions(-)
Applied to tip:x86/asm, thanks!
I'll push it out later today after some testing.
Thanks,
Ingo
tip-bot for Mikulas Patocka
merge bot[tip:x86/asm] x86/asm: Optimize memcpy_flushcache()
In reply to Mikulas Patockax86/asm: Optimize memcpy_flushcache()
Commit-ID: 02101c45ec5b19d607af7372680f5259050b4e9c Gitweb: https://git.kernel.org/tip/02101c45ec5b19d607af7372680f5259050b4e9c Author: Mikulas Patocka <[email protected]> AuthorDate: Wed, 8 Aug 2018 17:22:16 -0400 Committer: Ingo Molnar <[email protected]> CommitDate: Mon, 10 Sep 2018 15:17:12 +0200
x86/asm: Optimize memcpy_flushcache()
I use memcpy_flushcache() in my persistent memory driver for metadata updates, there are many 8-byte and 16-byte updates and it turns out that the overhead of memcpy_flushcache causes 2% performance degradation compared to "movnti" instruction explicitly coded using inline assembler.
The tests were done on a Skylake processor with persistent memory emulated using the "memmap" kernel parameter. dd was used to copy data to the dm-writecache target.
This patch recognizes memcpy_flushcache calls with constant short length and turns them into inline assembler - so that I don't have to use inline assembler in the driver.
--- arch/x86/include/asm/string_64.h | 20 +++++++++++++++++++- arch/x86/lib/usercopy_64.c | 4 ++-- 2 files changed, 21 insertions(+), 3 deletions(-)
arch/x86/include/asm/string_64.h +19 -1
@@ -149,7 +149,25 @@ memcpy_mcsafe(void *dst, const void *src, size_t cnt)#ifdef CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE #define __HAVE_ARCH_MEMCPY_FLUSHCACHE 1 -void memcpy_flushcache (void *dst,const void *src,size_t cnt); +void __memcpy_flushcache (void *dst,const void *src,size_t cnt); +static __always_inline void memcpy_flushcache(void *dst, const void *src, size_t cnt) +{ +if (__builtin_constant_p (cnt)) { +switch (cnt) { +case 4 : + asm ("movntil %1, %0" :"=m" (*(u32 *)dst) :"r" (*(u32 *)src)); +return ; +case 8 : + asm ("movntiq %1, %0" :"=m" (*(u64 *)dst) :"r" (*(u64 *)src)); +return ; +case 16 : + asm ("movntiq %1, %0" :"=m" (*(u64 *)dst) :"r" (*(u64 *)src)); + asm ("movntiq %1, %0" :"=m" (*(u64 *)(dst +8 )) :"r" (*(u64 *)(src +8 ))); +return ; + } + } +__memcpy_flushcache (dst, src, cnt); +}#endif #endif /* __KERNEL__ */
arch/x86/lib/usercopy_64.c +2 -2
@@ -153,7 +153,7 @@ long __copy_user_flushcache(void *dst, const void __user *src, unsigned size)return rc; } -void memcpy_flushcache (void *_dst,const void *_src,size_t size) +void __memcpy_flushcache (void *_dst,const void *_src,size_t size) {unsigned long dest = (unsigned long ) _dst;unsigned long source = (unsigned long ) _src;
@@ -216,7 +216,7 @@ void memcpy_flushcache(void *_dst, const void *_src, size_t size)clean_cache_range ((void *) dest, size); } } -EXPORT_SYMBOL_GPL (memcpy_flushcache); +EXPORT_SYMBOL_GPL (__memcpy_flushcache);void memcpy_page_flushcache (char *to,struct page *page,size_t offset,size_t len)
Mikulas Patocka
maintainerPATCH 2/4 swait: export the symbols __prepare_to_swait and __finish_swait
In reply to Mikulas PatockaIn order to reduce locking overhead, I use the spinlock in swait_queue_head to protect not only the wait queue, but also the list of events. Consequently, I need to use unlocked functions __prepare_to_swait and __finish_swait. These functions are declared in the file include/linux/swait.h, but they are not exported, and so they are not useable from kernel modules.
--- kernel/sched/swait.c | 2 ++ 1 file changed, 2 insertions(+)
kernel/sched/swait.c +2 -0
@@ -75,6 +75,7 @@ void __prepare_to_swait(struct swait_queif (list_empty (&wait->task_list))list_add (&wait->task_list, &q->task_list); } +EXPORT_SYMBOL (__prepare_to_swait);void prepare_to_swait (struct swait_queue_head *q,struct swait_queue *wait,int state) {
@@ -104,6 +105,7 @@ void __finish_swait(struct swait_queue_hif (!list_empty (&wait->task_list))list_del_init (&wait->task_list); } +EXPORT_SYMBOL (__finish_swait);void finish_swait (struct swait_queue_head *q,struct swait_queue *wait) {
Re: [patch 2/4] swait: export the symbols __prepare_to_swait and __finish_swait
Quoted 6 lines · Mikulas Patocka
In order to reduce locking overhead, I use the spinlock in
swait_queue_headto protect not only the wait queue, but also the list of events. Consequently, I need to use unlocked functions__prepare_to_swaitand__finish_swait. These functions are declared in the fileinclude/linux/swait.h, but they are not exported, and so they are not useable from kernel modules.
Please CC the author and maintainers of the swait code.
My impression is that this is the wrong thing to do. The swait code is supposed to be simple and self contained, and if you want to do anything else use normal waitqueues.
Quoted 29 lines
Signed-off-by Mikulas Patocka <[email protected]>--- kernel/sched/swait.c | 2 ++ 1 file changed, 2 insertions(+)Index:
linux-2.6/kernel/sched/swait.c
===================================================================kernel/sched/swait.c +2
-1@@ -75,6 +75,7 @@ void __prepare_to_swait(struct swait_queif (list_empty (&wait->task_list))list_add (&wait->task_list, &q->task_list); } +EXPORT_SYMBOL (__prepare_to_swait);void prepare_to_swait (struct swait_queue_head *q,struct swait_queue *wait,int state) {@@ -104,6 +105,7 @@ void __finish_swait(struct swait_queue_hif (!list_empty (&wait->task_list))list_del_init (&wait->task_list); } +EXPORT_SYMBOL (__finish_swait);void finish_swait (struct swait_queue_head *q,struct swait_queue *wait) { --
Quoted 3 lines
dm-devel mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/dm-devel
---end quoted text---
Re: [patch 2/4] swait: export the symbols __prepare_to_swait and __finish_swait
Quoted 8 lines · Christoph Hellwig
Quoted 6 lines · Mikulas Patocka
In order to reduce locking overhead, I use the spinlock in
swait_queue_headto protect not only the wait queue, but also the list of events. Consequently, I need to use unlocked functions__prepare_to_swaitand__finish_swait. These functions are declared in the fileinclude/linux/swait.h, but they are not exported, and so they are not useable from kernel modules.
Quoted 5 lines
Please CC the author and maintainers of the swait code.
My impression is that this is the wrong thing to do. The swait code is supposed to be simple and self contained, and if you want to do anything else use normal waitqueues.
You said the same thing last time around. I've since cc'd Peter and Thomas and haven't heard back, see:
https://www.redhat.com/archives/dm-devel/2018-May/msg00048.html
The entire point of exporting these symbols is to allow use of the "simple waitqueue" code to optimize -- without resorting to using normal waitqueues.
Mike
Peter Zijlstra
maintainerRe: [patch 2/4] swait: export the symbols __prepare_to_swait and __finish_swait
Quoted 5 lines · Mike Snitzer
Quoted 2 lines · Christoph Hellwig
Please CC the author and maintainers of the swait code.
Quoted 7 lines
Quoted 3 lines
My impression is that this is the wrong thing to do. The swait code is supposed to be simple and self contained, and if you want to do anything else use normal waitqueues.
You said the same thing last time around. I've since cc'd Peter and Thomas and haven't heard back, see:
https://www.redhat.com/archives/dm-devel/2018-May/msg00048.html
Yeah, sorry, got lost :/
Quoted 3 lines
The entire point of exporting these symbols is to allow use of the "simple waitqueue" code to optimize -- without resorting to using normal waitqueues.
So I don't immediately object to exporting them; however I do share some of hch's concerns. The reason swait exists is to be deterministic (for RT) -- something that regular wait code cannot be.
And by (ab)using / exporting the wait internal lock you risk loosing that. So I don't think the proposed usage is bad, it is possible to create badness.
So if we're going to export them; someone needs to keep an eye on things and ensure the lock isn't abused.
Re: [patch 2/4] swait: export the symbols __prepare_to_swait and __finish_swait
Quoted 10 lines · Peter Zijlstra
Quoted 9 lines · Mike Snitzer
Quoted 5 lines · Christoph Hellwig
Please CC the author and maintainers of the swait code.
My impression is that this is the wrong thing to do. The swait code is supposed to be simple and self contained, and if you want to do anything else use normal waitqueues.
Quoted 5 lines
Quoted 3 lines
You said the same thing last time around. I've since cc'd Peter and Thomas and haven't heard back, see:
https://www.redhat.com/archives/dm-devel/2018-May/msg00048.htmlYeah, sorry, got lost :/
np
Quoted 11 lines
Quoted 3 lines
The entire point of exporting these symbols is to allow use of the "simple waitqueue" code to optimize -- without resorting to using normal waitqueues.
So I don't immediately object to exporting them; however I do share some of hch's concerns. The reason swait exists is to be deterministic (for RT) -- something that regular wait code cannot be.
And by (ab)using / exporting the wait internal lock you risk loosing that. So I don't think the proposed usage is bad, it is possible to create badness.
Understood.
Quoted 2 lines
So if we're going to export them; someone needs to keep an eye on things and ensure the lock isn't abused.
I'll update the patch header and swait.h to reflect these requirements and send out a new patch.
If you could then reply with your explicit Ack I can stage it for 4.18 via linux-dm.git to ease cross tree dependencies (given dm-writecache depends on these exports) -- provided you're OK with me doing that.
Thanks,
Mike
PATCH v2 1/1 swait: export symbols __prepare_to_swait and __finish_swait
[Peter, in this v2 I switched to using _GPL for the exports and updated the patch header. As covered in previous mail, please let me know if you're OK with me staging this change for 4.18 via linux-dm.git with your Ack, thanks]
From: Mikulas Patocka <[email protected]>
Subject: [PATCH] swait: export symbols __prepare_to_swait and __finish_swait
__prepare_to_swait and __finish_swait are declared in include/linux/swait.h but they are not exported; so they are not useable from kernel modules.
A new consumer of swait (in dm-writecache) reduces its locking overhead by using the spinlock in swait_queue_head to protect not only the wait queue, but also the list of events. Consequently, this swait consuming kernel module needs to use these unlocked functions.
Peter Zijlstra explained:
"The reason swait exists is to be deterministic (for RT) -- something that regular wait code cannot be.
And by (ab)using / exporting the wait internal lock you risk losing that. So I don't think the proposed [dm-writecache] usage is bad, it is possible to create badness.
So if we're going to export them; someone needs to keep an eye on things and ensure the lock isn't abused."
So while this new use of the wait internal lock doesn't jeopardize the realtime requirements of swait, these exports do open swait's internal locking up to being abused. As such, EXPORT_SYMBOL_GPL is used because any future consumers of __prepare_to_swait and __finish_swait must always be thoroughly scrutinized.
--- kernel/sched/swait.c | 2 ++ 1 file changed, 2 insertions(+)
kernel/sched/swait.c +2 -0
@@ -75,6 +75,7 @@ void __prepare_to_swait(struct swait_queue_head *q, struct swait_queue *wait)if (list_empty (&wait->task_list))list_add (&wait->task_list, &q->task_list); } +EXPORT_SYMBOL_GPL (__prepare_to_swait);void prepare_to_swait (struct swait_queue_head *q,struct swait_queue *wait,int state) {
@@ -104,6 +105,7 @@ void __finish_swait(struct swait_queue_head *q, struct swait_queue *wait)if (!list_empty (&wait->task_list))list_del_init (&wait->task_list); } +EXPORT_SYMBOL_GPL (__finish_swait);void finish_swait (struct swait_queue_head *q,struct swait_queue *wait) {
Signature · 1 line
2.15.0
Mikulas Patocka
maintainerRe: [PATCH v2] swait: export symbols __prepare_to_swait and __finish_swait
Quoted 61 lines · Mike Snitzer
[Peter, in this v2 I switched to using
_GPLfor the exports and updated the patch header. As covered in previous mail, please let me know if you're OK with me staging this change for 4.18 via linux-dm.git with your Ack, thanks]From: Mikulas Patocka <[email protected]>
Subject: [PATCH] swait: export symbols__prepare_to_swaitand__finish_swait
__prepare_to_swaitand__finish_swaitare declared ininclude/linux/swait.hbut they are not exported; so they are not useable from kernel modules.A new consumer of swait (in dm-writecache) reduces its locking overhead by using the spinlock in
swait_queue_headto protect not only the wait queue, but also the list of events. Consequently, this swait consuming kernel module needs to use these unlocked functions.Peter Zijlstra explained:
"The reason swait exists is to be deterministic (for RT) -- something that regular wait code cannot be.
And by (ab)using / exporting the wait internal lock you risk losing that. So I don't think the proposed [dm-writecache] usage is bad, it is possible to create badness.
So if we're going to export them; someone needs to keep an eye on things and ensure the lock isn't abused."So while this new use of the wait internal lock doesn't jeopardize the realtime requirements of swait, these exports do open swait's internal locking up to being abused. As such,
EXPORT_SYMBOL_GPLis used because any future consumers of__prepare_to_swaitand__finish_swaitmust always be thoroughly scrutinized.Cc Peter Zijlstra <[email protected]>Signed-off-by Mikulas Patocka <[email protected]>Signed-off-by Mike Snitzer <[email protected]>--- kernel/sched/swait.c | 2 ++ 1 file changed, 2 insertions(+)kernel/sched/swait.c +2
-0@@ -75,6 +75,7 @@ void __prepare_to_swait(struct swait_queue_head *q, struct swait_queue *wait)if (list_empty (&wait->task_list))list_add (&wait->task_list, &q->task_list); } +EXPORT_SYMBOL_GPL (__prepare_to_swait);void prepare_to_swait (struct swait_queue_head *q,struct swait_queue *wait,int state) {@@ -104,6 +105,7 @@ void __finish_swait(struct swait_queue_head *q, struct swait_queue *wait)if (!list_empty (&wait->task_list))list_del_init (&wait->task_list); } +EXPORT_SYMBOL_GPL (__finish_swait);void finish_swait (struct swait_queue_head *q,struct swait_queue *wait) {Signature · 1 line
2.15.0
Then - you should export swake_up_locked with EXPORT_SYMBOL_GPL too.
Because swake_up_locked is unusable without __prepare_to_swait and __finish_swait.
Mikulas
Re: [PATCH v2] swait: export symbols __prepare_to_swait and __finish_swait
Quoted 68 lines · Mikulas Patocka
Quoted 61 lines · Mike Snitzer
[Peter, in this v2 I switched to using
_GPLfor the exports and updated the patch header. As covered in previous mail, please let me know if you're OK with me staging this change for 4.18 via linux-dm.git with your Ack, thanks]From: Mikulas Patocka <[email protected]>
Subject: [PATCH] swait: export symbols__prepare_to_swaitand__finish_swait
__prepare_to_swaitand__finish_swaitare declared ininclude/linux/swait.hbut they are not exported; so they are not useable from kernel modules.A new consumer of swait (in dm-writecache) reduces its locking overhead by using the spinlock in
swait_queue_headto protect not only the wait queue, but also the list of events. Consequently, this swait consuming kernel module needs to use these unlocked functions.Peter Zijlstra explained:
"The reason swait exists is to be deterministic (for RT) -- something that regular wait code cannot be.
And by (ab)using / exporting the wait internal lock you risk losing that. So I don't think the proposed [dm-writecache] usage is bad, it is possible to create badness.
So if we're going to export them; someone needs to keep an eye on things and ensure the lock isn't abused."So while this new use of the wait internal lock doesn't jeopardize the realtime requirements of swait, these exports do open swait's internal locking up to being abused. As such,
EXPORT_SYMBOL_GPLis used because any future consumers of__prepare_to_swaitand__finish_swaitmust always be thoroughly scrutinized.Cc Peter Zijlstra <[email protected]>Signed-off-by Mikulas Patocka <[email protected]>Signed-off-by Mike Snitzer <[email protected]>--- kernel/sched/swait.c | 2 ++ 1 file changed, 2 insertions(+)kernel/sched/swait.c +2
-0@@ -75,6 +75,7 @@ void __prepare_to_swait(struct swait_queue_head *q, struct swait_queue *wait)if (list_empty (&wait->task_list))list_add (&wait->task_list, &q->task_list); } +EXPORT_SYMBOL_GPL (__prepare_to_swait);void prepare_to_swait (struct swait_queue_head *q,struct swait_queue *wait,int state) {@@ -104,6 +105,7 @@ void __finish_swait(struct swait_queue_head *q, struct swait_queue *wait)if (!list_empty (&wait->task_list))list_del_init (&wait->task_list); } +EXPORT_SYMBOL_GPL (__finish_swait);void finish_swait (struct swait_queue_head *q,struct swait_queue *wait) {Signature · 1 line
2.15.0Then - you should export
swake_up_lockedwithEXPORT_SYMBOL_GPLtoo.
Quoted 2 lines
Because
swake_up_lockedis unusable without__prepare_to_swaitand__finish_swait.
Point taken. But if swake_up_locked is unusable without them it is implicitly _GPL once __prepare_to_swait and __finish_swait are exported via _GPL. Which is to say, I don't care to get into the games of switching symbols from EXPORT_SYMBOL to EXPORT_SYMBOL_GPL unless completely necessary. Happy to leave well enough alone on this.
So I consider this v2 perfectly adequate for our needs. And appreciate any additional review/acks.
Thanks,
Mike
Re: [PATCH v2] swait: export symbols __prepare_to_swait and __finish_swait
In reply to Mike SnitzerQuoted 26 lines · Mike Snitzer
[Peter, in this v2 I switched to using
_GPLfor the exports and updated the patch header. As covered in previous mail, please let me know if you're OK with me staging this change for 4.18 via linux-dm.git with your Ack, thanks]From: Mikulas Patocka <[email protected]>
Subject: [PATCH] swait: export symbols__prepare_to_swaitand__finish_swait
__prepare_to_swaitand__finish_swaitare declared ininclude/linux/swait.hbut they are not exported; so they are not useable from kernel modules.A new consumer of swait (in dm-writecache) reduces its locking overhead by using the spinlock in
swait_queue_headto protect not only the wait queue, but also the list of events. Consequently, this swait consuming kernel module needs to use these unlocked functions.Peter Zijlstra explained:
"The reason swait exists is to be deterministic (for RT) -- something that regular wait code cannot be.
And by (ab)using / exporting the wait internal lock you risk losing that. So I don't think the proposed [dm-writecache] usage is bad, it is possible to create badness.
So if we're going to export them; someone needs to keep an eye on things and ensure the lock isn't abused."
Quoted 6 lines
So while this new use of the wait internal lock doesn't jeopardize the realtime requirements of swait, these exports do open swait's internal locking up to being abused. As such,
EXPORT_SYMBOL_GPLis used because any future consumers of__prepare_to_swaitand__finish_swaitmust always be thoroughly scrutinized.
Quoted 29 lines
Signed-off-by Mikulas Patocka <[email protected]>Signed-off-by Mike Snitzer <[email protected]>--- kernel/sched/swait.c | 2 ++ 1 file changed, 2 insertions(+)kernel/sched/swait.c +2
-0@@ -75,6 +75,7 @@ void __prepare_to_swait(struct swait_queue_head *q, struct swait_queue *wait)if (list_empty (&wait->task_list))list_add (&wait->task_list, &q->task_list); } +EXPORT_SYMBOL_GPL (__prepare_to_swait);void prepare_to_swait (struct swait_queue_head *q,struct swait_queue *wait,int state) {@@ -104,6 +105,7 @@ void __finish_swait(struct swait_queue_head *q, struct swait_queue *wait)if (!list_empty (&wait->task_list))list_del_init (&wait->task_list); } +EXPORT_SYMBOL_GPL (__finish_swait);void finish_swait (struct swait_queue_head *q,struct swait_queue *wait) {Signature · 1 line
2.15.0
Re: [PATCH v2] swait: export symbols __prepare_to_swait and __finish_swait
Quoted 27 lines · Peter Zijlstra
Quoted 26 lines · Mike Snitzer
[Peter, in this v2 I switched to using
_GPLfor the exports and updated the patch header. As covered in previous mail, please let me know if you're OK with me staging this change for 4.18 via linux-dm.git with your Ack, thanks]From: Mikulas Patocka <[email protected]>
Subject: [PATCH] swait: export symbols__prepare_to_swaitand__finish_swait
__prepare_to_swaitand__finish_swaitare declared ininclude/linux/swait.hbut they are not exported; so they are not useable from kernel modules.A new consumer of swait (in dm-writecache) reduces its locking overhead by using the spinlock in
swait_queue_headto protect not only the wait queue, but also the list of events. Consequently, this swait consuming kernel module needs to use these unlocked functions.Peter Zijlstra explained:
"The reason swait exists is to be deterministic (for RT) -- something that regular wait code cannot be.
And by (ab)using / exporting the wait internal lock you risk losing that. So I don't think the proposed [dm-writecache] usage is bad, it is possible to create badness.
So if we're going to export them; someone needs to keep an eye on things and ensure the lock isn't abused."
Quoted 8 lines
Quoted 6 lines
So while this new use of the wait internal lock doesn't jeopardize the realtime requirements of swait, these exports do open swait's internal locking up to being abused. As such,
EXPORT_SYMBOL_GPLis used because any future consumers of__prepare_to_swaitand__finish_swaitmust always be thoroughly scrutinized.
Thanks Peter.
Mikulas Patocka
maintainerPATCH 3/4 dm-writecache
In reply to Mikulas PatockaThe dm-writecache target.
--- Documentation/device-mapper/writecache.txt | 68 drivers/md/Kconfig | 11 drivers/md/Makefile | 1 drivers/md/dm-writecache.c | 2414 +++++++++++++++++++++++++++++ 4 files changed, 2494 insertions(+)
drivers/md/Kconfig +11 -0
@@ -334,6 +334,17 @@ config DM_CACHE_SMQ of less memory utilization, improved performance and increased adaptability in the face of changing workloads. +config DM_WRITECACHE + tristate "Writecache target" + depends on BLK_DEV_DM + ---help--- + The writecache target caches writes on persistent memory or SSD. + It is intended for databases or other programs that need extremely + low commit latency. + + The writecache target doesn't cache reads because reads are supposed + to be cached in standard RAM. + config DM_ERA tristate "Era target (EXPERIMENTAL)" depends on BLK_DEV_DM
drivers/md/Makefile +1 -0
@@ -67,6 +67,7 @@ obj-$(CONFIG_DM_ERA) += dm-era.o obj-$(CONFIG_DM_LOG_WRITES) += dm-log-writes.o obj-$(CONFIG_DM_INTEGRITY) += dm-integrity.o obj-$(CONFIG_DM_ZONED) += dm-zoned.o +obj-$(CONFIG_DM_WRITECACHE) += dm-writecache.o ifeq ($(CONFIG_DM_UEVENT),y) dm-mod-objs += dm-uevent.o
drivers/md/dm-writecache.c new file +2414 -0
2,414 lines not on this page · raw message
Documentation/device-mapper/writecache.txt new file +68 -0
68 lines not on this page · raw message
Re: [patch 3/4] dm-writecache
Quoted 3 lines · Mikulas Patocka
The dm-writecache target.
Signed-off-by Mikulas Patocka <[email protected]>
You'll need to actually describe your new code in the changelog.
drivers/md/dm-writecache.c line 5
Quoted 8 lines
drivers/md/dm-writecache.c new file +5
-0@@ -0,0 +1,2414 @@ +/* +* Copyright (C) 2018 Red Hat. All rights reserved. +* +* This file is released under the GPL. +*/
New code needs a SPDX header.
Quoted 4 lines
drivers/md/dm-writecache.c new file +4
-0+/* +* On X86, non-temporal stores are more efficient than cache flushing. +* On ARM64, cache flushing is more efficient. +*/
drivers/md/dm-writecache.c line 58
Quoted 10 lines
drivers/md/dm-writecache.c new file +10
-0+#if defined(CONFIG_X86_64 ) +#define EAGER_DATA_FLUSH +#define NT_STORE (dest, src) \ +do { \ + typeof(src) val = (src); \ + memcpy_flushcache(&(dest), &val, sizeof(src)); \ +} while (0) +#else +#define NT_STORE (dest, src) WRITE_ONCE(dest, src) +#endif
No per-arch hacks in the driver please, this needs a proper Kconfig symbol provided from the architectures.
drivers/md/dm-writecache.c line 99
Quoted 13 lines
drivers/md/dm-writecache.c new file +13
-0+struct wc_entry { +struct rb_node rb_node; +struct list_head lru; +unsigned short wc_list_contiguous; + bool write_in_progress +#if BITS_PER_LONG == 64 + :1 +#endif + ; + unsigned long index +#if BITS_PER_LONG == 64 + :47 +#endif
Hacks like this shouldn't normally exist, but if you absolutely need them you need to explain why in a comment.
Haven't had time to do a full review due to my backlog, I'll try to find some time later today or tomorrow.
Mikulas Patocka
maintainerPATCH 4/4 dm-writecache: use new API for flushing
In reply to Mikulas PatockaUse new API for flushing persistent memory.
The problem is this:
* on X86-64, non-temporal stores have the best performance
* ARM64 doesn't have non-temporal stores, so we must flush cache. We should flush cache as late as possible, because it performs better this way.
We introduce functions pmem_memcpy, pmem_flush and pmem_commit. To commit data persistently, all three functions must be called.
The macro pmem_assign may be used instead of pmem_memcpy. pmem_assign (unlike pmem_memcpy) guarantees that 8-byte values are written atomically.
On X86, pmem_memcpy is memcpy_flushcache, pmem_flush is empty and pmem_commit is wmb.
On ARM64, pmem_memcpy is memcpy, pmem_flush is arch_wb_cache_pmem and pmem_commit is empty.
--- drivers/md/dm-writecache.c | 100 +++++++++++++++++++++++++-------------------- 1 file changed, 56 insertions(+), 44 deletions(-)
drivers/md/dm-writecache.c +56 -44
@@ -14,6 +14,7 @@#include <linux/dm-kcopyd.h> #include <linux/dax.h> #include <linux/pfn_t.h> +#include <linux/libnvdimm.h> #define DM_MSG_PREFIX "writecache"
@@ -47,14 +48,48 @@* On ARM64, cache flushing is more efficient. */ #if defined(CONFIG_X86_64 ) -#define EAGER_DATA_FLUSH -#define NT_STORE (dest, src) \ -do { \ - typeof(src) val = (src); \ - memcpy_flushcache(&(dest), &val, sizeof(src)); \ + +static void pmem_memcpy (void *dest,void *src,size_t len) +{ +memcpy_flushcache (dest, src, len); +} + +#define __pmem_assign (dest, src, uniq) \ +do { \ + typeof(dest) uniq = (src); \ + memcpy_flushcache(&(dest), &uniq, sizeof(dest)); \ } while (0) + +#define pmem_assign (dest, src) \ + __pmem_assign(dest, src, __UNIQUE_ID(pmem_assign)) + +static void pmem_flush (void *dest,size_t len) +{ +} + +static void pmem_commit (void ) +{ +wmb (); +} +#else -#define NT_STORE (dest, src) WRITE_ONCE(dest, src) + +static void pmem_memcpy (void *dest,void *src,size_t len) +{ +memcpy (dest, src, len); +} + +#define pmem_assign (dest, src) WRITE_ONCE(dest, src) + +static void pmem_flush (void *dest,size_t len) +{ +arch_wb_cache_pmem (dest, len); +} + +static void pmem_commit (void ) +{ +} +#endif #if defined(__HAVE_ARCH_MEMCPY_MCSAFE) && !defined(DM_WRITECACHE_ONLY_SSD )
@@ -105,7 +140,7 @@ struct wc_entry { };#ifndef DM_WRITECACHE_ONLY_SSD -#define WC_MODE_PMEM (wc) ((wc)->pmem_mode) +#define WC_MODE_PMEM (wc) (likely((wc)->pmem_mode))#define WC_MODE_FUA (wc) ((wc)->writeback_fua)#else #define WC_MODE_PMEM (wc) false
@@ -400,21 +435,6 @@ static void persistent_memory_invalidateinvalidate_kernel_vmap_range (ptr, size); } -static void persistent_memory_flush (struct dm_writecache *wc,void *ptr,size_t size) -{ -#ifndef EAGER_DATA_FLUSH -dax_flush (wc->ssd_dev->dax_dev, ptr, size); -#endif -} - -static void persistent_memory_commit_flushed (void ) -{ -#ifdef EAGER_DATA_FLUSH -/* needed since memcpy_flushcache is used instead of dax_flush */ -wmb (); -#endif -} -static struct wc_memory_superblock *sb (struct dm_writecache *wc) {return wc->memory_map;
@@ -462,21 +482,20 @@ static void clear_seq_count(struct dm_wr#ifdef DM_WRITECACHE_HANDLE_HARDWARE_ERRORS e->seq_count =-1 ;#endif -NT_STORE (memory_entry (wc, e)->seq_count,cpu_to_le64 (-1 )); +pmem_assign (memory_entry (wc, e)->seq_count,cpu_to_le64 (-1 )); }static void write_original_sector_seq_count (struct dm_writecache *wc,struct wc_entry *e,uint64_t original_sector,uint64_t seq_count) { -struct wc_memory_entry *me_p, me; +struct wc_memory_entry me;#ifdef DM_WRITECACHE_HANDLE_HARDWARE_ERRORS e->original_sector = original_sector; e->seq_count = seq_count;#endif - me_p =memory_entry (wc, e); me.original_sector =cpu_to_le64 (original_sector); me.seq_count =cpu_to_le64 (seq_count); -NT_STORE (*me_p, me); +pmem_assign (*memory_entry (wc, e), me); } #define writecache_error(wc, err, msg, arg...) \
@@ -491,8 +510,7 @@ do { \static void writecache_flush_all_metadata (struct dm_writecache *wc) {if (WC_MODE_PMEM (wc)) { -persistent_memory_flush (wc, - sb(wc), offsetof(struct wc_memory_superblock, entries[wc->n_blocks])); + pmem_flush(sb(wc), offsetof(struct wc_memory_superblock, entries[wc->n_blocks])); }else {memset (wc->dirty_bitmap,-1 , wc->dirty_bitmap_size); }
@@ -501,7 +519,7 @@ static void writecache_flush_all_metadatstatic void writecache_flush_region (struct dm_writecache *wc,void *ptr,size_t size) {if (WC_MODE_PMEM (wc)) -persistent_memory_flush (wc, ptr, size); +pmem_flush (ptr, size);else __set_bit (((char *)ptr - (char *)wc->memory_map) /BITMAP_GRANULARITY , wc->dirty_bitmap);
@@ -579,7 +597,7 @@ static void ssd_commit_flushed(struct dmstatic void writecache_commit_flushed (struct dm_writecache *wc) {if (WC_MODE_PMEM (wc)) -persistent_memory_commit_flushed (); +pmem_commit ();else ssd_commit_flushed (wc); }
@@ -788,10 +806,8 @@ static void writecache_poison_lists(strustatic void writecache_flush_entry (struct dm_writecache *wc,struct wc_entry *e) {writecache_flush_region (wc,memory_entry (wc, e),sizeof (struct wc_memory_entry )); -#ifndef EAGER_DATA_FLUSH if (WC_MODE_PMEM (wc))writecache_flush_region (wc,memory_data (wc, e), wc->block_size); -#endif }static bool writecache_entry_is_committed (struct dm_writecache *wc,struct wc_entry *e)
@@ -834,7 +850,7 @@ static void writecache_flush(struct dm_wwritecache_wait_for_ios (wc,WRITE ); wc->seq_count++; -NT_STORE (sb (wc)->seq_count,cpu_to_le64 (wc->seq_count)); +pmem_assign (sb (wc)->seq_count,cpu_to_le64 (wc->seq_count));writecache_flush_region (wc, &sb (wc)->seq_count,sizeof sb (wc)->seq_count);writecache_commit_flushed (wc);
@@ -1152,11 +1168,7 @@ static void bio_copy_block(struct dm_wri } }else {flush_dcache_page (bio_page (bio)); -#ifdef EAGER_DATA_FLUSH -memcpy_flushcache (data, buf, size); -#else -memcpy (data, buf, size); -#endif +pmem_memcpy (data, buf, size); }bvec_kunmap_irq (buf, &flags);
@@ -1850,18 +1862,18 @@ static int init_memory(struct dm_writecareturn r;for (b =0 ; b <ARRAY_SIZE (sb (wc)->padding); b++) -NT_STORE (sb (wc)->padding[b],cpu_to_le64 (0 )); -NT_STORE (sb (wc)->version,cpu_to_le32 (MEMORY_SUPERBLOCK_VERSION )); -NT_STORE (sb (wc)->block_size,cpu_to_le32 (wc->block_size)); -NT_STORE (sb (wc)->n_blocks,cpu_to_le64 (wc->n_blocks)); -NT_STORE (sb (wc)->seq_count,cpu_to_le64 (0 )); +pmem_assign (sb (wc)->padding[b],cpu_to_le64 (0 )); +pmem_assign (sb (wc)->version,cpu_to_le32 (MEMORY_SUPERBLOCK_VERSION )); +pmem_assign (sb (wc)->block_size,cpu_to_le32 (wc->block_size)); +pmem_assign (sb (wc)->n_blocks,cpu_to_le64 (wc->n_blocks)); +pmem_assign (sb (wc)->seq_count,cpu_to_le64 (0 ));for (b =0 ; b < wc->n_blocks; b++)write_original_sector_seq_count (wc, &wc->entries[b],-1 ,-1 );writecache_flush_all_metadata (wc);writecache_commit_flushed (wc); -NT_STORE (sb (wc)->magic,cpu_to_le32 (MEMORY_SUPERBLOCK_MAGIC )); +pmem_assign (sb (wc)->magic,cpu_to_le32 (MEMORY_SUPERBLOCK_MAGIC ));writecache_flush_region (wc, &sb (wc)->magic,sizeof sb (wc)->magic);writecache_commit_flushed (wc);
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [dm-devel] [patch 4/4] dm-writecache: use new API for flushing
Quoted 1 line · Mikulas Patocka
Use new API for flushing persistent memory.
The sentence doesnt make much sense. 'A new API', 'A better abstraction' maybe?
Quoted 10 lines
The problem is this:
* on X86-64, non-temporal stores have the best performance
* ARM64 doesn't have non-temporal stores, so we must flush cache. We should flush cache as late as possible, because it performs better this way.We introduce functions
pmem_memcpy,pmem_flushandpmem_commit. To commit data persistently, all three functions must be called.
Quoted 8 lines
The macro
pmem_assignmay be used instead ofpmem_memcpy.pmem_assign(unlikepmem_memcpy) guarantees that 8-byte values are written atomically.On X86,
pmem_memcpyismemcpy_flushcache,pmem_flushis empty andpmem_commitis wmb.On ARM64,
pmem_memcpyis memcpy,pmem_flushisarch_wb_cache_pmemandpmem_commitis empty.
All these should be provided by the pmem layer, and be properly documented. And be sorted before adding your new target that uses them.
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [patch 4/4] dm-writecache: use new API for flushing
Quoted 22 lines · Christoph Hellwig
Quoted 1 line · Mikulas Patocka
Use new API for flushing persistent memory.
The sentence doesnt make much sense. 'A new API', 'A better abstraction' maybe?
Quoted 16 lines
The problem is this:
* on X86-64, non-temporal stores have the best performance
* ARM64 doesn't have non-temporal stores, so we must flush cache. We should flush cache as late as possible, because it performs better this way.We introduce functions
pmem_memcpy,pmem_flushandpmem_commit. To commit data persistently, all three functions must be called.The macro
pmem_assignmay be used instead ofpmem_memcpy.pmem_assign(unlikepmem_memcpy) guarantees that 8-byte values are written atomically.On X86,
pmem_memcpyismemcpy_flushcache,pmem_flushis empty andpmem_commitis wmb.
Quoted 6 lines
Quoted 2 lines
On ARM64,
pmem_memcpyis memcpy,pmem_flushisarch_wb_cache_pmemandpmem_commitis empty.All these should be provided by the pmem layer, and be properly documented. And be sorted before adding your new target that uses them.
I don't see that as a hard requirement. Mikulas did the work to figure out what is more optimal on x86_64 vs amd64. It makes a difference for his target and that is sufficient to carry it locally until/when it is either elevated to pmem.
We cannot even get x86 and swait maintainers to reply to repeat requests for review. Stacking up further deps on pmem isn't high on my list.
Mike
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [patch 4/4] dm-writecache: use new API for flushing
Quoted 32 lines · Mike Snitzer
Quoted 22 lines · Christoph Hellwig
Quoted 1 line · Mikulas Patocka
Use new API for flushing persistent memory.
The sentence doesnt make much sense. 'A new API', 'A better abstraction' maybe?
Quoted 16 lines
The problem is this:
* on X86-64, non-temporal stores have the best performance
* ARM64 doesn't have non-temporal stores, so we must flush cache. We should flush cache as late as possible, because it performs better this way.We introduce functions
pmem_memcpy,pmem_flushandpmem_commit. To commit data persistently, all three functions must be called.The macro
pmem_assignmay be used instead ofpmem_memcpy.pmem_assign(unlikepmem_memcpy) guarantees that 8-byte values are written atomically.On X86,
pmem_memcpyismemcpy_flushcache,pmem_flushis empty andpmem_commitis wmb.Quoted 6 lines
Quoted 2 lines
On ARM64,
pmem_memcpyis memcpy,pmem_flushisarch_wb_cache_pmemandpmem_commitis empty.All these should be provided by the pmem layer, and be properly documented. And be sorted before adding your new target that uses them.
Quoted 8 lines
I don't see that as a hard requirement. Mikulas did the work to figure out what is more optimal on
x86_64vs amd64. It makes a difference for his target and that is sufficient to carry it locally until/when it is either elevated to pmem.We cannot even get x86 and swait maintainers to reply to repeat requests for review. Stacking up further deps on pmem isn't high on my list.
Except I'm being responsive. I agree with Christoph that we should build pmem helpers at an architecture level and not per-driver. Let's make this driver depend on ARCH_HAS_PMEM_API and require ARM to catch up to x86 in this space. We already have PowerPC enabling PMEM API, so I don't see an unreasonable barrier to ask the same of ARM. This patch is not even cc'd to linux-arm-kernel. Has the subject been broached with them?
A message that is not in the archive (sent off-list or not yet received): CAPcyv4g395RccdEPF=sCu5RdCH9zwD+GvOfSp7-F0Oh64CeDgA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org
Re: [patch 4/4] dm-writecache: use new API for flushing
Quoted 38 lines · Dan Williams
Quoted 37 lines · Mike Snitzer
Quoted 22 lines · Christoph Hellwig
Quoted 1 line · Mikulas Patocka
Use new API for flushing persistent memory.
The sentence doesnt make much sense. 'A new API', 'A better abstraction' maybe?
Quoted 16 lines
The problem is this:
* on X86-64, non-temporal stores have the best performance
* ARM64 doesn't have non-temporal stores, so we must flush cache. We should flush cache as late as possible, because it performs better this way.We introduce functions
pmem_memcpy,pmem_flushandpmem_commit. To commit data persistently, all three functions must be called.The macro
pmem_assignmay be used instead ofpmem_memcpy.pmem_assign(unlikepmem_memcpy) guarantees that 8-byte values are written atomically.On X86,
pmem_memcpyismemcpy_flushcache,pmem_flushis empty andpmem_commitis wmb.Quoted 6 lines
Quoted 2 lines
On ARM64,
pmem_memcpyis memcpy,pmem_flushisarch_wb_cache_pmemandpmem_commitis empty.All these should be provided by the pmem layer, and be properly documented. And be sorted before adding your new target that uses them.
I don't see that as a hard requirement. Mikulas did the work to figure out what is more optimal on
x86_64vs amd64. It makes a difference for his target and that is sufficient to carry it locally until/when it is either elevated to pmem.
Quoted 5 lines
Quoted 3 lines
We cannot even get x86 and swait maintainers to reply to repeat requests for review. Stacking up further deps on pmem isn't high on my list.
Except I'm being responsive.
Except you're looking to immediately punt to linux-arm-kernel ;)
Quoted 7 lines
I agree with Christoph that we should
build pmem helpers at an architecture level and not per-driver. Let's make this driver depend onARCH_HAS_PMEM_APIand require ARM to catch up to x86 in this space. We already have PowerPC enabling PMEM API, so I don't see an unreasonable barrier to ask the same of ARM. This patch is not even cc'd to linux-arm-kernel. Has the subject been broached with them?
No idea. Not by me.
The thing is, I'm no expert in pmem. You are. Coordinating the change with ARM et al feels unnecessarily limiting and quicky moves outside my control.
Serious question: Why can't this code land in this dm-writecache target and then be lifted (or obsoleted)?
But if you think it worthwhile to force ARM to step up then fine. That does limit the availability of using writecache on ARM while they get the PMEM API together.
I'll do whatever you want.. just put the smack down and tell me how it is ;)
Thanks,
Mike
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [patch 4/4] dm-writecache: use new API for flushing
Quoted 41 lines · Mike Snitzer
Quoted 38 lines · Dan Williams
Quoted 37 lines · Mike Snitzer
Quoted 22 lines · Christoph Hellwig
Quoted 1 line · Mikulas Patocka
Use new API for flushing persistent memory.
The sentence doesnt make much sense. 'A new API', 'A better abstraction' maybe?
Quoted 16 lines
The problem is this:
* on X86-64, non-temporal stores have the best performance
* ARM64 doesn't have non-temporal stores, so we must flush cache. We should flush cache as late as possible, because it performs better this way.We introduce functions
pmem_memcpy,pmem_flushandpmem_commit. To commit data persistently, all three functions must be called.The macro
pmem_assignmay be used instead ofpmem_memcpy.pmem_assign(unlikepmem_memcpy) guarantees that 8-byte values are written atomically.On X86,
pmem_memcpyismemcpy_flushcache,pmem_flushis empty andpmem_commitis wmb.Quoted 6 lines
Quoted 2 lines
On ARM64,
pmem_memcpyis memcpy,pmem_flushisarch_wb_cache_pmemandpmem_commitis empty.All these should be provided by the pmem layer, and be properly documented. And be sorted before adding your new target that uses them.
I don't see that as a hard requirement. Mikulas did the work to figure out what is more optimal on
x86_64vs amd64. It makes a difference for his target and that is sufficient to carry it locally until/when it is either elevated to pmem.
Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
We cannot even get x86 and swait maintainers to reply to repeat requests for review. Stacking up further deps on pmem isn't high on my list.
Except I'm being responsive.
Except you're looking to immediately punt to linux-arm-kernel ;)
Well, I'm not, not really. I'm saying drop ARM support, it's not ready.
Quoted 9 lines
Quoted 8 lines
I agree with Christoph that we should
build pmem helpers at an architecture level and not per-driver. Let's make this driver depend onARCH_HAS_PMEM_APIand require ARM to catch up to x86 in this space. We already have PowerPC enabling PMEM API, so I don't see an unreasonable barrier to ask the same of ARM. This patch is not even cc'd to linux-arm-kernel. Has the subject been broached with them?
Quoted 8 lines
No idea. Not by me.
The thing is, I'm no expert in pmem. You are. Coordinating the change with ARM et al feels unnecessarily limiting and quicky moves outside my control.
Serious question: Why can't this code land in this dm-writecache target and then be lifted (or obsoleted)?
Because we already have an API, and we don't want to promote local solutions to global problems, or carry unnecessary technical debt.
Quoted 7 lines
But if you think it worthwhile to force ARM to step up then fine. That does limit the availability of using writecache on ARM while they get the PMEM API together.
I'll do whatever you want.. just put the smack down and tell me how it is ;)
I'd say just control the variables you can control. Drop the ARM support if you want to move forward and propose extensions / updates to the pmem api for x86 and I'll help push those since I was involved in pushing the x86 pmem api in the first instance. That way you don't need to touch this driver as new archs add their pmem api enabling.
A message that is not in the archive (sent off-list or not yet received): CAPcyv4hWswV=VCfB7KatoW_zc-kUUju2jD45N-Gsg4sW-XFe-A-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org
Re: [patch 4/4] dm-writecache: use new API for flushing
Quoted 78 lines · Dan Williams
Quoted 41 lines · Mike Snitzer
Quoted 38 lines · Dan Williams
Quoted 37 lines · Mike Snitzer
Quoted 22 lines · Christoph Hellwig
Quoted 1 line · Mikulas Patocka
Use new API for flushing persistent memory.
The sentence doesnt make much sense. 'A new API', 'A better abstraction' maybe?
Quoted 16 lines
The problem is this:
* on X86-64, non-temporal stores have the best performance
* ARM64 doesn't have non-temporal stores, so we must flush cache. We should flush cache as late as possible, because it performs better this way.We introduce functions
pmem_memcpy,pmem_flushandpmem_commit. To commit data persistently, all three functions must be called.The macro
pmem_assignmay be used instead ofpmem_memcpy.pmem_assign(unlikepmem_memcpy) guarantees that 8-byte values are written atomically.On X86,
pmem_memcpyismemcpy_flushcache,pmem_flushis empty andpmem_commitis wmb.Quoted 6 lines
Quoted 2 lines
On ARM64,
pmem_memcpyis memcpy,pmem_flushisarch_wb_cache_pmemandpmem_commitis empty.All these should be provided by the pmem layer, and be properly documented. And be sorted before adding your new target that uses them.
I don't see that as a hard requirement. Mikulas did the work to figure out what is more optimal on
x86_64vs amd64. It makes a difference for his target and that is sufficient to carry it locally until/when it is either elevated to pmem.Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
We cannot even get x86 and swait maintainers to reply to repeat requests for review. Stacking up further deps on pmem isn't high on my list.
Except I'm being responsive.
Except you're looking to immediately punt to linux-arm-kernel ;)
Well, I'm not, not really. I'm saying drop ARM support, it's not ready.
Quoted 9 lines
Quoted 8 lines
I agree with Christoph that we should
build pmem helpers at an architecture level and not per-driver. Let's make this driver depend onARCH_HAS_PMEM_APIand require ARM to catch up to x86 in this space. We already have PowerPC enabling PMEM API, so I don't see an unreasonable barrier to ask the same of ARM. This patch is not even cc'd to linux-arm-kernel. Has the subject been broached with them?Quoted 8 lines
No idea. Not by me.
The thing is, I'm no expert in pmem. You are. Coordinating the change with ARM et al feels unnecessarily limiting and quicky moves outside my control.
Serious question: Why can't this code land in this dm-writecache target and then be lifted (or obsoleted)?
Because we already have an API, and we don't want to promote local solutions to global problems, or carry unnecessary technical debt.
Quoted 5 lines
But if you think it worthwhile to force ARM to step up then fine. That does limit the availability of using writecache on ARM while they get the PMEM API together.
Quoted 8 lines
Quoted 2 lines
I'll do whatever you want.. just put the smack down and tell me how it is ;)
I'd say just control the variables you can control. Drop the ARM support if you want to move forward and propose extensions / updates to the pmem api for x86 and I'll help push those since I was involved in pushing the x86 pmem api in the first instance. That way you don't need to touch this driver as new archs add their pmem api enabling.
Looking at Mikulas' wrapper API that you and hch are calling into question:
For ARM it is using arch/arm64/mm/flush.c:arch_wb_cache_pmem(). (And ARM does seem to be providing CONFIG_ARCH_HAS_PMEM_API.)
Whereas x86_64 is using memcpy_flushcache() as provided by CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE.
(Yet ARM does provide arch/arm64/lib/uaccess_flushcache.c:memcpy_flushcache)
Just seems this isn't purely about ARM lacking on an API level (given on x86_64 Mikulas isn't only using CONFIG_ARCH_HAS_PMEM_API).
Seems this is more to do with x86_64 having efficient Non-temporal stores?
Anyway, I'm still trying to appreciate the details here before I can make any forward progress.
Mike
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [dm-devel] [patch 4/4] dm-writecache: use new API for flushing
Hi, Mike,
Quoted 10 lines · Mike Snitzer
Looking at Mikulas' wrapper API that you and hch are calling into question:
For ARM it is using arch/arm64/mm/flush.c:arch_wb_cache_pmem(). (And ARM does seem to be providing
CONFIG_ARCH_HAS_PMEM_API.)Whereas
x86_64is usingmemcpy_flushcache()as provided byCONFIG_ARCH_HAS_UACCESS_FLUSHCACHE.
(Yet ARM does provide arch/arm64/lib/uaccess_flushcache.c:memcpy_flushcache)
Quoted 5 lines
Just seems this isn't purely about ARM lacking on an API level (given on
x86_64Mikulas isn't only usingCONFIG_ARCH_HAS_PMEM_API).Seems this is more to do with
x86_64having efficient Non-temporal stores?
Yeah, I think you've got that all right.
Quoted 2 lines
Anyway, I'm still trying to appreciate the details here before I can make any forward progress.
Making data persistent on x64 requires 3 steps:
1) copy the data into pmem (store instructions)
2) flush the cache lines associated with the data (clflush, clflush_opt, clwb)
3) wait on the flush to complete (sfence)
I'm not sure if other architectures require step 3. Mikulas' implementation seems to imply that arm64 doesn't require the fence.
The current pmem api provides:
memcpy* -- step 1memcpy_flushcache -- this combines steps 1 and 2dax_flush -- step 2
wmb* -- step 3
* not strictly part of the pmem api
So, if you didn't care about performance, you could write generic code that only used memcpy, dax_flush, and wmb (assuming other arches actually need the wmb). What Mikulas did was to abstract out an API that could be called by generic code that would work optimally on all architectures.
This looks like a worth-while addition to the PMEM API, to me. Mikulas, what do you think about refactoring the code as Christoph suggested?
Cheers,
Jeff
A message that is not in the archive (sent off-list or not yet received): x49r2m3nvyk.fsf-RRHT56Q3PSP4kTEheFKJxxDDeQx5vsVwAInAS/Ez/[email protected]
Re: [dm-devel] [patch 4/4] dm-writecache: use new API for flushing
Quoted 22 lines · Jeff Moyer
Hi, Mike,
Quoted 10 lines · Mike Snitzer
Looking at Mikulas' wrapper API that you and hch are calling into question:
For ARM it is using arch/arm64/mm/flush.c:arch_wb_cache_pmem(). (And ARM does seem to be providing
CONFIG_ARCH_HAS_PMEM_API.)Whereas
x86_64is usingmemcpy_flushcache()as provided byCONFIG_ARCH_HAS_UACCESS_FLUSHCACHE.
(Yet ARM does provide arch/arm64/lib/uaccess_flushcache.c:memcpy_flushcache)Quoted 5 lines
Just seems this isn't purely about ARM lacking on an API level (given on
x86_64Mikulas isn't only usingCONFIG_ARCH_HAS_PMEM_API).Seems this is more to do with
x86_64having efficient Non-temporal stores?Yeah, I think you've got that all right.
Quoted 7 lines
Quoted 2 lines
Anyway, I'm still trying to appreciate the details here before I can make any forward progress.
Making data persistent on x64 requires 3 steps:
1) copy the data into pmem (store instructions)
2) flush the cache lines associated with the data (clflush,clflush_opt, clwb)
3) wait on the flush to complete (sfence)
In theory it works this way. In practice, this sequence is useless because the cache flusing instructions are horribly slow.
So, the dm-writecache driver uses non-temporal stores instead of cache flushing.
Now, the problem with arm64 is that it doesn't have non-temporal stores. So, memcpy_flushcache on arm64 does cached stores and flushes the cache afterwards. And this eager flushing is slower than late flushing. On arm4, you want to do cached stores, then do something else, and flush the cache as late as possible.
Quoted 2 lines
I'm not sure if other architectures require step 3. Mikulas' implementation seems to imply that arm64 doesn't require the fence.
I suppose that arch_wb_cache_pmem() does whatever it needs to do to flush the cache. If not, add something like arch_wb_cache_pmem_commit().
Quoted 9 lines
The current pmem api provides:
memcpy* -- step 1
memcpy_flushcache-- this combines steps 1 and 2dax_flush-- step 2
wmb* -- step 3* not strictly part of the pmem api
Quoted 8 lines
So, if you didn't care about performance, you could write generic code that only used memcpy,
dax_flush, and wmb (assuming other arches actually need the wmb). What Mikulas did was to abstract out an API that could be called by generic code that would work optimally on all architectures.This looks like a worth-while addition to the PMEM API, to me. Mikulas, what do you think about refactoring the code as Christoph suggested?
I sent this patch
https://www.redhat.com/archives/dm-devel/2018-May/msg00054.html so that you can take the functions pmem_memcpy, pmem_assign, pmem_flush and pmem_commit and move them to the generic linux headers. If you want to do it, do it.
Quoted 2 lines
Cheers,
Jeff
Mikulas
Re: [patch 4/4] dm-writecache: use new API for flushing
In reply to a message not in the archiveQuoted 5 lines · Dan Williams
Quoted 3 lines
Quoted 1 line
Except I'm being responsive.
Except you're looking to immediately punt to linux-arm-kernel ;)
Well, I'm not, not really. I'm saying drop ARM support, it's not ready.
This is the worst thing to do - because once late cache flushing is dropped from the dm-writecache target, it could hardly be reintroduced again.
Quoted 25 lines
Quoted 8 lines
Quoted 7 lines
I agree with Christoph that we should
build pmem helpers at an architecture level and not per-driver. Let's make this driver depend onARCH_HAS_PMEM_APIand require ARM to catch up to x86 in this space. We already have PowerPC enabling PMEM API, so I don't see an unreasonable barrier to ask the same of ARM. This patch is not even cc'd to linux-arm-kernel. Has the subject been broached with them?Quoted 8 lines
No idea. Not by me.
The thing is, I'm no expert in pmem. You are. Coordinating the change with ARM et al feels unnecessarily limiting and quicky moves outside my control.
Serious question: Why can't this code land in this dm-writecache target and then be lifted (or obsoleted)?
Because we already have an API, and we don't want to promote local solutions to global problems, or carry unnecessary technical debt.
Quoted 5 lines
But if you think it worthwhile to force ARM to step up then fine. That does limit the availability of using writecache on ARM while they get the PMEM API together.
Quoted 5 lines
Quoted 2 lines
I'll do whatever you want.. just put the smack down and tell me how it is ;)
I'd say just control the variables you can control. Drop the ARM support if you want to move forward and propose extensions / updates
What do we gain by dropping it?
Quoted 3 lines
to the pmem api for x86 and I'll help push those since I was involved in pushing the x86 pmem api in the first instance. That way you don't need to touch this driver as new archs add their pmem api enabling.
The pmem API is x86-centric - that the problem.
Mikulas
A message that is not in the archive (sent off-list or not yet received): alpine.LRH.2.02.1805280943460.16538-Hpncn10jQN4oNljnaZt3ZvA+iT7yCHsGwRM8/[email protected]
Re: [patch 4/4] dm-writecache: use new API for flushing
Quoted 45 lines · Mikulas Patocka
Quoted 5 lines · Dan Williams
Quoted 3 lines
Quoted 1 line
Except I'm being responsive.
Except you're looking to immediately punt to linux-arm-kernel ;)
Well, I'm not, not really. I'm saying drop ARM support, it's not ready.
This is the worst thing to do - because once late cache flushing is dropped from the dm-writecache target, it could hardly be reintroduced again.
Quoted 25 lines
Quoted 8 lines
Quoted 7 lines
I agree with Christoph that we should
build pmem helpers at an architecture level and not per-driver. Let's make this driver depend onARCH_HAS_PMEM_APIand require ARM to catch up to x86 in this space. We already have PowerPC enabling PMEM API, so I don't see an unreasonable barrier to ask the same of ARM. This patch is not even cc'd to linux-arm-kernel. Has the subject been broached with them?Quoted 8 lines
No idea. Not by me.
The thing is, I'm no expert in pmem. You are. Coordinating the change with ARM et al feels unnecessarily limiting and quicky moves outside my control.
Serious question: Why can't this code land in this dm-writecache target and then be lifted (or obsoleted)?
Because we already have an API, and we don't want to promote local solutions to global problems, or carry unnecessary technical debt.
Quoted 5 lines
But if you think it worthwhile to force ARM to step up then fine. That does limit the availability of using writecache on ARM while they get the PMEM API together.
Quoted 5 lines
Quoted 2 lines
I'll do whatever you want.. just put the smack down and tell me how it is ;)
I'd say just control the variables you can control. Drop the ARM support if you want to move forward and propose extensions / updates
Quoted 7 lines
What do we gain by dropping it?
Quoted 3 lines
to the pmem api for x86 and I'll help push those since I was involved in pushing the x86 pmem api in the first instance. That way you don't need to touch this driver as new archs add their pmem api enabling.
The pmem API is x86-centric - that the problem.
When I read your patch I came away with the impression that ARM had not added memcpy_flushcache() yet and you were working around that fact. Now that I look, ARM *does* define memcpy_flushcache() and you're avoiding it. You use memcpy+arch_wb_pmem where arch_wb_pmem on ARM64 is defined as __clean_dcache_area_pop(dst, cnt). The ARM memcpy_flushcache() implementation is:
memcpy(dst, src, cnt);
__clean_dcache_area_pop(dst, cnt);So, I do not see how what you're doing is any less work unless you are flushing less than you copy?
If memcpy_flushcache() is slower than memcpy + arch_wb_pmem then the ARM implementation is broken and that needs to be addressed not worked around in a driver.
A message that is not in the archive (sent off-list or not yet received): CAPcyv4gxCNqqG2G3R6f=kH3zNbByhgE2R-trJWurH49-p+51Gg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org
Re: [dm-devel] [patch 4/4] dm-writecache: use new API for flushing
Quoted 10 lines · Dan Williams
When I read your patch I came away with the impression that ARM had not added
memcpy_flushcache()yet and you were working around that fact. Now that I look, ARM *does* definememcpy_flushcache()and you're avoiding it. You use memcpy+arch_wb_pmem wherearch_wb_pmemon ARM64 is defined as__clean_dcache_area_pop(dst, cnt). The ARMmemcpy_flushcache()implementation is:memcpy(dst, src, cnt); __clean_dcache_area_pop(dst, cnt);
Quoted 6 lines
So, I do not see how what you're doing is any less work unless you are flushing less than you copy?
If
memcpy_flushcache()is slower than memcpy +arch_wb_pmemthen the ARM implementation is broken and that needs to be addressed not worked around in a driver.
I think Mikulas wanted to batch up multiple copies and flush at the end. According to his commit message, that batching gained him 2% performance.
-Jeff
A message that is not in the archive (sent off-list or not yet received): x49h8mpmf8v.fsf-RRHT56Q3PSP4kTEheFKJxxDDeQx5vsVwAInAS/Ez/[email protected]
Re: [dm-devel] [patch 4/4] dm-writecache: use new API for flushing
Quoted 19 lines · Jeff Moyer
Quoted 10 lines · Dan Williams
When I read your patch I came away with the impression that ARM had not added
memcpy_flushcache()yet and you were working around that fact. Now that I look, ARM *does* definememcpy_flushcache()and you're avoiding it. You use memcpy+arch_wb_pmem wherearch_wb_pmemon ARM64 is defined as__clean_dcache_area_pop(dst, cnt). The ARMmemcpy_flushcache()implementation is:memcpy(dst, src, cnt); __clean_dcache_area_pop(dst, cnt);Quoted 6 lines
So, I do not see how what you're doing is any less work unless you are flushing less than you copy?
If
memcpy_flushcache()is slower than memcpy +arch_wb_pmemthen the ARM implementation is broken and that needs to be addressed not worked around in a driver.
Quoted 5 lines
I think Mikulas wanted to batch up multiple copies and flush at the end. According to his commit message, that batching gained him 2% performance.
-Jeff
No - this 2% difference is inlined memcpy_flushcache() vs out-of-line memcpy_flushcache().
I thought that dax_flush() performed 12% better memcpy_flushcache() - but the reason why it performed better was - that it was not flushing the cache at all.
Mikulas
Re: [dm-devel] [patch 4/4] dm-writecache: use new API for flushing
In reply to a message not in the archiveQuoted 15 lines · Jeff Moyer
Quoted 13 lines · Dan Williams
When I read your patch I came away with the impression that ARM had not added
memcpy_flushcache()yet and you were working around that fact. Now that I look, ARM *does* definememcpy_flushcache()and you're avoiding it. You use memcpy+arch_wb_pmem wherearch_wb_pmemon ARM64 is defined as__clean_dcache_area_pop(dst, cnt). The ARMmemcpy_flushcache()implementation is:memcpy(dst, src, cnt); __clean_dcache_area_pop(dst, cnt);So, I do not see how what you're doing is any less work unless you are flushing less than you copy?
Quoted 7 lines
Quoted 3 lines
If
memcpy_flushcache()is slower than memcpy +arch_wb_pmemthen the ARM implementation is broken and that needs to be addressed not worked around in a driver.I think Mikulas wanted to batch up multiple copies and flush at the end. According to his commit message, that batching gained him 2% performance.
Nevermind me, I just caught up with the rest of the thread. :)
-Jeff
Re: [patch 4/4] dm-writecache: use new API for flushing
In reply to a message not in the archiveQuoted 42 lines · Dan Williams
Quoted 32 lines · Mike Snitzer
Quoted 22 lines · Christoph Hellwig
Quoted 1 line · Mikulas Patocka
Use new API for flushing persistent memory.
The sentence doesnt make much sense. 'A new API', 'A better abstraction' maybe?
Quoted 16 lines
The problem is this:
* on X86-64, non-temporal stores have the best performance
* ARM64 doesn't have non-temporal stores, so we must flush cache. We should flush cache as late as possible, because it performs better this way.We introduce functions
pmem_memcpy,pmem_flushandpmem_commit. To commit data persistently, all three functions must be called.The macro
pmem_assignmay be used instead ofpmem_memcpy.pmem_assign(unlikepmem_memcpy) guarantees that 8-byte values are written atomically.On X86,
pmem_memcpyismemcpy_flushcache,pmem_flushis empty andpmem_commitis wmb.Quoted 6 lines
Quoted 2 lines
On ARM64,
pmem_memcpyis memcpy,pmem_flushisarch_wb_cache_pmemandpmem_commitis empty.All these should be provided by the pmem layer, and be properly documented. And be sorted before adding your new target that uses them.
Quoted 8 lines
I don't see that as a hard requirement. Mikulas did the work to figure out what is more optimal on
x86_64vs amd64. It makes a difference for his target and that is sufficient to carry it locally until/when it is either elevated to pmem.We cannot even get x86 and swait maintainers to reply to repeat requests for review. Stacking up further deps on pmem isn't high on my list.
Quoted 7 lines
Except I'm being responsive. I agree with Christoph that we should build pmem helpers at an architecture level and not per-driver. Let's make this driver depend on
ARCH_HAS_PMEM_APIand require ARM to catch up to x86 in this space. We already have PowerPC enabling PMEM API, so I don't see an unreasonable barrier to ask the same of ARM. This patch is not even cc'd to linux-arm-kernel. Has the subject been broached with them?
The ARM code can't "catch-up" with X86.
On X86 - non-temporal stores (i.e. memcpy_flushcache) are faster than cached write and cache flushing.
The ARM architecture doesn't have non-temporal stores. So, memcpy_flushcache on ARM does memcpy (that writes data to the cache) and then flushes the cache. But this eager cache flushig is slower than late cache flushing.
The optimal code sequence on ARM to write to persistent memory is to call memcpy, then do something else, and then call arch_wb_cache_pmem as late as possible. And this ARM-optimized code sequence is just horribly slow on X86.
This issue can't be "fixed" in ARM-specific source code. The ARM processor have such a characteristics that eager cache flushing is slower than late cache flushing - and that's it - you can't change processor behavior.
If you don't want '#if defined(CONFIG_X86_64)' in the dm-writecache driver, then just take the functions that are in this conditional block and move them to some generic linux header.
Mikulas
Re: [patch 4/4] dm-writecache: use new API for flushing
In reply to Mikulas PatockaQuoted 11 lines · Mikulas Patocka
Use new API for flushing persistent memory.
The problem is this:
* on X86-64, non-temporal stores have the best performance
* ARM64 doesn't have non-temporal stores, so we must flush cache. We should flush cache as late as possible, because it performs better this way.We introduce functions
pmem_memcpy,pmem_flushandpmem_commit. To commit data persistently, all three functions must be called.
Quoted 8 lines
The macro
pmem_assignmay be used instead ofpmem_memcpy.pmem_assign(unlikepmem_memcpy) guarantees that 8-byte values are written atomically.On X86,
pmem_memcpyismemcpy_flushcache,pmem_flushis empty andpmem_commitis wmb.On ARM64,
pmem_memcpyis memcpy,pmem_flushisarch_wb_cache_pmemandpmem_commitis empty.
I don't want to grow driver-local wrappers for pmem. You should use memcpy_flushcache directly() and if an architecture does not define memcpy_flushcache() then don't allow building dm-writecache, i.e. this driver should 'depends on CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE'. I don't see a need to add a standalone flush operation if all relevant archs provide memcpy_flushcache(). As for commit, I'd say just use wmb() directly since all archs define it. Alternatively we could introduce memcpy_flushcache_relaxed() to be the un-ordered version of the copy routine and memcpy_flushcache() would imply a wmb().
Mikulas Patocka
maintainerRe: [patch 4/4] dm-writecache: use new API for flushing
Quoted 21 lines · Dan Williams
Quoted 11 lines · Mikulas Patocka
Use new API for flushing persistent memory.
The problem is this:
* on X86-64, non-temporal stores have the best performance
* ARM64 doesn't have non-temporal stores, so we must flush cache. We should flush cache as late as possible, because it performs better this way.We introduce functions
pmem_memcpy,pmem_flushandpmem_commit. To commit data persistently, all three functions must be called.Quoted 8 lines
The macro
pmem_assignmay be used instead ofpmem_memcpy.pmem_assign(unlikepmem_memcpy) guarantees that 8-byte values are written atomically.On X86,
pmem_memcpyismemcpy_flushcache,pmem_flushis empty andpmem_commitis wmb.On ARM64,
pmem_memcpyis memcpy,pmem_flushisarch_wb_cache_pmemandpmem_commitis empty.
Quoted 9 lines
I don't want to grow driver-local wrappers for pmem. You should use
memcpy_flushcachedirectly()and if an architecture does not definememcpy_flushcache()then don't allow building dm-writecache, i.e. this driver should 'depends onCONFIG_ARCH_HAS_UACCESS_FLUSHCACHE'. I don't see a need to add a standalone flush operation if all relevant archs providememcpy_flushcache(). As for commit, I'd say just usewmb()directly since all archs define it. Alternatively we could introducememcpy_flushcache_relaxed()to be the un-ordered version of the copy routine andmemcpy_flushcache()would imply awmb().
But memcpy_flushcache() on ARM64 is slow.
Mikulas
A message that is not in the archive (sent off-list or not yet received): alpine.LRH.2.02.1805250213270.13894-Hpncn10jQN4oNljnaZt3ZvA+iT7yCHsGwRM8/[email protected]
Re: [patch 4/4] dm-writecache: use new API for flushing
Quoted 35 lines · Mikulas Patocka
Quoted 21 lines · Dan Williams
Quoted 11 lines · Mikulas Patocka
Use new API for flushing persistent memory.
The problem is this:
* on X86-64, non-temporal stores have the best performance
* ARM64 doesn't have non-temporal stores, so we must flush cache. We should flush cache as late as possible, because it performs better this way.We introduce functions
pmem_memcpy,pmem_flushandpmem_commit. To commit data persistently, all three functions must be called.Quoted 8 lines
The macro
pmem_assignmay be used instead ofpmem_memcpy.pmem_assign(unlikepmem_memcpy) guarantees that 8-byte values are written atomically.On X86,
pmem_memcpyismemcpy_flushcache,pmem_flushis empty andpmem_commitis wmb.On ARM64,
pmem_memcpyis memcpy,pmem_flushisarch_wb_cache_pmemandpmem_commitis empty.Quoted 9 lines
I don't want to grow driver-local wrappers for pmem. You should use
memcpy_flushcachedirectly()and if an architecture does not definememcpy_flushcache()then don't allow building dm-writecache, i.e. this driver should 'depends onCONFIG_ARCH_HAS_UACCESS_FLUSHCACHE'. I don't see a need to add a standalone flush operation if all relevant archs providememcpy_flushcache(). As for commit, I'd say just usewmb()directly since all archs define it. Alternatively we could introducememcpy_flushcache_relaxed()to be the un-ordered version of the copy routine andmemcpy_flushcache()would imply awmb().
Quoted 1 line
But
memcpy_flushcache()on ARM64 is slow.
Yes, Dan can you please take some time to fully appreciate what this small wrapper API is providing (maybe you've done that, but your recent reply is mixed-message). Seems you're keeping the innovation it provides at arms-length. Basically the PMEM APIs you've helped construct are lacking, forcing DM developers to own fixing them is an inversion that only serves to stonewall.
Please, less time on stonewalling and more time lifting this wrapper API; otherwise the dm-writecache local wrapper API is a near-term means to an end.
I revised the dm-writecache patch header yesterday, please review:
https://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm.git/commit/?h=dm-4.18&id=2105231db61b08752bc4247d2fe7838657700b0d
(the last paragraph in particular, I intend to move forward with this wrapper unless someone on the PMEM side of the house steps up and lifts it up between now and when the 4.18 merge window opens)
dm: add writecache target
The writecache target caches writes on persistent memory or SSD. It is intended for databases or other programs that need extremely low commit latency.
The writecache target doesn't cache reads because reads are supposed to be cached in page cache in normal RAM.
The following describes the approach used to provide the most efficient flushing of persistent memory on X86_64 vs ARM64:
* On X86_64 non-temporal stores (i.e. memcpy_flushcache) are faster than cached writes and cache flushing.
* The ARM64 architecture doesn't have non-temporal stores. So, memcpy_flushcache on ARM does memcpy (that writes data to the cache) and then flushes the cache. But this eager cache flushig is slower than late cache flushing.
The optimal code sequence on ARM to write to persistent memory is to call memcpy, then do something else, and then call arch_wb_cache_pmem as late as possible. And this ARM-optimized code sequence is just horribly slow on X86.
This issue can't be "fixed" in ARM-specific source code. The ARM processor have characteristics such that eager cache flushing is slower than late cache flushing - and that's it - you can't change processor behavior.
We introduce a wrapper API for flushing persistent memory with functions pmem_memcpy, pmem_flush and pmem_commit. To commit data persistently, all three functions must be called.
The macro pmem_assign may be used instead of pmem_memcpy. pmem_assign (unlike pmem_memcpy) guarantees that 8-byte values are written atomically.
On X86_64, pmem_memcpy is memcpy_flushcache, pmem_flush is empty and pmem_commit is wmb.
On ARM64, pmem_memcpy is memcpy, pmem_flush is arch_wb_cache_pmem and pmem_commit is empty.
It is clear that this wrapper API for flushing persistent memory needs to be elevated out of this dm-writecache driver. But that can happen later without requiring DM developers to blaze new trails on pmem specific implementation details/quirks (pmem developers need to clean up their APIs given they are already spread across CONFIG_ARCH_HAS_PMEM_API and CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE and they absolutely don't take into account the duality of the different programming models needed to achieve optimal cross-architecture use of persistent memory).
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [patch 4/4] dm-writecache: use new API for flushing
Quoted 100 lines · Mike Snitzer
Quoted 35 lines · Mikulas Patocka
Quoted 21 lines · Dan Williams
Quoted 11 lines · Mikulas Patocka
Use new API for flushing persistent memory.
The problem is this:
* on X86-64, non-temporal stores have the best performance
* ARM64 doesn't have non-temporal stores, so we must flush cache. We should flush cache as late as possible, because it performs better this way.We introduce functions
pmem_memcpy,pmem_flushandpmem_commit. To commit data persistently, all three functions must be called.Quoted 8 lines
The macro
pmem_assignmay be used instead ofpmem_memcpy.pmem_assign(unlikepmem_memcpy) guarantees that 8-byte values are written atomically.On X86,
pmem_memcpyismemcpy_flushcache,pmem_flushis empty andpmem_commitis wmb.On ARM64,
pmem_memcpyis memcpy,pmem_flushisarch_wb_cache_pmemandpmem_commitis empty.Quoted 9 lines
I don't want to grow driver-local wrappers for pmem. You should use
memcpy_flushcachedirectly()and if an architecture does not definememcpy_flushcache()then don't allow building dm-writecache, i.e. this driver should 'depends onCONFIG_ARCH_HAS_UACCESS_FLUSHCACHE'. I don't see a need to add a standalone flush operation if all relevant archs providememcpy_flushcache(). As for commit, I'd say just usewmb()directly since all archs define it. Alternatively we could introducememcpy_flushcache_relaxed()to be the un-ordered version of the copy routine andmemcpy_flushcache()would imply awmb().Quoted 1 line
But
memcpy_flushcache()on ARM64 is slow.Yes, Dan can you please take some time to fully appreciate what this small wrapper API is providing (maybe you've done that, but your recent reply is mixed-message). Seems you're keeping the innovation it provides at arms-length. Basically the PMEM APIs you've helped construct are lacking, forcing DM developers to own fixing them is an inversion that only serves to stonewall.
Please, less time on stonewalling and more time lifting this wrapper API; otherwise the dm-writecache local wrapper API is a near-term means to an end.
I revised the dm-writecache patch header yesterday, please review:
https://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm.git/commit/?h=dm-4.18&id=2105231db61b08752bc4247d2fe7838657700b0d
(the last paragraph in particular, I intend to move forward with this wrapper unless someone on the PMEM side of the house steps up and lifts it up between now and when the 4.18 merge window opens)dm: add writecache target
The writecache target caches writes on persistent memory or SSD. It is intended for databases or other programs that need extremely low commit latency.The writecache target doesn't cache reads because reads are supposed to be cached in page cache in normal RAM.
The following describes the approach used to provide the most efficient flushing of persistent memory on
X86_64vs ARM64:* On
X86_64non-temporal stores (i.e.memcpy_flushcache) are faster than cached writes and cache flushing.* The ARM64 architecture doesn't have non-temporal stores. So,
memcpy_flushcacheon ARM does memcpy (that writes data to the cache) and then flushes the cache. But this eager cache flushig is slower than late cache flushing.The optimal code sequence on ARM to write to persistent memory is to call memcpy, then do something else, and then call
arch_wb_cache_pmemas late as possible. And this ARM-optimized code sequence is just horribly slow on X86.This issue can't be "fixed" in ARM-specific source code. The ARM processor have characteristics such that eager cache flushing is slower than late cache flushing - and that's it - you can't change processor behavior.
We introduce a wrapper API for flushing persistent memory with functions
pmem_memcpy,pmem_flushandpmem_commit. To commit data persistently, all three functions must be called.The macro
pmem_assignmay be used instead ofpmem_memcpy.pmem_assign(unlikepmem_memcpy) guarantees that 8-byte values are written atomically.On
X86_64,pmem_memcpyismemcpy_flushcache,pmem_flushis empty andpmem_commitis wmb.On ARM64,
pmem_memcpyis memcpy,pmem_flushisarch_wb_cache_pmemandpmem_commitis empty.
Quoted 8 lines
It is clear that this wrapper API for flushing persistent memory needs to be elevated out of this dm-writecache driver. But that can happen later without requiring DM developers to blaze new trails on pmem specific implementation details/quirks (pmem developers need to clean up their APIs given they are already spread across
CONFIG_ARCH_HAS_PMEM_APIandCONFIG_ARCH_HAS_UACCESS_FLUSHCACHEand they absolutely don't take into account the duality of the different programming models needed to achieve optimal cross-architecture use of persistent memory).
Right, so again, what is wrong with memcpy_flushcache_relaxed() + wmb() or otherwise making memcpy_flushcache() ordered. I do not see that as a trailblazing requirement, I see that as typical review and a reduction of the operation space that you are proposing.
A message that is not in the archive (sent off-list or not yet received): CAPcyv4j-v5HGBg9JMBXt7UUyw=K_bGC7t5tQGfXM9G4qjOpFjQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org
Re: [patch 4/4] dm-writecache: use new API for flushing
Quoted 16 lines · Dan Williams
Quoted 15 lines · Mike Snitzer
Quoted 12 lines · Mikulas Patocka
Quoted 9 lines · Dan Williams
I don't want to grow driver-local wrappers for pmem. You should use
memcpy_flushcachedirectly()and if an architecture does not definememcpy_flushcache()then don't allow building dm-writecache, i.e. this driver should 'depends onCONFIG_ARCH_HAS_UACCESS_FLUSHCACHE'. I don't see a need to add a standalone flush operation if all relevant archs providememcpy_flushcache(). As for commit, I'd say just usewmb()directly since all archs define it. Alternatively we could introducememcpy_flushcache_relaxed()to be the un-ordered version of the copy routine andmemcpy_flushcache()would imply awmb().
Quoted 6 lines
Quoted 1 line
Quoted 1 line
But
memcpy_flushcache()on ARM64 is slow.Right, so again, what is wrong with
memcpy_flushcache_relaxed()+wmb()or otherwise makingmemcpy_flushcache()ordered. I do not see that as a trailblazing requirement, I see that as typical review and a reduction of the operation space that you are proposing.
memcpy_flushcache on ARM64 is generally wrong thing to do, because it is slower than memcpy and explicit cache flush.
Suppose that you want to write data to a block device and make it persistent. So you send a WRITE bio and then a FLUSH bio.
Now - how to implement these two bios on persistent memory:
On X86, the WRITE bio does memcpy_flushcache() and the FLUSH bio does wmb() - this is the optimal implementation.
But on ARM64, memcpy_flushcache() is suboptimal. On ARM64, the optimal implementation is that the WRITE bio does just memcpy() and the FLUSH bio does arch_wb_cache_pmem() on the affected range.
Why is memcpy_flushcache() is suboptimal on ARM? The ARM architecture doesn't have non-temporal stores. So, memcpy_flushcache() is implemented as memcpy() followed by a cache flush.
Now - if you flush the cache immediatelly after memcpy, the cache is full of dirty lines and the cache-flushing code has to write these lines back and that is slow.
If you flush the cache some time after memcpy (i.e. when the FLUSH bio is received), the processor already flushed some part of the cache on its own, so the cache-flushing function has less work to do and it is faster.
So the conclusion is - don't use memcpy_flushcache on ARM. This problem cannot be fixed by a better implementation of memcpy_flushcache.
Mikulas
A message that is not in the archive (sent off-list or not yet received): alpine.LRH.2.02.1805260246250.15978-Hpncn10jQN4oNljnaZt3ZvA+iT7yCHsGwRM8/[email protected]
Re: [patch 4/4] dm-writecache: use new API for flushing
Quoted 50 lines · Mikulas Patocka
Quoted 16 lines · Dan Williams
Quoted 15 lines · Mike Snitzer
Quoted 12 lines · Mikulas Patocka
Quoted 9 lines · Dan Williams
I don't want to grow driver-local wrappers for pmem. You should use
memcpy_flushcachedirectly()and if an architecture does not definememcpy_flushcache()then don't allow building dm-writecache, i.e. this driver should 'depends onCONFIG_ARCH_HAS_UACCESS_FLUSHCACHE'. I don't see a need to add a standalone flush operation if all relevant archs providememcpy_flushcache(). As for commit, I'd say just usewmb()directly since all archs define it. Alternatively we could introducememcpy_flushcache_relaxed()to be the un-ordered version of the copy routine andmemcpy_flushcache()would imply awmb().Quoted 6 lines
Quoted 1 line
Quoted 1 line
But
memcpy_flushcache()on ARM64 is slow.Right, so again, what is wrong with
memcpy_flushcache_relaxed()+wmb()or otherwise makingmemcpy_flushcache()ordered. I do not see that as a trailblazing requirement, I see that as typical review and a reduction of the operation space that you are proposing.
memcpy_flushcacheon ARM64 is generally wrong thing to do, because it is slower than memcpy and explicit cache flush.Suppose that you want to write data to a block device and make it persistent. So you send a WRITE bio and then a FLUSH bio.
Now - how to implement these two bios on persistent memory:
On X86, the WRITE bio does
memcpy_flushcache()and the FLUSH bio doeswmb()- this is the optimal implementation.But on ARM64,
memcpy_flushcache()is suboptimal. On ARM64, the optimal implementation is that the WRITE bio does justmemcpy()and the FLUSH bio doesarch_wb_cache_pmem()on the affected range.Why is
memcpy_flushcache()is suboptimal on ARM? The ARM architecture doesn't have non-temporal stores. So,memcpy_flushcache()is implemented asmemcpy()followed by a cache flush.Now - if you flush the cache immediatelly after memcpy, the cache is full of dirty lines and the cache-flushing code has to write these lines back and that is slow.
Quoted 6 lines
If you flush the cache some time after memcpy (i.e. when the FLUSH bio is received), the processor already flushed some part of the cache on its own, so the cache-flushing function has less work to do and it is faster.
So the conclusion is - don't use
memcpy_flushcacheon ARM. This problem cannot be fixed by a better implementation ofmemcpy_flushcache.
It sounds like ARM might be better off with mapping its pmem as write-through rather than write-back, and skip the explicit cache management altogether. You speak of "optimal" and "sub-optimal", but what would be more clear is fio measurements of the relative IOPs and latency profiles of the different approaches. The reason I am continuing to push here is that reducing the operation space from 'copy-flush-commit' to just 'copy' or 'copy-commit' simplifies the maintenance long term.
A message that is not in the archive (sent off-list or not yet received): CAPcyv4jwLsCNvNhgvv2DDSZuQsQXYEpKUU_5w1pTnyKj-uDBbQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org
Re: [patch 4/4] dm-writecache: use new API for flushing
Quoted 55 lines · Dan Williams
Quoted 54 lines · Mikulas Patocka
Quoted 16 lines · Dan Williams
Quoted 15 lines · Mike Snitzer
Quoted 12 lines · Mikulas Patocka
Quoted 9 lines · Dan Williams
I don't want to grow driver-local wrappers for pmem. You should use
memcpy_flushcachedirectly()and if an architecture does not definememcpy_flushcache()then don't allow building dm-writecache, i.e. this driver should 'depends onCONFIG_ARCH_HAS_UACCESS_FLUSHCACHE'. I don't see a need to add a standalone flush operation if all relevant archs providememcpy_flushcache(). As for commit, I'd say just usewmb()directly since all archs define it. Alternatively we could introducememcpy_flushcache_relaxed()to be the un-ordered version of the copy routine andmemcpy_flushcache()would imply awmb().Quoted 6 lines
Quoted 1 line
Quoted 1 line
But
memcpy_flushcache()on ARM64 is slow.Right, so again, what is wrong with
memcpy_flushcache_relaxed()+wmb()or otherwise makingmemcpy_flushcache()ordered. I do not see that as a trailblazing requirement, I see that as typical review and a reduction of the operation space that you are proposing.
memcpy_flushcacheon ARM64 is generally wrong thing to do, because it is slower than memcpy and explicit cache flush.Suppose that you want to write data to a block device and make it persistent. So you send a WRITE bio and then a FLUSH bio.
Now - how to implement these two bios on persistent memory:
On X86, the WRITE bio does
memcpy_flushcache()and the FLUSH bio doeswmb()- this is the optimal implementation.But on ARM64,
memcpy_flushcache()is suboptimal. On ARM64, the optimal implementation is that the WRITE bio does justmemcpy()and the FLUSH bio doesarch_wb_cache_pmem()on the affected range.Why is
memcpy_flushcache()is suboptimal on ARM? The ARM architecture doesn't have non-temporal stores. So,memcpy_flushcache()is implemented asmemcpy()followed by a cache flush.Now - if you flush the cache immediatelly after memcpy, the cache is full of dirty lines and the cache-flushing code has to write these lines back and that is slow.
If you flush the cache some time after memcpy (i.e. when the FLUSH bio is received), the processor already flushed some part of the cache on its own, so the cache-flushing function has less work to do and it is faster.
Quoted 5 lines
Quoted 2 lines
So the conclusion is - don't use
memcpy_flushcacheon ARM. This problem cannot be fixed by a better implementation ofmemcpy_flushcache.It sounds like ARM might be better off with mapping its pmem as write-through rather than write-back, and skip the explicit cache
I doubt it would perform well - write combining combines the writes into a larger segments - and write-through doesn't.
Quoted 6 lines
management altogether. You speak of "optimal" and "sub-optimal", but what would be more clear is fio measurements of the relative IOPs and latency profiles of the different approaches. The reason I am continuing to push here is that reducing the operation space from 'copy-flush-commit' to just 'copy' or 'copy-commit' simplifies the maintenance long term.
I measured it (with nvme backing store) and late cache flushing has 12% better performance than eager flushing with memcpy_flushcache().
131836 4k iops - vs - 117016.
Mikulas
A message that is not in the archive (sent off-list or not yet received): alpine.LRH.2.02.1805280922190.13486-Hpncn10jQN4oNljnaZt3ZvA+iT7yCHsGwRM8/[email protected]
Re: [patch 4/4] dm-writecache: use new API for flushing
Quoted 59 lines · Mikulas Patocka
Quoted 55 lines · Dan Williams
Quoted 54 lines · Mikulas Patocka
Quoted 16 lines · Dan Williams
Quoted 15 lines · Mike Snitzer
Quoted 12 lines · Mikulas Patocka
Quoted 9 lines · Dan Williams
I don't want to grow driver-local wrappers for pmem. You should use
memcpy_flushcachedirectly()and if an architecture does not definememcpy_flushcache()then don't allow building dm-writecache, i.e. this driver should 'depends onCONFIG_ARCH_HAS_UACCESS_FLUSHCACHE'. I don't see a need to add a standalone flush operation if all relevant archs providememcpy_flushcache(). As for commit, I'd say just usewmb()directly since all archs define it. Alternatively we could introducememcpy_flushcache_relaxed()to be the un-ordered version of the copy routine andmemcpy_flushcache()would imply awmb().Quoted 6 lines
Quoted 1 line
Quoted 1 line
But
memcpy_flushcache()on ARM64 is slow.Right, so again, what is wrong with
memcpy_flushcache_relaxed()+wmb()or otherwise makingmemcpy_flushcache()ordered. I do not see that as a trailblazing requirement, I see that as typical review and a reduction of the operation space that you are proposing.
memcpy_flushcacheon ARM64 is generally wrong thing to do, because it is slower than memcpy and explicit cache flush.Suppose that you want to write data to a block device and make it persistent. So you send a WRITE bio and then a FLUSH bio.
Now - how to implement these two bios on persistent memory:
On X86, the WRITE bio does
memcpy_flushcache()and the FLUSH bio doeswmb()- this is the optimal implementation.But on ARM64,
memcpy_flushcache()is suboptimal. On ARM64, the optimal implementation is that the WRITE bio does justmemcpy()and the FLUSH bio doesarch_wb_cache_pmem()on the affected range.Why is
memcpy_flushcache()is suboptimal on ARM? The ARM architecture doesn't have non-temporal stores. So,memcpy_flushcache()is implemented asmemcpy()followed by a cache flush.Now - if you flush the cache immediatelly after memcpy, the cache is full of dirty lines and the cache-flushing code has to write these lines back and that is slow.
If you flush the cache some time after memcpy (i.e. when the FLUSH bio is received), the processor already flushed some part of the cache on its own, so the cache-flushing function has less work to do and it is faster.
Quoted 9 lines
Quoted 5 lines
Quoted 2 lines
So the conclusion is - don't use
memcpy_flushcacheon ARM. This problem cannot be fixed by a better implementation ofmemcpy_flushcache.It sounds like ARM might be better off with mapping its pmem as write-through rather than write-back, and skip the explicit cache
I doubt it would perform well - write combining combines the writes into a larger segments - and write-through doesn't.
Last I checked write-through caching does not disable write combining
Quoted 9 lines
Quoted 6 lines
management altogether. You speak of "optimal" and "sub-optimal", but what would be more clear is fio measurements of the relative IOPs and latency profiles of the different approaches. The reason I am continuing to push here is that reducing the operation space from 'copy-flush-commit' to just 'copy' or 'copy-commit' simplifies the maintenance long term.
I measured it (with nvme backing store) and late cache flushing has 12% better performance than eager flushing with
memcpy_flushcache().
I assume what you're seeing is ARM64 over-flushing the amount of dirty data so it becomes more efficient to do an amortized flush at the end? However, that effectively makes memcpy_flushcache() unusable in the way it can be used on x86. You claimed that ARM does not support non-temporal stores, but it does, see the STNP instruction. I do not want to see arch specific optimizations in drivers, so either write-through mappings is a potential answer to remove the need to explicitly manage flushing, or just implement STNP hacks in memcpy_flushcache() like you did with MOVNT on x86.
Quoted 1 line
131836 4k iops - vs - 117016.
To be clear this is memcpy_flushcache() vs memcpy + flush?
A message that is not in the archive (sent off-list or not yet received): CAPcyv4jXV4aZ6wqqjVPL8J4LxwTtXnzQCLZ0Wk5oB4_0uxpg7g-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org
Re: [patch 4/4] dm-writecache: use new API for flushing
Quoted 92 lines · Dan Williams
Quoted 59 lines · Mikulas Patocka
Quoted 55 lines · Dan Williams
Quoted 54 lines · Mikulas Patocka
Quoted 16 lines · Dan Williams
Quoted 15 lines · Mike Snitzer
Quoted 12 lines · Mikulas Patocka
Quoted 9 lines · Dan Williams
I don't want to grow driver-local wrappers for pmem. You should use
memcpy_flushcachedirectly()and if an architecture does not definememcpy_flushcache()then don't allow building dm-writecache, i.e. this driver should 'depends onCONFIG_ARCH_HAS_UACCESS_FLUSHCACHE'. I don't see a need to add a standalone flush operation if all relevant archs providememcpy_flushcache(). As for commit, I'd say just usewmb()directly since all archs define it. Alternatively we could introducememcpy_flushcache_relaxed()to be the un-ordered version of the copy routine andmemcpy_flushcache()would imply awmb().Quoted 6 lines
Quoted 1 line
Quoted 1 line
But
memcpy_flushcache()on ARM64 is slow.Right, so again, what is wrong with
memcpy_flushcache_relaxed()+wmb()or otherwise makingmemcpy_flushcache()ordered. I do not see that as a trailblazing requirement, I see that as typical review and a reduction of the operation space that you are proposing.
memcpy_flushcacheon ARM64 is generally wrong thing to do, because it is slower than memcpy and explicit cache flush.Suppose that you want to write data to a block device and make it persistent. So you send a WRITE bio and then a FLUSH bio.
Now - how to implement these two bios on persistent memory:
On X86, the WRITE bio does
memcpy_flushcache()and the FLUSH bio doeswmb()- this is the optimal implementation.But on ARM64,
memcpy_flushcache()is suboptimal. On ARM64, the optimal implementation is that the WRITE bio does justmemcpy()and the FLUSH bio doesarch_wb_cache_pmem()on the affected range.Why is
memcpy_flushcache()is suboptimal on ARM? The ARM architecture doesn't have non-temporal stores. So,memcpy_flushcache()is implemented asmemcpy()followed by a cache flush.Now - if you flush the cache immediatelly after memcpy, the cache is full of dirty lines and the cache-flushing code has to write these lines back and that is slow.
If you flush the cache some time after memcpy (i.e. when the FLUSH bio is received), the processor already flushed some part of the cache on its own, so the cache-flushing function has less work to do and it is faster.
Quoted 9 lines
Quoted 5 lines
Quoted 2 lines
So the conclusion is - don't use
memcpy_flushcacheon ARM. This problem cannot be fixed by a better implementation ofmemcpy_flushcache.It sounds like ARM might be better off with mapping its pmem as write-through rather than write-back, and skip the explicit cache
I doubt it would perform well - write combining combines the writes into a larger segments - and write-through doesn't.
Last I checked write-through caching does not disable write combining
Quoted 9 lines
Quoted 6 lines
management altogether. You speak of "optimal" and "sub-optimal", but what would be more clear is fio measurements of the relative IOPs and latency profiles of the different approaches. The reason I am continuing to push here is that reducing the operation space from 'copy-flush-commit' to just 'copy' or 'copy-commit' simplifies the maintenance long term.
I measured it (with nvme backing store) and late cache flushing has 12% better performance than eager flushing with
memcpy_flushcache().I assume what you're seeing is ARM64 over-flushing the amount of dirty data so it becomes more efficient to do an amortized flush at the end? However, that effectively makes
memcpy_flushcache()unusable in the way it can be used on x86. You claimed that ARM does not support non-temporal stores, but it does, see the STNP instruction. I do not want to see arch specific optimizations in drivers, so either write-through mappings is a potential answer to remove the need to explicitly manage flushing, or just implement STNP hacks inmemcpy_flushcache()like you did with MOVNT on x86.
Quoted 3 lines
Quoted 1 line
131836 4k iops - vs - 117016.
To be clear this is
memcpy_flushcache()vs memcpy + flush?
I found out what caused the difference. I used dax_flush on the version of dm-writecache that I had on the ARM machine (with the kernel 4.14, because it is the last version where dax on ramdisk works) - and I thought that dax_flush flushes the cache, but it doesn't.
When I replaced dax_flush with arch_wb_cache_pmem, the performance difference between early flushing and late flushing disappeared.
So I think we can remove this per-architecture switch from dm-writecache.
Mikulas
A message that is not in the archive (sent off-list or not yet received): alpine.LRH.2.02.1805300903220.1090-Hpncn10jQN4oNljnaZt3ZvA+iT7yCHsGwRM8/[email protected]
Re: [patch 4/4] dm-writecache: use new API for flushing
Quoted 28 lines · Mikulas Patocka
Quoted 15 lines · Dan Williams
Quoted 3 lines · Mikulas Patocka
I measured it (with nvme backing store) and late cache flushing has 12% better performance than eager flushing with
memcpy_flushcache().I assume what you're seeing is ARM64 over-flushing the amount of dirty data so it becomes more efficient to do an amortized flush at the end? However, that effectively makes
memcpy_flushcache()unusable in the way it can be used on x86. You claimed that ARM does not support non-temporal stores, but it does, see the STNP instruction. I do not want to see arch specific optimizations in drivers, so either write-through mappings is a potential answer to remove the need to explicitly manage flushing, or just implement STNP hacks inmemcpy_flushcache()like you did with MOVNT on x86.Quoted 3 lines
Quoted 1 line
131836 4k iops - vs - 117016.
To be clear this is
memcpy_flushcache()vs memcpy + flush?I found out what caused the difference. I used
dax_flushon the version of dm-writecache that I had on the ARM machine (with the kernel 4.14, because it is the last version where dax on ramdisk works) - and I thought thatdax_flushflushes the cache, but it doesn't.
Quoted 4 lines
When I replaced
dax_flushwitharch_wb_cache_pmem, the performance difference between early flushing and late flushing disappeared.So I think we can remove this per-architecture switch from dm-writecache.
That is really great news, can you submit an incremental patch that layers ontop of the linux-dm.git 'dm-4.18' branch?
Thanks,
Mike
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [patch 4/4] dm-writecache: use new API for flushing
Quoted 5 lines · Mike Snitzer
That is really great news, can you submit an incremental patch that layers ontop of the linux-dm.git 'dm-4.18' branch?
Thanks,
Mike
I've sent the current version that I have. I fixed the bugs that were reported here (missing DAX, dm_bufio_client_create, __branch_check__ long->int truncation).
Mikulas
A message that is not in the archive (sent off-list or not yet received): alpine.LRH.2.02.1805300919070.11327-Hpncn10jQN4oNljnaZt3ZvA+iT7yCHsGwRM8/[email protected]
Re: [patch 4/4] dm-writecache: use new API for flushing
Quoted 7 lines · Mikulas Patocka
Quoted 3 lines · Mike Snitzer
That is really great news, can you submit an incremental patch that layers ontop of the linux-dm.git 'dm-4.18' branch?
Quoted 6 lines
Quoted 2 lines
Thanks,
MikeI've sent the current version that I have. I fixed the bugs that were reported here (missing DAX,
dm_bufio_client_create,__branch_check__long->inttruncation).
OK, but a monolithic dm-writecache.c is no longer useful to me. I can drop Arnd's gcc warning fix (with the idea that Ingo or Steve will take your __branch_check__ patch). Not sure what the dm_bufio_client_create fix is... must've missed a report about that.
ANyway, point is we're on too a different phase of dm-writecache.c's development. I've picked it up and am trying to get it ready for the 4.18 merge window (likely opening Sunday). Therefore it needs to be in a git tree, and incremental changes overlayed. I cannot be rebasing at this late stage in the 4.18 development window.
Thanks,
Mike
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [patch 4/4] dm-writecache: use new API for flushing
Quoted 22 lines · Mike Snitzer
Quoted 7 lines · Mikulas Patocka
Quoted 3 lines · Mike Snitzer
That is really great news, can you submit an incremental patch that layers ontop of the linux-dm.git 'dm-4.18' branch?
Quoted 6 lines
Quoted 2 lines
Thanks,
MikeI've sent the current version that I have. I fixed the bugs that were reported here (missing DAX,
dm_bufio_client_create,__branch_check__long->inttruncation).OK, but a monolithic
dm-writecache.cis no longer useful to me. I can drop Arnd's gcc warning fix (with the idea that Ingo or Steve will take your__branch_check__patch). Not sure what thedm_bufio_client_createfix is... must've missed a report about that.
Quoted 8 lines
ANyway, point is we're on too a different phase of dm-writecache.c's development. I've picked it up and am trying to get it ready for the 4.18 merge window (likely opening Sunday). Therefore it needs to be in a git tree, and incremental changes overlayed. I cannot be rebasing at this late stage in the 4.18 development window.
Thanks,
Mike
I downloaded dm-writecache from your git repository some times ago - but you changed a lot of useless things (i.e. reordering the fields in the structure) since that time - so, you'll have to merge the changes.
You dropped the latency measuring code - why? We still would like to benchmark the driver.
Mikulas
A message that is not in the archive (sent off-list or not yet received): alpine.LRH.2.02.1805300929500.11327-Hpncn10jQN4oNljnaZt3ZvA+iT7yCHsGwRM8/[email protected]
Re: [patch 4/4] dm-writecache: use new API for flushing
Quoted 32 lines · Mikulas Patocka
Quoted 28 lines · Mike Snitzer
Quoted 7 lines · Mikulas Patocka
Quoted 3 lines · Mike Snitzer
That is really great news, can you submit an incremental patch that layers ontop of the linux-dm.git 'dm-4.18' branch?
Quoted 6 lines
Quoted 2 lines
Thanks,
MikeI've sent the current version that I have. I fixed the bugs that were reported here (missing DAX,
dm_bufio_client_create,__branch_check__long->inttruncation).OK, but a monolithic
dm-writecache.cis no longer useful to me. I can drop Arnd's gcc warning fix (with the idea that Ingo or Steve will take your__branch_check__patch). Not sure what thedm_bufio_client_createfix is... must've missed a report about that.ANyway, point is we're on too a different phase of dm-writecache.c's development. I've picked it up and am trying to get it ready for the 4.18 merge window (likely opening Sunday). Therefore it needs to be in a git tree, and incremental changes overlayed. I cannot be rebasing at this late stage in the 4.18 development window.
Quoted 6 lines
Quoted 2 lines
Thanks,
MikeI downloaded dm-writecache from your git repository some times ago - but you changed a lot of useless things (i.e. reordering the fields in the structure) since that time - so, you'll have to merge the changes.
Fine I'll deal with it. reordering the fields eliminated holes in the structure and reduced struct members spanning cache lines.
Quoted 2 lines
You dropped the latency measuring code - why? We still would like to benchmark the driver.
I saved that patch. It is a development-only patch. I tried to have you work on formalizing the code further by making the functions actually get called, and by wrapping the code with CONFIG_DM_WRITECACHE_MEASURE_LATENCY. In the end I dropped it for now and we'll just have to apply the patch when we need to benchmark.
Here is the current patch if you'd like to improve it (e.g. actually call measure_latency_start and measure_latency_end in places) -- I seemed to have lost my incremental change to switch over to CONFIG_DM_WRITECACHE_MEASURE_LATENCY (likely due to rebase); can worry about that later.
This is based on the dm-4.18 branch.
From 20a7c123271741cb7260154b68730942417e803a Mon Sep 17 00:00:00 2001
From: Mikulas Patocka <[email protected]>
Date: Tue, 22 May 2018 15:54:53 -0400
Subject: [PATCH] dm writecache: add the ability to measure some latencies
Developer-only code that won't go upstream (as-is).
drivers/md/dm-writecache.c | 94 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 87 insertions(+), 7 deletions(-)
drivers/md/dm-writecache.c +87 -7
@@ -28,6 +28,8 @@#define AUTOCOMMIT_BLOCKS_PMEM 64#define AUTOCOMMIT_MSEC 1000 +//#define WC_MEASURE_LATENCY +#define BITMAP_GRANULARITY 65536#if BITMAP_GRANULARITY <PAGE_SIZE #undef BITMAP_GRANULARITY
@@ -217,6 +219,15 @@ struct dm_writecache {struct dm_kcopyd_client *dm_kcopyd;unsigned long *dirty_bitmap;unsigned dirty_bitmap_size; + +#ifdef WC_MEASURE_LATENCY +ktime_t lock_acquired_time; +ktime_t max_lock_held; +ktime_t max_lock_wait; +ktime_t max_freelist_wait; +ktime_t measure_latency_time; +ktime_t max_measure_latency; +#endif };#define WB_LIST_INLINE 16
@@ -243,15 +254,60 @@ struct copy_struct {DECLARE_DM_KCOPYD_THROTTLE_WITH_MODULE_PARM (dm_writecache_throttle,"A percentage of time allocated for data copying" ); -static void wc_lock (struct dm_writecache *wc) +static inline void measure_latency_start (struct dm_writecache *wc) +{ +#ifdef WC_MEASURE_LATENCY + wc->measure_latency_time =ktime_get (); +#endif +} + +static inline void measure_latency_end (struct dm_writecache *wc,unsigned long n) { +#ifdef WC_MEASURE_LATENCY +ktime_t now =ktime_get (); +if (now - wc->measure_latency_time > wc->max_measure_latency) { + wc->max_measure_latency = now - wc->measure_latency_time; +printk (KERN_DEBUG "dm-writecache: measured latency %lld.%03lldus, %lu steps\n" , + wc->max_measure_latency /1000 , wc->max_measure_latency %1000 , n); + } +#endif +} + +static void __wc_lock (struct dm_writecache *wc,int line) +{ +#ifdef WC_MEASURE_LATENCY +ktime_t before, after; + before =ktime_get (); +#endif mutex_lock (&wc->lock); +#ifdef WC_MEASURE_LATENCY + after =ktime_get (); +if (unlikely (after - before > wc->max_lock_wait)) { + wc->max_lock_wait = after - before; +printk (KERN_DEBUG "dm-writecache: waiting for lock for %lld.%03lldus at %d\n" , + wc->max_lock_wait /1000 , wc->max_lock_wait %1000 , line); + after =ktime_get (); + } + wc->lock_acquired_time = after; +#endif } +#define wc_lock (wc) __wc_lock(wc, __LINE__) -static void wc_unlock (struct dm_writecache *wc) +static void __wc_unlock (struct dm_writecache *wc,int line) { +#ifdef WC_MEASURE_LATENCY +ktime_t now =ktime_get (); +if (now - wc->lock_acquired_time > wc->max_lock_held) { + wc->max_lock_held = now - wc->lock_acquired_time; +printk (KERN_DEBUG "dm-writecache: lock held for %lld.%03lldus at %d\n" , + wc->max_lock_held /1000 , wc->max_lock_held %1000 , line); + } +#endif mutex_unlock (&wc->lock); } +#define wc_unlock (wc) __wc_unlock(wc, __LINE__) + +#define wc_unlock_long (wc) mutex_unlock(&wc->lock)#if IS_ENABLED (CONFIG_DAX_DRIVER )static int persistent_memory_claim (struct dm_writecache *wc)
@@ -293,6 +349,10 @@ static int persistent_memory_claim(struct dm_writecache *wc) r = -EOPNOTSUPP ; goto err2; } +#ifdef WC_MEASURE_LATENCY +printk (KERN_DEBUG "dm-writecache: device %s, pfn %016llx\n" , + wc->ssd_dev->name, pfn.val); +#endif if (da != p) {long i; wc->memory_map =NULL ;
@@ -701,16 +761,35 @@ static void writecache_free_entry(struct dm_writecache *wc, struct wc_entry *e)swake_up (&wc->freelist_wait); } -static void writecache_wait_on_freelist (struct dm_writecache *wc) +static void __writecache_wait_on_freelist (struct dm_writecache *wc,bool measure,int line) {DECLARE_SWAITQUEUE (wait); +#ifdef WC_MEASURE_LATENCY +ktime_t before, after; +#endif prepare_to_swait (&wc->freelist_wait, &wait,TASK_UNINTERRUPTIBLE );wc_unlock (wc); +#ifdef WC_MEASURE_LATENCY +if (measure) + before =ktime_get (); +#endif io_schedule ();finish_swait (&wc->freelist_wait, &wait); +#ifdef WC_MEASURE_LATENCY +if (measure) { + after =ktime_get (); +if (unlikely (after - before > wc->max_freelist_wait)) { + wc->max_freelist_wait = after - before; +printk (KERN_DEBUG "dm-writecache: waiting on freelist for %lld.%03lldus at %d\n" , + wc->max_freelist_wait /1000 , wc->max_freelist_wait %1000 , line); + } + } +#endif wc_lock (wc); } +#define writecache_wait_on_freelist (wc) __writecache_wait_on_freelist(wc, true, __LINE__) +#define writecache_wait_on_freelist_long (wc) __writecache_wait_on_freelist(wc, false, __LINE__)static void writecache_poison_lists (struct dm_writecache *wc) {
@@ -890,7 +969,7 @@ static void writecache_suspend(struct dm_target *ti)writecache_poison_lists (wc); -wc_unlock (wc); +wc_unlock_long (wc); }static int writecache_alloc_entries (struct dm_writecache *wc)
@@ -1001,7 +1080,7 @@ static void writecache_resume(struct dm_target *ti)writecache_commit_flushed (wc); } -wc_unlock (wc); +wc_unlock_long (wc); }static int process_flush_mesg (unsigned argc,char **argv,struct dm_writecache *wc)
@@ -1472,8 +1551,9 @@ static void __writeback_throttle(struct dm_writecache *wc, struct writeback_listif (unlikely (wc->max_writeback_jobs)) {if (READ_ONCE (wc->writeback_size) - wbl->size >= wc->max_writeback_jobs) {wc_lock (wc); -while (wc->writeback_size - wbl->size >= wc->max_writeback_jobs) -writecache_wait_on_freelist (wc); +while (wc->writeback_size - wbl->size >= wc->max_writeback_jobs) { +writecache_wait_on_freelist_long (wc); + }wc_unlock (wc); } }
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [patch 4/4] dm-writecache: use new API for flushing
Quoted 38 lines · Mike Snitzer
Quoted 35 lines · Mikulas Patocka
Quoted 30 lines · Mike Snitzer
Quoted 7 lines · Mikulas Patocka
Quoted 3 lines · Mike Snitzer
That is really great news, can you submit an incremental patch that layers ontop of the linux-dm.git 'dm-4.18' branch?
Quoted 6 lines
Quoted 2 lines
Thanks,
MikeI've sent the current version that I have. I fixed the bugs that were reported here (missing DAX,
dm_bufio_client_create,__branch_check__long->inttruncation).OK, but a monolithic
dm-writecache.cis no longer useful to me. I can drop Arnd's gcc warning fix (with the idea that Ingo or Steve will take your__branch_check__patch). Not sure what thedm_bufio_client_createfix is... must've missed a report about that.ANyway, point is we're on too a different phase of dm-writecache.c's development. I've picked it up and am trying to get it ready for the 4.18 merge window (likely opening Sunday). Therefore it needs to be in a git tree, and incremental changes overlayed. I cannot be rebasing at this late stage in the 4.18 development window.
Thanks,
Mike
Quoted 6 lines
Quoted 3 lines
I downloaded dm-writecache from your git repository some times ago - but you changed a lot of useless things (i.e. reordering the fields in the structure) since that time - so, you'll have to merge the changes.
Fine I'll deal with it. reordering the fields eliminated holes in the structure and reduced struct members spanning cache lines.
And what about this?
#define WC_MODE_PMEM(wc) ((wc)->pmem_mode)
The code that I had just allowed the compiler to optimize out persistent-memory code if we have DM_WRITECACHE_ONLY_SSD defined - and you deleted it.
Most architectures don't have persistent memory and the dm-writecache driver could work in ssd-only mode on them. On these architectures, I define
#define WC_MODE_PMEM(wc) false
- and the compiler will just automatically remove the tests for that condition and the unused branch. It does also eliminate unused static functions.
Mikulas
A message that is not in the archive (sent off-list or not yet received): alpine.LRH.2.02.1805300959460.16696-Hpncn10jQN4oNljnaZt3ZvA+iT7yCHsGwRM8/[email protected]
Re: [patch 4/4] dm-writecache: use new API for flushing
Quoted 56 lines · Mikulas Patocka
Quoted 38 lines · Mike Snitzer
Quoted 35 lines · Mikulas Patocka
Quoted 30 lines · Mike Snitzer
Quoted 7 lines · Mikulas Patocka
Quoted 3 lines · Mike Snitzer
That is really great news, can you submit an incremental patch that layers ontop of the linux-dm.git 'dm-4.18' branch?
Quoted 6 lines
Quoted 2 lines
Thanks,
MikeI've sent the current version that I have. I fixed the bugs that were reported here (missing DAX,
dm_bufio_client_create,__branch_check__long->inttruncation).OK, but a monolithic
dm-writecache.cis no longer useful to me. I can drop Arnd's gcc warning fix (with the idea that Ingo or Steve will take your__branch_check__patch). Not sure what thedm_bufio_client_createfix is... must've missed a report about that.ANyway, point is we're on too a different phase of dm-writecache.c's development. I've picked it up and am trying to get it ready for the 4.18 merge window (likely opening Sunday). Therefore it needs to be in a git tree, and incremental changes overlayed. I cannot be rebasing at this late stage in the 4.18 development window.
Thanks,
MikeQuoted 6 lines
Quoted 3 lines
I downloaded dm-writecache from your git repository some times ago - but you changed a lot of useless things (i.e. reordering the fields in the structure) since that time - so, you'll have to merge the changes.
Fine I'll deal with it. reordering the fields eliminated holes in the structure and reduced struct members spanning cache lines.
And what about this?
#defineWC_MODE_PMEM(wc)((wc)->pmem_mode)The code that I had just allowed the compiler to optimize out persistent-memory code if we have
DM_WRITECACHE_ONLY_SSDdefined - and you deleted it.
Quoted 7 lines
Most architectures don't have persistent memory and the dm-writecache driver could work in ssd-only mode on them. On these architectures, I define
#defineWC_MODE_PMEM(wc)false
- and the compiler will just automatically remove the tests for that condition and the unused branch. It does also eliminate unused static functions.
This level of microoptimization can be backfilled. But as it was, there were too many #defines. And I'm really not concerned with eliminating unused static functions for this case.
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [patch 4/4] dm-writecache: use new API for flushing
Quoted 67 lines · Mike Snitzer
Quoted 56 lines · Mikulas Patocka
Quoted 38 lines · Mike Snitzer
Quoted 35 lines · Mikulas Patocka
Quoted 30 lines · Mike Snitzer
Quoted 7 lines · Mikulas Patocka
Quoted 3 lines · Mike Snitzer
That is really great news, can you submit an incremental patch that layers ontop of the linux-dm.git 'dm-4.18' branch?
Quoted 6 lines
Quoted 2 lines
Thanks,
MikeI've sent the current version that I have. I fixed the bugs that were reported here (missing DAX,
dm_bufio_client_create,__branch_check__long->inttruncation).OK, but a monolithic
dm-writecache.cis no longer useful to me. I can drop Arnd's gcc warning fix (with the idea that Ingo or Steve will take your__branch_check__patch). Not sure what thedm_bufio_client_createfix is... must've missed a report about that.ANyway, point is we're on too a different phase of dm-writecache.c's development. I've picked it up and am trying to get it ready for the 4.18 merge window (likely opening Sunday). Therefore it needs to be in a git tree, and incremental changes overlayed. I cannot be rebasing at this late stage in the 4.18 development window.
Thanks,
MikeQuoted 6 lines
Quoted 3 lines
I downloaded dm-writecache from your git repository some times ago - but you changed a lot of useless things (i.e. reordering the fields in the structure) since that time - so, you'll have to merge the changes.
Fine I'll deal with it. reordering the fields eliminated holes in the structure and reduced struct members spanning cache lines.
And what about this?
#defineWC_MODE_PMEM(wc)((wc)->pmem_mode)The code that I had just allowed the compiler to optimize out persistent-memory code if we have
DM_WRITECACHE_ONLY_SSDdefined - and you deleted it.Quoted 7 lines
Most architectures don't have persistent memory and the dm-writecache driver could work in ssd-only mode on them. On these architectures, I define
#defineWC_MODE_PMEM(wc)false
- and the compiler will just automatically remove the tests for that condition and the unused branch. It does also eliminate unused static functions.
Quoted 3 lines
This level of microoptimization can be backfilled. But as it was, there were too many #defines. And I'm really not concerned with eliminating unused static functions for this case.
I don't see why "too many defines" would be a problem.
If I compile it with and without pmem support, the difference is 15kB-vs-12kB. If we look at just one function (writecache_map), the difference is 1595 bytes - vs - 1280 bytes. So, it produces real savings in code size.
The problem with performance is not caused a condition that always jumps the same way (that is predicted by the CPU and it causes no delays in the pipeline) - the problem is that a bigger function consumes more i-cache. There is no reason to include code that can't be executed.
Note that we should also redefine pmem_assign on architectures that don't support persistent memory:
#ifndef DM_WRITECACHE_ONLY_SSD
#define pmem_assign(dest, src) \
do { \
typeof(dest) uniq = (src); \
memcpy_flushcache(&(dest), &uniq, sizeof(dest)); \} while (0)
#else
#define pmem_assign(dest, src) ((dest) = (src))
#endif
I.e. we should not call memcpy_flushcache if we can't have persistent memory. Cache flushing is slow and we should not do it if we don't have to.
Mikulas
A message that is not in the archive (sent off-list or not yet received): alpine.LRH.2.02.1805301023380.21890-Hpncn10jQN4oNljnaZt3ZvA+iT7yCHsGwRM8/[email protected]
Re: [patch 4/4] dm-writecache: use new API for flushing
Quoted 33 lines · Mikulas Patocka
Quoted 18 lines · Mike Snitzer
Quoted 10 lines
Quoted 2 lines
Fine I'll deal with it. reordering the fields eliminated holes in the structure and reduced struct members spanning cache lines.
And what about this?
#defineWC_MODE_PMEM(wc)((wc)->pmem_mode)The code that I had just allowed the compiler to optimize out persistent-memory code if we have
DM_WRITECACHE_ONLY_SSDdefined - and you deleted it.Quoted 7 lines
Most architectures don't have persistent memory and the dm-writecache driver could work in ssd-only mode on them. On these architectures, I define
#defineWC_MODE_PMEM(wc)false
- and the compiler will just automatically remove the tests for that condition and the unused branch. It does also eliminate unused static functions.Quoted 3 lines
This level of microoptimization can be backfilled. But as it was, there were too many #defines. And I'm really not concerned with eliminating unused static functions for this case.
I don't see why "too many defines" would be a problem.
If I compile it with and without pmem support, the difference is 15kB-vs-12kB. If we look at just one function (
writecache_map), the difference is 1595 bytes - vs - 1280 bytes. So, it produces real savings in code size.
Quoted 4 lines
The problem with performance is not caused a condition that always jumps the same way (that is predicted by the CPU and it causes no delays in the pipeline) - the problem is that a bigger function consumes more i-cache. There is no reason to include code that can't be executed.
Please double check you see the reduced code size you're expecting using the latest dm-writecache.c in linux-dm.git's dm-4.18 branch.
Thanks,
Mike
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [patch 4/4] dm-writecache: use new API for flushing
Quoted 41 lines · Mike Snitzer
Quoted 33 lines · Mikulas Patocka
Quoted 18 lines · Mike Snitzer
Quoted 10 lines
Quoted 2 lines
Fine I'll deal with it. reordering the fields eliminated holes in the structure and reduced struct members spanning cache lines.
And what about this?
#defineWC_MODE_PMEM(wc)((wc)->pmem_mode)The code that I had just allowed the compiler to optimize out persistent-memory code if we have
DM_WRITECACHE_ONLY_SSDdefined - and you deleted it.Quoted 7 lines
Most architectures don't have persistent memory and the dm-writecache driver could work in ssd-only mode on them. On these architectures, I define
#defineWC_MODE_PMEM(wc)false
- and the compiler will just automatically remove the tests for that condition and the unused branch. It does also eliminate unused static functions.Quoted 3 lines
This level of microoptimization can be backfilled. But as it was, there were too many #defines. And I'm really not concerned with eliminating unused static functions for this case.
I don't see why "too many defines" would be a problem.
If I compile it with and without pmem support, the difference is 15kB-vs-12kB. If we look at just one function (
writecache_map), the difference is 1595 bytes - vs - 1280 bytes. So, it produces real savings in code size.Quoted 4 lines
The problem with performance is not caused a condition that always jumps the same way (that is predicted by the CPU and it causes no delays in the pipeline) - the problem is that a bigger function consumes more i-cache. There is no reason to include code that can't be executed.
Quoted 5 lines
Please double check you see the reduced code size you're expecting using the latest
dm-writecache.cin linux-dm.git's dm-4.18 branch.Thanks,
Mike
I checked that - it's OK.
Mikulas
Re: [patch 4/4] dm-writecache: use new API for flushing
In reply to a message not in the archiveQuoted 7 lines · Mikulas Patocka
And what about this?
#defineWC_MODE_PMEM(wc)((wc)->pmem_mode)The code that I had just allowed the compiler to optimize out persistent-memory code if we have
DM_WRITECACHE_ONLY_SSDdefined - and you deleted it.
Quoted 7 lines
Most architectures don't have persistent memory and the dm-writecache driver could work in ssd-only mode on them. On these architectures, I define
#defineWC_MODE_PMEM(wc)false
- and the compiler will just automatically remove the tests for that condition and the unused branch. It does also eliminate unused static functions.
Here is the patch that I just folded into the rebased version of dm-writecache now in the dm-4.18 branch.
(I rebased ontop of Jens' latest block tree for 4.18 that now includes the mempool_init changes, etc.)
--- drivers/md/dm-writecache.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-)
drivers/md/dm-writecache.c +15 -2
@@ -34,13 +34,21 @@#define BITMAP_GRANULARITY PAGE_SIZE#endif +#if defined(CONFIG_ARCH_HAS_PMEM_API ) &&IS_ENABLED (CONFIG_DAX_DRIVER ) +#define DM_WRITECACHE_HAS_PMEM +#endif + +#ifdef DM_WRITECACHE_HAS_PMEM #define pmem_assign (dest, src) \ do { \ typeof(dest) uniq = (src); \ memcpy_flushcache(&(dest), &uniq, sizeof(dest)); \ } while (0) +#else +#define pmem_assign (dest, src) ((dest)) = (src)) +#endif -#if defined(__HAVE_ARCH_MEMCPY_MCSAFE) && defined(CONFIG_ARCH_HAS_PMEM_API ) +#if defined(__HAVE_ARCH_MEMCPY_MCSAFE) && defined(DM_WRITECACHE_HAS_PMEM )#define DM_WRITECACHE_HANDLE_HARDWARE_ERRORS #endif
@@ -87,8 +95,13 @@ struct wc_entry {#endif }; +#ifdef DM_WRITECACHE_HAS_PMEM #define WC_MODE_PMEM (wc) ((wc)->pmem_mode)#define WC_MODE_FUA (wc) ((wc)->writeback_fua) +#else +#define WC_MODE_PMEM (wc) false +#define WC_MODE_FUA (wc) false +#endif #define WC_MODE_SORT_FREELIST (wc) (!WC_MODE_PMEM(wc))struct dm_writecache {
@@ -1857,7 +1870,7 @@ static int writecache_ctr(struct dm_target *ti, unsigned argc, char **argv)if (!strcasecmp (string,"s" )) { wc->pmem_mode = false; }else if (!strcasecmp (string,"p" )) { -#if defined(CONFIG_ARCH_HAS_PMEM_API ) &&IS_ENABLED (CONFIG_DAX_DRIVER ) +#ifdef DM_WRITECACHE_HAS_PMEM wc->pmem_mode = true; wc->writeback_fua = true;#else
Signature · 1 line
2.15.0
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [patch 4/4] dm-writecache: use new API for flushing
Quoted 80 lines · Mike Snitzer
Quoted 7 lines · Mikulas Patocka
And what about this?
#defineWC_MODE_PMEM(wc)((wc)->pmem_mode)The code that I had just allowed the compiler to optimize out persistent-memory code if we have
DM_WRITECACHE_ONLY_SSDdefined - and you deleted it.Quoted 7 lines
Most architectures don't have persistent memory and the dm-writecache driver could work in ssd-only mode on them. On these architectures, I define
#defineWC_MODE_PMEM(wc)false
- and the compiler will just automatically remove the tests for that condition and the unused branch. It does also eliminate unused static functions.Here is the patch that I just folded into the rebased version of dm-writecache now in the dm-4.18 branch.
(I rebased ontop of Jens' latest block tree for 4.18 that now includes the
mempool_initchanges, etc.)--- drivers/md/dm-writecache.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-)drivers/md/dm-writecache.c +15
-2@@ -34,13 +34,21 @@#define BITMAP_GRANULARITY PAGE_SIZE#endif +#if defined(CONFIG_ARCH_HAS_PMEM_API ) &&IS_ENABLED (CONFIG_DAX_DRIVER ) +#define DM_WRITECACHE_HAS_PMEM +#endif + +#ifdef DM_WRITECACHE_HAS_PMEM #define pmem_assign (dest, src) \ do { \ typeof(dest) uniq = (src); \ memcpy_flushcache(&(dest), &uniq, sizeof(dest)); \ } while (0) +#else +#define pmem_assign (dest, src) ((dest)) = (src)) +#endif -#if defined(__HAVE_ARCH_MEMCPY_MCSAFE) && defined(CONFIG_ARCH_HAS_PMEM_API ) +#if defined(__HAVE_ARCH_MEMCPY_MCSAFE) && defined(DM_WRITECACHE_HAS_PMEM )#define DM_WRITECACHE_HANDLE_HARDWARE_ERRORS #endif @@ -87,8 +95,13 @@ struct wc_entry {#endif }; +#ifdef DM_WRITECACHE_HAS_PMEM #define WC_MODE_PMEM (wc) ((wc)->pmem_mode)#define WC_MODE_FUA (wc) ((wc)->writeback_fua) +#else +#define WC_MODE_PMEM (wc) false +#define WC_MODE_FUA (wc) false +#endif #define WC_MODE_SORT_FREELIST (wc) (!WC_MODE_PMEM(wc))struct dm_writecache {@@ -1857,7 +1870,7 @@ static int writecache_ctr(struct dm_target *ti, unsigned argc, char **argv)if (!strcasecmp (string,"s" )) { wc->pmem_mode = false; }else if (!strcasecmp (string,"p" )) { -#if defined(CONFIG_ARCH_HAS_PMEM_API ) &&IS_ENABLED (CONFIG_DAX_DRIVER ) +#ifdef DM_WRITECACHE_HAS_PMEM wc->pmem_mode = true; wc->writeback_fua = true;#else Signature · 1 line
2.15.0
OK.
I think that persistent_memory_claim should also be conditioned based on DM_WRITECACHE_HAS_PMEM - i.e. if we have DM_WRITECACHE_HAS_PMEM, we don't need to use other ifdefs.
Is there some difference between "#if IS_ENABLED(CONFIG_OPTION)" and "#if defined(CONFIG_OPTION)"?
Mikulas
A message that is not in the archive (sent off-list or not yet received): alpine.LRH.2.02.1805310412240.30096-Hpncn10jQN4oNljnaZt3ZvA+iT7yCHsGwRM8/[email protected]
Re: [patch 4/4] dm-writecache: use new API for flushing
Quoted 87 lines · Mikulas Patocka
Quoted 80 lines · Mike Snitzer
Quoted 7 lines · Mikulas Patocka
And what about this?
#defineWC_MODE_PMEM(wc)((wc)->pmem_mode)The code that I had just allowed the compiler to optimize out persistent-memory code if we have
DM_WRITECACHE_ONLY_SSDdefined - and you deleted it.Quoted 7 lines
Most architectures don't have persistent memory and the dm-writecache driver could work in ssd-only mode on them. On these architectures, I define
#defineWC_MODE_PMEM(wc)false
- and the compiler will just automatically remove the tests for that condition and the unused branch. It does also eliminate unused static functions.Here is the patch that I just folded into the rebased version of dm-writecache now in the dm-4.18 branch.
(I rebased ontop of Jens' latest block tree for 4.18 that now includes the
mempool_initchanges, etc.)--- drivers/md/dm-writecache.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-)drivers/md/dm-writecache.c +15
-2@@ -34,13 +34,21 @@#define BITMAP_GRANULARITY PAGE_SIZE#endif +#if defined(CONFIG_ARCH_HAS_PMEM_API ) &&IS_ENABLED (CONFIG_DAX_DRIVER ) +#define DM_WRITECACHE_HAS_PMEM +#endif + +#ifdef DM_WRITECACHE_HAS_PMEM #define pmem_assign (dest, src) \ do { \ typeof(dest) uniq = (src); \ memcpy_flushcache(&(dest), &uniq, sizeof(dest)); \ } while (0) +#else +#define pmem_assign (dest, src) ((dest)) = (src)) +#endif -#if defined(__HAVE_ARCH_MEMCPY_MCSAFE) && defined(CONFIG_ARCH_HAS_PMEM_API ) +#if defined(__HAVE_ARCH_MEMCPY_MCSAFE) && defined(DM_WRITECACHE_HAS_PMEM )#define DM_WRITECACHE_HANDLE_HARDWARE_ERRORS #endif @@ -87,8 +95,13 @@ struct wc_entry {#endif }; +#ifdef DM_WRITECACHE_HAS_PMEM #define WC_MODE_PMEM (wc) ((wc)->pmem_mode)#define WC_MODE_FUA (wc) ((wc)->writeback_fua) +#else +#define WC_MODE_PMEM (wc) false +#define WC_MODE_FUA (wc) false +#endif #define WC_MODE_SORT_FREELIST (wc) (!WC_MODE_PMEM(wc))struct dm_writecache {@@ -1857,7 +1870,7 @@ static int writecache_ctr(struct dm_target *ti, unsigned argc, char **argv)if (!strcasecmp (string,"s" )) { wc->pmem_mode = false; }else if (!strcasecmp (string,"p" )) { -#if defined(CONFIG_ARCH_HAS_PMEM_API ) &&IS_ENABLED (CONFIG_DAX_DRIVER ) +#ifdef DM_WRITECACHE_HAS_PMEM wc->pmem_mode = true; wc->writeback_fua = true;#else Signature · 1 line
2.15.0OK.
Quoted 6 lines
I think that
persistent_memory_claimshould also be conditioned based onDM_WRITECACHE_HAS_PMEM- i.e. if we haveDM_WRITECACHE_HAS_PMEM, we don't need to use other ifdefs.Is there some difference between "#if
IS_ENABLED(CONFIG_OPTION)" and "#ifdefined(CONFIG_OPTION)"?
Not that I'm aware of:
#define IS_ENABLED(option) __or(IS_BUILTIN(option), IS_MODULE(option))
Here is the incremental patch I just folded in:
drivers/md/dm-writecache.c +2 -2
@@ -34,7 +34,7 @@#define BITMAP_GRANULARITY PAGE_SIZE#endif -#if defined(CONFIG_ARCH_HAS_PMEM_API ) &&IS_ENABLED (CONFIG_DAX_DRIVER ) +#if IS_ENABLED (CONFIG_ARCH_HAS_PMEM_API ) &&IS_ENABLED (CONFIG_DAX_DRIVER )#define DM_WRITECACHE_HAS_PMEM #endif
@@ -218,7 +218,7 @@ static void wc_unlock(struct dm_writecache *wc)mutex_unlock (&wc->lock); } -#if IS_ENABLED (CONFIG_DAX_DRIVER ) +#ifdef DM_WRITECACHE_HAS_PMEM static int persistent_memory_claim (struct dm_writecache *wc) {int r;
Dan Williams
Acked-byRe: [patch 4/4] dm-writecache: use new API for flushing
In reply to a message not in the archiveQuoted 105 lines · Mikulas Patocka
Quoted 92 lines · Dan Williams
Quoted 59 lines · Mikulas Patocka
Quoted 55 lines · Dan Williams
Quoted 54 lines · Mikulas Patocka
Quoted 16 lines · Dan Williams
Quoted 15 lines · Mike Snitzer
Quoted 12 lines · Mikulas Patocka
Quoted 9 lines · Dan Williams
I don't want to grow driver-local wrappers for pmem. You should use
memcpy_flushcachedirectly()and if an architecture does not definememcpy_flushcache()then don't allow building dm-writecache, i.e. this driver should 'depends onCONFIG_ARCH_HAS_UACCESS_FLUSHCACHE'. I don't see a need to add a standalone flush operation if all relevant archs providememcpy_flushcache(). As for commit, I'd say just usewmb()directly since all archs define it. Alternatively we could introducememcpy_flushcache_relaxed()to be the un-ordered version of the copy routine andmemcpy_flushcache()would imply awmb().Quoted 6 lines
Quoted 1 line
Quoted 1 line
But
memcpy_flushcache()on ARM64 is slow.Right, so again, what is wrong with
memcpy_flushcache_relaxed()+wmb()or otherwise makingmemcpy_flushcache()ordered. I do not see that as a trailblazing requirement, I see that as typical review and a reduction of the operation space that you are proposing.
memcpy_flushcacheon ARM64 is generally wrong thing to do, because it is slower than memcpy and explicit cache flush.Suppose that you want to write data to a block device and make it persistent. So you send a WRITE bio and then a FLUSH bio.
Now - how to implement these two bios on persistent memory:
On X86, the WRITE bio does
memcpy_flushcache()and the FLUSH bio doeswmb()- this is the optimal implementation.But on ARM64,
memcpy_flushcache()is suboptimal. On ARM64, the optimal implementation is that the WRITE bio does justmemcpy()and the FLUSH bio doesarch_wb_cache_pmem()on the affected range.Why is
memcpy_flushcache()is suboptimal on ARM? The ARM architecture doesn't have non-temporal stores. So,memcpy_flushcache()is implemented asmemcpy()followed by a cache flush.Now - if you flush the cache immediatelly after memcpy, the cache is full of dirty lines and the cache-flushing code has to write these lines back and that is slow.
If you flush the cache some time after memcpy (i.e. when the FLUSH bio is received), the processor already flushed some part of the cache on its own, so the cache-flushing function has less work to do and it is faster.
Quoted 9 lines
Quoted 5 lines
Quoted 2 lines
So the conclusion is - don't use
memcpy_flushcacheon ARM. This problem cannot be fixed by a better implementation ofmemcpy_flushcache.It sounds like ARM might be better off with mapping its pmem as write-through rather than write-back, and skip the explicit cache
I doubt it would perform well - write combining combines the writes into a larger segments - and write-through doesn't.
Last I checked write-through caching does not disable write combining
Quoted 9 lines
Quoted 6 lines
management altogether. You speak of "optimal" and "sub-optimal", but what would be more clear is fio measurements of the relative IOPs and latency profiles of the different approaches. The reason I am continuing to push here is that reducing the operation space from 'copy-flush-commit' to just 'copy' or 'copy-commit' simplifies the maintenance long term.
I measured it (with nvme backing store) and late cache flushing has 12% better performance than eager flushing with
memcpy_flushcache().I assume what you're seeing is ARM64 over-flushing the amount of dirty data so it becomes more efficient to do an amortized flush at the end? However, that effectively makes
memcpy_flushcache()unusable in the way it can be used on x86. You claimed that ARM does not support non-temporal stores, but it does, see the STNP instruction. I do not want to see arch specific optimizations in drivers, so either write-through mappings is a potential answer to remove the need to explicitly manage flushing, or just implement STNP hacks inmemcpy_flushcache()like you did with MOVNT on x86.Quoted 3 lines
Quoted 1 line
131836 4k iops - vs - 117016.
To be clear this is
memcpy_flushcache()vs memcpy + flush?I found out what caused the difference. I used
dax_flushon the version of dm-writecache that I had on the ARM machine (with the kernel 4.14, because it is the last version where dax on ramdisk works) - and I thought thatdax_flushflushes the cache, but it doesn't.
Quoted 4 lines
When I replaced
dax_flushwitharch_wb_cache_pmem, the performance difference between early flushing and late flushing disappeared.So I think we can remove this per-architecture switch from dm-writecache.
Great find! Thanks for the due diligence. Feel free to add:
...on the reworks to unify ARM and x86.
A message that is not in the archive (sent off-list or not yet received): CAPcyv4j3pDQ3YMK5Eije0dgGw+1CQYazPJ-zvqfvGF-9O_gVJw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org
Re: [patch 4/4] dm-writecache: use new API for flushing
Quoted 109 lines · Dan Williams
Quoted 108 lines · Mikulas Patocka
Quoted 92 lines · Dan Williams
Quoted 59 lines · Mikulas Patocka
Quoted 55 lines · Dan Williams
Quoted 54 lines · Mikulas Patocka
Quoted 16 lines · Dan Williams
Quoted 15 lines · Mike Snitzer
Quoted 12 lines · Mikulas Patocka
Quoted 9 lines · Dan Williams
I don't want to grow driver-local wrappers for pmem. You should use
memcpy_flushcachedirectly()and if an architecture does not definememcpy_flushcache()then don't allow building dm-writecache, i.e. this driver should 'depends onCONFIG_ARCH_HAS_UACCESS_FLUSHCACHE'. I don't see a need to add a standalone flush operation if all relevant archs providememcpy_flushcache(). As for commit, I'd say just usewmb()directly since all archs define it. Alternatively we could introducememcpy_flushcache_relaxed()to be the un-ordered version of the copy routine andmemcpy_flushcache()would imply awmb().Quoted 6 lines
Quoted 1 line
Quoted 1 line
But
memcpy_flushcache()on ARM64 is slow.Right, so again, what is wrong with
memcpy_flushcache_relaxed()+wmb()or otherwise makingmemcpy_flushcache()ordered. I do not see that as a trailblazing requirement, I see that as typical review and a reduction of the operation space that you are proposing.
memcpy_flushcacheon ARM64 is generally wrong thing to do, because it is slower than memcpy and explicit cache flush.Suppose that you want to write data to a block device and make it persistent. So you send a WRITE bio and then a FLUSH bio.
Now - how to implement these two bios on persistent memory:
On X86, the WRITE bio does
memcpy_flushcache()and the FLUSH bio doeswmb()- this is the optimal implementation.But on ARM64,
memcpy_flushcache()is suboptimal. On ARM64, the optimal implementation is that the WRITE bio does justmemcpy()and the FLUSH bio doesarch_wb_cache_pmem()on the affected range.Why is
memcpy_flushcache()is suboptimal on ARM? The ARM architecture doesn't have non-temporal stores. So,memcpy_flushcache()is implemented asmemcpy()followed by a cache flush.Now - if you flush the cache immediatelly after memcpy, the cache is full of dirty lines and the cache-flushing code has to write these lines back and that is slow.
If you flush the cache some time after memcpy (i.e. when the FLUSH bio is received), the processor already flushed some part of the cache on its own, so the cache-flushing function has less work to do and it is faster.
Quoted 9 lines
Quoted 5 lines
Quoted 2 lines
So the conclusion is - don't use
memcpy_flushcacheon ARM. This problem cannot be fixed by a better implementation ofmemcpy_flushcache.It sounds like ARM might be better off with mapping its pmem as write-through rather than write-back, and skip the explicit cache
I doubt it would perform well - write combining combines the writes into a larger segments - and write-through doesn't.
Last I checked write-through caching does not disable write combining
Quoted 9 lines
Quoted 6 lines
management altogether. You speak of "optimal" and "sub-optimal", but what would be more clear is fio measurements of the relative IOPs and latency profiles of the different approaches. The reason I am continuing to push here is that reducing the operation space from 'copy-flush-commit' to just 'copy' or 'copy-commit' simplifies the maintenance long term.
I measured it (with nvme backing store) and late cache flushing has 12% better performance than eager flushing with
memcpy_flushcache().I assume what you're seeing is ARM64 over-flushing the amount of dirty data so it becomes more efficient to do an amortized flush at the end? However, that effectively makes
memcpy_flushcache()unusable in the way it can be used on x86. You claimed that ARM does not support non-temporal stores, but it does, see the STNP instruction. I do not want to see arch specific optimizations in drivers, so either write-through mappings is a potential answer to remove the need to explicitly manage flushing, or just implement STNP hacks inmemcpy_flushcache()like you did with MOVNT on x86.Quoted 3 lines
Quoted 1 line
131836 4k iops - vs - 117016.
To be clear this is
memcpy_flushcache()vs memcpy + flush?I found out what caused the difference. I used
dax_flushon the version of dm-writecache that I had on the ARM machine (with the kernel 4.14, because it is the last version where dax on ramdisk works) - and I thought thatdax_flushflushes the cache, but it doesn't.When I replaced
dax_flushwitharch_wb_cache_pmem, the performance difference between early flushing and late flushing disappeared.
Quoted 7 lines
Quoted 1 line
So I think we can remove this per-architecture switch from dm-writecache.
Great find! Thanks for the due diligence. Feel free to add:
Acked-by Dan Williams <[email protected]>...on the reworks to unify ARM and x86.
One more note. The side effect of not using dax_flush() is that you may end up flushing caches on systems where the platform has asserted it will take responsibility for flushing caches at power loss. If / when those systems become more prevalent we may want to think of a way to combine the non-temporal optimization and the cache-flush-bypass optimizations. However that is something that can wait for a later change beyond 4.18.
A message that is not in the archive (sent off-list or not yet received): CAPcyv4gD-ZaXyV1SFAndobUYJOGLkx9rOyb5zNbzJXB_kVCzoA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org
Re: [patch 4/4] dm-writecache: use new API for flushing
Quoted 6 lines · Dan Williams
Quoted 5 lines
Great find! Thanks for the due diligence. Feel free to add:
Acked-by Dan Williams <[email protected]>...on the reworks to unify ARM and x86.
Quoted 7 lines
One more note. The side effect of not using
dax_flush()is that you may end up flushing caches on systems where the platform has asserted it will take responsibility for flushing caches at power loss. If / when those systems become more prevalent we may want to think of a way to combine the non-temporal optimization and the cache-flush-bypass optimizations. However that is something that can wait for a later change beyond 4.18.
We could define memcpy_flushpmem, that falls back to memcpy or memcpy_flushcache, depending on whether the platform flushes the caches at power loss or not.
Mikulas
A message that is not in the archive (sent off-list or not yet received): alpine.LRH.2.02.1805310416540.30096-Hpncn10jQN4oNljnaZt3ZvA+iT7yCHsGwRM8/[email protected]
Re: [patch 4/4] dm-writecache: use new API for flushing
Quoted 18 lines · Mikulas Patocka
Quoted 6 lines · Dan Williams
Quoted 5 lines
Great find! Thanks for the due diligence. Feel free to add:
Acked-by Dan Williams <[email protected]>...on the reworks to unify ARM and x86.
Quoted 7 lines
One more note. The side effect of not using
dax_flush()is that you may end up flushing caches on systems where the platform has asserted it will take responsibility for flushing caches at power loss. If / when those systems become more prevalent we may want to think of a way to combine the non-temporal optimization and the cache-flush-bypass optimizations. However that is something that can wait for a later change beyond 4.18.
Quoted 3 lines
We could define
memcpy_flushpmem, that falls back to memcpy ormemcpy_flushcache, depending on whether the platform flushes the caches at power loss or not.
The problem is that some platforms only power fail protect a subset of the physical address range, but yes, if the platform makes a global assertion we can globally replace memcpy_flushpmem() with plain memcpy.
A message that is not in the archive (sent off-list or not yet received): CAPcyv4gzFbdBbUhPJ6W4mTJWAkvqVw_4FVhVdePEJzc28Sg-Sg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org
Re: [patch 4/4] dm-writecache: use new API for flushing
Quoted 19 lines · Dan Williams
Quoted 18 lines · Mikulas Patocka
Quoted 13 lines · Dan Williams
Quoted 5 lines
Great find! Thanks for the due diligence. Feel free to add:
Acked-by Dan Williams <[email protected]>...on the reworks to unify ARM and x86.
One more note. The side effect of not using
dax_flush()is that you may end up flushing caches on systems where the platform has asserted it will take responsibility for flushing caches at power loss. If / when those systems become more prevalent we may want to think of a way to combine the non-temporal optimization and the cache-flush-bypass optimizations. However that is something that can wait for a later change beyond 4.18.
Quoted 6 lines
Quoted 3 lines
We could define
memcpy_flushpmem, that falls back to memcpy ormemcpy_flushcache, depending on whether the platform flushes the caches at power loss or not.The problem is that some platforms only power fail protect a subset of the physical address range,
How can this be? A psysical address may be cached on any CPU, so either there is enough power to flush all the CPUs' caches or there isn't.
How does the CPU design that protects only a part of physical addresses look like?
Quoted 3 lines
but yes, if the platform makes a global
assertion we can globally replacememcpy_flushpmem()with plain memcpy.
Mikulas
A message that is not in the archive (sent off-list or not yet received): alpine.LRH.2.02.1805311127001.31059-Hpncn10jQN4oNljnaZt3ZvA+iT7yCHsGwRM8/[email protected]
Re: [patch 4/4] dm-writecache: use new API for flushing
Quoted 27 lines · Mikulas Patocka
Quoted 23 lines · Dan Williams
Quoted 21 lines · Mikulas Patocka
Quoted 6 lines · Dan Williams
Quoted 5 lines
Great find! Thanks for the due diligence. Feel free to add:
Acked-by Dan Williams <[email protected]>...on the reworks to unify ARM and x86.
Quoted 7 lines
One more note. The side effect of not using
dax_flush()is that you may end up flushing caches on systems where the platform has asserted it will take responsibility for flushing caches at power loss. If / when those systems become more prevalent we may want to think of a way to combine the non-temporal optimization and the cache-flush-bypass optimizations. However that is something that can wait for a later change beyond 4.18.We could define
memcpy_flushpmem, that falls back to memcpy ormemcpy_flushcache, depending on whether the platform flushes the caches at power loss or not.
Quoted 8 lines
Quoted 2 lines
The problem is that some platforms only power fail protect a subset of the physical address range,
How can this be? A psysical address may be cached on any CPU, so either there is enough power to flush all the CPUs' caches or there isn't.
How does the CPU design that protects only a part of physical addresses look like?
It's not necessarily a CPU problem, it may be a problem of having enough stored energy to potentially software loops to flush caches. There's also the consideration that a general purpose platform may mix persistent memory technologies from different vendors where some might be flash-backed DRAM and some might be persistent media directly.
For now I don't think we need to worry about it, but I don't want to make the assumption that this property is platform global given the history of how persistent memory has been deployed to date.