diff options
author | Tom Tucker <tom@opengridcomputing.com> | 2007-12-30 22:07:53 -0500 |
---|---|---|
committer | J. Bruce Fields <bfields@citi.umich.edu> | 2008-02-01 16:42:11 -0500 |
commit | 7a18208383ab3f3ce4a1f4e0536acc9372523d81 (patch) | |
tree | 851a1cc29d753297c2e7cf4cb4a95c4af7868427 /net | |
parent | bb5cf160b282644c4491afbf76fbc66f5dc35030 (diff) |
svc: Make close transport independent
Move sk_list and sk_ready to svc_xprt. This involves close because these
lists are walked by svcs when closing all their transports. So I combined
the moving of these lists to svc_xprt with making close transport independent.
The svc_force_sock_close has been changed to svc_close_all and takes a list
as an argument. This removes some svc internals knowledge from the svcs.
This code races with module removal and transport addition.
Thanks to Simon Holm Thøgersen for a compile fix.
Signed-off-by: Tom Tucker <tom@opengridcomputing.com>
Acked-by: Neil Brown <neilb@suse.de>
Reviewed-by: Chuck Lever <chuck.lever@oracle.com>
Reviewed-by: Greg Banks <gnb@sgi.com>
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Cc: Simon Holm Thøgersen <odie@cs.aau.dk>
Diffstat (limited to 'net')
-rw-r--r-- | net/sunrpc/svc.c | 9 | ||||
-rw-r--r-- | net/sunrpc/svc_xprt.c | 2 | ||||
-rw-r--r-- | net/sunrpc/svcsock.c | 104 |
3 files changed, 54 insertions, 61 deletions
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index 8281a0402652..a5eb2d6b14ae 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c | |||
@@ -459,9 +459,6 @@ svc_create_pooled(struct svc_program *prog, unsigned int bufsize, | |||
459 | void | 459 | void |
460 | svc_destroy(struct svc_serv *serv) | 460 | svc_destroy(struct svc_serv *serv) |
461 | { | 461 | { |
462 | struct svc_sock *svsk; | ||
463 | struct svc_sock *tmp; | ||
464 | |||
465 | dprintk("svc: svc_destroy(%s, %d)\n", | 462 | dprintk("svc: svc_destroy(%s, %d)\n", |
466 | serv->sv_program->pg_name, | 463 | serv->sv_program->pg_name, |
467 | serv->sv_nrthreads); | 464 | serv->sv_nrthreads); |
@@ -476,14 +473,12 @@ svc_destroy(struct svc_serv *serv) | |||
476 | 473 | ||
477 | del_timer_sync(&serv->sv_temptimer); | 474 | del_timer_sync(&serv->sv_temptimer); |
478 | 475 | ||
479 | list_for_each_entry_safe(svsk, tmp, &serv->sv_tempsocks, sk_list) | 476 | svc_close_all(&serv->sv_tempsocks); |
480 | svc_force_close_socket(svsk); | ||
481 | 477 | ||
482 | if (serv->sv_shutdown) | 478 | if (serv->sv_shutdown) |
483 | serv->sv_shutdown(serv); | 479 | serv->sv_shutdown(serv); |
484 | 480 | ||
485 | list_for_each_entry_safe(svsk, tmp, &serv->sv_permsocks, sk_list) | 481 | svc_close_all(&serv->sv_permsocks); |
486 | svc_force_close_socket(svsk); | ||
487 | 482 | ||
488 | BUG_ON(!list_empty(&serv->sv_permsocks)); | 483 | BUG_ON(!list_empty(&serv->sv_permsocks)); |
489 | BUG_ON(!list_empty(&serv->sv_tempsocks)); | 484 | BUG_ON(!list_empty(&serv->sv_tempsocks)); |
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index ea17b533db74..95186b548099 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c | |||
@@ -97,6 +97,8 @@ void svc_xprt_init(struct svc_xprt_class *xcl, struct svc_xprt *xprt, | |||
97 | xprt->xpt_ops = xcl->xcl_ops; | 97 | xprt->xpt_ops = xcl->xcl_ops; |
98 | kref_init(&xprt->xpt_ref); | 98 | kref_init(&xprt->xpt_ref); |
99 | xprt->xpt_server = serv; | 99 | xprt->xpt_server = serv; |
100 | INIT_LIST_HEAD(&xprt->xpt_list); | ||
101 | INIT_LIST_HEAD(&xprt->xpt_ready); | ||
100 | } | 102 | } |
101 | EXPORT_SYMBOL_GPL(svc_xprt_init); | 103 | EXPORT_SYMBOL_GPL(svc_xprt_init); |
102 | 104 | ||
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index f86538e1dec6..6f63a5ca6a91 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c | |||
@@ -81,11 +81,11 @@ | |||
81 | 81 | ||
82 | static struct svc_sock *svc_setup_socket(struct svc_serv *, struct socket *, | 82 | static struct svc_sock *svc_setup_socket(struct svc_serv *, struct socket *, |
83 | int *errp, int flags); | 83 | int *errp, int flags); |
84 | static void svc_delete_socket(struct svc_sock *svsk); | 84 | static void svc_delete_xprt(struct svc_xprt *xprt); |
85 | static void svc_udp_data_ready(struct sock *, int); | 85 | static void svc_udp_data_ready(struct sock *, int); |
86 | static int svc_udp_recvfrom(struct svc_rqst *); | 86 | static int svc_udp_recvfrom(struct svc_rqst *); |
87 | static int svc_udp_sendto(struct svc_rqst *); | 87 | static int svc_udp_sendto(struct svc_rqst *); |
88 | static void svc_close_socket(struct svc_sock *svsk); | 88 | static void svc_close_xprt(struct svc_xprt *xprt); |
89 | static void svc_sock_detach(struct svc_xprt *); | 89 | static void svc_sock_detach(struct svc_xprt *); |
90 | static void svc_sock_free(struct svc_xprt *); | 90 | static void svc_sock_free(struct svc_xprt *); |
91 | 91 | ||
@@ -293,7 +293,7 @@ svc_sock_enqueue(struct svc_sock *svsk) | |||
293 | wake_up(&rqstp->rq_wait); | 293 | wake_up(&rqstp->rq_wait); |
294 | } else { | 294 | } else { |
295 | dprintk("svc: socket %p put into queue\n", svsk->sk_sk); | 295 | dprintk("svc: socket %p put into queue\n", svsk->sk_sk); |
296 | list_add_tail(&svsk->sk_ready, &pool->sp_sockets); | 296 | list_add_tail(&svsk->sk_xprt.xpt_ready, &pool->sp_sockets); |
297 | BUG_ON(svsk->sk_xprt.xpt_pool != pool); | 297 | BUG_ON(svsk->sk_xprt.xpt_pool != pool); |
298 | } | 298 | } |
299 | 299 | ||
@@ -313,8 +313,8 @@ svc_sock_dequeue(struct svc_pool *pool) | |||
313 | return NULL; | 313 | return NULL; |
314 | 314 | ||
315 | svsk = list_entry(pool->sp_sockets.next, | 315 | svsk = list_entry(pool->sp_sockets.next, |
316 | struct svc_sock, sk_ready); | 316 | struct svc_sock, sk_xprt.xpt_ready); |
317 | list_del_init(&svsk->sk_ready); | 317 | list_del_init(&svsk->sk_xprt.xpt_ready); |
318 | 318 | ||
319 | dprintk("svc: socket %p dequeued, inuse=%d\n", | 319 | dprintk("svc: socket %p dequeued, inuse=%d\n", |
320 | svsk->sk_sk, atomic_read(&svsk->sk_xprt.xpt_ref.refcount)); | 320 | svsk->sk_sk, atomic_read(&svsk->sk_xprt.xpt_ref.refcount)); |
@@ -572,7 +572,7 @@ svc_sock_names(char *buf, struct svc_serv *serv, char *toclose) | |||
572 | if (!serv) | 572 | if (!serv) |
573 | return 0; | 573 | return 0; |
574 | spin_lock_bh(&serv->sv_lock); | 574 | spin_lock_bh(&serv->sv_lock); |
575 | list_for_each_entry(svsk, &serv->sv_permsocks, sk_list) { | 575 | list_for_each_entry(svsk, &serv->sv_permsocks, sk_xprt.xpt_list) { |
576 | int onelen = one_sock_name(buf+len, svsk); | 576 | int onelen = one_sock_name(buf+len, svsk); |
577 | if (toclose && strcmp(toclose, buf+len) == 0) | 577 | if (toclose && strcmp(toclose, buf+len) == 0) |
578 | closesk = svsk; | 578 | closesk = svsk; |
@@ -584,7 +584,7 @@ svc_sock_names(char *buf, struct svc_serv *serv, char *toclose) | |||
584 | /* Should unregister with portmap, but you cannot | 584 | /* Should unregister with portmap, but you cannot |
585 | * unregister just one protocol... | 585 | * unregister just one protocol... |
586 | */ | 586 | */ |
587 | svc_close_socket(closesk); | 587 | svc_close_xprt(&closesk->sk_xprt); |
588 | else if (toclose) | 588 | else if (toclose) |
589 | return -ENOENT; | 589 | return -ENOENT; |
590 | return len; | 590 | return len; |
@@ -1427,12 +1427,12 @@ svc_sock_update_bufs(struct svc_serv *serv) | |||
1427 | spin_lock_bh(&serv->sv_lock); | 1427 | spin_lock_bh(&serv->sv_lock); |
1428 | list_for_each(le, &serv->sv_permsocks) { | 1428 | list_for_each(le, &serv->sv_permsocks) { |
1429 | struct svc_sock *svsk = | 1429 | struct svc_sock *svsk = |
1430 | list_entry(le, struct svc_sock, sk_list); | 1430 | list_entry(le, struct svc_sock, sk_xprt.xpt_list); |
1431 | set_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags); | 1431 | set_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags); |
1432 | } | 1432 | } |
1433 | list_for_each(le, &serv->sv_tempsocks) { | 1433 | list_for_each(le, &serv->sv_tempsocks) { |
1434 | struct svc_sock *svsk = | 1434 | struct svc_sock *svsk = |
1435 | list_entry(le, struct svc_sock, sk_list); | 1435 | list_entry(le, struct svc_sock, sk_xprt.xpt_list); |
1436 | set_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags); | 1436 | set_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags); |
1437 | } | 1437 | } |
1438 | spin_unlock_bh(&serv->sv_lock); | 1438 | spin_unlock_bh(&serv->sv_lock); |
@@ -1469,7 +1469,7 @@ static void svc_check_conn_limits(struct svc_serv *serv) | |||
1469 | */ | 1469 | */ |
1470 | svsk = list_entry(serv->sv_tempsocks.prev, | 1470 | svsk = list_entry(serv->sv_tempsocks.prev, |
1471 | struct svc_sock, | 1471 | struct svc_sock, |
1472 | sk_list); | 1472 | sk_xprt.xpt_list); |
1473 | set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags); | 1473 | set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags); |
1474 | svc_xprt_get(&svsk->sk_xprt); | 1474 | svc_xprt_get(&svsk->sk_xprt); |
1475 | } | 1475 | } |
@@ -1576,7 +1576,7 @@ svc_recv(struct svc_rqst *rqstp, long timeout) | |||
1576 | len = 0; | 1576 | len = 0; |
1577 | if (test_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags)) { | 1577 | if (test_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags)) { |
1578 | dprintk("svc_recv: found XPT_CLOSE\n"); | 1578 | dprintk("svc_recv: found XPT_CLOSE\n"); |
1579 | svc_delete_socket(svsk); | 1579 | svc_delete_xprt(&svsk->sk_xprt); |
1580 | } else if (test_bit(XPT_LISTENER, &svsk->sk_xprt.xpt_flags)) { | 1580 | } else if (test_bit(XPT_LISTENER, &svsk->sk_xprt.xpt_flags)) { |
1581 | struct svc_xprt *newxpt; | 1581 | struct svc_xprt *newxpt; |
1582 | newxpt = svsk->sk_xprt.xpt_ops->xpo_accept(&svsk->sk_xprt); | 1582 | newxpt = svsk->sk_xprt.xpt_ops->xpo_accept(&svsk->sk_xprt); |
@@ -1685,7 +1685,7 @@ svc_age_temp_sockets(unsigned long closure) | |||
1685 | } | 1685 | } |
1686 | 1686 | ||
1687 | list_for_each_safe(le, next, &serv->sv_tempsocks) { | 1687 | list_for_each_safe(le, next, &serv->sv_tempsocks) { |
1688 | svsk = list_entry(le, struct svc_sock, sk_list); | 1688 | svsk = list_entry(le, struct svc_sock, sk_xprt.xpt_list); |
1689 | 1689 | ||
1690 | if (!test_and_set_bit(XPT_OLD, &svsk->sk_xprt.xpt_flags)) | 1690 | if (!test_and_set_bit(XPT_OLD, &svsk->sk_xprt.xpt_flags)) |
1691 | continue; | 1691 | continue; |
@@ -1701,9 +1701,9 @@ svc_age_temp_sockets(unsigned long closure) | |||
1701 | 1701 | ||
1702 | while (!list_empty(&to_be_aged)) { | 1702 | while (!list_empty(&to_be_aged)) { |
1703 | le = to_be_aged.next; | 1703 | le = to_be_aged.next; |
1704 | /* fiddling the sk_list node is safe 'cos we're XPT_DETACHED */ | 1704 | /* fiddling the sk_xprt.xpt_list node is safe 'cos we're XPT_DETACHED */ |
1705 | list_del_init(le); | 1705 | list_del_init(le); |
1706 | svsk = list_entry(le, struct svc_sock, sk_list); | 1706 | svsk = list_entry(le, struct svc_sock, sk_xprt.xpt_list); |
1707 | 1707 | ||
1708 | dprintk("queuing svsk %p for closing, %lu seconds old\n", | 1708 | dprintk("queuing svsk %p for closing, %lu seconds old\n", |
1709 | svsk, get_seconds() - svsk->sk_lastrecv); | 1709 | svsk, get_seconds() - svsk->sk_lastrecv); |
@@ -1757,7 +1757,6 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv, | |||
1757 | svsk->sk_lastrecv = get_seconds(); | 1757 | svsk->sk_lastrecv = get_seconds(); |
1758 | spin_lock_init(&svsk->sk_lock); | 1758 | spin_lock_init(&svsk->sk_lock); |
1759 | INIT_LIST_HEAD(&svsk->sk_deferred); | 1759 | INIT_LIST_HEAD(&svsk->sk_deferred); |
1760 | INIT_LIST_HEAD(&svsk->sk_ready); | ||
1761 | mutex_init(&svsk->sk_mutex); | 1760 | mutex_init(&svsk->sk_mutex); |
1762 | 1761 | ||
1763 | /* Initialize the socket */ | 1762 | /* Initialize the socket */ |
@@ -1769,7 +1768,7 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv, | |||
1769 | spin_lock_bh(&serv->sv_lock); | 1768 | spin_lock_bh(&serv->sv_lock); |
1770 | if (is_temporary) { | 1769 | if (is_temporary) { |
1771 | set_bit(XPT_TEMP, &svsk->sk_xprt.xpt_flags); | 1770 | set_bit(XPT_TEMP, &svsk->sk_xprt.xpt_flags); |
1772 | list_add(&svsk->sk_list, &serv->sv_tempsocks); | 1771 | list_add(&svsk->sk_xprt.xpt_list, &serv->sv_tempsocks); |
1773 | serv->sv_tmpcnt++; | 1772 | serv->sv_tmpcnt++; |
1774 | if (serv->sv_temptimer.function == NULL) { | 1773 | if (serv->sv_temptimer.function == NULL) { |
1775 | /* setup timer to age temp sockets */ | 1774 | /* setup timer to age temp sockets */ |
@@ -1780,7 +1779,7 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv, | |||
1780 | } | 1779 | } |
1781 | } else { | 1780 | } else { |
1782 | clear_bit(XPT_TEMP, &svsk->sk_xprt.xpt_flags); | 1781 | clear_bit(XPT_TEMP, &svsk->sk_xprt.xpt_flags); |
1783 | list_add(&svsk->sk_list, &serv->sv_permsocks); | 1782 | list_add(&svsk->sk_xprt.xpt_list, &serv->sv_permsocks); |
1784 | } | 1783 | } |
1785 | spin_unlock_bh(&serv->sv_lock); | 1784 | spin_unlock_bh(&serv->sv_lock); |
1786 | 1785 | ||
@@ -1912,66 +1911,63 @@ static void svc_sock_free(struct svc_xprt *xprt) | |||
1912 | } | 1911 | } |
1913 | 1912 | ||
1914 | /* | 1913 | /* |
1915 | * Remove a dead socket | 1914 | * Remove a dead transport |
1916 | */ | 1915 | */ |
1917 | static void | 1916 | static void svc_delete_xprt(struct svc_xprt *xprt) |
1918 | svc_delete_socket(struct svc_sock *svsk) | ||
1919 | { | 1917 | { |
1920 | struct svc_serv *serv; | 1918 | struct svc_serv *serv = xprt->xpt_server; |
1921 | struct sock *sk; | ||
1922 | |||
1923 | dprintk("svc: svc_delete_socket(%p)\n", svsk); | ||
1924 | |||
1925 | serv = svsk->sk_xprt.xpt_server; | ||
1926 | sk = svsk->sk_sk; | ||
1927 | 1919 | ||
1928 | svsk->sk_xprt.xpt_ops->xpo_detach(&svsk->sk_xprt); | 1920 | dprintk("svc: svc_delete_xprt(%p)\n", xprt); |
1921 | xprt->xpt_ops->xpo_detach(xprt); | ||
1929 | 1922 | ||
1930 | spin_lock_bh(&serv->sv_lock); | 1923 | spin_lock_bh(&serv->sv_lock); |
1931 | 1924 | if (!test_and_set_bit(XPT_DETACHED, &xprt->xpt_flags)) | |
1932 | if (!test_and_set_bit(XPT_DETACHED, &svsk->sk_xprt.xpt_flags)) | 1925 | list_del_init(&xprt->xpt_list); |
1933 | list_del_init(&svsk->sk_list); | ||
1934 | /* | 1926 | /* |
1935 | * We used to delete the svc_sock from whichever list | 1927 | * We used to delete the transport from whichever list |
1936 | * it's sk_ready node was on, but we don't actually | 1928 | * it's sk_xprt.xpt_ready node was on, but we don't actually |
1937 | * need to. This is because the only time we're called | 1929 | * need to. This is because the only time we're called |
1938 | * while still attached to a queue, the queue itself | 1930 | * while still attached to a queue, the queue itself |
1939 | * is about to be destroyed (in svc_destroy). | 1931 | * is about to be destroyed (in svc_destroy). |
1940 | */ | 1932 | */ |
1941 | if (!test_and_set_bit(XPT_DEAD, &svsk->sk_xprt.xpt_flags)) { | 1933 | if (!test_and_set_bit(XPT_DEAD, &xprt->xpt_flags)) { |
1942 | BUG_ON(atomic_read(&svsk->sk_xprt.xpt_ref.refcount) < 2); | 1934 | BUG_ON(atomic_read(&xprt->xpt_ref.refcount) < 2); |
1943 | if (test_bit(XPT_TEMP, &svsk->sk_xprt.xpt_flags)) | 1935 | if (test_bit(XPT_TEMP, &xprt->xpt_flags)) |
1944 | serv->sv_tmpcnt--; | 1936 | serv->sv_tmpcnt--; |
1945 | svc_xprt_put(&svsk->sk_xprt); | 1937 | svc_xprt_put(xprt); |
1946 | } | 1938 | } |
1947 | |||
1948 | spin_unlock_bh(&serv->sv_lock); | 1939 | spin_unlock_bh(&serv->sv_lock); |
1949 | } | 1940 | } |
1950 | 1941 | ||
1951 | static void svc_close_socket(struct svc_sock *svsk) | 1942 | static void svc_close_xprt(struct svc_xprt *xprt) |
1952 | { | 1943 | { |
1953 | set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags); | 1944 | set_bit(XPT_CLOSE, &xprt->xpt_flags); |
1954 | if (test_and_set_bit(XPT_BUSY, &svsk->sk_xprt.xpt_flags)) | 1945 | if (test_and_set_bit(XPT_BUSY, &xprt->xpt_flags)) |
1955 | /* someone else will have to effect the close */ | 1946 | /* someone else will have to effect the close */ |
1956 | return; | 1947 | return; |
1957 | 1948 | ||
1958 | svc_xprt_get(&svsk->sk_xprt); | 1949 | svc_xprt_get(xprt); |
1959 | svc_delete_socket(svsk); | 1950 | svc_delete_xprt(xprt); |
1960 | clear_bit(XPT_BUSY, &svsk->sk_xprt.xpt_flags); | 1951 | clear_bit(XPT_BUSY, &xprt->xpt_flags); |
1961 | svc_xprt_put(&svsk->sk_xprt); | 1952 | svc_xprt_put(xprt); |
1962 | } | 1953 | } |
1963 | 1954 | ||
1964 | void svc_force_close_socket(struct svc_sock *svsk) | 1955 | void svc_close_all(struct list_head *xprt_list) |
1965 | { | 1956 | { |
1966 | set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags); | 1957 | struct svc_xprt *xprt; |
1967 | if (test_bit(XPT_BUSY, &svsk->sk_xprt.xpt_flags)) { | 1958 | struct svc_xprt *tmp; |
1968 | /* Waiting to be processed, but no threads left, | 1959 | |
1969 | * So just remove it from the waiting list | 1960 | list_for_each_entry_safe(xprt, tmp, xprt_list, xpt_list) { |
1970 | */ | 1961 | set_bit(XPT_CLOSE, &xprt->xpt_flags); |
1971 | list_del_init(&svsk->sk_ready); | 1962 | if (test_bit(XPT_BUSY, &xprt->xpt_flags)) { |
1972 | clear_bit(XPT_BUSY, &svsk->sk_xprt.xpt_flags); | 1963 | /* Waiting to be processed, but no threads left, |
1964 | * So just remove it from the waiting list | ||
1965 | */ | ||
1966 | list_del_init(&xprt->xpt_ready); | ||
1967 | clear_bit(XPT_BUSY, &xprt->xpt_flags); | ||
1968 | } | ||
1969 | svc_close_xprt(xprt); | ||
1973 | } | 1970 | } |
1974 | svc_close_socket(svsk); | ||
1975 | } | 1971 | } |
1976 | 1972 | ||
1977 | /* | 1973 | /* |