> +static int attach_task_by_pid(struct container *cont, char *pidbuf)
> +{
> +     pid_t pid;
> +     struct task_struct *tsk;
> +     int ret;
> +
> +     if (sscanf(pidbuf, "%d", &pid) != 1)
> +             return -EIO;
> +
> +     if (pid) {
> +             read_lock(&tasklist_lock);

You could just use rcu_read_lock() and rcu_read_unlock() instead
of read_lock(&tasklist_lock) and read_unlock(&tasklist_lock).

> +
> +             tsk = find_task_by_pid(pid);
> +             if (!tsk || tsk->flags & PF_EXITING) {
> +                     read_unlock(&tasklist_lock);
> +                     return -ESRCH;
> +             }
> +
> +             get_task_struct(tsk);
> +             read_unlock(&tasklist_lock);
> +
> +             if ((current->euid) && (current->euid != tsk->uid)
> +                 && (current->euid != tsk->suid)) {
> +                     put_task_struct(tsk);
> +                     return -EACCES;
> +             }
> +     } else {
> +             tsk = current;
> +             get_task_struct(tsk);
> +     }
> +
> +     ret = attach_task(cont, tsk);
> +     put_task_struct(tsk);
> +     return ret;
> +}
> +
>  /* The various types of files and directories in a container file system */
> 
>  typedef enum {
> @@ -684,6 +789,54 @@ typedef enum {
>       FILE_TASKLIST,
>  } container_filetype_t;
> 
> +static ssize_t container_common_file_write(struct container *cont,
> +                                        struct cftype *cft,
> +                                        struct file *file,
> +                                        const char __user *userbuf,
> +                                        size_t nbytes, loff_t *unused_ppos)
> +{
> +     container_filetype_t type = cft->private;
> +     char *buffer;
> +     int retval = 0;
> +
> +     if (nbytes >= PATH_MAX)
> +             return -E2BIG;
> +
> +     /* +1 for nul-terminator */
> +     if ((buffer = kmalloc(nbytes + 1, GFP_KERNEL)) == 0)
> +             return -ENOMEM;
> +
> +     if (copy_from_user(buffer, userbuf, nbytes)) {
> +             retval = -EFAULT;
> +             goto out1;
> +     }
> +     buffer[nbytes] = 0;     /* nul-terminate */
> +
> +     mutex_lock(&container_mutex);
> +
> +     if (container_is_removed(cont)) {
> +             retval = -ENODEV;
> +             goto out2;
> +     }

Can't we make this check prior to kmalloc() and copy_from_user()?



> +int container_task_count(const struct container *cont) {
> +     int count = 0;
> +     struct task_struct *g, *p;
> +     struct container_subsys_state *css;
> +     int subsys_id;
> +     get_first_subsys(cont, &css, &subsys_id);
> +
> +     read_lock(&tasklist_lock);

Can be replaced with rcu_read_lock() and rcu_read_unlock()

> +     do_each_thread(g, p) {
> +             if (task_subsys_state(p, subsys_id) == css)
> +                     count ++;
> +     } while_each_thread(g, p);
> +     read_unlock(&tasklist_lock);
> +     return count;
> +}
> +
> +static int pid_array_load(pid_t *pidarray, int npids, struct container *cont)
> +{
> +     int n = 0;
> +     struct task_struct *g, *p;
> +     struct container_subsys_state *css;
> +     int subsys_id;
> +     get_first_subsys(cont, &css, &subsys_id);
> +     rcu_read_lock();
> +     read_lock(&tasklist_lock);

The read_lock() and read_unlock() are redundant

> +
> +     do_each_thread(g, p) {
> +             if (task_subsys_state(p, subsys_id) == css) {
> +                     pidarray[n++] = pid_nr(task_pid(p));
> +                     if (unlikely(n == npids))
> +                             goto array_full;
> +             }
> +     } while_each_thread(g, p);
> +
> +array_full:
> +     read_unlock(&tasklist_lock);
> +     rcu_read_unlock();
> +     return n;
> +}
> +
[snip]

> +static int container_tasks_open(struct inode *unused, struct file *file)
> +{
> +     struct container *cont = __d_cont(file->f_dentry->d_parent);
> +     struct ctr_struct *ctr;
> +     pid_t *pidarray;
> +     int npids;
> +     char c;
> +
> +     if (!(file->f_mode & FMODE_READ))
> +             return 0;
> +
> +     ctr = kmalloc(sizeof(*ctr), GFP_KERNEL);
> +     if (!ctr)
> +             goto err0;
> +
> +     /*
> +      * If container gets more users after we read count, we won't have
> +      * enough space - tough.  This race is indistinguishable to the
> +      * caller from the case that the additional container users didn't
> +      * show up until sometime later on.
> +      */
> +     npids = container_task_count(cont);
> +     pidarray = kmalloc(npids * sizeof(pid_t), GFP_KERNEL);
> +     if (!pidarray)
> +             goto err1;
> +
> +     npids = pid_array_load(pidarray, npids, cont);
> +     sort(pidarray, npids, sizeof(pid_t), cmppid, NULL);
> +
> +     /* Call pid_array_to_buf() twice, first just to get bufsz */
> +     ctr->bufsz = pid_array_to_buf(&c, sizeof(c), pidarray, npids) + 1;
> +     ctr->buf = kmalloc(ctr->bufsz, GFP_KERNEL);
> +     if (!ctr->buf)
> +             goto err2;
> +     ctr->bufsz = pid_array_to_buf(ctr->buf, ctr->bufsz, pidarray, npids);
> +
> +     kfree(pidarray);
> +     file->private_data = ctr;
> +     return 0;
> +
> +err2:
> +     kfree(pidarray);
> +err1:
> +     kfree(ctr);
> +err0:
> +     return -ENOMEM;
> +}
> +

Any chance we could get a per-container task list? It will
help subsystem writers as well. Alternatively, subsystems
could use the attach_task() callback to track all tasks,
but a per-container list will avoid duplication.



-- 
        Warm Regards,
        Balbir Singh
        Linux Technology Center
        IBM, ISTL

-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
ckrm-tech mailing list
https://lists.sourceforge.net/lists/listinfo/ckrm-tech

Reply via email to