uint32_t ruc_timer_threadCreate( pthread_t *thrdId , void *arg ) { pthread_attr_t attr; int err; /* ** The thread is initialized with ** attributes object default values */ if((err=pthread_attr_init(&attr)) != 0) { RUC_WARNING(errno); return RUC_NOK; } /* ** Create the thread */ if((err=pthread_create(thrdId,&attr,ruc_timer_TickerThread,arg)) != 0) { RUC_WARNING(errno); return RUC_NOK; } return RUC_OK; }
// 64BITS uint32_t ruc_timer_xmitReadyInternalSock(uint32 timerRef,int socketId) uint32_t ruc_timer_xmitReadyInternalSock(void * timerRef,int socketId) { ruc_timer_t *p; uint32_t socketIdx; /* ** Get the pointer to the timer Object */ p = ruc_timer_getObjRef(); if (p == (ruc_timer_t*)NULL) { /* ** bad reference */ RUC_WARNING(timerRef); return FALSE; } socketIdx = ruc_timer_getIntSockIdxFromSocketId(p,socketId); if (socketIdx == -1) { /* ** something really wrong */ RUC_WARNING(p); return FALSE; } if (socketIdx == RUC_SOC_RECV) return FALSE; else return FALSE; }
uint32_t af_unix_generic_srv_acceptIn_Cbk(void * socket_ctx_p,int socketId) { af_unix_ctx_generic_t *sock_p; sock_p = (af_unix_ctx_generic_t*)socket_ctx_p; struct sockaddr sockAddr; int sockAddrLen= sizeof(sockAddr); int fdWork; if((fdWork=accept(socketId,(struct sockaddr *)&sockAddr,(socklen_t *)&sockAddrLen)) == -1) { /* ** accept is rejected ! */ RUC_WARNING(errno); return TRUE; } /* ** Create the socket and bind it with the socket controller */ af_unix_sock_accept_create(fdWork,sock_p->af_family,sock_p->nickname,sock_p->conf_p); return TRUE; }
// 64BITS uint32_t ruc_timer_xmitEvtInternalSock(uint32 timerRef,int socketId) uint32_t ruc_timer_xmitEvtInternalSock(void * timerRef,int socketId) { ruc_timer_t *p; /* ** Get the pointer to the timer Object */ p = ruc_timer_getObjRef(); if (p == (ruc_timer_t*)NULL) { /* ** bad reference */ RUC_WARNING(timerRef); return FALSE; } RUC_WARNING(p); return FALSE; }
/** Send a message to a destination AF_UNIX socket @param fd : source socket @param pMsg: pointer to the message to send @param lgth : length of the message to send @param len_sent_p : contains the effective length @retval RUC_OK : message sent @retval RUC_PARTIAL : message partially sent @retval RUC_WOULDBLOCK : congested (not sent) @retval RUC_DISC : bad destination ** **-------------------------------------------- */ uint32_t af_unix_send_stream_generic(int fd,char *pMsg,int lgth,int *len_sent_p) { int ret; *len_sent_p = 0; ret=send(fd,pMsg,(int)lgth,0); if (ret == 0) { /* ** the other end is probably dead */ return RUC_DISC; } if (ret > 0) { *len_sent_p = ret; if (ret == lgth) return RUC_OK; return RUC_PARTIAL; } /* ** error cases ** 2 cases only : WOULD BLOCK or deconnection */ if (errno==EWOULDBLOCK) { /* ** congestion detected: the message has not been ** sent */ return RUC_WOULDBLOCK; } else { switch (errno) { case ENOENT: /* ** the destination might not be there ** -> the north socket has not been yet created */ case ECONNREFUSED: /* ** socket is still here but the process is certainly down */ default : return RUC_DISC; break; } RUC_WARNING(errno); return RUC_DISC; } return RUC_DISC; }
void ruc_timer_generateTicker(ruc_timer_t *p,uint32_t evt) { int nBytes; ruc_timer_signalMsg_t timerSignal; // 64BITS timerSignal.timerRef = (uint32_t)p; timerSignal.timerRef = p; timerSignal.signalType = RUC_TIMER_TICK; nBytes = send(p->internalSocket[RUC_SOC_SEND], (const char *)&timerSignal, sizeof(ruc_timer_signalMsg_t), 0); if (nBytes != sizeof(ruc_timer_signalMsg_t)) { /* ** message not sent */ #if 0 RUC_WARNING(errno); #endif } }
// 64BITS uint32_t ruc_timer_rcvMsgInternalSock(uint32 timerRef,int socketId) uint32_t ruc_timer_rcvMsgInternalSock(void * timerRef,int socketId) { ruc_timer_t *p; uint32_t socketIdx; int bytesRcvd; ruc_timer_signalMsg_t timerSignal; /* ** Get the pointer to the timer Object */ p = ruc_timer_getObjRef(); if (p == (ruc_timer_t*)NULL) { /* ** bad reference */ RUC_WARNING(timerRef); return FALSE; } socketIdx = ruc_timer_getIntSockIdxFromSocketId(p,socketId); if (socketIdx == -1) { /* ** something really wrong */ RUC_WARNING(p); return FALSE; } if (socketIdx == RUC_SOC_SEND) { /* ** should not occur */ RUC_WARNING(socketId); return FALSE; } /* ** Ticker received ** */ bytesRcvd = recv(socketId, (char *)&timerSignal, sizeof(ruc_timer_signalMsg_t), 0); if (bytesRcvd != sizeof(ruc_timer_signalMsg_t)) { /* ** something wrong : (BUG) */ RUC_TIMER_TRC("timer_rcvMsgIntSock_err",-1,errno,socketId,-1); RUC_WARNING(errno); return TRUE; } /* ** process the signal */ switch ( timerSignal.signalType) { case RUC_TIMER_TICK: ruc_timer_tickReceived(p); break; default: RUC_TIMER_TRC("timer_rcvMsgIntSock_err",-1,timerSignal.signalType,-1,-1); RUC_WARNING(timerSignal.signalType); break; } return TRUE; }
/** * callback associated with the socket controller for receiving a message on a AF_UNIX socket operating of datagram mode @param socket_pointer: pointer to the socket context @param socketId: reference of the socket--> not used */ uint32_t af_unix_recv_generic_cbk(void * socket_pointer,int socketId) { uint8_t buffer_header[ROZOFS_MAX_HEADER_SIZE]; af_unix_ctx_generic_t *sock_p = (af_unix_ctx_generic_t*)socket_pointer; int bytesRcvd; struct sockaddr_un sockAddr; int sockAddrLen; com_recv_template_t *recv_p; uint16_t recv_credit; int eintr_count; void *buf_recv_p; int full_msg_len; uint32_t payloadLen; char *sockname_p; uint8_t *payload_p; recv_p = &sock_p->recv; recv_credit = recv_p->recv_credit_conf; sockAddrLen = sizeof(sockAddr); /* ** Get the header of the message without removing the message from the ** socket queue */ eintr_count = 0; while(recv_credit != 0) { bytesRcvd = recvfrom(sock_p->socketRef, buffer_header, recv_p->headerSize, MSG_PEEK, (struct sockaddr *)&sockAddr, ( socklen_t *)&sockAddrLen); if (bytesRcvd == -1) { switch (errno) { case EAGAIN: /* ** the socket is empty */ return TRUE; case EINTR: /* ** re-attempt to read the socket */ eintr_count++; if (eintr_count < 3) continue; /* ** here we consider it as a error */ RUC_WARNING(eintr_count); sock_p->stats.totalRecvError++; return TRUE; case EBADF: case EFAULT: case EINVAL: default: /* ** We might need to double checl if the socket must be killed */ RUC_WARNING(errno); sock_p->stats.totalRecvError++; return TRUE; } } /* ** check we have the right length */ if (bytesRcvd != recv_p->headerSize) { /* ** unable to read the full header, so drop the current message. Notice that for ** the AF_UNIX case, the message will be truncated to the max size of buffer_header ** Here we will indicate an error an attempt to read the next inflight message if any */ sock_p->stats.totalRecvBadHeader++; RUC_WARNING(bytesRcvd); recvfrom(sock_p->socketRef, buffer_header, recv_p->headerSize, 0, (struct sockaddr *)&sockAddr, ( socklen_t *)&sockAddrLen); sock_p->stats.totalRecvBadHeader++; recv_credit--; continue; } /* ** get the length of the payload of the message */ payloadLen = com_sock_extract_length_from_header_host_format((char*)buffer_header,recv_p->msgLenOffset,recv_p->msgLenSize); if (payloadLen == 0) { /* ** the length information is wrong, skip that message and attempt to read the next one ** in sequence */ RUC_WARNING(payloadLen); recvfrom(sock_p->socketRef, buffer_header, recv_p->headerSize, 0, (struct sockaddr *)&sockAddr, ( socklen_t *)&sockAddrLen); sock_p->stats.totalRecvBadHeader++; recv_credit--; continue; } /* ** check if the message does not exceed the max buffer size */ full_msg_len = payloadLen + recv_p->headerSize; if (full_msg_len > recv_p->bufSize) { /* ** message exceeds the capacity of the receiver-> drop it */ RUC_WARNING(payloadLen); recvfrom(sock_p->socketRef, buffer_header, recv_p->headerSize, 0, (struct sockaddr *)&sockAddr, ( socklen_t *)&sockAddrLen); sock_p->stats.totalRecvBadLength++; recv_credit--; continue; } /* ** Ok now call the application for receive buffer allocation */ if (sock_p->userRcvAllocBufCallBack != NULL) { buf_recv_p = (sock_p->userRcvAllocBufCallBack)(sock_p->userRef,sock_p->index,full_msg_len); } else { buf_recv_p = af_unix_alloc_recv_buf(); } if (buf_recv_p == NULL) { /* ** the receiver is out of buffer-> leave the message in the receiver queue and exit */ sock_p->stats.totalRecvOutoFBuf++; return TRUE; } payload_p = (uint8_t*)ruc_buf_getPayload(buf_recv_p); /* ** OK, we have a receive buffer, so receive the full message and give to the application ** but before read it from the socket */ eintr_count = 0; retry: bytesRcvd = recvfrom(sock_p->socketRef, payload_p, full_msg_len, 0, (struct sockaddr *)&sockAddr, ( socklen_t *)&sockAddrLen); if (bytesRcvd == -1) { switch (errno) { case EAGAIN: /* ** the socket is empty--> that situation MUST not occur: */ ruc_buf_freeBuffer(buf_recv_p); return TRUE; case EINTR: /* ** re-attempt to read the socket */ eintr_count++; if (eintr_count < 3) goto retry; /* ** here we consider it as a error */ RUC_WARNING(eintr_count); /* ** release the receive buffer */ ruc_buf_freeBuffer(buf_recv_p); sock_p->stats.totalRecvError++; return TRUE; case EBADF: case EFAULT: case EINVAL: default: /* ** We might need to double checl if the socket must be killed */ ruc_buf_freeBuffer(buf_recv_p); RUC_WARNING(errno); sock_p->stats.totalRecvError++; return TRUE; } } /* ** check we have the right length */ if (bytesRcvd != full_msg_len) { /* ** that situation must not occur with datagram socket */ RUC_WARNING(errno); ruc_buf_freeBuffer(buf_recv_p); sock_p->stats.totalRecvError++; recv_credit--; continue; } /* ** OK, copy the reference of the source in the packet buffer */ sockname_p = ruc_buf_get_usrSrcInfo(buf_recv_p); memcpy(sockname_p,&sockAddr.sun_path,sockAddrLen); /* ** OK, call the receive process of the application */ sock_p->stats.totalRecvBytes += full_msg_len; sock_p->stats.totalRecvSuccess++; (sock_p->userRcvCallBack)(sock_p->userRef,sock_p->index,buf_recv_p); recv_credit--; } return TRUE; }
/** * Init of the pseudo fuse thread @param ch : initial channel @param se : initial session @param rozofs_fuse_buffer_count : number of request buffers (corresponds to the number of fuse save context) @retval 0 on success @retval -1 on error */ int rozofs_fuse_init(struct fuse_chan *ch,struct fuse_session *se,int rozofs_fuse_buffer_count) { int status = 0; int i; // return 0; fuse_sharemem_init_done = 0; int fileflags; rozofs_fuse_ctx_p = malloc(sizeof (rozofs_fuse_ctx_t)); if (rozofs_fuse_ctx_p == NULL) { /* ** cannot allocate memory for fuse rozofs context */ return -1; } memset(rozofs_fuse_ctx_p,0,sizeof (rozofs_fuse_ctx_t)); /* ** clear read/write merge stats table */ memset(rozofs_write_merge_stats_tab,0,sizeof(uint64_t)*RZ_FUSE_WRITE_MAX); memset (rozofs_write_buf_section_table,0,sizeof(uint64_t)*ROZOFS_FUSE_NB_OF_BUSIZE_SECTION_MAX); memset (rozofs_read_buf_section_table,0,sizeof(uint64_t)*ROZOFS_FUSE_NB_OF_BUSIZE_SECTION_MAX); memset(&rozofs_fuse_read_write_stats_buf,0,sizeof(rozofs_fuse_read_write_stats)); /* ** init of the context */ rozofs_fuse_ctx_p->fuseReqPoolRef = NULL; rozofs_fuse_ctx_p->ch = NULL; rozofs_fuse_ctx_p->se = se; rozofs_fuse_ctx_p->bufsize = 0; rozofs_fuse_ctx_p->buf_fuse_req_p = NULL; rozofs_fuse_ctx_p->dir_attr_invalidate = 0; rozofs_fuse_ctx_p->initBufCount = rozofs_fuse_buffer_count; while (1) { /* ** get the receive buffer size for former channel in order to create the request distributor: ** note: by default the fuse buffer is 4K+128K: for RozoFS the payload can reach 512K (x4) */ int bufsize = fuse_chan_bufsize(ch)*4; rozofs_fuse_ctx_p->bufsize = bufsize; /* ** create the distributor fro receiving data from fuse kernel */ status = rozofs_fuse_init_rcv_buffer_pool(ROZOFS_FUSE_RECV_BUF_COUNT,bufsize); if (status < 0) { severe( "rozofs_fuse_init fuse buffer pool creation error(%d,%d)", (int)ROZOFS_FUSE_RECV_BUF_COUNT, (int)bufsize ) ; status = -1; break; } /* ** create the pool */ rozofs_fuse_ctx_p->fuseReqPoolRef = ruc_buf_poolCreate(rozofs_fuse_buffer_count,sizeof(rozofs_fuse_save_ctx_t)); if (rozofs_fuse_ctx_p->fuseReqPoolRef == NULL) { severe( "rozofs_fuse_init buffer pool creation error(%d,%d)", (int)rozofs_fuse_buffer_count, (int)sizeof(rozofs_fuse_save_ctx_t) ) ; status = -1; break; } ruc_buffer_debug_register_pool("fuseCtx", rozofs_fuse_ctx_p->fuseReqPoolRef); /* ** Allocate a head of list for queueing pending lookup requests */ for (i=0; i< ROZOFS_MAX_LKUP_QUEUE ; i++) { ruc_listHdrInit(&rozofs_lookup_queue[i]); } /* ** allocate a buffer for receiving the fuse request */ rozofs_fuse_ctx_p->buf_fuse_req_p = malloc(bufsize); if (rozofs_fuse_ctx_p == NULL) { severe( "rozofs_fuse_init out of memory %d", bufsize ) ; status = -1; break; } /* ** get the fd of the channel */ rozofs_fuse_ctx_p->fd = fuse_chan_fd(ch); /* ** wait the end of the share memroy init prior providing it to fuse */ while (rozofs_shared_mem_init_done == 0) sleep(1); /* ** create a new channel with the specific operation for rozofs (non-blocking) */ rozofs_fuse_ctx_p->ch = fuse_chan_new(&rozofs_fuse_ch_ops,fuse_chan_fd(ch),bufsize,rozofs_fuse_ctx_p); if (rozofs_fuse_ctx_p->ch == NULL) { severe( "rozofs_fuse_init fuse_chan_new error" ) ; status = -1; break; } /* ** remove the association between the initial session and channel */ fuse_session_remove_chan(ch); /* ** OK, now add the new channel */ fuse_session_add_chan(se,rozofs_fuse_ctx_p->ch ); /* ** set the channel in non blocking mode */ if((fileflags=fcntl(rozofs_fuse_ctx_p->fd,F_GETFL,0))==-1) { RUC_WARNING(errno); status = -1; break; } if((fcntl(rozofs_fuse_ctx_p->fd,F_SETFL,fileflags|O_NDELAY))==-1) { RUC_WARNING(errno); status = -1; break; } /* ** send XON to the fuse channel */ { int ret; rozofs_fuse_ctx_p->ioctl_supported = 1; rozofs_fuse_ctx_p->data_xon = 1; while(1) { ret = ioctl(rozofs_fuse_ctx_p->fd,1,NULL); if (ret < 0) { warning("ioctl error %s",strerror(errno)); rozofs_fuse_ctx_p->ioctl_supported = 0; break; } if (rozofs_fuse_ctx_p->dir_attr_invalidate == 0) { ret = ioctl(rozofs_fuse_ctx_p->fd,3,NULL); if (ret < 0) { warning("ioctl error %s",strerror(errno)); // rozofs_fuse_ctx_p->ioctl_supported = 0; rozofs_fuse_ctx_p->dir_attr_invalidate = 1; break; } } break; } } /* ** perform the connection with the socket controller */ /* ** OK, we are almost done, just need to connect with the socket controller */ rozofs_fuse_ctx_p->connectionId = ruc_sockctl_connect(rozofs_fuse_ctx_p->fd, // Reference of the socket "rozofs_fuse", // name of the socket 3, // Priority within the socket controller (void*)rozofs_fuse_ctx_p, // user param for socketcontroller callback &rozofs_fuse_callBack_sock); // Default callbacks if (rozofs_fuse_ctx_p->connectionId == NULL) { /* ** Fail to connect with the socket controller */ RUC_WARNING(-1); status = -1; break; } rozofs_fuse_get_ticker(); status = 0; break; } /* ** attach the callback on socket controller */ //#warning no poller ruc_sockCtrl_attach_applicative_poller(rozofs_fuse_scheduler_entry_point); for(i = 0; i < 3;i++) fuse_profile[i] = 0; uma_dbg_addTopic("fuse", rozofs_fuse_show); return status; }
/** Creation of a AF_UNIX stream socket in non blocking mode see /proc/sys/net/core for socket parameters: - wmem_default: default xmit buffer size - wmem_max : max allocatable Changing the max is still possible with root privilege: either edit /etc/sysctl.conf (permanent) : (write): net.core.wmem_default = xxxx net.core.wmem_max = xxxx (read): net.core.rmem_default = xxxx net.core.rmem_max = xxxx or temporary with: echo <new_value> > /proc/sys/net/core/<your_param> @param nickname : name of socket for socket controller display name @param remote_sun_path : name of remote the AF_UNIX socket @param size: size in byte of the xmit buffer (the service double that value retval: !=0 reference of the created socket context retval < 0 : error on socket context creation */ int af_unix_sock_listening_create(char *nickname,char *remote_sun_path,af_unix_socket_conf_t *conf_p) { af_unix_ctx_generic_t *sock_p; com_xmit_template_t *xmit_p; com_recv_template_t *recv_p; int ret = -1; int len; char buf_nickname[ROZOFS_SOCK_EXTNAME_SIZE]; char *buf_nickname_p; buf_nickname_p = buf_nickname; len = strlen(remote_sun_path); if (len >= AF_UNIX_SOCKET_NAME_SIZE) { /* ** name is too big!! */ RUC_WARNING(len); return -1; } len = strlen(remote_sun_path); if (len >= AF_UNIX_SOCKET_NAME_SIZE) { /* ** name is too big!! */ RUC_WARNING(len); return -1; } /* ** Allocate a socket context */ sock_p = af_unix_alloc(); if (sock_p == NULL) { /* ** Out of socket context */ RUC_WARNING(-1); return -1; } xmit_p = &sock_p->xmit; recv_p = &sock_p->recv; sock_p->af_family = AF_UNIX; while(1) { /* ** Copy the name of the socket */ buf_nickname_p +=sprintf(buf_nickname_p,"L[U]:%s",nickname); strcpy(sock_p->nickname,nickname); /* ** Copy the sun path */ strcpy(sock_p->remote_sun_path,remote_sun_path); /* ** create the socket */ sock_p->socketRef = af_unix_sock_stream_create_internal(sock_p->remote_sun_path,conf_p->so_sendbufsize); if (sock_p->socketRef == -1) { ret = -1; break; } /* ** store the use configuration */ sock_p->conf_p = conf_p; /* ** copy the family id and instance id */ sock_p->family = conf_p->family; sock_p->instance_id = conf_p->instance_id; /* ** install the receiver part */ recv_p->headerSize = conf_p->headerSize; recv_p->msgLenOffset = conf_p->msgLenOffset; recv_p->msgLenSize = conf_p->msgLenSize; recv_p->bufSize = conf_p->bufSize; /* ** install the user reference */ sock_p->userRef = conf_p->userRef; /* ** Call the listen */ if((listen(sock_p->socketRef,5))==-1) { severe( " ruc_tcp_server_connect: listen fails for %s ,",sock_p->nickname ); break; } /* ** OK, we are almost done, just need to connect with the socket controller */ sock_p->connectionId = ruc_sockctl_connect(sock_p->socketRef, // Reference of the socket buf_nickname, // name of the socket 3, // Priority within the socket controller (void*)sock_p, // user param for socketcontroller callback &af_unix_generic_listening_callBack_sock); // Default callbacks if (sock_p->connectionId == NULL) { /* ** Fail to connect with the socket controller */ RUC_WARNING(-1); break; } /* ** All is fine */ xmit_p->state = XMIT_READY; ret = sock_p->index; return ret; break; } /* ** Check the operation status: in case of error, release the socket and the context */ if (sock_p->socketRef != -1) close(sock_p->socketRef); // unlink(sock_p->sockname); /* ** release the context */ af_unix_free_from_ptr(sock_p); return -1; }
/** Creation of a AF_UNIX socket Datagram in non blocking mode see /proc/sys/net/core for socket parameters: - wmem_default: default xmit buffer size - wmem_max : max allocatable Changing the max is still possible with root privilege: either edit /etc/sysctl.conf (permanent) : (write): net.core.wmem_default = xxxx net.core.wmem_max = xxxx (read): net.core.rmem_default = xxxx net.core.rmem_max = xxxx or temporary with: echo <new_value> > /proc/sys/net/core/<your_param> @param socketRef : fd descriptor of the new socket @param nickname : nicknem of the listening socket @param af_family : extracted from the listening scoket (AF_INET or AF_UNIX) @param remote : remote information @param size: size in byte of the xmit buffer (the service double that value retval: !=0 reference of the created socket context retval < 0 : error on socket context creation */ int af_unix_sock_accept_create(int socketRef,int af_family, char *nickname,af_unix_socket_conf_t *conf_p) { af_unix_ctx_generic_t *sock_p; com_xmit_template_t *xmit_p; com_recv_template_t *recv_p; uint32_t ipAddr; uint16_t port; int ret = -1; /* ** Allocate a socket context */ sock_p = af_unix_alloc(); if (sock_p == NULL) { /* ** Out of socket context */ RUC_WARNING(-1); close(socketRef); return -1; } xmit_p = &sock_p->xmit; recv_p = &sock_p->recv; sock_p->af_family = af_family; while(1) { if (sock_p->af_family == AF_UNIX) { /* ** Copy the name of the socket */ sock_p->nickname[0]='A'; sock_p->nickname[1]=':'; strcpy(&sock_p->nickname[2],nickname); } else { struct sockaddr_in vSckAddr; int vSckAddrLen=sizeof(struct sockaddr); char *name_p = sock_p->nickname; if((getpeername(socketRef, (struct sockaddr *)&vSckAddr,(socklen_t*) &vSckAddrLen)) == -1) { name_p += sprintf(name_p,"A:%s/????", nickname); } else { ipAddr = (uint32_t) ntohl((uint32_t)(/*(struct sockaddr *)*/vSckAddr.sin_addr.s_addr)); port = ntohs((uint16_t)(vSckAddr.sin_port)); sock_p->remote_ipaddr_host = ipAddr; sock_p->remote_port_host = port; name_p += sprintf(name_p,"A:%s/", nickname); name_p += sprintf(name_p,"%u.%u.%u.%u:%u", (ipAddr>>24)&0xFF, (ipAddr>>16)&0xFF,(ipAddr>>8)&0xFF,(ipAddr)&0xFF,port); } } /* ** configure the socket to operate in non blocking mode */ sock_p->socketRef = socketRef; if (sock_p->af_family == AF_UNIX) { af_unix_sock_set_non_blocking(sock_p->socketRef,conf_p->so_sendbufsize); } else { //#warning put code for TCP scoket tuning af_inet_tcp_tuneTcpSocket(sock_p->socketRef,conf_p->so_sendbufsize); } /* ** copy the family id and instance id */ sock_p->family = conf_p->family; sock_p->instance_id = conf_p->instance_id; /* ** install the receiver part */ recv_p->headerSize = conf_p->headerSize; recv_p->msgLenOffset = conf_p->msgLenOffset; recv_p->msgLenSize = conf_p->msgLenSize; recv_p->bufSize = conf_p->bufSize; /* ** set- the service type for the stream receiver */ if (conf_p->recv_srv_type == ROZOFS_RPC_SRV) { recv_p->rpc.receiver_active = 1; recv_p->rpc.max_receive_sz = conf_p->rpc_recv_max_sz; } else { recv_p->rpc.receiver_active = 0; } /* ** install the mandatory user callbacks */ sock_p->userRcvCallBack = conf_p->userRcvCallBack; /* ** Install the optional user callbacks */ if (conf_p->userRcvAllocBufCallBack) sock_p->userRcvAllocBufCallBack = conf_p->userRcvAllocBufCallBack; if (conf_p->userDiscCallBack) sock_p->userDiscCallBack = conf_p->userDiscCallBack; if (conf_p->userRcvReadyCallBack) sock_p->userRcvReadyCallBack = conf_p->userRcvReadyCallBack; if (conf_p->userXmitReadyCallBack) sock_p->userXmitReadyCallBack = conf_p->userXmitReadyCallBack; if (conf_p->userXmitEventCallBack) sock_p->userXmitEventCallBack = conf_p->userXmitEventCallBack; if (conf_p->userHdrAnalyzerCallBack) sock_p->userHdrAnalyzerCallBack = conf_p->userHdrAnalyzerCallBack; /* ** install the user reference */ sock_p->userRef = conf_p->userRef; /* ** Check if the user has provided its own buffer pools (notice that the user might not provide ** any pool and use the common AF_UNIX socket pool or can use its own one by providing ** a userRcvAllocBufCallBack callback. */ if (conf_p->xmitPool != 0) xmit_p->xmitPoolRef = conf_p->xmitPool; if (conf_p->xmitPool != 0) recv_p->rcvPoolRef = conf_p->recvPool; /* ** OK, we are almost done, just need to connect with the socket controller */ sock_p->connectionId = ruc_sockctl_connect(sock_p->socketRef, // Reference of the socket sock_p->nickname, // name of the socket 16, // Priority within the socket controller (void*)sock_p, // user param for socketcontroller callback &af_unix_generic_server_accepted_callBack_sock); // Default callbacks if (sock_p->connectionId == NULL) { /* ** Fail to connect with the socket controller */ RUC_WARNING(-1); break; } /* ** All is fine */ xmit_p->state = XMIT_READY; ret = sock_p->index; return ret; break; } /* ** Check the operation status: in case of error, release the socket and the context */ if (sock_p->socketRef != -1) close(sock_p->socketRef); /* ** release the context */ af_unix_free_from_ptr(sock_p); return -1; }
/** Creation of a AF_UNIX socket stream in non blocking mode see /proc/sys/net/core for socket parameters: - wmem_default: default xmit buffer size - wmem_max : max allocatable Changing the max is still possible with root privilege: either edit /etc/sysctl.conf (permanent) : (write): net.core.wmem_default = xxxx net.core.wmem_max = xxxx (read): net.core.rmem_default = xxxx net.core.rmem_max = xxxx or temporary with: echo <new_value> > /proc/sys/net/core/<your_param> @param name0fSocket : name of the AF_UNIX socket @param size: size in byte of the xmit buffer (the service double that value retval: >0 reference of the created AF_UNIX socket retval < 0 : error on socket creation */ int af_unix_sock_stream_create_internal(char *nameOfSocket,int size) { int ret; int fd=-1; struct sockaddr_un addr; int fdsize; int optionsize=sizeof(fdsize); int fileflags; /* ** create a datagram socket */ fd=socket(PF_UNIX,SOCK_STREAM,0); if(fd<0) { RUC_WARNING(errno); return -1; } /* ** remove fd if it already exists */ ret=unlink(nameOfSocket); /* ** named the socket reception side */ addr.sun_family= AF_UNIX; strcpy(addr.sun_path,nameOfSocket); ret=bind(fd,(struct sockaddr*)&addr,sizeof(addr)); if(ret<0) { RUC_WARNING(errno); return -1; } /* ** change the length for the send buffer, nothing to do for receive buf ** since it is out of the scope of the AF_SOCKET */ ret= getsockopt(fd,SOL_SOCKET,SO_SNDBUF,(char*)&fdsize,( socklen_t *)&optionsize); if(ret<0) { RUC_WARNING(errno); return -1; } /* ** update the size, always the double of the input */ fdsize=2*size; /* ** set a new size for emission and ** reception socket's buffer */ ret=setsockopt(fd,SOL_SOCKET,SO_SNDBUF,(char*)&fdsize,sizeof(int)); if(ret<0) { RUC_WARNING(errno); return -1; } /* ** Change the mode of the socket to non blocking */ if((fileflags=fcntl(fd,F_GETFL,0))==-1) { RUC_WARNING(errno); return -1; } // #warning socket is operating blocking mode #if 1 if((fcntl(fd,F_SETFL,fileflags|O_NDELAY))==-1) { RUC_WARNING(errno); return -1; } #endif return(fd); }
/** ruc_obj_desc_t *ruc_listCreate_shared(uint32_t nbElements,uint32 size) creation of a double linked list. The input arguments are the number of elements and the size of an element. it is mandatory that the element includes ruc_obj_desc_t at the beginning of its structure. @param nbElements : number of elements to create @param size : size of the structure of an element (including the size of ruc_obj_desc_t). @param key: key of the shared memory @retval <> NULL: pointer to the head of list @retval == NULL: out of memory note : the number of elements must not include the head of list. */ ruc_obj_desc_t *ruc_listCreate_shared(uint32_t nbElements,uint32_t size,key_t key) { ruc_obj_desc_t *p,*phead; uint32_t listId; uint8_t *pbyte; int i; int shmid; RUC_LIST_TRC("listCreate_in_shared",nbElements,size,-1,-1); /* ** reject the creation if the size is less than the ** ruc_obj_desc_t structure size */ if (size < sizeof(ruc_obj_desc_t)) { RUC_WARNING(-1); return (ruc_obj_desc_t*)NULL; } /* ** if the size is not long word aligned, adjust the size ** to do it. */ if ((size & 0x3) != 0) { size = ((size & (~0x3)) + 4 ); } /* ** test that the size does not exceed 32 bits */ { uint32_t nbElementOrig; uint32_t memRequested; nbElementOrig = nbElements+1; if (nbElementOrig == 0) { RUC_WARNING(-1); return (ruc_obj_desc_t*)NULL; } memRequested = size*(nbElementOrig); nbElementOrig = memRequested/size; if (nbElementOrig != (nbElements+1)) { /* ** overlap */ RUC_LIST_TRC("listCreate_err",nbElementOrig,nbElements,-1,-1); RUC_WARNING(-1); return (ruc_obj_desc_t*)NULL; } } /* ** create the shared memory */ if ((shmid = shmget(key, size*(nbElements+1), IPC_CREAT | 0666)) < 0) { perror("shmget"); RUC_WARNING(errno); return (ruc_obj_desc_t*)NULL; } /* * Now we attach the segment to our data space. */ if ((p =(ruc_obj_desc_t *) shmat(shmid, NULL, 0)) == (ruc_obj_desc_t *) -1) { perror("shmat"); RUC_WARNING(errno); return (ruc_obj_desc_t*)NULL; } /* ** get the list Id for the new list */ listId = ruc_getListId(); /* ** store the reference of the shared memory */ ruc_list_shmid_table[listId] = shmid; /* ** head of list initialization */ phead = p; phead->ps = phead; phead->pp = phead; phead->sysRef = p; phead->type = RUC_LIST_HEAD; phead->countOrObjId = nbElements ; phead->eltSize = size; phead->usrEvtCode = 0; phead->listId = listId; pbyte = (uint8_t*)p; for (i = 0; i < nbElements; i++) { pbyte +=size; p = (ruc_obj_desc_t*)pbyte; /* ** initialize the element header */ ruc_listEltInit(p); p->sysRef = phead; p->type = RUC_LIST_ELEM; p->listId = phead->listId; /* ** insert in the list */ ruc_objInsertTail(phead,p); } RUC_LIST_TRC("listCreate_out",nbElements,size,phead,phead->listId); return phead; }
uint32_t ruc_listDelete_shared(ruc_obj_desc_t *phead) { uint32_t ret; int shmid; /* ** check that phead is a head of list */ RUC_LIST_TRC("listDelete_in",phead,-1,-1,-1); if (phead->type != RUC_LIST_HEAD) { RUC_WARNING(phead->type); return RUC_NOK; } /* ** check that all the elements are in the linked list ** note : that control is optional. It is based of the ** control of the list Identifier */ ret = ruc_listCheck(phead); if (ret != TRUE) { RUC_WARNING(-1); /* ** there is some elements that are not in the queue ** or queued to another queue */ ret = ruc_listRecover(phead,TRUE); if (ret != TRUE) { /* ** unable to recover the elements or the recover ** optional is not active */ RUC_WARNING(-1); return RUC_NOK; } } /* ** all is fine, clear the type and free the memory */ phead->type = 0; /* ** get the reference of the shared memory */ shmid = ruc_list_shmid_table[phead->listId]; /* ** detach from the shared memory */ if (shmdt(phead)< 0) { RUC_WARNING(errno); } /* ** delete it */ if(shmctl(shmid,IPC_RMID,NULL) < 0) { RUC_WARNING(errno); } return RUC_OK; }
/** north_lbg_module_init create the Transaction context pool @param : north_lbg_ctx_count : number of Transaction context @retval : RUC_OK : done @retval RUC_NOK : out of memory */ uint32_t north_lbg_module_init(uint32_t north_lbg_ctx_count) { north_lbg_ctx_t *p; uint32_t idxCur; ruc_obj_desc_t *pnext; uint32_t ret = RUC_OK; north_lbg_context_allocated = 0; north_lbg_context_count = north_lbg_ctx_count; north_lbg_context_freeListHead = (north_lbg_ctx_t*) NULL; /* ** create the active list */ ruc_listHdrInit((ruc_obj_desc_t*) & north_lbg_context_activeListHead); /* ** create the af unix context pool */ north_lbg_context_freeListHead = (north_lbg_ctx_t*) ruc_listCreate(north_lbg_ctx_count, sizeof (north_lbg_ctx_t)); if (north_lbg_context_freeListHead == (north_lbg_ctx_t*) NULL) { /* ** out of memory */ RUC_WARNING(north_lbg_ctx_count * sizeof (north_lbg_ctx_t)); return RUC_NOK; } /* ** store the pointer to the first context */ north_lbg_context_pfirst = north_lbg_context_freeListHead; /* ** initialize each entry of the free list */ idxCur = 0; pnext = (ruc_obj_desc_t*) NULL; while ((p = (north_lbg_ctx_t*) ruc_objGetNext((ruc_obj_desc_t*) north_lbg_context_freeListHead, &pnext)) != (north_lbg_ctx_t*) NULL) { p->index = idxCur; p->free = TRUE; north_lbg_ctxInit(p, TRUE); p->state = NORTH_LBG_DEPENDENCY; idxCur++; } north_lbg_debug_init(); /* ** timer mode init */ north_lbg_tmr_init(200, 15); return ret; }
uint32_t ruc_timer_createInternalSocket(ruc_timer_t *p) { int ret; uint32_t retcode = RUC_NOK; int fileflags; /* ** 1 - create the socket pair */ ret = socketpair( AF_UNIX, SOCK_DGRAM, 0, &p->internalSocket[0]); if (ret < 0) { /* ** unable to create the sockets */ RUC_WARNING(errno); return RUC_NOK; } while (1) { /* ** change socket mode to asynchronous */ if((fileflags=fcntl(p->internalSocket[RUC_SOC_SEND],F_GETFL,0))==-1) { RUC_WARNING(errno); break; } if(fcntl(p->internalSocket[RUC_SOC_SEND],F_SETFL,fileflags|O_NDELAY)==-1) { RUC_WARNING(errno); break; } /* ** 2 - perform the connection with the socket controller */ p->intSockconnectionId[RUC_SOC_SEND]= ruc_sockctl_connect(p->internalSocket[RUC_SOC_SEND], "TMR_SOCK_XMIT", 16, // 64BITS (uint32_t)p, p, &ruc_timer_callBack_InternalSock); // 64BITS if (p->intSockconnectionId[RUC_SOC_SEND]== (uint32_t)NULL) if (p->intSockconnectionId[RUC_SOC_SEND]== NULL) { RUC_WARNING(RUC_SOC_SEND); break; } p->intSockconnectionId[RUC_SOC_RECV]= ruc_sockctl_connect(p->internalSocket[RUC_SOC_RECV], "TMR_SOCK_RECV", 16, // 64BITS (uint32_t)p, p, &ruc_timer_callBack_InternalSock); // 64BITS if (p->intSockconnectionId[RUC_SOC_RECV]== (uint32_t) NULL) if (p->intSockconnectionId[RUC_SOC_RECV]== NULL) { RUC_WARNING(RUC_SOC_SEND); break; } /* ** done */ retcode = RUC_OK; break; } if (retcode != RUC_OK) { /* ** something wrong: close the sockets and disconnect ** from socket controller */ close (p->internalSocket[RUC_SOC_SEND]); close (p->internalSocket[RUC_SOC_RECV]); // 64BITS if (p->intSockconnectionId[RUC_SOC_RECV] != (uint32_t) NULL) if (p->intSockconnectionId[RUC_SOC_RECV] != NULL) { ruc_sockctl_disconnect(p->intSockconnectionId[RUC_SOC_RECV]); // 64BITS p->intSockconnectionId[RUC_SOC_RECV] = (uint32_t) NULL; p->intSockconnectionId[RUC_SOC_RECV] = NULL; } // 64BITS if (p->intSockconnectionId[RUC_SOC_SEND] != (uint32_t) NULL) if (p->intSockconnectionId[RUC_SOC_SEND] != NULL) { ruc_sockctl_disconnect(p->intSockconnectionId[RUC_SOC_SEND]); // 64BITS p->intSockconnectionId[RUC_SOC_SEND] = (uint32_t) NULL; p->intSockconnectionId[RUC_SOC_SEND] = NULL; } return RUC_NOK; } return RUC_OK; }
/** Send a message to a destination AF_UNIX socket @param fd : source socket @param pMsg: pointer to the message to send @param lgth : length of the message to send @param destSock : pathname of the destination AF_UNIX socket @retval RUC_OK : message sent @retval RUC_WOULDBLOCK : congested (not sent) @retval RUC_DISC : bad destination ** **-------------------------------------------- */ uint32_t af_unix_send_generic(int fd, char *pMsg, uint32_t lgth, char* destSock) { struct sockaddr_un dest; int ret; dest.sun_family= AF_UNIX; bcopy(destSock,dest.sun_path,(strlen(destSock)+1)); ret=sendto(fd,pMsg,(int)lgth,0,(struct sockaddr*)&dest,sizeof(dest)); if (ret == -1) { /* ** 2 cases only : WOULD BLOCK or deconnection */ if (errno==EWOULDBLOCK) { /* ** congestion detected: the message has not been ** sent */ return RUC_WOULDBLOCK; } else { // RUC_WARNING(errno); switch (errno) { case ENOENT: /* ** the destination might not be there ** -> the north socket has not been yet created */ case ECONNREFUSED: /* ** socket is still here but the process is certainly down */ default : return RUC_DISC; break; } RUC_WARNING(errno); return RUC_DISC; } } /* ** the message has been sent. Double check ** that everything has been sent */ if (ret == (int)lgth) { /* ** it is OK */ return RUC_OK; } /* ** For datagram type either the full message is sent or nothing!! */ ERRFAT " Cannot block in the message of a message " ENDERRFAT; return RUC_WOULDBLOCK; }
/** * Init of the pseudo fuse thread @param ch : initial channel @param se : initial session @param rozofs_fuse_buffer_count : number of request buffers (corresponds to the number of fuse save context) @retval 0 on success @retval -1 on error */ int rozofs_fuse_init(struct fuse_chan *ch,struct fuse_session *se,int rozofs_fuse_buffer_count) { int status = 0; // return 0; int fileflags; rozofs_fuse_ctx_p = malloc(sizeof (rozofs_fuse_ctx_t)); if (rozofs_fuse_ctx_p == NULL) { /* ** cannot allocate memory for fuse rozofs context */ return -1; } /* ** clear read/write merge stats table */ memset(rozofs_write_merge_stats_tab,0,sizeof(uint64_t)*RZ_FUSE_WRITE_MAX); memset (rozofs_write_buf_section_table,0,sizeof(uint64_t)*ROZOFS_FUSE_NB_OF_BUSIZE_SECTION_MAX); memset (rozofs_read_buf_section_table,0,sizeof(uint64_t)*ROZOFS_FUSE_NB_OF_BUSIZE_SECTION_MAX); memset(&rozofs_fuse_read_write_stats_buf,0,sizeof(rozofs_fuse_read_write_stats)); /* ** init of the context */ rozofs_fuse_ctx_p->fuseReqPoolRef = NULL; rozofs_fuse_ctx_p->ch = NULL; rozofs_fuse_ctx_p->se = se; rozofs_fuse_ctx_p->bufsize = 0; rozofs_fuse_ctx_p->buf_fuse_req_p = NULL; rozofs_fuse_ctx_p->initBufCount = rozofs_fuse_buffer_count; while (1) { /* ** get the receive buffer size for former channel in order to create the request distributor */ int bufsize = fuse_chan_bufsize(ch); rozofs_fuse_ctx_p->bufsize = bufsize; /* ** create the pool */ rozofs_fuse_ctx_p->fuseReqPoolRef = ruc_buf_poolCreate(rozofs_fuse_buffer_count,sizeof(rozofs_fuse_save_ctx_t)); if (rozofs_fuse_ctx_p->fuseReqPoolRef == NULL) { ERRLOG "rozofs_fuse_init buffer pool creation error(%d,%d)", (int)rozofs_fuse_buffer_count, (int)sizeof(rozofs_fuse_save_ctx_t) ENDERRLOG ; status = -1; break; } /* ** allocate a buffer for receiving the fuse request */ rozofs_fuse_ctx_p->buf_fuse_req_p = malloc(bufsize); if (rozofs_fuse_ctx_p == NULL) { ERRLOG "rozofs_fuse_init out of memory %d", bufsize ENDERRLOG ; status = -1; break; } /* ** get the fd of the channel */ rozofs_fuse_ctx_p->fd = fuse_chan_fd(ch); /* ** create a new channel with the specific operation for rozofs (non-blocking) */ rozofs_fuse_ctx_p->ch = fuse_chan_new(&rozofs_fuse_ch_ops,fuse_chan_fd(ch),fuse_chan_bufsize(ch),rozofs_fuse_ctx_p); if (rozofs_fuse_ctx_p->ch == NULL) { ERRLOG "rozofs_fuse_init fuse_chan_new error" ENDERRLOG ; status = -1; break; } /* ** remove the association between the initial session and channel */ fuse_session_remove_chan(ch); /* ** OK, now add the new channel */ fuse_session_add_chan(se,rozofs_fuse_ctx_p->ch ); /* ** set the channel in non blocking mode */ if((fileflags=fcntl(rozofs_fuse_ctx_p->fd,F_GETFL,0))==-1) { RUC_WARNING(errno); status = -1; break; } if((fcntl(rozofs_fuse_ctx_p->fd,F_SETFL,fileflags|O_NDELAY))==-1) { RUC_WARNING(errno); status = -1; break; } /* ** perform the connection with the socket controller */ /* ** OK, we are almost done, just need to connect with the socket controller */ rozofs_fuse_ctx_p->connectionId = ruc_sockctl_connect(rozofs_fuse_ctx_p->fd, // Reference of the socket "rozofs_fuse", // name of the socket 3, // Priority within the socket controller (void*)rozofs_fuse_ctx_p, // user param for socketcontroller callback &rozofs_fuse_callBack_sock); // Default callbacks if (rozofs_fuse_ctx_p->connectionId == NULL) { /* ** Fail to connect with the socket controller */ RUC_WARNING(-1); status = -1; break; } status = 0; break; } uma_dbg_addTopic("fuse", rozofs_fuse_show); return status; }
/** af_unix_module_init create the Transaction context pool @param : af_unix_ctx_count : number of Transaction context @param : max_xmit_buf_count : number of xmit buffers @param : max_xmit_buf_size : xmit buffer size @param : max_recv_buf_count : number of receive buffers @param : max_recv_buf_count : receive buffer size @retval : RUC_OK : done @retval RUC_NOK : out of memory */ uint32_t af_unix_module_init(uint32_t af_unix_ctx_count, int max_xmit_buf_count, int max_xmit_buf_size, int max_recv_buf_count, int max_recv_buf_size ) { af_unix_ctx_generic_t *p; uint32_t idxCur; ruc_obj_desc_t *pnext; uint32_t ret = RUC_OK; af_unix_xmit_buf_count = max_xmit_buf_count; af_unix_xmit_buf_size = max_xmit_buf_size; af_unix_recv_buf_count = max_recv_buf_count; af_unix_recv_buf_size = max_recv_buf_size; af_unix_context_allocated = 0; af_unix_context_count = af_unix_ctx_count; while (1) { af_unix_buffer_pool_tb[0] = ruc_buf_poolCreate(af_unix_xmit_buf_count, af_unix_xmit_buf_size); if (af_unix_buffer_pool_tb[0] == NULL) { ret = RUC_NOK; severe( "xmit ruc_buf_poolCreate(%d,%d)", af_unix_xmit_buf_count, af_unix_xmit_buf_size ); break; } af_unix_buffer_pool_tb[1] = ruc_buf_poolCreate(af_unix_recv_buf_count, af_unix_recv_buf_size); if (af_unix_buffer_pool_tb[1] == NULL) { ret = RUC_NOK; severe( "rcv ruc_buf_poolCreate(%d,%d)", af_unix_recv_buf_count, af_unix_recv_buf_size ); break; } af_unix_context_freeListHead = (af_unix_ctx_generic_t*) NULL; /* ** create the active list */ ruc_listHdrInit((ruc_obj_desc_t*) & af_unix_context_activeListHead); /* ** create the af unix context pool */ af_unix_context_freeListHead = (af_unix_ctx_generic_t*) ruc_listCreate(af_unix_ctx_count, sizeof (af_unix_ctx_generic_t)); if (af_unix_context_freeListHead == (af_unix_ctx_generic_t*) NULL) { /* ** out of memory */ RUC_WARNING(af_unix_ctx_count * sizeof (af_unix_ctx_generic_t)); return RUC_NOK; } /* ** store the pointer to the first context */ af_unix_context_pfirst = af_unix_context_freeListHead; /* ** initialize each entry of the free list */ idxCur = 0; pnext = (ruc_obj_desc_t*) NULL; while ((p = (af_unix_ctx_generic_t*) ruc_objGetNext((ruc_obj_desc_t*) af_unix_context_freeListHead, &pnext)) != (af_unix_ctx_generic_t*) NULL) { p->index = idxCur; p->free = TRUE; af_unix_ctxInit(p, TRUE); idxCur++; } af_unix_debug_init(); break; } return ret; }