Yikun Jiang a68570b5d9 Add computing offloading code
1. Add computing offloading code
2. Add script.md
3. Add virsh_demo.xml

Change-Id: Id9ef883e2f0eb727eb5448b9d1c47767f46b1021
Signed-off-by: Yikun Jiang <yikunkero@gmail.com>
2023-10-23 19:29:57 +08:00

759 lines
20 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/******************************************************************************
* Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved.
* qtfs licensed under the Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
* PURPOSE.
* See the Mulan PSL v2 for more details.
* Author: Liqiang
* Create: 2023-03-20
* Description:
*******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <sys/epoll.h>
#include <netinet/ip.h>
#include <netinet/in.h>
#include <sys/un.h>
#include <netinet/udp.h>
#include <netinet/tcp.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <glib.h>
#include <sys/resource.h>
#include <sys/prctl.h>
#include <sys/file.h>
#include <linux/vm_sockets.h>
#include "comm.h"
#include "uds_main.h"
#include "uds_event.h"
char *uds_log_str[UDS_LOG_MAX + 1] = {"NONE", "ERROR", "INFO", "UNKNOWN"};
struct uds_global_var g_uds_var;
struct uds_global_var *p_uds_var = &g_uds_var;
struct uds_event_global_var *g_event_var = NULL;
GHashTable *event_tmout_hash;
struct uds_event *uds_alloc_event()
{
struct uds_event *p = (struct uds_event *)malloc(sizeof(struct uds_event));
if (p == NULL) {
uds_err("malloc failed.");
return NULL;
}
memset(p, 0, sizeof(struct uds_event));
return p;
}
int uds_event_insert(int efd, struct uds_event *event)
{
struct epoll_event evt;
evt.data.ptr = (void *)event;
evt.events = EPOLLIN;
if (-1 == epoll_ctl(efd, EPOLL_CTL_ADD, event->fd, &evt)) {
uds_err("epoll ctl add fd:%d event failed.", event->fd);
return -1;
}
return 0;
}
int uds_event_suspend(int efd, struct uds_event *event)
{
int ret = epoll_ctl(efd, EPOLL_CTL_DEL, event->fd, NULL);
if (ret != 0) {
uds_err("failed to suspend fd:%d.", event->fd);
return -1;
}
return 0;
}
int uds_event_delete(int efd, int fd)
{
close(fd);
return 0;
}
int uds_recv_with_timeout(int fd, char *msg, int len)
{
#define TMOUT_BLOCK_SIZE 1024
#define TMOUT_UNIT_MS 20
#define TMOUT_INTERVAL 1
#define TMOUT_MAX_MS 1000
int total_recv = 0;
int ret;
int tmout_ms = ((len / TMOUT_BLOCK_SIZE) + 1) * TMOUT_UNIT_MS;
if (len <= 0 || msg == NULL || fd < 0) {
uds_err("invalid param fd:%d len:%d or %s", fd, len, (msg == NULL) ? "msg is NULL" : "msg is not NULL");
return 0;
}
if (tmout_ms > TMOUT_MAX_MS)
tmout_ms = TMOUT_MAX_MS;
do {
ret = recv(fd, &msg[total_recv], len - total_recv, 0);
if (ret < 0) {
uds_err("recv failed ret:%d errno:%d", ret, errno);
return ret;
}
total_recv += ret;
if (total_recv > len) {
uds_err("fatal error total recv:%d longger than target len:%d", total_recv, len);
return 0;
}
if (total_recv == len) {
return total_recv;
}
usleep(TMOUT_INTERVAL * 1000);
tmout_ms -= TMOUT_INTERVAL;
} while (tmout_ms > 0);
uds_err("Fatal error, the target recv len:%d and only %d length is received when it time out", len, total_recv);
return 0;
}
#pragma GCC diagnostic ignored "-Wpointer-to-int-cast"
int uds_event_tmout_item(gpointer key, gpointer value, gpointer data)
{
struct uds_event *evt = (struct uds_event *)value;
if (evt->tmout == 0) {
uds_err("Unexpected time out value in fd:%d", key);
goto clear;
}
evt->tmout--;
if (evt->tmout > 0)
return 0;
uds_log("The connection was not established within 5s, the fd:%d wait was over due to a timeout.", key);
clear:
close((int)key);
free(evt);
return 1;
}
#pragma GCC diagnostic pop
void uds_event_timeout_proc()
{
g_hash_table_foreach_remove(event_tmout_hash, uds_event_tmout_item, NULL);
}
void uds_main_loop(int efd, struct uds_thread_arg *arg)
{
int n = 0;
int ret;
struct uds_event *udsevt;
struct epoll_event *evts = NULL;
struct uds_event_global_var *p_event_var = arg->p_event_var;
if (p_event_var == NULL) {
uds_err("event variable invalid.");
return;
}
evts = calloc(UDS_EPOLL_MAX_EVENTS, sizeof(struct epoll_event));
if (evts == NULL) {
uds_err("init calloc evts failed.");
return;
}
if (uds_event_module_init(p_event_var) == EVENT_ERR) {
uds_err("uds event module init failed, main loop not run.");
free(evts);
return;
}
#ifdef QTFS_SERVER
extern int engine_run;
while (engine_run) {
#else
while (1) {
#endif
n = epoll_wait(efd, evts, UDS_EPOLL_MAX_EVENTS, 1000);
if (n == 0) {
uds_event_timeout_proc();
continue;
}
if (n < 0) {
uds_err("epoll wait return errcode:%d", n);
continue;
}
arg->info.events += n;
uds_event_pre_hook(p_event_var);
for (int i = 0; i < n; i++) {
udsevt = (struct uds_event *)evts[i].data.ptr;
uds_log("event fd:%d events:%d tofree:%u", udsevt->fd, evts[i].events, udsevt->tofree);
if (udsevt->handler == NULL) {
uds_err("bad event, fd:%d handler is NULL.", udsevt->fd);
continue;
}
// 预检查失败择不执行handler
if (uds_event_pre_handler(udsevt) == EVENT_ERR) {
continue;
}
ret = udsevt->handler(udsevt, efd, p_event_var);
// 此处释放当前事件peer事件需要handler里面释放
if (ret == EVENT_DEL) {
uds_del_event(udsevt);
}
}
uds_event_post_hook(p_event_var);
}
free(evts);
uds_log("main loop exit.");
uds_event_module_fini(p_event_var);
return;
}
#define UDS_MAX_LISTEN_NUM 64
int uds_build_tcp_connection(struct uds_conn_arg *arg)
{
int family = AF_VSOCK;
if (arg->cs > UDS_SOCKET_SERVER) {
uds_err("cs type %d is error.", arg->cs);
return -1;
}
#ifdef UDS_TEST_MODE
family = AF_INET;
struct sockaddr_in sock_addr;
memset(&sock_addr, 0, sizeof(sock_addr));
sock_addr.sin_family = AF_INET;
#else
family = AF_VSOCK;
struct sockaddr_vm sock_addr;
memset(&sock_addr, 0, sizeof(sock_addr));
sock_addr.svm_family = AF_VSOCK;
#endif
int sock_fd = socket(family, SOCK_STREAM, 0);
if (sock_fd < 0) {
uds_err("As %s failed, socket fd: %d, errno:%d.",
(arg->cs == UDS_SOCKET_CLIENT) ? "client" : "server",
sock_fd, errno);
return -1;
}
arg->sockfd = sock_fd;
if (arg->cs == UDS_SOCKET_SERVER) {
#ifdef UDS_TEST_MODE
sock_addr.sin_port = htons(p_uds_var->tcp.port);
sock_addr.sin_addr.s_addr = inet_addr(p_uds_var->tcp.addr);
#else
sock_addr.svm_port = p_uds_var->vsock.port;
sock_addr.svm_cid = p_uds_var->vsock.cid;
#endif
if (bind(sock_fd, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) < 0) {
uds_err("As tcp server failed, bind error, errno:%d.",
errno);
goto close_and_return;
}
if (listen(sock_fd, UDS_MAX_LISTEN_NUM) < 0) {
uds_err("As tcp server listen failed, errno:%d.", errno);
goto close_and_return;
}
} else {
#ifdef UDS_TEST_MODE
sock_addr.sin_port = htons(p_uds_var->tcp.peerport);
sock_addr.sin_addr.s_addr = inet_addr(p_uds_var->tcp.peeraddr);
#else
sock_addr.svm_port = p_uds_var->vsock.peerport;
sock_addr.svm_cid = p_uds_var->vsock.peercid;
#endif
if (connect(arg->sockfd, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) < 0) {
goto close_and_return;
}
arg->connfd = sock_fd;
#ifdef UDS_TEST_MODE
uds_log("Connect to tcp server successed, ip:%s port:%u", p_uds_var->tcp.peeraddr, p_uds_var->tcp.peerport);
#else
uds_log("Connect to vsock server successed, cid:%u port:%u", p_uds_var->vsock.peercid, p_uds_var->vsock.peerport);
#endif
}
return 0;
close_and_return:
close(sock_fd);
return -1;
}
int uds_build_unix_connection(struct uds_conn_arg *arg)
{
if (arg->cs > UDS_SOCKET_SERVER) {
uds_err("cs type %d is error.", arg->cs);
return -1;
}
struct sockaddr_un sock_addr = {
.sun_family = AF_UNIX,
};
int sock_fd = socket(AF_UNIX, arg->udstype, 0);
if (sock_fd < 0) {
uds_err("As %s failed, socket fd: %d, errno:%d.",
(arg->cs == UDS_SOCKET_CLIENT) ? "client" : "server",
sock_fd, errno);
return -1;
}
strncpy(sock_addr.sun_path, arg->sun_path, sizeof(sock_addr.sun_path));
arg->sockfd = sock_fd;
if (arg->cs == UDS_SOCKET_SERVER) {
unlink(sock_addr.sun_path);
if (bind(sock_fd, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) < 0) {
uds_err("As uds server failed, bind error, errno:%d.",
errno);
goto close_and_return;
}
if (listen(sock_fd, UDS_MAX_LISTEN_NUM) < 0) {
uds_err("As uds server listen failed, errno:%d.", errno);
goto close_and_return;
}
} else {
if (connect(arg->sockfd, (struct sockaddr *)&sock_addr, sizeof(struct sockaddr_un)) < 0) {
goto close_and_return;
}
arg->connfd = sock_fd;
uds_log("Connect to uds server successed, sun path:%s", arg->sun_path);
}
return 0;
close_and_return:
uds_log("close sockfd:%d and return", sock_fd);
close(sock_fd);
return -1;
}
int uds_sock_step_accept(int sock_fd, int family)
{
struct sockaddr_in in_addr;
struct sockaddr_un un_addr;
socklen_t len = (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_un);
int connfd;
if (family == AF_INET) {
connfd = accept(sock_fd, (struct sockaddr *)&in_addr, &len);
} else {
connfd = accept(sock_fd, (struct sockaddr *)&un_addr, &len);
}
if (connfd < 0) {
uds_err("Accept error:%d, errno:%d.", connfd, errno);
return connfd;
}
if (family == AF_INET) {
uds_log("Accept success, ip:%s, port:%u",
inet_ntoa(in_addr.sin_addr),
ntohs(in_addr.sin_port));
} else {
uds_log("Accept success, sun path:%s", un_addr.sun_path);
}
return connfd;
}
struct uds_event *uds_add_event(int fd, struct uds_event *peer, int (*handler)(void *, int, struct uds_event_global_var *), void *priv)
{
struct uds_event *newevt = uds_alloc_event();
int hash = fd % p_uds_var->work_thread_num;
if (newevt == NULL || p_uds_var->efd[hash] <= 0) {
uds_err("alloc event failed, efd:%d hash:%d", p_uds_var->efd[hash], hash);
if(newevt != NULL) {
free(newevt);
}
return NULL;
}
newevt->fd = fd;
newevt->peer = peer; // 如果tcp回应消息转回uds这个fd
newevt->handler = handler;
newevt->priv = priv;
newevt->tofree = 0;
newevt->tmout = 0;
if (uds_event_insert(p_uds_var->efd[hash], newevt) != 0) {
uds_del_event(newevt);
return NULL;
}
return newevt;
}
struct uds_event *uds_add_pipe_event(int fd, int peerfd, int (*handler)(void *, int, struct uds_event_global_var *), void *priv)
{
int hash = fd % p_uds_var->work_thread_num;
struct uds_event *newevt = uds_alloc_event();
if (newevt == NULL || p_uds_var->efd[hash] <= 0) {
uds_err("alloc event failed, efd:%d", p_uds_var->efd[hash]);
return NULL;
}
newevt->fd = fd;
newevt->peerfd = peerfd; // 如果tcp回应消息转回uds这个fd
newevt->handler = handler;
newevt->priv = priv;
newevt->tofree = 0;
newevt->pipe = 1;
newevt->tmout = 0;
if (uds_event_insert(p_uds_var->efd[hash], newevt) != 0) {
uds_del_event(newevt);
return NULL;
}
return newevt;
}
void uds_del_event(struct uds_event *evt)
{
int hash = evt->fd % p_uds_var->work_thread_num;
if (evt->pipe == 1 && evt->peerfd != -1) {
// pipe是单向peerfd没有epoll事件所以直接关闭
close(evt->peerfd);
evt->peerfd = -1;
}
uds_event_delete(p_uds_var->efd[hash], evt->fd);
free(evt);
return;
}
void uds_thread_diag_init(struct uds_thread_info *info)
{
info->events = 0;
info->fdnum = 0;
}
void *uds_proxy_thread(void *arg)
{
struct uds_thread_arg *parg = (struct uds_thread_arg *)arg;
// set thread name to "udsproxyd"
prctl(PR_SET_NAME, (unsigned long)"udsproxyd");
uds_thread_diag_init(&parg->info);
uds_main_loop(parg->efd, parg);
return NULL;
}
struct uds_event *uds_init_unix_listener(const char *addr, int (*handler)(void *, int, struct uds_event_global_var *))
{
struct uds_event *udsevt;
struct uds_conn_arg arg;
struct uds_conn_arg *parg = &arg;
parg->cs = UDS_SOCKET_SERVER;
strncpy(parg->sun_path, addr, sizeof(parg->sun_path) - 1);
parg->udstype = SOCK_STREAM;
if (uds_build_unix_connection(parg) != 0)
return NULL;
udsevt = uds_add_event(parg->sockfd, NULL, handler, NULL);
if (udsevt == NULL) {
close(parg->sockfd);
uds_err("add unix listener event failed.");
return NULL;
}
return udsevt;
}
struct uds_event *uds_init_tcp_listener()
{
struct uds_event *tcpevt;
struct uds_conn_arg arg;
struct uds_conn_arg *parg = &arg;
parg->cs = UDS_SOCKET_SERVER;
if (uds_build_tcp_connection(parg) != 0)
return NULL;
tcpevt = uds_add_event(parg->sockfd, NULL, uds_event_tcp_listener, NULL);
if (tcpevt == NULL)
return NULL;
return tcpevt;
}
static inline void uds_rollback_efd(int *efd, int maxidx)
{
for (int i = 0; i < maxidx; i++) {
close(efd[i]);
}
return;
}
static int uds_thread_execute()
{
pthread_t *thrd = (pthread_t *)malloc(sizeof(pthread_t) * p_uds_var->work_thread_num);
if (thrd == NULL) {
uds_err("thread info malloc failed.");
return -1;
}
for (int i = 0; i < p_uds_var->work_thread_num; i++) {
p_uds_var->work_thread[i].p_event_var = &g_event_var[i];
p_uds_var->work_thread[i].efd = p_uds_var->efd[i];
(void)pthread_create(&thrd[i], NULL, uds_proxy_thread, &p_uds_var->work_thread[i]);
}
p_uds_var->loglevel = UDS_LOG_NONE;
for (int i = 0; i < p_uds_var->work_thread_num; i++)
pthread_join(thrd[i], NULL);
free(thrd);
return 0;
}
void uds_thread_create()
{
struct uds_conn_arg arg;
struct uds_conn_arg *parg = &arg;
struct uds_event *udsevt;
struct uds_event *tcpevt;
struct uds_event *diagevt;
struct uds_event *logevt;
int efd;
int ret;
for (int i = 0; i < p_uds_var->work_thread_num; i++) {
efd = epoll_create1(0);
if (efd == -1) {
uds_rollback_efd(p_uds_var->efd, i);
uds_err("epoll create1 failed, i:%d.", i);
return;
}
p_uds_var->efd[i] = efd;
}
if ((udsevt = uds_init_unix_listener(UDS_BUILD_CONN_ADDR, uds_event_uds_listener)) == NULL)
goto rollbackefd;
if ((tcpevt = uds_init_tcp_listener()) == NULL)
goto end;
if ((diagevt = uds_init_unix_listener(UDS_DIAG_ADDR, uds_event_diag_info)) == NULL)
goto end1;
if ((logevt = uds_init_unix_listener(UDS_LOGLEVEL_UPD, uds_event_debug_level)) == NULL)
goto end2;
if (chmod(UDS_BUILD_CONN_ADDR, UDS_FILE_MODE) < 0 ||
chmod(UDS_DIAG_ADDR, UDS_FILE_MODE) < 0 ||
chmod(UDS_LOGLEVEL_UPD, UDS_FILE_MODE) < 0) {
uds_err("set sock file mode to %o failed, errno:%d", UDS_FILE_MODE, errno);
goto end3;
}
ret = uds_thread_execute();
if (ret < 0) {
uds_err("uds create thread failed.");
}
end3:
uds_del_event(logevt);
end2:
uds_del_event(diagevt);
end1:
uds_del_event(tcpevt);
end:
uds_del_event(udsevt);
rollbackefd:
for (int i = 0; i < p_uds_var->work_thread_num; i++)
close(p_uds_var->efd[i]);
return;
}
int uds_env_prepare()
{
DIR *dir;
if (access(UDS_BUILD_CONN_ADDR, 0) == 0)
return EVENT_OK;
if ((dir = opendir(UDS_BUILD_CONN_DIR)) == NULL) {
if (mkdir(UDS_BUILD_CONN_DIR, 0600) < 0) {
uds_err("mkdir %s failed.", UDS_BUILD_CONN_DIR);
return EVENT_ERR;
}
} else {
closedir(dir);
}
return EVENT_OK;
}
int uds_hash_init()
{
event_tmout_hash = g_hash_table_new(g_direct_hash, g_direct_equal);
if (event_tmout_hash == NULL) {
uds_err("g_hash_table_new failed.");
return EVENT_ERR;
}
uds_log("init event time out hash");
return EVENT_OK;
}
void uds_hash_destroy()
{
g_hash_table_destroy(event_tmout_hash);
event_tmout_hash = NULL;
return;
}
#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
int uds_hash_insert_dirct(GHashTable *table, int key, struct uds_event *value)
{
if (g_hash_table_insert(table, (gpointer)key, value) == 0) {
uds_err("Hash table key:%d is already exist, update it.", key);
return -1;
}
uds_log("Hash insert key:%d", key);
return 0;
}
void *uds_hash_lookup_dirct(GHashTable *table, int key)
{
return (void *)g_hash_table_lookup(table, (gpointer)key);
}
int uds_hash_remove_dirct(GHashTable *table, int key)
{
if (g_hash_table_remove(table, (gpointer)key) == 0) {
uds_err("Remove key:%d from hash failed.", key);
return -1;
}
return 0;
}
#pragma GCC diagnostic pop
static void uds_rlimit()
{
struct rlimit lim;
getrlimit(RLIMIT_NOFILE, &lim);
if (lim.rlim_cur >= UDS_FD_LIMIT)
return;
uds_log("uds proxy fd cur limit:%d, change to:%d", lim.rlim_cur, UDS_FD_LIMIT);
lim.rlim_cur = UDS_FD_LIMIT;
setrlimit(RLIMIT_NOFILE, &lim);
return;
}
// port invalid range 1024~65536
#define UDS_PORT_VALID(port) (port >= 1024 && port < 65536)
#define ARG_NUM 6
static int uds_arg_check_and_init(int argc, char *argv[])
{
int myport;
int peerport;
memset(p_uds_var, 0, sizeof(struct uds_global_var));
p_uds_var->loglevel = UDS_LOG_INFO;
p_uds_var->logstr = uds_log_str;
if (argc != ARG_NUM) {
uds_helpinfo(argv);
return -1;
}
myport = atoi(argv[3]);
peerport = atoi(argv[5]);
p_uds_var->work_thread_num = atoi(argv[1]);
if (p_uds_var->work_thread_num <= 0 || p_uds_var->work_thread_num > UDS_WORK_THREAD_MAX) {
uds_err("work thread num:%d is invalid.(must be 1~%d)", p_uds_var->work_thread_num, UDS_WORK_THREAD_MAX);
return -1;
}
if (!UDS_PORT_VALID(myport) || !UDS_PORT_VALID(peerport)) {
uds_err("local port:%d or peer port:%d invalid.(must be 1024~65535)", myport, peerport);
return -1;
}
p_uds_var->efd = (int *)malloc(sizeof(int) * p_uds_var->work_thread_num);
if (p_uds_var->efd == NULL) {
uds_err("efd malloc failed, num:%d", p_uds_var->work_thread_num);
return -1;
}
p_uds_var->work_thread = (struct uds_thread_arg *)malloc(sizeof(struct uds_thread_arg) * p_uds_var->work_thread_num);
if (p_uds_var->work_thread == NULL) {
free(p_uds_var->efd);
uds_err("work thread var malloc failed.");
return -1;
}
#ifdef UDS_TEST_MODE
p_uds_var->tcp.port = atoi(argv[3]);
strncpy(p_uds_var->tcp.addr, argv[2], sizeof(p_uds_var->tcp.addr) - 1);
p_uds_var->tcp.peerport = atoi(argv[5]);
strncpy(p_uds_var->tcp.peeraddr, argv[4], sizeof(p_uds_var->tcp.peeraddr) - 1);
uds_log("uds proxy param thread num:%d ip:%s port:%u peerip:%s port:%u",
p_uds_var->work_thread_num, p_uds_var->tcp.addr, p_uds_var->tcp.port,
p_uds_var->tcp.peeraddr, p_uds_var->tcp.peerport);
#else
// vsock param: <thread num> <local cid> <local port> <peer cid> <peer port>
// port and peerport is checked before
p_uds_var->vsock.cid = atoi(argv[2]);
p_uds_var->vsock.port = myport;
p_uds_var->vsock.peercid = atoi(argv[4]);
p_uds_var->vsock.peerport = peerport;
#endif
g_event_var = (struct uds_event_global_var *)malloc(sizeof(struct uds_event_global_var) * p_uds_var->work_thread_num);
if (g_event_var == NULL) {
free(p_uds_var->efd);
free(p_uds_var->work_thread);
uds_err("event variable malloc failed");
return -1;
}
return 0;
}
static void uds_sig_pipe(int signum)
{
return;
}
void uds_helpinfo(char *argv[])
{
uds_err("Usage:");
uds_err(" %s <thread nums> <addr> <port> <peeraddr> <peerport>.", argv[0]);
uds_err("Param:");
uds_err(" <thread nums> - numbers of work thread(currently only supports 1 thread)");
uds_err(" <addr> - server ip address");
uds_err(" <port> - port number");
uds_err(" <peeraddr> - peer address");
uds_err(" <peerport> - peer port");
return;
}
int check_socket_lock(void)
{
int lock_fd = open(UDS_LOCK_ADDR, O_RDONLY | O_CREAT, 0600);
if (lock_fd == -1)
return -EINVAL;
return flock(lock_fd, LOCK_EX | LOCK_NB);
}
#ifdef QTFS_SERVER
int uds_proxy_main(int argc, char *argv[])
{
#else
int main(int argc, char *argv[])
{
mode_t newmask = 0077;
uds_log("change uds umask from:%o to %o", umask(newmask), newmask);
#endif
if (uds_arg_check_and_init(argc, argv) < 0) {
uds_err("global var init failed.");
return -1;
}
if (uds_env_prepare() != EVENT_OK) {
uds_err("proxy prepare environment failed.");
return -1;
}
if (check_socket_lock() < 0) {
uds_err("another proxy running");
return -1;
}
if (uds_hash_init() != EVENT_OK) {
uds_err("proxy hash init failed.");
return -1;
}
#ifndef QTFS_SERVER
uds_rlimit();
#endif
signal(SIGPIPE, uds_sig_pipe);
uds_thread_create();
uds_hash_destroy();
return 0;
}