Exemple #1
0
/**
 * cr_hand_abort - wrapper/helper for CR_OP_HAND_ABORT
 * @file: (struct file *) of the control node
 * @flags: abort type
 *
 * DESCRIPTION:
 * This function dispatches to the checkpoint-time or restart-time
 * "abort" code.
 */
int cr_hand_abort(struct file *filp, unsigned int flags)
{
    cr_task_t *cr_task;
    int retval;

    CR_KTRACE_FUNC_ENTRY();

    // Lookup this task
    retval = -ESRCH;
    cr_task = cr_task_get(current);
    if (!cr_task) {
	// No matching task found.
        CR_ERR("%s: No matching task found!", __FUNCTION__);
	goto out_no_task;
    }

    // Dispatch according to the matching request
    if (cr_task->chkpt_proc_req) {
	retval = cr_chkpt_abort(cr_task, flags);
    } else if (cr_task->rstrt_proc_req) {
	retval = cr_rstrt_abort(cr_task, flags);
    } else {
	// No matching request found.
        CR_ERR("%s: No matching request found!", __FUNCTION__);
    }

    cr_task_put(cr_task);

out_no_task:
    CR_KTRACE_FUNC_EXIT("Returning %d", retval);
    return retval;
}
/**
 * cr_proc_cleanup - Initialization code
 *
 * DESCRIPTION:
 * This function removes /proc/checkpoint and /proc/checkpoint/ctrl
 */
void cr_proc_cleanup(void)
{
    CR_KTRACE_FUNC_ENTRY();

    remove_proc_entry("ctrl", proc_checkpoint);
    remove_proc_entry("checkpoint", cr_proc_root);
}
Exemple #3
0
static int ctrl_open(struct inode * inode, struct file * file)
{
	cr_pdata_t *priv;

	CR_KTRACE_FUNC_ENTRY();

	CR_NO_LOCKS();
	priv = cr_kmem_cache_zalloc(cr_pdata_t, cr_pdata_cachep, GFP_KERNEL);
	if (priv) {
		file->private_data = (void*)priv;
	}

	return priv ? 0 : -ENOMEM;
}
Exemple #4
0
static unsigned int ctrl_poll(struct file *filp, poll_table *wait)
{
	unsigned int mask;
	cr_pdata_t *priv;

	CR_KTRACE_FUNC_ENTRY();

	priv = filp->private_data;
        if (priv && priv->rstrt_req) {
		mask = cr_rstrt_poll(filp, wait);
	} else if (priv && priv->chkpt_req) {
		mask = cr_chkpt_poll(filp, wait);
	} else {
		mask = POLLERR;
	}

	return mask;
}
Exemple #5
0
static int ctrl_release(struct inode * inode, struct file * file)
{
	cr_pdata_t *priv;

	CR_KTRACE_FUNC_ENTRY();

	priv = file->private_data;
	if (priv) {
		cr_chkpt_req_release(file, priv);
		cr_rstrt_req_release(file, priv);
		cr_phase1_release(file, priv);
		cr_phase2_release(file, priv);
		kmem_cache_free(cr_pdata_cachep, priv);
		file->private_data = NULL;
	}

	return 0;
}
/**
 * cr_proc_init - Initialization code
 *
 * DESCRIPTION:
 * This function registers /proc/checkpoint and /proc/checkpoint/ctrl
 */
int __init cr_proc_init(void)
{
    CR_KTRACE_FUNC_ENTRY();

    proc_checkpoint = create_proc_entry("checkpoint", S_IFDIR, cr_proc_root);
    if (proc_checkpoint == NULL) {
        CR_ERR("proc_create_entry(/proc/checkpoint/) failed");
        return -ENOMEM;
    }

    proc_ctrl = create_proc_entry("ctrl", S_IFREG | S_IRUGO | S_IWUGO,
                                  proc_checkpoint);
    if (proc_ctrl == NULL) {
        CR_ERR("proc_create_entry(/proc/checkpoint/ctrl) failed");
        return -ENOMEM;
    }

    proc_ctrl->proc_fops = &cr_ctrl_fops;

    return 0;
}
Exemple #7
0
/**
 * cr_hand_complete - wrapper/helper for CR_OP_HAND_DONE
 * @file: (struct file *) of the control node
 *
 * DESCRIPTION:
 * This function dispatches to the checkpoint-time or restart-time
 * post-handler "task_complete" code.
 */
int cr_hand_complete(struct file *filp, unsigned int flags)
{
    cr_task_t *cr_task;
    int retval;

    CR_KTRACE_FUNC_ENTRY();

    retval = -EINVAL;
    if (flags & ~CR_HOLD_BOTH) {
        CR_ERR("%s: invalid flags", __FUNCTION__);
	goto out_no_task;
    }

    // Lookup this task
    retval = -ESRCH;
    cr_task = cr_task_get(current);
    if (!cr_task) {
	// No matching task found.
        CR_ERR("%s: No matching task found!", __FUNCTION__);
	goto out_no_task;
    }

    // Dispatch according to the matching request
    if (cr_task->chkpt_proc_req) {
	retval = cr_chkpt_task_complete(cr_task, flags & CR_HOLD_CONT);
    } else if (cr_task->rstrt_proc_req) {
	retval = cr_rstrt_task_complete(cr_task, flags & CR_HOLD_RSTRT, /* need_lock= */ 1);
    } else {
	// No matching request found.
        CR_ERR("%s: No matching request found!", __FUNCTION__);
    }

    cr_task_put(cr_task);

out_no_task:
    CR_KTRACE_FUNC_EXIT("Returning %d", retval);
    return retval;
}
Exemple #8
0
const char *
cr_location2path(cr_location_t *loc, char *buf, int size)
{
	CR_PATH_DECL(path);
	char *name = NULL;

	CR_KTRACE_FUNC_ENTRY();

	if (loc->filp) {
		/* It's a file */
		CR_PATH_GET_FILE(path, loc->filp);
    		name = cr_getpath(path, buf, size);
		path_put(path);
	} else if (loc->fs) {
		/* It's a directory */
    		CR_PATH_GET_FS(path, loc->fs->pwd);
    		name = cr_getpath(path, buf, size - 2);
		path_put(path);

		if (name) {
			int len = strlen(buf);
			buf[len+0] = '/';
			buf[len+1] = '.';
			buf[len+2] = '\0';
		}
	} else {
		/* I don't know what it is */
		name = "";
	}

	if (!name) {
		name = ERR_PTR(-EBADF);
	}

	return name;
}
Exemple #9
0
/**
 * ctrl_ioctl - ioctl() method for the C/R control node
 * @inode: (struct inode *) of the control node
 * @file: (struct file *) of the control node
 * @op: The operation/command to perform
 * @arg: The (optional) argument to the command as an unsigned long
 *
 * DESCRIPTION:
 * This function is the ioctl() method in the file_operations for
 * the C/R control node.  It acts as a dispatcher to the functions
 * which do the real work.
 */
static int ctrl_ioctl(struct inode *inode, struct file *file,
		      unsigned int op, unsigned long arg)
{
	CR_KTRACE_FUNC_ENTRY("op=%08x arg=0x%lx", op, arg);

	switch(op) {
	//
	// Calls from libcr:
	//
	// XXX: When adding cases here, also add to the ioctl32 init/cleanup
	//      code below and to the big switch in cr_compat.c.
	case CR_OP_HAND_CHKPT:
		return cr_dump_self(file, arg);

	case CR_OP_HAND_ABORT:
		return cr_hand_abort(file, arg);

	case CR_OP_HAND_SUSP:
		return cr_suspend(file, (struct timeval __user *)arg);

	case CR_OP_HAND_PHASE1:
		return cr_phase1_register(file, (int)arg);

	case CR_OP_HAND_PHASE2:
		return cr_phase2_register(file, (int)arg);

	case CR_OP_HAND_SRC:
		return cr_rstrt_src(file, (char __user *)arg);

	case CR_OP_HAND_CHKPT_INFO:
		return cr_chkpt_info(file, (struct cr_chkpt_info __user *)arg);

	case CR_OP_HAND_DONE:
		return cr_hand_complete(file, arg);


	//
	// Calls from cr_checkpoint:
	//
	case CR_OP_CHKPT_REQ:
		return cr_chkpt_req(file, (struct cr_chkpt_args __user *)arg);

	case CR_OP_CHKPT_REAP:
		return cr_chkpt_reap(file);

	case CR_OP_CHKPT_FWD:
		return cr_chkpt_fwd(file, (struct cr_fwd_args __user *)arg);

	case CR_OP_CHKPT_LOG:
		return cr_chkpt_log(file, (struct cr_log_args __user *)arg);

	//
	// Calls from cr_restart:
	//
	case CR_OP_RSTRT_REQ:
		return cr_rstrt_request_restart(file, (struct cr_rstrt_args __user *)arg);

	case CR_OP_RSTRT_REAP:
		return cr_rstrt_reap(file);

	case CR_OP_RSTRT_CHILD:
		return cr_rstrt_child(file);

	case CR_OP_RSTRT_PROCS:
		return cr_rstrt_procs(file, (struct cr_procs_tbl __user *)arg);

	case CR_OP_RSTRT_LOG:
		return cr_rstrt_log(file, (struct cr_log_args __user *)arg);

	//
	// General calls
	//
	case CR_OP_VERSION:
	    {
		// Simple enough to do here
		// User-space must have equal MAJOR and MINOR <= kernel
		// If we supported multiple major versions then this is
		// where we could do the "personallity switching".
		unsigned long major = (arg >> 16);
		unsigned long minor = (arg & 0xffff);
		// If major==0, must match minor; otherwise user-MINOR <= kernel-MINOR
		int match = (major == CR_MODULE_MAJOR) &&
			    (major ? (minor <= CR_MODULE_MINOR)
				   : (minor == CR_MODULE_MINOR));
		if (!match) {
		    CR_WARN("request from pid %d for unsupported version %d.%d",
			    (int)current->pid, (int)major, (int)minor);
		}
		return match ? 0 : -CR_EVERSION;
	    }

	default:
		CR_KTRACE_BADPARM("unknown op %x", _IOC_NR(op));
		return -ENOTTY;
	}
}