diff options
Diffstat (limited to 'kernel/cgroup.c')
-rw-r--r-- | kernel/cgroup.c | 95 |
1 files changed, 24 insertions, 71 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 14efffed72c8..22db0a7cf1fa 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -1121,7 +1121,6 @@ static void init_cgroup_housekeeping(struct cgroup *cgrp) | |||
1121 | INIT_LIST_HEAD(&cgrp->children); | 1121 | INIT_LIST_HEAD(&cgrp->children); |
1122 | INIT_LIST_HEAD(&cgrp->css_sets); | 1122 | INIT_LIST_HEAD(&cgrp->css_sets); |
1123 | INIT_LIST_HEAD(&cgrp->release_list); | 1123 | INIT_LIST_HEAD(&cgrp->release_list); |
1124 | INIT_LIST_HEAD(&cgrp->pids_list); | ||
1125 | init_rwsem(&cgrp->pids_mutex); | 1124 | init_rwsem(&cgrp->pids_mutex); |
1126 | } | 1125 | } |
1127 | 1126 | ||
@@ -2431,30 +2430,12 @@ err: | |||
2431 | return ret; | 2430 | return ret; |
2432 | } | 2431 | } |
2433 | 2432 | ||
2434 | /* | ||
2435 | * Cache pids for all threads in the same pid namespace that are | ||
2436 | * opening the same "tasks" file. | ||
2437 | */ | ||
2438 | struct cgroup_pids { | ||
2439 | /* The node in cgrp->pids_list */ | ||
2440 | struct list_head list; | ||
2441 | /* The cgroup those pids belong to */ | ||
2442 | struct cgroup *cgrp; | ||
2443 | /* The namepsace those pids belong to */ | ||
2444 | struct pid_namespace *ns; | ||
2445 | /* Array of process ids in the cgroup */ | ||
2446 | pid_t *tasks_pids; | ||
2447 | /* How many files are using the this tasks_pids array */ | ||
2448 | int use_count; | ||
2449 | /* Length of the current tasks_pids array */ | ||
2450 | int length; | ||
2451 | }; | ||
2452 | |||
2453 | static int cmppid(const void *a, const void *b) | 2433 | static int cmppid(const void *a, const void *b) |
2454 | { | 2434 | { |
2455 | return *(pid_t *)a - *(pid_t *)b; | 2435 | return *(pid_t *)a - *(pid_t *)b; |
2456 | } | 2436 | } |
2457 | 2437 | ||
2438 | |||
2458 | /* | 2439 | /* |
2459 | * seq_file methods for the "tasks" file. The seq_file position is the | 2440 | * seq_file methods for the "tasks" file. The seq_file position is the |
2460 | * next pid to display; the seq_file iterator is a pointer to the pid | 2441 | * next pid to display; the seq_file iterator is a pointer to the pid |
@@ -2469,47 +2450,45 @@ static void *cgroup_tasks_start(struct seq_file *s, loff_t *pos) | |||
2469 | * after a seek to the start). Use a binary-search to find the | 2450 | * after a seek to the start). Use a binary-search to find the |
2470 | * next pid to display, if any | 2451 | * next pid to display, if any |
2471 | */ | 2452 | */ |
2472 | struct cgroup_pids *cp = s->private; | 2453 | struct cgroup *cgrp = s->private; |
2473 | struct cgroup *cgrp = cp->cgrp; | ||
2474 | int index = 0, pid = *pos; | 2454 | int index = 0, pid = *pos; |
2475 | int *iter; | 2455 | int *iter; |
2476 | 2456 | ||
2477 | down_read(&cgrp->pids_mutex); | 2457 | down_read(&cgrp->pids_mutex); |
2478 | if (pid) { | 2458 | if (pid) { |
2479 | int end = cp->length; | 2459 | int end = cgrp->pids_length; |
2480 | 2460 | ||
2481 | while (index < end) { | 2461 | while (index < end) { |
2482 | int mid = (index + end) / 2; | 2462 | int mid = (index + end) / 2; |
2483 | if (cp->tasks_pids[mid] == pid) { | 2463 | if (cgrp->tasks_pids[mid] == pid) { |
2484 | index = mid; | 2464 | index = mid; |
2485 | break; | 2465 | break; |
2486 | } else if (cp->tasks_pids[mid] <= pid) | 2466 | } else if (cgrp->tasks_pids[mid] <= pid) |
2487 | index = mid + 1; | 2467 | index = mid + 1; |
2488 | else | 2468 | else |
2489 | end = mid; | 2469 | end = mid; |
2490 | } | 2470 | } |
2491 | } | 2471 | } |
2492 | /* If we're off the end of the array, we're done */ | 2472 | /* If we're off the end of the array, we're done */ |
2493 | if (index >= cp->length) | 2473 | if (index >= cgrp->pids_length) |
2494 | return NULL; | 2474 | return NULL; |
2495 | /* Update the abstract position to be the actual pid that we found */ | 2475 | /* Update the abstract position to be the actual pid that we found */ |
2496 | iter = cp->tasks_pids + index; | 2476 | iter = cgrp->tasks_pids + index; |
2497 | *pos = *iter; | 2477 | *pos = *iter; |
2498 | return iter; | 2478 | return iter; |
2499 | } | 2479 | } |
2500 | 2480 | ||
2501 | static void cgroup_tasks_stop(struct seq_file *s, void *v) | 2481 | static void cgroup_tasks_stop(struct seq_file *s, void *v) |
2502 | { | 2482 | { |
2503 | struct cgroup_pids *cp = s->private; | 2483 | struct cgroup *cgrp = s->private; |
2504 | struct cgroup *cgrp = cp->cgrp; | ||
2505 | up_read(&cgrp->pids_mutex); | 2484 | up_read(&cgrp->pids_mutex); |
2506 | } | 2485 | } |
2507 | 2486 | ||
2508 | static void *cgroup_tasks_next(struct seq_file *s, void *v, loff_t *pos) | 2487 | static void *cgroup_tasks_next(struct seq_file *s, void *v, loff_t *pos) |
2509 | { | 2488 | { |
2510 | struct cgroup_pids *cp = s->private; | 2489 | struct cgroup *cgrp = s->private; |
2511 | int *p = v; | 2490 | int *p = v; |
2512 | int *end = cp->tasks_pids + cp->length; | 2491 | int *end = cgrp->tasks_pids + cgrp->pids_length; |
2513 | 2492 | ||
2514 | /* | 2493 | /* |
2515 | * Advance to the next pid in the array. If this goes off the | 2494 | * Advance to the next pid in the array. If this goes off the |
@@ -2536,33 +2515,26 @@ static const struct seq_operations cgroup_tasks_seq_operations = { | |||
2536 | .show = cgroup_tasks_show, | 2515 | .show = cgroup_tasks_show, |
2537 | }; | 2516 | }; |
2538 | 2517 | ||
2539 | static void release_cgroup_pid_array(struct cgroup_pids *cp) | 2518 | static void release_cgroup_pid_array(struct cgroup *cgrp) |
2540 | { | 2519 | { |
2541 | struct cgroup *cgrp = cp->cgrp; | ||
2542 | |||
2543 | down_write(&cgrp->pids_mutex); | 2520 | down_write(&cgrp->pids_mutex); |
2544 | BUG_ON(!cp->use_count); | 2521 | BUG_ON(!cgrp->pids_use_count); |
2545 | if (!--cp->use_count) { | 2522 | if (!--cgrp->pids_use_count) { |
2546 | list_del(&cp->list); | 2523 | kfree(cgrp->tasks_pids); |
2547 | put_pid_ns(cp->ns); | 2524 | cgrp->tasks_pids = NULL; |
2548 | kfree(cp->tasks_pids); | 2525 | cgrp->pids_length = 0; |
2549 | kfree(cp); | ||
2550 | } | 2526 | } |
2551 | up_write(&cgrp->pids_mutex); | 2527 | up_write(&cgrp->pids_mutex); |
2552 | } | 2528 | } |
2553 | 2529 | ||
2554 | static int cgroup_tasks_release(struct inode *inode, struct file *file) | 2530 | static int cgroup_tasks_release(struct inode *inode, struct file *file) |
2555 | { | 2531 | { |
2556 | struct seq_file *seq; | 2532 | struct cgroup *cgrp = __d_cgrp(file->f_dentry->d_parent); |
2557 | struct cgroup_pids *cp; | ||
2558 | 2533 | ||
2559 | if (!(file->f_mode & FMODE_READ)) | 2534 | if (!(file->f_mode & FMODE_READ)) |
2560 | return 0; | 2535 | return 0; |
2561 | 2536 | ||
2562 | seq = file->private_data; | 2537 | release_cgroup_pid_array(cgrp); |
2563 | cp = seq->private; | ||
2564 | |||
2565 | release_cgroup_pid_array(cp); | ||
2566 | return seq_release(inode, file); | 2538 | return seq_release(inode, file); |
2567 | } | 2539 | } |
2568 | 2540 | ||
@@ -2581,8 +2553,6 @@ static struct file_operations cgroup_tasks_operations = { | |||
2581 | static int cgroup_tasks_open(struct inode *unused, struct file *file) | 2553 | static int cgroup_tasks_open(struct inode *unused, struct file *file) |
2582 | { | 2554 | { |
2583 | struct cgroup *cgrp = __d_cgrp(file->f_dentry->d_parent); | 2555 | struct cgroup *cgrp = __d_cgrp(file->f_dentry->d_parent); |
2584 | struct pid_namespace *ns = current->nsproxy->pid_ns; | ||
2585 | struct cgroup_pids *cp; | ||
2586 | pid_t *pidarray; | 2556 | pid_t *pidarray; |
2587 | int npids; | 2557 | int npids; |
2588 | int retval; | 2558 | int retval; |
@@ -2609,37 +2579,20 @@ static int cgroup_tasks_open(struct inode *unused, struct file *file) | |||
2609 | * array if necessary | 2579 | * array if necessary |
2610 | */ | 2580 | */ |
2611 | down_write(&cgrp->pids_mutex); | 2581 | down_write(&cgrp->pids_mutex); |
2612 | 2582 | kfree(cgrp->tasks_pids); | |
2613 | list_for_each_entry(cp, &cgrp->pids_list, list) { | 2583 | cgrp->tasks_pids = pidarray; |
2614 | if (ns == cp->ns) | 2584 | cgrp->pids_length = npids; |
2615 | goto found; | 2585 | cgrp->pids_use_count++; |
2616 | } | ||
2617 | |||
2618 | cp = kzalloc(sizeof(*cp), GFP_KERNEL); | ||
2619 | if (!cp) { | ||
2620 | up_write(&cgrp->pids_mutex); | ||
2621 | kfree(pidarray); | ||
2622 | return -ENOMEM; | ||
2623 | } | ||
2624 | cp->cgrp = cgrp; | ||
2625 | cp->ns = ns; | ||
2626 | get_pid_ns(ns); | ||
2627 | list_add(&cp->list, &cgrp->pids_list); | ||
2628 | found: | ||
2629 | kfree(cp->tasks_pids); | ||
2630 | cp->tasks_pids = pidarray; | ||
2631 | cp->length = npids; | ||
2632 | cp->use_count++; | ||
2633 | up_write(&cgrp->pids_mutex); | 2586 | up_write(&cgrp->pids_mutex); |
2634 | 2587 | ||
2635 | file->f_op = &cgroup_tasks_operations; | 2588 | file->f_op = &cgroup_tasks_operations; |
2636 | 2589 | ||
2637 | retval = seq_open(file, &cgroup_tasks_seq_operations); | 2590 | retval = seq_open(file, &cgroup_tasks_seq_operations); |
2638 | if (retval) { | 2591 | if (retval) { |
2639 | release_cgroup_pid_array(cp); | 2592 | release_cgroup_pid_array(cgrp); |
2640 | return retval; | 2593 | return retval; |
2641 | } | 2594 | } |
2642 | ((struct seq_file *)file->private_data)->private = cp; | 2595 | ((struct seq_file *)file->private_data)->private = cgrp; |
2643 | return 0; | 2596 | return 0; |
2644 | } | 2597 | } |
2645 | 2598 | ||