@@ -114,8 +114,10 @@ static bool blkcg_policy_enabled(struct gendisk *disk,
114
114
return pol && test_bit (pol -> plid , disk -> blkcg_pols );
115
115
}
116
116
117
- static void blkg_free (struct blkcg_gq * blkg )
117
+ static void blkg_free_workfn (struct work_struct * work )
118
118
{
119
+ struct blkcg_gq * blkg = container_of (work , struct blkcg_gq ,
120
+ free_work );
119
121
int i ;
120
122
121
123
/*
@@ -140,9 +142,23 @@ static void blkg_free(struct blkcg_gq *blkg)
140
142
kfree (blkg );
141
143
}
142
144
143
- static void blkg_free_workfn (struct work_struct * work )
145
+ /**
146
+ * blkg_free - free a blkg
147
+ * @blkg: blkg to free
148
+ *
149
+ * Free @blkg which may be partially allocated.
150
+ */
151
+ static void blkg_free (struct blkcg_gq * blkg )
144
152
{
145
- blkg_free (container_of (work , struct blkcg_gq , free_work ));
153
+ if (!blkg )
154
+ return ;
155
+
156
+ /*
157
+ * Both ->pd_free_fn() and request queue's release handler may
158
+ * sleep, so free us by scheduling one work func
159
+ */
160
+ INIT_WORK (& blkg -> free_work , blkg_free_workfn );
161
+ schedule_work (& blkg -> free_work );
146
162
}
147
163
148
164
static void __blkg_release (struct rcu_head * rcu )
@@ -153,10 +169,7 @@ static void __blkg_release(struct rcu_head *rcu)
153
169
154
170
/* release the blkcg and parent blkg refs this blkg has been holding */
155
171
css_put (& blkg -> blkcg -> css );
156
-
157
- /* ->pd_free_fn() may sleep, so free from a work queue */
158
- INIT_WORK (& blkg -> free_work , blkg_free_workfn );
159
- schedule_work (& blkg -> free_work );
172
+ blkg_free (blkg );
160
173
}
161
174
162
175
/*
0 commit comments