Hi "André,
[FYI, it's a private test report for your RFC patch.]
[auto build test WARNING on tip/locking/core]
[also build test WARNING on tip/x86/asm arm64/for-next/core tip/perf/core linus/master
v5.11]
[cannot apply to next-20210216]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]
url:
https://github.com/0day-ci/linux/commits/Andr-Almeida/Add-futex2-syscalls...
base:
https://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git
3765d01bab73bdb920ef711203978f02cd26e4da
config: x86_64-randconfig-s022-20210215 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-15) 9.3.0
reproduce:
# apt-get install sparse
# sparse version: v0.6.3-215-g0fb77bb6-dirty
#
https://github.com/0day-ci/linux/commit/e6093387f473950baee3fada6d63ff846...
git remote add linux-review
https://github.com/0day-ci/linux
git fetch --no-tags linux-review Andr-Almeida/Add-futex2-syscalls/20210215-233004
git checkout e6093387f473950baee3fada6d63ff84621c5463
# save the attached .config to linux build tree
make W=1 C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' ARCH=x86_64
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp(a)intel.com>
"sparse warnings: (new ones prefixed by >>)"
kernel/futex2.c:111:21: sparse: sparse: symbol 'futex_table' was not declared.
Should it be static?
kernel/futex2.c:112:14: sparse: sparse: symbol 'futex2_hashsize' was not
declared. Should it be static?
kernel/futex2.c:358:13: sparse: sparse: incorrect type in argument 1 (different base
types) @@ expected void const volatile [noderef] __user *ptr @@ got unsigned long
[usertype] address @@
kernel/futex2.c:358:13: sparse: expected void const volatile [noderef] __user *ptr
kernel/futex2.c:358:13: sparse: got unsigned long [usertype] address
kernel/futex2.c:517:51: sparse: sparse: incorrect type in argument 1 (different address
spaces) @@ expected void [noderef] __user *uaddr @@ got void * @@
kernel/futex2.c:517:51: sparse: expected void [noderef] __user *uaddr
kernel/futex2.c:517:51: sparse: got void *
kernel/futex2.c:532:45: sparse: sparse: incorrect type in argument 2 (different address
spaces) @@ expected unsigned int [noderef] [usertype] __user *uaddr @@ got
unsigned int [usertype] *[assigned] uaddr @@
kernel/futex2.c:532:45: sparse: expected unsigned int [noderef] [usertype] __user
*uaddr
kernel/futex2.c:532:45: sparse: got unsigned int [usertype] *[assigned] uaddr
kernel/futex2.c:541:29: sparse: sparse: incorrect type in argument 1 (different address
spaces) @@ expected void const volatile [noderef] __user *ptr @@ got unsigned int
[usertype] *[assigned] uaddr @@
kernel/futex2.c:541:29: sparse: expected void const volatile [noderef] __user *ptr
kernel/futex2.c:541:29: sparse: got unsigned int [usertype] *[assigned] uaddr
kernel/futex2.c:828:48: sparse: sparse: incorrect type in argument 1 (different address
spaces) @@ expected void [noderef] __user *uaddr @@ got void *[addressable] uaddr
@@
kernel/futex2.c:828:48: sparse: expected void [noderef] __user *uaddr
kernel/futex2.c:828:48: sparse: got void *[addressable] uaddr
kernel/futex2.c:1115:19: sparse: sparse: incorrect type in assignment (different
address spaces) @@ expected void *uaddr @@ got void [noderef] __user * @@
kernel/futex2.c:1115:19: sparse: expected void *uaddr
kernel/futex2.c:1115:19: sparse: got void [noderef] __user *
> kernel/futex2.c:884:57: sparse: sparse: cast removes address
space '__user' of expression
> kernel/futex2.c:884:57: sparse: sparse: incorrect type in argument 2 (different
address spaces) @@ expected struct compat_futex_waitv [noderef] __user *uwaitv @@
got struct compat_futex_waitv * @@
kernel/futex2.c:884:57: sparse: expected
struct compat_futex_waitv [noderef] __user *uwaitv
kernel/futex2.c:884:57: sparse: got struct compat_futex_waitv *
kernel/futex2.c:993:13: sparse: sparse: context imbalance in
'futex_double_unlock' - unexpected unlock
kernel/futex2.c:1012:34: sparse: sparse: incorrect type in argument 1 (different
address spaces) @@ expected void [noderef] __user *uaddr @@ got void *uaddr @@
kernel/futex2.c:1012:34: sparse: expected void [noderef] __user *uaddr
kernel/futex2.c:1012:34: sparse: got void *uaddr
kernel/futex2.c:1016:34: sparse: sparse: incorrect type in argument 1 (different
address spaces) @@ expected void [noderef] __user *uaddr @@ got void *uaddr @@
kernel/futex2.c:1016:34: sparse: expected void [noderef] __user *uaddr
kernel/futex2.c:1016:34: sparse: got void *uaddr
kernel/futex2.c:1022:42: sparse: sparse: incorrect type in argument 1 (different
address spaces) @@ expected void [noderef] __user *uaddr @@ got void *uaddr @@
kernel/futex2.c:1022:42: sparse: expected void [noderef] __user *uaddr
kernel/futex2.c:1022:42: sparse: got void *uaddr
kernel/futex2.c:1028:42: sparse: sparse: incorrect type in argument 1 (different
address spaces) @@ expected void [noderef] __user *uaddr @@ got void *uaddr @@
kernel/futex2.c:1028:42: sparse: expected void [noderef] __user *uaddr
kernel/futex2.c:1028:42: sparse: got void *uaddr
kernel/futex2.c:1047:40: sparse: sparse: incorrect type in argument 2 (different
address spaces) @@ expected unsigned int [noderef] [usertype] __user *uaddr @@ got
void *uaddr @@
kernel/futex2.c:1047:40: sparse: expected unsigned int [noderef] [usertype] __user
*uaddr
kernel/futex2.c:1047:40: sparse: got void *uaddr
kernel/futex2.c:1051:21: sparse: sparse: incorrect type in argument 1 (different
address spaces) @@ expected void const volatile [noderef] __user *ptr @@ got
unsigned int [usertype] *[noderef] __user @@
kernel/futex2.c:1051:21: sparse: expected void const volatile [noderef] __user
*ptr
kernel/futex2.c:1051:21: sparse: got unsigned int [usertype] *[noderef] __user
kernel/futex2.c:1000:19: sparse: sparse: context imbalance in
'__se_compat_sys_futex_requeue' - different lock contexts for basic block
kernel/futex2.c:1199:57: sparse: sparse: cast removes address space '__user' of
expression
> kernel/futex2.c:1199:57: sparse: sparse: incorrect type in
argument 2 (different address spaces) @@ expected struct compat_futex_requeue
[noderef] __user *uaddr @@ got struct compat_futex_requeue * @@
kernel/futex2.c:1199:57: sparse: expected struct compat_futex_requeue [noderef] __user
*uaddr
kernel/futex2.c:1199:57: sparse: got struct compat_futex_requeue *
kernel/futex2.c:1204:57: sparse: sparse: cast removes address space '__user' of
expression
kernel/futex2.c:1204:57: sparse: sparse: incorrect type in argument 2 (different
address spaces) @@ expected struct compat_futex_requeue [noderef] __user *uaddr @@
got struct compat_futex_requeue * @@
kernel/futex2.c:1204:57: sparse: expected struct compat_futex_requeue [noderef]
__user *uaddr
kernel/futex2.c:1204:57: sparse: got struct compat_futex_requeue *
kernel/futex2.c:1012:34: sparse: sparse: incorrect type in argument 1 (different
address spaces) @@ expected void [noderef] __user *uaddr @@ got void *uaddr @@
kernel/futex2.c:1012:34: sparse: expected void [noderef] __user *uaddr
kernel/futex2.c:1012:34: sparse: got void *uaddr
kernel/futex2.c:1016:34: sparse: sparse: incorrect type in argument 1 (different
address spaces) @@ expected void [noderef] __user *uaddr @@ got void *uaddr @@
kernel/futex2.c:1016:34: sparse: expected void [noderef] __user *uaddr
kernel/futex2.c:1016:34: sparse: got void *uaddr
kernel/futex2.c:1022:42: sparse: sparse: incorrect type in argument 1 (different
address spaces) @@ expected void [noderef] __user *uaddr @@ got void *uaddr @@
kernel/futex2.c:1022:42: sparse: expected void [noderef] __user *uaddr
kernel/futex2.c:1022:42: sparse: got void *uaddr
kernel/futex2.c:1028:42: sparse: sparse: incorrect type in argument 1 (different
address spaces) @@ expected void [noderef] __user *uaddr @@ got void *uaddr @@
kernel/futex2.c:1028:42: sparse: expected void [noderef] __user *uaddr
kernel/futex2.c:1028:42: sparse: got void *uaddr
kernel/futex2.c:1047:40: sparse: sparse: incorrect type in argument 2 (different
address spaces) @@ expected unsigned int [noderef] [usertype] __user *uaddr @@ got
void *uaddr @@
kernel/futex2.c:1047:40: sparse: expected unsigned int [noderef] [usertype] __user
*uaddr
kernel/futex2.c:1047:40: sparse: got void *uaddr
kernel/futex2.c:1051:21: sparse: sparse: incorrect type in argument 1 (different
address spaces) @@ expected void const volatile [noderef] __user *ptr @@ got
unsigned int [usertype] *[noderef] __user @@
kernel/futex2.c:1051:21: sparse: expected void const volatile [noderef] __user
*ptr
kernel/futex2.c:1051:21: sparse: got unsigned int [usertype] *[noderef] __user
kernel/futex2.c:1000:19: sparse: sparse: context imbalance in
'__se_sys_futex_requeue' - different lock contexts for basic block
vim +/__user +884 kernel/futex2.c
841
842 /**
843 * sys_futex_waitv - Wait on a list of futexes
844 * @waiters: List of futexes to wait on
845 * @nr_futexes: Length of futexv
846 * @flags: Flag for timeout (monotonic/realtime)
847 * @timo: Optional absolute timeout.
848 *
849 * Given an array of `struct futex_waitv`, wait on each uaddr. The thread wakes
850 * if a futex_wake() is performed at any uaddr. The syscall returns immediately
851 * if any waiter has *uaddr != val. *timo is an optional timeout value for the
852 * operation. Each waiter has individual flags. The `flags` argument for the
853 * syscall should be used solely for specifying the timeout as realtime, if
854 * needed. Flags for shared futexes, sizes, etc. should be used on the
855 * individual flags of each waiter.
856 *
857 * Returns the array index of one of the awaken futexes. There's no given
858 * information of how many were awakened, or any particular attribute of it (if
859 * it's the first awakened, if it is of the smaller index...).
860 */
861 SYSCALL_DEFINE4(futex_waitv, struct futex_waitv __user *, waiters,
862 unsigned int, nr_futexes, unsigned int, flags,
863 struct __kernel_timespec __user *, timo)
864 {
865 struct futexv_head *futexv;
866 int ret;
867
868 if (flags & ~FUTEXV_MASK)
869 return -EINVAL;
870
871 if (!nr_futexes || nr_futexes > FUTEX_WAITV_MAX || !waiters)
872 return -EINVAL;
873
874 futexv = kmalloc((sizeof(struct futex_waiter) * nr_futexes) +
875 sizeof(*futexv), GFP_KERNEL);
876 if (!futexv)
877 return -ENOMEM;
878
879 futexv->hint = false;
880 futexv->task = current;
881
882 #ifdef CONFIG_X86_X32_ABI
883 if (in_x32_syscall()) {
884 ret = compat_futex_parse_waitv(futexv, (struct
compat_futex_waitv *)waiters,
885 nr_futexes);
886 } else
887 #endif
888 {
889 ret = futex_parse_waitv(futexv, waiters, nr_futexes);
890 }
891
892 if (!ret)
893 ret = futex_set_timer_and_wait(futexv, nr_futexes, timo, flags);
894
895 kfree(futexv);
896
897 return ret;
898 }
899
900 /**
901 * futex_get_parent - For a given futex in a futexv list, get a pointer to the
futexv
902 * @waiter: Address of futex in the list
903 * @index: Index of futex in the list
904 *
905 * Return: A pointer to its futexv struct
906 */
907 static inline struct futexv_head *futex_get_parent(uintptr_t waiter,
908 unsigned int index)
909 {
910 uintptr_t parent = waiter - sizeof(struct futexv_head)
911 - (uintptr_t)(index * sizeof(struct futex_waiter));
912
913 return (struct futexv_head *)parent;
914 }
915
916 /**
917 * futex_mark_wake - Find the task to be wake and add it in wake queue
918 * @waiter: Waiter to be wake
919 * @bucket: Bucket to be decremented
920 * @wake_q: Wake queue to insert the task
921 */
922 static void futex_mark_wake(struct futex_waiter *waiter,
923 struct futex_bucket *bucket,
924 struct wake_q_head *wake_q)
925 {
926 struct task_struct *task;
927 struct futexv_head *parent = futex_get_parent((uintptr_t)waiter,
928 waiter->index);
929
930 parent->hint = true;
931 task = parent->task;
932 get_task_struct(task);
933 list_del_init_careful(&waiter->list);
934 wake_q_add_safe(wake_q, task);
935 bucket_dec_waiters(bucket);
936 }
937
938 static inline bool futex_match(struct futex_key key1, struct futex_key key2)
939 {
940 return (key1.index == key2.index &&
941 key1.pointer == key2.pointer &&
942 key1.offset == key2.offset);
943 }
944
945 /**
946 * sys_futex_wake - Wake a number of futexes waiting on an address
947 * @uaddr: Address of futex to be woken up
948 * @nr_wake: Number of futexes waiting in uaddr to be woken up
949 * @flags: Flags for size and shared
950 *
951 * Wake `nr_wake` threads waiting at uaddr.
952 *
953 * Returns the number of woken threads on success, error code otherwise.
954 */
955 SYSCALL_DEFINE3(futex_wake, void __user *, uaddr, unsigned int, nr_wake,
956 unsigned int, flags)
957 {
958 bool shared = (flags & FUTEX_SHARED_FLAG) ? true : false;
959 unsigned int size = flags & FUTEX_SIZE_MASK;
960 struct futex_waiter waiter, *aux, *tmp;
961 struct futex_bucket *bucket;
962 DEFINE_WAKE_Q(wake_q);
963 int ret = 0;
964
965 if (flags & ~FUTEX2_MASK)
966 return -EINVAL;
967
968 if (size != FUTEX_32)
969 return -EINVAL;
970
971 bucket = futex_get_bucket(uaddr, &waiter.key, shared);
972 if (IS_ERR(bucket))
973 return PTR_ERR(bucket);
974
975 if (!bucket_get_waiters(bucket) || !nr_wake)
976 return 0;
977
978 spin_lock(&bucket->lock);
979 list_for_each_entry_safe(aux, tmp, &bucket->list, list) {
980 if (futex_match(waiter.key, aux->key)) {
981 futex_mark_wake(aux, bucket, &wake_q);
982 if (++ret >= nr_wake)
983 break;
984 }
985 }
986 spin_unlock(&bucket->lock);
987
988 wake_up_q(&wake_q);
989
990 return ret;
991 }
992
993 static void futex_double_unlock(struct futex_bucket *b1, struct futex_bucket *b2)
994 {
995 spin_unlock(&b1->lock);
996 if (b1 != b2)
997 spin_unlock(&b2->lock);
998 }
999
1000 static inline int __futex_requeue(struct futex_requeue rq1,
1001 struct futex_requeue rq2, unsigned int nr_wake,
1002 unsigned int nr_requeue, unsigned int cmpval,
1003 bool shared1, bool shared2)
1004 {
1005 struct futex_waiter w1, w2, *aux, *tmp;
1006 bool retry = false;
1007 struct futex_bucket *b1, *b2;
1008 DEFINE_WAKE_Q(wake_q);
1009 u32 uval;
1010 int ret;
1011
1012 b1 = futex_get_bucket(rq1.uaddr, &w1.key, shared1);
1013 if (IS_ERR(b1))
1014 return PTR_ERR(b1);
1015
1016 b2 = futex_get_bucket(rq2.uaddr, &w2.key, shared2);
1017 if (IS_ERR(b2))
1018 return PTR_ERR(b2);
1019
1020 retry:
1021 if (shared1 && retry) {
1022 b1 = futex_get_bucket(rq1.uaddr, &w1.key, shared1);
1023 if (IS_ERR(b1))
1024 return PTR_ERR(b1);
1025 }
1026
1027 if (shared2 && retry) {
1028 b2 = futex_get_bucket(rq2.uaddr, &w2.key, shared2);
1029 if (IS_ERR(b2))
1030 return PTR_ERR(b2);
1031 }
1032
1033 bucket_inc_waiters(b2);
1034 /*
1035 * To ensure the locks are taken in the same order for all threads (and
1036 * thus avoiding deadlocks), take the "smaller" one first
1037 */
1038 if (b1 <= b2) {
1039 spin_lock(&b1->lock);
1040 if (b1 < b2)
1041 spin_lock_nested(&b2->lock, SINGLE_DEPTH_NESTING);
1042 } else {
1043 spin_lock(&b2->lock);
1044 spin_lock_nested(&b1->lock, SINGLE_DEPTH_NESTING);
1045 }
1046
1047 ret = futex_get_user(&uval, rq1.uaddr);
1048
1049 if (unlikely(ret)) {
1050 futex_double_unlock(b1, b2);
1051 if (__get_user(uval, (u32 * __user)rq1.uaddr))
1052 return -EFAULT;
1053
1054 bucket_dec_waiters(b2);
1055 retry = true;
1056 goto retry;
1057 }
1058
1059 if (uval != cmpval) {
1060 futex_double_unlock(b1, b2);
1061
1062 bucket_dec_waiters(b2);
1063 return -EAGAIN;
1064 }
1065
1066 list_for_each_entry_safe(aux, tmp, &b1->list, list) {
1067 if (futex_match(w1.key, aux->key)) {
1068 if (ret < nr_wake) {
1069 futex_mark_wake(aux, b1, &wake_q);
1070 ret++;
1071 continue;
1072 }
1073
1074 if (ret >= nr_wake + nr_requeue)
1075 break;
1076
1077 aux->key.pointer = w2.key.pointer;
1078 aux->key.index = w2.key.index;
1079 aux->key.offset = w2.key.offset;
1080
1081 if (b1 != b2) {
1082 list_del_init_careful(&aux->list);
1083 bucket_dec_waiters(b1);
1084
1085 list_add_tail(&aux->list, &b2->list);
1086 bucket_inc_waiters(b2);
1087 }
1088 ret++;
1089 }
1090 }
1091
1092 futex_double_unlock(b1, b2);
1093 wake_up_q(&wake_q);
1094 bucket_dec_waiters(b2);
1095
1096 return ret;
1097 }
1098
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org