* [RFC PATCH] futex: don't retry futex_wait() with stale uaddr/val after spurious wakeup
@ 2019-11-06 22:43 Jan Stancek
2019-11-07 11:11 ` Thomas Gleixner
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Jan Stancek @ 2019-11-06 22:43 UTC (permalink / raw)
To: tglx, mingo; +Cc: peterz, dvhart, longman, linux-kernel, jstancek
Assume following scenario: process A is sleeping on futex (uaddr1)
inside futex_wait(). Process B requeues this waiter via FUTEX_CMP_REQUEUE
to uaddr2, but doesn't wake it up. Later, process A spuriously wakes up
and futex_wait() retries to queue again with same uaddr1/val1:
if (!signal_pending(current))
goto retry;
Problem: Userspace fails to wake process A with futex(uaddr2, FUTEX_WAKE)
Store target uaddr/val in futex_requeue() and let futex_wait()
retry after spurious wake up using stored values.
Fixes: d58e6576b0de ("futex: Handle spurious wake up")
Signed-off-by: Jan Stancek <jstancek@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Darren Hart <dvhart@infradead.org>
Cc: Waiman Long <longman@redhat.com>
---
kernel/futex.c | 52 +++++++++++++++++++++++++++++++++-------------------
1 file changed, 33 insertions(+), 19 deletions(-)
diff --git a/kernel/futex.c b/kernel/futex.c
index bd18f60e4c6c..c13cfee25d35 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -237,6 +237,9 @@ struct futex_q {
struct rt_mutex_waiter *rt_waiter;
union futex_key *requeue_pi_key;
u32 bitset;
+
+ u32 *uaddr;
+ u32 val;
} __randomize_layout;
static const struct futex_q futex_q_init = {
@@ -1939,6 +1942,7 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags,
struct futex_hash_bucket *hb1, *hb2;
struct futex_q *this, *next;
DEFINE_WAKE_Q(wake_q);
+ u32 curval, targetval;
if (nr_wake < 0 || nr_requeue < 0)
return -EINVAL;
@@ -2005,30 +2009,32 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags,
hb_waiters_inc(hb2);
double_lock_hb(hb1, hb2);
- if (likely(cmpval != NULL)) {
- u32 curval;
-
+ ret = get_futex_value_locked(&targetval, uaddr2);
+ if (!ret && likely(cmpval != NULL))
ret = get_futex_value_locked(&curval, uaddr1);
- if (unlikely(ret)) {
- double_unlock_hb(hb1, hb2);
- hb_waiters_dec(hb2);
+ if (unlikely(ret)) {
+ double_unlock_hb(hb1, hb2);
+ hb_waiters_dec(hb2);
+ ret = get_user(targetval, uaddr2);
+ if (!ret && likely(cmpval != NULL))
ret = get_user(curval, uaddr1);
- if (ret)
- goto out_put_keys;
- if (!(flags & FLAGS_SHARED))
- goto retry_private;
+ if (ret)
+ goto out_put_keys;
- put_futex_key(&key2);
- put_futex_key(&key1);
- goto retry;
- }
- if (curval != *cmpval) {
- ret = -EAGAIN;
- goto out_unlock;
- }
+ if (!(flags & FLAGS_SHARED))
+ goto retry_private;
+
+ put_futex_key(&key2);
+ put_futex_key(&key1);
+ goto retry;
+ }
+
+ if (likely(cmpval != NULL) && (curval != *cmpval)) {
+ ret = -EAGAIN;
+ goto out_unlock;
}
if (requeue_pi && (task_count - nr_wake < nr_requeue)) {
@@ -2185,6 +2191,12 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags,
}
}
requeue_futex(this, hb1, hb2, &key2);
+ /*
+ * Save target uaddr/val, in case futex_wait() wakes
+ * up spuriously and retries to requeue.
+ */
+ this->uaddr = uaddr2;
+ this->val = targetval;
drop_count++;
}
@@ -2717,6 +2729,8 @@ static int futex_wait(u32 __user *uaddr, unsigned int flags, u32 val,
if (!bitset)
return -EINVAL;
q.bitset = bitset;
+ q.uaddr = uaddr;
+ q.val = val;
to = futex_setup_timer(abs_time, &timeout, flags,
current->timer_slack_ns);
@@ -2725,7 +2739,7 @@ static int futex_wait(u32 __user *uaddr, unsigned int flags, u32 val,
* Prepare to wait on uaddr. On success, holds hb lock and increments
* q.key refs.
*/
- ret = futex_wait_setup(uaddr, val, flags, &q, &hb);
+ ret = futex_wait_setup(q.uaddr, q.val, flags, &q, &hb);
if (ret)
goto out;
--
1.8.3.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [RFC PATCH] futex: don't retry futex_wait() with stale uaddr/val after spurious wakeup
2019-11-06 22:43 [RFC PATCH] futex: don't retry futex_wait() with stale uaddr/val after spurious wakeup Jan Stancek
@ 2019-11-07 11:11 ` Thomas Gleixner
2019-11-07 13:16 ` Jan Stancek
2019-11-08 23:27 ` kbuild test robot
2019-11-12 2:36 ` kbuild test robot
2 siblings, 1 reply; 5+ messages in thread
From: Thomas Gleixner @ 2019-11-07 11:11 UTC (permalink / raw)
To: Jan Stancek; +Cc: Ingo Molnar, Peter Zijlstra, Darren Hart, longman, LKML
Jan!
On Wed, 6 Nov 2019, Jan Stancek wrote:
> Assume following scenario: process A is sleeping on futex (uaddr1)
> inside futex_wait(). Process B requeues this waiter via FUTEX_CMP_REQUEUE
> to uaddr2, but doesn't wake it up. Later, process A spuriously wakes up
> and futex_wait() retries to queue again with same uaddr1/val1:
> if (!signal_pending(current))
> goto retry;
My brain is already wreckaged by staring into futex code for several days
in a row. So it might be just me, but the above qualifies for 'word
salad' as Peter Zijlstra named a similar changelog.
Please try to explain problems in very clear and understandable ways. The
futex code is confusing enough already.
> Problem: Userspace fails to wake process A with futex(uaddr2, FUTEX_WAKE)
>
> Store target uaddr/val in futex_requeue() and let futex_wait()
> retry after spurious wake up using stored values.
A bit less terse explanations might make the reader actually understand
right away what you are trying to say.
You're describing the WHAT, not the WHY.
> diff --git a/kernel/futex.c b/kernel/futex.c
> index bd18f60e4c6c..c13cfee25d35 100644
> --- a/kernel/futex.c
> +++ b/kernel/futex.c
> @@ -237,6 +237,9 @@ struct futex_q {
> struct rt_mutex_waiter *rt_waiter;
> union futex_key *requeue_pi_key;
> u32 bitset;
> +
> + u32 *uaddr;
> + u32 val;
> } __randomize_layout;
>
> static const struct futex_q futex_q_init = {
> @@ -1939,6 +1942,7 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags,
> struct futex_hash_bucket *hb1, *hb2;
> struct futex_q *this, *next;
> DEFINE_WAKE_Q(wake_q);
> + u32 curval, targetval;
>
> if (nr_wake < 0 || nr_requeue < 0)
> return -EINVAL;
> @@ -2005,30 +2009,32 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags,
> hb_waiters_inc(hb2);
> double_lock_hb(hb1, hb2);
>
> - if (likely(cmpval != NULL)) {
> - u32 curval;
> -
> + ret = get_futex_value_locked(&targetval, uaddr2);
Storing that value is meaningless as it is subject to change right after
the requeue operation has finished.
Also there is absolutely no requirement for this address to be accessible
at the time of this call. At least not for CMP_REQUEUE, CMP_REQUEUE_PI is a
different case.
> + if (!ret && likely(cmpval != NULL))
> ret = get_futex_value_locked(&curval, uaddr1);
>
> - if (unlikely(ret)) {
> - double_unlock_hb(hb1, hb2);
> - hb_waiters_dec(hb2);
> + if (unlikely(ret)) {
> + double_unlock_hb(hb1, hb2);
> + hb_waiters_dec(hb2);
>
> + ret = get_user(targetval, uaddr2);
> + if (!ret && likely(cmpval != NULL))
> ret = get_user(curval, uaddr1);
> - if (ret)
> - goto out_put_keys;
>
> - if (!(flags & FLAGS_SHARED))
> - goto retry_private;
> + if (ret)
> + goto out_put_keys;
>
> - put_futex_key(&key2);
> - put_futex_key(&key1);
> - goto retry;
> - }
> - if (curval != *cmpval) {
> - ret = -EAGAIN;
> - goto out_unlock;
> - }
> + if (!(flags & FLAGS_SHARED))
> + goto retry_private;
> +
> + put_futex_key(&key2);
> + put_futex_key(&key1);
> + goto retry;
> + }
> +
> + if (likely(cmpval != NULL) && (curval != *cmpval)) {
> + ret = -EAGAIN;
> + goto out_unlock;
> }
I can halfways understand the chunks below this, but the above is
absolutely unclear why this needs to be reshuffled. There is no explanation
whatsoever why that code needs to be changed to achive the below.
This changes the code flow massively and there is absolutely no indication
why this is equivivalent to the previous state.
If at all, and I doubt it, this restructuring wants to be a separate patch.
> @@ -2725,7 +2739,7 @@ static int futex_wait(u32 __user *uaddr, unsigned int flags, u32 val,
> * Prepare to wait on uaddr. On success, holds hb lock and increments
> * q.key refs.
> */
> - ret = futex_wait_setup(uaddr, val, flags, &q, &hb);
> + ret = futex_wait_setup(q.uaddr, q.val, flags, &q, &hb);
> if (ret)
> goto out;
>
So you go great length to "fix" the spurious wakeup case, but what happens if
there is an actual signal?
It will return to handle the signal and then run into the exactly same
situation because it restarts the syscall with the original uaddr1/uval,
right?
That means that the shortcut which was added in commit d58e6576b0de
("futex: Handle spurious wake up") is equivalent to the actual signal case.
So the above churn is pretty pointless because it "fixes" not even half of
the problem and you can't fix the -ERESTARTSYS case at all.
IIRC the uaddr1 value is supposed to change on a requeue operation so that
a late incoming waiter goes back with -EWOULDBLOCK. And excatly the same
would happen on the retry.
Aside of that you are completely failing to explain in which context you
observe this problem. Is that failing on libc, some test case or some other
maybe experimental code?
If there is an actual use case for keeping the uaddr1 value the same across
a requeue then this needs to be described properly and also needs to be
handled differently and consistently in all cases not just for a spurious
wakeup.
But let's talk about that once you came up with a proper explanation for
what you are trying to solve and why you think it's correct.
Thanks,
tglx
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [RFC PATCH] futex: don't retry futex_wait() with stale uaddr/val after spurious wakeup
2019-11-07 11:11 ` Thomas Gleixner
@ 2019-11-07 13:16 ` Jan Stancek
0 siblings, 0 replies; 5+ messages in thread
From: Jan Stancek @ 2019-11-07 13:16 UTC (permalink / raw)
To: Thomas Gleixner; +Cc: Ingo Molnar, Peter Zijlstra, Darren Hart, longman, LKML
My apologies for the 'word salad'.
> So you go great length to "fix" the spurious wakeup case, but what happens if
> there is an actual signal?
>
> It will return to handle the signal and then run into the exactly same
> situation because it restarts the syscall with the original uaddr1/uval,
> right?
Right, I missed that.
>
> That means that the shortcut which was added in commit d58e6576b0de
> ("futex: Handle spurious wake up") is equivalent to the actual signal case.
>
> So the above churn is pretty pointless because it "fixes" not even half of
> the problem and you can't fix the -ERESTARTSYS case at all.
>
> IIRC the uaddr1 value is supposed to change on a requeue operation so that
> a late incoming waiter goes back with -EWOULDBLOCK. And excatly the same
> would happen on the retry.
>
> Aside of that you are completely failing to explain in which context you
> observe this problem. Is that failing on libc, some test case or some other
> maybe experimental code?
It's test case (LTP futex_cmp_requeue01), which keeps uaddr1 value same
across requeue, and then sporadically fails to wake up some child processes.
>
> If there is an actual use case for keeping the uaddr1 value the same across
> a requeue..
It seems both I and test author missed some hint at man page
for FUTEX_CMP_REQUEUE and assumed this was valid use case.
> But let's talk about that once you came up with a proper explanation for
> what you are trying to solve and why you think it's correct.
Thank you for the detailed response.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [RFC PATCH] futex: don't retry futex_wait() with stale uaddr/val after spurious wakeup
2019-11-06 22:43 [RFC PATCH] futex: don't retry futex_wait() with stale uaddr/val after spurious wakeup Jan Stancek
2019-11-07 11:11 ` Thomas Gleixner
@ 2019-11-08 23:27 ` kbuild test robot
2019-11-12 2:36 ` kbuild test robot
2 siblings, 0 replies; 5+ messages in thread
From: kbuild test robot @ 2019-11-08 23:27 UTC (permalink / raw)
To: kbuild-all
[-- Attachment #1: Type: text/plain, Size: 26045 bytes --]
Hi Jan,
[FYI, it's a private test report for your RFC patch.]
[auto build test WARNING on tip/locking/core]
[also build test WARNING on v5.4-rc6 next-20191108]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]
url: https://github.com/0day-ci/linux/commits/Jan-Stancek/futex-don-t-retry-futex_wait-with-stale-uaddr-val-after-spurious-wakeup/20191109-055627
base: https://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git a0855d24fc22d49cdc25664fb224caee16998683
reproduce: make htmldocs
If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@intel.com>
All warnings (new ones prefixed by >>):
Warning: The Sphinx 'sphinx_rtd_theme' HTML theme was not found. Make sure you have the theme installed to produce pretty HTML output. Falling back to the default theme.
WARNING: dot(1) not found, for better output quality install graphviz from http://www.graphviz.org
WARNING: convert(1) not found, for SVG to PDF conversion install ImageMagick (https://www.imagemagick.org)
include/linux/regulator/machine.h:196: warning: Function parameter or member 'max_uV_step' not described in 'regulation_constraints'
include/linux/regulator/driver.h:223: warning: Function parameter or member 'resume' not described in 'regulator_ops'
Error: Cannot open file drivers/dma-buf/reservation.c
Error: Cannot open file drivers/dma-buf/reservation.c
Error: Cannot open file drivers/dma-buf/reservation.c
Error: Cannot open file include/linux/reservation.h
Error: Cannot open file include/linux/reservation.h
>> kernel/futex.c:244: warning: Function parameter or member 'uaddr' not described in 'futex_q'
>> kernel/futex.c:244: warning: Function parameter or member 'val' not described in 'futex_q'
include/linux/lsm_hooks.h:1822: warning: Function parameter or member 'quotactl' not described in 'security_list_options'
include/linux/lsm_hooks.h:1822: warning: Function parameter or member 'quota_on' not described in 'security_list_options'
include/linux/lsm_hooks.h:1822: warning: Function parameter or member 'sb_free_mnt_opts' not described in 'security_list_options'
include/linux/lsm_hooks.h:1822: warning: Function parameter or member 'sb_eat_lsm_opts' not described in 'security_list_options'
include/linux/lsm_hooks.h:1822: warning: Function parameter or member 'sb_kern_mount' not described in 'security_list_options'
include/linux/lsm_hooks.h:1822: warning: Function parameter or member 'sb_show_options' not described in 'security_list_options'
include/linux/lsm_hooks.h:1822: warning: Function parameter or member 'sb_add_mnt_opt' not described in 'security_list_options'
include/linux/lsm_hooks.h:1822: warning: Function parameter or member 'd_instantiate' not described in 'security_list_options'
include/linux/lsm_hooks.h:1822: warning: Function parameter or member 'getprocattr' not described in 'security_list_options'
include/linux/lsm_hooks.h:1822: warning: Function parameter or member 'setprocattr' not described in 'security_list_options'
include/linux/lsm_hooks.h:1822: warning: Function parameter or member 'locked_down' not described in 'security_list_options'
include/linux/spi/spi.h:190: warning: Function parameter or member 'driver_override' not described in 'spi_device'
lib/genalloc.c:1: warning: 'gen_pool_add_virt' not found
lib/genalloc.c:1: warning: 'gen_pool_alloc' not found
lib/genalloc.c:1: warning: 'gen_pool_free' not found
lib/genalloc.c:1: warning: 'gen_pool_alloc_algo' not found
drivers/gpio/gpiolib-of.c:92: warning: Excess function parameter 'dev' description in 'of_gpio_need_valid_mask'
include/linux/i2c.h:337: warning: Function parameter or member 'init_irq' not described in 'i2c_client'
drivers/usb/typec/bus.c:1: warning: 'typec_altmode_unregister_driver' not found
drivers/usb/typec/bus.c:1: warning: 'typec_altmode_register_driver' not found
drivers/usb/typec/class.c:1: warning: 'typec_altmode_register_notifier' not found
drivers/usb/typec/class.c:1: warning: 'typec_altmode_unregister_notifier' not found
include/linux/w1.h:277: warning: Function parameter or member 'of_match_table' not described in 'w1_family'
fs/fs-writeback.c:918: warning: Excess function parameter 'nr_pages' description in 'cgroup_writeback_by_id'
fs/direct-io.c:258: warning: Excess function parameter 'offset' description in 'dio_complete'
fs/libfs.c:496: warning: Excess function parameter 'available' description in 'simple_write_end'
fs/posix_acl.c:647: warning: Function parameter or member 'inode' not described in 'posix_acl_update_mode'
fs/posix_acl.c:647: warning: Function parameter or member 'mode_p' not described in 'posix_acl_update_mode'
fs/posix_acl.c:647: warning: Function parameter or member 'acl' not described in 'posix_acl_update_mode'
kernel/dma/coherent.c:1: warning: no structured comments found
include/linux/input/sparse-keymap.h:43: warning: Function parameter or member 'sw' not described in 'key_entry'
include/linux/skbuff.h:888: warning: Function parameter or member 'dev_scratch' not described in 'sk_buff'
include/linux/skbuff.h:888: warning: Function parameter or member 'list' not described in 'sk_buff'
include/linux/skbuff.h:888: warning: Function parameter or member 'ip_defrag_offset' not described in 'sk_buff'
include/linux/skbuff.h:888: warning: Function parameter or member 'skb_mstamp_ns' not described in 'sk_buff'
include/linux/skbuff.h:888: warning: Function parameter or member '__cloned_offset' not described in 'sk_buff'
include/linux/skbuff.h:888: warning: Function parameter or member 'head_frag' not described in 'sk_buff'
include/linux/skbuff.h:888: warning: Function parameter or member '__pkt_type_offset' not described in 'sk_buff'
include/linux/skbuff.h:888: warning: Function parameter or member 'encapsulation' not described in 'sk_buff'
include/linux/skbuff.h:888: warning: Function parameter or member 'encap_hdr_csum' not described in 'sk_buff'
include/linux/skbuff.h:888: warning: Function parameter or member 'csum_valid' not described in 'sk_buff'
include/linux/skbuff.h:888: warning: Function parameter or member '__pkt_vlan_present_offset' not described in 'sk_buff'
include/linux/skbuff.h:888: warning: Function parameter or member 'vlan_present' not described in 'sk_buff'
include/linux/skbuff.h:888: warning: Function parameter or member 'csum_complete_sw' not described in 'sk_buff'
include/linux/skbuff.h:888: warning: Function parameter or member 'csum_level' not described in 'sk_buff'
include/linux/skbuff.h:888: warning: Function parameter or member 'inner_protocol_type' not described in 'sk_buff'
include/linux/skbuff.h:888: warning: Function parameter or member 'remcsum_offload' not described in 'sk_buff'
include/linux/skbuff.h:888: warning: Function parameter or member 'sender_cpu' not described in 'sk_buff'
include/linux/skbuff.h:888: warning: Function parameter or member 'reserved_tailroom' not described in 'sk_buff'
include/linux/skbuff.h:888: warning: Function parameter or member 'inner_ipproto' not described in 'sk_buff'
include/net/sock.h:233: warning: Function parameter or member 'skc_addrpair' not described in 'sock_common'
include/net/sock.h:233: warning: Function parameter or member 'skc_portpair' not described in 'sock_common'
include/net/sock.h:233: warning: Function parameter or member 'skc_ipv6only' not described in 'sock_common'
include/net/sock.h:233: warning: Function parameter or member 'skc_net_refcnt' not described in 'sock_common'
include/net/sock.h:233: warning: Function parameter or member 'skc_v6_daddr' not described in 'sock_common'
include/net/sock.h:233: warning: Function parameter or member 'skc_v6_rcv_saddr' not described in 'sock_common'
include/net/sock.h:233: warning: Function parameter or member 'skc_cookie' not described in 'sock_common'
include/net/sock.h:233: warning: Function parameter or member 'skc_listener' not described in 'sock_common'
include/net/sock.h:233: warning: Function parameter or member 'skc_tw_dr' not described in 'sock_common'
include/net/sock.h:233: warning: Function parameter or member 'skc_rcv_wnd' not described in 'sock_common'
include/net/sock.h:233: warning: Function parameter or member 'skc_tw_rcv_nxt' not described in 'sock_common'
include/net/sock.h:515: warning: Function parameter or member 'sk_rx_skb_cache' not described in 'sock'
include/net/sock.h:515: warning: Function parameter or member 'sk_wq_raw' not described in 'sock'
include/net/sock.h:515: warning: Function parameter or member 'tcp_rtx_queue' not described in 'sock'
include/net/sock.h:515: warning: Function parameter or member 'sk_tx_skb_cache' not described in 'sock'
include/net/sock.h:515: warning: Function parameter or member 'sk_route_forced_caps' not described in 'sock'
include/net/sock.h:515: warning: Function parameter or member 'sk_txtime_report_errors' not described in 'sock'
include/net/sock.h:515: warning: Function parameter or member 'sk_validate_xmit_skb' not described in 'sock'
include/net/sock.h:515: warning: Function parameter or member 'sk_bpf_storage' not described in 'sock'
include/net/sock.h:2439: warning: Function parameter or member 'tcp_rx_skb_cache_key' not described in 'DECLARE_STATIC_KEY_FALSE'
include/net/sock.h:2439: warning: Excess function parameter 'sk' description in 'DECLARE_STATIC_KEY_FALSE'
include/net/sock.h:2439: warning: Excess function parameter 'skb' description in 'DECLARE_STATIC_KEY_FALSE'
include/linux/netdevice.h:2053: warning: Function parameter or member 'gso_partial_features' not described in 'net_device'
include/linux/netdevice.h:2053: warning: Function parameter or member 'l3mdev_ops' not described in 'net_device'
include/linux/netdevice.h:2053: warning: Function parameter or member 'xfrmdev_ops' not described in 'net_device'
include/linux/netdevice.h:2053: warning: Function parameter or member 'tlsdev_ops' not described in 'net_device'
include/linux/netdevice.h:2053: warning: Function parameter or member 'name_assign_type' not described in 'net_device'
include/linux/netdevice.h:2053: warning: Function parameter or member 'ieee802154_ptr' not described in 'net_device'
include/linux/netdevice.h:2053: warning: Function parameter or member 'mpls_ptr' not described in 'net_device'
include/linux/netdevice.h:2053: warning: Function parameter or member 'xdp_prog' not described in 'net_device'
include/linux/netdevice.h:2053: warning: Function parameter or member 'gro_flush_timeout' not described in 'net_device'
include/linux/netdevice.h:2053: warning: Function parameter or member 'nf_hooks_ingress' not described in 'net_device'
include/linux/netdevice.h:2053: warning: Function parameter or member '____cacheline_aligned_in_smp' not described in 'net_device'
include/linux/netdevice.h:2053: warning: Function parameter or member 'qdisc_hash' not described in 'net_device'
include/linux/netdevice.h:2053: warning: Function parameter or member 'xps_cpus_map' not described in 'net_device'
include/linux/netdevice.h:2053: warning: Function parameter or member 'xps_rxqs_map' not described in 'net_device'
include/linux/phylink.h:56: warning: Function parameter or member '__ETHTOOL_DECLARE_LINK_MODE_MASK(advertising' not described in 'phylink_link_state'
include/linux/phylink.h:56: warning: Function parameter or member '__ETHTOOL_DECLARE_LINK_MODE_MASK(lp_advertising' not described in 'phylink_link_state'
drivers/net/phy/phylink.c:595: warning: Function parameter or member 'config' not described in 'phylink_create'
drivers/net/phy/phylink.c:595: warning: Excess function parameter 'ndev' description in 'phylink_create'
include/linux/bitmap.h:341: warning: Function parameter or member 'nbits' not described in 'bitmap_or_equal'
include/linux/rculist.h:374: warning: Excess function parameter 'cond' description in 'list_for_each_entry_rcu'
include/linux/rculist.h:651: warning: Excess function parameter 'cond' description in 'hlist_for_each_entry_rcu'
mm/util.c:1: warning: 'get_user_pages_fast' not found
mm/slab.c:4215: warning: Function parameter or member 'objp' not described in '__ksize'
>> kernel/futex.c:244: warning: Function parameter or member 'uaddr' not described in 'futex_q'
>> kernel/futex.c:244: warning: Function parameter or member 'val' not described in 'futex_q'
drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c:335: warning: Excess function parameter 'dev' description in 'amdgpu_gem_prime_export'
drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c:336: warning: Excess function parameter 'dev' description in 'amdgpu_gem_prime_export'
drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c:142: warning: Function parameter or member 'blockable' not described in 'amdgpu_mn_read_lock'
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:347: warning: cannot understand function prototype: 'struct amdgpu_vm_pt_cursor '
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:348: warning: cannot understand function prototype: 'struct amdgpu_vm_pt_cursor '
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:494: warning: Function parameter or member 'start' not described in 'amdgpu_vm_pt_first_dfs'
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:546: warning: Function parameter or member 'adev' not described in 'for_each_amdgpu_vm_pt_dfs_safe'
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:546: warning: Function parameter or member 'vm' not described in 'for_each_amdgpu_vm_pt_dfs_safe'
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:546: warning: Function parameter or member 'start' not described in 'for_each_amdgpu_vm_pt_dfs_safe'
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:546: warning: Function parameter or member 'cursor' not described in 'for_each_amdgpu_vm_pt_dfs_safe'
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:546: warning: Function parameter or member 'entry' not described in 'for_each_amdgpu_vm_pt_dfs_safe'
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:821: warning: Function parameter or member 'level' not described in 'amdgpu_vm_bo_param'
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1283: warning: Function parameter or member 'params' not described in 'amdgpu_vm_update_flags'
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1283: warning: Function parameter or member 'bo' not described in 'amdgpu_vm_update_flags'
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1283: warning: Function parameter or member 'level' not described in 'amdgpu_vm_update_flags'
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1283: warning: Function parameter or member 'pe' not described in 'amdgpu_vm_update_flags'
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1283: warning: Function parameter or member 'addr' not described in 'amdgpu_vm_update_flags'
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1283: warning: Function parameter or member 'count' not described in 'amdgpu_vm_update_flags'
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1283: warning: Function parameter or member 'incr' not described in 'amdgpu_vm_update_flags'
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1283: warning: Function parameter or member 'flags' not described in 'amdgpu_vm_update_flags'
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:2821: warning: Function parameter or member 'pasid' not described in 'amdgpu_vm_make_compute'
drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c:378: warning: Excess function parameter 'entry' description in 'amdgpu_irq_dispatch'
drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c:379: warning: Function parameter or member 'ih' not described in 'amdgpu_irq_dispatch'
drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c:379: warning: Excess function parameter 'entry' description in 'amdgpu_irq_dispatch'
drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c:1: warning: no structured comments found
drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c:1: warning: no structured comments found
drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c:1: warning: 'pp_dpm_sclk pp_dpm_mclk pp_dpm_pcie' not found
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h:132: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source @atomic_obj
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h:238: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source gpu_info FW provided soc bounding box struct or 0 if not
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h:243: warning: Function parameter or member 'atomic_obj' not described in 'amdgpu_display_manager'
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h:243: warning: Function parameter or member 'backlight_link' not described in 'amdgpu_display_manager'
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h:243: warning: Function parameter or member 'backlight_caps' not described in 'amdgpu_display_manager'
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h:243: warning: Function parameter or member 'freesync_module' not described in 'amdgpu_display_manager'
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h:243: warning: Function parameter or member 'fw_dmcu' not described in 'amdgpu_display_manager'
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h:243: warning: Function parameter or member 'dmcu_fw_version' not described in 'amdgpu_display_manager'
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h:243: warning: Function parameter or member 'soc_bounding_box' not described in 'amdgpu_display_manager'
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c:1: warning: 'register_hpd_handlers' not found
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c:1: warning: 'dm_crtc_high_irq' not found
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c:1: warning: 'dm_pflip_high_irq' not found
include/drm/drm_modeset_helper_vtables.h:1053: warning: Function parameter or member 'prepare_writeback_job' not described in 'drm_connector_helper_funcs'
include/drm/drm_modeset_helper_vtables.h:1053: warning: Function parameter or member 'cleanup_writeback_job' not described in 'drm_connector_helper_funcs'
include/drm/drm_atomic_state_helper.h:1: warning: no structured comments found
include/drm/drm_gem_shmem_helper.h:87: warning: Function parameter or member 'madv' not described in 'drm_gem_shmem_object'
include/drm/drm_gem_shmem_helper.h:87: warning: Function parameter or member 'madv_list' not described in 'drm_gem_shmem_object'
drivers/gpu/drm/i915/display/intel_dpll_mgr.h:158: warning: Enum value 'DPLL_ID_TGL_MGPLL5' not described in enum 'intel_dpll_id'
drivers/gpu/drm/i915/display/intel_dpll_mgr.h:158: warning: Enum value 'DPLL_ID_TGL_MGPLL6' not described in enum 'intel_dpll_id'
drivers/gpu/drm/i915/display/intel_dpll_mgr.h:158: warning: Excess enum value 'DPLL_ID_TGL_TCPLL6' description in 'intel_dpll_id'
drivers/gpu/drm/i915/display/intel_dpll_mgr.h:158: warning: Excess enum value 'DPLL_ID_TGL_TCPLL5' description in 'intel_dpll_id'
drivers/gpu/drm/i915/display/intel_dpll_mgr.h:342: warning: Function parameter or member 'wakeref' not described in 'intel_shared_dpll'
Error: Cannot open file drivers/gpu/drm/i915/i915_gem_batch_pool.c
Error: Cannot open file drivers/gpu/drm/i915/i915_gem_batch_pool.c
Error: Cannot open file drivers/gpu/drm/i915/i915_gem_batch_pool.c
drivers/gpu/drm/i915/i915_drv.h:1129: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source The OA context specific information.
drivers/gpu/drm/i915/i915_drv.h:1143: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source State of the OA buffer.
drivers/gpu/drm/i915/i915_drv.h:1154: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source Locks reads and writes to all head/tail state
drivers/gpu/drm/i915/i915_drv.h:1176: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source One 'aging' tail pointer and one 'aged' tail pointer ready to
drivers/gpu/drm/i915/i915_drv.h:1188: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source Index for the aged tail ready to read() data up to.
drivers/gpu/drm/i915/i915_drv.h:1193: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source A monotonic timestamp for when the current aging tail pointer
drivers/gpu/drm/i915/i915_drv.h:1199: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source Although we can always read back the head pointer register,
drivers/gpu/drm/i915/i915_drv.h:1207: warning: Function parameter or member 'pinned_ctx' not described in 'i915_perf_stream'
drivers/gpu/drm/i915/i915_drv.h:1207: warning: Function parameter or member 'specific_ctx_id' not described in 'i915_perf_stream'
drivers/gpu/drm/i915/i915_drv.h:1207: warning: Function parameter or member 'specific_ctx_id_mask' not described in 'i915_perf_stream'
drivers/gpu/drm/i915/i915_drv.h:1207: warning: Function parameter or member 'poll_check_timer' not described in 'i915_perf_stream'
drivers/gpu/drm/i915/i915_drv.h:1207: warning: Function parameter or member 'poll_wq' not described in 'i915_perf_stream'
drivers/gpu/drm/i915/i915_drv.h:1207: warning: Function parameter or member 'pollin' not described in 'i915_perf_stream'
drivers/gpu/drm/i915/i915_drv.h:1207: warning: Function parameter or member 'periodic' not described in 'i915_perf_stream'
drivers/gpu/drm/i915/i915_drv.h:1207: warning: Function parameter or member 'period_exponent' not described in 'i915_perf_stream'
drivers/gpu/drm/i915/i915_drv.h:1207: warning: Function parameter or member 'oa_buffer' not described in 'i915_perf_stream'
drivers/gpu/drm/i915/i915_drv.h:1129: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source The OA context specific information.
drivers/gpu/drm/i915/i915_drv.h:1143: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source State of the OA buffer.
drivers/gpu/drm/i915/i915_drv.h:1154: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source Locks reads and writes to all head/tail state
drivers/gpu/drm/i915/i915_drv.h:1176: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source One 'aging' tail pointer and one 'aged' tail pointer ready to
drivers/gpu/drm/i915/i915_drv.h:1188: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source Index for the aged tail ready to read() data up to.
drivers/gpu/drm/i915/i915_drv.h:1193: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source A monotonic timestamp for when the current aging tail pointer
drivers/gpu/drm/i915/i915_drv.h:1199: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source Although we can always read back the head pointer register,
drivers/gpu/drm/i915/i915_drv.h:1129: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source The OA context specific information.
drivers/gpu/drm/i915/i915_drv.h:1143: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source State of the OA buffer.
drivers/gpu/drm/i915/i915_drv.h:1154: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source Locks reads and writes to all head/tail state
drivers/gpu/drm/i915/i915_drv.h:1176: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source One 'aging' tail pointer and one 'aged' tail pointer ready to
drivers/gpu/drm/i915/i915_drv.h:1188: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source Index for the aged tail ready to read() data up to.
drivers/gpu/drm/i915/i915_drv.h:1193: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source A monotonic timestamp for when the current aging tail pointer
drivers/gpu/drm/i915/i915_drv.h:1199: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source Although we can always read back the head pointer register,
drivers/gpu/drm/mcde/mcde_drv.c:1: warning: 'ST-Ericsson MCDE DRM Driver' not found
include/net/cfg80211.h:1185: warning: Function parameter or member 'txpwr' not described in 'station_parameters'
include/net/mac80211.h:4056: warning: Function parameter or member 'sta_set_txpwr' not described in 'ieee80211_ops'
include/net/mac80211.h:2018: warning: Function parameter or member 'txpwr' not described in 'ieee80211_sta'
Documentation/admin-guide/perf/imx-ddr.rst:21: WARNING: Unexpected indentation.
Documentation/admin-guide/perf/imx-ddr.rst:34: WARNING: Unexpected indentation.
Documentation/admin-guide/perf/imx-ddr.rst:40: WARNING: Unexpected indentation.
Documentation/admin-guide/perf/imx-ddr.rst:45: WARNING: Unexpected indentation.
Documentation/admin-guide/perf/imx-ddr.rst:52: WARNING: Unexpected indentation.
Documentation/hwmon/inspur-ipsps1.rst:2: WARNING: Title underline too short.
vim +244 kernel/futex.c
^1da177e4c3f41 Linus Torvalds 2005-04-16 @244
:::::: The code at line 244 was first introduced by commit
:::::: 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 Linux-2.6.12-rc2
:::::: TO: Linus Torvalds <torvalds@ppc970.osdl.org>
:::::: CC: Linus Torvalds <torvalds@ppc970.osdl.org>
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org Intel Corporation
[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 7279 bytes --]
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [RFC PATCH] futex: don't retry futex_wait() with stale uaddr/val after spurious wakeup
2019-11-06 22:43 [RFC PATCH] futex: don't retry futex_wait() with stale uaddr/val after spurious wakeup Jan Stancek
2019-11-07 11:11 ` Thomas Gleixner
2019-11-08 23:27 ` kbuild test robot
@ 2019-11-12 2:36 ` kbuild test robot
2 siblings, 0 replies; 5+ messages in thread
From: kbuild test robot @ 2019-11-12 2:36 UTC (permalink / raw)
To: kbuild-all
[-- Attachment #1: Type: text/plain, Size: 14704 bytes --]
Hi Jan,
[FYI, it's a private test report for your RFC patch.]
[auto build test WARNING on tip/locking/core]
[cannot apply to v5.4-rc7 next-20191111]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]
url: https://github.com/0day-ci/linux/commits/Jan-Stancek/futex-don-t-retry-futex_wait-with-stale-uaddr-val-after-spurious-wakeup/20191109-055627
base: https://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git a0855d24fc22d49cdc25664fb224caee16998683
reproduce:
# apt-get install sparse
# sparse version: v0.6.1-29-g781bc5d-dirty
make ARCH=x86_64 allmodconfig
make C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__'
If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@intel.com>
sparse warnings: (new ones prefixed by >>)
>> kernel/futex.c:2198:29: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected unsigned int [usertype] *uaddr @@ got unsigned int [nodeunsigned int [usertype] *uaddr @@
>> kernel/futex.c:2198:29: sparse: expected unsigned int [usertype] *uaddr
>> kernel/futex.c:2198:29: sparse: got unsigned int [noderef] [usertype] <asn:1> *uaddr2
>> kernel/futex.c:2732:17: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected unsigned int [usertype] *[assigned] uaddr @@ got unsigneunsigned int [usertype] *[assigned] uaddr @@
>> kernel/futex.c:2732:17: sparse: expected unsigned int [usertype] *[assigned] uaddr
>> kernel/futex.c:2732:17: sparse: got unsigned int [noderef] [usertype] <asn:1> *uaddr
>> kernel/futex.c:2742:33: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected unsigned int [noderef] [usertype] <asn:1> *uaddr @@ got d int [noderef] [usertype] <asn:1> *uaddr @@
>> kernel/futex.c:2742:33: sparse: expected unsigned int [noderef] [usertype] <asn:1> *uaddr
>> kernel/futex.c:2742:33: sparse: got unsigned int [usertype] *[assigned] uaddr
kernel/futex.c:1562:9: sparse: sparse: context imbalance in 'wake_futex_pi' - unexpected unlock
kernel/futex.c:1722:33: sparse: sparse: context imbalance in 'futex_wake_op' - different lock contexts for basic block
include/linux/kasan-checks.h:38:20: sparse: sparse: context imbalance in 'futex_requeue' - different lock contexts for basic block
kernel/futex.c:2503:9: sparse: sparse: context imbalance in 'fixup_pi_state_owner' - unexpected unlock
kernel/futex.c:2612:13: sparse: sparse: context imbalance in 'futex_wait_queue_me' - unexpected unlock
kernel/futex.c:2714:1: sparse: sparse: context imbalance in 'futex_wait_setup' - different lock contexts for basic block
kernel/futex.c:2995:12: sparse: sparse: context imbalance in 'futex_unlock_pi' - different lock contexts for basic block
kernel/futex.c:3273:29: sparse: sparse: context imbalance in 'futex_wait_requeue_pi' - unexpected unlock
vim +2198 kernel/futex.c
1916
1917 /**
1918 * futex_requeue() - Requeue waiters from uaddr1 to uaddr2
1919 * @uaddr1: source futex user address
1920 * @flags: futex flags (FLAGS_SHARED, etc.)
1921 * @uaddr2: target futex user address
1922 * @nr_wake: number of waiters to wake (must be 1 for requeue_pi)
1923 * @nr_requeue: number of waiters to requeue (0-INT_MAX)
1924 * @cmpval: @uaddr1 expected value (or %NULL)
1925 * @requeue_pi: if we are attempting to requeue from a non-pi futex to a
1926 * pi futex (pi to pi requeue is not supported)
1927 *
1928 * Requeue waiters on uaddr1 to uaddr2. In the requeue_pi case, try to acquire
1929 * uaddr2 atomically on behalf of the top waiter.
1930 *
1931 * Return:
1932 * - >=0 - on success, the number of tasks requeued or woken;
1933 * - <0 - on error
1934 */
1935 static int futex_requeue(u32 __user *uaddr1, unsigned int flags,
1936 u32 __user *uaddr2, int nr_wake, int nr_requeue,
1937 u32 *cmpval, int requeue_pi)
1938 {
1939 union futex_key key1 = FUTEX_KEY_INIT, key2 = FUTEX_KEY_INIT;
1940 int drop_count = 0, task_count = 0, ret;
1941 struct futex_pi_state *pi_state = NULL;
1942 struct futex_hash_bucket *hb1, *hb2;
1943 struct futex_q *this, *next;
1944 DEFINE_WAKE_Q(wake_q);
1945 u32 curval, targetval;
1946
1947 if (nr_wake < 0 || nr_requeue < 0)
1948 return -EINVAL;
1949
1950 /*
1951 * When PI not supported: return -ENOSYS if requeue_pi is true,
1952 * consequently the compiler knows requeue_pi is always false past
1953 * this point which will optimize away all the conditional code
1954 * further down.
1955 */
1956 if (!IS_ENABLED(CONFIG_FUTEX_PI) && requeue_pi)
1957 return -ENOSYS;
1958
1959 if (requeue_pi) {
1960 /*
1961 * Requeue PI only works on two distinct uaddrs. This
1962 * check is only valid for private futexes. See below.
1963 */
1964 if (uaddr1 == uaddr2)
1965 return -EINVAL;
1966
1967 /*
1968 * requeue_pi requires a pi_state, try to allocate it now
1969 * without any locks in case it fails.
1970 */
1971 if (refill_pi_state_cache())
1972 return -ENOMEM;
1973 /*
1974 * requeue_pi must wake as many tasks as it can, up to nr_wake
1975 * + nr_requeue, since it acquires the rt_mutex prior to
1976 * returning to userspace, so as to not leave the rt_mutex with
1977 * waiters and no owner. However, second and third wake-ups
1978 * cannot be predicted as they involve race conditions with the
1979 * first wake and a fault while looking up the pi_state. Both
1980 * pthread_cond_signal() and pthread_cond_broadcast() should
1981 * use nr_wake=1.
1982 */
1983 if (nr_wake != 1)
1984 return -EINVAL;
1985 }
1986
1987 retry:
1988 ret = get_futex_key(uaddr1, flags & FLAGS_SHARED, &key1, FUTEX_READ);
1989 if (unlikely(ret != 0))
1990 goto out;
1991 ret = get_futex_key(uaddr2, flags & FLAGS_SHARED, &key2,
1992 requeue_pi ? FUTEX_WRITE : FUTEX_READ);
1993 if (unlikely(ret != 0))
1994 goto out_put_key1;
1995
1996 /*
1997 * The check above which compares uaddrs is not sufficient for
1998 * shared futexes. We need to compare the keys:
1999 */
2000 if (requeue_pi && match_futex(&key1, &key2)) {
2001 ret = -EINVAL;
2002 goto out_put_keys;
2003 }
2004
2005 hb1 = hash_futex(&key1);
2006 hb2 = hash_futex(&key2);
2007
2008 retry_private:
2009 hb_waiters_inc(hb2);
2010 double_lock_hb(hb1, hb2);
2011
2012 ret = get_futex_value_locked(&targetval, uaddr2);
2013 if (!ret && likely(cmpval != NULL))
2014 ret = get_futex_value_locked(&curval, uaddr1);
2015
2016 if (unlikely(ret)) {
2017 double_unlock_hb(hb1, hb2);
2018 hb_waiters_dec(hb2);
2019
2020 ret = get_user(targetval, uaddr2);
2021 if (!ret && likely(cmpval != NULL))
2022 ret = get_user(curval, uaddr1);
2023
2024 if (ret)
2025 goto out_put_keys;
2026
2027 if (!(flags & FLAGS_SHARED))
2028 goto retry_private;
2029
2030 put_futex_key(&key2);
2031 put_futex_key(&key1);
2032 goto retry;
2033 }
2034
2035 if (likely(cmpval != NULL) && (curval != *cmpval)) {
2036 ret = -EAGAIN;
2037 goto out_unlock;
2038 }
2039
2040 if (requeue_pi && (task_count - nr_wake < nr_requeue)) {
2041 /*
2042 * Attempt to acquire uaddr2 and wake the top waiter. If we
2043 * intend to requeue waiters, force setting the FUTEX_WAITERS
2044 * bit. We force this here where we are able to easily handle
2045 * faults rather in the requeue loop below.
2046 */
2047 ret = futex_proxy_trylock_atomic(uaddr2, hb1, hb2, &key1,
2048 &key2, &pi_state, nr_requeue);
2049
2050 /*
2051 * At this point the top_waiter has either taken uaddr2 or is
2052 * waiting on it. If the former, then the pi_state will not
2053 * exist yet, look it up one more time to ensure we have a
2054 * reference to it. If the lock was taken, ret contains the
2055 * vpid of the top waiter task.
2056 * If the lock was not taken, we have pi_state and an initial
2057 * refcount on it. In case of an error we have nothing.
2058 */
2059 if (ret > 0) {
2060 WARN_ON(pi_state);
2061 drop_count++;
2062 task_count++;
2063 /*
2064 * If we acquired the lock, then the user space value
2065 * of uaddr2 should be vpid. It cannot be changed by
2066 * the top waiter as it is blocked on hb2 lock if it
2067 * tries to do so. If something fiddled with it behind
2068 * our back the pi state lookup might unearth it. So
2069 * we rather use the known value than rereading and
2070 * handing potential crap to lookup_pi_state.
2071 *
2072 * If that call succeeds then we have pi_state and an
2073 * initial refcount on it.
2074 */
2075 ret = lookup_pi_state(uaddr2, ret, hb2, &key2, &pi_state);
2076 }
2077
2078 switch (ret) {
2079 case 0:
2080 /* We hold a reference on the pi state. */
2081 break;
2082
2083 /* If the above failed, then pi_state is NULL */
2084 case -EFAULT:
2085 double_unlock_hb(hb1, hb2);
2086 hb_waiters_dec(hb2);
2087 put_futex_key(&key2);
2088 put_futex_key(&key1);
2089 ret = fault_in_user_writeable(uaddr2);
2090 if (!ret)
2091 goto retry;
2092 goto out;
2093 case -EAGAIN:
2094 /*
2095 * Two reasons for this:
2096 * - Owner is exiting and we just wait for the
2097 * exit to complete.
2098 * - The user space value changed.
2099 */
2100 double_unlock_hb(hb1, hb2);
2101 hb_waiters_dec(hb2);
2102 put_futex_key(&key2);
2103 put_futex_key(&key1);
2104 cond_resched();
2105 goto retry;
2106 default:
2107 goto out_unlock;
2108 }
2109 }
2110
2111 plist_for_each_entry_safe(this, next, &hb1->chain, list) {
2112 if (task_count - nr_wake >= nr_requeue)
2113 break;
2114
2115 if (!match_futex(&this->key, &key1))
2116 continue;
2117
2118 /*
2119 * FUTEX_WAIT_REQEUE_PI and FUTEX_CMP_REQUEUE_PI should always
2120 * be paired with each other and no other futex ops.
2121 *
2122 * We should never be requeueing a futex_q with a pi_state,
2123 * which is awaiting a futex_unlock_pi().
2124 */
2125 if ((requeue_pi && !this->rt_waiter) ||
2126 (!requeue_pi && this->rt_waiter) ||
2127 this->pi_state) {
2128 ret = -EINVAL;
2129 break;
2130 }
2131
2132 /*
2133 * Wake nr_wake waiters. For requeue_pi, if we acquired the
2134 * lock, we already woke the top_waiter. If not, it will be
2135 * woken by futex_unlock_pi().
2136 */
2137 if (++task_count <= nr_wake && !requeue_pi) {
2138 mark_wake_futex(&wake_q, this);
2139 continue;
2140 }
2141
2142 /* Ensure we requeue to the expected futex for requeue_pi. */
2143 if (requeue_pi && !match_futex(this->requeue_pi_key, &key2)) {
2144 ret = -EINVAL;
2145 break;
2146 }
2147
2148 /*
2149 * Requeue nr_requeue waiters and possibly one more in the case
2150 * of requeue_pi if we couldn't acquire the lock atomically.
2151 */
2152 if (requeue_pi) {
2153 /*
2154 * Prepare the waiter to take the rt_mutex. Take a
2155 * refcount on the pi_state and store the pointer in
2156 * the futex_q object of the waiter.
2157 */
2158 get_pi_state(pi_state);
2159 this->pi_state = pi_state;
2160 ret = rt_mutex_start_proxy_lock(&pi_state->pi_mutex,
2161 this->rt_waiter,
2162 this->task);
2163 if (ret == 1) {
2164 /*
2165 * We got the lock. We do neither drop the
2166 * refcount on pi_state nor clear
2167 * this->pi_state because the waiter needs the
2168 * pi_state for cleaning up the user space
2169 * value. It will drop the refcount after
2170 * doing so.
2171 */
2172 requeue_pi_wake_futex(this, &key2, hb2);
2173 drop_count++;
2174 continue;
2175 } else if (ret) {
2176 /*
2177 * rt_mutex_start_proxy_lock() detected a
2178 * potential deadlock when we tried to queue
2179 * that waiter. Drop the pi_state reference
2180 * which we took above and remove the pointer
2181 * to the state from the waiters futex_q
2182 * object.
2183 */
2184 this->pi_state = NULL;
2185 put_pi_state(pi_state);
2186 /*
2187 * We stop queueing more waiters and let user
2188 * space deal with the mess.
2189 */
2190 break;
2191 }
2192 }
2193 requeue_futex(this, hb1, hb2, &key2);
2194 /*
2195 * Save target uaddr/val, in case futex_wait() wakes
2196 * up spuriously and retries to requeue.
2197 */
> 2198 this->uaddr = uaddr2;
2199 this->val = targetval;
2200 drop_count++;
2201 }
2202
2203 /*
2204 * We took an extra initial reference to the pi_state either
2205 * in futex_proxy_trylock_atomic() or in lookup_pi_state(). We
2206 * need to drop it here again.
2207 */
2208 put_pi_state(pi_state);
2209
2210 out_unlock:
2211 double_unlock_hb(hb1, hb2);
2212 wake_up_q(&wake_q);
2213 hb_waiters_dec(hb2);
2214
2215 /*
2216 * drop_futex_key_refs() must be called outside the spinlocks. During
2217 * the requeue we moved futex_q's from the hash bucket at key1 to the
2218 * one at key2 and updated their key pointer. We no longer need to
2219 * hold the references to key1.
2220 */
2221 while (--drop_count >= 0)
2222 drop_futex_key_refs(&key1);
2223
2224 out_put_keys:
2225 put_futex_key(&key2);
2226 out_put_key1:
2227 put_futex_key(&key1);
2228 out:
2229 return ret ? ret : task_count;
2230 }
2231
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org Intel Corporation
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2019-11-12 2:36 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-11-06 22:43 [RFC PATCH] futex: don't retry futex_wait() with stale uaddr/val after spurious wakeup Jan Stancek
2019-11-07 11:11 ` Thomas Gleixner
2019-11-07 13:16 ` Jan Stancek
2019-11-08 23:27 ` kbuild test robot
2019-11-12 2:36 ` kbuild test robot
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.