Hi,
this is resending of the series, I previously sent. There are no changes
in separate patches except of [4/6], which is rebased on recent tip.git.
Two patches from the previous sending are already applied by Peter,
so they are not in this series. They are:
83ced169d9a0 "locking/rwsem-xadd: Add killable versions of rwsem_down_read_failed()" and
0aa1125fa8bc "locking/rwsem-spinlock: Add killable versions of __down_read()"
Also, there is one patch more [6/6], which was sent separate in
the reply to the first series.
So, there is no changes (except [4/6]). Please, take a look.
---
The series introduces new down_read_killable() primitive, which
is similar to down_read(), but it may be interrupted by a signal.
The most touched is architectures code. Also, it marks a new user
of the primitive, which is iterate_dir().
---
Kirill Tkhai (6):
alpha: Add __down_read_killable()
ia64: Add __down_read_killable()
s390: Add __down_read_killable()
x86: Add __down_read_killable()
rwsem: Add down_read_killable()
fs: Use killable down_read() in iterate_dir()
arch/alpha/include/asm/rwsem.h | 18 ++++++++++++++++--
arch/ia64/include/asm/rwsem.h | 22 +++++++++++++++++++---
arch/s390/include/asm/rwsem.h | 18 ++++++++++++++++--
arch/x86/include/asm/rwsem.h | 35 +++++++++++++++++++++++++----------
arch/x86/lib/rwsem.S | 12 ++++++++++++
fs/readdir.c | 11 +++++------
include/asm-generic/rwsem.h | 8 ++++++++
include/linux/rwsem.h | 1 +
kernel/locking/rwsem.c | 16 ++++++++++++++++
9 files changed, 118 insertions(+), 23 deletions(-)
--
Signed-off-by: Kirill Tkhai <[email protected]>
Similar to __down_write_killable(), and read killable primitive.
Signed-off-by: Kirill Tkhai <[email protected]>
---
arch/alpha/include/asm/rwsem.h | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/arch/alpha/include/asm/rwsem.h b/arch/alpha/include/asm/rwsem.h
index 77873d0ad293..7118bd090085 100644
--- a/arch/alpha/include/asm/rwsem.h
+++ b/arch/alpha/include/asm/rwsem.h
@@ -21,7 +21,7 @@
#define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS
#define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
-static inline void __down_read(struct rw_semaphore *sem)
+static inline int ___down_read(struct rw_semaphore *sem)
{
long oldcount;
#ifndef CONFIG_SMP
@@ -41,10 +41,24 @@ static inline void __down_read(struct rw_semaphore *sem)
:"=&r" (oldcount), "=m" (sem->count), "=&r" (temp)
:"Ir" (RWSEM_ACTIVE_READ_BIAS), "m" (sem->count) : "memory");
#endif
- if (unlikely(oldcount < 0))
+ return (oldcount < 0);
+}
+
+static inline void __down_read(struct rw_semaphore *sem)
+{
+ if (unlikely(___down_read(sem)))
rwsem_down_read_failed(sem);
}
+static inline int __down_read_killable(struct rw_semaphore *sem)
+{
+ if (unlikely(___down_read(sem)))
+ if (IS_ERR(rwsem_down_read_failed_killable(sem)))
+ return -EINTR;
+
+ return 0;
+}
+
/*
* trylock for reading -- returns 1 if successful, 0 if contention
*/
Similar to __down_write_killable(), and read killable primitive.
Signed-off-by: Kirill Tkhai <[email protected]>
---
arch/ia64/include/asm/rwsem.h | 22 +++++++++++++++++++---
1 file changed, 19 insertions(+), 3 deletions(-)
diff --git a/arch/ia64/include/asm/rwsem.h b/arch/ia64/include/asm/rwsem.h
index 8fa98dd303b4..1fb8b7cb1c98 100644
--- a/arch/ia64/include/asm/rwsem.h
+++ b/arch/ia64/include/asm/rwsem.h
@@ -37,15 +37,31 @@
/*
* lock for reading
*/
-static inline void
-__down_read (struct rw_semaphore *sem)
+static inline int
+___down_read (struct rw_semaphore *sem)
{
long result = ia64_fetchadd8_acq((unsigned long *)&sem->count.counter, 1);
- if (result < 0)
+ return (result < 0);
+}
+
+static inline void
+__down_read (struct rw_semaphore *sem)
+{
+ if (___down_read(sem))
rwsem_down_read_failed(sem);
}
+static inline int
+__down_read_killable (struct rw_semaphore *sem)
+{
+ if (___down_read(sem))
+ if (IS_ERR(rwsem_down_read_failed_killable(sem)))
+ return -EINTR;
+
+ return 0;
+}
+
/*
* lock for writing
*/
Similar to __down_write_killable(), add read killable primitive:
extract current __down_read() code to macros and teach it to get
different functions as slow_path argument:
store ax register to ret, and add sp register and preserve its value.
Add call_rwsem_down_read_failed_killable() assembly entry similar
to call_rwsem_down_read_failed():
push dx register to stack in additional to common registers,
as it's not declarated as modifiable in ____down_read().
Signed-off-by: Kirill Tkhai <[email protected]>
---
arch/x86/include/asm/rwsem.h | 35 +++++++++++++++++++++++++----------
arch/x86/lib/rwsem.S | 12 ++++++++++++
2 files changed, 37 insertions(+), 10 deletions(-)
diff --git a/arch/x86/include/asm/rwsem.h b/arch/x86/include/asm/rwsem.h
index a8f486e7a124..1e51195c0b63 100644
--- a/arch/x86/include/asm/rwsem.h
+++ b/arch/x86/include/asm/rwsem.h
@@ -60,18 +60,33 @@
/*
* lock for reading
*/
+#define ____down_read(sem, slow_path) \
+({ \
+ struct rw_semaphore* ret; \
+ asm volatile("# beginning down_read\n\t" \
+ LOCK_PREFIX _ASM_INC "(%[sem])\n\t" \
+ /* adds 0x00000001 */ \
+ " jns 1f\n" \
+ " call " slow_path "\n" \
+ "1:\n\t" \
+ "# ending down_read\n\t" \
+ : "+m" (sem->count), "=a" (ret), \
+ ASM_CALL_CONSTRAINT \
+ : [sem] "a" (sem) \
+ : "memory", "cc"); \
+ ret; \
+})
+
static inline void __down_read(struct rw_semaphore *sem)
{
- asm volatile("# beginning down_read\n\t"
- LOCK_PREFIX _ASM_INC "(%[sem])\n\t"
- /* adds 0x00000001 */
- " jns 1f\n"
- " call call_rwsem_down_read_failed\n"
- "1:\n\t"
- "# ending down_read\n\t"
- : "+m" (sem->count)
- : [sem] "a" (sem)
- : "memory", "cc");
+ ____down_read(sem, "call_rwsem_down_read_failed");
+}
+
+static inline int __down_read_killable(struct rw_semaphore *sem)
+{
+ if (IS_ERR(____down_read(sem, "call_rwsem_down_read_failed_killable")))
+ return -EINTR;
+ return 0;
}
/*
diff --git a/arch/x86/lib/rwsem.S b/arch/x86/lib/rwsem.S
index bf2c6074efd2..dc2ab6ea6768 100644
--- a/arch/x86/lib/rwsem.S
+++ b/arch/x86/lib/rwsem.S
@@ -98,6 +98,18 @@ ENTRY(call_rwsem_down_read_failed)
ret
ENDPROC(call_rwsem_down_read_failed)
+ENTRY(call_rwsem_down_read_failed_killable)
+ FRAME_BEGIN
+ save_common_regs
+ __ASM_SIZE(push,) %__ASM_REG(dx)
+ movq %rax,%rdi
+ call rwsem_down_read_failed_killable
+ __ASM_SIZE(pop,) %__ASM_REG(dx)
+ restore_common_regs
+ FRAME_END
+ ret
+ENDPROC(call_rwsem_down_read_failed_killable)
+
ENTRY(call_rwsem_down_write_failed)
FRAME_BEGIN
save_common_regs
Similar to __down_write_killable(), and read killable primitive.
Signed-off-by: Kirill Tkhai <[email protected]>
---
arch/s390/include/asm/rwsem.h | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/arch/s390/include/asm/rwsem.h b/arch/s390/include/asm/rwsem.h
index 597e7e96b59e..6bef7d5fbf1c 100644
--- a/arch/s390/include/asm/rwsem.h
+++ b/arch/s390/include/asm/rwsem.h
@@ -49,7 +49,7 @@
/*
* lock for reading
*/
-static inline void __down_read(struct rw_semaphore *sem)
+static inline int ___down_read(struct rw_semaphore *sem)
{
signed long old, new;
@@ -62,10 +62,24 @@ static inline void __down_read(struct rw_semaphore *sem)
: "=&d" (old), "=&d" (new), "=Q" (sem->count)
: "Q" (sem->count), "i" (RWSEM_ACTIVE_READ_BIAS)
: "cc", "memory");
- if (old < 0)
+ return (old < 0);
+}
+
+static inline void __down_read(struct rw_semaphore *sem)
+{
+ if (___down_read(sem))
rwsem_down_read_failed(sem);
}
+static inline int __down_read_killable(struct rw_semaphore *sem)
+{
+ if (___down_read(sem))
+ if (IS_ERR(rwsem_down_read_failed_killable(sem)))
+ return -EINTR;
+
+ return 0;
+}
+
/*
* trylock for reading -- returns 1 if successful, 0 if contention
*/
Similar to down_read() and down_write_killable(),
add killable version of down_read(), based on
__down_read_killable() function, added in previous
patches.
Signed-off-by: Kirill Tkhai <[email protected]>
---
include/asm-generic/rwsem.h | 8 ++++++++
include/linux/rwsem.h | 1 +
kernel/locking/rwsem.c | 16 ++++++++++++++++
3 files changed, 25 insertions(+)
diff --git a/include/asm-generic/rwsem.h b/include/asm-generic/rwsem.h
index 6c6a2141f271..2f71b913b555 100644
--- a/include/asm-generic/rwsem.h
+++ b/include/asm-generic/rwsem.h
@@ -37,6 +37,14 @@ static inline void __down_read(struct rw_semaphore *sem)
rwsem_down_read_failed(sem);
}
+static inline int __down_read_killable(struct rw_semaphore *sem)
+{
+ if (unlikely(atomic_long_inc_return_acquire(&sem->count) <= 0))
+ if (IS_ERR(rwsem_down_read_failed_killable(sem)))
+ return -EINTR;
+ return 0;
+}
+
static inline int __down_read_trylock(struct rw_semaphore *sem)
{
long tmp;
diff --git a/include/linux/rwsem.h b/include/linux/rwsem.h
index 0ad7318ff299..6ac8ee5f15dd 100644
--- a/include/linux/rwsem.h
+++ b/include/linux/rwsem.h
@@ -111,6 +111,7 @@ static inline int rwsem_is_contended(struct rw_semaphore *sem)
* lock for reading
*/
extern void down_read(struct rw_semaphore *sem);
+extern int __must_check down_read_killable(struct rw_semaphore *sem);
/*
* trylock for reading -- returns 1 if successful, 0 if contention
diff --git a/kernel/locking/rwsem.c b/kernel/locking/rwsem.c
index 4d48b1c4870d..e53f7746d9fd 100644
--- a/kernel/locking/rwsem.c
+++ b/kernel/locking/rwsem.c
@@ -28,6 +28,22 @@ void __sched down_read(struct rw_semaphore *sem)
EXPORT_SYMBOL(down_read);
+int __sched down_read_killable(struct rw_semaphore *sem)
+{
+ might_sleep();
+ rwsem_acquire_read(&sem->dep_map, 0, 0, _RET_IP_);
+
+ if (LOCK_CONTENDED_RETURN(sem, __down_read_trylock, __down_read_killable)) {
+ rwsem_release(&sem->dep_map, 1, _RET_IP_);
+ return -EINTR;
+ }
+
+ rwsem_set_reader_owned(sem);
+ return 0;
+}
+
+EXPORT_SYMBOL(down_read_killable);
+
/*
* trylock for reading -- returns 1 if successful, 0 if contention
*/
There was mutex_lock_interruptible() initially, and it was changed
to rwsem, but there were not killable rwsem primitives that time.
>From commit 9902af79c01a:
"The main issue is the lack of down_write_killable(), so the places
like readdir.c switched to plain inode_lock(); once killable
variants of rwsem primitives appear, that'll be dealt with"
Use down_read_killable() same as down_write_killable() in !shared
case, as concurrent inode_lock() may take much time, that may be
wanted to be interrupted by user.
Signed-off-by: Kirill Tkhai <[email protected]>
---
fs/readdir.c | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/fs/readdir.c b/fs/readdir.c
index 89659549c09d..7c584bbb4ce3 100644
--- a/fs/readdir.c
+++ b/fs/readdir.c
@@ -36,13 +36,12 @@ int iterate_dir(struct file *file, struct dir_context *ctx)
if (res)
goto out;
- if (shared) {
- inode_lock_shared(inode);
- } else {
+ if (shared)
+ res = down_read_killable(&inode->i_rwsem);
+ else
res = down_write_killable(&inode->i_rwsem);
- if (res)
- goto out;
- }
+ if (res)
+ goto out;
res = -ENOENT;
if (!IS_DEADDIR(inode)) {
On Fri, Sep 29, 2017 at 07:06:18PM +0300, Kirill Tkhai wrote:
> Similar to __down_write_killable(), and read killable primitive.
>
> Signed-off-by: Kirill Tkhai <[email protected]>
> ---
> arch/s390/include/asm/rwsem.h | 18 ++++++++++++++++--
> 1 file changed, 16 insertions(+), 2 deletions(-)
>
> diff --git a/arch/s390/include/asm/rwsem.h b/arch/s390/include/asm/rwsem.h
FWIW, while looking into this patch I realized that we never optimized our
rwsem primitives to make use of new atomic instructions.
The generic rwsem header file however does, since it uses atomic ops which
we did optimize. Even when compiling for old machines the generic version
generates better code. Therefore I will remove the 15 years old s390
implementation and switch to the generic version instead.
The same might be true for alpha and ia64...
On Sat, 30 Sep 2017 11:20:02 +0200
Heiko Carstens <[email protected]> wrote:
> On Fri, Sep 29, 2017 at 07:06:18PM +0300, Kirill Tkhai wrote:
> > Similar to __down_write_killable(), and read killable primitive.
> >
> > Signed-off-by: Kirill Tkhai <[email protected]>
> > ---
> > arch/s390/include/asm/rwsem.h | 18 ++++++++++++++++--
> > 1 file changed, 16 insertions(+), 2 deletions(-)
> >
> > diff --git a/arch/s390/include/asm/rwsem.h b/arch/s390/include/asm/rwsem.h
>
> FWIW, while looking into this patch I realized that we never optimized our
> rwsem primitives to make use of new atomic instructions.
>
> The generic rwsem header file however does, since it uses atomic ops which
> we did optimize. Even when compiling for old machines the generic version
> generates better code. Therefore I will remove the 15 years old s390
> implementation and switch to the generic version instead.
Take care not to conflict with the queued spinlock/rwlock patches on the
features branch.
https://git.kernel.org/pub/scm/linux/kernel/git/s390/linux.git/commit/?h=features&id=eb3b7b848fb3dd00f7a57d633d4ae4d194aa7865
Me thinks that what you have in mind is already done.
--
blue skies,
Martin.
"Reality continues to ruin my life." - Calvin.
On Sat, Sep 30, 2017 at 12:36:12PM +0200, Martin Schwidefsky wrote:
> On Sat, 30 Sep 2017 11:20:02 +0200
> Heiko Carstens <[email protected]> wrote:
>
> > On Fri, Sep 29, 2017 at 07:06:18PM +0300, Kirill Tkhai wrote:
> > > Similar to __down_write_killable(), and read killable primitive.
> > >
> > > Signed-off-by: Kirill Tkhai <[email protected]>
> > > ---
> > > arch/s390/include/asm/rwsem.h | 18 ++++++++++++++++--
> > > 1 file changed, 16 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/arch/s390/include/asm/rwsem.h b/arch/s390/include/asm/rwsem.h
> >
> > FWIW, while looking into this patch I realized that we never optimized our
> > rwsem primitives to make use of new atomic instructions.
> >
> > The generic rwsem header file however does, since it uses atomic ops which
> > we did optimize. Even when compiling for old machines the generic version
> > generates better code. Therefore I will remove the 15 years old s390
> > implementation and switch to the generic version instead.
>
> Take care not to conflict with the queued spinlock/rwlock patches on the
> features branch.
>
> https://git.kernel.org/pub/scm/linux/kernel/git/s390/linux.git/commit/?h=features&id=eb3b7b848fb3dd00f7a57d633d4ae4d194aa7865
>
> Me thinks that what you have in mind is already done.
No, it's not done. You probably mixed up rwlocks and rwsems?
On Sat, 30 Sep 2017 12:36:12 +0200
Martin Schwidefsky <[email protected]> wrote:
> On Sat, 30 Sep 2017 11:20:02 +0200
> Heiko Carstens <[email protected]> wrote:
>
> > On Fri, Sep 29, 2017 at 07:06:18PM +0300, Kirill Tkhai wrote:
> > > Similar to __down_write_killable(), and read killable primitive.
> > >
> > > Signed-off-by: Kirill Tkhai <[email protected]>
> > > ---
> > > arch/s390/include/asm/rwsem.h | 18 ++++++++++++++++--
> > > 1 file changed, 16 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/arch/s390/include/asm/rwsem.h b/arch/s390/include/asm/rwsem.h
> >
> > FWIW, while looking into this patch I realized that we never optimized our
> > rwsem primitives to make use of new atomic instructions.
> >
> > The generic rwsem header file however does, since it uses atomic ops which
> > we did optimize. Even when compiling for old machines the generic version
> > generates better code. Therefore I will remove the 15 years old s390
> > implementation and switch to the generic version instead.
>
> Take care not to conflict with the queued spinlock/rwlock patches on the
> features branch.
>
> https://git.kernel.org/pub/scm/linux/kernel/git/s390/linux.git/commit/?h=features&id=eb3b7b848fb3dd00f7a57d633d4ae4d194aa7865
>
> Me thinks that what you have in mind is already done.
Argh, pitfall rwlock != rwsem. Using the atomic_ops for the rwsem code makes
a lot of sense. Yes, please..
--
blue skies,
Martin.
"Reality continues to ruin my life." - Calvin.