예제 #1
0
/** 
 * \<\<public\>\> Skeleton response message rx constructor.
 * This method is called by the factory class.
 *
 * @param msg_id - message ID that will be used for this error message
 * instance.
 * @return a new error message or NULL.
 */
struct tcmi_msg* tcmi_skelresp_msg_new_rx(u_int32_t msg_id)
{
	struct tcmi_skelresp_msg *msg;

	/* Check if the factory is building what it really thinks. */
	if (msg_id != TCMI_SKELRESP_MSG_ID) {
		mdbg(ERR3, "Factory specified message ID(%x) doesn't match real ID(%x)",
		     msg_id, TCMI_SKELRESP_MSG_ID);
		goto exit0;
	}
	if (!(msg = TCMI_SKELRESP_MSG(kmalloc(sizeof(struct tcmi_skelresp_msg), 
					    GFP_KERNEL)))) {
		mdbg(ERR3, "Can't allocate testing message");
		goto exit0;
	}
	/* Initialized the message for receiving, message ID is extended with error flags */
	if (tcmi_msg_init_rx(TCMI_MSG(msg), TCMI_SKELRESP_MSG_ID, &skelresp_msg_ops)) {
		mdbg(ERR3, "Error initializing testing message %x", msg_id);
		goto exit1;
	}

	return TCMI_MSG(msg);

	/* error handling */
 exit1:
	kfree(msg);
 exit0:
	return NULL;
}
/** 
 * \<\<public\>\> PPM_P message rx constructor.
 * This method is called by the factory class.
 *
 * @param msg_id - message ID that will be used for this error message
 * instance.
 * @return a new error message or NULL.
 */
struct tcmi_msg* tcmi_ppm_p_migr_back_guestreq_procmsg_new_rx(u_int32_t msg_id)
{
	struct tcmi_ppm_p_migr_back_guestreq_procmsg *msg;

	/* Check if the factory is building what it really thinks. */
	if (msg_id != TCMI_PPM_P_MIGR_BACK_GUESTREQ_PROCMSG_ID) {
		mdbg(ERR3, "Factory specified message ID(%x) doesn't match real ID(%x)",
		     msg_id, TCMI_PPM_P_MIGR_BACK_GUESTREQ_PROCMSG_ID);
		goto exit0;
	}
	/* Allocate the instance */
	if (!(msg = TCMI_PPM_P_MIGR_BACK_GUESTREQ_PROCMSG(kmalloc(sizeof(struct tcmi_ppm_p_migr_back_guestreq_procmsg), 
								 GFP_KERNEL)))) {
		mdbg(ERR3, "Can't allocate test request message");
		goto exit0;
	}
	/* Initialize the message for receiving. */
	if (tcmi_procmsg_init_rx(TCMI_PROCMSG(msg), TCMI_PPM_P_MIGR_BACK_GUESTREQ_PROCMSG_ID, 
				 &ppm_p_migr_back_guestreq_procmsg_ops)) {
		mdbg(ERR3, "Error initializing test request message %x", msg_id);
		goto exit1;
	}

	return TCMI_MSG(msg);

	/* error handling */
 exit1:
	kfree(msg);
 exit0:
	return NULL;
}
예제 #3
0
/** \<\<public\>\> Close proxyfile
 * @param *self - pointer to this file instance
 *
 * @return zero on succes
 * */
int proxyfs_proxy_file_close(struct proxyfs_proxy_file_t *self)
{
	struct proxyfs_msg *msg;
	struct proxyfs_msg *msg_resp;
	long rtn = -ERESTARTSYS;
	u_int32_t exitting = current->flags & PF_EXITING;

	mdbg(INFO2, "Close proxy file requested. Ident: %lu Exitting: %d", proxyfs_file_get_file_ident(PROXYFS_FILE(self)), exitting );
	
	// We have to wait for a write buffer empty event..
	// TODO: however, if the peer connection is broken, this will never happen, and the close method will block.. what to do? Likely we should wait with some long timeout and then just break (or at least recheck connection)
	if( proxyfs_proxy_file_wait_interruptible(self, PROXYFS_FILE_ALL_WRITTEN ) == 0 ) {
		minfo(ERR2, "Closing of ident: %lu failed. Not all written", proxyfs_file_get_file_ident(PROXYFS_FILE(self)));
		return -ERESTARTSYS;
	}

	msg = proxyfs_msg_new(MSG_CLOSE, proxyfs_file_get_file_ident(PROXYFS_FILE(self)), sizeof(exitting), &exitting); 
	if(msg != NULL){
		msg_resp = proxyfs_client_do_syscall(self->task, self, msg);
		// What the fck?????
		if( msg_resp == (void*)MSG_CLOSE_RESP )
			rtn = 0;
	}

  
	if ( rtn != 0 && proxyfs_peer_get_state(PROXYFS_FILE(self)->peer) != PEER_CONNECTED) {
	      // Even if our remote syscall has failed, we have to pretend it succeded as the peer is no longer connected and there is no chance of further close success
	      rtn = 0;
	}

	mdbg(INFO2, "Close proxy file request DONE, Res: %ld", rtn);

	return rtn;
}
예제 #4
0
/** \<\<public\>\> Used to set proper tid after a new process was forked.. it must be run in that process context */
int tcmi_guesttask_post_fork_set_tid(void *self, struct tcmi_method_wrapper *wr) {
	int res = TCMI_TASK_KEEP_PUMPING;
	struct tcmi_task *self_tsk = TCMI_TASK(self);

	mdbg(INFO3, "Task - remote pid %d being set after fork",
	     tcmi_task_remote_pid(self_tsk));

        if (current->set_child_tid) {
		mdbg(INFO3, "Tid set required");	     	
                put_user(tcmi_task_remote_pid(self_tsk), current->set_child_tid);
	}

	if ( thread_group_leader(current) ) { // Proxyfs file names changing is required only for group leaders
		// TODO: Make a separate method for this, it does not belong here
		// Modifies proxyfs file references to references specific to this task
		if ( proxyfs_clone_file_names(tcmi_task_remote_pid(self_tsk)) ) {
			mdbg(INFO3, "Task proxy fs clonning has failed. Pid %d", tcmi_task_remote_pid(self_tsk));
			// We cannot simply return KILL_ME here.. this would remove current TCMI task and kill the process,
			// but the exit hook won't be called!
			force_sig(SIGKILL, current);
		}
	}

	return res;
}
/**
 * \<\<private\>\> Receives the message via a specified connection.
 * Receiving the message requires reading checkpoint size.  Based on
 * the size, it allocates space for the checkpoint name string and reads it
 * from the socket.
 *
 * @param *self - this message instance
 * @param *sock - KKC socket used for receiving message data
 * @return 0 when successfully received.
 */
static int tcmi_ppm_p_migr_back_guestreq_procmsg_recv(struct tcmi_procmsg *self, struct kkc_sock *sock)
{
	int err = -EINVAL;
	struct tcmi_ppm_p_migr_back_guestreq_procmsg *self_msg = TCMI_PPM_P_MIGR_BACK_GUESTREQ_PROCMSG(self);
	
	/* Receive the remote PID and checkpoint name size */	
	if ((err = kkc_sock_recv(sock, &self_msg->size, 
				 sizeof(self_msg->size), KKC_SOCK_BLOCK)) < 0) {
		mdbg(ERR3, "Failed to receive pid and size");
		goto exit0;
	}


	if (!(self_msg->ckpt_name = (char*)kmalloc(self_msg->size, GFP_KERNEL))) {
		mdbg(ERR3, "Can't allocate memory for checkpoint name");
		goto exit0;
	}
	
	/* Receive the checkpoint name */	
	if ((err = kkc_sock_recv(sock, self_msg->ckpt_name, 
				 self_msg->size, KKC_SOCK_BLOCK)) < 0) {
		mdbg(ERR3, "Failed to receive checkpoint name");
		goto exit0;
	}
	mdbg(INFO2, "PPM_P migrate back guest request received guest PID=%d, size=%d, ckptname='%s'",
	     tcmi_procmsg_dst_pid(self), self_msg->size, self_msg->ckpt_name);

	return 0;
	/* error handling*/
 exit0:
	return err;
}
예제 #6
0
static void handlePSMsg(DDTypedBufferMsg_t *msg)
{
    if (msg->header.dest == PSC_getMyTID()) {
	/* message for me, let's get infos and forward to all accounters */

	mdbg(PSACC_LOG_ACC_MSG, "%s: got msg %s\n", __func__,
	     getAccountMsgType(msg->type));

	switch (msg->type) {
	    case PSP_ACCOUNT_QUEUE:
	    case PSP_ACCOUNT_DELETE:
	    case PSP_ACCOUNT_SLOTS:
	    case PSP_ACCOUNT_START:
		/* nothing to do here for me */
		break;
	    case PSP_ACCOUNT_LOG:
		handleAccountLog(msg);
		break;
	    case PSP_ACCOUNT_CHILD:
		handleAccountChild(msg);
		break;
	    case PSP_ACCOUNT_END:
		handleAccountEnd(msg);
		break;
	    default:
		mlog("%s: invalid msg type %i sender %s\n", __func__, msg->type,
		     PSC_printTID(msg->header.sender));
	}
	mdbg(PSACC_LOG_VERBOSE, "%s: msg type %s sender %s\n", __func__,
	     getAccountMsgType(msg->type), PSC_printTID(msg->header.sender));
    }

    /* forward msg to accounting daemons */
    if (origHandler) origHandler((DDBufferMsg_t *) msg);
}
예제 #7
0
/**
 * Internal helper method for performing both npm/ppm physical migration back to ccn.
 *
 * @return 0 on success, error code otherwise
 */
static int tcmi_guesttask_migrateback_p(struct tcmi_task* self, struct tcmi_npm_params* npm_params) {
	struct tcmi_msg *req;

	mdbg(INFO2, "Process '%s' - guest local PID %d, migrating back (npm params: %p)", current->comm, tcmi_task_local_pid(self), npm_params);

	if (tcmi_taskhelper_checkpoint(self, npm_params) < 0) {
		mdbg(ERR3, "Failed to create a checkpoint");
		goto exit0;
	}
	tcmi_taskhelper_flushfiles();
	if (!(req = tcmi_ppm_p_migr_back_guestreq_procmsg_new_tx(tcmi_task_remote_pid(self), tcmi_task_ckpt_name(self)))) {
		mdbg(ERR3, "Error creating a migration back message");
		goto exit0;
	}
	if (tcmi_task_check_peer_lost(self, tcmi_task_send_anonymous_msg(self, req)) < 0) {
		mdbg(ERR3, "Failed to send message!!");
		goto exit1;
	}

	director_migrated_home(tcmi_task_local_pid(self));
	
	return 0;
 exit1:
	tcmi_msg_put(req);
 exit0:
	return -EFAULT;
}
예제 #8
0
/**
 * \<\<public\>\> Symbolic link is created as a regular ctlfs
 * entry. In addition, it retains an extra reference to the target
 * object. 
 *
 * @param *parent - pointer to the parent entry - has to be a directory
 * @param *target - target entry to which link should point to
 * @param namefmt - nameformat string (printf style)
 * @return new symlink instance or NULL
 */
struct tcmi_ctlfs_entry* tcmi_ctlfs_symlink_new(struct tcmi_ctlfs_entry *parent,
						struct tcmi_ctlfs_entry *target,
						const char namefmt[], ...)
{
	struct tcmi_ctlfs_symlink *symlink;
	va_list args;
	va_start(args, namefmt);
	mdbg(INFO4, "Creating new symlink");

	if (!(symlink = kmalloc(sizeof(struct tcmi_ctlfs_symlink), GFP_ATOMIC))) {
		mdbg(ERR3, "Failed to allocate memory for symlink");
		goto exit0;
	}
	if (tcmi_ctlfs_entry_init(TCMI_CTLFS_ENTRY(symlink), 
				  TCMI_CTLFS_ENTRY(parent), 
				  S_IFLNK|S_IRWXUGO,
				  &tcmi_ctlfs_symlink_ops,
				  &tcmi_ctlfs_symlink_inode_operations,
				  NULL, namefmt, args)) {
		mdbg(ERR3, "Failed to initialize the symlink");
		goto exit1;
	}
	symlink->target_entry = tcmi_ctlfs_entry_get(target);
	va_end(args);

	return TCMI_CTLFS_ENTRY(symlink);

	/* error handling */
 exit1:
	kfree(symlink);
 exit0:
	va_end(args);
	return NULL;
}
예제 #9
0
/**
 * \<\<public\>\> TCMI CCN manager constructor.
 * The initialization is accomplished exactly in this order:
 * - create new instance
 * - allocate new slot vector for shadow processes.
 * - delegates all remaining intialization work to the generic manager.
 * - authenticate the connecting PEN
 * 
 * @param *parent - pointer to struct of parent for example - decrement count of connected nodes*
 * @param *sock - socket where the new PEN is registering
 * @param ccn_id - CCN identifier
 * @param *root - directory where the migration manager should create its
 * files and directories
 * @param *migproc - directory where the migrated process will have their info
 * @param namefmt - nameformat string for the main manager directory name (printf style)
 * @param ... - variable arguments
 * @return new TCMI CCN manager instance or NULL
 */
struct tcmi_migman* tcmi_ccnmigman_new(struct tcmi_man *parent, struct kkc_sock *sock, u_int32_t ccn_id, struct tcmi_slot* manager_slot,
					  struct tcmi_ctlfs_entry *root,
				       struct tcmi_ctlfs_entry *migproc,
					  const char namefmt[], ...)
{
	struct tcmi_ccnmigman *migman;
	va_list args;

	minfo(INFO2, "Creating new TCMI CCN migration manager");
	if (!(migman = TCMI_CCNMIGMAN(kmalloc(sizeof(struct tcmi_ccnmigman), 
					      GFP_KERNEL)))) {
		mdbg(ERR3, "Can't allocate memory for CCM migration manager");
		goto exit0;
	}
	init_waitqueue_head(&migman->wq);
	va_start(args, namefmt);
	if (tcmi_migman_init(parent ,TCMI_MIGMAN(migman), sock, ccn_id, 0, UNKNOWN, manager_slot, root, migproc,
			     &ccnmigman_ops, namefmt, args) < 0) {
		mdbg(ERR3, "TCMI CCN migman initialization failed!");
		va_end(args);
		goto exit1;
	}
	va_end(args);
	
	return TCMI_MIGMAN(migman);

	/* error handling */
 exit1:
	kfree(migman);
 exit0:
	return NULL;
}
예제 #10
0
/** 
 * \<\<public\>\> Error message constructor for transferring. 
 *
 * An error message is considered one way only and is usually used as a
 * error response to some other process message. The user thus has to specify
 * the transaction ID of the message that the error message is a response too.
 * Messages with TCMI_TRANSACTION_INVAL_ID are possible too. No search
 * for a matching transaction will be performed at the receiving party and
 * the message will be queued in a regular request queue. 
 *
 * As for any other process message, the destination PID has to be specified
 *
 * @param msg_id - ID assigned to the error message, it will be extended
 * with error flags, so that the message factory at the receiving party uses
 * the above implemented tcmi_err_procmsg_new_rx() constructor.
 * @param trans_id - transaction ID 
 * @param err_code - error code that will be stored in the message
 * @param dst_pid - destination process PID
 * @return a new error ready for the transfer or NULL.
 */
struct tcmi_msg* tcmi_err_procmsg_new_tx(u_int32_t msg_id, u_int32_t trans_id, int err_code,
					 pid_t dst_pid)
{
	struct tcmi_err_procmsg *msg;

	if (!(msg = TCMI_ERR_PROCMSG(kmalloc(sizeof(struct tcmi_err_procmsg), GFP_KERNEL)))) {
		mdbg(ERR3, "Can't allocate memory for error message %x", msg_id);
		goto exit0;
	}

	/* Initialize the message for transfer, message ID is
	 * extended with error flags, no transaction created or
	 * response ID setup. Only the transaction ID, that will get
	 * send along with the message, is set. */
	if (tcmi_procmsg_init_tx(TCMI_PROCMSG(msg), TCMI_MSG_FLG_SET_ERR(msg_id), &err_procmsg_ops, 
				 dst_pid, 0,
				 NULL, 0, 0, trans_id)) {
		mdbg(ERR3, "Error initializing error message %x", msg_id);
		goto exit1;
	}
	msg->err_code = err_code;
	return TCMI_MSG(msg);

	/* error handling */
 exit1:
	kfree(msg);
 exit0:
	return NULL;
	
}
예제 #11
0
/**
 * \<\<private\>\> The path is built as follows:
 * - The path needs to be traversed to the root directory first '../', the number
 * of these elements is determined by the depth of the symlink in the tree.
 * - the minimum required buffer length is calculated based on:
 *        - symlink depth (see above)
 *        - pathname length of the target entry
 * - the buffer is then filled with ../'s
 * - the path of the target entry is then filled in
 * 
 * Should the target entry be invalid, the function terminates with an error
 * access to the target entry is serialized by the lock. 
 *
 * @param *self - pointer to this instance
 * @param *path - storage buffer for the path
 * @param length - maximum path length (storage buffer size)
 * @return 0 upon success
 */
static int tcmi_ctlfs_symlink_get_link(struct tcmi_ctlfs_symlink *self, 
				       char *path, int length)
{
	char * s;
	int depth, size;
	int err = -EINVAL;

	depth = tcmi_ctlfs_entry_depth(TCMI_CTLFS_ENTRY(self));
	/* we are interested in the depth of the parent entry, this is safe since
	 a minimum symlink depth is 1 (when it resides in the root directory) */
	depth--;
	size = tcmi_ctlfs_entry_path_length(self->target_entry) + depth * 3 - 1;
	if (size > length) {
		err = -ENAMETOOLONG;
		goto exit0;
	}
	mdbg(INFO4,"depth = %d, size = %d", depth, size);

	for (s = path; depth--; s += 3)
		strcpy(s,"../");

	if (self->target_entry)
		tcmi_ctlfs_entry_fill_path(self->target_entry, path, size);

	mdbg(INFO3, "path = '%s'\n", path);

	return 0;

	/* error handling */
 exit0:
/*   tcmi_ctlfs_symlink_unlock(self); */
	return err;
}
예제 #12
0
/**
 * \<\<public\>\> Prepares execution of a file given the arrays of arguments and
 * environment.  Allocates memory for all execve parameters and copies
 * the parameters into the instance.  The main purpose of this method
 * is setup everything for execve. After using this method, the caller
 * is able to release all memory resources and issue
 * tcmi_task_execve().
 *
 * To reduce the overhead when releasing the argv/envp arrays of the task,
 * the layout of each array is as follows. All strings are put
 * at the end of the array.
 *
 \verbatim
 +-------------+
 | pointer  0  |--+
 +-------------+  |
 | pointer  1  |--------------------+
 +-------------+  |                 |
 .             .  |                 |
 .             .  |                 |
 +-------------+  |                 |
 | pointer  n  |---------------------------------------------+
 +-------------+  |                 |                        |
 | NULL        |  |                 |                        |
 +-------------+--V-----------------V------------------------V----------+
 | "string 0 goes up here\0", "string 1 here\0", ..., "string n here\0" |
 +----------------------------------------------------------------------+

 \endverbatim 
 * This code can be used to printout the argv/envp arrays for testing.
 \verbatim
	int i;
	mdbg(INFO3, "Environ test");
	for(i = 0; self->argv[i] != NULL; i++)
		mdbg(INFO3, "ARGV[%d]='%s'", i, self->argv[i]);

	for(i = 0; self->envp[i] != NULL; i++)
		mdbg(INFO3, "ENVP[%d]='%s'", i, self->envp[i]); 

 \endverbatim
 *
 * @param *self - pointer to this task instance
 * @param *file
 * @param **argv - arguments list terminated by NULL
 * @param **envp - environment strings terminated by NULL
 * @return 0 upon success, otherwise -ENOEXEC
 */
int tcmi_task_prepare_execve(struct tcmi_task *self, char *file, char **argv, char **envp)
{
	/* release the old context first. */
	tcmi_task_release_execve_context(self);

	if (!(self->ckpt_pathname = (char*)kmalloc(strlen(file) + 1, GFP_ATOMIC))) {
		mdbg(ERR3, "Can't allocate memory for execve file '%s'", file);
		goto exit0;
	}
	strcpy(self->ckpt_pathname, file);
	if (tcmi_task_copy_strings(&self->argv, argv) < 0) {
		mdbg(ERR3, "Failed copying ARGV array for file '%s'", file);
		goto exit1;
	}
	if (tcmi_task_copy_strings(&self->envp, envp) < 0) {
		mdbg(ERR3, "Failed copying ENVP array for file '%s'", file);
		goto exit2;
	}
	mdbg(INFO4, "Allocated TCMI task execve context(%s, %p, %p) PID=%d, %p", 
	     self->ckpt_pathname, self->argv, self->envp, tcmi_task_local_pid(self), self);
	return 0;

	/* error handling */
 exit2:
	kfree(self->argv);
	self->argv = NULL;
 exit1:
	kfree(self->ckpt_pathname);
	self->ckpt_pathname = NULL;
 exit0:
	return -ENOEXEC;
}
예제 #13
0
/** 
 * \<\<public\>\> Processes all methods in the queue.  This method is
 * used as a method pump, it keeps on unwrapping methods from the
 * queue and executing them until one of them returns a results
 * different from TCMI_TASK_KEEP_PUMPING. This result is communicated
 * to the component that controls this particular task (usually the
 * migration component). Every iteration, the signals are also
 * handled. This might also influence the method pump and terminate
 * it.
 *
 * The method wrapper is released once the method is executed only if
 * there was no execve problem. To explain this: some methods perform
 * an execve operation - in which case, the execution context changes
 * immediately. Therefore, these methods have to discard the method
 * wrapper on their own. Should the execve fail, they have already
 * discarded the wrapper and thus have on control over it. In that
 * case, the returned error is TCMI_TASK_EXECVE_FAILED_KILL_ME and we
 * have to prevent releasing this method wrapper.
 *
 * The specific task method that had been executed had a
 * chance to get an extra reference and resubmit the method wrapper
 * into the method queue.
 *
 * @param *self - pointer to this task instance
 * @return result of the last executed method
 */
int tcmi_task_process_methods(struct tcmi_task *self)
{
	int res = TCMI_TASK_KEEP_PUMPING;
	struct tcmi_method_wrapper *w;

	while ((!tcmi_queue_empty(&self->method_queue)) && 
	       (res == TCMI_TASK_KEEP_PUMPING)) {
		/* handle any pending signals */
		if ((res = tcmi_taskhelper_do_signals(self)) != TCMI_TASK_KEEP_PUMPING)
			break;

		/* get next method to proces */
		tcmi_queue_remove_entry(&self->method_queue, w, node);
		/* unwrap & destroy the method wrapper excluding the execve failure */
		if ((res = tcmi_method_wrapper_call(w, self)) != 
		    TCMI_TASK_EXECVE_FAILED_KILL_ME) {			
			mdbg(INFO3, "Execve have NOT failed.");
			tcmi_method_wrapper_put(w);
		} else {
			mdbg(INFO3, "Execve have failed.");
		}
	}

	mdbg(INFO3, "Process methods finished with res %d", res);

	return res;
}
예제 #14
0
/** 
 * \<\<public\>\> Skeleton response message tx constructor.
 *
 * The testing response message is a one-way message, no transaction
 * is needs to be started, the user only needs to specify the
 * transaction ID that it is the reply to.
 *
 * When performing the generic tx init, the response message ID is
 * specified (TCMI_SKELRESP_MSG_ID)
 *
 * @param trans_id - transaction ID that this message is replying to.
 * @return a new test response message for the transfer or NULL.
 */
struct tcmi_msg* tcmi_skelresp_msg_new_tx(u_int32_t trans_id)
{
	struct tcmi_skelresp_msg *msg;

	if (!(msg = TCMI_SKELRESP_MSG(kmalloc(sizeof(struct tcmi_skelresp_msg), 
					    GFP_KERNEL)))) {
		mdbg(ERR3, "Can't allocate testing message");
		goto exit0;
	}

	/* Initialize the message for transfer, no transaction
	 * required, no timout, no response ID */
	if (tcmi_msg_init_tx(TCMI_MSG(msg), TCMI_SKELRESP_MSG_ID, &skelresp_msg_ops, 
			     NULL, 0, 0, trans_id)) {
		mdbg(ERR3, "Error initializing testing response message");
		goto exit1;
	}
	return TCMI_MSG(msg);

	/* error handling */
 exit1:
	kfree(msg);
 exit0:
	return NULL;
	
}
예제 #15
0
int ccfs_write_lower(struct inode *ccfsinode, char *data,
			 loff_t offset, size_t size)
{
	struct ccfs_inode *inode_info;
	ssize_t octets_written;
	mm_segment_t fs_save;
	int rc = 0;

	inode_info = ccfs_inode_to_private(ccfsinode);
	mutex_lock(&inode_info->lower_file_mutex);
	BUG_ON(!inode_info->lower_file);
	inode_info->lower_file->f_pos = offset;
	mdbg(INFO3, "Inode %p has lower file: %p (%ld)", ccfsinode, inode_info->lower_file, atomic_long_read(&inode_info->lower_file->f_count));
	
	fs_save = get_fs();
	set_fs(get_ds());
	octets_written = vfs_write(inode_info->lower_file, data, size,
				   &inode_info->lower_file->f_pos);
	set_fs(fs_save);
	if (octets_written < 0) {
	  	mdbg(INFO3, "Error writing. Written %lld, size %ud", (long long) octets_written, (unsigned int) size);
		rc = -EINVAL;
	}	
	mutex_unlock(&inode_info->lower_file_mutex);
	mark_inode_dirty_sync(ccfsinode);
	return rc;
}
예제 #16
0
파일: inode.c 프로젝트: FIT-CVUT/clondike
static int ccfs_setattr(struct dentry *dentry, struct iattr *ia)
{
	int rc = 0;
	struct dentry *lower_dentry;
	struct inode *inode;
	struct inode *lower_inode;

	inode = dentry->d_inode;
	lower_inode = ccfs_get_nested_inode(inode);
	lower_dentry = ccfs_get_nested_dentry(dentry);
	
	if (ia->ia_valid & ATTR_SIZE) {
		mdbg(INFO3,
				"ia->ia_valid = [0x%x] ATTR_SIZE" " = [0x%x]",
				ia->ia_valid, ATTR_SIZE);
		rc = ccfs_truncate(dentry, ia->ia_size);
		ia->ia_valid &= ~ATTR_SIZE;
		mdbg(INFO3,"ia->ia_valid = [%x]",
				ia->ia_valid);
		if (rc < 0)
			goto out;
	}

	/*
	 * mode change is for clearing setuid/setgid bits. Allow lower fs
	 * to interpret this in its own way.
	 */
	if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
		ia->ia_valid &= ~ATTR_MODE;

	rc = notify_change(lower_dentry, ia);
out:
	fsstack_copy_attr_all(inode, lower_inode);
	return rc;
}
예제 #17
0
/**
 * \<\<public\>\> Reads a memory area from the checkpoint file. Reads
 * the VM area header and checks for the requested type. The actual
 * work is then delegated to the light or heavy version of this
 * method.
 *
 * @param *ckpt - checkpoint file where the area is stored
 * @return 0 upon success.
 */
int tcmi_ckpt_vm_area_read(struct tcmi_ckpt *ckpt)
{
	int err = 0;
	struct tcmi_ckpt_vm_area_hdr hdr;
	
	if (tcmi_ckpt_read(ckpt, &hdr, sizeof(hdr)) < 0) {
		mdbg(ERR3, "Error read VM aread header");
		goto exit0;
	}
	mdbg(INFO4, "Reading VMA start:%08llx, end: %08llx, flags: %08llx, pgoff %08llx", 
	     (unsigned long long)hdr.vm_start, (unsigned long long)hdr.vm_end, (unsigned long long)hdr.vm_flags, (unsigned long long)hdr.vm_pgoff);
	/* light version only when it's non-writable and  maps a file */
	if (hdr.type == TCMI_CKPT_VM_AREA_LIGHT)
		err = tcmi_ckpt_vm_area_read_l(ckpt, &hdr);
	else if (hdr.type == TCMI_CKPT_VM_AREA_HEAVY)
		err = tcmi_ckpt_vm_area_read_h(ckpt, &hdr);
	else {
		mdbg(ERR3, "Unrecognized header type %x", hdr.type);
		goto exit0;
	}
	return err;

	/* error handling */
 exit0:
	return -EINVAL;
}
예제 #18
0
파일: inode.c 프로젝트: FIT-CVUT/clondike
//Replaced last parameter struct nameidata to bool excl and changed type mode parameter to umode_t | by Jiri Rakosnik
static int ccfs_do_create(struct inode *directory_inode, struct dentry *ecryptfs_dentry, umode_t mode, bool excl)
{
	int rc;
	struct dentry *lower_dentry;
	struct dentry *lower_dir_dentry;

	lower_dentry = ccfs_get_nested_dentry(ecryptfs_dentry);
	lower_dir_dentry = lock_parent(lower_dentry);
	if (unlikely(IS_ERR(lower_dir_dentry))) {
		mdbg(ERR1, "Error locking directory of "
				"dentry");
		rc = PTR_ERR(lower_dir_dentry);
		goto out;
	}
	rc = ccfs_create_underlying_file(lower_dir_dentry->d_inode, ecryptfs_dentry, mode, excl);
	
	if (unlikely(rc)) {
		mdbg(ERR1,
				"Failure to create underlying file");
		goto out_lock;
	}
	rc = ccfs_interpose(lower_dentry, ecryptfs_dentry,
				directory_inode->i_sb, 0);
	if (rc) {
		mdbg(ERR1, "Failure in ccfs_interpose");
		goto out_lock;
	}
	fsstack_copy_attr_times(directory_inode, lower_dir_dentry->d_inode);
	fsstack_copy_inode_size(directory_inode, lower_dir_dentry->d_inode);
out_lock:
	unlock_dir(lower_dir_dentry);
out:
	return rc;
}
예제 #19
0
/**
 * \<\<public\>\> Initializes a root entry instance.
 *
 * @param *self - pointer to this instance
 * @param *sb - pointer to the super block of the filesystem
 * @param *mode - file type and access rights for the inode
 * @param *entry_ops - custom operations of the child class
 * @param *i_ops - inode operations
 * @param *f_ops - file operations(also stored in the new inode)
 * @return 0 upon success
 */
int tcmi_ctlfs_rootentry_init(struct tcmi_ctlfs_entry *self,
                              struct super_block *sb,
                              mode_t mode,
                              struct tcmi_ctlfs_ops *entry_ops,
                              const struct inode_operations *i_ops,
                              const struct file_operations *f_ops)
{
    struct dentry *root;
    struct inode *inode;

    mdbg(INFO3, "Initializing a root entry");
    if (!(inode = tcmi_ctlfs_get_inode(NULL, sb, mode, i_ops, f_ops))) {
        mdbg(ERR1, "Failed to allocate inode for root dentry!");
        goto exit0;
    }
    /* try allocating the dentry */
    //Replaced function d_alloc_root to d_make_root for kernel 3.x | by Jiri Rakosnik
    if (!(root = d_make_root(inode))) {
        mdbg(ERR1, "Failed to allocate a root dentry!");
        goto exit1;
    }
    /* Initialize the dentry */
    root->d_fsdata = (void *)self;
    root->d_op = &tcmi_ctlfs_dentry_ops;
    self->dentry = root;
    sb->s_root = root;
    /* Custom operations of the child class */
    self->entry_ops = entry_ops;
    return 0;
    /* error handling*/
exit1:
    iput(inode);
exit0:
    return -ENOSPC;
}
예제 #20
0
void fetchAccInfo(Job_t *job)
{
    AccountDataExt_t accData;

    if (job->pid == -1) return;

    mdbg(PSMOM_LOG_ACC, "%s: request for job-pid %i\n", __func__, job->pid);
    psAccountGetDataByJob(job->pid, &accData);

    uint64_t avgVsize = accData.avgVsizeCount ?
	accData.avgVsizeTotal / accData.avgVsizeCount : 0;
    uint64_t avgRss = accData.avgRssCount ?
	accData.avgRssTotal / accData.avgRssCount : 0;

    mdbg(PSMOM_LOG_ACC, "%s: account data for pid %d: maxVsize %zu maxRss %zu"
	 " pageSize %lu utime %lu.%06lu stime %lu.%06lu num_tasks %u"
	 " avgVsize %lu avgRss %lu minCPUtime %lu totCPUtime %lu"
	 " maxRssTotal %lu maxVsizeTotal %lu avg cpufrq %.2fG\n", __func__,
	 job->pid, accData.maxVsize, accData.maxRss, accData.pageSize,
	 accData.rusage.ru_utime.tv_sec, accData.rusage.ru_utime.tv_usec,
	 accData.rusage.ru_stime.tv_sec, accData.rusage.ru_stime.tv_usec,
	 accData.numTasks, avgVsize, avgRss,
	 accData.minCputime, accData.totCputime,
	 accData.maxRssTotal, accData.maxVsizeTotal,
	 (double) accData.cpuFreq / ((double) accData.numTasks * 1048576));

    calcJobPollCpuTime(job, accData.cstime, accData.cutime);
    addJobWaitCpuTime(job, accData.totCputime);
    setJobCpuTime(job);
    setJobMemUsage(job, accData.maxRssTotal, accData.maxVsizeTotal);
    setJobWalltime(job);
}
예제 #21
0
int tcmi_guesttask_post_fork(struct tcmi_task* self, struct tcmi_task* child, long fork_result, pid_t remote_child_pid) {
	struct tcmi_msg *m;

	if ( fork_result < 0 ) {
		// Notify CCN about fork-failed
		// We're reusing exit msg here, but it may be better to introduce a specific event for this, right?
		if (!(m = tcmi_exit_procmsg_new_tx(remote_child_pid, fork_result))) {
			mdbg(ERR3, "Can't create failed-fork exit message");
			goto exit0;
		}
	} else {
		BUG_ON(child == NULL); // If fork succeeded, child cannot be null, right?

		tcmi_task_set_remote_pid(child, remote_child_pid);		

		if (!(m = tcmi_guest_started_procmsg_new_tx(TCMI_TRANSACTION_INVAL_ID, 
							      tcmi_task_remote_pid(child), 
							      tcmi_task_local_pid(child)))) {
			mdbg(ERR3, "Cannot create a guest response in post-fork!");
			goto exit0;
		}		
	}

	tcmi_task_send_anonymous_msg(self, m);
	tcmi_msg_put(m);

	return 0;

exit0:
	// TODO: Some better failure handling? Shall we stop this task, if we've failed to inform CCN that it is running? CCN does not know it's ID in this case...
	return -EINVAL;
}
예제 #22
0
/** 
 * \<\<public\>\> Message rx constructor.
 * This method is called by the factory class.
 *
 * @param msg_id - message ID that will be used for this message
 * instance.
 * @return a new message or NULL.
 */
struct tcmi_msg* tcmi_disconnect_msg_new_rx(u_int32_t msg_id)
{
	struct tcmi_disconnect_msg *msg;

	/* Check if the factory is building what it really thinks. */
	if (msg_id != TCMI_DISCONNECT_MSG_ID) {
		mdbg(ERR3, "Factory specified message ID(%x) doesn't match real ID(%x)",
		     msg_id, TCMI_DISCONNECT_MSG_ID);
		goto exit0;
	}
	/* Allocate the instance */
	if (!(msg = TCMI_DISCONNECT_MSG(kmalloc(sizeof(struct tcmi_disconnect_msg), GFP_KERNEL)))) {
		mdbg(ERR3, "Can't allocate disconnect request message");
		goto exit0;
	}
	
	/* Initialized the message for receiving. */
	if (tcmi_msg_init_rx(TCMI_MSG(msg), TCMI_DISCONNECT_MSG_ID, &disconnect_msg_ops)) {
		mdbg(ERR3, "Error initializing disconnect request message %x", msg_id);
		goto exit1;
	}

	return TCMI_MSG(msg);

	/* error handling */
 exit1:
	kfree(msg);
 exit0:
	return NULL;
}
예제 #23
0
/** 
 * \<\<public\>\> Instance constructor.
 * - allocates a new instance.
 * - delegates its initialization to the super class.
 *
 * @param local_pid - local PID on PEN
 * @param migman - The migration manager that maintains this task
 * @param *sock - socket used for communication with shadow task on CCN
 * @param *d_migproc - directory where ctlfs entries of migrated
 * processes reside
 * @param *d_migman - TCMI ctlfs directory of the migration manager
 * responsible for this task
 * @return 0 upon success
 */
struct tcmi_task* tcmi_guesttask_new(pid_t local_pid, struct tcmi_migman* migman,
				    struct kkc_sock *sock, 
				    struct tcmi_ctlfs_entry *d_migproc, 
				    struct tcmi_ctlfs_entry *d_migman)
{
	struct tcmi_guesttask *task;
	minfo(INFO2, "Creating new TCMI guest task");
	if (!(task = TCMI_GUESTTASK(kmalloc(sizeof(struct tcmi_guesttask), 
						   GFP_ATOMIC)))) {
		mdbg(ERR3, "Can't allocate memory for TCMI ppm guest task");
		goto exit0;
	}
	if (tcmi_task_init(TCMI_TASK(task), local_pid, migman, sock, 
			   d_migproc, d_migman, &guesttask_ops) < 0) {
		mdbg(ERR3, "TCMI ppm guest task initialization failed!");
		goto exit1;
	}

	return TCMI_TASK(task);

	/* error handling */
 exit1:
	kfree(task);
 exit0:
	return NULL;
}
예제 #24
0
/** 
 * \<\<public\>\> Disconnect message tx constructor.
 *
 *
 * @param *transactions - storage for the new transaction
 * @return a new message ready for the transfer or NULL.
 */
struct tcmi_msg* tcmi_disconnect_msg_new_tx(void)
{
	struct tcmi_disconnect_msg *msg;

	if (!(msg = TCMI_DISCONNECT_MSG(kmalloc(sizeof(struct tcmi_disconnect_msg), GFP_KERNEL)))) {
		mdbg(ERR3, "Can't allocate disconnect request message");
		goto exit0;
	}
	
	/* Initialize the message for transfer */
	if (tcmi_msg_init_tx(TCMI_MSG(msg), TCMI_DISCONNECT_MSG_ID, &disconnect_msg_ops, 
			     NULL, 0,
			     0, TCMI_TRANSACTION_INVAL_ID)) {
		mdbg(ERR3, "Error initializing disconnect request message message");
		goto exit1;
	}
	return TCMI_MSG(msg);

	/* error handling */
 exit1:
	kfree(msg);
 exit0:
	return NULL;
	
}
/**
 * \<\<private\>\> Sends the PPM_P migrate back guest request
 *
 * @param *self - this message instance
 * @param *sock - KKC socket used for sending message data
 * @return 0 when successfully sent.
 */
static int tcmi_ppm_p_migr_back_guestreq_procmsg_send(struct tcmi_procmsg *self, struct kkc_sock *sock)
{
	int err;
	struct tcmi_ppm_p_migr_back_guestreq_procmsg *self_msg = TCMI_PPM_P_MIGR_BACK_GUESTREQ_PROCMSG(self);

	
	/* Send the checkpoint name size */	
	if ((err = kkc_sock_send(sock, &self_msg->size, 
				 sizeof(self_msg->size), KKC_SOCK_BLOCK)) < 0) {
		mdbg(ERR3, "Failed to send checkpoint size");
		goto exit0;
	}

	/* Send the checkpoint name */	
	if ((err = kkc_sock_send(sock, self_msg->ckpt_name, 
				 self_msg->size, KKC_SOCK_BLOCK)) < 0) {
		mdbg(ERR3, "Failed to send checkpoint name");
		goto exit0;
	}

	mdbg(INFO2, "PPM_P migrate back guest request sent guest PID=%d, size=%d, ckptname='%s'",
	     tcmi_procmsg_dst_pid(self), self_msg->size, self_msg->ckpt_name);

	return 0;
	/* error handling */
 exit0:
	return err;
	
}
예제 #26
0
/** 
 * \<\<public\>\> Receives a message via a specified connection.
 * - reads the transaction ID from the connection
 * - calls the receive method of the child class
 *
 * The transaction ID is temporarily stored in the instance and will
 * be used upon delivery when searching for the corresponding
 * transaction.
 *
 * @param *self - pointer to this message instance
 * @param *sock - KKC socket used for receiving message data
 * @return >=0 upon success.Unlike tcmi_msg_send() we don't convert a
 * >=0 result to 0 as this will never get communicated to the user.
 * The \link tcmi_comm.c::tcmi_comm_thread receiving thread \endlink
 * is the only component that should use this method.
 */
int tcmi_msg_recv(struct tcmi_msg *self, struct kkc_sock *sock)

{
	int err = 0;
	struct tcmi_msg_ops *ops = self->msg_ops;
	if ((err = kkc_sock_rcv_lock_interruptible(sock))) {
		mdbg(ERR3, "Socket lock - interrupted by a signal %d", err);
		goto exit0;
	}
	/* Receive the transaction ID part */	
	if ((err = kkc_sock_recv(sock, &self->trans_id, 
				 sizeof(self->trans_id), KKC_SOCK_BLOCK)) < 0) {
		mdbg(ERR3, "Failed to receive transaction ID's");
		goto exit1;
	}

	mdbg(INFO3, "Receiving message(ID=%x req=%x resp=%x)", 
	     self->msg_id, self->trans_id.req, self->trans_id.resp);
	/* */
	if (ops && ops->recv) 
		err = ops->recv(self, sock);
	kkc_sock_rcv_unlock(sock);
	return err;

	/* error handling */
 exit1:
	kkc_sock_rcv_unlock(sock);
 exit0:
	return err;
}
예제 #27
0
/**
 * \<\<public\>\> Root entry accessor. If the filesystem has not been
 * activated yet, a kernel mount is performed. The kernel mount in
 * turn ensures instantiation of the root directory. A user might have
 * already mounted the filesystem from userspace. This is not a
 * problem as we allow only one instance of the filesystem in
 * memory(enforced by get_sb_single()), so only a reference counter of
 * the root directory and the associated superblock is
 * incremented. The last thread that releases the last reference to
 * the super block and eventually to the root directory causes the
 * whole filesystem to be released. See tcmi_ctlfs_kill_super() for
 * details on this.
 *
 * If the filesystem is already active (the vfs_mnt is valid), the
 * mount reference count is adjusted.
 *
 * It is necessary to protect the vfs_mnt variable as it can be
 * manipulated by other threads that might issue tcmi_ctlfs_put_root()
 * and release the vfs mount from under us.
 *
 * @return pointer to the root entry (reference counter adjusted by
 * tcmi_ctlfs_entry_get()) or NULL
 */
struct tcmi_ctlfs_entry* tcmi_ctlfs_get_root(void)
{
	down(&self.vfs_mnt_sem);
	/* when the VFS mount is currently inactive we have to create
	 * a new one */
	if (!self.vfs_mnt) {
		mdbg(INFO3, "Mounting");
		self.vfs_mnt = kern_mount(&self.fs_type);
		if (IS_ERR(self.vfs_mnt)) {
			minfo(ERR1, "Could not mount!");
			self.vfs_mnt = NULL;
			/* if the mount failed, the root directory
			 * instance doesn't exist too, so we don't
			 * need to explicitely delete it*/
			self.root_dir = NULL;
		}
	} 
	/* VFS mount still active, just increment its ref. counter */
	else
		mntget(self.vfs_mnt);
	up(&self.vfs_mnt_sem);

	mdbg(INFO3, "sb c_count=%d, s_active=%d", self.sb->s_count, 
	     atomic_read(&self.sb->s_active));
	mdbg(INFO3, "mount mnt_count=%d", atomic_read(&self.vfs_mnt->mnt_count));
	return tcmi_ctlfs_entry_get(self.root_dir);
}
예제 #28
0
/** 
 * \<\<public\>\> Class method - creates a message based on a
 * descriptor.  Verifies, that the message type in the message ID
 * matches the one in the selected descriptor. Then, based on message
 * ID flags calles the regular rx constructor or error rx constructor.
 * This method is meant to be called by the message factory.
 *
 * @param msg_id - this message ID is for verification
 * @param *dsc - descriptor of a message that is to be built
 * @return new message instance or NULL
 */
struct tcmi_msg* tcmi_msg_new_rx(u_int32_t msg_id, struct tcmi_msg_dsc *dsc)
{
	struct tcmi_msg *msg = NULL;

	if (TCMI_MSG_TYPE(msg_id) != TCMI_MSG_TYPE(dsc->msg_id)) {
		mdbg(ERR3, "Requested message ID type(%x) doesn't match the descriptor(%x)",
		     TCMI_MSG_TYPE(msg_id), TCMI_MSG_TYPE(dsc->msg_id));
		goto exit0;
	}
	/* based on message flags call the regular or error rx constructor */
	switch (TCMI_MSG_FLG(msg_id)) {
	case TCMI_MSG_REGFLGS:
		if (!dsc->new_rx) {
			mdbg(ERR3, "Regular rx message constructor not present, bailing out..");
			goto exit0;
		}
		msg = dsc->new_rx(msg_id);
		break;
	case TCMI_MSG_ERRFLGS:
		if (!dsc->new_rx_err) {
			mdbg(ERR3, "Error rx message constructor not present, bailing out..");
			goto exit0;
		}
		msg = dsc->new_rx_err(msg_id);
		break;
	default:
		mdbg(ERR3, "Unexpected message flags value in message ID %x", msg_id);
	}
	return msg;
	/* error handling */
 exit0:
	return NULL;
}
예제 #29
0
/** \<\<public\>\> Fsync proxyfile and coresponding real file
 * @param *self - pointer to this file instance
 *
 * @return zero on succes
 * */
int proxyfs_proxy_file_fsync(struct proxyfs_proxy_file_t *self)
{
	struct proxyfs_msg *msg;
	struct proxyfs_msg *msg_resp;
	long rtn = -ERESTARTSYS;

	mdbg(INFO2, "Fsync requested. Ident: %lu", proxyfs_file_get_file_ident(PROXYFS_FILE(self)));

	// empty write buf
	switch ( proxyfs_proxy_file_wait_interruptible(self, PROXYFS_FILE_ALL_WRITTEN ) ) {
		case 0:
			mdbg(INFO2, "Cannot fsync, interrupted. Ident: %lu", proxyfs_file_get_file_ident(PROXYFS_FILE(self)));
			return -ERESTARTSYS;
		case PROXYFS_FILE_CLOSED:
			mdbg(INFO2, "Cannot fsync, already closed. Ident: %lu", proxyfs_file_get_file_ident(PROXYFS_FILE(self)));
			return -EFAULT;
		default:
			mdbg(INFO3, "Fsync all written, may proceed");		
		// Otherwise process further
	}

	mdbg(INFO2, "Sending fsync request. Ident: %lu", proxyfs_file_get_file_ident(PROXYFS_FILE(self)));

	msg = proxyfs_msg_new(MSG_FSYNC, proxyfs_file_get_file_ident(PROXYFS_FILE(self)), 0, NULL); 
	if(msg != NULL){
		msg_resp = proxyfs_client_do_syscall(self->task, self, msg);
		if( msg_resp == (void*)MSG_FSYNC_RESP )
			rtn = 0;
	}
	return rtn;
}
예제 #30
0
/** 
 * \<\<public\>\> Skeleton message tx constructor.
 *
 * The skeleton message can have a transaction associated with it =
 * there is a response expected for this message by the
 * sender. Therefore, the user specifies the transaction slot vector.
 *
 * When performing the generic tx init, the response message ID is
 * specified (TCMI_RESPSKEL_MSG_ID) so that it will be associated with the
 * transaction
 *
 * @param *transactions - storage for the new transaction(NULL for one-way messages)
 * @return a new error ready for the transfer or NULL.
 */
struct tcmi_msg* tcmi_skel_msg_new_tx(struct tcmi_slotvec *transactions)
{
	struct tcmi_skel_msg *msg;

	if (!(msg = TCMI_SKEL_MSG(kmalloc(sizeof(struct tcmi_skel_msg), GFP_KERNEL)))) {
		mdbg(ERR3, "Can't allocate test request message");
		goto exit0;
	}

	/* Initialize the message for transfer */
	if (tcmi_msg_init_tx(TCMI_MSG(msg), TCMI_SKEL_MSG_ID, &skel_msg_ops, 
			     transactions, TCMI_SKELRESP_MSG_ID,
			     TCMI_SKEL_MSGTIMEOUT, TCMI_TRANSACTION_INVAL_ID)) {
		mdbg(ERR3, "Error initializing test request message message");
		goto exit1;
	}
	return TCMI_MSG(msg);

	/* error handling */
 exit1:
	kfree(msg);
 exit0:
	return NULL;
	
}