aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/cpuset.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/cpuset.c')
-rw-r--r--kernel/cpuset.c109
1 files changed, 35 insertions, 74 deletions
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index d5738910c34c..276ce7e4f1ab 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -227,10 +227,6 @@ static struct cpuset top_cpuset = {
227 * The task_struct fields mems_allowed and mems_generation may only 227 * The task_struct fields mems_allowed and mems_generation may only
228 * be accessed in the context of that task, so require no locks. 228 * be accessed in the context of that task, so require no locks.
229 * 229 *
230 * The cpuset_common_file_write handler for operations that modify
231 * the cpuset hierarchy holds cgroup_mutex across the entire operation,
232 * single threading all such cpuset modifications across the system.
233 *
234 * The cpuset_common_file_read() handlers only hold callback_mutex across 230 * The cpuset_common_file_read() handlers only hold callback_mutex across
235 * small pieces of code, such as when reading out possibly multi-word 231 * small pieces of code, such as when reading out possibly multi-word
236 * cpumasks and nodemasks. 232 * cpumasks and nodemasks.
@@ -772,7 +768,7 @@ static void cpuset_change_cpumask(struct task_struct *tsk,
772 * @cs: the cpuset to consider 768 * @cs: the cpuset to consider
773 * @buf: buffer of cpu numbers written to this cpuset 769 * @buf: buffer of cpu numbers written to this cpuset
774 */ 770 */
775static int update_cpumask(struct cpuset *cs, char *buf) 771static int update_cpumask(struct cpuset *cs, const char *buf)
776{ 772{
777 struct cpuset trialcs; 773 struct cpuset trialcs;
778 struct cgroup_scanner scan; 774 struct cgroup_scanner scan;
@@ -792,7 +788,6 @@ static int update_cpumask(struct cpuset *cs, char *buf)
792 * that parsing. The validate_change() call ensures that cpusets 788 * that parsing. The validate_change() call ensures that cpusets
793 * with tasks have cpus. 789 * with tasks have cpus.
794 */ 790 */
795 buf = strstrip(buf);
796 if (!*buf) { 791 if (!*buf) {
797 cpus_clear(trialcs.cpus_allowed); 792 cpus_clear(trialcs.cpus_allowed);
798 } else { 793 } else {
@@ -902,7 +897,7 @@ static void cpuset_migrate_mm(struct mm_struct *mm, const nodemask_t *from,
902 897
903static void *cpuset_being_rebound; 898static void *cpuset_being_rebound;
904 899
905static int update_nodemask(struct cpuset *cs, char *buf) 900static int update_nodemask(struct cpuset *cs, const char *buf)
906{ 901{
907 struct cpuset trialcs; 902 struct cpuset trialcs;
908 nodemask_t oldmem; 903 nodemask_t oldmem;
@@ -929,7 +924,6 @@ static int update_nodemask(struct cpuset *cs, char *buf)
929 * that parsing. The validate_change() call ensures that cpusets 924 * that parsing. The validate_change() call ensures that cpusets
930 * with tasks have memory. 925 * with tasks have memory.
931 */ 926 */
932 buf = strstrip(buf);
933 if (!*buf) { 927 if (!*buf) {
934 nodes_clear(trialcs.mems_allowed); 928 nodes_clear(trialcs.mems_allowed);
935 } else { 929 } else {
@@ -1256,72 +1250,14 @@ typedef enum {
1256 FILE_SPREAD_SLAB, 1250 FILE_SPREAD_SLAB,
1257} cpuset_filetype_t; 1251} cpuset_filetype_t;
1258 1252
1259static ssize_t cpuset_common_file_write(struct cgroup *cont,
1260 struct cftype *cft,
1261 struct file *file,
1262 const char __user *userbuf,
1263 size_t nbytes, loff_t *unused_ppos)
1264{
1265 struct cpuset *cs = cgroup_cs(cont);
1266 cpuset_filetype_t type = cft->private;
1267 char *buffer;
1268 int retval = 0;
1269
1270 /* Crude upper limit on largest legitimate cpulist user might write. */
1271 if (nbytes > 100U + 6 * max(NR_CPUS, MAX_NUMNODES))
1272 return -E2BIG;
1273
1274 /* +1 for nul-terminator */
1275 buffer = kmalloc(nbytes + 1, GFP_KERNEL);
1276 if (!buffer)
1277 return -ENOMEM;
1278
1279 if (copy_from_user(buffer, userbuf, nbytes)) {
1280 retval = -EFAULT;
1281 goto out1;
1282 }
1283 buffer[nbytes] = 0; /* nul-terminate */
1284
1285 cgroup_lock();
1286
1287 if (cgroup_is_removed(cont)) {
1288 retval = -ENODEV;
1289 goto out2;
1290 }
1291
1292 switch (type) {
1293 case FILE_CPULIST:
1294 retval = update_cpumask(cs, buffer);
1295 break;
1296 case FILE_MEMLIST:
1297 retval = update_nodemask(cs, buffer);
1298 break;
1299 default:
1300 retval = -EINVAL;
1301 goto out2;
1302 }
1303
1304 if (retval == 0)
1305 retval = nbytes;
1306out2:
1307 cgroup_unlock();
1308out1:
1309 kfree(buffer);
1310 return retval;
1311}
1312
1313static int cpuset_write_u64(struct cgroup *cgrp, struct cftype *cft, u64 val) 1253static int cpuset_write_u64(struct cgroup *cgrp, struct cftype *cft, u64 val)
1314{ 1254{
1315 int retval = 0; 1255 int retval = 0;
1316 struct cpuset *cs = cgroup_cs(cgrp); 1256 struct cpuset *cs = cgroup_cs(cgrp);
1317 cpuset_filetype_t type = cft->private; 1257 cpuset_filetype_t type = cft->private;
1318 1258
1319 cgroup_lock(); 1259 if (!cgroup_lock_live_group(cgrp))
1320
1321 if (cgroup_is_removed(cgrp)) {
1322 cgroup_unlock();
1323 return -ENODEV; 1260 return -ENODEV;
1324 }
1325 1261
1326 switch (type) { 1262 switch (type) {
1327 case FILE_CPU_EXCLUSIVE: 1263 case FILE_CPU_EXCLUSIVE:
@@ -1367,12 +1303,9 @@ static int cpuset_write_s64(struct cgroup *cgrp, struct cftype *cft, s64 val)
1367 struct cpuset *cs = cgroup_cs(cgrp); 1303 struct cpuset *cs = cgroup_cs(cgrp);
1368 cpuset_filetype_t type = cft->private; 1304 cpuset_filetype_t type = cft->private;
1369 1305
1370 cgroup_lock(); 1306 if (!cgroup_lock_live_group(cgrp))
1371
1372 if (cgroup_is_removed(cgrp)) {
1373 cgroup_unlock();
1374 return -ENODEV; 1307 return -ENODEV;
1375 } 1308
1376 switch (type) { 1309 switch (type) {
1377 case FILE_SCHED_RELAX_DOMAIN_LEVEL: 1310 case FILE_SCHED_RELAX_DOMAIN_LEVEL:
1378 retval = update_relax_domain_level(cs, val); 1311 retval = update_relax_domain_level(cs, val);
@@ -1386,6 +1319,32 @@ static int cpuset_write_s64(struct cgroup *cgrp, struct cftype *cft, s64 val)
1386} 1319}
1387 1320
1388/* 1321/*
1322 * Common handling for a write to a "cpus" or "mems" file.
1323 */
1324static int cpuset_write_resmask(struct cgroup *cgrp, struct cftype *cft,
1325 const char *buf)
1326{
1327 int retval = 0;
1328
1329 if (!cgroup_lock_live_group(cgrp))
1330 return -ENODEV;
1331
1332 switch (cft->private) {
1333 case FILE_CPULIST:
1334 retval = update_cpumask(cgroup_cs(cgrp), buf);
1335 break;
1336 case FILE_MEMLIST:
1337 retval = update_nodemask(cgroup_cs(cgrp), buf);
1338 break;
1339 default:
1340 retval = -EINVAL;
1341 break;
1342 }
1343 cgroup_unlock();
1344 return retval;
1345}
1346
1347/*
1389 * These ascii lists should be read in a single call, by using a user 1348 * These ascii lists should be read in a single call, by using a user
1390 * buffer large enough to hold the entire map. If read in smaller 1349 * buffer large enough to hold the entire map. If read in smaller
1391 * chunks, there is no guarantee of atomicity. Since the display format 1350 * chunks, there is no guarantee of atomicity. Since the display format
@@ -1504,14 +1463,16 @@ static struct cftype files[] = {
1504 { 1463 {
1505 .name = "cpus", 1464 .name = "cpus",
1506 .read = cpuset_common_file_read, 1465 .read = cpuset_common_file_read,
1507 .write = cpuset_common_file_write, 1466 .write_string = cpuset_write_resmask,
1467 .max_write_len = (100U + 6 * NR_CPUS),
1508 .private = FILE_CPULIST, 1468 .private = FILE_CPULIST,
1509 }, 1469 },
1510 1470
1511 { 1471 {
1512 .name = "mems", 1472 .name = "mems",
1513 .read = cpuset_common_file_read, 1473 .read = cpuset_common_file_read,
1514 .write = cpuset_common_file_write, 1474 .write_string = cpuset_write_resmask,
1475 .max_write_len = (100U + 6 * MAX_NUMNODES),
1515 .private = FILE_MEMLIST, 1476 .private = FILE_MEMLIST,
1516 }, 1477 },
1517 1478