This patch set includes a number fixes/cleanups to TIPC's socket code.
The first 6 are fairly trivial, while the last one does a complete overhaul
of the locking TIPC uses to make it more Linux-like. Please see each
individual patch for a further description.
Summary:
include/net/tipc/tipc_port.h | 6
net/tipc/port.c | 31 +
net/tipc/socket.c | 1113 ++++++++++++++++++++++++------------------
3 files changed, 667 insertions(+), 483 deletions(-)
Allan Stephens (7):
[TIPC]: Skip connection flow control in connectionless sockets
[TIPC]: Allow stream receive to read from multiple TIPC messages
[TIPC]: Ignore message padding when receiving stream data
[TIPC]: Correct "off by 1" error in socket queue limit enforcement
[TIPC]: Add error check to detect non-blocking form of connect()
[TIPC]: Cosmetic changes to TIPC connect() code
[TIPC]: Overhaul of socket locking logic
Thanks,
Al
--From: Allan Stephens <allan.stephens@windriver.com> All applied, thanks Allan. --
This patch fixes TIPC's connect routine to conform to Linux
kernel style norms of indentation, line length, etc.
Signed-off-by: Allan Stephens <allan.stephens@windriver.com>
---
net/tipc/socket.c | 143 +++++++++++++++++++++++++++--------------------------
1 files changed, 72 insertions(+), 71 deletions(-)
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 348e4ff..df19603 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -1248,77 +1248,78 @@ static void wakeupdispatch(struct tipc_port *tport)
static int connect(struct socket *sock, struct sockaddr *dest, int destlen,
int flags)
{
- struct tipc_sock *tsock = tipc_sk(sock->sk);
- struct sockaddr_tipc *dst = (struct sockaddr_tipc *)dest;
- struct msghdr m = {NULL,};
- struct sk_buff *buf;
- struct tipc_msg *msg;
- int res;
-
- /* For now, TIPC does not allow use of connect() with DGRAM or RDM types */
-
- if (sock->state == SS_READY)
- return -EOPNOTSUPP;
-
- /* For now, TIPC does not support the non-blocking form of connect() */
-
- if (flags & O_NONBLOCK)
- return -EWOULDBLOCK;
-
- /* Issue Posix-compliant error code if socket is in the wrong state */
-
- if (sock->state == SS_LISTENING)
- return -EOPNOTSUPP;
- if (sock->state == SS_CONNECTING)
- return -EALREADY;
- if (sock->state != SS_UNCONNECTED)
- return -EISCONN;
-
- /*
- * Reject connection attempt using multicast address
- *
- * Note: send_msg() validates the rest of the address fields,
- * so there's no need to do it here
- */
-
- if (dst->addrtype == TIPC_ADDR_MCAST)
- return -EINVAL;
-
- /* Send a 'SYN-' to destination */
-
- m.msg_name = dest;
- m.msg_namelen = destlen;
- if ((res = send_msg(NULL, sock, &m, 0)) < 0) {
- sock->state = SS_DISCONNECTING;
- return res;
- }
-
- if (mutex_lock_interruptible(&tsock->lock))
- return -ERESTARTSYS;
-
- /* Wait for destination's 'ACK' re...This patch causes TIPC to return an error indication if the non-
blocking form of connect() is requested (which TIPC does not yet
support).
Signed-off-by: Allan Stephens <allan.stephens@windriver.com>
---
net/tipc/socket.c | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 4c83aba..348e4ff 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -1260,6 +1260,11 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen,
if (sock->state == SS_READY)
return -EOPNOTSUPP;
+ /* For now, TIPC does not support the non-blocking form of connect() */
+
+ if (flags & O_NONBLOCK)
+ return -EWOULDBLOCK;
+
/* Issue Posix-compliant error code if socket is in the wrong state */
if (sock->state == SS_LISTENING)
--
1.5.3.2
--This patch fixes a bug that allowed TIPC to queue 1 more message
than allowed by the socket receive queue threshold limits. The
patch also improves the threshold code's logic and naming to help
prevent this sort of error from recurring in the future.
Signed-off-by: Allan Stephens <allan.stephens@windriver.com>
---
net/tipc/socket.c | 22 ++++++++++------------
1 files changed, 10 insertions(+), 12 deletions(-)
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index ead22e5..4c83aba 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -1079,15 +1079,15 @@ exit:
}
/**
- * queue_overloaded - test if queue overload condition exists
+ * rx_queue_full - determine if receive queue can accept another message
+ * @msg: message to be added to queue
* @queue_size: current size of queue
* @base: nominal maximum size of queue
- * @msg: message to be added to queue
*
- * Returns 1 if queue is currently overloaded, 0 otherwise
+ * Returns 1 if queue is unable to accept message, 0 otherwise
*/
-static int queue_overloaded(u32 queue_size, u32 base, struct tipc_msg *msg)
+static int rx_queue_full(struct tipc_msg *msg, u32 queue_size, u32 base)
{
u32 threshold;
u32 imp = msg_importance(msg);
@@ -1104,7 +1104,7 @@ static int queue_overloaded(u32 queue_size, u32 base, struct tipc_msg *msg)
if (msg_connected(msg))
threshold *= 4;
- return (queue_size > threshold);
+ return (queue_size >= threshold);
}
/**
@@ -1189,16 +1189,14 @@ static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf)
/* Reject message if there isn't room to queue it */
- if (unlikely((u32)atomic_read(&tipc_queue_size) >
- OVERLOAD_LIMIT_BASE)) {
- if (queue_overloaded(atomic_read(&tipc_queue_size),
- OVERLOAD_LIMIT_BASE, msg))
+ recv_q_len = (u32)atomic_read(&tipc_queue_size);
+ if (unlikely(recv_q_len >= OVERLOAD_LIMIT_BASE)) {
+ if (rx_queue_full(msg, recv_q_len, OVERLOAD_LIMIT_BASE))
return TIPC_ERR_OVERLO...This patch modifies TIPC's socket code to follow the same approach
used by other protocols. This change eliminates the need for a
mutex in the TIPC-specific portion of the socket protocol data
structure -- in its place, the standard Linux socket backlog queue
and associated locking routines are utilized. These changes fix
a long-standing receive queue bug on SMP systems, and also enable
individual read and write threads to utilize a socket without
unnecessarily interfering with each other.
Signed-off-by: Allan Stephens <allan.stephens@windriver.com>
---
include/net/tipc/tipc_port.h | 6 +
net/tipc/port.c | 31 +-
net/tipc/socket.c | 1002 ++++++++++++++++++++++++------------------
3 files changed, 608 insertions(+), 431 deletions(-)
diff --git a/include/net/tipc/tipc_port.h b/include/net/tipc/tipc_port.h
index c9b36b7..11105bc 100644
--- a/include/net/tipc/tipc_port.h
+++ b/include/net/tipc/tipc_port.h
@@ -96,6 +96,12 @@ struct tipc_port *tipc_get_port(const u32 ref);
void *tipc_get_handle(const u32 ref);
+/*
+ * The following routines require that the port be locked on entry
+ */
+
+int tipc_disconnect_port(struct tipc_port *tp_ptr);
+
#endif
diff --git a/net/tipc/port.c b/net/tipc/port.c
index e2646a9..2f58064 100644
--- a/net/tipc/port.c
+++ b/net/tipc/port.c
@@ -1240,6 +1240,28 @@ exit:
return res;
}
+/**
+ * tipc_disconnect_port - disconnect port from peer
+ *
+ * Port must be locked.
+ */
+
+int tipc_disconnect_port(struct tipc_port *tp_ptr)
+{
+ int res;
+
+ if (tp_ptr->connected) {
+ tp_ptr->connected = 0;
+ /* let timer expire on it's own to avoid deadlock! */
+ tipc_nodesub_unsubscribe(
+ &((struct port *)tp_ptr)->subscription);
+ res = TIPC_OK;
+ } else {
+ res = -ENOTCONN;
+ }
+ return res;
+}
+
/*
* tipc_disconnect(): Disconnect port form peer.
* This is a node local operation.
@@ -1248,17 +1270,12 @@ exit:
int tipc_disconnect(u32 ref)
...This patch ensures that padding bytes appearing at the end of
an incoming TIPC message are not returned as valid stream data.
Signed-off-by: Allan Stephens <allan.stephens@windriver.com>
---
net/tipc/socket.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index c1a199c..ead22e5 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -1027,7 +1027,7 @@ restart:
if (!err) {
buf_crs = (unsigned char *)(TIPC_SKB_CB(buf)->handle);
- sz = skb_tail_pointer(buf) - buf_crs;
+ sz = (unsigned char *)msg + msg_size(msg) - buf_crs;
needed = (buf_len - sz_copied);
sz_to_copy = (sz <= needed) ? sz : needed;
--
1.5.3.2
--This patch optimizes the receive path for SOCK_DGRAM and SOCK_RDM
messages by skipping over code that handles connection-based flow
control.
Signed-off-by: Allan Stephens <allan.stephens@windriver.com>
---
net/tipc/socket.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index ca6f52f..91aa2dc 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -919,7 +919,8 @@ restart:
/* Consume received message (optional) */
if (likely(!(flags & MSG_PEEK))) {
- if (unlikely(++tsock->p->conn_unacked >= TIPC_FLOW_CONTROL_WIN))
+ if ((sock->state != SS_READY) &&
+ (++tsock->p->conn_unacked >= TIPC_FLOW_CONTROL_WIN))
tipc_acknowledge(tsock->p->ref, tsock->p->conn_unacked);
advance_queue(tsock);
}
--
1.5.3.2
--This patch allows a stream socket to receive data from multiple TIPC messages in its receive queue, without requiring the use of the MSG_WAITALL flag. Acknowledgements to Florian Westphal <fw-tipc@strlen.de> for identifying this issue and suggesting how to correct it. Signed-off-by: Allan Stephens <allan.stephens@windriver.com> --- net/tipc/socket.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 91aa2dc..c1a199c 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -1065,7 +1065,9 @@ restart: /* Loop around if more data is required */ if ((sz_copied < buf_len) /* didn't get all requested data */ - && (flags & MSG_WAITALL) /* ... and need to wait for more */ + && (!skb_queue_empty(&sock->sk->sk_receive_queue) || + (flags & MSG_WAITALL)) + /* ... and more is ready or required */ && (!(flags & MSG_PEEK)) /* ... and aren't just peeking at data */ && (!err) /* ... and haven't reached a FIN */ ) -- 1.5.3.2 --
| Karl Meyer | PROBLEM: 2.6.23-rc "NETDEV WATCHDOG: eth0: transmit timed out" |
| David Miller | Slow DOWN, please!!! |
| Mark Fasheh | [PATCH 0/39] Ocfs2 updates for 2.6.28 |
| Bart Van Assche | Integration of SCST in the mainstream Linux kernel |
git: | |
| Shawn O. Pearce | Re: pack operation is thrashing my server |
| Pierre Habouzit | git send-email improvements |
| Matthieu Moy | git push to a non-bare repository |
| Shawn O. Pearce | libgit2 - a true git library |
| Elad Efrat | Integrating securelevel and kauth(9) |
| Hubert Feyrer | Re: Compressed vnd handling tested successfully |
| Lord Isildur | Re: Fork bomb protection patch |
| Matt Thomas | Re: FFS journal |
| Will Maier | cron doesn't run commands in /etc/crontab? |
| Richard Stallman | Real men don't attack straw men |
| Harald Dunkel | Re: Packet Filter: how to keep device names on hardware failure? |
| Jordi Espasa Clofent | Resolving dependencies with pkg_add |
| Question on swap as ramdisk partition | 1 hour ago | Linux kernel |
| Netfilter kernel module | 11 hours ago | Linux kernel |
| serial driver xmit problem | 14 hours ago | Linux kernel |
| Why Windows is better than Linux | 14 hours ago | Linux general |
| How can I see my kernel messages in vt12? | 21 hours ago | Linux kernel |
| Grub | 1 day ago | Linux general |
| vmalloc_fault handling in x86_64 | 1 day ago | Linux kernel |
| epoll_wait()ing on epoll FD | 1 day ago | Linux kernel |
| Framebuffer in x86_64 causes problems to multiseat | 1 day ago | Linux kernel |
| Difference between 2.4 and 2.6 regarding thread creation | 2 days ago | Linux general |
