aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/target
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@linux-iscsi.org>2011-02-09 18:34:53 -0500
committerJames Bottomley <James.Bottomley@suse.de>2011-02-12 12:39:14 -0500
commit7c2bf6e925c38b8e3358f5046971b0d6086ddcf8 (patch)
tree824200b53c4a95cab8e337d6c776aaacb1ef782a /drivers/target
parent85dc98d93f3dc41cce54118a7abab9e6aa616dd2 (diff)
[SCSI] target: Fix top-level configfs_subsystem default_group shutdown breakage
This patch fixes two bugs uncovered during testing with slub_debug=FPUZ during module_exit() -> target_core_exit_configfs() with release of configfs subsystem consumer default groups, namely how this should be working with fs/configfs/dir.c:configfs_unregister_subsystem() release logic for struct config_group->default_group. The first issue involves configfs_unregister_subsystem() expecting to walk+drain the top-level subsys->su_group.default_groups directly in unlink_group(), and not directly from the configfs subsystem consumer for the top level struct config_group->default_groups. This patch drops the walk+drain of subsys->su_group.default_groups from TCM configfs subsystem consumer code, and moves the top-level ->default_groups kfree() after configfs_unregister_subsystem() has been called. The second issue involves calling core_alua_free_lu_gp(se_global->default_lu_gp) to release the default_lu_gp->lu_gp_group before configfs_unregister_subsystem() has been called. This patches also moves the core_alua_free_lu_gp() call to release default_lu_group->lu_gp_group after the subsys has been unregistered. Finally, this patch explictly clears the [lu_gp,alua,hba]_cg->default_groups pointers after kfree() to ensure that no stale memory is picked up from child struct config_group->default_group[] while configfs_unregister_subsystem() is called. Reported-by: Fubo Chen <fubo.chen@gmail.com> Signed-off-by: Nicholas A. Bellinger <nab@linux-iscsi.org> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/target')
-rw-r--r--drivers/target/target_core_configfs.c20
1 files changed, 11 insertions, 9 deletions
diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c
index 2764510798b0..1cb74d57ed5f 100644
--- a/drivers/target/target_core_configfs.c
+++ b/drivers/target/target_core_configfs.c
@@ -3178,8 +3178,7 @@ static void target_core_exit_configfs(void)
3178 config_item_put(item); 3178 config_item_put(item);
3179 } 3179 }
3180 kfree(lu_gp_cg->default_groups); 3180 kfree(lu_gp_cg->default_groups);
3181 core_alua_free_lu_gp(se_global->default_lu_gp); 3181 lu_gp_cg->default_groups = NULL;
3182 se_global->default_lu_gp = NULL;
3183 3182
3184 alua_cg = &se_global->alua_group; 3183 alua_cg = &se_global->alua_group;
3185 for (i = 0; alua_cg->default_groups[i]; i++) { 3184 for (i = 0; alua_cg->default_groups[i]; i++) {
@@ -3188,6 +3187,7 @@ static void target_core_exit_configfs(void)
3188 config_item_put(item); 3187 config_item_put(item);
3189 } 3188 }
3190 kfree(alua_cg->default_groups); 3189 kfree(alua_cg->default_groups);
3190 alua_cg->default_groups = NULL;
3191 3191
3192 hba_cg = &se_global->target_core_hbagroup; 3192 hba_cg = &se_global->target_core_hbagroup;
3193 for (i = 0; hba_cg->default_groups[i]; i++) { 3193 for (i = 0; hba_cg->default_groups[i]; i++) {
@@ -3196,15 +3196,17 @@ static void target_core_exit_configfs(void)
3196 config_item_put(item); 3196 config_item_put(item);
3197 } 3197 }
3198 kfree(hba_cg->default_groups); 3198 kfree(hba_cg->default_groups);
3199 3199 hba_cg->default_groups = NULL;
3200 for (i = 0; subsys->su_group.default_groups[i]; i++) { 3200 /*
3201 item = &subsys->su_group.default_groups[i]->cg_item; 3201 * We expect subsys->su_group.default_groups to be released
3202 subsys->su_group.default_groups[i] = NULL; 3202 * by configfs subsystem provider logic..
3203 config_item_put(item); 3203 */
3204 } 3204 configfs_unregister_subsystem(subsys);
3205 kfree(subsys->su_group.default_groups); 3205 kfree(subsys->su_group.default_groups);
3206 3206
3207 configfs_unregister_subsystem(subsys); 3207 core_alua_free_lu_gp(se_global->default_lu_gp);
3208 se_global->default_lu_gp = NULL;
3209
3208 printk(KERN_INFO "TARGET_CORE[0]: Released ConfigFS Fabric" 3210 printk(KERN_INFO "TARGET_CORE[0]: Released ConfigFS Fabric"
3209 " Infrastructure\n"); 3211 " Infrastructure\n");
3210 3212