@@ -1862,8 +1862,13 @@ struct migration_arg {
1862
1862
struct set_affinity_pending * pending ;
1863
1863
};
1864
1864
1865
+ /*
1866
+ * @refs: number of wait_for_completion()
1867
+ * @stop_pending: is @stop_work in use
1868
+ */
1865
1869
struct set_affinity_pending {
1866
1870
refcount_t refs ;
1871
+ unsigned int stop_pending ;
1867
1872
struct completion done ;
1868
1873
struct cpu_stop_work stop_work ;
1869
1874
struct migration_arg arg ;
@@ -1898,8 +1903,8 @@ static struct rq *__migrate_task(struct rq *rq, struct rq_flags *rf,
1898
1903
*/
1899
1904
static int migration_cpu_stop (void * data )
1900
1905
{
1901
- struct set_affinity_pending * pending ;
1902
1906
struct migration_arg * arg = data ;
1907
+ struct set_affinity_pending * pending = arg -> pending ;
1903
1908
struct task_struct * p = arg -> task ;
1904
1909
int dest_cpu = arg -> dest_cpu ;
1905
1910
struct rq * rq = this_rq ();
@@ -1921,7 +1926,6 @@ static int migration_cpu_stop(void *data)
1921
1926
raw_spin_lock (& p -> pi_lock );
1922
1927
rq_lock (rq , & rf );
1923
1928
1924
- pending = p -> migration_pending ;
1925
1929
/*
1926
1930
* If task_rq(p) != rq, it cannot be migrated here, because we're
1927
1931
* holding rq->lock, if p->on_rq == 0 it cannot get enqueued because
@@ -1932,21 +1936,14 @@ static int migration_cpu_stop(void *data)
1932
1936
goto out ;
1933
1937
1934
1938
if (pending ) {
1935
- p -> migration_pending = NULL ;
1939
+ if (p -> migration_pending == pending )
1940
+ p -> migration_pending = NULL ;
1936
1941
complete = true;
1937
1942
}
1938
1943
1939
- /* migrate_enable() -- we must not race against SCA */
1940
1944
if (dest_cpu < 0 ) {
1941
- /*
1942
- * When this was migrate_enable() but we no longer
1943
- * have a @pending, a concurrent SCA 'fixed' things
1944
- * and we should be valid again. Nothing to do.
1945
- */
1946
- if (!pending ) {
1947
- WARN_ON_ONCE (!cpumask_test_cpu (task_cpu (p ), & p -> cpus_mask ));
1945
+ if (cpumask_test_cpu (task_cpu (p ), & p -> cpus_mask ))
1948
1946
goto out ;
1949
- }
1950
1947
1951
1948
dest_cpu = cpumask_any_distribute (& p -> cpus_mask );
1952
1949
}
@@ -1956,7 +1953,14 @@ static int migration_cpu_stop(void *data)
1956
1953
else
1957
1954
p -> wake_cpu = dest_cpu ;
1958
1955
1959
- } else if (dest_cpu < 0 || pending ) {
1956
+ /*
1957
+ * XXX __migrate_task() can fail, at which point we might end
1958
+ * up running on a dodgy CPU, AFAICT this can only happen
1959
+ * during CPU hotplug, at which point we'll get pushed out
1960
+ * anyway, so it's probably not a big deal.
1961
+ */
1962
+
1963
+ } else if (pending ) {
1960
1964
/*
1961
1965
* This happens when we get migrated between migrate_enable()'s
1962
1966
* preempt_enable() and scheduling the stopper task. At that
@@ -1971,43 +1975,32 @@ static int migration_cpu_stop(void *data)
1971
1975
* ->pi_lock, so the allowed mask is stable - if it got
1972
1976
* somewhere allowed, we're done.
1973
1977
*/
1974
- if (pending && cpumask_test_cpu (task_cpu (p ), p -> cpus_ptr )) {
1975
- p -> migration_pending = NULL ;
1978
+ if (cpumask_test_cpu (task_cpu (p ), p -> cpus_ptr )) {
1979
+ if (p -> migration_pending == pending )
1980
+ p -> migration_pending = NULL ;
1976
1981
complete = true;
1977
1982
goto out ;
1978
1983
}
1979
1984
1980
- /*
1981
- * When this was migrate_enable() but we no longer have an
1982
- * @pending, a concurrent SCA 'fixed' things and we should be
1983
- * valid again. Nothing to do.
1984
- */
1985
- if (!pending ) {
1986
- WARN_ON_ONCE (!cpumask_test_cpu (task_cpu (p ), & p -> cpus_mask ));
1987
- goto out ;
1988
- }
1989
-
1990
1985
/*
1991
1986
* When migrate_enable() hits a rq mis-match we can't reliably
1992
1987
* determine is_migration_disabled() and so have to chase after
1993
1988
* it.
1994
1989
*/
1990
+ WARN_ON_ONCE (!pending -> stop_pending );
1995
1991
task_rq_unlock (rq , p , & rf );
1996
1992
stop_one_cpu_nowait (task_cpu (p ), migration_cpu_stop ,
1997
1993
& pending -> arg , & pending -> stop_work );
1998
1994
return 0 ;
1999
1995
}
2000
1996
out :
1997
+ if (pending )
1998
+ pending -> stop_pending = false;
2001
1999
task_rq_unlock (rq , p , & rf );
2002
2000
2003
2001
if (complete )
2004
2002
complete_all (& pending -> done );
2005
2003
2006
- /* For pending->{arg,stop_work} */
2007
- pending = arg -> pending ;
2008
- if (pending && refcount_dec_and_test (& pending -> refs ))
2009
- wake_up_var (& pending -> refs );
2010
-
2011
2004
return 0 ;
2012
2005
}
2013
2006
@@ -2194,11 +2187,7 @@ static int affine_move_task(struct rq *rq, struct task_struct *p, struct rq_flag
2194
2187
int dest_cpu , unsigned int flags )
2195
2188
{
2196
2189
struct set_affinity_pending my_pending = { }, * pending = NULL ;
2197
- struct migration_arg arg = {
2198
- .task = p ,
2199
- .dest_cpu = dest_cpu ,
2200
- };
2201
- bool complete = false;
2190
+ bool stop_pending , complete = false;
2202
2191
2203
2192
/* Can the task run on the task's current CPU? If so, we're done */
2204
2193
if (cpumask_test_cpu (task_cpu (p ), & p -> cpus_mask )) {
@@ -2210,12 +2199,16 @@ static int affine_move_task(struct rq *rq, struct task_struct *p, struct rq_flag
2210
2199
push_task = get_task_struct (p );
2211
2200
}
2212
2201
2202
+ /*
2203
+ * If there are pending waiters, but no pending stop_work,
2204
+ * then complete now.
2205
+ */
2213
2206
pending = p -> migration_pending ;
2214
- if (pending ) {
2215
- refcount_inc (& pending -> refs );
2207
+ if (pending && !pending -> stop_pending ) {
2216
2208
p -> migration_pending = NULL ;
2217
2209
complete = true;
2218
2210
}
2211
+
2219
2212
task_rq_unlock (rq , p , rf );
2220
2213
2221
2214
if (push_task ) {
@@ -2224,7 +2217,7 @@ static int affine_move_task(struct rq *rq, struct task_struct *p, struct rq_flag
2224
2217
}
2225
2218
2226
2219
if (complete )
2227
- goto do_complete ;
2220
+ complete_all ( & pending -> done ) ;
2228
2221
2229
2222
return 0 ;
2230
2223
}
@@ -2235,6 +2228,12 @@ static int affine_move_task(struct rq *rq, struct task_struct *p, struct rq_flag
2235
2228
/* Install the request */
2236
2229
refcount_set (& my_pending .refs , 1 );
2237
2230
init_completion (& my_pending .done );
2231
+ my_pending .arg = (struct migration_arg ) {
2232
+ .task = p ,
2233
+ .dest_cpu = -1 , /* any */
2234
+ .pending = & my_pending ,
2235
+ };
2236
+
2238
2237
p -> migration_pending = & my_pending ;
2239
2238
} else {
2240
2239
pending = p -> migration_pending ;
@@ -2259,60 +2258,59 @@ static int affine_move_task(struct rq *rq, struct task_struct *p, struct rq_flag
2259
2258
return - EINVAL ;
2260
2259
}
2261
2260
2262
- if (flags & SCA_MIGRATE_ENABLE ) {
2263
-
2264
- refcount_inc (& pending -> refs ); /* pending->{arg,stop_work} */
2265
- p -> migration_flags &= ~MDF_PUSH ;
2266
- task_rq_unlock (rq , p , rf );
2267
-
2268
- pending -> arg = (struct migration_arg ) {
2269
- .task = p ,
2270
- .dest_cpu = -1 ,
2271
- .pending = pending ,
2272
- };
2273
-
2274
- stop_one_cpu_nowait (cpu_of (rq ), migration_cpu_stop ,
2275
- & pending -> arg , & pending -> stop_work );
2276
-
2277
- return 0 ;
2278
- }
2279
-
2280
2261
if (task_running (rq , p ) || p -> state == TASK_WAKING ) {
2281
2262
/*
2282
- * Lessen races (and headaches) by delegating
2283
- * is_migration_disabled(p) checks to the stopper, which will
2284
- * run on the same CPU as said p .
2263
+ * MIGRATE_ENABLE gets here because 'p == current', but for
2264
+ * anything else we cannot do is_migration_disabled(), punt
2265
+ * and have the stopper function handle it all race-free .
2285
2266
*/
2267
+ stop_pending = pending -> stop_pending ;
2268
+ if (!stop_pending )
2269
+ pending -> stop_pending = true;
2270
+
2271
+ if (flags & SCA_MIGRATE_ENABLE )
2272
+ p -> migration_flags &= ~MDF_PUSH ;
2273
+
2286
2274
task_rq_unlock (rq , p , rf );
2287
- stop_one_cpu (cpu_of (rq ), migration_cpu_stop , & arg );
2288
2275
2276
+ if (!stop_pending ) {
2277
+ stop_one_cpu_nowait (cpu_of (rq ), migration_cpu_stop ,
2278
+ & pending -> arg , & pending -> stop_work );
2279
+ }
2280
+
2281
+ if (flags & SCA_MIGRATE_ENABLE )
2282
+ return 0 ;
2289
2283
} else {
2290
2284
2291
2285
if (!is_migration_disabled (p )) {
2292
2286
if (task_on_rq_queued (p ))
2293
2287
rq = move_queued_task (rq , rf , p , dest_cpu );
2294
2288
2295
- p -> migration_pending = NULL ;
2296
- complete = true;
2289
+ if (!pending -> stop_pending ) {
2290
+ p -> migration_pending = NULL ;
2291
+ complete = true;
2292
+ }
2297
2293
}
2298
2294
task_rq_unlock (rq , p , rf );
2299
2295
2300
- do_complete :
2301
2296
if (complete )
2302
2297
complete_all (& pending -> done );
2303
2298
}
2304
2299
2305
2300
wait_for_completion (& pending -> done );
2306
2301
2307
2302
if (refcount_dec_and_test (& pending -> refs ))
2308
- wake_up_var (& pending -> refs );
2303
+ wake_up_var (& pending -> refs ); /* No UaF, just an address */
2309
2304
2310
2305
/*
2311
2306
* Block the original owner of &pending until all subsequent callers
2312
2307
* have seen the completion and decremented the refcount
2313
2308
*/
2314
2309
wait_var_event (& my_pending .refs , !refcount_read (& my_pending .refs ));
2315
2310
2311
+ /* ARGH */
2312
+ WARN_ON_ONCE (my_pending .stop_pending );
2313
+
2316
2314
return 0 ;
2317
2315
}
2318
2316
0 commit comments