static int send_packet(struct kiocb *iocb, struct socket *sock, struct msghdr *m, size_t total_len) { struct sock *sk = sock->sk; struct tipc_port *tport = tipc_sk_port(sk); struct sockaddr_tipc *dest = (struct sockaddr_tipc *)m->msg_name; long timeout_val; int res; /* Handle implied connection establishment */ if (unlikely(dest)) return send_msg(iocb, sock, m, total_len); if ((total_len > TIPC_MAX_USER_MSG_SIZE) || (m->msg_iovlen > (unsigned)INT_MAX)) return -EMSGSIZE; if (iocb) lock_sock(sk); timeout_val = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT); do { if (unlikely(sock->state != SS_CONNECTED)) { if (sock->state == SS_DISCONNECTING) res = -EPIPE; else res = -ENOTCONN; break; } res = tipc_send(tport->ref, m->msg_iovlen, m->msg_iov, total_len); if (likely(res != -ELINKCONG)) break; if (timeout_val <= 0L) { res = timeout_val ? timeout_val : -EWOULDBLOCK; break; } release_sock(sk); timeout_val = wait_event_interruptible_timeout(*sk_sleep(sk), (!tport->congested || !tport->connected), timeout_val); lock_sock(sk); } while (1); if (iocb) release_sock(sk); return res; }
static int send_packet(struct kiocb *iocb, struct socket *sock, struct msghdr *m, size_t total_len) { struct sock *sk = sock->sk; struct tipc_port *tport = tipc_sk_port(sk); struct sockaddr_tipc *dest = (struct sockaddr_tipc *)m->msg_name; int res; /* Handle implied connection establishment */ if (unlikely(dest)) return send_msg(iocb, sock, m, total_len); if (iocb) lock_sock(sk); do { if (unlikely(sock->state != SS_CONNECTED)) { if (sock->state == SS_DISCONNECTING) res = -EPIPE; else res = -ENOTCONN; break; } res = tipc_send(tport->ref, m->msg_iovlen, m->msg_iov); if (likely(res != -ELINKCONG)) { break; } if (m->msg_flags & MSG_DONTWAIT) { res = -EWOULDBLOCK; break; } release_sock(sk); res = wait_event_interruptible(*sk_sleep(sk), (!tport->congested || !tport->connected)); lock_sock(sk); if (res) break; } while (1); if (iocb) release_sock(sk); return res; }
static int send_packet(struct kiocb *iocb, struct socket *sock, struct msghdr *m, size_t total_len) { struct tipc_sock *tsock = tipc_sk(sock->sk); struct sockaddr_tipc *dest = (struct sockaddr_tipc *)m->msg_name; int res; /* Handle implied connection establishment */ if (unlikely(dest)) return send_msg(iocb, sock, m, total_len); if (down_interruptible(&tsock->sem)) { return -ERESTARTSYS; } do { if (unlikely(sock->state != SS_CONNECTED)) { if (sock->state == SS_DISCONNECTING) res = -EPIPE; else res = -ENOTCONN; goto exit; } res = tipc_send(tsock->p->ref, m->msg_iovlen, m->msg_iov); if (likely(res != -ELINKCONG)) { exit: up(&tsock->sem); return res; } if (m->msg_flags & MSG_DONTWAIT) { res = -EWOULDBLOCK; goto exit; } if (wait_event_interruptible(*sock->sk->sk_sleep, !tsock->p->congested)) { res = -ERESTARTSYS; goto exit; } } while (1); }
static void cfg_cmd_event(struct tipc_cmd_msg *msg, char *data, u32 sz, struct tipc_portid const *orig) { int rv = -EINVAL; struct tipc_cmd_result_msg rmsg; struct iovec msg_sect[2]; int *arg; msg->cmd = ntohl(msg->cmd); cfg_prepare_res_msg(msg->cmd, msg->usr_handle, rv, &rmsg, msg_sect, data, 0); if (ntohl(msg->magic) != TIPC_MAGIC) goto exit; switch (msg->cmd) { case TIPC_CREATE_LINK: if (!cfg_check_connection(orig)) rv = disc_create_link(&msg->argv.create_link); break; case TIPC_LINK_SUBSCRIBE: { struct subscr_data *sub; if (mng.link_subscriptions > 64) break; sub = kmalloc(sizeof(*sub), GFP_ATOMIC); if (sub == NULL) { warn("Memory squeeze; dropped remote link subscription\n"); break; } INIT_LIST_HEAD(&sub->subd_list); tipc_createport(mng.user_ref, (void *)sub, TIPC_HIGH_IMPORTANCE, 0, 0, (tipc_conn_shutdown_event)cfg_linksubscr_cancel, 0, 0, (tipc_conn_msg_event)cfg_linksubscr_cancel, 0, &sub->port_ref); if (!sub->port_ref) { kfree(sub); break; } memcpy(sub->usr_handle,msg->usr_handle, sizeof(sub->usr_handle)); sub->domain = msg->argv.domain; list_add_tail(&sub->subd_list, &mng.link_subscribers); tipc_connect2port(sub->port_ref, orig); rmsg.retval = TIPC_OK; tipc_send(sub->port_ref, 2u, msg_sect); mng.link_subscriptions++; return; } default: rv = tipc_cfg_cmd(msg, data, sz, (u32 *)&msg_sect[1].iov_len, orig); } exit: rmsg.result_len = htonl(msg_sect[1].iov_len); rmsg.retval = htonl(rv); tipc_cfg_respond(msg_sect, 2u, orig); }