Beispiel #1
0
int krg_task_alloc(struct task_struct *task, struct pid *pid)
{
	struct task_kddm_object *obj;
	int nr = pid_knr(pid);

	task->task_obj = NULL;
	if (!task->nsproxy->krg_ns)
		return 0;
#ifdef CONFIG_KRG_EPM
	if (krg_current)
		return 0;
#endif
	/* Exclude kernel threads and local pids from using task kddm objects. */
	/*
	 * At this stage, current->mm points the mm of the task being duplicated
	 * instead of the mm of task for which this struct is being allocated,
	 * but we only need to know whether it is NULL or not, which will be the
	 * same after copy_mm.
	 */
	if (!(nr & GLOBAL_PID_MASK) || !current->mm)
		return 0;

	obj = krg_task_create_writelock(nr);
	if (!obj)
		return -ENOMEM;

	/* Set the link between task kddm object and tsk */
	obj->task = task;
	task->task_obj = obj;

	return 0;
}
Beispiel #2
0
static void __put_pid(struct pid_kddm_object *obj)
{
	struct pid *pid = obj->pid;
	int nr = pid_knr(pid);
	int may_put;
	int grabbed = 0;

	/* Try to avoid grabing the kddm object */
	read_lock(&tasklist_lock);
	spin_lock(&pid_kddm_lock);
	may_put = may_put_pid(obj);
	spin_unlock(&pid_kddm_lock);
	if (!may_put)
		goto release_work;
	read_unlock(&tasklist_lock);

	/* The pid seems to be unused locally. Have to check globally. */
	/* Prevent pidmaps from changing host nodes. */
	pidmap_map_read_lock();
	fkddm_grab_object(kddm_def_ns, PID_KDDM_ID, nr,
			  KDDM_NO_FT_REQ | KDDM_DONT_KILL);
	grabbed = 1;

	read_lock(&tasklist_lock);

	spin_lock(&pid_kddm_lock);
	may_put = may_put_pid(obj);
	if (may_put) {
		obj->active = 0;
		obj->node_count--;
		if (obj->node_count)
			/* Still used elsewhere */
			may_put = 0;
	}
	spin_unlock(&pid_kddm_lock);

release_work:
	spin_lock(&put_pid_wq_lock);
	list_del_init(&obj->wq);
	spin_unlock(&put_pid_wq_lock);

	read_unlock(&tasklist_lock);

	if (may_put) {
		_kddm_remove_frozen_object(pid_kddm_set, nr);
		pidmap_map_read_unlock();
	} else if (grabbed) {
		_kddm_put_object(pid_kddm_set, nr);
		pidmap_map_read_unlock();
	}
}
Beispiel #3
0
int export_pid(struct epm_action *action,
	       ghost_t *ghost, struct pid_link *link)
{
	struct pid *pid = link->pid;
	int nr = pid_knr(pid);
	int retval;

	if (!(nr & GLOBAL_PID_MASK))
		return -EPERM;

	if (ORIG_NODE(nr) == kerrighed_node_id && !pid->kddm_obj
	    && action->type != EPM_CHECKPOINT) {
		retval = create_pid_kddm_object(pid, 0);
		if (retval)
			return retval;
	}
	return ghost_write(ghost, &nr, sizeof(nr));
}
Beispiel #4
0
static int create_pid_kddm_object(struct pid *pid, int early)
{
	int nr = pid_knr(pid);
	struct pid_kddm_object *obj;
	struct task_kddm_object *task_obj;

	obj = _kddm_grab_object(pid_kddm_set, nr);
	if (IS_ERR(obj)) {
		_kddm_put_object(pid_kddm_set, nr);
		return PTR_ERR(obj);
	}
	BUG_ON(!obj);
	task_obj = krg_task_readlock(nr);

	spin_lock(&pid_kddm_lock);
	BUG_ON(early && pid->kddm_obj);
	if (!pid->kddm_obj) {
		obj->pid = pid;
		obj->active = 1;
		if (early)
			obj->attach_pending = 1;
		BUG_ON(obj->task_obj);
		if (task_obj) {
			BUG_ON(task_obj->pid_obj);
			/*
			 * These rcu_assign_pointer are not really needed,
			 * but are cleaner :)
			 */
			rcu_assign_pointer(obj->task_obj, task_obj);
			rcu_assign_pointer(obj->task_obj->pid_obj, obj);
		}
		pid->kddm_obj = obj;
	}
	BUG_ON(pid->kddm_obj != obj);
	spin_unlock(&pid_kddm_lock);

	krg_task_unlock(nr);
	_kddm_put_object(pid_kddm_set, nr);

	return 0;
}