Commit 7a18208383ab3f3ce4a1f4e0536acc9372523d81
Committed by
J. Bruce Fields
1 parent
bb5cf160b2
Exists in
master
and in
7 other branches
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>
Showing 7 changed files with 62 additions and 69 deletions Side-by-side Diff
fs/lockd/svc.c
... | ... | @@ -221,10 +221,10 @@ |
221 | 221 | |
222 | 222 | static int find_xprt(struct svc_serv *serv, char *proto) |
223 | 223 | { |
224 | - struct svc_sock *svsk; | |
224 | + struct svc_xprt *xprt; | |
225 | 225 | int found = 0; |
226 | - list_for_each_entry(svsk, &serv->sv_permsocks, sk_list) | |
227 | - if (strcmp(svsk->sk_xprt.xpt_class->xcl_name, proto) == 0) { | |
226 | + list_for_each_entry(xprt, &serv->sv_permsocks, xpt_list) | |
227 | + if (strcmp(xprt->xpt_class->xcl_name, proto) == 0) { | |
228 | 228 | found = 1; |
229 | 229 | break; |
230 | 230 | } |
fs/nfsd/nfssvc.c
... | ... | @@ -155,8 +155,8 @@ |
155 | 155 | static void nfsd_last_thread(struct svc_serv *serv) |
156 | 156 | { |
157 | 157 | /* When last nfsd thread exits we need to do some clean-up */ |
158 | - struct svc_sock *svsk; | |
159 | - list_for_each_entry(svsk, &serv->sv_permsocks, sk_list) | |
158 | + struct svc_xprt *xprt; | |
159 | + list_for_each_entry(xprt, &serv->sv_permsocks, xpt_list) | |
160 | 160 | lockd_down(); |
161 | 161 | nfsd_serv = NULL; |
162 | 162 | nfsd_racache_shutdown(); |
include/linux/sunrpc/svc_xprt.h
... | ... | @@ -36,6 +36,8 @@ |
36 | 36 | struct svc_xprt_class *xpt_class; |
37 | 37 | struct svc_xprt_ops *xpt_ops; |
38 | 38 | struct kref xpt_ref; |
39 | + struct list_head xpt_list; | |
40 | + struct list_head xpt_ready; | |
39 | 41 | unsigned long xpt_flags; |
40 | 42 | #define XPT_BUSY 0 /* enqueued/receiving */ |
41 | 43 | #define XPT_CONN 1 /* conn pending */ |
include/linux/sunrpc/svcsock.h
... | ... | @@ -17,8 +17,6 @@ |
17 | 17 | */ |
18 | 18 | struct svc_sock { |
19 | 19 | struct svc_xprt sk_xprt; |
20 | - struct list_head sk_ready; /* list of ready sockets */ | |
21 | - struct list_head sk_list; /* list of all sockets */ | |
22 | 20 | struct socket * sk_sock; /* berkeley socket layer */ |
23 | 21 | struct sock * sk_sk; /* INET layer */ |
24 | 22 | |
... | ... | @@ -51,7 +49,7 @@ |
51 | 49 | /* |
52 | 50 | * Function prototypes. |
53 | 51 | */ |
54 | -void svc_force_close_socket(struct svc_sock *); | |
52 | +void svc_close_all(struct list_head *); | |
55 | 53 | int svc_recv(struct svc_rqst *, long); |
56 | 54 | int svc_send(struct svc_rqst *); |
57 | 55 | void svc_drop(struct svc_rqst *); |
net/sunrpc/svc.c
... | ... | @@ -459,9 +459,6 @@ |
459 | 459 | void |
460 | 460 | svc_destroy(struct svc_serv *serv) |
461 | 461 | { |
462 | - struct svc_sock *svsk; | |
463 | - struct svc_sock *tmp; | |
464 | - | |
465 | 462 | dprintk("svc: svc_destroy(%s, %d)\n", |
466 | 463 | serv->sv_program->pg_name, |
467 | 464 | serv->sv_nrthreads); |
468 | 465 | |
... | ... | @@ -476,14 +473,12 @@ |
476 | 473 | |
477 | 474 | del_timer_sync(&serv->sv_temptimer); |
478 | 475 | |
479 | - list_for_each_entry_safe(svsk, tmp, &serv->sv_tempsocks, sk_list) | |
480 | - svc_force_close_socket(svsk); | |
476 | + svc_close_all(&serv->sv_tempsocks); | |
481 | 477 | |
482 | 478 | if (serv->sv_shutdown) |
483 | 479 | serv->sv_shutdown(serv); |
484 | 480 | |
485 | - list_for_each_entry_safe(svsk, tmp, &serv->sv_permsocks, sk_list) | |
486 | - svc_force_close_socket(svsk); | |
481 | + svc_close_all(&serv->sv_permsocks); | |
487 | 482 | |
488 | 483 | BUG_ON(!list_empty(&serv->sv_permsocks)); |
489 | 484 | BUG_ON(!list_empty(&serv->sv_tempsocks)); |
net/sunrpc/svc_xprt.c
net/sunrpc/svcsock.c
... | ... | @@ -81,11 +81,11 @@ |
81 | 81 | |
82 | 82 | static struct svc_sock *svc_setup_socket(struct svc_serv *, struct socket *, |
83 | 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 | 85 | static void svc_udp_data_ready(struct sock *, int); |
86 | 86 | static int svc_udp_recvfrom(struct svc_rqst *); |
87 | 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 | 89 | static void svc_sock_detach(struct svc_xprt *); |
90 | 90 | static void svc_sock_free(struct svc_xprt *); |
91 | 91 | |
... | ... | @@ -293,7 +293,7 @@ |
293 | 293 | wake_up(&rqstp->rq_wait); |
294 | 294 | } else { |
295 | 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 | 297 | BUG_ON(svsk->sk_xprt.xpt_pool != pool); |
298 | 298 | } |
299 | 299 | |
... | ... | @@ -313,8 +313,8 @@ |
313 | 313 | return NULL; |
314 | 314 | |
315 | 315 | svsk = list_entry(pool->sp_sockets.next, |
316 | - struct svc_sock, sk_ready); | |
317 | - list_del_init(&svsk->sk_ready); | |
316 | + struct svc_sock, sk_xprt.xpt_ready); | |
317 | + list_del_init(&svsk->sk_xprt.xpt_ready); | |
318 | 318 | |
319 | 319 | dprintk("svc: socket %p dequeued, inuse=%d\n", |
320 | 320 | svsk->sk_sk, atomic_read(&svsk->sk_xprt.xpt_ref.refcount)); |
... | ... | @@ -572,7 +572,7 @@ |
572 | 572 | if (!serv) |
573 | 573 | return 0; |
574 | 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 | 576 | int onelen = one_sock_name(buf+len, svsk); |
577 | 577 | if (toclose && strcmp(toclose, buf+len) == 0) |
578 | 578 | closesk = svsk; |
... | ... | @@ -584,7 +584,7 @@ |
584 | 584 | /* Should unregister with portmap, but you cannot |
585 | 585 | * unregister just one protocol... |
586 | 586 | */ |
587 | - svc_close_socket(closesk); | |
587 | + svc_close_xprt(&closesk->sk_xprt); | |
588 | 588 | else if (toclose) |
589 | 589 | return -ENOENT; |
590 | 590 | return len; |
591 | 591 | |
... | ... | @@ -1427,12 +1427,12 @@ |
1427 | 1427 | spin_lock_bh(&serv->sv_lock); |
1428 | 1428 | list_for_each(le, &serv->sv_permsocks) { |
1429 | 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 | 1431 | set_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags); |
1432 | 1432 | } |
1433 | 1433 | list_for_each(le, &serv->sv_tempsocks) { |
1434 | 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 | 1436 | set_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags); |
1437 | 1437 | } |
1438 | 1438 | spin_unlock_bh(&serv->sv_lock); |
... | ... | @@ -1469,7 +1469,7 @@ |
1469 | 1469 | */ |
1470 | 1470 | svsk = list_entry(serv->sv_tempsocks.prev, |
1471 | 1471 | struct svc_sock, |
1472 | - sk_list); | |
1472 | + sk_xprt.xpt_list); | |
1473 | 1473 | set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags); |
1474 | 1474 | svc_xprt_get(&svsk->sk_xprt); |
1475 | 1475 | } |
... | ... | @@ -1576,7 +1576,7 @@ |
1576 | 1576 | len = 0; |
1577 | 1577 | if (test_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags)) { |
1578 | 1578 | dprintk("svc_recv: found XPT_CLOSE\n"); |
1579 | - svc_delete_socket(svsk); | |
1579 | + svc_delete_xprt(&svsk->sk_xprt); | |
1580 | 1580 | } else if (test_bit(XPT_LISTENER, &svsk->sk_xprt.xpt_flags)) { |
1581 | 1581 | struct svc_xprt *newxpt; |
1582 | 1582 | newxpt = svsk->sk_xprt.xpt_ops->xpo_accept(&svsk->sk_xprt); |
... | ... | @@ -1685,7 +1685,7 @@ |
1685 | 1685 | } |
1686 | 1686 | |
1687 | 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 | 1690 | if (!test_and_set_bit(XPT_OLD, &svsk->sk_xprt.xpt_flags)) |
1691 | 1691 | continue; |
1692 | 1692 | |
... | ... | @@ -1701,9 +1701,9 @@ |
1701 | 1701 | |
1702 | 1702 | while (!list_empty(&to_be_aged)) { |
1703 | 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 | 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 | 1708 | dprintk("queuing svsk %p for closing, %lu seconds old\n", |
1709 | 1709 | svsk, get_seconds() - svsk->sk_lastrecv); |
... | ... | @@ -1757,7 +1757,6 @@ |
1757 | 1757 | svsk->sk_lastrecv = get_seconds(); |
1758 | 1758 | spin_lock_init(&svsk->sk_lock); |
1759 | 1759 | INIT_LIST_HEAD(&svsk->sk_deferred); |
1760 | - INIT_LIST_HEAD(&svsk->sk_ready); | |
1761 | 1760 | mutex_init(&svsk->sk_mutex); |
1762 | 1761 | |
1763 | 1762 | /* Initialize the socket */ |
... | ... | @@ -1769,7 +1768,7 @@ |
1769 | 1768 | spin_lock_bh(&serv->sv_lock); |
1770 | 1769 | if (is_temporary) { |
1771 | 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 | 1772 | serv->sv_tmpcnt++; |
1774 | 1773 | if (serv->sv_temptimer.function == NULL) { |
1775 | 1774 | /* setup timer to age temp sockets */ |
... | ... | @@ -1780,7 +1779,7 @@ |
1780 | 1779 | } |
1781 | 1780 | } else { |
1782 | 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 | 1784 | spin_unlock_bh(&serv->sv_lock); |
1786 | 1785 | |
1787 | 1786 | |
1788 | 1787 | |
1789 | 1788 | |
1790 | 1789 | |
1791 | 1790 | |
1792 | 1791 | |
1793 | 1792 | |
1794 | 1793 | |
1795 | 1794 | |
1796 | 1795 | |
1797 | 1796 | |
1798 | 1797 | |
1799 | 1798 | |
1800 | 1799 | |
1801 | 1800 | |
... | ... | @@ -1912,66 +1911,63 @@ |
1912 | 1911 | } |
1913 | 1912 | |
1914 | 1913 | /* |
1915 | - * Remove a dead socket | |
1914 | + * Remove a dead transport | |
1916 | 1915 | */ |
1917 | -static void | |
1918 | -svc_delete_socket(struct svc_sock *svsk) | |
1916 | +static void svc_delete_xprt(struct svc_xprt *xprt) | |
1919 | 1917 | { |
1920 | - struct svc_serv *serv; | |
1921 | - struct sock *sk; | |
1918 | + struct svc_serv *serv = xprt->xpt_server; | |
1922 | 1919 | |
1923 | - dprintk("svc: svc_delete_socket(%p)\n", svsk); | |
1920 | + dprintk("svc: svc_delete_xprt(%p)\n", xprt); | |
1921 | + xprt->xpt_ops->xpo_detach(xprt); | |
1924 | 1922 | |
1925 | - serv = svsk->sk_xprt.xpt_server; | |
1926 | - sk = svsk->sk_sk; | |
1927 | - | |
1928 | - svsk->sk_xprt.xpt_ops->xpo_detach(&svsk->sk_xprt); | |
1929 | - | |
1930 | 1923 | spin_lock_bh(&serv->sv_lock); |
1931 | - | |
1932 | - if (!test_and_set_bit(XPT_DETACHED, &svsk->sk_xprt.xpt_flags)) | |
1933 | - list_del_init(&svsk->sk_list); | |
1924 | + if (!test_and_set_bit(XPT_DETACHED, &xprt->xpt_flags)) | |
1925 | + list_del_init(&xprt->xpt_list); | |
1934 | 1926 | /* |
1935 | - * We used to delete the svc_sock from whichever list | |
1936 | - * it's sk_ready node was on, but we don't actually | |
1927 | + * We used to delete the transport from whichever list | |
1928 | + * it's sk_xprt.xpt_ready node was on, but we don't actually | |
1937 | 1929 | * need to. This is because the only time we're called |
1938 | 1930 | * while still attached to a queue, the queue itself |
1939 | 1931 | * is about to be destroyed (in svc_destroy). |
1940 | 1932 | */ |
1941 | - if (!test_and_set_bit(XPT_DEAD, &svsk->sk_xprt.xpt_flags)) { | |
1942 | - BUG_ON(atomic_read(&svsk->sk_xprt.xpt_ref.refcount) < 2); | |
1943 | - if (test_bit(XPT_TEMP, &svsk->sk_xprt.xpt_flags)) | |
1933 | + if (!test_and_set_bit(XPT_DEAD, &xprt->xpt_flags)) { | |
1934 | + BUG_ON(atomic_read(&xprt->xpt_ref.refcount) < 2); | |
1935 | + if (test_bit(XPT_TEMP, &xprt->xpt_flags)) | |
1944 | 1936 | serv->sv_tmpcnt--; |
1945 | - svc_xprt_put(&svsk->sk_xprt); | |
1937 | + svc_xprt_put(xprt); | |
1946 | 1938 | } |
1947 | - | |
1948 | 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); | |
1954 | - if (test_and_set_bit(XPT_BUSY, &svsk->sk_xprt.xpt_flags)) | |
1944 | + set_bit(XPT_CLOSE, &xprt->xpt_flags); | |
1945 | + if (test_and_set_bit(XPT_BUSY, &xprt->xpt_flags)) | |
1955 | 1946 | /* someone else will have to effect the close */ |
1956 | 1947 | return; |
1957 | 1948 | |
1958 | - svc_xprt_get(&svsk->sk_xprt); | |
1959 | - svc_delete_socket(svsk); | |
1960 | - clear_bit(XPT_BUSY, &svsk->sk_xprt.xpt_flags); | |
1961 | - svc_xprt_put(&svsk->sk_xprt); | |
1949 | + svc_xprt_get(xprt); | |
1950 | + svc_delete_xprt(xprt); | |
1951 | + clear_bit(XPT_BUSY, &xprt->xpt_flags); | |
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); | |
1967 | - if (test_bit(XPT_BUSY, &svsk->sk_xprt.xpt_flags)) { | |
1968 | - /* Waiting to be processed, but no threads left, | |
1969 | - * So just remove it from the waiting list | |
1970 | - */ | |
1971 | - list_del_init(&svsk->sk_ready); | |
1972 | - clear_bit(XPT_BUSY, &svsk->sk_xprt.xpt_flags); | |
1957 | + struct svc_xprt *xprt; | |
1958 | + struct svc_xprt *tmp; | |
1959 | + | |
1960 | + list_for_each_entry_safe(xprt, tmp, xprt_list, xpt_list) { | |
1961 | + set_bit(XPT_CLOSE, &xprt->xpt_flags); | |
1962 | + if (test_bit(XPT_BUSY, &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 | /* |