2006-10-17 18:44:53

by Chuck Lever III

[permalink] [raw]
Subject: [PATCH 00/10] RPC transport switch patches for 2.6.20

Hi Trond-

Same patches as last week, with the following changes: the first patch is one
I should have sent with these; not sure if you've seen it yet; the last patch
in this set is the only one that has changed -- I modified it according to
comments I received from you and hch.

Please consider these as candidates for 2.6.20.

--
corporate: <chuck dot lever at oracle dot com>

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs


2006-10-17 18:44:59

by Chuck Lever III

[permalink] [raw]
Subject: [PATCH 03/10] SUNRPC: Allocate a private data area for socket-specific rpc_xprt fields

When setting up a new transport instance, allocate enough memory for an
rpc_xprt and a private area. As part of the same memory allocation, it
will be easy to find one, given a pointer to the other.

Test plan:
Compile kernel with CONFIG_NFS enabled.

Signed-off-by: Chuck Lever <[email protected]>
---

net/sunrpc/xprtsock.c | 15 +++++++++++++--
1 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index a6f778f..5ddb20d 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -125,6 +125,15 @@ static inline void xs_pktdump(char *msg,
}
#endif

+struct xs_xprt {
+ struct rpc_xprt xprt;
+};
+
+static inline struct xs_xprt *xs_private_data(struct rpc_xprt *xprt)
+{
+ return (struct xs_xprt *) xprt;
+}
+
static void xs_format_peer_addresses(struct rpc_xprt *xprt)
{
struct sockaddr_in *addr = (struct sockaddr_in *) &xprt->addr;
@@ -1352,6 +1361,7 @@ static struct rpc_xprt_ops xs_tcp_ops =

static struct rpc_xprt *xs_setup_xprt(struct sockaddr *addr, size_t addrlen, unsigned int slot_table_size)
{
+ struct xs_xprt *private;
struct rpc_xprt *xprt;

if (addrlen > sizeof(xprt->addr)) {
@@ -1359,11 +1369,12 @@ static struct rpc_xprt *xs_setup_xprt(st
return ERR_PTR(-EBADF);
}

- xprt = kzalloc(sizeof(struct rpc_xprt), GFP_KERNEL);
- if (xprt == NULL) {
+ private = kzalloc(sizeof(struct xs_xprt), GFP_KERNEL);
+ if (private == NULL) {
dprintk("RPC: xs_setup_xprt: couldn't allocate rpc_xprt\n");
return ERR_PTR(-ENOMEM);
}
+ xprt = &private->xprt;

xprt->max_reqs = slot_table_size;
xprt->slot = kcalloc(xprt->max_reqs, sizeof(struct rpc_rqst), GFP_KERNEL);

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

2006-10-17 18:44:53

by Chuck Lever III

[permalink] [raw]
Subject: [PATCH 01/10] SUNRPC: minor optimization of "xid" field in rpc_xprt

Move the xid field in the rpc_xprt structure to be in the same cache line
as the reserve_lock, since these are used at the same time.

Test plan:
None.

Signed-off-by: Chuck Lever <[email protected]>
---

include/linux/sunrpc/xprt.h | 7 +------
1 files changed, 1 insertions(+), 6 deletions(-)

diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 60394fb..0321fb5 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -158,11 +158,6 @@ struct rpc_xprt {
resvport : 1; /* use a reserved port */

/*
- * XID
- */
- __u32 xid; /* Next XID value to use */
-
- /*
* State of TCP reply receive stuff
*/
__be32 tcp_recm, /* Fragment header */
@@ -193,8 +188,8 @@ struct rpc_xprt {
*/
spinlock_t transport_lock; /* lock transport info */
spinlock_t reserve_lock; /* lock slot table */
+ u32 xid; /* Next XID value to use */
struct rpc_task * snd_task; /* Task blocked in send */
-
struct list_head recv;

struct {

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

2006-10-17 18:44:54

by Chuck Lever III

[permalink] [raw]
Subject: [PATCH 02/10] SUNRPC: Make the transport-specific setup routine allocate rpc_xprt

Change the location where the rpc_xprt structure is allocated so each
transport implementation can allocate a private area from the same
chunk of memory.

Note also that xprt->ops->destroy, rather than xprt_destroy, is now
responsible for freeing rpc_xprt when the transport is destroyed.

Test plan:
Connectathon.

Signed-off-by: Chuck Lever <[email protected]>
---

include/linux/sunrpc/xprt.h | 4 +-
net/sunrpc/xprt.c | 31 ++++++------------
net/sunrpc/xprtsock.c | 73 +++++++++++++++++++++++++++++--------------
3 files changed, 61 insertions(+), 47 deletions(-)

diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 0321fb5..d791901 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -265,8 +265,8 @@ void xprt_disconnect(struct rpc_xprt *
/*
* Socket transport setup operations
*/
-int xs_setup_udp(struct rpc_xprt *xprt, struct rpc_timeout *to);
-int xs_setup_tcp(struct rpc_xprt *xprt, struct rpc_timeout *to);
+struct rpc_xprt * xs_setup_udp(struct sockaddr *addr, size_t addrlen, struct rpc_timeout *to);
+struct rpc_xprt * xs_setup_tcp(struct sockaddr *addr, size_t addrlen, struct rpc_timeout *to);

/*
* Reserved bit positions in xprt->state
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 8085747..8cc2afa 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -891,39 +891,25 @@ void xprt_set_timeout(struct rpc_timeout
*/
struct rpc_xprt *xprt_create_transport(int proto, struct sockaddr *ap, size_t size, struct rpc_timeout *to)
{
- int result;
struct rpc_xprt *xprt;
struct rpc_rqst *req;

- if ((xprt = kzalloc(sizeof(struct rpc_xprt), GFP_KERNEL)) == NULL) {
- dprintk("RPC: xprt_create_transport: no memory\n");
- return ERR_PTR(-ENOMEM);
- }
- if (size <= sizeof(xprt->addr)) {
- memcpy(&xprt->addr, ap, size);
- xprt->addrlen = size;
- } else {
- kfree(xprt);
- dprintk("RPC: xprt_create_transport: address too large\n");
- return ERR_PTR(-EBADF);
- }
-
switch (proto) {
case IPPROTO_UDP:
- result = xs_setup_udp(xprt, to);
+ xprt = xs_setup_udp(ap, size, to);
break;
case IPPROTO_TCP:
- result = xs_setup_tcp(xprt, to);
+ xprt = xs_setup_tcp(ap, size, to);
break;
default:
printk(KERN_ERR "RPC: unrecognized transport protocol: %d\n",
proto);
return ERR_PTR(-EIO);
}
- if (result) {
- kfree(xprt);
- dprintk("RPC: xprt_create_transport: failed, %d\n", result);
- return ERR_PTR(result);
+ if (IS_ERR(xprt)) {
+ dprintk("RPC: xprt_create_transport: failed, %ld\n",
+ -PTR_ERR(xprt));
+ return xprt;
}

kref_init(&xprt->kref);
@@ -969,8 +955,11 @@ static void xprt_destroy(struct kref *kr
dprintk("RPC: destroying transport %p\n", xprt);
xprt->shutdown = 1;
del_timer_sync(&xprt->timer);
+
+ /*
+ * Tear down transport state and free the rpc_xprt
+ */
xprt->ops->destroy(xprt);
- kfree(xprt);
}

/**
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 757fc91..a6f778f 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -528,6 +528,7 @@ static void xs_destroy(struct rpc_xprt *
xs_close(xprt);
xs_free_peer_addresses(xprt);
kfree(xprt->slot);
+ kfree(xprt);
}

static inline struct rpc_xprt *xprt_from_sock(struct sock *sk)
@@ -1349,26 +1350,53 @@ static struct rpc_xprt_ops xs_tcp_ops =
.print_stats = xs_tcp_print_stats,
};

+static struct rpc_xprt *xs_setup_xprt(struct sockaddr *addr, size_t addrlen, unsigned int slot_table_size)
+{
+ struct rpc_xprt *xprt;
+
+ if (addrlen > sizeof(xprt->addr)) {
+ dprintk("RPC: xs_setup_xprt: address too large\n");
+ return ERR_PTR(-EBADF);
+ }
+
+ xprt = kzalloc(sizeof(struct rpc_xprt), GFP_KERNEL);
+ if (xprt == NULL) {
+ dprintk("RPC: xs_setup_xprt: couldn't allocate rpc_xprt\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ xprt->max_reqs = slot_table_size;
+ xprt->slot = kcalloc(xprt->max_reqs, sizeof(struct rpc_rqst), GFP_KERNEL);
+ if (xprt->slot == NULL) {
+ kfree(xprt);
+ dprintk("RPC: xs_setup_xprt: couldn't allocate slot table\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ memcpy(&xprt->addr, addr, addrlen);
+ xprt->addrlen = addrlen;
+ xprt->port = xs_get_random_port();
+
+ return xprt;
+}
+
/**
* xs_setup_udp - Set up transport to use a UDP socket
- * @xprt: transport to set up
+ * @addr: address of remote server
+ * @addrlen: length of address in bytes
* @to: timeout parameters
*
*/
-int xs_setup_udp(struct rpc_xprt *xprt, struct rpc_timeout *to)
+struct rpc_xprt *xs_setup_udp(struct sockaddr *addr, size_t addrlen, struct rpc_timeout *to)
{
- size_t slot_table_size;
- struct sockaddr_in *addr = (struct sockaddr_in *) &xprt->addr;
+ struct rpc_xprt *xprt;

- xprt->max_reqs = xprt_udp_slot_table_entries;
- slot_table_size = xprt->max_reqs * sizeof(xprt->slot[0]);
- xprt->slot = kzalloc(slot_table_size, GFP_KERNEL);
- if (xprt->slot == NULL)
- return -ENOMEM;
+ xprt = xs_setup_xprt(addr, addrlen, xprt_udp_slot_table_entries);
+ if (IS_ERR(xprt))
+ return xprt;

- if (ntohs(addr->sin_port) != 0)
+ if (ntohs(((struct sockaddr_in *)addr)->sin_port) != 0)
xprt_set_bound(xprt);
- xprt->port = xs_get_random_port();

xprt->prot = IPPROTO_UDP;
xprt->tsh_size = 0;
@@ -1392,29 +1420,26 @@ int xs_setup_udp(struct rpc_xprt *xprt,
dprintk("RPC: set up transport to address %s\n",
xs_print_peer_address(xprt, RPC_DISPLAY_ALL));

- return 0;
+ return xprt;
}

/**
* xs_setup_tcp - Set up transport to use a TCP socket
- * @xprt: transport to set up
+ * @addr: address of remote server
+ * @addrlen: length of address in bytes
* @to: timeout parameters
*
*/
-int xs_setup_tcp(struct rpc_xprt *xprt, struct rpc_timeout *to)
+struct rpc_xprt *xs_setup_tcp(struct sockaddr *addr, size_t addrlen, struct rpc_timeout *to)
{
- size_t slot_table_size;
- struct sockaddr_in *addr = (struct sockaddr_in *) &xprt->addr;
+ struct rpc_xprt *xprt;

- xprt->max_reqs = xprt_tcp_slot_table_entries;
- slot_table_size = xprt->max_reqs * sizeof(xprt->slot[0]);
- xprt->slot = kzalloc(slot_table_size, GFP_KERNEL);
- if (xprt->slot == NULL)
- return -ENOMEM;
+ xprt = xs_setup_xprt(addr, addrlen, xprt_tcp_slot_table_entries);
+ if (IS_ERR(xprt))
+ return xprt;

- if (ntohs(addr->sin_port) != 0)
+ if (ntohs(((struct sockaddr_in *)addr)->sin_port) != 0)
xprt_set_bound(xprt);
- xprt->port = xs_get_random_port();

xprt->prot = IPPROTO_TCP;
xprt->tsh_size = sizeof(rpc_fraghdr) / sizeof(u32);
@@ -1437,5 +1462,5 @@ int xs_setup_tcp(struct rpc_xprt *xprt,
dprintk("RPC: set up transport to address %s\n",
xs_print_peer_address(xprt, RPC_DISPLAY_ALL));

- return 0;
+ return xprt;
}

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

2006-10-17 18:44:59

by Chuck Lever III

[permalink] [raw]
Subject: [PATCH 08/10] SUNRPC: move saved socket callback functions to a private data structure

Move the three fields for saving socket callback functions out of the
rpc_xprt structure and into a private data structure maintained in
net/sunrpc/xprtsock.c.

Test plan:
Compile kernel with CONFIG_NFS enabled.

Signed-off-by: Chuck Lever <[email protected]>
---

include/linux/sunrpc/xprt.h | 6 ------
net/sunrpc/xprtsock.c | 25 ++++++++++++++++---------
2 files changed, 16 insertions(+), 15 deletions(-)

diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 21beb56..17f3227 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -17,8 +17,6 @@ #include <linux/sunrpc/sched.h>
#include <linux/sunrpc/xdr.h>
#include <linux/sunrpc/msg_prot.h>

-#include <net/sock.h>
-
extern unsigned int xprt_udp_slot_table_entries;
extern unsigned int xprt_tcp_slot_table_entries;

@@ -191,10 +189,6 @@ struct rpc_xprt {
bklog_u; /* backlog queue utilization */
} stat;

- void (*old_data_ready)(struct sock *, int);
- void (*old_state_change)(struct sock *);
- void (*old_write_space)(struct sock *);
-
char * address_strings[RPC_DISPLAY_MAX];
};

diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index c0e23e3..5eeccc4 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -157,6 +157,13 @@ struct xs_xprt {
*/
size_t rcvsize,
sndsize;
+
+ /*
+ * Saved socket callback addresses
+ */
+ void (*old_data_ready)(struct sock *, int);
+ void (*old_state_change)(struct sock *);
+ void (*old_write_space)(struct sock *);
};

/*
@@ -554,9 +561,9 @@ static void xs_close(struct rpc_xprt *xp
private->sock = NULL;

sk->sk_user_data = NULL;
- sk->sk_data_ready = xprt->old_data_ready;
- sk->sk_state_change = xprt->old_state_change;
- sk->sk_write_space = xprt->old_write_space;
+ sk->sk_data_ready = private->old_data_ready;
+ sk->sk_state_change = private->old_state_change;
+ sk->sk_write_space = private->old_write_space;
write_unlock_bh(&sk->sk_callback_lock);

sk->sk_no_check = 0;
@@ -1155,9 +1162,9 @@ static void xs_udp_connect_worker(void *
write_lock_bh(&sk->sk_callback_lock);

sk->sk_user_data = xprt;
- xprt->old_data_ready = sk->sk_data_ready;
- xprt->old_state_change = sk->sk_state_change;
- xprt->old_write_space = sk->sk_write_space;
+ private->old_data_ready = sk->sk_data_ready;
+ private->old_state_change = sk->sk_state_change;
+ private->old_write_space = sk->sk_write_space;
sk->sk_data_ready = xs_udp_data_ready;
sk->sk_write_space = xs_udp_write_space;
sk->sk_no_check = UDP_CSUM_NORCV;
@@ -1242,9 +1249,9 @@ static void xs_tcp_connect_worker(void *
write_lock_bh(&sk->sk_callback_lock);

sk->sk_user_data = xprt;
- xprt->old_data_ready = sk->sk_data_ready;
- xprt->old_state_change = sk->sk_state_change;
- xprt->old_write_space = sk->sk_write_space;
+ private->old_data_ready = sk->sk_data_ready;
+ private->old_state_change = sk->sk_state_change;
+ private->old_write_space = sk->sk_write_space;
sk->sk_data_ready = xs_tcp_data_ready;
sk->sk_state_change = xs_tcp_state_change;
sk->sk_write_space = xs_tcp_write_space;

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

2006-10-17 18:45:01

by Chuck Lever III

[permalink] [raw]
Subject: [PATCH 05/10] SUNRPC: Move TCP receive state variables into private data structure

Move the TCP receive state variables from the generic rpc_xprt structure to
a private structure maintained inside net/sunrpc/xprtsock.c.

Also rename a function/variable pair to refer to RPC fragment headers
instead of record markers, to be consistent with types defined in
sunrpc/*.h.

Test plan:
Connectathon with NFS over TCP.

Signed-off-by: Chuck Lever <[email protected]>
---

include/linux/sunrpc/xprt.h | 14 ----
net/sunrpc/xprtsock.c | 159 +++++++++++++++++++++++++------------------
2 files changed, 91 insertions(+), 82 deletions(-)

diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 4c074a7..3ff8230 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -158,15 +158,6 @@ struct rpc_xprt {
resvport : 1; /* use a reserved port */

/*
- * State of TCP reply receive stuff
- */
- __be32 tcp_recm, /* Fragment header */
- tcp_xid; /* Current XID */
- u32 tcp_reclen, /* fragment length */
- tcp_offset; /* fragment offset */
- unsigned long tcp_copied, /* copied to request */
- tcp_flags;
- /*
* Connection of transports
*/
unsigned long connect_timeout,
@@ -212,11 +203,6 @@ struct rpc_xprt {
char * address_strings[RPC_DISPLAY_MAX];
};

-#define XPRT_LAST_FRAG (1 << 0)
-#define XPRT_COPY_RECM (1 << 1)
-#define XPRT_COPY_XID (1 << 2)
-#define XPRT_COPY_DATA (1 << 3)
-
#ifdef __KERNEL__

/*
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 79088e8..363b2fc 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -133,8 +133,28 @@ struct xs_xprt {
*/
struct socket * sock;
struct sock * inet;
+
+ /*
+ * State of TCP reply receive
+ */
+ __be32 tcp_fraghdr,
+ tcp_xid;
+
+ u32 tcp_offset,
+ tcp_reclen;
+
+ unsigned long tcp_copied,
+ tcp_flags;
};

+/*
+ * tcp_flags
+ */
+#define XS_LAST_FRAG (1UL << 0)
+#define XS_COPY_FRGH (1UL << 1)
+#define XS_COPY_XID (1UL << 2)
+#define XS_COPY_DATA (1UL << 3)
+
static inline struct xs_xprt *xs_private_data(struct rpc_xprt *xprt)
{
return (struct xs_xprt *) xprt;
@@ -641,73 +661,73 @@ static inline size_t xs_tcp_copy_data(sk

static inline void xs_tcp_read_fraghdr(struct rpc_xprt *xprt, skb_reader_t *desc)
{
+ struct xs_xprt *private = xs_private_data(xprt);
size_t len, used;
char *p;

- p = ((char *) &xprt->tcp_recm) + xprt->tcp_offset;
- len = sizeof(xprt->tcp_recm) - xprt->tcp_offset;
+ p = ((char *) &private->tcp_fraghdr) + private->tcp_offset;
+ len = sizeof(private->tcp_fraghdr) - private->tcp_offset;
used = xs_tcp_copy_data(desc, p, len);
- xprt->tcp_offset += used;
+ private->tcp_offset += used;
if (used != len)
return;

- xprt->tcp_reclen = ntohl(xprt->tcp_recm);
- if (xprt->tcp_reclen & RPC_LAST_STREAM_FRAGMENT)
- xprt->tcp_flags |= XPRT_LAST_FRAG;
+ private->tcp_reclen = ntohl(private->tcp_fraghdr);
+ if (private->tcp_reclen & RPC_LAST_STREAM_FRAGMENT)
+ private->tcp_flags |= XS_LAST_FRAG;
else
- xprt->tcp_flags &= ~XPRT_LAST_FRAG;
- xprt->tcp_reclen &= RPC_FRAGMENT_SIZE_MASK;
+ private->tcp_flags &= ~XS_LAST_FRAG;
+ private->tcp_reclen &= RPC_FRAGMENT_SIZE_MASK;

- xprt->tcp_flags &= ~XPRT_COPY_RECM;
- xprt->tcp_offset = 0;
+ private->tcp_flags &= ~XS_COPY_FRGH;
+ private->tcp_offset = 0;

/* Sanity check of the record length */
- if (unlikely(xprt->tcp_reclen < 4)) {
+ if (unlikely(private->tcp_reclen < 4)) {
dprintk("RPC: invalid TCP record fragment length\n");
xprt_disconnect(xprt);
return;
}
dprintk("RPC: reading TCP record fragment of length %d\n",
- xprt->tcp_reclen);
+ private->tcp_reclen);
}

-static void xs_tcp_check_recm(struct rpc_xprt *xprt)
+static void xs_tcp_check_fraghdr(struct xs_xprt *private)
{
- dprintk("RPC: xprt = %p, tcp_copied = %lu, tcp_offset = %u, tcp_reclen = %u, tcp_flags = %lx\n",
- xprt, xprt->tcp_copied, xprt->tcp_offset, xprt->tcp_reclen, xprt->tcp_flags);
- if (xprt->tcp_offset == xprt->tcp_reclen) {
- xprt->tcp_flags |= XPRT_COPY_RECM;
- xprt->tcp_offset = 0;
- if (xprt->tcp_flags & XPRT_LAST_FRAG) {
- xprt->tcp_flags &= ~XPRT_COPY_DATA;
- xprt->tcp_flags |= XPRT_COPY_XID;
- xprt->tcp_copied = 0;
+ if (private->tcp_offset == private->tcp_reclen) {
+ private->tcp_flags |= XS_COPY_FRGH;
+ private->tcp_offset = 0;
+ if (private->tcp_flags & XS_LAST_FRAG) {
+ private->tcp_flags &= ~XS_COPY_DATA;
+ private->tcp_flags |= XS_COPY_XID;
+ private->tcp_copied = 0;
}
}
}

-static inline void xs_tcp_read_xid(struct rpc_xprt *xprt, skb_reader_t *desc)
+static inline void xs_tcp_read_xid(struct xs_xprt *private, skb_reader_t *desc)
{
size_t len, used;
char *p;

- len = sizeof(xprt->tcp_xid) - xprt->tcp_offset;
+ len = sizeof(private->tcp_xid) - private->tcp_offset;
dprintk("RPC: reading XID (%Zu bytes)\n", len);
- p = ((char *) &xprt->tcp_xid) + xprt->tcp_offset;
+ p = ((char *) &private->tcp_xid) + private->tcp_offset;
used = xs_tcp_copy_data(desc, p, len);
- xprt->tcp_offset += used;
+ private->tcp_offset += used;
if (used != len)
return;
- xprt->tcp_flags &= ~XPRT_COPY_XID;
- xprt->tcp_flags |= XPRT_COPY_DATA;
- xprt->tcp_copied = 4;
+ private->tcp_flags &= ~XS_COPY_XID;
+ private->tcp_flags |= XS_COPY_DATA;
+ private->tcp_copied = 4;
dprintk("RPC: reading reply for XID %08x\n",
- ntohl(xprt->tcp_xid));
- xs_tcp_check_recm(xprt);
+ ntohl(private->tcp_xid));
+ xs_tcp_check_fraghdr(private);
}

static inline void xs_tcp_read_request(struct rpc_xprt *xprt, skb_reader_t *desc)
{
+ struct xs_xprt *private = xs_private_data(xprt);
struct rpc_rqst *req;
struct xdr_buf *rcvbuf;
size_t len;
@@ -715,116 +735,116 @@ static inline void xs_tcp_read_request(s

/* Find and lock the request corresponding to this xid */
spin_lock(&xprt->transport_lock);
- req = xprt_lookup_rqst(xprt, xprt->tcp_xid);
+ req = xprt_lookup_rqst(xprt, private->tcp_xid);
if (!req) {
- xprt->tcp_flags &= ~XPRT_COPY_DATA;
+ private->tcp_flags &= ~XS_COPY_DATA;
dprintk("RPC: XID %08x request not found!\n",
- ntohl(xprt->tcp_xid));
+ ntohl(private->tcp_xid));
spin_unlock(&xprt->transport_lock);
return;
}

rcvbuf = &req->rq_private_buf;
len = desc->count;
- if (len > xprt->tcp_reclen - xprt->tcp_offset) {
+ if (len > private->tcp_reclen - private->tcp_offset) {
skb_reader_t my_desc;

- len = xprt->tcp_reclen - xprt->tcp_offset;
+ len = private->tcp_reclen - private->tcp_offset;
memcpy(&my_desc, desc, sizeof(my_desc));
my_desc.count = len;
- r = xdr_partial_copy_from_skb(rcvbuf, xprt->tcp_copied,
+ r = xdr_partial_copy_from_skb(rcvbuf, private->tcp_copied,
&my_desc, xs_tcp_copy_data);
desc->count -= r;
desc->offset += r;
} else
- r = xdr_partial_copy_from_skb(rcvbuf, xprt->tcp_copied,
+ r = xdr_partial_copy_from_skb(rcvbuf, private->tcp_copied,
desc, xs_tcp_copy_data);

if (r > 0) {
- xprt->tcp_copied += r;
- xprt->tcp_offset += r;
+ private->tcp_copied += r;
+ private->tcp_offset += r;
}
if (r != len) {
/* Error when copying to the receive buffer,
* usually because we weren't able to allocate
* additional buffer pages. All we can do now
- * is turn off XPRT_COPY_DATA, so the request
+ * is turn off XS_COPY_DATA, so the request
* will not receive any additional updates,
* and time out.
* Any remaining data from this record will
* be discarded.
*/
- xprt->tcp_flags &= ~XPRT_COPY_DATA;
+ private->tcp_flags &= ~XS_COPY_DATA;
dprintk("RPC: XID %08x truncated request\n",
- ntohl(xprt->tcp_xid));
+ ntohl(private->tcp_xid));
dprintk("RPC: xprt = %p, tcp_copied = %lu, tcp_offset = %u, tcp_reclen = %u\n",
- xprt, xprt->tcp_copied, xprt->tcp_offset, xprt->tcp_reclen);
+ xprt, private->tcp_copied, private->tcp_offset, private->tcp_reclen);
goto out;
}

dprintk("RPC: XID %08x read %Zd bytes\n",
- ntohl(xprt->tcp_xid), r);
+ ntohl(private->tcp_xid), r);
dprintk("RPC: xprt = %p, tcp_copied = %lu, tcp_offset = %u, tcp_reclen = %u\n",
- xprt, xprt->tcp_copied, xprt->tcp_offset, xprt->tcp_reclen);
+ xprt, private->tcp_copied, private->tcp_offset, private->tcp_reclen);

- if (xprt->tcp_copied == req->rq_private_buf.buflen)
- xprt->tcp_flags &= ~XPRT_COPY_DATA;
- else if (xprt->tcp_offset == xprt->tcp_reclen) {
- if (xprt->tcp_flags & XPRT_LAST_FRAG)
- xprt->tcp_flags &= ~XPRT_COPY_DATA;
+ if (private->tcp_copied == req->rq_private_buf.buflen)
+ private->tcp_flags &= ~XS_COPY_DATA;
+ else if (private->tcp_offset == private->tcp_reclen) {
+ if (private->tcp_flags & XS_LAST_FRAG)
+ private->tcp_flags &= ~XS_COPY_DATA;
}

out:
- if (!(xprt->tcp_flags & XPRT_COPY_DATA))
- xprt_complete_rqst(req->rq_task, xprt->tcp_copied);
+ if (!(private->tcp_flags & XS_COPY_DATA))
+ xprt_complete_rqst(req->rq_task, private->tcp_copied);
spin_unlock(&xprt->transport_lock);
- xs_tcp_check_recm(xprt);
+ xs_tcp_check_fraghdr(private);
}

-static inline void xs_tcp_read_discard(struct rpc_xprt *xprt, skb_reader_t *desc)
+static inline void xs_tcp_read_discard(struct xs_xprt *private, skb_reader_t *desc)
{
size_t len;

- len = xprt->tcp_reclen - xprt->tcp_offset;
+ len = private->tcp_reclen - private->tcp_offset;
if (len > desc->count)
len = desc->count;
desc->count -= len;
desc->offset += len;
- xprt->tcp_offset += len;
+ private->tcp_offset += len;
dprintk("RPC: discarded %Zu bytes\n", len);
- xs_tcp_check_recm(xprt);
+ xs_tcp_check_fraghdr(private);
}

static int xs_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, unsigned int offset, size_t len)
{
struct rpc_xprt *xprt = rd_desc->arg.data;
+ struct xs_xprt *private = xs_private_data(xprt);
skb_reader_t desc = {
.skb = skb,
.offset = offset,
.count = len,
- .csum = 0
};

dprintk("RPC: xs_tcp_data_recv started\n");
do {
/* Read in a new fragment marker if necessary */
/* Can we ever really expect to get completely empty fragments? */
- if (xprt->tcp_flags & XPRT_COPY_RECM) {
+ if (private->tcp_flags & XS_COPY_FRGH) {
xs_tcp_read_fraghdr(xprt, &desc);
continue;
}
/* Read in the xid if necessary */
- if (xprt->tcp_flags & XPRT_COPY_XID) {
- xs_tcp_read_xid(xprt, &desc);
+ if (private->tcp_flags & XS_COPY_XID) {
+ xs_tcp_read_xid(private, &desc);
continue;
}
/* Read in the request data */
- if (xprt->tcp_flags & XPRT_COPY_DATA) {
+ if (private->tcp_flags & XS_COPY_DATA) {
xs_tcp_read_request(xprt, &desc);
continue;
}
/* Skip over any trailing bytes on short reads */
- xs_tcp_read_discard(xprt, &desc);
+ xs_tcp_read_discard(private, &desc);
} while (desc.count);
dprintk("RPC: xs_tcp_data_recv done\n");
return len - desc.count;
@@ -878,11 +898,14 @@ static void xs_tcp_state_change(struct s
case TCP_ESTABLISHED:
spin_lock_bh(&xprt->transport_lock);
if (!xprt_test_and_set_connected(xprt)) {
+ struct xs_xprt *private = xs_private_data(xprt);
+
/* Reset TCP record info */
- xprt->tcp_offset = 0;
- xprt->tcp_reclen = 0;
- xprt->tcp_copied = 0;
- xprt->tcp_flags = XPRT_COPY_RECM | XPRT_COPY_XID;
+ private->tcp_offset = 0;
+ private->tcp_reclen = 0;
+ private->tcp_copied = 0;
+ private->tcp_flags = XS_COPY_FRGH | XS_COPY_XID;
+
xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO;
xprt_wake_pending_tasks(xprt, 0);
}

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

2006-10-17 18:45:02

by Chuck Lever III

[permalink] [raw]
Subject: [PATCH 10/10] SUNRPC: skb_read_bits is the same as xs_tcp_copy_data

Clean-up: eliminate xs_tcp_copy_data -- it's exactly the same logic as the
common routine skb_read_bits. The UDP and TCP socket read code now share
the same routine for copying data into an xdr_buf.

Also, rename skb_read_bits() since it is now a public function, and rename
skb_read_and_csum_bits() to be consistent.

Signed-off-by: Chuck Lever <[email protected]>
---

include/linux/sunrpc/xdr.h | 1 +
net/sunrpc/socklib.c | 14 +++++++-------
net/sunrpc/xprtsock.c | 24 ++++--------------------
3 files changed, 12 insertions(+), 27 deletions(-)

diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h
index ac69e55..b5728ca 100644
--- a/include/linux/sunrpc/xdr.h
+++ b/include/linux/sunrpc/xdr.h
@@ -156,6 +156,7 @@ typedef struct {

typedef size_t (*skb_read_actor_t)(skb_reader_t *desc, void *to, size_t len);

+size_t xdr_skb_read_bits(skb_reader_t *desc, void *to, size_t len);
extern int csum_partial_copy_to_xdr(struct xdr_buf *, struct sk_buff *);
extern ssize_t xdr_partial_copy_from_skb(struct xdr_buf *, unsigned int,
skb_reader_t *, skb_read_actor_t);
diff --git a/net/sunrpc/socklib.c b/net/sunrpc/socklib.c
index 6f17527..4bb37e8 100644
--- a/net/sunrpc/socklib.c
+++ b/net/sunrpc/socklib.c
@@ -16,7 +16,7 @@ #include <linux/sunrpc/xdr.h>


/**
- * skb_read_bits - copy some data bits from skb to internal buffer
+ * xdr_skb_read_bits - copy some data bits from skb to internal buffer
* @desc: sk_buff copy helper
* @to: copy destination
* @len: number of bytes to copy
@@ -24,11 +24,11 @@ #include <linux/sunrpc/xdr.h>
* Possibly called several times to iterate over an sk_buff and copy
* data out of it.
*/
-static size_t skb_read_bits(skb_reader_t *desc, void *to, size_t len)
+size_t xdr_skb_read_bits(skb_reader_t *desc, void *to, size_t len)
{
if (len > desc->count)
len = desc->count;
- if (skb_copy_bits(desc->skb, desc->offset, to, len))
+ if (unlikely(skb_copy_bits(desc->skb, desc->offset, to, (int) len)))
return 0;
desc->count -= len;
desc->offset += len;
@@ -36,14 +36,14 @@ static size_t skb_read_bits(skb_reader_t
}

/**
- * skb_read_and_csum_bits - copy and checksum from skb to buffer
+ * xdr_skb_read_and_csum_bits - copy and checksum from skb to buffer
* @desc: sk_buff copy helper
* @to: copy destination
* @len: number of bytes to copy
*
* Same as skb_read_bits, but calculate a checksum at the same time.
*/
-static size_t skb_read_and_csum_bits(skb_reader_t *desc, void *to, size_t len)
+static size_t xdr_skb_read_and_csum_bits(skb_reader_t *desc, void *to, size_t len)
{
unsigned int csum2, pos;

@@ -157,7 +157,7 @@ int csum_partial_copy_to_xdr(struct xdr_
goto no_checksum;

desc.csum = csum_partial(skb->data, desc.offset, skb->csum);
- if (xdr_partial_copy_from_skb(xdr, 0, &desc, skb_read_and_csum_bits) < 0)
+ if (xdr_partial_copy_from_skb(xdr, 0, &desc, xdr_skb_read_and_csum_bits) < 0)
return -1;
if (desc.offset != skb->len) {
unsigned int csum2;
@@ -172,7 +172,7 @@ int csum_partial_copy_to_xdr(struct xdr_
netdev_rx_csum_fault(skb->dev);
return 0;
no_checksum:
- if (xdr_partial_copy_from_skb(xdr, 0, &desc, skb_read_bits) < 0)
+ if (xdr_partial_copy_from_skb(xdr, 0, &desc, xdr_skb_read_bits) < 0)
return -1;
if (desc.count)
return -1;
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index de15e42..8083935 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -667,22 +667,6 @@ static void xs_udp_data_ready(struct soc
read_unlock(&sk->sk_callback_lock);
}

-static inline size_t xs_tcp_copy_data(skb_reader_t *desc, void *p, size_t len)
-{
- if (len > desc->count)
- len = desc->count;
- if (skb_copy_bits(desc->skb, desc->offset, p, len)) {
- dprintk("RPC: failed to copy %zu bytes from skb. %zu bytes remain\n",
- len, desc->count);
- return 0;
- }
- desc->offset += len;
- desc->count -= len;
- dprintk("RPC: copied %zu bytes from skb. %zu bytes remain\n",
- len, desc->count);
- return len;
-}
-
static inline void xs_tcp_read_fraghdr(struct rpc_xprt *xprt, skb_reader_t *desc)
{
struct xs_xprt *private = xs_private_data(xprt);
@@ -691,7 +675,7 @@ static inline void xs_tcp_read_fraghdr(s

p = ((char *) &private->tcp_fraghdr) + private->tcp_offset;
len = sizeof(private->tcp_fraghdr) - private->tcp_offset;
- used = xs_tcp_copy_data(desc, p, len);
+ used = xdr_skb_read_bits(desc, p, len);
private->tcp_offset += used;
if (used != len)
return;
@@ -737,7 +721,7 @@ static inline void xs_tcp_read_xid(struc
len = sizeof(private->tcp_xid) - private->tcp_offset;
dprintk("RPC: reading XID (%Zu bytes)\n", len);
p = ((char *) &private->tcp_xid) + private->tcp_offset;
- used = xs_tcp_copy_data(desc, p, len);
+ used = xdr_skb_read_bits(desc, p, len);
private->tcp_offset += used;
if (used != len)
return;
@@ -777,12 +761,12 @@ static inline void xs_tcp_read_request(s
memcpy(&my_desc, desc, sizeof(my_desc));
my_desc.count = len;
r = xdr_partial_copy_from_skb(rcvbuf, private->tcp_copied,
- &my_desc, xs_tcp_copy_data);
+ &my_desc, xdr_skb_read_bits);
desc->count -= r;
desc->offset += r;
} else
r = xdr_partial_copy_from_skb(rcvbuf, private->tcp_copied,
- desc, xs_tcp_copy_data);
+ desc, xdr_skb_read_bits);

if (r > 0) {
private->tcp_copied += r;

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

2006-10-17 18:45:03

by Chuck Lever III

[permalink] [raw]
Subject: [PATCH 09/10] SUNRPC: Store formatted addresses in private data structure

Hide buffers that store formatted IP addresses in a private data structure
maintained in net/sunrpc/xprtsock.c.

Test plan:
Enable RPCDBG_TRANS and run some typical workloads.

Signed-off-by: Chuck Lever <[email protected]>
---

include/linux/sunrpc/xprt.h | 2 --
net/sunrpc/xprtsock.c | 27 +++++++++++++++++----------
2 files changed, 17 insertions(+), 12 deletions(-)

diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 17f3227..37a42c8 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -188,8 +188,6 @@ struct rpc_xprt {
unsigned long long req_u, /* average requests on the wire */
bklog_u; /* backlog queue utilization */
} stat;
-
- char * address_strings[RPC_DISPLAY_MAX];
};

#ifdef __KERNEL__
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 5eeccc4..de15e42 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -164,6 +164,8 @@ struct xs_xprt {
void (*old_data_ready)(struct sock *, int);
void (*old_state_change)(struct sock *);
void (*old_write_space)(struct sock *);
+
+ char * address_strings[RPC_DISPLAY_MAX];
};

/*
@@ -187,6 +189,7 @@ static inline struct rpc_xprt *xprt_from
static void xs_format_peer_addresses(struct rpc_xprt *xprt)
{
struct sockaddr_in *addr = (struct sockaddr_in *) &xprt->addr;
+ struct xs_xprt *private = xs_private_data(xprt);
char *buf;

buf = kzalloc(20, GFP_KERNEL);
@@ -194,19 +197,19 @@ static void xs_format_peer_addresses(str
snprintf(buf, 20, "%u.%u.%u.%u",
NIPQUAD(addr->sin_addr.s_addr));
}
- xprt->address_strings[RPC_DISPLAY_ADDR] = buf;
+ private->address_strings[RPC_DISPLAY_ADDR] = buf;

buf = kzalloc(8, GFP_KERNEL);
if (buf) {
snprintf(buf, 8, "%u",
ntohs(addr->sin_port));
}
- xprt->address_strings[RPC_DISPLAY_PORT] = buf;
+ private->address_strings[RPC_DISPLAY_PORT] = buf;

if (xprt->prot == IPPROTO_UDP)
- xprt->address_strings[RPC_DISPLAY_PROTO] = "udp";
+ private->address_strings[RPC_DISPLAY_PROTO] = "udp";
else
- xprt->address_strings[RPC_DISPLAY_PROTO] = "tcp";
+ private->address_strings[RPC_DISPLAY_PROTO] = "tcp";

buf = kzalloc(48, GFP_KERNEL);
if (buf) {
@@ -215,14 +218,16 @@ static void xs_format_peer_addresses(str
ntohs(addr->sin_port),
xprt->prot == IPPROTO_UDP ? "udp" : "tcp");
}
- xprt->address_strings[RPC_DISPLAY_ALL] = buf;
+ private->address_strings[RPC_DISPLAY_ALL] = buf;
}

static void xs_free_peer_addresses(struct rpc_xprt *xprt)
{
- kfree(xprt->address_strings[RPC_DISPLAY_ADDR]);
- kfree(xprt->address_strings[RPC_DISPLAY_PORT]);
- kfree(xprt->address_strings[RPC_DISPLAY_ALL]);
+ struct xs_xprt *private = xs_private_data(xprt);
+
+ kfree(private->address_strings[RPC_DISPLAY_ADDR]);
+ kfree(private->address_strings[RPC_DISPLAY_PORT]);
+ kfree(private->address_strings[RPC_DISPLAY_ALL]);
}

#define XS_SENDMSG_FLAGS (MSG_DONTWAIT | MSG_NOSIGNAL)
@@ -1074,8 +1079,10 @@ static unsigned short xs_get_random_port
*/
static char *xs_print_peer_address(struct rpc_xprt *xprt, enum rpc_display_format_t format)
{
- if (xprt->address_strings[format] != NULL)
- return xprt->address_strings[format];
+ struct xs_xprt *private = xs_private_data(xprt);
+
+ if (private->address_strings[format] != NULL)
+ return private->address_strings[format];
else
return "unprintable";
}

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

2006-10-17 18:45:02

by Chuck Lever III

[permalink] [raw]
Subject: [PATCH 06/10] SUNRPC: Move rpc_xprt socket connect fields into private data structure

Move the socket-specific connection management fields out of the generic
rpc_xprt structure into a private data structure maintained in
net/sunrpc/xprtsock.c.

Test plan:
Connectathon.

Signed-off-by: Chuck Lever <[email protected]>
---

include/linux/sunrpc/xprt.h | 2 --
net/sunrpc/xprtsock.c | 36 +++++++++++++++++++++++++-----------
2 files changed, 25 insertions(+), 13 deletions(-)

diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 3ff8230..18bf72c 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -163,8 +163,6 @@ struct rpc_xprt {
unsigned long connect_timeout,
bind_timeout,
reestablish_timeout;
- struct work_struct connect_worker;
- unsigned short port;

/*
* Disconnection of idle transports
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 363b2fc..b0bead5 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -145,6 +145,12 @@ struct xs_xprt {

unsigned long tcp_copied,
tcp_flags;
+
+ /*
+ * Connection of transports
+ */
+ struct work_struct connect_worker;
+ unsigned short port;
};

/*
@@ -565,7 +571,7 @@ static void xs_destroy(struct rpc_xprt *
{
dprintk("RPC: xs_destroy xprt %p\n", xprt);

- cancel_delayed_work(&xprt->connect_worker);
+ cancel_delayed_work(&xs_private_data(xprt)->connect_worker);
flush_scheduled_work();

xprt_disconnect(xprt);
@@ -1076,18 +1082,19 @@ static void xs_set_port(struct rpc_xprt

static int xs_bindresvport(struct rpc_xprt *xprt, struct socket *sock)
{
+ struct xs_xprt *private = xs_private_data(xprt);
struct sockaddr_in myaddr = {
.sin_family = AF_INET,
};
int err;
- unsigned short port = xprt->port;
+ unsigned short port = private->port;

do {
myaddr.sin_port = htons(port);
err = kernel_bind(sock, (struct sockaddr *) &myaddr,
sizeof(myaddr));
if (err == 0) {
- xprt->port = port;
+ private->port = port;
dprintk("RPC: xs_bindresvport bound to port %u\n",
port);
return 0;
@@ -1096,7 +1103,7 @@ static int xs_bindresvport(struct rpc_xp
port = xprt_max_resvport;
else
port--;
- } while (err == -EADDRINUSE && port != xprt->port);
+ } while (err == -EADDRINUSE && port != private->port);

dprintk("RPC: can't bind to reserved port (%d).\n", -err);
return err;
@@ -1302,14 +1309,14 @@ static void xs_connect(struct rpc_task *
if (private->sock != NULL) {
dprintk("RPC: xs_connect delayed xprt %p for %lu seconds\n",
xprt, xprt->reestablish_timeout / HZ);
- schedule_delayed_work(&xprt->connect_worker,
+ schedule_delayed_work(&private->connect_worker,
xprt->reestablish_timeout);
xprt->reestablish_timeout <<= 1;
if (xprt->reestablish_timeout > XS_TCP_MAX_REEST_TO)
xprt->reestablish_timeout = XS_TCP_MAX_REEST_TO;
} else {
dprintk("RPC: xs_connect scheduled xprt %p\n", xprt);
- schedule_work(&xprt->connect_worker);
+ schedule_work(&private->connect_worker);

/* flush_scheduled_work can sleep... */
if (!RPC_IS_ASYNC(task))
@@ -1325,8 +1332,10 @@ static void xs_connect(struct rpc_task *
*/
static void xs_udp_print_stats(struct rpc_xprt *xprt, struct seq_file *seq)
{
+ struct xs_xprt *private = xs_private_data(xprt);
+
seq_printf(seq, "\txprt:\tudp %u %lu %lu %lu %lu %Lu %Lu\n",
- xprt->port,
+ private->port,
xprt->stat.bind_count,
xprt->stat.sends,
xprt->stat.recvs,
@@ -1343,13 +1352,14 @@ static void xs_udp_print_stats(struct rp
*/
static void xs_tcp_print_stats(struct rpc_xprt *xprt, struct seq_file *seq)
{
+ struct xs_xprt *private = xs_private_data(xprt);
long idle_time = 0;

if (xprt_connected(xprt))
idle_time = (long)(jiffies - xprt->last_used) / HZ;

seq_printf(seq, "\txprt:\ttcp %u %lu %lu %lu %ld %lu %lu %lu %Lu %Lu\n",
- xprt->port,
+ private->port,
xprt->stat.bind_count,
xprt->stat.connect_count,
xprt->stat.connect_time,
@@ -1423,7 +1433,7 @@ static struct rpc_xprt *xs_setup_xprt(st

memcpy(&xprt->addr, addr, addrlen);
xprt->addrlen = addrlen;
- xprt->port = xs_get_random_port();
+ private->port = xs_get_random_port();

return xprt;
}
@@ -1438,10 +1448,12 @@ static struct rpc_xprt *xs_setup_xprt(st
struct rpc_xprt *xs_setup_udp(struct sockaddr *addr, size_t addrlen, struct rpc_timeout *to)
{
struct rpc_xprt *xprt;
+ struct xs_xprt *private;

xprt = xs_setup_xprt(addr, addrlen, xprt_udp_slot_table_entries);
if (IS_ERR(xprt))
return xprt;
+ private = xs_private_data(xprt);

if (ntohs(((struct sockaddr_in *)addr)->sin_port) != 0)
xprt_set_bound(xprt);
@@ -1451,7 +1463,7 @@ struct rpc_xprt *xs_setup_udp(struct soc
/* XXX: header size can vary due to auth type, IPv6, etc. */
xprt->max_payload = (1U << 16) - (MAX_HEADER << 3);

- INIT_WORK(&xprt->connect_worker, xs_udp_connect_worker, xprt);
+ INIT_WORK(&private->connect_worker, xs_udp_connect_worker, xprt);
xprt->bind_timeout = XS_BIND_TO;
xprt->connect_timeout = XS_UDP_CONN_TO;
xprt->reestablish_timeout = XS_UDP_REEST_TO;
@@ -1481,10 +1493,12 @@ struct rpc_xprt *xs_setup_udp(struct soc
struct rpc_xprt *xs_setup_tcp(struct sockaddr *addr, size_t addrlen, struct rpc_timeout *to)
{
struct rpc_xprt *xprt;
+ struct xs_xprt *private;

xprt = xs_setup_xprt(addr, addrlen, xprt_tcp_slot_table_entries);
if (IS_ERR(xprt))
return xprt;
+ private = xs_private_data(xprt);

if (ntohs(((struct sockaddr_in *)addr)->sin_port) != 0)
xprt_set_bound(xprt);
@@ -1493,7 +1507,7 @@ struct rpc_xprt *xs_setup_tcp(struct soc
xprt->tsh_size = sizeof(rpc_fraghdr) / sizeof(u32);
xprt->max_payload = RPC_MAX_FRAGMENT_SIZE;

- INIT_WORK(&xprt->connect_worker, xs_tcp_connect_worker, xprt);
+ INIT_WORK(&private->connect_worker, xs_tcp_connect_worker, xprt);
xprt->bind_timeout = XS_BIND_TO;
xprt->connect_timeout = XS_TCP_CONN_TO;
xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO;

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

2006-10-17 18:45:03

by Chuck Lever III

[permalink] [raw]
Subject: [PATCH 07/10] SUNRPC: Move the UDP socket bufsize parameters to a private data structure

Move the socket-specific buffer size parameters for UDP sockets to a
private data structure maintained in net/sunrpc/xprtsock.c.

Test plan:
Connectathon with NFS over UDP.

Signed-off-by: Chuck Lever <[email protected]>
---

include/linux/sunrpc/xprt.h | 3 ---
net/sunrpc/xprtsock.c | 24 ++++++++++++++++--------
2 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 18bf72c..21beb56 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -137,9 +137,6 @@ struct rpc_xprt {
unsigned long cong; /* current congestion */
unsigned long cwnd; /* congestion window */

- size_t rcvsize, /* transport rcv buffer size */
- sndsize; /* transport send buffer size */
-
size_t max_payload; /* largest RPC payload size,
in bytes */
unsigned int tsh_size; /* size of transport specific
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index b0bead5..c0e23e3 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -151,6 +151,12 @@ struct xs_xprt {
*/
struct work_struct connect_worker;
unsigned short port;
+
+ /*
+ * UDP socket buffer size parameters
+ */
+ size_t rcvsize,
+ sndsize;
};

/*
@@ -1003,13 +1009,13 @@ static void xs_udp_do_set_buffer_size(st
struct xs_xprt *private = xs_private_data(xprt);
struct sock *sk = private->inet;

- if (xprt->rcvsize) {
+ if (private->rcvsize) {
sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
- sk->sk_rcvbuf = xprt->rcvsize * xprt->max_reqs * 2;
+ sk->sk_rcvbuf = private->rcvsize * xprt->max_reqs * 2;
}
- if (xprt->sndsize) {
+ if (private->sndsize) {
sk->sk_userlocks |= SOCK_SNDBUF_LOCK;
- sk->sk_sndbuf = xprt->sndsize * xprt->max_reqs * 2;
+ sk->sk_sndbuf = private->sndsize * xprt->max_reqs * 2;
sk->sk_write_space(sk);
}
}
@@ -1024,12 +1030,14 @@ static void xs_udp_do_set_buffer_size(st
*/
static void xs_udp_set_buffer_size(struct rpc_xprt *xprt, size_t sndsize, size_t rcvsize)
{
- xprt->sndsize = 0;
+ struct xs_xprt *private = xs_private_data(xprt);
+
+ private->sndsize = 0;
if (sndsize)
- xprt->sndsize = sndsize + 1024;
- xprt->rcvsize = 0;
+ private->sndsize = sndsize + 1024;
+ private->rcvsize = 0;
if (rcvsize)
- xprt->rcvsize = rcvsize + 1024;
+ private->rcvsize = rcvsize + 1024;

xs_udp_do_set_buffer_size(xprt);
}

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

2006-10-17 18:45:08

by Chuck Lever III

[permalink] [raw]
Subject: [PATCH 04/10] SUNRPC: Remove sock and inet fields from rpc_xprt

The "sock" and "inet" fields are socket-specific. Move them to a private
data structure maintained entirely within net/sunrpc/xprtsock.c

Test plan:
Connectathon.

Signed-off-by: Chuck Lever <[email protected]>
---

include/linux/sunrpc/xprt.h | 4 +--
net/sunrpc/xprtsock.c | 68 ++++++++++++++++++++++++++-----------------
2 files changed, 43 insertions(+), 29 deletions(-)

diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index d791901..4c074a7 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -17,6 +17,8 @@ #include <linux/sunrpc/sched.h>
#include <linux/sunrpc/xdr.h>
#include <linux/sunrpc/msg_prot.h>

+#include <net/sock.h>
+
extern unsigned int xprt_udp_slot_table_entries;
extern unsigned int xprt_tcp_slot_table_entries;

@@ -126,8 +128,6 @@ struct rpc_xprt_ops {
struct rpc_xprt {
struct kref kref; /* Reference count */
struct rpc_xprt_ops * ops; /* transport methods */
- struct socket * sock; /* BSD socket layer */
- struct sock * inet; /* INET layer */

struct rpc_timeout timeout; /* timeout parms */
struct sockaddr_storage addr; /* server address */
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 5ddb20d..79088e8 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -127,6 +127,12 @@ #endif

struct xs_xprt {
struct rpc_xprt xprt;
+
+ /*
+ * Network layer
+ */
+ struct socket * sock;
+ struct sock * inet;
};

static inline struct xs_xprt *xs_private_data(struct rpc_xprt *xprt)
@@ -134,6 +140,11 @@ static inline struct xs_xprt *xs_private
return (struct xs_xprt *) xprt;
}

+static inline struct rpc_xprt *xprt_from_sock(struct sock *sk)
+{
+ return (struct rpc_xprt *) sk->sk_user_data;
+}
+
static void xs_format_peer_addresses(struct rpc_xprt *xprt)
{
struct sockaddr_in *addr = (struct sockaddr_in *) &xprt->addr;
@@ -300,19 +311,20 @@ static void xs_nospace(struct rpc_task *
{
struct rpc_rqst *req = task->tk_rqstp;
struct rpc_xprt *xprt = req->rq_xprt;
+ struct socket *sock = xs_private_data(xprt)->sock;

dprintk("RPC: %4d xmit incomplete (%u left of %u)\n",
task->tk_pid, req->rq_slen - req->rq_bytes_sent,
req->rq_slen);

- if (test_bit(SOCK_ASYNC_NOSPACE, &xprt->sock->flags)) {
+ if (test_bit(SOCK_ASYNC_NOSPACE, &sock->flags)) {
/* Protect against races with write_space */
spin_lock_bh(&xprt->transport_lock);

/* Don't race with disconnect */
if (!xprt_connected(xprt))
task->tk_status = -ENOTCONN;
- else if (test_bit(SOCK_NOSPACE, &xprt->sock->flags))
+ else if (test_bit(SOCK_NOSPACE, &sock->flags))
xprt_wait_for_buffer_space(task);

spin_unlock_bh(&xprt->transport_lock);
@@ -344,8 +356,10 @@ static int xs_udp_send_request(struct rp
req->rq_svec->iov_len);

req->rq_xtime = jiffies;
- status = xs_sendpages(xprt->sock, (struct sockaddr *) &xprt->addr,
- xprt->addrlen, xdr, req->rq_bytes_sent);
+ status = xs_sendpages(xs_private_data(xprt)->sock,
+ (struct sockaddr *) &xprt->addr,
+ xprt->addrlen, xdr,
+ req->rq_bytes_sent);

dprintk("RPC: xs_udp_send_request(%u) = %d\n",
xdr->len - req->rq_bytes_sent, status);
@@ -415,8 +429,8 @@ static int xs_tcp_send_request(struct rp
* called sendmsg(). */
while (1) {
req->rq_xtime = jiffies;
- status = xs_sendpages(xprt->sock, NULL, 0, xdr,
- req->rq_bytes_sent);
+ status = xs_sendpages(xs_private_data(xprt)->sock,
+ NULL, 0, xdr, req->rq_bytes_sent);

dprintk("RPC: xs_tcp_send_request(%u) = %d\n",
xdr->len - req->rq_bytes_sent, status);
@@ -494,8 +508,9 @@ out_release:
*/
static void xs_close(struct rpc_xprt *xprt)
{
- struct socket *sock = xprt->sock;
- struct sock *sk = xprt->inet;
+ struct xs_xprt *private = xs_private_data(xprt);
+ struct socket *sock = private->sock;
+ struct sock *sk = private->inet;

if (!sk)
goto clear_close_wait;
@@ -503,8 +518,8 @@ static void xs_close(struct rpc_xprt *xp
dprintk("RPC: xs_close xprt %p\n", xprt);

write_lock_bh(&sk->sk_callback_lock);
- xprt->inet = NULL;
- xprt->sock = NULL;
+ private->inet = NULL;
+ private->sock = NULL;

sk->sk_user_data = NULL;
sk->sk_data_ready = xprt->old_data_ready;
@@ -540,11 +555,6 @@ static void xs_destroy(struct rpc_xprt *
kfree(xprt);
}

-static inline struct rpc_xprt *xprt_from_sock(struct sock *sk)
-{
- return (struct rpc_xprt *) sk->sk_user_data;
-}
-
/**
* xs_udp_data_ready - "data ready" callback for UDP sockets
* @sk: socket with data to read
@@ -961,7 +971,8 @@ static void xs_tcp_write_space(struct so

static void xs_udp_do_set_buffer_size(struct rpc_xprt *xprt)
{
- struct sock *sk = xprt->inet;
+ struct xs_xprt *private = xs_private_data(xprt);
+ struct sock *sk = private->inet;

if (xprt->rcvsize) {
sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
@@ -1077,7 +1088,8 @@ static int xs_bindresvport(struct rpc_xp
static void xs_udp_connect_worker(void *args)
{
struct rpc_xprt *xprt = (struct rpc_xprt *) args;
- struct socket *sock = xprt->sock;
+ struct xs_xprt *private = xs_private_data(xprt);
+ struct socket *sock = private->sock;
int err, status = -EIO;

if (xprt->shutdown || !xprt_bound(xprt))
@@ -1099,7 +1111,7 @@ static void xs_udp_connect_worker(void *
dprintk("RPC: worker connecting xprt %p to address: %s\n",
xprt, xs_print_peer_address(xprt, RPC_DISPLAY_ALL));

- if (!xprt->inet) {
+ if (!private->inet) {
struct sock *sk = sock->sk;

write_lock_bh(&sk->sk_callback_lock);
@@ -1116,8 +1128,8 @@ static void xs_udp_connect_worker(void *
xprt_set_connected(xprt);

/* Reset to new socket */
- xprt->sock = sock;
- xprt->inet = sk;
+ private->sock = sock;
+ private->inet = sk;

write_unlock_bh(&sk->sk_callback_lock);
}
@@ -1135,7 +1147,7 @@ out:
static void xs_tcp_reuse_connection(struct rpc_xprt *xprt)
{
int result;
- struct socket *sock = xprt->sock;
+ struct socket *sock = xs_private_data(xprt)->sock;
struct sockaddr any;

dprintk("RPC: disconnecting xprt %p to reuse port\n", xprt);
@@ -1161,13 +1173,14 @@ static void xs_tcp_reuse_connection(stru
static void xs_tcp_connect_worker(void *args)
{
struct rpc_xprt *xprt = (struct rpc_xprt *)args;
- struct socket *sock = xprt->sock;
+ struct xs_xprt *private = xs_private_data(xprt);
+ struct socket *sock = private->sock;
int err, status = -EIO;

if (xprt->shutdown || !xprt_bound(xprt))
goto out;

- if (!xprt->sock) {
+ if (!private->sock) {
/* start from scratch */
if ((err = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock)) < 0) {
dprintk("RPC: can't create TCP transport socket (%d).\n", -err);
@@ -1185,7 +1198,7 @@ static void xs_tcp_connect_worker(void *
dprintk("RPC: worker connecting xprt %p to address: %s\n",
xprt, xs_print_peer_address(xprt, RPC_DISPLAY_ALL));

- if (!xprt->inet) {
+ if (!private->inet) {
struct sock *sk = sock->sk;

write_lock_bh(&sk->sk_callback_lock);
@@ -1208,8 +1221,8 @@ static void xs_tcp_connect_worker(void *
xprt_clear_connected(xprt);

/* Reset to new socket */
- xprt->sock = sock;
- xprt->inet = sk;
+ private->sock = sock;
+ private->inet = sk;

write_unlock_bh(&sk->sk_callback_lock);
}
@@ -1258,11 +1271,12 @@ out_clear:
static void xs_connect(struct rpc_task *task)
{
struct rpc_xprt *xprt = task->tk_xprt;
+ struct xs_xprt *private = xs_private_data(xprt);

if (xprt_test_and_set_connecting(xprt))
return;

- if (xprt->sock != NULL) {
+ if (private->sock != NULL) {
dprintk("RPC: xs_connect delayed xprt %p for %lu seconds\n",
xprt, xprt->reestablish_timeout / HZ);
schedule_delayed_work(&xprt->connect_worker,

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

2006-10-18 21:22:33

by Trond Myklebust

[permalink] [raw]
Subject: Re: [PATCH 01/10] SUNRPC: minor optimization of "xid" field in rpc_xprt

On Tue, 2006-10-17 at 14:44 -0400, Chuck Lever wrote:
> Move the xid field in the rpc_xprt structure to be in the same cache line
> as the reserve_lock, since these are used at the same time.

Applied.

Thanks
Trond


-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

2006-10-18 21:29:38

by Trond Myklebust

[permalink] [raw]
Subject: Re: [PATCH 02/10] SUNRPC: Make the transport-specific setup routine allocate rpc_xprt

On Tue, 2006-10-17 at 14:44 -0400, Chuck Lever wrote:
> Change the location where the rpc_xprt structure is allocated so each
> transport implementation can allocate a private area from the same
> chunk of memory.
>
> Note also that xprt->ops->destroy, rather than xprt_destroy, is now
> responsible for freeing rpc_xprt when the transport is destroyed.

Applied

Thanks
Trond


-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

2006-10-18 21:32:53

by Trond Myklebust

[permalink] [raw]
Subject: Re: [PATCH 10/10] SUNRPC: skb_read_bits is the same as xs_tcp_copy_data

On Tue, 2006-10-17 at 14:44 -0400, Chuck Lever wrote:
> Clean-up: eliminate xs_tcp_copy_data -- it's exactly the same logic as the
> common routine skb_read_bits. The UDP and TCP socket read code now share
> the same routine for copying data into an xdr_buf.
>
> Also, rename skb_read_bits() since it is now a public function, and rename
> skb_read_and_csum_bits() to be consistent.

This cleanup doesn't appear to depend directly on anything in the
previous 9 patches, but I can't apply it due to the 'private' code
changes.



-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

2006-10-18 21:34:55

by Chuck Lever

[permalink] [raw]
Subject: Re: [PATCH 10/10] SUNRPC: skb_read_bits is the same as xs_tcp_copy_data

On 10/18/06, Trond Myklebust <[email protected]> wrote:
> On Tue, 2006-10-17 at 14:44 -0400, Chuck Lever wrote:
> > Clean-up: eliminate xs_tcp_copy_data -- it's exactly the same logic as the
> > common routine skb_read_bits. The UDP and TCP socket read code now share
> > the same routine for copying data into an xdr_buf.
> >
> > Also, rename skb_read_bits() since it is now a public function, and rename
> > skb_read_and_csum_bits() to be consistent.
>
> This cleanup doesn't appear to depend directly on anything in the
> previous 9 patches, but I can't apply it due to the 'private' code
> changes.

I will resend 3 through 10 after making the changes you suggested.

--
"We who cut mere stones must always be envisioning cathedrals"
-- Quarry worker's creed

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs