Skip to content

Commit 70087dc

Browse files
rhvgoyalJens Axboe
authored and
Jens Axboe
committed
blk-throttle: Use task_subsys_state() to determine a task's blkio_cgroup
Currentlly we first map the task to cgroup and then cgroup to blkio_cgroup. There is a more direct way to get to blkio_cgroup from task using task_subsys_state(). Use that. The real reason for the fix is that it also avoids a race in generic cgroup code. During remount/umount rebind_subsystems() is called and it can do following with and rcu protection. cgrp->subsys[i] = NULL; That means if somebody got hold of cgroup under rcu and then it tried to do cgroup->subsys[] to get to blkio_cgroup, it would get NULL which is wrong. I was running into this race condition with ltp running on a upstream derived kernel and that lead to crash. So ideally we should also fix cgroup generic code to wait for rcu grace period before setting pointer to NULL. Li Zefan is not very keen on introducing synchronize_wait() as he thinks it will slow down moun/remount/umount operations. So for the time being atleast fix the kernel crash by taking a more direct route to blkio_cgroup. One tester had reported a crash while running LTP on a derived kernel and with this fix crash is no more seen while the test has been running for over 6 days. Signed-off-by: Vivek Goyal <[email protected]> Reviewed-by: Li Zefan <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent 02e3522 commit 70087dc

File tree

4 files changed

+19
-11
lines changed

4 files changed

+19
-11
lines changed

block/blk-cgroup.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,13 @@ struct blkio_cgroup *cgroup_to_blkio_cgroup(struct cgroup *cgroup)
114114
}
115115
EXPORT_SYMBOL_GPL(cgroup_to_blkio_cgroup);
116116

117+
struct blkio_cgroup *task_blkio_cgroup(struct task_struct *tsk)
118+
{
119+
return container_of(task_subsys_state(tsk, blkio_subsys_id),
120+
struct blkio_cgroup, css);
121+
}
122+
EXPORT_SYMBOL_GPL(task_blkio_cgroup);
123+
117124
static inline void
118125
blkio_update_group_weight(struct blkio_group *blkg, unsigned int weight)
119126
{

block/blk-cgroup.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,7 @@ static inline void blkiocg_set_start_empty_time(struct blkio_group *blkg) {}
291291
#if defined(CONFIG_BLK_CGROUP) || defined(CONFIG_BLK_CGROUP_MODULE)
292292
extern struct blkio_cgroup blkio_root_cgroup;
293293
extern struct blkio_cgroup *cgroup_to_blkio_cgroup(struct cgroup *cgroup);
294+
extern struct blkio_cgroup *task_blkio_cgroup(struct task_struct *tsk);
294295
extern void blkiocg_add_blkio_group(struct blkio_cgroup *blkcg,
295296
struct blkio_group *blkg, void *key, dev_t dev,
296297
enum blkio_policy_id plid);
@@ -314,6 +315,8 @@ void blkiocg_update_io_remove_stats(struct blkio_group *blkg,
314315
struct cgroup;
315316
static inline struct blkio_cgroup *
316317
cgroup_to_blkio_cgroup(struct cgroup *cgroup) { return NULL; }
318+
static inline struct blkio_cgroup *
319+
task_blkio_cgroup(struct task_struct *tsk) { return NULL; }
317320

318321
static inline void blkiocg_add_blkio_group(struct blkio_cgroup *blkcg,
319322
struct blkio_group *blkg, void *key, dev_t dev,

block/blk-throttle.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -160,9 +160,8 @@ static void throtl_put_tg(struct throtl_grp *tg)
160160
}
161161

162162
static struct throtl_grp * throtl_find_alloc_tg(struct throtl_data *td,
163-
struct cgroup *cgroup)
163+
struct blkio_cgroup *blkcg)
164164
{
165-
struct blkio_cgroup *blkcg = cgroup_to_blkio_cgroup(cgroup);
166165
struct throtl_grp *tg = NULL;
167166
void *key = td;
168167
struct backing_dev_info *bdi = &td->queue->backing_dev_info;
@@ -229,12 +228,12 @@ static struct throtl_grp * throtl_find_alloc_tg(struct throtl_data *td,
229228

230229
static struct throtl_grp * throtl_get_tg(struct throtl_data *td)
231230
{
232-
struct cgroup *cgroup;
233231
struct throtl_grp *tg = NULL;
232+
struct blkio_cgroup *blkcg;
234233

235234
rcu_read_lock();
236-
cgroup = task_cgroup(current, blkio_subsys_id);
237-
tg = throtl_find_alloc_tg(td, cgroup);
235+
blkcg = task_blkio_cgroup(current);
236+
tg = throtl_find_alloc_tg(td, blkcg);
238237
if (!tg)
239238
tg = &td->root_tg;
240239
rcu_read_unlock();

block/cfq-iosched.c

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1014,10 +1014,9 @@ void cfq_update_blkio_group_weight(void *key, struct blkio_group *blkg,
10141014
cfqg->needs_update = true;
10151015
}
10161016

1017-
static struct cfq_group *
1018-
cfq_find_alloc_cfqg(struct cfq_data *cfqd, struct cgroup *cgroup, int create)
1017+
static struct cfq_group * cfq_find_alloc_cfqg(struct cfq_data *cfqd,
1018+
struct blkio_cgroup *blkcg, int create)
10191019
{
1020-
struct blkio_cgroup *blkcg = cgroup_to_blkio_cgroup(cgroup);
10211020
struct cfq_group *cfqg = NULL;
10221021
void *key = cfqd;
10231022
int i, j;
@@ -1079,12 +1078,12 @@ cfq_find_alloc_cfqg(struct cfq_data *cfqd, struct cgroup *cgroup, int create)
10791078
*/
10801079
static struct cfq_group *cfq_get_cfqg(struct cfq_data *cfqd, int create)
10811080
{
1082-
struct cgroup *cgroup;
1081+
struct blkio_cgroup *blkcg;
10831082
struct cfq_group *cfqg = NULL;
10841083

10851084
rcu_read_lock();
1086-
cgroup = task_cgroup(current, blkio_subsys_id);
1087-
cfqg = cfq_find_alloc_cfqg(cfqd, cgroup, create);
1085+
blkcg = task_blkio_cgroup(current);
1086+
cfqg = cfq_find_alloc_cfqg(cfqd, blkcg, create);
10881087
if (!cfqg && create)
10891088
cfqg = &cfqd->root_group;
10901089
rcu_read_unlock();

0 commit comments

Comments
 (0)