/** 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; }
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; }
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; }
/** * 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; }
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(); }; };
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(); }; };
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; }
/** 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; }
/** 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; }