| @@ -310,28 +310,11 @@ struct blkcg_gq *blkg_lookup_create(struct blkcg *blkcg, · 309 unmodified lines |
| 310 | } | 310 | } |
| 311 | } | 311 | } |
| 312 | | 312 | |
| 313 | static void blkg_pd_offline(struct blkcg_gq *blkg) | | |
| 314 | { | | |
| 315 | int i; | | |
| 316 | | | |
| 317 | lockdep_assert_held(blkg->q->queue_lock); | | |
| 318 | lockdep_assert_held(&blkg->blkcg->lock); | | |
| 319 | | | |
| 320 | for (i = 0; i < BLKCG_MAX_POLS; i++) { | | |
| 321 | struct blkcg_policy *pol = blkcg_policy[i]; | | |
| 322 | | | |
| 323 | if (blkg->pd[i] && !blkg->pd[i]->offline && | | |
| 324 | pol->pd_offline_fn) { | | |
| 325 | pol->pd_offline_fn(blkg->pd[i]); | | |
| 326 | blkg->pd[i]->offline = true; | | |
| 327 | } | | |
| 328 | } | | |
| 329 | } | | |
| 330 | | | |
| 331 | static void blkg_destroy(struct blkcg_gq *blkg) | 313 | static void blkg_destroy(struct blkcg_gq *blkg) |
| 332 | { | 314 | { |
| 333 | struct blkcg *blkcg = blkg->blkcg; | 315 | struct blkcg *blkcg = blkg->blkcg; |
| 334 | struct blkcg_gq *parent = blkg->parent; | 316 | struct blkcg_gq *parent = blkg->parent; |
| | 317 | int i; |
| 335 | | 318 | |
| 336 | lockdep_assert_held(blkg->q->queue_lock); | 319 | lockdep_assert_held(blkg->q->queue_lock); |
| 337 | lockdep_assert_held(&blkcg->lock); | 320 | lockdep_assert_held(&blkcg->lock); |
| @@ -340,6 +323,13 @@ static void blkg_destroy(struct blkcg_gq *blkg) · 2 unmodified lines |
| 340 | WARN_ON_ONCE(list_empty(&blkg->q_node)); | 323 | WARN_ON_ONCE(list_empty(&blkg->q_node)); |
| 341 | WARN_ON_ONCE(hlist_unhashed(&blkg->blkcg_node)); | 324 | WARN_ON_ONCE(hlist_unhashed(&blkg->blkcg_node)); |
| 342 | | 325 | |
| | 326 | for (i = 0; i < BLKCG_MAX_POLS; i++) { |
| | 327 | struct blkcg_policy *pol = blkcg_policy[i]; |
| | 328 | |
| | 329 | if (blkg->pd[i] && pol->pd_offline_fn) |
| | 330 | pol->pd_offline_fn(blkg->pd[i]); |
| | 331 | } |
| | 332 | |
| 343 | if (parent) { | 333 | if (parent) { |
| 344 | blkg_rwstat_add_aux(&parent->stat_bytes, &blkg->stat_bytes); | 334 | blkg_rwstat_add_aux(&parent->stat_bytes, &blkg->stat_bytes); |
| 345 | blkg_rwstat_add_aux(&parent->stat_ios, &blkg->stat_ios); | 335 | blkg_rwstat_add_aux(&parent->stat_ios, &blkg->stat_ios); |
| @@ -382,7 +372,6 @@ static void blkg_destroy_all(struct request_queue *q) · 36 unmodified lines |
| 382 | struct blkcg *blkcg = blkg->blkcg; | 372 | struct blkcg *blkcg = blkg->blkcg; |
| 383 | | 373 | |
| 384 | spin_lock(&blkcg->lock); | 374 | spin_lock(&blkcg->lock); |
| 385 | blkg_pd_offline(blkg); | | |
| 386 | blkg_destroy(blkg); | 375 | blkg_destroy(blkg); |
| 387 | spin_unlock(&blkcg->lock); | 376 | spin_unlock(&blkcg->lock); |
| 388 | } | 377 | } |
| @@ -1053,59 +1042,64 @@ static struct cftype blkcg_legacy_files[] = { · 664 unmodified lines |
| 1053 | { } /* terminate */ | 1042 | { } /* terminate */ |
| 1054 | }; | 1043 | }; |
| 1055 | | 1044 | |
| | 1045 | /* |
| | 1046 | * blkcg destruction is a three-stage process. |
| | 1047 | * |
| | 1048 | * 1. Destruction starts. The blkcg_css_offline() callback is invoked |
| | 1049 | * which offlines writeback. Here we tie the next stage of blkg destruction |
| | 1050 | * to the completion of writeback associated with the blkcg. This lets us |
| | 1051 | * avoid punting potentially large amounts of outstanding writeback to root |
| | 1052 | * while maintaining any ongoing policies. The next stage is triggered when |
| | 1053 | * the nr_cgwbs count goes to zero. |
| | 1054 | * |
| | 1055 | * 2. When the nr_cgwbs count goes to zero, blkcg_destroy_blkgs() is called |
| | 1056 | * and handles the destruction of blkgs. Here the css reference held by |
| | 1057 | * the blkg is put back eventually allowing blkcg_css_free() to be called. |
| | 1058 | * This work may occur in cgwb_release_workfn() on the cgwb_release |
| | 1059 | * workqueue. Any submitted ios that fail to get the blkg ref will be |
| | 1060 | * punted to the root_blkg. |
| | 1061 | * |
| | 1062 | * 3. Once the blkcg ref count goes to zero, blkcg_css_free() is called. |
| | 1063 | * This finally frees the blkcg. |
| | 1064 | */ |
| | 1065 | |
| 1056 | /** | 1066 | /** |
| 1057 | * blkcg_css_offline - cgroup css_offline callback | 1067 | * blkcg_css_offline - cgroup css_offline callback |
| 1058 | * @css: css of interest | 1068 | * @css: css of interest |
| 1059 | * | 1069 | * |
| 1060 | * This function is called when @css is about to go away and responsible | 1070 | * This function is called when @css is about to go away. Here the cgwbs are |
| 1061 | * for offlining all blkgs pd and killing all wbs associated with @css. | 1071 | * offlined first and only once writeback associated with the blkcg has |
| 1062 | * blkgs pd offline should be done while holding both q and blkcg locks. | 1072 | * finished do we start step 2 (see above). |
| 1063 | * As blkcg lock is nested inside q lock, this function performs reverse | | |
| 1064 | * double lock dancing. | | |
| 1065 | * | | |
| 1066 | * This is the blkcg counterpart of ioc_release_fn(). | | |
| 1067 | */ | 1073 | */ |
| 1068 | static void blkcg_css_offline(struct cgroup_subsys_state *css) | 1074 | static void blkcg_css_offline(struct cgroup_subsys_state *css) |
| 1069 | { | 1075 | { |
| 1070 | struct blkcg *blkcg = css_to_blkcg(css); | 1076 | struct blkcg *blkcg = css_to_blkcg(css); |
| 1071 | struct blkcg_gq *blkg; | | |
| 1072 | | | |
| 1073 | spin_lock_irq(&blkcg->lock); | | |
| 1074 | | | |
| 1075 | hlist_for_each_entry(blkg, &blkcg->blkg_list, blkcg_node) { | | |
| 1076 | struct request_queue *q = blkg->q; | | |
| 1077 | | | |
| 1078 | if (spin_trylock(q->queue_lock)) { | | |
| 1079 | blkg_pd_offline(blkg); | | |
| 1080 | spin_unlock(q->queue_lock); | | |
| 1081 | } else { | | |
| 1082 | spin_unlock_irq(&blkcg->lock); | | |
| 1083 | cpu_relax(); | | |
| 1084 | spin_lock_irq(&blkcg->lock); | | |
| 1085 | } | | |
| 1086 | } | | |
| 1087 | | | |
| 1088 | spin_unlock_irq(&blkcg->lock); | | |
| 1089 | | 1077 | |
| | 1078 | /* this prevents anyone from attaching or migrating to this blkcg */ |
| 1090 | wb_blkcg_offline(blkcg); | 1079 | wb_blkcg_offline(blkcg); |
| | 1080 | |
| | 1081 | /* put the base cgwb reference allowing step 2 to be triggered */ |
| | 1082 | blkcg_cgwb_put(blkcg); |
| 1091 | } | 1083 | } |
| 1092 | | 1084 | |
| 1093 | /** | 1085 | /** |
| 1094 | * blkcg_destroy_all_blkgs - destroy all blkgs associated with a blkcg | 1086 | * blkcg_destroy_blkgs - responsible for shooting down blkgs |
| 1095 | * @blkcg: blkcg of interest | 1087 | * @blkcg: blkcg of interest |
| 1096 | * | 1088 | * |
| 1097 | * This function is called when blkcg css is about to free and responsible for | 1089 | * blkgs should be removed while holding both q and blkcg locks. As blkcg lock |
| 1098 | * destroying all blkgs associated with @blkcg. | | |
| 1099 | * blkgs should be removed while holding both q and blkcg locks. As blkcg lock | | |
| 1100 | * is nested inside q lock, this function performs reverse double lock dancing. | 1090 | * is nested inside q lock, this function performs reverse double lock dancing. |
| | 1091 | * Destroying the blkgs releases the reference held on the blkcg's css allowing |
| | 1092 | * blkcg_css_free to eventually be called. |
| | 1093 | * |
| | 1094 | * This is the blkcg counterpart of ioc_release_fn(). |
| 1101 | */ | 1095 | */ |
| 1102 | static void blkcg_destroy_all_blkgs(struct blkcg *blkcg) | 1096 | void blkcg_destroy_blkgs(struct blkcg *blkcg) |
| 1103 | { | 1097 | { |
| 1104 | spin_lock_irq(&blkcg->lock); | 1098 | spin_lock_irq(&blkcg->lock); |
| | 1099 | |
| 1105 | while (!hlist_empty(&blkcg->blkg_list)) { | 1100 | while (!hlist_empty(&blkcg->blkg_list)) { |
| 1106 | struct blkcg_gq *blkg = hlist_entry(blkcg->blkg_list.first, | 1101 | struct blkcg_gq *blkg = hlist_entry(blkcg->blkg_list.first, |
| 1107 | struct blkcg_gq, | 1102 | struct blkcg_gq, blkcg_node); |
| 1108 | blkcg_node); | | |
| 1109 | struct request_queue *q = blkg->q; | 1103 | struct request_queue *q = blkg->q; |
| 1110 | | 1104 | |
| 1111 | if (spin_trylock(q->queue_lock)) { | 1105 | if (spin_trylock(q->queue_lock)) { |
| @@ -1117,6 +1111,7 @@ static void blkcg_destroy_all_blkgs(struct blkcg *blkcg) · 5 unmodified lines |
| 1117 | spin_lock_irq(&blkcg->lock); | 1111 | spin_lock_irq(&blkcg->lock); |
| 1118 | } | 1112 | } |
| 1119 | } | 1113 | } |
| | 1114 | |
| 1120 | spin_unlock_irq(&blkcg->lock); | 1115 | spin_unlock_irq(&blkcg->lock); |
| 1121 | } | 1116 | } |
| 1122 | | 1117 | |
| @@ -1125,8 +1120,6 @@ static void blkcg_css_free(struct cgroup_subsys_state *css) · 2 unmodified lines |
| 1125 | struct blkcg *blkcg = css_to_blkcg(css); | 1120 | struct blkcg *blkcg = css_to_blkcg(css); |
| 1126 | int i; | 1121 | int i; |
| 1127 | | 1122 | |
| 1128 | blkcg_destroy_all_blkgs(blkcg); | | |
| 1129 | | | |
| 1130 | mutex_lock(&blkcg_pol_mutex); | 1123 | mutex_lock(&blkcg_pol_mutex); |
| 1131 | | 1124 | |
| 1132 | list_del(&blkcg->all_blkcgs_node); | 1125 | list_del(&blkcg->all_blkcgs_node); |
| @@ -1189,6 +1182,7 @@ blkcg_css_alloc(struct cgroup_subsys_state *parent_css) · 56 unmodified lines |
| 1189 | INIT_HLIST_HEAD(&blkcg->blkg_list); | 1182 | INIT_HLIST_HEAD(&blkcg->blkg_list); |
| 1190 | #ifdef CONFIG_CGROUP_WRITEBACK | 1183 | #ifdef CONFIG_CGROUP_WRITEBACK |
| 1191 | INIT_LIST_HEAD(&blkcg->cgwb_list); | 1184 | INIT_LIST_HEAD(&blkcg->cgwb_list); |
| | 1185 | refcount_set(&blkcg->cgwb_refcnt, 1); |
| 1192 | #endif | 1186 | #endif |
| 1193 | list_add_tail(&blkcg->all_blkcgs_node, &all_blkcgs); | 1187 | list_add_tail(&blkcg->all_blkcgs_node, &all_blkcgs); |
| 1194 | | 1188 | |
| @@ -1480,11 +1474,8 @@ void blkcg_deactivate_policy(struct request_queue *q, · 285 unmodified lines |
| 1480 | | 1474 | |
| 1481 | list_for_each_entry(blkg, &q->blkg_list, q_node) { | 1475 | list_for_each_entry(blkg, &q->blkg_list, q_node) { |
| 1482 | if (blkg->pd[pol->plid]) { | 1476 | if (blkg->pd[pol->plid]) { |
| 1483 | if (!blkg->pd[pol->plid]->offline && | 1477 | if (pol->pd_offline_fn) |
| 1484 | pol->pd_offline_fn) { | | |
| 1485 | pol->pd_offline_fn(blkg->pd[pol->plid]); | 1478 | pol->pd_offline_fn(blkg->pd[pol->plid]); |
| 1486 | blkg->pd[pol->plid]->offline = true; | | |
| 1487 | } | | |
| 1488 | pol->pd_free_fn(blkg->pd[pol->plid]); | 1479 | pol->pd_free_fn(blkg->pd[pol->plid]); |
| 1489 | blkg->pd[pol->plid] = NULL; | 1480 | blkg->pd[pol->plid] = NULL; |
| 1490 | } | 1481 | } |