MTC_STATIC MTC_STATUS check_head_valid( SCRIPT_DATA_HEAD *head) { if (head->magic != SCRIPT_MAGIC) { log_internal(MTC_LOG_WARNING, "SC: head->magic is invalid (%x).\n", head->magic); return MTC_ERROR_SC_IMPROPER_DATA; } if (head->response != 0) { log_internal(MTC_LOG_WARNING, "SC: head->response is invalid (%x).\n", head->response); return MTC_ERROR_SC_IMPROPER_DATA; } if (head->type >= SCRIPT_TYPE_NUM) { log_internal(MTC_LOG_WARNING, "SC: head->type is invalid (%x).\n", head->type); return MTC_ERROR_SC_IMPROPER_DATA; } if (head->length > sizeof(((SCRIPT_DATA_REQUEST *)NULL)->body)) { log_internal(MTC_LOG_WARNING, "SC: head->length is invalid (%x).\n", head->length); return MTC_ERROR_SC_IMPROPER_DATA; } return MTC_SUCCESS; // SUCCESS }
void log_func_gnutls(int level, const char *message) { assert_se(message); if (0 <= level && level < (int) ELEMENTSOF(gnutls_log_map)) { if (gnutls_log_map[level].enabled) log_internal(gnutls_log_map[level].level, 0, NULL, 0, NULL, "gnutls %d/%s: %s", level, gnutls_log_map[level].names[1], message); } else { log_debug("Received GNUTLS message with unknown level %d.", level); log_internal(LOG_DEBUG, 0, NULL, 0, NULL, "gnutls: %s", message); } }
void spa_history_log_internal(spa_t *spa, const char *operation, dmu_tx_t *tx, const char *fmt, ...) { dmu_tx_t *htx = tx; va_list adx; nvlist_t *nvl; /* create a tx if we didn't get one */ if (tx == NULL) { htx = dmu_tx_create_dd(spa_get_dsl(spa)->dp_mos_dir); if (dmu_tx_assign(htx, TXG_WAIT) != 0) { dmu_tx_abort(htx); return; } } va_start(adx, fmt); VERIFY0(nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_PUSHPAGE)); log_internal(nvl, operation, spa, htx, fmt, adx); va_end(adx); /* if we didn't get a tx from the caller, commit the one we made */ if (tx == NULL) dmu_tx_commit(htx); }
static int lua_log(lua_State *L) { int nargs = lua_gettop(L); ASSERT_MSG(nargs >= 1, "Not enough arguments passed to log()"); enum log_level level = log_level_get(lua_tostring(L, 1)); int depth = luaL_checkinteger(L, 2); // Depth to ignore and report upper location if (depth < 0) return luaL_error(L, "Second argument mustn't be less then zero"); struct lua_Debug ldebug; lua_getstack(L, depth + 1, &ldebug); // get informations about caller lua_getinfo(L, "Sln", &ldebug); size_t sum = 1; size_t sizes[nargs - 2]; const char *strs[nargs - 2]; for (int i = 3; i <= nargs; i ++) { if (lua_isnil(L, i)) strs[i - 3] = "<nil>"; else if((strs[i - 3] = lua_tostring(L, i)) == NULL) // If it is not nil nor string or number, it is function or table so too complex just for simple log function strs[i - 3] = "<complex-type>"; sizes[i - 3] = strlen(strs[i - 3]); sum += sizes[i - 3]; } char *message = alloca(sum); size_t pos = 0; for (size_t i = 0; i < (unsigned)nargs - 2; i ++) { memcpy(message + pos, strs[i], sizes[i]); pos += sizes[i]; } message[pos] = '\0'; char *file = aprintf("%s.lua", ldebug.source); log_internal(level, file, ldebug.currentline, ldebug.name ? ldebug.name : "Globals", "%s", message); return 0; }
/* Dump an error message to stderr */ void log_error(const char *format, ...) { va_list ap; va_start(ap, format); return log_internal(stderr, "ERROR", format, &ap); va_end(ap); }
MTC_STATIC MTC_STATUS create_threads(void) { static SCRIPT_SERVICE_THREAD_PARAM thread_param[SCRIPT_SOCKET_NUM]; SCRIPT_SERVICE_THREAD_PARAM *p; MTC_U32 sock_index; MTC_U32 type_index; int pthread_ret; for (sock_index = 0; sock_index < SCRIPT_SOCKET_NUM; sock_index++) { p = &thread_param[sock_index]; memset(p, 0, sizeof(SCRIPT_SERVICE_THREAD_PARAM)); switch (sock_index) { case SCRIPT_SOCK_INDEX_FOR_OTHER: strcpy(p->thread_name, "sc_thread_other"); break; case SCRIPT_SOCK_INDEX_FOR_QUERY: strcpy(p->thread_name, "sc_thread_query"); break; case SCRIPT_SOCK_INDEX_FOR_INTERNAL: strcpy(p->thread_name, "sc_thread_internal"); break; default: strcpy(p->thread_name, "sc_thread_unknown"); break; } p->socket = sc_listening_socket[sock_index]; p->funcnum = SCRIPT_TYPE_NUM; for (type_index = 0; type_index < SCRIPT_TYPE_NUM; type_index ++) { if (type_to_socket_index(type_index) == sock_index) { p->func[type_index] = type_to_func(type_index); } else { p->func[type_index] = NULL; } } pthread_ret = pthread_create(&(sc_thread[sock_index]), xhad_pthread_attr, script_service_thread, p); if (fist_on("sc.pthread")) pthread_ret = FIST_PTHREAD_ERRCODE; if (pthread_ret != 0) { log_internal(MTC_LOG_ERR, "SC: cannot create thread (thread:%s). (sys %d)\n", p->thread_name, pthread_ret); return MTC_ERROR_SC_PTHREAD; } } return MTC_SUCCESS; }
/* Dump a debug trace message to stdout */ void log_debug(const char *format, ...) { va_list ap; if (!log_debug_flag) { return; } va_start(ap, format); return log_internal(stdout, "DEBUG", format, &ap); va_end(ap); }
MTC_STATIC MTC_STATUS script_initialize0(void) { int pthread_ret; pthread_ret = pthread_spin_init(&lock, 0); if (fist_on("sc.pthread")) pthread_ret = FIST_PTHREAD_ERRCODE; if (pthread_ret != 0) { log_internal(MTC_LOG_ERR, "SC: cannot create spin_lock. (sys %d)\n", pthread_ret); return MTC_ERROR_SC_PTHREAD; } return create_sockets(); }
MTC_STATIC MTC_U32 type_to_socket_index(MTC_U32 type) { SCRIPT_SOCKET_TABLE s_table[] = SCRIPT_SOCKET_TABLE_INITIALIZER; MTC_U32 i; for (i = 0; i < SCRIPT_TYPE_NUM; i++) { if (type == s_table[i].type) { return s_table[i].socket_index; } } log_internal(MTC_LOG_ERR, "SC: invalid type (%d).\n", type); assert(FALSE); return 0; }
// // // NAME: // // type_to_func(); // // DESCRIPTION: // // get service_function from script_type; // // FORMAL PARAMETERS: // // type - script_type // // RETURN VALUE: // // pointer to the service function // // ENVIRONMENT: // // dom0 // // MTC_STATIC SCRIPT_SERVICE_FUNC type_to_func(MTC_U32 type) { SCRIPT_FUNC_TABLE f_table[] = SCRIPT_FUNC_TABLE_INITIALIZER; MTC_U32 i; for (i = 0; i < SCRIPT_TYPE_NUM; i++) { if (type == f_table[i].type) { return f_table[i].func; } } log_internal(MTC_LOG_ERR, "SC: invalid type (%d).\n", type); assert(FALSE); return NULL; }
void spa_history_log_internal_ds(dsl_dataset_t *ds, const char *operation, dmu_tx_t *tx, const char *fmt, ...) { va_list adx; char namebuf[MAXNAMELEN]; nvlist_t *nvl = fnvlist_alloc(); ASSERT(tx != NULL); dsl_dataset_name(ds, namebuf); fnvlist_add_string(nvl, ZPOOL_HIST_DSNAME, namebuf); fnvlist_add_uint64(nvl, ZPOOL_HIST_DSID, ds->ds_object); va_start(adx, fmt); log_internal(nvl, operation, dsl_dataset_get_spa(ds), tx, fmt, adx); va_end(adx); }
void spa_history_log_internal_dd(dsl_dir_t *dd, const char *operation, dmu_tx_t *tx, const char *fmt, ...) { va_list adx; char namebuf[MAXNAMELEN]; nvlist_t *nvl = fnvlist_alloc(); ASSERT(tx != NULL); dsl_dir_name(dd, namebuf); fnvlist_add_string(nvl, ZPOOL_HIST_DSNAME, namebuf); fnvlist_add_uint64(nvl, ZPOOL_HIST_DSID, dd->dd_phys->dd_head_dataset_obj); va_start(adx, fmt); log_internal(nvl, operation, dd->dd_pool->dp_spa, tx, fmt, adx); va_end(adx); }
void spa_history_log_internal(history_internal_events_t event, spa_t *spa, dmu_tx_t *tx, const char *fmt, ...) { dmu_tx_t *htx = tx; va_list adx; /* create a tx if we didn't get one */ if (tx == NULL) { htx = dmu_tx_create_dd(spa_get_dsl(spa)->dp_mos_dir); if (dmu_tx_assign(htx, TXG_WAIT) != 0) { dmu_tx_abort(htx); return; } } va_start(adx, fmt); log_internal(event, spa, htx, fmt, adx); va_end(adx); /* if we didn't get a tx from the caller, commit the one we made */ if (tx == NULL) dmu_tx_commit(htx); }
MTC_STATIC MTC_STATUS create_sockets(void) { struct sockaddr_un listening_socket_addr; char sockname[sizeof(((struct sockaddr_un *)0)->sun_path)] = ""; char *sockname_list[] = SCRIPT_SOCK_NAME_ARRAY; MTC_S32 i; if (fist_on("sc.socket")) { log_internal(MTC_LOG_INFO, "SC: FIST socket error\n"); goto error_return; } for (i = 0; i < SCRIPT_SOCKET_NUM; i++) { // make abstract namespace for PF_UNIX socket memset(sockname, 0, sizeof(sockname)); memcpy(sockname+1, sockname_list[i], strlen(sockname_list[i])); // Create a listening socket listening_socket_addr.sun_family = PF_UNIX; memset(listening_socket_addr.sun_path, '\0', sizeof(listening_socket_addr.sun_path)); // ASSERT(sizeof(listening_socket_addr.sun_path) >= sizeof(sockname)); memcpy(listening_socket_addr.sun_path, sockname, sizeof(sockname)); if ((sc_listening_socket[i] = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { log_internal(MTC_LOG_ERR, "SC: cannnot create socket for %s. (sys %d)\n", sockname_list[i], errno); goto error_return; } // Bind a name to the listening socket if (bind(sc_listening_socket[i], (struct sockaddr *)&listening_socket_addr, sizeof(listening_socket_addr)) < 0) { log_internal(MTC_LOG_ERR, "SC: cannnot bind socket for %s. (sys %d)\n", sockname_list[i], errno); goto error_return; } // Listen on the listening socket if (listen(sc_listening_socket[i], 5) == -1) { log_internal(MTC_LOG_ERR, "SC: cannnot listen socket for %s. (sys %d)\n", sockname_list[i], errno); goto error_return; } } return MTC_SUCCESS; error_return: return MTC_ERROR_SC_SOCKET; }
void log_error_internal(const char *format, ...) { va_list ap; va_start(ap, format); log_internal(LOG_ERROR, 'E', format, ap); }
void log_warning_internal(const char *format, ...) { va_list ap; va_start(ap, format); log_internal(LOG_WARNING, 'W', format, ap); }
void log_info_internal(const char *format, ...) { va_list ap; va_start(ap, format); log_internal(LOG_INFO, 'I', format, ap); }
void log_debug_internal(const char *format, ...) { va_list ap; va_start(ap, format); log_internal(LOG_DEBUG, 'D', format, ap); }
MTC_STATIC void * script_service_thread( void *param) { int listening_socket, message_socket; struct sockaddr_un message_socket_addr; socklen_t message_socket_len; char thread_name[THREAD_NAME_LEN]; MTC_BOOLEAN term = FALSE; SCRIPT_DATA_REQUEST request; SCRIPT_DATA_RESPONSE response; MTC_U32 service_func_num; SCRIPT_SERVICE_FUNC *service_func; MTC_BOOLEAN reported = FALSE; int read_num, write_num, size; int ret; listening_socket = ((SCRIPT_SERVICE_THREAD_PARAM *) param)->socket; strcpy(thread_name, ((SCRIPT_SERVICE_THREAD_PARAM *) param)->thread_name); service_func_num = ((SCRIPT_SERVICE_THREAD_PARAM *) param)->funcnum; service_func = ((SCRIPT_SERVICE_THREAD_PARAM *) param)->func; do { fd_set fds; int nfds; struct timeval wait; int selected; char *bufptr; // // wait new connection // memset((void *)&request, 0, sizeof(request)); memset((void *)&response, 0, sizeof(response)); FD_ZERO(&fds); nfds = 0; FD_SET(listening_socket, &fds); nfds = listening_socket; wait = mstotv(POLLING_TIMEOUT); selected = select (nfds+1, &fds, NULL, NULL, &wait); if (selected == 0) { // select timeout goto continue_loop; } if (selected < 0) { // select failed log_message(MTC_LOG_WARNING, "SC: select failed (thread:%s). (sys %d)\n", thread_name, errno); // try to continue; sleep(10); goto continue_loop; } if (!FD_ISSET(listening_socket, &fds)) { log_message(MTC_LOG_WARNING, "SC: socket is not set after select (thread:%s).\n", thread_name); // only bug, ignore } // // accept // message_socket_len = sizeof(message_socket_addr); if ((message_socket = accept(listening_socket, (struct sockaddr *) &message_socket_addr, &message_socket_len)) < 0) { log_message(MTC_LOG_WARNING, "SC: accept failed (thread:%s). (sys %d)\n", thread_name, errno); goto continue_loop; } // // read request head // size = sizeof(request.head); read_num = 0; bufptr = (char *)&request; while (size - read_num > 0) { // select before read FD_ZERO(&fds); FD_SET(message_socket, &fds); nfds = message_socket; wait = mstotv(_Wh * 1000); selected = select (nfds+1, &fds, NULL, NULL, &wait); if (selected == 0) { // select timeout log_message(MTC_LOG_WARNING, "SC: select timeout (thread:%s).\n", thread_name); close(message_socket); goto continue_loop; } if (selected < 0) { // select failed log_message(MTC_LOG_WARNING, "SC: select failed (thread:%s). (sys %d)\n", thread_name, errno); close(message_socket); goto continue_loop; } // read if ((ret = read(message_socket, bufptr + read_num, size - read_num)) <= 0) { // EOF or fail log_message(MTC_LOG_WARNING, "SC: read failed in request head (thread:%s). (sys %d)\n", thread_name, errno); close (message_socket); goto continue_loop; } read_num += ret; } // // check head // if (check_head_valid(&request.head) != MTC_SUCCESS) { // invalid head if (reported == FALSE) { log_message(MTC_LOG_ERR, "Script service received an invalid message.\n"); reported = TRUE; } log_message(MTC_LOG_WARNING, "SC: invalild head (thread:%s).\n", thread_name); close (message_socket); goto continue_loop; } // // read request body // size = request.head.length; read_num = 0; bufptr = (char *)&request.body; while (size - read_num > 0) { // select before read FD_ZERO(&fds); FD_SET(message_socket, &fds); nfds = message_socket; wait = mstotv(_Wh * 1000); selected = select (nfds+1, &fds, NULL, NULL, &wait); if (selected == 0) { // select timeout log_message(MTC_LOG_WARNING, "SC: select timeout (thread:%s).\n", thread_name); close(message_socket); goto continue_loop; } if (selected < 0) { // select failed log_message(MTC_LOG_WARNING, "SC: select failed (thread:%s). (sys %d)\n", thread_name, errno); close(message_socket); goto continue_loop; } // read if ((ret = read(message_socket, bufptr + read_num, size - read_num)) <= 0) { // EOF or fail log_message(MTC_LOG_WARNING, "SC: read failed in request body (thread:%s). (sys %d)\n", thread_name, errno); close (message_socket); goto continue_loop; } read_num += ret; } // // call script service function; // response.head.magic = SCRIPT_MAGIC; response.head.response = 1; response.head.type = request.head.type; response.head.length = sizeof(response.body); if (request.head.type > service_func_num || service_func[request.head.type] == NULL) { // invalid type if (reported == FALSE) { log_message(MTC_LOG_ERR, "Script service received an invalid message.\n"); reported = TRUE; } log_message(MTC_LOG_WARNING, "SC: invalid type(%d) in head (thread:%s).\n", request.head.type, thread_name); close (message_socket); goto continue_loop; } ret = service_func[request.head.type](request.head.length, (void *) &request.body, &(response.head.length), (void *) &response.body); if (ret != MTC_SUCCESS) { // service func failed // internal error log_internal(MTC_LOG_ERR, "SC: service func for type %d failed (thread:%s) status=%d.\n", request.head.type, thread_name, ret); close (message_socket); goto continue_loop; } // // write response // size = sizeof(response.head) + response.head.length; write_num = 0; bufptr = (char *)&response; while (size - write_num > 0) { // select before write FD_ZERO(&fds); FD_SET(message_socket, &fds); nfds = message_socket; wait = mstotv(_Wh * 1000); selected = select (nfds+1, NULL, &fds, NULL, &wait); if (selected == 0) { // select timeout log_message(MTC_LOG_WARNING, "SC: select timeout (thread:%s).\n", thread_name); close(message_socket); goto continue_loop; } if (selected < 0) { // select failed log_message(MTC_LOG_WARNING, "SC: select failed (thread:%s). (sys %d)\n", thread_name, errno); close(message_socket); goto continue_loop; } if ((ret = write(message_socket, bufptr + write_num, size - write_num)) <= 0) { // EOF or fail log_message(MTC_LOG_WARNING, "SC: write failed in response (thread:%s). (sys %d)\n", thread_name, errno); close (message_socket); goto continue_loop; } write_num += ret; } // close connection graceful; close (message_socket); // check set_excluded script_service_check_after_set_excluded(request.head.type, response.head.length, (void *) &response.body); continue_loop: pthread_spin_lock(&lock); term = terminate; pthread_spin_unlock(&lock); } while (!term); return NULL; }
noreturn static void log_assert_errno(const char *text, int eno, const char *file, int line, const char *func) { log_internal(LOG_CRIT, 0, file, line, func, "'%s' failed at %s:%u (%s): %s.", text, file, line, func, strerror(eno)); abort(); }