int crypto_run(struct fcrypt *fcr, struct kernel_crypt_op *kcop) { struct csession *ses_ptr; struct crypt_op *cop = &kcop->cop; int ret; if (unlikely(cop->op != COP_ENCRYPT && cop->op != COP_DECRYPT)) { ddebug(1, "invalid operation op=%u", cop->op); return -EINVAL; } /* this also enters ses_ptr->sem */ ses_ptr = crypto_get_session_by_sid(fcr, cop->ses); if (unlikely(!ses_ptr)) { derr(1, "invalid session ID=0x%08X", cop->ses); return -EINVAL; } if (ses_ptr->hdata.init != 0 && (cop->flags == 0 || cop->flags & COP_FLAG_RESET)) { ret = cryptodev_hash_reset(&ses_ptr->hdata); if (unlikely(ret)) { derr(1, "error in cryptodev_hash_reset()"); goto out_unlock; } } if (ses_ptr->cdata.init != 0) { int blocksize = ses_ptr->cdata.blocksize; if (unlikely(cop->len % blocksize)) { derr(1, "data size (%u) isn't a multiple of block size (%u)", cop->len, blocksize); ret = -EINVAL; goto out_unlock; } cryptodev_cipher_set_iv(&ses_ptr->cdata, kcop->iv, min(ses_ptr->cdata.ivsize, kcop->ivlen)); } if (likely(cop->len)) { if (cop->flags & COP_FLAG_NO_ZC) { if (unlikely(ses_ptr->alignmask && !IS_ALIGNED((unsigned long)cop->src, ses_ptr->alignmask))) { dwarning(2, "source address %p is not %d byte aligned - disabling zero copy", cop->src, ses_ptr->alignmask + 1); cop->flags &= ~COP_FLAG_NO_ZC; } if (unlikely(ses_ptr->alignmask && !IS_ALIGNED((unsigned long)cop->dst, ses_ptr->alignmask))) { dwarning(2, "destination address %p is not %d byte aligned - disabling zero copy", cop->dst, ses_ptr->alignmask + 1); cop->flags &= ~COP_FLAG_NO_ZC; } } if (cop->flags & COP_FLAG_NO_ZC) ret = __crypto_run_std(ses_ptr, &kcop->cop); else ret = __crypto_run_zc(ses_ptr, kcop); if (unlikely(ret)) goto out_unlock; } if (ses_ptr->cdata.init != 0) { cryptodev_cipher_get_iv(&ses_ptr->cdata, kcop->iv, min(ses_ptr->cdata.ivsize, kcop->ivlen)); } if (ses_ptr->hdata.init != 0 && ((cop->flags & COP_FLAG_FINAL) || (!(cop->flags & COP_FLAG_UPDATE) || cop->len == 0))) { ret = cryptodev_hash_final(&ses_ptr->hdata, kcop->hash_output); if (unlikely(ret)) { derr(0, "CryptoAPI failure: %d", ret); goto out_unlock; } kcop->digestsize = ses_ptr->hdata.digestsize; } if (ses_ptr->rdata.init != 0 && cop->len > 0) { kcop->rng_output = kmalloc(cop->len, GFP_KERNEL); if (unlikely(!kcop->rng_output)) { derr(0, "Not enough space to store %d random bytes.", cop->len); ret = -ENOMEM; goto out_unlock; } ret = cryptodev_rng_get_bytes(&ses_ptr->rdata, kcop->rng_output, cop->len); // some RNGs return 0 for success, while // some return the number of bytes generated if (unlikely(ret != 0 && ret != cop->len)) { derr(0, "RNG failure: %d", ret); kfree(kcop->rng_output); kcop->rng_output = NULL; goto out_unlock; } ret = 0; kcop->rnglen = cop->len; } out_unlock: crypto_put_session(ses_ptr); return ret; }
error_code meta_service::start() { dassert(!_started, "meta service is already started"); // init server state error_code err = _state->initialize(); if (err != ERR_OK) { derror("init server_state failed, err = %s", err.to_string()); return err; } ddebug("init server state succeed"); // we should start the FD service to response to the workers fd request _failure_detector = new meta_server_failure_detector(_state, this); err = _failure_detector->start( _opts.fd_check_interval_seconds, _opts.fd_beacon_interval_seconds, _opts.fd_lease_seconds, _opts.fd_grace_seconds, false ); if (err != ERR_OK) { derror("start failure_detector failed, err = %s", err.to_string()); return err; } // should register rpc handlers before acquiring leader lock, so that this meta service // can tell others who is the current leader register_rpc_handlers(); // become leader _failure_detector->acquire_leader_lock(); dassert(_failure_detector->is_primary(), "must be primary at this point"); ddebug("hahaha, I got the primary lock! now start to recover server state"); // recover server state while ((err = _state->on_become_leader()) != ERR_OK) { derror("recover server state failed, err = %s, retry ...", err.to_string()); } // create server load balancer // TODO: create per app server load balancer const char* server_load_balancer = dsn_config_get_value_string( "meta_server", "server_load_balancer_type", "simple_stateful_load_balancer", "server_load_balancer provider type" ); _balancer = dsn::utils::factory_store< ::dsn::dist::server_load_balancer>::create( server_load_balancer, PROVIDER_TYPE_MAIN, _state ); _failure_detector->sync_node_state_and_start_service(); ddebug("start meta_service succeed"); return ERR_OK; }
void replica::on_prepare_reply(std::pair<mutation_ptr, partition_status> pr, int err, message_ptr& request, message_ptr& reply) { check_hashed_access(); mutation_ptr& mu = pr.first; partition_status targetStatus = pr.second; // skip callback for old mutations if (mu->data.header.ballot < get_ballot() || PS_PRIMARY != status()) return; dassert (mu->data.header.ballot == get_ballot(), ""); end_point node = request->header().to_address; partition_status st = _primary_states.GetNodeStatus(node); // handle reply prepare_ack resp; // handle error if (err) { resp.err = err; } else { unmarshall(reply, resp); ddebug( "%s: mutation %s on_prepare_reply from %s:%d", name(), mu->name(), node.name.c_str(), static_cast<int>(node.port) ); } if (resp.err == ERR_SUCCESS) { dassert (resp.ballot == get_ballot(), ""); dassert (resp.decree == mu->data.header.decree, ""); switch (targetStatus) { case PS_SECONDARY: dassert (_primary_states.check_exist(node, PS_SECONDARY), ""); dassert (mu->left_secondary_ack_count() > 0, ""); if (0 == mu->decrease_left_secondary_ack_count()) { do_possible_commit_on_primary(mu); } break; case PS_POTENTIAL_SECONDARY: dassert (mu->left_potential_secondary_ack_count() > 0, ""); if (0 == mu->decrease_left_potential_secondary_ack_count()) { do_possible_commit_on_primary(mu); } break; default: ddebug( "%s: mutation %s prepare ack skipped coz the node is now inactive", name(), mu->name() ); break; } } // failure handling else { // note targetStatus and (curent) status may diff if (targetStatus == PS_POTENTIAL_SECONDARY) { dassert (mu->left_potential_secondary_ack_count() > 0, ""); if (0 == mu->decrease_left_potential_secondary_ack_count()) { do_possible_commit_on_primary(mu); } } handle_remote_failure(st, node, resp.err); } }
void replica::init_prepare(mutation_ptr& mu) { dassert (PS_PRIMARY == status(), ""); error_code err = ERR_SUCCESS; uint8_t count = 0; if (static_cast<int>(_primary_states.membership.secondaries.size()) + 1 < _options.mutation_2pc_min_replica_count) { err = ERR_NOT_ENOUGH_MEMBER; goto ErrOut; } mu->data.header.last_committed_decree = last_committed_decree(); if (mu->data.header.decree == invalid_decree) { mu->set_id(get_ballot(), _prepare_list->max_decree() + 1); } else { mu->set_id(get_ballot(), mu->data.header.decree); } if (mu->data.header.decree > _prepare_list->max_decree() && _prepare_list->count() >= _options.staleness_for_commit) { err = ERR_CAPACITY_EXCEEDED; goto ErrOut; } dassert (mu->data.header.decree > last_committed_decree(), ""); // local prepare without log err = _prepare_list->prepare(mu, PS_PRIMARY); if (err != ERR_SUCCESS) { goto ErrOut; } ddebug("%s: mutation %s init_prepare", name(), mu->name()); // // TODO: bounded staleness on secondaries // dassert (mu->data.header.decree <= last_committed_decree() + _options.staleness_for_commit, ""); // remote prepare dassert (mu->remote_tasks().size() == 0, ""); mu->set_left_secondary_ack_count((unsigned int)_primary_states.membership.secondaries.size()); for (auto it = _primary_states.membership.secondaries.begin(); it != _primary_states.membership.secondaries.end(); it++) { send_prepare_message(*it, PS_SECONDARY, mu, _options.prepare_timeout_ms_for_secondaries); } count = 0; for (auto it = _primary_states.learners.begin(); it != _primary_states.learners.end(); it++) { if (it->second.prepare_start_decree != invalid_decree && mu->data.header.decree >= it->second.prepare_start_decree) { send_prepare_message(it->first, PS_POTENTIAL_SECONDARY, mu, _options.prepare_timeout_ms_for_potential_secondaries); count++; } } mu->set_left_potential_secondary_ack_count(count); // local log dassert (mu->data.header.log_offset == invalid_offset, ""); dassert (mu->log_task() == nullptr, ""); mu->log_task() = _stub->_log->append(mu, LPC_WRITE_REPLICATION_LOG, this, std::bind(&replica::on_append_log_completed, this, mu, std::placeholders::_1, std::placeholders::_2), gpid_to_hash(get_gpid()) ); if (nullptr == mu->log_task()) { err = ERR_FILE_OPERATION_FAILED; handle_local_failure(err); goto ErrOut; } return; ErrOut: response_client_message(mu->client_request, err); return; }
void replica::on_prepare(message_ptr& request) { check_hashed_access(); replica_configuration rconfig; unmarshall(request, rconfig); mutation_ptr mu = mutation::read_from(request); decree decree = mu->data.header.decree; ddebug( "%s: mutation %s on_prepare", name(), mu->name()); dassert (mu->data.header.ballot == rconfig.ballot, ""); if (mu->data.header.ballot < get_ballot()) { ddebug( "%s: mutation %s on_prepare skipped due to old view", name(), mu->name()); return; } // update configuration when necessary else if (rconfig.ballot > get_ballot()) { update_local_configuration(rconfig); } if (PS_INACTIVE == status() || PS_ERROR == status()) { ddebug( "%s: mutation %s on_prepare to %s skipped", name(), mu->name(), enum_to_string(status()) ); ack_prepare_message(ERR_INVALID_STATE, mu); return; } else if (PS_POTENTIAL_SECONDARY == status()) { if (_potential_secondary_states.learning_status != LearningWithPrepare && _potential_secondary_states.learning_status != LearningSucceeded) { ddebug( "%s: mutation %s on_prepare to %s skipped, learnings state = %s", name(), mu->name(), enum_to_string(status()), enum_to_string(_potential_secondary_states.learning_status) ); // do not retry as there may retries later return; } } dassert (rconfig.status == status(), ""); if (decree <= last_committed_decree()) { ack_prepare_message(ERR_SUCCESS, mu); return; } // real prepare start auto mu2 = _prepare_list->get_mutation_by_decree(decree); if (mu2 != nullptr && mu2->data.header.ballot == mu->data.header.ballot) { ddebug( "%s: mutation %s redundant prepare skipped", name(), mu->name()); if (mu2->is_prepared()) { ack_prepare_message(ERR_SUCCESS, mu); } return; } int err = _prepare_list->prepare(mu, status()); dassert (err == ERR_SUCCESS, ""); if (PS_POTENTIAL_SECONDARY == status()) { dassert (mu->data.header.decree <= last_committed_decree() + _options.staleness_for_start_prepare_for_potential_secondary, ""); } else { dassert (PS_SECONDARY == status(), ""); dassert (mu->data.header.decree <= last_committed_decree() + _options.staleness_for_commit, ""); } // write log dassert (mu->log_task() == nullptr, ""); mu->log_task() = _stub->_log->append(mu, LPC_WRITE_REPLICATION_LOG, this, std::bind(&replica::on_append_log_completed, this, mu, std::placeholders::_1, std::placeholders::_2), gpid_to_hash(get_gpid()) ); if (nullptr == mu->log_task()) { err = ERR_FILE_OPERATION_FAILED; ack_prepare_message(err, mu); handle_local_failure(err); } }