Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'rcu/misc' into next

- In order to prepare the layout for nohz_full work deferral to
user exit, the context tracking state must shrink the counter
of transitions to/from RCU not watching. The only possible hazard
is to trigger wrap-around more easily, delaying a bit grace periods
when that happens. This should be a rare event though. Yet add
debugging and torture code to test that assumption.

- Fix memory leak on locktorture module

- Annotate accesses in rculist_nulls.h to prevent from KCSAN warnings.
On recent discussions, we also concluded that all those WRITE_ONCE()
and READ_ONCE() on list APIs deserve appropriate comments. Something
to be expected for the next cycle.

- Provide a script to apply several configs to several commits with torture.

- Allow torture to reuse a build directory in order to save needless
rebuild time.

- Various cleanups.

+219 -31
+37 -7
include/linux/context_tracking_state.h
··· 18 18 CT_STATE_MAX = 4, 19 19 }; 20 20 21 - /* Odd value for watching, else even. */ 22 - #define CT_RCU_WATCHING CT_STATE_MAX 23 - 24 - #define CT_STATE_MASK (CT_STATE_MAX - 1) 25 - #define CT_RCU_WATCHING_MASK (~CT_STATE_MASK) 26 - 27 21 struct context_tracking { 28 22 #ifdef CONFIG_CONTEXT_TRACKING_USER 29 23 /* ··· 38 44 #endif 39 45 }; 40 46 47 + /* 48 + * We cram two different things within the same atomic variable: 49 + * 50 + * CT_RCU_WATCHING_START CT_STATE_START 51 + * | | 52 + * v v 53 + * MSB [ RCU watching counter ][ context_state ] LSB 54 + * ^ ^ 55 + * | | 56 + * CT_RCU_WATCHING_END CT_STATE_END 57 + * 58 + * Bits are used from the LSB upwards, so unused bits (if any) will always be in 59 + * upper bits of the variable. 60 + */ 41 61 #ifdef CONFIG_CONTEXT_TRACKING 62 + #define CT_SIZE (sizeof(((struct context_tracking *)0)->state) * BITS_PER_BYTE) 63 + 64 + #define CT_STATE_WIDTH bits_per(CT_STATE_MAX - 1) 65 + #define CT_STATE_START 0 66 + #define CT_STATE_END (CT_STATE_START + CT_STATE_WIDTH - 1) 67 + 68 + #define CT_RCU_WATCHING_MAX_WIDTH (CT_SIZE - CT_STATE_WIDTH) 69 + #define CT_RCU_WATCHING_WIDTH (IS_ENABLED(CONFIG_RCU_DYNTICKS_TORTURE) ? 2 : CT_RCU_WATCHING_MAX_WIDTH) 70 + #define CT_RCU_WATCHING_START (CT_STATE_END + 1) 71 + #define CT_RCU_WATCHING_END (CT_RCU_WATCHING_START + CT_RCU_WATCHING_WIDTH - 1) 72 + #define CT_RCU_WATCHING BIT(CT_RCU_WATCHING_START) 73 + 74 + #define CT_STATE_MASK GENMASK(CT_STATE_END, CT_STATE_START) 75 + #define CT_RCU_WATCHING_MASK GENMASK(CT_RCU_WATCHING_END, CT_RCU_WATCHING_START) 76 + 77 + #define CT_UNUSED_WIDTH (CT_RCU_WATCHING_MAX_WIDTH - CT_RCU_WATCHING_WIDTH) 78 + 79 + static_assert(CT_STATE_WIDTH + 80 + CT_RCU_WATCHING_WIDTH + 81 + CT_UNUSED_WIDTH == 82 + CT_SIZE); 83 + 42 84 DECLARE_PER_CPU(struct context_tracking, context_tracking); 43 - #endif 85 + #endif /* CONFIG_CONTEXT_TRACKING */ 44 86 45 87 #ifdef CONFIG_CONTEXT_TRACKING_USER 46 88 static __always_inline int __ct_state(void)
+3 -3
include/linux/rculist_nulls.h
··· 138 138 139 139 if (last) { 140 140 WRITE_ONCE(n->next, last->next); 141 - n->pprev = &last->next; 141 + WRITE_ONCE(n->pprev, &last->next); 142 142 rcu_assign_pointer(hlist_nulls_next_rcu(last), n); 143 143 } else { 144 144 hlist_nulls_add_head_rcu(n, h); ··· 148 148 /* after that hlist_nulls_del will work */ 149 149 static inline void hlist_nulls_add_fake(struct hlist_nulls_node *n) 150 150 { 151 - n->pprev = &n->next; 152 - n->next = (struct hlist_nulls_node *)NULLS_MARKER(NULL); 151 + WRITE_ONCE(n->pprev, &n->next); 152 + WRITE_ONCE(n->next, (struct hlist_nulls_node *)NULLS_MARKER(NULL)); 153 153 } 154 154 155 155 /**
+6 -2
kernel/locking/locktorture.c
··· 103 103 .get = param_get_cpumask, 104 104 }; 105 105 106 - module_param_cb(bind_readers, &lt_bind_ops, &bind_readers, 0644); 107 - module_param_cb(bind_writers, &lt_bind_ops, &bind_writers, 0644); 106 + module_param_cb(bind_readers, &lt_bind_ops, &bind_readers, 0444); 107 + module_param_cb(bind_writers, &lt_bind_ops, &bind_writers, 0444); 108 108 109 109 long torture_sched_setaffinity(pid_t pid, const struct cpumask *in_mask, bool dowarn); 110 110 ··· 1211 1211 cxt.cur_ops->exit(); 1212 1212 cxt.init_called = false; 1213 1213 } 1214 + 1215 + free_cpumask_var(bind_readers); 1216 + free_cpumask_var(bind_writers); 1217 + 1214 1218 torture_cleanup_end(); 1215 1219 } 1216 1220
+15
kernel/rcu/Kconfig.debug
··· 213 213 when looking for certain types of RCU usage bugs, for example, 214 214 too-short RCU read-side critical sections. 215 215 216 + 217 + config RCU_DYNTICKS_TORTURE 218 + bool "Minimize RCU dynticks counter size" 219 + depends on RCU_EXPERT && !COMPILE_TEST 220 + default n 221 + help 222 + This option sets the width of the dynticks counter to its 223 + minimum usable value. This minimum width greatly increases 224 + the probability of flushing out bugs involving counter wrap, 225 + but it also increases the probability of extending grace period 226 + durations. This Kconfig option should therefore be avoided in 227 + production due to the consequent increased probability of OOMs. 228 + 229 + This has no value for production and is only for testing. 230 + 216 231 endmenu # "RCU Debugging"
+1 -3
kernel/rcu/rcutorture.c
··· 2438 2438 newstate = rcutorture_extend_mask(rtors.readstate, trsp); 2439 2439 WARN_ON_ONCE(newstate & RCUTORTURE_RDR_UPDOWN); 2440 2440 rcutorture_one_extend(&rtors.readstate, newstate, trsp, rtors.rtrsp++); 2441 - if (!rcu_torture_one_read_start(&rtors, trsp, myid)) { 2442 - rcutorture_one_extend(&rtors.readstate, 0, trsp, rtors.rtrsp); 2441 + if (!rcu_torture_one_read_start(&rtors, trsp, myid)) 2443 2442 return false; 2444 - } 2445 2443 rtors.rtrsp = rcutorture_loop_extend(&rtors.readstate, trsp, rtors.rtrsp); 2446 2444 rcu_torture_one_read_end(&rtors, trsp); 2447 2445 return true;
+40 -16
tools/testing/selftests/rcutorture/bin/kvm-again.sh
··· 31 31 if ! cp "$oldrun/scenarios" $T/scenarios.oldrun 32 32 then 33 33 # Later on, can reconstitute this from console.log files. 34 - echo Prior run batches file does not exist: $oldrun/batches 34 + echo Prior run scenarios file does not exist: $oldrun/scenarios 35 35 exit 1 36 36 fi 37 37 ··· 68 68 echo " --datestamp string" 69 69 echo " --dryrun" 70 70 echo " --duration minutes | <seconds>s | <hours>h | <days>d" 71 - echo " --link hard|soft|copy" 71 + echo " --link hard|soft|copy|inplace|inplace-force" 72 72 echo " --remote" 73 73 echo " --rundir /new/res/path" 74 74 echo "Command line: $scriptname $args" ··· 121 121 shift 122 122 ;; 123 123 --link) 124 - checkarg --link "hard|soft|copy" "$#" "$2" 'hard\|soft\|copy' '^--' 124 + checkarg --link "hard|soft|copy|inplace|inplace-force" "$#" "$2" 'hard\|soft\|copy\|inplace\|inplace-force' '^--' 125 125 case "$2" in 126 126 copy) 127 127 arg_link="cp -R" ··· 131 131 ;; 132 132 soft) 133 133 arg_link="cp -Rs" 134 + ;; 135 + inplace) 136 + arg_link="inplace" 137 + rundir="$oldrun" 138 + ;; 139 + inplace-force) 140 + arg_link="inplace-force" 141 + rundir="$oldrun" 134 142 ;; 135 143 esac 136 144 shift ··· 180 172 181 173 echo ---- Re-run results directory: $rundir 182 174 183 - # Copy old run directory tree over and adjust. 184 - mkdir -p "`dirname "$rundir"`" 185 - if ! $arg_link "$oldrun" "$rundir" 175 + if test "$oldrun" != "$rundir" 186 176 then 187 - echo "Cannot copy from $oldrun to $rundir." 188 - usage 177 + # Copy old run directory tree over and adjust. 178 + mkdir -p "`dirname "$rundir"`" 179 + if ! $arg_link "$oldrun" "$rundir" 180 + then 181 + echo "Cannot copy from $oldrun to $rundir." 182 + usage 183 + fi 184 + rm -f "$rundir"/*/{console.log,console.log.diags,qemu_pid,qemu-pid,qemu-retval,Warnings,kvm-test-1-run.sh.out,kvm-test-1-run-qemu.sh.out,vmlinux} "$rundir"/log 185 + touch "$rundir/log" 186 + echo $scriptname $args | tee -a "$rundir/log" 187 + echo $oldrun > "$rundir/re-run" 188 + if ! test -d "$rundir/../../bin" 189 + then 190 + $arg_link "$oldrun/../../bin" "$rundir/../.." 191 + fi 192 + else 193 + # Check for a run having already happened. 194 + find "$rundir" -name console.log -print > $T/oldrun-console.log 195 + if test -s $T/oldrun-console.log 196 + then 197 + echo Run already took place in $rundir 198 + if test "$arg_link" = inplace 199 + then 200 + usage 201 + fi 202 + fi 189 203 fi 190 - rm -f "$rundir"/*/{console.log,console.log.diags,qemu_pid,qemu-pid,qemu-retval,Warnings,kvm-test-1-run.sh.out,kvm-test-1-run-qemu.sh.out,vmlinux} "$rundir"/log 191 - touch "$rundir/log" 192 - echo $scriptname $args | tee -a "$rundir/log" 193 - echo $oldrun > "$rundir/re-run" 194 - if ! test -d "$rundir/../../bin" 195 - then 196 - $arg_link "$oldrun/../../bin" "$rundir/../.." 197 - fi 204 + 205 + # Find runs to be done based on their qemu-cmd files. 198 206 for i in $rundir/*/qemu-cmd 199 207 do 200 208 cp "$i" $T
+116
tools/testing/selftests/rcutorture/bin/kvm-series.sh
··· 1 + #!/bin/bash 2 + # SPDX-License-Identifier: GPL-2.0+ 3 + # 4 + # Usage: kvm-series.sh config-list commit-id-list [ kvm.sh parameters ] 5 + # 6 + # Tests the specified list of unadorned configs ("TREE01 SRCU-P" but not 7 + # "CFLIST" or "3*TRACE01") and an indication of a set of commits to test, 8 + # then runs each commit through the specified list of commits using kvm.sh. 9 + # The runs are grouped into a -series/config/commit directory tree. 10 + # Each run defaults to a duration of one minute. 11 + # 12 + # Run in top-level Linux source directory. Please note that this is in 13 + # no way a replacement for "git bisect"!!! 14 + # 15 + # This script is intended to replace kvm-check-branches.sh by providing 16 + # ease of use and faster execution. 17 + 18 + T="`mktemp -d ${TMPDIR-/tmp}/kvm-series.sh.XXXXXX`" 19 + trap 'rm -rf $T' 0 20 + 21 + scriptname=$0 22 + args="$*" 23 + 24 + config_list="${1}" 25 + if test -z "${config_list}" 26 + then 27 + echo "$0: Need a quoted list of --config arguments for first argument." 28 + exit 1 29 + fi 30 + if test -z "${config_list}" || echo "${config_list}" | grep -q '\*' 31 + then 32 + echo "$0: Repetition ('*') not allowed in config list." 33 + exit 1 34 + fi 35 + 36 + commit_list="${2}" 37 + if test -z "${commit_list}" 38 + then 39 + echo "$0: Need a list of commits (e.g., HEAD^^^..) for second argument." 40 + exit 2 41 + fi 42 + git log --pretty=format:"%h" "${commit_list}" > $T/commits 43 + ret=$? 44 + if test "${ret}" -ne 0 45 + then 46 + echo "$0: Invalid commit list ('${commit_list}')." 47 + exit 2 48 + fi 49 + sha1_list=`cat $T/commits` 50 + 51 + shift 52 + shift 53 + 54 + RCUTORTURE="`pwd`/tools/testing/selftests/rcutorture"; export RCUTORTURE 55 + PATH=${RCUTORTURE}/bin:$PATH; export PATH 56 + . functions.sh 57 + 58 + ret=0 59 + nfail=0 60 + nsuccess=0 61 + faillist= 62 + successlist= 63 + cursha1="`git rev-parse --abbrev-ref HEAD`" 64 + ds="`date +%Y.%m.%d-%H.%M.%S`-series" 65 + startdate="`date`" 66 + starttime="`get_starttime`" 67 + 68 + echo " --- " $scriptname $args | tee -a $T/log 69 + echo " --- Results directory: " $ds | tee -a $T/log 70 + 71 + for config in ${config_list} 72 + do 73 + sha_n=0 74 + for sha in ${sha1_list} 75 + do 76 + sha1=${sha_n}.${sha} # Enable "sort -k1nr" to list commits in order. 77 + echo Starting ${config}/${sha1} at `date` | tee -a $T/log 78 + git checkout "${sha}" 79 + time tools/testing/selftests/rcutorture/bin/kvm.sh --configs "$config" --datestamp "$ds/${config}/${sha1}" --duration 1 "$@" 80 + curret=$? 81 + if test "${curret}" -ne 0 82 + then 83 + nfail=$((nfail+1)) 84 + faillist="$faillist ${config}/${sha1}(${curret})" 85 + else 86 + nsuccess=$((nsuccess+1)) 87 + successlist="$successlist ${config}/${sha1}" 88 + # Successful run, so remove large files. 89 + rm -f ${RCUTORTURE}/$ds/${config}/${sha1}/{vmlinux,bzImage,System.map,Module.symvers} 90 + fi 91 + if test "${ret}" -eq 0 92 + then 93 + ret=${curret} 94 + fi 95 + sha_n=$((sha_n+1)) 96 + done 97 + done 98 + git checkout "${cursha1}" 99 + 100 + echo ${nsuccess} SUCCESSES: | tee -a $T/log 101 + echo ${successlist} | fmt | tee -a $T/log 102 + echo | tee -a $T/log 103 + echo ${nfail} FAILURES: | tee -a $T/log 104 + echo ${faillist} | fmt | tee -a $T/log 105 + if test -n "${faillist}" 106 + then 107 + echo | tee -a $T/log 108 + echo Failures across commits: | tee -a $T/log 109 + echo ${faillist} | tr ' ' '\012' | sed -e 's,^[^/]*/,,' -e 's/([0-9]*)//' | 110 + sort | uniq -c | sort -k2n | tee -a $T/log 111 + fi 112 + echo Started at $startdate, ended at `date`, duration `get_starttime_duration $starttime`. | tee -a $T/log 113 + echo Summary: Successes: ${nsuccess} Failures: ${nfail} | tee -a $T/log 114 + cp $T/log tools/testing/selftests/rcutorture/res/${ds} 115 + 116 + exit "${ret}"
+1
tools/testing/selftests/rcutorture/configs/rcu/TREE04
··· 16 16 CONFIG_RCU_EXPERT=y 17 17 CONFIG_RCU_EQS_DEBUG=y 18 18 CONFIG_RCU_LAZY=y 19 + CONFIG_RCU_DYNTICKS_TORTURE=y