#include <linux/udp.h>
#include <linux/tcp.h>
#include <linux/sunrpc/clnt.h>
+#include <linux/sunrpc/sched.h>
#include <linux/file.h>
#include <net/sock.h>
#include <net/udp.h>
#include <net/tcp.h>
+/*
+ * xprtsock tunables
+ */
+unsigned int xprt_udp_slot_table_entries = RPC_DEF_SLOT_TABLE;
+unsigned int xprt_tcp_slot_table_entries = RPC_DEF_SLOT_TABLE;
+
+unsigned int xprt_min_resvport = RPC_DEF_MIN_RESVPORT;
+unsigned int xprt_max_resvport = RPC_DEF_MAX_RESVPORT;
+
/*
* How many times to try sending a request on a socket before waiting
* for the socket buffer to clear.
struct sock *sk = xprt->inet;
if (!sk)
- return;
+ goto clear_close_wait;
dprintk("RPC: xs_close xprt %p\n", xprt);
sk->sk_no_check = 0;
sock_release(sock);
+clear_close_wait:
+ smp_mb__before_clear_bit();
+ clear_bit(XPRT_CLOSE_WAIT, &xprt->state);
+ smp_mb__after_clear_bit();
}
/**
case TCP_SYN_SENT:
case TCP_SYN_RECV:
break;
+ case TCP_CLOSE_WAIT:
+ /* Try to schedule an autoclose RPC calls */
+ set_bit(XPRT_CLOSE_WAIT, &xprt->state);
+ if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0)
+ schedule_work(&xprt->task_cleanup);
default:
xprt_disconnect(xprt);
- break;
}
out:
read_unlock(&sk->sk_callback_lock);
read_unlock(&sk->sk_callback_lock);
}
-/**
- * xs_udp_set_buffer_size - set send and receive limits
- * @xprt: generic transport
- *
- * Set socket send and receive limits based on the
- * sndsize and rcvsize fields in the generic transport
- * structure.
- */
-static void xs_udp_set_buffer_size(struct rpc_xprt *xprt)
+static void xs_udp_do_set_buffer_size(struct rpc_xprt *xprt)
{
struct sock *sk = xprt->inet;
}
/**
- * xs_tcp_set_buffer_size - set send and receive limits
+ * xs_udp_set_buffer_size - set send and receive limits
* @xprt: generic transport
+ * @sndsize: requested size of send buffer, in bytes
+ * @rcvsize: requested size of receive buffer, in bytes
*
- * Nothing to do for TCP.
+ * Set socket send and receive buffer size limits.
*/
-static void xs_tcp_set_buffer_size(struct rpc_xprt *xprt)
+static void xs_udp_set_buffer_size(struct rpc_xprt *xprt, size_t sndsize, size_t rcvsize)
{
- return;
+ xprt->sndsize = 0;
+ if (sndsize)
+ xprt->sndsize = sndsize + 1024;
+ xprt->rcvsize = 0;
+ if (rcvsize)
+ xprt->rcvsize = rcvsize + 1024;
+
+ xs_udp_do_set_buffer_size(xprt);
}
/**
xprt_adjust_cwnd(task, -ETIMEDOUT);
}
+/**
+ * xs_set_port - reset the port number in the remote endpoint address
+ * @xprt: generic transport
+ * @port: new port number
+ *
+ */
+static void xs_set_port(struct rpc_xprt *xprt, unsigned short port)
+{
+ dprintk("RPC: setting port for xprt %p to %u\n", xprt, port);
+ xprt->addr.sin_port = htons(port);
+}
+
static int xs_bindresvport(struct rpc_xprt *xprt, struct socket *sock)
{
struct sockaddr_in myaddr = {
sk->sk_data_ready = xs_udp_data_ready;
sk->sk_write_space = xs_udp_write_space;
sk->sk_no_check = UDP_CSUM_NORCV;
+ sk->sk_allocation = GFP_ATOMIC;
xprt_set_connected(xprt);
write_unlock_bh(&sk->sk_callback_lock);
}
- xs_udp_set_buffer_size(xprt);
+ xs_udp_do_set_buffer_size(xprt);
status = 0;
out:
xprt_wake_pending_tasks(xprt, status);
sk->sk_data_ready = xs_tcp_data_ready;
sk->sk_state_change = xs_tcp_state_change;
sk->sk_write_space = xs_tcp_write_space;
+ sk->sk_allocation = GFP_ATOMIC;
/* socket options */
sk->sk_userlocks |= SOCK_BINDPORT_LOCK;
.set_buffer_size = xs_udp_set_buffer_size,
.reserve_xprt = xprt_reserve_xprt_cong,
.release_xprt = xprt_release_xprt_cong,
+ .set_port = xs_set_port,
.connect = xs_connect,
+ .buf_alloc = rpc_malloc,
+ .buf_free = rpc_free,
.send_request = xs_udp_send_request,
.set_retrans_timeout = xprt_set_retrans_timeout_rtt,
.timer = xs_udp_timer,
};
static struct rpc_xprt_ops xs_tcp_ops = {
- .set_buffer_size = xs_tcp_set_buffer_size,
.reserve_xprt = xprt_reserve_xprt,
.release_xprt = xprt_release_xprt,
+ .set_port = xs_set_port,
.connect = xs_connect,
+ .buf_alloc = rpc_malloc,
+ .buf_free = rpc_free,
.send_request = xs_tcp_send_request,
.set_retrans_timeout = xprt_set_retrans_timeout_def,
.close = xs_close,