@@ -1135,24 +1135,26 @@ struct kernfs_syscall_ops cgroup1_kf_syscall_ops = {
1135
1135
.show_path = cgroup_show_path ,
1136
1136
};
1137
1137
1138
- int cgroup1_get_tree (struct fs_context * fc )
1138
+ /*
1139
+ * The guts of cgroup1 mount - find or create cgroup_root to use.
1140
+ * Called with cgroup_mutex held; returns 0 on success, -E... on
1141
+ * error and positive - in case when the candidate is busy dying.
1142
+ * On success it stashes a reference to cgroup_root into given
1143
+ * cgroup_fs_context; that reference is *NOT* counting towards the
1144
+ * cgroup_root refcount.
1145
+ */
1146
+ static int cgroup1_root_to_use (struct fs_context * fc )
1139
1147
{
1140
1148
struct cgroup_namespace * ns = current -> nsproxy -> cgroup_ns ;
1141
1149
struct cgroup_fs_context * ctx = cgroup_fc2context (fc );
1142
1150
struct cgroup_root * root ;
1143
1151
struct cgroup_subsys * ss ;
1144
1152
int i , ret ;
1145
1153
1146
- /* Check if the caller has permission to mount. */
1147
- if (!ns_capable (ns -> user_ns , CAP_SYS_ADMIN ))
1148
- return - EPERM ;
1149
-
1150
- cgroup_lock_and_drain_offline (& cgrp_dfl_root .cgrp );
1151
-
1152
1154
/* First find the desired set of subsystems */
1153
1155
ret = check_cgroupfs_options (fc );
1154
1156
if (ret )
1155
- goto out_unlock ;
1157
+ return ret ;
1156
1158
1157
1159
/*
1158
1160
* Destruction of cgroup root is asynchronous, so subsystems may
@@ -1166,12 +1168,8 @@ int cgroup1_get_tree(struct fs_context *fc)
1166
1168
ss -> root == & cgrp_dfl_root )
1167
1169
continue ;
1168
1170
1169
- if (!percpu_ref_tryget_live (& ss -> root -> cgrp .self .refcnt )) {
1170
- mutex_unlock (& cgroup_mutex );
1171
- msleep (10 );
1172
- ret = restart_syscall ();
1173
- goto out_free ;
1174
- }
1171
+ if (!percpu_ref_tryget_live (& ss -> root -> cgrp .self .refcnt ))
1172
+ return 1 ; /* restart */
1175
1173
cgroup_put (& ss -> root -> cgrp );
1176
1174
}
1177
1175
@@ -1200,63 +1198,70 @@ int cgroup1_get_tree(struct fs_context *fc)
1200
1198
(ctx -> subsys_mask != root -> subsys_mask )) {
1201
1199
if (!name_match )
1202
1200
continue ;
1203
- ret = - EBUSY ;
1204
- goto out_unlock ;
1201
+ return - EBUSY ;
1205
1202
}
1206
1203
1207
1204
if (root -> flags ^ ctx -> flags )
1208
1205
pr_warn ("new mount options do not match the existing superblock, will be ignored\n" );
1209
1206
1210
1207
ctx -> root = root ;
1211
- ret = 0 ;
1212
- goto out_unlock ;
1208
+ return 0 ;
1213
1209
}
1214
1210
1215
1211
/*
1216
1212
* No such thing, create a new one. name= matching without subsys
1217
1213
* specification is allowed for already existing hierarchies but we
1218
1214
* can't create new one without subsys specification.
1219
1215
*/
1220
- if (!ctx -> subsys_mask && !ctx -> none ) {
1221
- ret = cg_invalf (fc , "cgroup1: No subsys list or none specified" );
1222
- goto out_unlock ;
1223
- }
1216
+ if (!ctx -> subsys_mask && !ctx -> none )
1217
+ return cg_invalf (fc , "cgroup1: No subsys list or none specified" );
1224
1218
1225
1219
/* Hierarchies may only be created in the initial cgroup namespace. */
1226
- if (ns != & init_cgroup_ns ) {
1227
- ret = - EPERM ;
1228
- goto out_unlock ;
1229
- }
1220
+ if (ns != & init_cgroup_ns )
1221
+ return - EPERM ;
1230
1222
1231
1223
root = kzalloc (sizeof (* root ), GFP_KERNEL );
1232
- if (!root ) {
1233
- ret = - ENOMEM ;
1234
- goto out_unlock ;
1235
- }
1224
+ if (!root )
1225
+ return - ENOMEM ;
1236
1226
1237
1227
ctx -> root = root ;
1238
1228
init_cgroup_root (ctx );
1239
1229
1240
1230
ret = cgroup_setup_root (root , ctx -> subsys_mask );
1241
1231
if (ret )
1242
1232
cgroup_free_root (root );
1233
+ return ret ;
1234
+ }
1235
+
1236
+ int cgroup1_get_tree (struct fs_context * fc )
1237
+ {
1238
+ struct cgroup_namespace * ns = current -> nsproxy -> cgroup_ns ;
1239
+ struct cgroup_fs_context * ctx = cgroup_fc2context (fc );
1240
+ int ret ;
1241
+
1242
+ /* Check if the caller has permission to mount. */
1243
+ if (!ns_capable (ns -> user_ns , CAP_SYS_ADMIN ))
1244
+ return - EPERM ;
1245
+
1246
+ cgroup_lock_and_drain_offline (& cgrp_dfl_root .cgrp );
1247
+
1248
+ ret = cgroup1_root_to_use (fc );
1249
+ if (!ret && !percpu_ref_tryget_live (& ctx -> root -> cgrp .self .refcnt ))
1250
+ ret = 1 ; /* restart */
1243
1251
1244
- out_unlock :
1245
- if (!ret && !percpu_ref_tryget_live (& root -> cgrp .self .refcnt )) {
1246
- mutex_unlock (& cgroup_mutex );
1247
- msleep (10 );
1248
- return restart_syscall ();
1249
- }
1250
1252
mutex_unlock (& cgroup_mutex );
1251
- out_free :
1252
- if (ret )
1253
- return ret ;
1254
1253
1255
- ret = cgroup_do_mount (fc , CGROUP_SUPER_MAGIC , ns );
1256
- if (!ret && percpu_ref_is_dying (& root -> cgrp .self .refcnt )) {
1254
+ if (!ret )
1255
+ ret = cgroup_do_mount (fc , CGROUP_SUPER_MAGIC , ns );
1256
+
1257
+ if (!ret && percpu_ref_is_dying (& ctx -> root -> cgrp .self .refcnt )) {
1257
1258
struct super_block * sb = fc -> root -> d_sb ;
1258
1259
dput (fc -> root );
1259
1260
deactivate_locked_super (sb );
1261
+ ret = 1 ;
1262
+ }
1263
+
1264
+ if (unlikely (ret > 0 )) {
1260
1265
msleep (10 );
1261
1266
return restart_syscall ();
1262
1267
}
0 commit comments