/** Import an MM struct
 *  @author Renaud Lottiaux
 *
 *  @param  obj_entry  Object entry of the object to import.
 *  @param  _buffer   Data to import in the object.
 */
int mm_import_object (struct rpc_desc *desc,
		      struct kddm_set *_set,
		      struct kddm_obj *obj_entry,
		      objid_t objid,
		      int flags)
{
	struct mm_struct *mm;
	krgsyms_val_t unmap_id, get_unmap_id;
	struct kddm_set *set;
	unique_id_t mm_id, kddm_id;
	void *context_vdso;
	int r;

	mm = obj_entry->object;

	r = rpc_unpack (desc, 0, &mm_id, sizeof(unique_id_t));
	if (r)
		return r;

	r = rpc_unpack (desc, 0, &kddm_id, sizeof(unique_id_t));
	if (r)
		return r;

	r = rpc_unpack (desc, 0, &context_vdso, sizeof(void*));
	if (r)
		return r;

	if (mm == NULL) {
		/* First import */
		set = _find_get_kddm_set(kddm_def_ns, kddm_id);
		BUG_ON (set == NULL);

		mm = set->obj_set;
		mm->mm_id = mm_id;
		atomic_inc(&mm->mm_users);
		obj_entry->object = mm;
		put_kddm_set(set);
		mm->context.vdso = context_vdso;
	}

	r = rpc_unpack(desc, 0, &mm->copyset, sizeof(krgnodemask_t));
	if (r)
		return r;

	r = rpc_unpack_type(desc, get_unmap_id);
	if (r)
		return r;

	mm->get_unmapped_area = krgsyms_import (get_unmap_id);

	r = rpc_unpack_type(desc, unmap_id);
	if (r)
		return r;
	mm->unmap_area = krgsyms_import (unmap_id);

	return 0;
}
예제 #2
0
static int unpack_path(struct rpc_desc *desc, struct path *path)
{
	char *tmp;
	int len, err;

	err = -ENOMEM;
	tmp = (char *)__get_free_page(GFP_KERNEL);
	if (!tmp)
		goto out;

	err = rpc_unpack_type(desc, len);
	if (err)
		goto out_free;
	err = rpc_unpack(desc, 0, tmp, len);
	if (err)
		goto out_free;

	err = kern_path(tmp, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, path);

out_free:
	free_page((unsigned long)tmp);

out:
	return err;
}
예제 #3
0
static int handle_enter_barrier(struct rpc_desc* desc,
				void *_msg, size_t size)
{
	struct cluster_barrier_id *id = ((struct cluster_barrier_id *) _msg);
	struct cluster_barrier_core *core_bar;
	struct cluster_barrier *barrier;
	krgnodemask_t nodes;

	rpc_unpack(desc, 0, &nodes, sizeof(krgnodemask_t));

	barrier = hashtable_find (barrier_table, id->key);
	BUG_ON(!barrier);

	core_bar = &barrier->core[id->toggle];

	if (krgnodes_empty(core_bar->nodes_to_wait)) {
		krgnodes_copy(core_bar->nodes_in_barrier, nodes);
		krgnodes_copy(core_bar->nodes_to_wait, nodes);
	}
	else
		BUG_ON(!krgnodes_equal(core_bar->nodes_in_barrier, nodes));

	krgnode_clear(desc->client, core_bar->nodes_to_wait);

	if (krgnodes_empty(core_bar->nodes_to_wait)) {
                rpc_async_m(RPC_EXIT_BARRIER, &core_bar->nodes_in_barrier,
			    id, sizeof (struct cluster_barrier_id));
	}

	return 0;
}
예제 #4
0
/**
 *  Unpack the result value of a remote, sleepable, interruptible operation
 *  @author Renaud Lottiaux
 *
 *  @param desc		The RPC descriptor to get the result from.
 *  @param res		Pointer to store the result.
 *  @param size		Size of the result.
 *
 *  @return		0 in case of success, or negative error code.
 */
int unpack_remote_sleep_res(struct rpc_desc *desc, void *res, size_t size)
{
	int err, flags;

	flags = RPC_FLAGS_INTR;
	for (;;) {
		err = rpc_unpack(desc, flags, res, size);
		switch (err) {
			case RPC_EOK:
				return 0;
			case RPC_EINTR:
				BUG_ON(flags != RPC_FLAGS_INTR);
				rpc_signal(desc, SIGINT);
				/*
				 * We do not need to explicitly receive SIGACK,
				 * since the server will return the result
				 * anyway.
				 */
				flags = 0;
				break;
			case RPC_EPIPE:
				return -EPIPE;
			default:
				BUG();
		}
	}

	return err;
}
예제 #5
0
void rpc_handler_kthread_void(struct rpc_desc* desc){
	int err;
	struct rpc_data rpc_data;

	BUG_ON(!desc);
	
	err = rpc_unpack(desc, RPC_FLAGS_NOCOPY,
			 &rpc_data, 0);
	
	if(!err){
		BUG_ON(!desc);
		BUG_ON(!desc->service);
		BUG_ON(!desc->service->h);
		
		((rpc_handler_void_t)desc->service->h)(desc, rpc_data.data,
						       rpc_data.size);

		rpc_free_buffer(&rpc_data);
		
	}else{
		printk("unexpected event\n");
		BUG();
	};

};
예제 #6
0
void rpc_handler_kthread_int(struct rpc_desc* desc){
	int res;
	int id;
	int err;
	struct rpc_data rpc_data;

	err = rpc_unpack(desc, RPC_FLAGS_NOCOPY,
			 &rpc_data, 0);
	
	if(!err){
	
		id = rpc_pack(desc, RPC_FLAGS_LATER,
				&res, sizeof(res));

		res = ((rpc_handler_int_t)desc->service->h)(desc,
							    rpc_data.data,
							    rpc_data.size);

		rpc_free_buffer(&rpc_data);
		rpc_wait_pack(desc, id);

	}else{
		printk("unexpected event\n");
		BUG();
	};
};
예제 #7
0
static void *kddm_tree_import (struct rpc_desc* desc, int *free_data)
{
	int *tree_type;

	tree_type = kmalloc (sizeof (int), GFP_KERNEL);
	*free_data = 1;

	rpc_unpack(desc, 0, tree_type, sizeof (int));
	return tree_type;
}
struct file *rcv_faf_file_desc(struct rpc_desc *desc)
{
	int r, first_import;
	void *fdesc;
	int fdesc_size;
	long fobjid;
	struct dvfs_file_struct *dvfs_file = NULL;
	struct file *file = NULL;

	r = rpc_unpack_type(desc, fobjid);
	if (r)
		goto error;

	r = rpc_unpack_type(desc, fdesc_size);
	if (r)
		goto error;

	fdesc = kmalloc(GFP_KERNEL, fdesc_size);
	if (!fdesc) {
		r = -ENOMEM;
		goto error;
	}

	r = rpc_unpack(desc, 0, fdesc, fdesc_size);
	if (r)
		goto err_free_desc;

	/* Check if the file struct is already present */
	first_import = 0;

	file = begin_import_dvfs_file(fobjid, &dvfs_file);

	if (!file) {
		file = create_faf_file_from_krg_desc(current, fdesc);
		first_import = 1;
	}

	r = end_import_dvfs_file(fobjid, dvfs_file, file, first_import);
	if (r)
		goto err_free_desc;

err_free_desc:
	kfree(fdesc);

error:
	if (r)
		file = ERR_PTR(r);

	return file;
}
예제 #9
0
/** Request an IO linker to import data into an object.
 *  @author Renaud Lottiaux
 *
 *  @param set          Kddm Set the object belong to.
 *  @param obj_entry    Object entry to import data into.
 *  @param buffer       Buffer containing data to import.
 */
int kddm_io_import_object (struct rpc_desc *desc,
                           struct kddm_set *set,
                           struct kddm_obj *obj_entry,
                           objid_t objid,
			   int flags)
{
	struct iolinker_struct *io = set->iolinker;
	int res;

	BUG_ON (OBJ_STATE(obj_entry) != INV_FILLING);

	might_sleep();

	if (io && io->import_object)
		res = io->import_object(desc, set, obj_entry, objid, flags);
	else
		res = rpc_unpack(desc, 0, obj_entry->object, set->obj_size);

	return res;
}
예제 #10
0
/** Handler for writing in a FAF open file.
 *  @author Renaud Lottiaux, Matthieu Fertré
 *
 *  @param from    Node sending the request
 *  @param msgIn   Request message
 */
void handle_faf_write(struct rpc_desc* desc, void *msgIn, size_t size)
{
	struct faf_rw_msg *msg = msgIn;
	struct file *file = NULL;
	long to_recv;
	char *buf = NULL;
	ssize_t buf_size = PAGE_SIZE;
	ssize_t r, nr_received = -ENOMEM;
	loff_t fpos;
	int err;

	r = remote_sleep_prepare(desc);
	if (r) {
		rpc_cancel(desc);
		return;
	}

	to_recv = msg->count;
	fpos = msg->pos;

	buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
	if (!buf)
		goto error;

	nr_received = 0;

	file = fget(msg->server_fd);

	while (to_recv > 0) {
		err = rpc_unpack_type(desc, buf_size);
		if (err)
			goto cancel;

		/* copy_from_user has failed on the other side */
		if (buf_size < 0) {
			nr_received = buf_size;
			break;
		}

		err = rpc_unpack(desc, 0, buf, buf_size);
		if (err)
			goto cancel;

		r = vfs_write(file, buf, buf_size, &fpos);

		/* The last write failed. Break the write sequence */
		if (r < 0) {
			nr_received = r;
			break;
		}
		nr_received += r;
		to_recv -= buf_size;
	}

error:
	err = rpc_pack_type(desc, nr_received);
	if (err)
		goto cancel;

	/* send the updated file position */
	err = rpc_pack_type(desc, fpos);
	if (err)
		goto cancel;

out:
	if (buf)
		kfree(buf);
	if (file)
		fput(file);

	remote_sleep_finish();
	return;

cancel:
	rpc_cancel(desc);
	goto out;
}