static void _update_remote_name(struct harbor *h, struct skynet_context * context, const char name[GLOBALNAME_LENGTH], uint32_t handle) { struct keyvalue * node = _hash_search(h->map, name); if (node == NULL) { node = _hash_insert(h->map, name); } node->value = handle; if (node->queue) { _dispatch_queue(h, context, node->queue, handle, name); _release_queue(node->queue); node->queue = NULL; } }
static int _remote_send_name(struct harbor *h, struct skynet_context * context, uint32_t source, const char name[GLOBALNAME_LENGTH], int type, int session, const char * msg, size_t sz) { struct keyvalue * node = _hash_search(h->map, name); if (node == NULL) { node = _hash_insert(h->map, name); } if (node->value == 0) { if (node->queue == NULL) { node->queue = _new_queue(); } struct remote_message_header header; header.source = source; header.destination = type << HANDLE_REMOTE_SHIFT; header.session = (uint32_t)session; _push_queue(node->queue, msg, sz, &header); // 0 for request _remote_register_name(h, context, name, 0); return 0; } else { return _remote_send_handle(h, context, source, node->value, type, session, msg, sz); } }
static void client_ref_io(struct client_output *output, struct mref_object *mref) { struct client_mref_aspect *mref_a; int error = -EINVAL; mref_a = client_mref_get_aspect(output->brick, mref); if (unlikely(!mref_a)) { goto error; } while (output->brick->max_flying > 0 && atomic_read(&output->fly_count) > output->brick->max_flying) { MARS_IO("sleeping request pos = %lld len = %d rw = %d (flying = %d)\n", mref->ref_pos, mref->ref_len, mref->ref_rw, atomic_read(&output->fly_count)); #ifdef IO_DEBUGGING brick_msleep(3000); #else brick_msleep(1000 * 2 / HZ); #endif } atomic_inc(&mars_global_io_flying); atomic_inc(&output->fly_count); _mref_get(mref); mref_a->submit_jiffies = jiffies; _hash_insert(output, mref_a); MARS_IO("added request id = %d pos = %lld len = %d rw = %d (flying = %d)\n", mref->ref_id, mref->ref_pos, mref->ref_len, mref->ref_rw, atomic_read(&output->fly_count)); wake_up_interruptible(&output->event); return; error: MARS_ERR("IO error = %d\n", error); SIMPLE_CALLBACK(mref, error); client_ref_put(output, mref); }
static int sender_thread(void *data) { struct client_output *output = data; struct client_brick *brick = output->brick; unsigned long flags; bool do_kill = false; int status = 0; output->receiver.restart_count = 0; while (!brick_thread_should_stop()) { struct list_head *tmp = NULL; struct client_mref_aspect *mref_a; struct mref_object *mref; if (unlikely(output->recv_error != 0 || !mars_socket_is_alive(&output->socket))) { MARS_DBG("recv_error = %d do_kill = %d\n", output->recv_error, do_kill); if (do_kill) { do_kill = false; _kill_socket(output); brick_msleep(3000); } status = _connect(output, brick->brick_name); MARS_IO("connect status = %d\n", status); if (unlikely(status < 0)) { brick_msleep(3000); _do_timeout(output, &output->wait_list, false); _do_timeout(output, &output->mref_list, false); continue; } brick->connection_state = 2; do_kill = true; /* Re-Submit any waiting requests */ MARS_IO("re-submit\n"); _do_resubmit(output); } wait_event_interruptible_timeout(output->event, !list_empty(&output->mref_list) || output->get_info || output->recv_error != 0 || brick_thread_should_stop(), 1 * HZ); if (unlikely(output->recv_error != 0)) { MARS_DBG("recv_error = %d\n", output->recv_error); brick_msleep(1000); continue; } if (output->get_info) { status = _request_info(output); if (status >= 0) { output->get_info = false; } else { MARS_WRN("cannot get info, status = %d\n", status); brick_msleep(1000); } } /* Grab the next mref from the queue */ traced_lock(&output->lock, flags); if (list_empty(&output->mref_list)) { traced_unlock(&output->lock, flags); continue; } tmp = output->mref_list.next; list_del(tmp); list_add(tmp, &output->wait_list); mref_a = container_of(tmp, struct client_mref_aspect, io_head); traced_unlock(&output->lock, flags); mref = mref_a->object; if (brick->limit_mode) { int amount = 0; if (mref->ref_cs_mode < 2) amount = (mref->ref_len - 1) / 1024 + 1; mars_limit_sleep(&client_limiter, amount); } MARS_IO("sending mref, id = %d pos = %lld len = %d rw = %d\n", mref->ref_id, mref->ref_pos, mref->ref_len, mref->ref_rw); status = mars_send_mref(&output->socket, mref); MARS_IO("status = %d\n", status); if (unlikely(status < 0)) { // retry submission on next occasion.. MARS_WRN("sending failed, status = %d\n", status); if (do_kill) { do_kill = false; _kill_socket(output); } _hash_insert(output, mref_a); brick_msleep(1000); continue; } } //done: if (status < 0) { MARS_WRN("sender thread terminated with status = %d\n", status); } if (do_kill) { _kill_socket(output); } /* Signal error on all pending IO requests. * We have no other chance (except probably delaying * this until destruction which is probably not what * we want). */ _do_timeout(output, &output->wait_list, true); _do_timeout(output, &output->mref_list, true); wake_up_interruptible(&output->sender.run_event); MARS_DBG("sender terminated\n"); return status; }
static int receiver_thread(void *data) { struct client_output *output = data; int status = 0; while (!brick_thread_should_stop()) { struct mars_cmd cmd = {}; struct list_head *tmp; struct client_mref_aspect *mref_a = NULL; struct mref_object *mref = NULL; unsigned long flags; status = mars_recv_struct(&output->socket, &cmd, mars_cmd_meta); MARS_IO("got cmd = %d status = %d\n", cmd.cmd_code, status); if (status < 0) goto done; switch (cmd.cmd_code & CMD_FLAG_MASK) { case CMD_NOTIFY: mars_trigger(); break; case CMD_CONNECT: if (cmd.cmd_int1 < 0) { status = cmd.cmd_int1; MARS_ERR("at remote side: brick connect failed, remote status = %d\n", status); goto done; } break; case CMD_CB: { int hash_index = cmd.cmd_int1 % CLIENT_HASH_MAX; traced_lock(&output->lock, flags); for (tmp = output->hash_table[hash_index].next; tmp != &output->hash_table[hash_index]; tmp = tmp->next) { struct mref_object *tmp_mref; mref_a = container_of(tmp, struct client_mref_aspect, hash_head); tmp_mref = mref_a->object; if (unlikely(!tmp_mref)) { traced_unlock(&output->lock, flags); MARS_ERR("bad internal mref pointer\n"); status = -EBADR; goto done; } if (tmp_mref->ref_id == cmd.cmd_int1) { mref = tmp_mref; list_del_init(&mref_a->hash_head); list_del_init(&mref_a->io_head); break; } } traced_unlock(&output->lock, flags); if (unlikely(!mref)) { MARS_WRN("got unknown id = %d for callback\n", cmd.cmd_int1); status = -EBADR; goto done; } MARS_IO("got callback id = %d, old pos = %lld len = %d rw = %d\n", mref->ref_id, mref->ref_pos, mref->ref_len, mref->ref_rw); status = mars_recv_cb(&output->socket, mref, &cmd); MARS_IO("new status = %d, pos = %lld len = %d rw = %d\n", status, mref->ref_pos, mref->ref_len, mref->ref_rw); if (unlikely(status < 0)) { MARS_WRN("interrupted data transfer during callback, status = %d\n", status); _hash_insert(output, mref_a); goto done; } SIMPLE_CALLBACK(mref, 0); client_ref_put(output, mref); atomic_dec(&output->fly_count); atomic_dec(&mars_global_io_flying); break; } case CMD_GETINFO: status = mars_recv_struct(&output->socket, &output->info, mars_info_meta); if (status < 0) { MARS_WRN("got bad info from remote side, status = %d\n", status); goto done; } output->got_info = true; wake_up_interruptible(&output->info_event); break; default: MARS_ERR("got bad command %d from remote side, terminating.\n", cmd.cmd_code); status = -EBADR; goto done; } done: brick_string_free(cmd.cmd_str1); if (unlikely(status < 0)) { if (!output->recv_error) { MARS_DBG("signalling status = %d\n", status); output->recv_error = status; } wake_up_interruptible(&output->event); brick_msleep(100); } } if (status < 0) { MARS_WRN("receiver thread terminated with status = %d, recv_error = %d\n", status, output->recv_error); } mars_shutdown_socket(&output->socket); wake_up_interruptible(&output->receiver.run_event); return status; }
/* fat_file_open -- * Open fat-file. Two hash tables are accessed by key * constructed from cluster num and offset of the node (i.e. * files/directories are distinguished by location on the disk). * First, hash table("vhash") consists of fat-file descriptors corresponded * to "valid" files is accessed. Search is made by 2 fields equal to key * constructed. If descriptor is found in the "vhash" - return it. * Otherwise search is made in hash table("rhash") consits of fat-file * descriptors corresponded to "removed-but-still-open" files with the * same keys. * If search failed, new fat-file descriptor is added to "vhash" * with both key fields equal to constructed key. Otherwise new fat-file * descriptor is added to "vhash" with first key field equal to key * constructed and the second equal to an unique (unique among all values * of second key fields) value. * * PARAMETERS: * mt_entry - mount table entry * pos - cluster and offset of the node * fat_fd - placeholder for returned fat-file descriptor * * RETURNS: * RC_OK and pointer to opened descriptor on success, or -1 if error * occured (errno set appropriately) */ int fat_file_open( rtems_filesystem_mount_table_entry_t *mt_entry, fat_dir_pos_t *dir_pos, fat_file_fd_t **fat_fd ) { int rc = RC_OK; fat_fs_info_t *fs_info = mt_entry->fs_info; fat_file_fd_t *lfat_fd = NULL; uint32_t key = 0; /* construct key */ key = fat_construct_key(mt_entry, &dir_pos->sname); /* access "valid" hash table */ rc = _hash_search(mt_entry, fs_info->vhash, key, 0, &lfat_fd); if ( rc == RC_OK ) { /* return pointer to fat_file_descriptor allocated before */ (*fat_fd) = lfat_fd; lfat_fd->links_num++; return rc; } /* access "removed-but-still-open" hash table */ rc = _hash_search(mt_entry, fs_info->rhash, key, key, &lfat_fd); lfat_fd = (*fat_fd) = (fat_file_fd_t*)malloc(sizeof(fat_file_fd_t)); if ( lfat_fd == NULL ) rtems_set_errno_and_return_minus_one( ENOMEM ); memset(lfat_fd, 0, sizeof(fat_file_fd_t)); lfat_fd->links_num = 1; lfat_fd->flags &= ~FAT_FILE_REMOVED; lfat_fd->map.last_cln = FAT_UNDEFINED_VALUE; lfat_fd->dir_pos = *dir_pos; if ( rc != RC_OK ) lfat_fd->ino = key; else { lfat_fd->ino = fat_get_unique_ino(mt_entry); if ( lfat_fd->ino == 0 ) { free((*fat_fd)); /* * XXX: kernel resource is unsufficient, but not the memory, * but there is no suitable errno :( */ rtems_set_errno_and_return_minus_one( ENOMEM ); } } _hash_insert(fs_info->vhash, key, lfat_fd->ino, lfat_fd); /* * other fields of fat-file descriptor will be initialized on upper * level */ return RC_OK; }