2020-05-27 18:59:16

by André Almeida

[permalink] [raw]
Subject: [PATCH 0/4] futex: Minor code improvements

Hello,

This series aims to make some small code improvements that I found in
futex.c, removing some lines and trying to make the code easier to read
and understand.

All commits tested with futex tests from kselftest.

André Almeida (4):
futex: Remove put_futex_key()
futex: Remove needless goto's
futex: Remove unused or redundant includes
futex: Consistently use fshared as boolean

kernel/futex.c | 115 +++++++++++--------------------------------------
1 file changed, 26 insertions(+), 89 deletions(-)

--
2.26.2


2020-05-27 18:59:22

by André Almeida

[permalink] [raw]
Subject: [PATCH 1/4] futex: Remove put_futex_key()

Since 4b39f99c ("futex: Remove {get,drop}_futex_key_refs()"),
function put_futex_key() is empty. Remove all references for this
function and redundant labels.

Signed-off-by: André Almeida <[email protected]>
---
kernel/futex.c | 61 ++++++++++----------------------------------------
1 file changed, 12 insertions(+), 49 deletions(-)

diff --git a/kernel/futex.c b/kernel/futex.c
index b59532862bc0..1f0287a51dce 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -674,10 +674,6 @@ get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key, enum futex_a
return err;
}

-static inline void put_futex_key(union futex_key *key)
-{
-}
-
/**
* fault_in_user_writeable() - Fault in user address and verify RW access
* @uaddr: pointer to faulting user space address
@@ -1614,7 +1610,7 @@ futex_wake(u32 __user *uaddr, unsigned int flags, int nr_wake, u32 bitset)

/* Make sure we really have tasks to wakeup */
if (!hb_waiters_pending(hb))
- goto out_put_key;
+ goto out;

spin_lock(&hb->lock);

@@ -1637,8 +1633,6 @@ futex_wake(u32 __user *uaddr, unsigned int flags, int nr_wake, u32 bitset)

spin_unlock(&hb->lock);
wake_up_q(&wake_q);
-out_put_key:
- put_futex_key(&key);
out:
return ret;
}
@@ -1709,7 +1703,7 @@ futex_wake_op(u32 __user *uaddr1, unsigned int flags, u32 __user *uaddr2,
goto out;
ret = get_futex_key(uaddr2, flags & FLAGS_SHARED, &key2, FUTEX_WRITE);
if (unlikely(ret != 0))
- goto out_put_key1;
+ goto out;

hb1 = hash_futex(&key1);
hb2 = hash_futex(&key2);
@@ -1727,13 +1721,13 @@ futex_wake_op(u32 __user *uaddr1, unsigned int flags, u32 __user *uaddr2,
* an MMU, but we might get them from range checking
*/
ret = op_ret;
- goto out_put_keys;
+ goto out;
}

if (op_ret == -EFAULT) {
ret = fault_in_user_writeable(uaddr2);
if (ret)
- goto out_put_keys;
+ goto out;
}

if (!(flags & FLAGS_SHARED)) {
@@ -1741,8 +1735,6 @@ futex_wake_op(u32 __user *uaddr1, unsigned int flags, u32 __user *uaddr2,
goto retry_private;
}

- put_futex_key(&key2);
- put_futex_key(&key1);
cond_resched();
goto retry;
}
@@ -1778,10 +1770,6 @@ futex_wake_op(u32 __user *uaddr1, unsigned int flags, u32 __user *uaddr2,
out_unlock:
double_unlock_hb(hb1, hb2);
wake_up_q(&wake_q);
-out_put_keys:
- put_futex_key(&key2);
-out_put_key1:
- put_futex_key(&key1);
out:
return ret;
}
@@ -1993,7 +1981,7 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags,
ret = get_futex_key(uaddr2, flags & FLAGS_SHARED, &key2,
requeue_pi ? FUTEX_WRITE : FUTEX_READ);
if (unlikely(ret != 0))
- goto out_put_key1;
+ goto out;

/*
* The check above which compares uaddrs is not sufficient for
@@ -2001,7 +1989,7 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags,
*/
if (requeue_pi && match_futex(&key1, &key2)) {
ret = -EINVAL;
- goto out_put_keys;
+ goto out;
}

hb1 = hash_futex(&key1);
@@ -2022,13 +2010,11 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags,

ret = get_user(curval, uaddr1);
if (ret)
- goto out_put_keys;
+ goto out;

if (!(flags & FLAGS_SHARED))
goto retry_private;

- put_futex_key(&key2);
- put_futex_key(&key1);
goto retry;
}
if (curval != *cmpval) {
@@ -2087,8 +2073,6 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags,
case -EFAULT:
double_unlock_hb(hb1, hb2);
hb_waiters_dec(hb2);
- put_futex_key(&key2);
- put_futex_key(&key1);
ret = fault_in_user_writeable(uaddr2);
if (!ret)
goto retry;
@@ -2103,8 +2087,6 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags,
*/
double_unlock_hb(hb1, hb2);
hb_waiters_dec(hb2);
- put_futex_key(&key2);
- put_futex_key(&key1);
/*
* Handle the case where the owner is in the middle of
* exiting. Wait for the exit to complete otherwise
@@ -2214,10 +2196,6 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags,
wake_up_q(&wake_q);
hb_waiters_dec(hb2);

-out_put_keys:
- put_futex_key(&key2);
-out_put_key1:
- put_futex_key(&key1);
out:
return ret ? ret : task_count;
}
@@ -2694,7 +2672,6 @@ static int futex_wait_setup(u32 __user *uaddr, u32 val, unsigned int flags,
if (!(flags & FLAGS_SHARED))
goto retry_private;

- put_futex_key(&q->key);
goto retry;
}

@@ -2704,8 +2681,6 @@ static int futex_wait_setup(u32 __user *uaddr, u32 val, unsigned int flags,
}

out:
- if (ret)
- put_futex_key(&q->key);
return ret;
}

@@ -2850,7 +2825,6 @@ static int futex_lock_pi(u32 __user *uaddr, unsigned int flags,
* - EAGAIN: The user space value changed.
*/
queue_unlock(hb);
- put_futex_key(&q.key);
/*
* Handle the case where the owner is in the middle of
* exiting. Wait for the exit to complete otherwise
@@ -2958,13 +2932,11 @@ static int futex_lock_pi(u32 __user *uaddr, unsigned int flags,
put_pi_state(pi_state);
}

- goto out_put_key;
+ goto out;

out_unlock_put_key:
queue_unlock(hb);

-out_put_key:
- put_futex_key(&q.key);
out:
if (to) {
hrtimer_cancel(&to->timer);
@@ -2977,12 +2949,11 @@ static int futex_lock_pi(u32 __user *uaddr, unsigned int flags,

ret = fault_in_user_writeable(uaddr);
if (ret)
- goto out_put_key;
+ goto out;

if (!(flags & FLAGS_SHARED))
goto retry_private;

- put_futex_key(&q.key);
goto retry;
}

@@ -3111,16 +3082,13 @@ static int futex_unlock_pi(u32 __user *uaddr, unsigned int flags)
out_unlock:
spin_unlock(&hb->lock);
out_putkey:
- put_futex_key(&key);
return ret;

pi_retry:
- put_futex_key(&key);
cond_resched();
goto retry;

pi_faulted:
- put_futex_key(&key);

ret = fault_in_user_writeable(uaddr);
if (!ret)
@@ -3262,7 +3230,7 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
*/
ret = futex_wait_setup(uaddr, val, flags, &q, &hb);
if (ret)
- goto out_key2;
+ goto out;

/*
* The check above which compares uaddrs is not sufficient for
@@ -3271,7 +3239,7 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
if (match_futex(&q.key, &key2)) {
queue_unlock(hb);
ret = -EINVAL;
- goto out_put_keys;
+ goto out;
}

/* Queue the futex_q, drop the hb lock, wait for wakeup. */
@@ -3281,7 +3249,7 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
ret = handle_early_requeue_pi_wakeup(hb, &q, &key2, to);
spin_unlock(&hb->lock);
if (ret)
- goto out_put_keys;
+ goto out;

/*
* In order for us to be here, we know our q.key == key2, and since
@@ -3371,11 +3339,6 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
ret = -EWOULDBLOCK;
}

-out_put_keys:
- put_futex_key(&q.key);
-out_key2:
- put_futex_key(&key2);
-
out:
if (to) {
hrtimer_cancel(&to->timer);
--
2.26.2

2020-05-27 18:59:24

by André Almeida

[permalink] [raw]
Subject: [PATCH 2/4] futex: Remove needless goto's

As stated in the coding style documentation[1], "if there is no cleanup
needed then just return directly", instead of jumping to a label and
then returning. Remove such goto's and replace with a return statement.
When there's a ternary operator on the return value, replace with the
result of the operation when is logically possible to determine it by
the control flow.

[1] https://www.kernel.org/doc/html/latest/process/coding-style.html#centralized-exiting-of-functions

Signed-off-by: André Almeida <[email protected]>
---
kernel/futex.c | 40 ++++++++++++++++------------------------
1 file changed, 16 insertions(+), 24 deletions(-)

diff --git a/kernel/futex.c b/kernel/futex.c
index 1f0287a51dce..ec07de620d1e 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -1604,13 +1604,13 @@ futex_wake(u32 __user *uaddr, unsigned int flags, int nr_wake, u32 bitset)

ret = get_futex_key(uaddr, flags & FLAGS_SHARED, &key, FUTEX_READ);
if (unlikely(ret != 0))
- goto out;
+ return ret;

hb = hash_futex(&key);

/* Make sure we really have tasks to wakeup */
if (!hb_waiters_pending(hb))
- goto out;
+ return ret;

spin_lock(&hb->lock);

@@ -1633,7 +1633,6 @@ futex_wake(u32 __user *uaddr, unsigned int flags, int nr_wake, u32 bitset)

spin_unlock(&hb->lock);
wake_up_q(&wake_q);
-out:
return ret;
}

@@ -1700,10 +1699,10 @@ futex_wake_op(u32 __user *uaddr1, unsigned int flags, u32 __user *uaddr2,
retry:
ret = get_futex_key(uaddr1, flags & FLAGS_SHARED, &key1, FUTEX_READ);
if (unlikely(ret != 0))
- goto out;
+ return ret;
ret = get_futex_key(uaddr2, flags & FLAGS_SHARED, &key2, FUTEX_WRITE);
if (unlikely(ret != 0))
- goto out;
+ return ret;

hb1 = hash_futex(&key1);
hb2 = hash_futex(&key2);
@@ -1721,13 +1720,13 @@ futex_wake_op(u32 __user *uaddr1, unsigned int flags, u32 __user *uaddr2,
* an MMU, but we might get them from range checking
*/
ret = op_ret;
- goto out;
+ return ret;
}

if (op_ret == -EFAULT) {
ret = fault_in_user_writeable(uaddr2);
if (ret)
- goto out;
+ return ret;
}

if (!(flags & FLAGS_SHARED)) {
@@ -1770,7 +1769,6 @@ futex_wake_op(u32 __user *uaddr1, unsigned int flags, u32 __user *uaddr2,
out_unlock:
double_unlock_hb(hb1, hb2);
wake_up_q(&wake_q);
-out:
return ret;
}

@@ -1977,20 +1975,18 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags,
retry:
ret = get_futex_key(uaddr1, flags & FLAGS_SHARED, &key1, FUTEX_READ);
if (unlikely(ret != 0))
- goto out;
+ return ret;
ret = get_futex_key(uaddr2, flags & FLAGS_SHARED, &key2,
requeue_pi ? FUTEX_WRITE : FUTEX_READ);
if (unlikely(ret != 0))
- goto out;
+ return ret;

/*
* The check above which compares uaddrs is not sufficient for
* shared futexes. We need to compare the keys:
*/
- if (requeue_pi && match_futex(&key1, &key2)) {
- ret = -EINVAL;
- goto out;
- }
+ if (requeue_pi && match_futex(&key1, &key2))
+ return -EINVAL;

hb1 = hash_futex(&key1);
hb2 = hash_futex(&key2);
@@ -2010,7 +2006,7 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags,

ret = get_user(curval, uaddr1);
if (ret)
- goto out;
+ return ret;

if (!(flags & FLAGS_SHARED))
goto retry_private;
@@ -2076,7 +2072,7 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags,
ret = fault_in_user_writeable(uaddr2);
if (!ret)
goto retry;
- goto out;
+ return ret;
case -EBUSY:
case -EAGAIN:
/*
@@ -2195,8 +2191,6 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags,
double_unlock_hb(hb1, hb2);
wake_up_q(&wake_q);
hb_waiters_dec(hb2);
-
-out:
return ret ? ret : task_count;
}

@@ -2542,7 +2536,7 @@ static int fixup_owner(u32 __user *uaddr, struct futex_q *q, int locked)
*/
if (q->pi_state->owner != current)
ret = fixup_pi_state_owner(uaddr, q, current);
- goto out;
+ return ret ? ret : locked;
}

/*
@@ -2555,7 +2549,7 @@ static int fixup_owner(u32 __user *uaddr, struct futex_q *q, int locked)
*/
if (q->pi_state->owner == current) {
ret = fixup_pi_state_owner(uaddr, q, NULL);
- goto out;
+ return ret;
}

/*
@@ -2569,8 +2563,7 @@ static int fixup_owner(u32 __user *uaddr, struct futex_q *q, int locked)
q->pi_state->owner);
}

-out:
- return ret ? ret : locked;
+ return ret;
}

/**
@@ -2667,7 +2660,7 @@ static int futex_wait_setup(u32 __user *uaddr, u32 val, unsigned int flags,

ret = get_user(uval, uaddr);
if (ret)
- goto out;
+ return ret;

if (!(flags & FLAGS_SHARED))
goto retry_private;
@@ -2680,7 +2673,6 @@ static int futex_wait_setup(u32 __user *uaddr, u32 val, unsigned int flags,
ret = -EWOULDBLOCK;
}

-out:
return ret;
}

--
2.26.2

2020-05-27 18:59:27

by André Almeida

[permalink] [raw]
Subject: [PATCH 4/4] futex: Consistently use fshared as boolean

Since fshared is meant to true/false values, declare it as bool. If the
code ever reaches the code beneath again label, we are sure that the
futex is shared, so we can use the true value instead of the variable.

Signed-off-by: André Almeida <[email protected]>
---
kernel/futex.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/kernel/futex.c b/kernel/futex.c
index 7bc5340396aa..a04f3793114f 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -457,7 +457,7 @@ static u64 get_inode_sequence_number(struct inode *inode)
/**
* get_futex_key() - Get parameters which are the keys for a futex
* @uaddr: virtual address of the futex
- * @fshared: 0 for a PROCESS_PRIVATE futex, 1 for PROCESS_SHARED
+ * @fshared: false for a PROCESS_PRIVATE futex, true for PROCESS_SHARED
* @key: address where result is stored.
* @rw: mapping needs to be read/write (values: FUTEX_READ,
* FUTEX_WRITE)
@@ -479,7 +479,8 @@ static u64 get_inode_sequence_number(struct inode *inode)
* lock_page() might sleep, the caller should not hold a spinlock.
*/
static int
-get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key, enum futex_access rw)
+get_futex_key(u32 __user *uaddr, bool fshared, union futex_key *key,
+ enum futex_access rw)
{
unsigned long address = (unsigned long)uaddr;
struct mm_struct *mm = current->mm;
@@ -516,7 +517,7 @@ get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key, enum futex_a

again:
/* Ignore any VERIFY_READ mapping (futex common case) */
- if (unlikely(should_fail_futex(fshared)))
+ if (unlikely(should_fail_futex(true)))
return -EFAULT;

err = get_user_pages_fast(address, 1, FOLL_WRITE, &page);
@@ -604,7 +605,7 @@ get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key, enum futex_a
* A RO anonymous page will never change and thus doesn't make
* sense for futex operations.
*/
- if (unlikely(should_fail_futex(fshared)) || ro) {
+ if (unlikely(should_fail_futex(true)) || ro) {
err = -EFAULT;
goto out;
}
--
2.26.2