aboutsummaryrefslogtreecommitdiffstats
path: root/fs/configfs
diff options
context:
space:
mode:
authorJoel Becker <joel.becker@oracle.com>2008-06-17 18:34:32 -0400
committerMark Fasheh <mfasheh@suse.com>2008-07-31 19:21:13 -0400
commit70526b67443a980d5029d9cf06903bef731a4e96 (patch)
treeaf4558619eeeda7f0075017881d8274d03854ca9 /fs/configfs
parent99cefda42ac550863b5ae1df9e60322e377decf9 (diff)
[PATCH] configfs: Pin configfs subsystems separately from new config_items.
configfs_mkdir() creates a new item by calling its parent's ->make_item/group() functions. Once that object is created, configfs_mkdir() calls try_module_get() on the new item's module. If it succeeds, the module owning the new item cannot be unloaded, and configfs is safe to reference the item. If the item and the subsystem it belongs to are part of the same module, the subsystem is also pinned. This is the common case. However, if the subsystem is made up of multiple modules, this may not pin the subsystem. Thus, it would be possible to unload the toplevel subsystem module while there is still a child item. Thus, we now try_module_get() the subsystem's module. This only really affects children of the toplevel subsystem group. Deeper children already have their parents pinned. Signed-off-by: Joel Becker <joel.becker@oracle.com> Signed-off-by: Mark Fasheh <mfasheh@suse.com>
Diffstat (limited to 'fs/configfs')
-rw-r--r--fs/configfs/dir.c42
1 files changed, 33 insertions, 9 deletions
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
index a89058b39884..7a8db78a91d2 100644
--- a/fs/configfs/dir.c
+++ b/fs/configfs/dir.c
@@ -1100,7 +1100,7 @@ static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
1100 struct configfs_subsystem *subsys; 1100 struct configfs_subsystem *subsys;
1101 struct configfs_dirent *sd; 1101 struct configfs_dirent *sd;
1102 struct config_item_type *type; 1102 struct config_item_type *type;
1103 struct module *owner = NULL; 1103 struct module *subsys_owner = NULL, *new_item_owner = NULL;
1104 char *name; 1104 char *name;
1105 1105
1106 if (dentry->d_parent == configfs_sb->s_root) { 1106 if (dentry->d_parent == configfs_sb->s_root) {
@@ -1137,10 +1137,25 @@ static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
1137 goto out_put; 1137 goto out_put;
1138 } 1138 }
1139 1139
1140 /*
1141 * The subsystem may belong to a different module than the item
1142 * being created. We don't want to safely pin the new item but
1143 * fail to pin the subsystem it sits under.
1144 */
1145 if (!subsys->su_group.cg_item.ci_type) {
1146 ret = -EINVAL;
1147 goto out_put;
1148 }
1149 subsys_owner = subsys->su_group.cg_item.ci_type->ct_owner;
1150 if (!try_module_get(subsys_owner)) {
1151 ret = -EINVAL;
1152 goto out_put;
1153 }
1154
1140 name = kmalloc(dentry->d_name.len + 1, GFP_KERNEL); 1155 name = kmalloc(dentry->d_name.len + 1, GFP_KERNEL);
1141 if (!name) { 1156 if (!name) {
1142 ret = -ENOMEM; 1157 ret = -ENOMEM;
1143 goto out_put; 1158 goto out_subsys_put;
1144 } 1159 }
1145 1160
1146 snprintf(name, dentry->d_name.len + 1, "%s", dentry->d_name.name); 1161 snprintf(name, dentry->d_name.len + 1, "%s", dentry->d_name.name);
@@ -1172,7 +1187,7 @@ static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
1172 * If ret != 0, then link_obj() was never called. 1187 * If ret != 0, then link_obj() was never called.
1173 * There are no extra references to clean up. 1188 * There are no extra references to clean up.
1174 */ 1189 */
1175 goto out_put; 1190 goto out_subsys_put;
1176 } 1191 }
1177 1192
1178 /* 1193 /*
@@ -1186,8 +1201,8 @@ static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
1186 goto out_unlink; 1201 goto out_unlink;
1187 } 1202 }
1188 1203
1189 owner = type->ct_owner; 1204 new_item_owner = type->ct_owner;
1190 if (!try_module_get(owner)) { 1205 if (!try_module_get(new_item_owner)) {
1191 ret = -EINVAL; 1206 ret = -EINVAL;
1192 goto out_unlink; 1207 goto out_unlink;
1193 } 1208 }
@@ -1236,9 +1251,13 @@ out_unlink:
1236 mutex_unlock(&subsys->su_mutex); 1251 mutex_unlock(&subsys->su_mutex);
1237 1252
1238 if (module_got) 1253 if (module_got)
1239 module_put(owner); 1254 module_put(new_item_owner);
1240 } 1255 }
1241 1256
1257out_subsys_put:
1258 if (ret)
1259 module_put(subsys_owner);
1260
1242out_put: 1261out_put:
1243 /* 1262 /*
1244 * link_obj()/link_group() took a reference from child->parent, 1263 * link_obj()/link_group() took a reference from child->parent,
@@ -1257,7 +1276,7 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry)
1257 struct config_item *item; 1276 struct config_item *item;
1258 struct configfs_subsystem *subsys; 1277 struct configfs_subsystem *subsys;
1259 struct configfs_dirent *sd; 1278 struct configfs_dirent *sd;
1260 struct module *owner = NULL; 1279 struct module *subsys_owner = NULL, *dead_item_owner = NULL;
1261 int ret; 1280 int ret;
1262 1281
1263 if (dentry->d_parent == configfs_sb->s_root) 1282 if (dentry->d_parent == configfs_sb->s_root)
@@ -1284,6 +1303,10 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry)
1284 return -EINVAL; 1303 return -EINVAL;
1285 } 1304 }
1286 1305
1306 /* configfs_mkdir() shouldn't have allowed this */
1307 BUG_ON(!subsys->su_group.cg_item.ci_type);
1308 subsys_owner = subsys->su_group.cg_item.ci_type->ct_owner;
1309
1287 /* 1310 /*
1288 * Ensure that no racing symlink() will make detach_prep() fail while 1311 * Ensure that no racing symlink() will make detach_prep() fail while
1289 * the new link is temporarily attached 1312 * the new link is temporarily attached
@@ -1321,7 +1344,7 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry)
1321 config_item_put(parent_item); 1344 config_item_put(parent_item);
1322 1345
1323 if (item->ci_type) 1346 if (item->ci_type)
1324 owner = item->ci_type->ct_owner; 1347 dead_item_owner = item->ci_type->ct_owner;
1325 1348
1326 if (sd->s_type & CONFIGFS_USET_DIR) { 1349 if (sd->s_type & CONFIGFS_USET_DIR) {
1327 configfs_detach_group(item); 1350 configfs_detach_group(item);
@@ -1343,7 +1366,8 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry)
1343 /* Drop our reference from above */ 1366 /* Drop our reference from above */
1344 config_item_put(item); 1367 config_item_put(item);
1345 1368
1346 module_put(owner); 1369 module_put(dead_item_owner);
1370 module_put(subsys_owner);
1347 1371
1348 return 0; 1372 return 0;
1349} 1373}