aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@hammerspace.com>2019-03-09 12:07:17 -0500
committerTrond Myklebust <trond.myklebust@hammerspace.com>2019-03-10 14:08:19 -0400
commit009a82f6437490c262584d65a14094a818bcb747 (patch)
treeb768ab0b1d4b8a102c556f9b3b6fa1052fef933e
parent03e51d32da995030a16697038232171807eeb0f2 (diff)
SUNRPC: Micro-optimise when the task is known not to be sleeping
In cases where we know the task is not sleeping, try to optimise away the indirect call to task->tk_action() by replacing it with a direct call. Only change tail calls, to allow gcc to perform tail call elimination. Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
-rw-r--r--include/linux/sunrpc/sched.h8
-rw-r--r--net/sunrpc/clnt.c99
2 files changed, 73 insertions, 34 deletions
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
index 52d41d0c1ae1..ec861cd0cfe8 100644
--- a/include/linux/sunrpc/sched.h
+++ b/include/linux/sunrpc/sched.h
@@ -304,4 +304,12 @@ rpc_clnt_swap_deactivate(struct rpc_clnt *clnt)
304} 304}
305#endif /* CONFIG_SUNRPC_SWAP */ 305#endif /* CONFIG_SUNRPC_SWAP */
306 306
307static inline bool
308rpc_task_need_resched(const struct rpc_task *task)
309{
310 if (RPC_IS_QUEUED(task) || task->tk_callback)
311 return true;
312 return false;
313}
314
307#endif /* _LINUX_SUNRPC_SCHED_H_ */ 315#endif /* _LINUX_SUNRPC_SCHED_H_ */
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 67c955d8b21b..498dd6ad5bc5 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -1540,6 +1540,7 @@ call_start(struct rpc_task *task)
1540 clnt->cl_stats->rpccnt++; 1540 clnt->cl_stats->rpccnt++;
1541 task->tk_action = call_reserve; 1541 task->tk_action = call_reserve;
1542 rpc_task_set_transport(task, clnt); 1542 rpc_task_set_transport(task, clnt);
1543 call_reserve(task);
1543} 1544}
1544 1545
1545/* 1546/*
@@ -1553,6 +1554,9 @@ call_reserve(struct rpc_task *task)
1553 task->tk_status = 0; 1554 task->tk_status = 0;
1554 task->tk_action = call_reserveresult; 1555 task->tk_action = call_reserveresult;
1555 xprt_reserve(task); 1556 xprt_reserve(task);
1557 if (rpc_task_need_resched(task))
1558 return;
1559 call_reserveresult(task);
1556} 1560}
1557 1561
1558static void call_retry_reserve(struct rpc_task *task); 1562static void call_retry_reserve(struct rpc_task *task);
@@ -1575,6 +1579,7 @@ call_reserveresult(struct rpc_task *task)
1575 if (status >= 0) { 1579 if (status >= 0) {
1576 if (task->tk_rqstp) { 1580 if (task->tk_rqstp) {
1577 task->tk_action = call_refresh; 1581 task->tk_action = call_refresh;
1582 call_refresh(task);
1578 return; 1583 return;
1579 } 1584 }
1580 1585
@@ -1600,6 +1605,7 @@ call_reserveresult(struct rpc_task *task)
1600 /* fall through */ 1605 /* fall through */
1601 case -EAGAIN: /* woken up; retry */ 1606 case -EAGAIN: /* woken up; retry */
1602 task->tk_action = call_retry_reserve; 1607 task->tk_action = call_retry_reserve;
1608 call_retry_reserve(task);
1603 return; 1609 return;
1604 case -EIO: /* probably a shutdown */ 1610 case -EIO: /* probably a shutdown */
1605 break; 1611 break;
@@ -1622,6 +1628,9 @@ call_retry_reserve(struct rpc_task *task)
1622 task->tk_status = 0; 1628 task->tk_status = 0;
1623 task->tk_action = call_reserveresult; 1629 task->tk_action = call_reserveresult;
1624 xprt_retry_reserve(task); 1630 xprt_retry_reserve(task);
1631 if (rpc_task_need_resched(task))
1632 return;
1633 call_reserveresult(task);
1625} 1634}
1626 1635
1627/* 1636/*
@@ -1636,6 +1645,9 @@ call_refresh(struct rpc_task *task)
1636 task->tk_status = 0; 1645 task->tk_status = 0;
1637 task->tk_client->cl_stats->rpcauthrefresh++; 1646 task->tk_client->cl_stats->rpcauthrefresh++;
1638 rpcauth_refreshcred(task); 1647 rpcauth_refreshcred(task);
1648 if (rpc_task_need_resched(task))
1649 return;
1650 call_refreshresult(task);
1639} 1651}
1640 1652
1641/* 1653/*
@@ -1654,6 +1666,7 @@ call_refreshresult(struct rpc_task *task)
1654 case 0: 1666 case 0:
1655 if (rpcauth_uptodatecred(task)) { 1667 if (rpcauth_uptodatecred(task)) {
1656 task->tk_action = call_allocate; 1668 task->tk_action = call_allocate;
1669 call_allocate(task);
1657 return; 1670 return;
1658 } 1671 }
1659 /* Use rate-limiting and a max number of retries if refresh 1672 /* Use rate-limiting and a max number of retries if refresh
@@ -1672,6 +1685,7 @@ call_refreshresult(struct rpc_task *task)
1672 task->tk_cred_retry--; 1685 task->tk_cred_retry--;
1673 dprintk("RPC: %5u %s: retry refresh creds\n", 1686 dprintk("RPC: %5u %s: retry refresh creds\n",
1674 task->tk_pid, __func__); 1687 task->tk_pid, __func__);
1688 call_refresh(task);
1675 return; 1689 return;
1676 } 1690 }
1677 dprintk("RPC: %5u %s: refresh creds failed with error %d\n", 1691 dprintk("RPC: %5u %s: refresh creds failed with error %d\n",
@@ -1697,8 +1711,10 @@ call_allocate(struct rpc_task *task)
1697 task->tk_status = 0; 1711 task->tk_status = 0;
1698 task->tk_action = call_encode; 1712 task->tk_action = call_encode;
1699 1713
1700 if (req->rq_buffer) 1714 if (req->rq_buffer) {
1715 call_encode(task);
1701 return; 1716 return;
1717 }
1702 1718
1703 if (proc->p_proc != 0) { 1719 if (proc->p_proc != 0) {
1704 BUG_ON(proc->p_arglen == 0); 1720 BUG_ON(proc->p_arglen == 0);
@@ -1719,8 +1735,12 @@ call_allocate(struct rpc_task *task)
1719 1735
1720 status = xprt->ops->buf_alloc(task); 1736 status = xprt->ops->buf_alloc(task);
1721 xprt_inject_disconnect(xprt); 1737 xprt_inject_disconnect(xprt);
1722 if (status == 0) 1738 if (status == 0) {
1739 if (rpc_task_need_resched(task))
1740 return;
1741 call_encode(task);
1723 return; 1742 return;
1743 }
1724 if (status != -ENOMEM) { 1744 if (status != -ENOMEM) {
1725 rpc_exit(task, status); 1745 rpc_exit(task, status);
1726 return; 1746 return;
@@ -1803,12 +1823,8 @@ call_encode(struct rpc_task *task)
1803 xprt_request_enqueue_receive(task); 1823 xprt_request_enqueue_receive(task);
1804 xprt_request_enqueue_transmit(task); 1824 xprt_request_enqueue_transmit(task);
1805out: 1825out:
1806 task->tk_action = call_transmit; 1826 task->tk_action = call_bind;
1807 /* Check that the connection is OK */ 1827 call_bind(task);
1808 if (!xprt_bound(task->tk_xprt))
1809 task->tk_action = call_bind;
1810 else if (!xprt_connected(task->tk_xprt))
1811 task->tk_action = call_connect;
1812} 1828}
1813 1829
1814/* 1830/*
@@ -1842,14 +1858,17 @@ call_bind(struct rpc_task *task)
1842 return; 1858 return;
1843 } 1859 }
1844 1860
1861 if (xprt_bound(xprt)) {
1862 task->tk_action = call_connect;
1863 call_connect(task);
1864 return;
1865 }
1866
1845 dprint_status(task); 1867 dprint_status(task);
1846 1868
1847 task->tk_action = call_connect; 1869 task->tk_action = call_bind_status;
1848 if (!xprt_bound(xprt)) { 1870 task->tk_timeout = xprt->bind_timeout;
1849 task->tk_action = call_bind_status; 1871 xprt->ops->rpcbind(task);
1850 task->tk_timeout = xprt->bind_timeout;
1851 xprt->ops->rpcbind(task);
1852 }
1853} 1872}
1854 1873
1855/* 1874/*
@@ -1869,6 +1888,7 @@ call_bind_status(struct rpc_task *task)
1869 dprint_status(task); 1888 dprint_status(task);
1870 task->tk_status = 0; 1889 task->tk_status = 0;
1871 task->tk_action = call_connect; 1890 task->tk_action = call_connect;
1891 call_connect(task);
1872 return; 1892 return;
1873 } 1893 }
1874 1894
@@ -1949,21 +1969,24 @@ call_connect(struct rpc_task *task)
1949 return; 1969 return;
1950 } 1970 }
1951 1971
1972 if (xprt_connected(xprt)) {
1973 task->tk_action = call_transmit;
1974 call_transmit(task);
1975 return;
1976 }
1977
1952 dprintk("RPC: %5u call_connect xprt %p %s connected\n", 1978 dprintk("RPC: %5u call_connect xprt %p %s connected\n",
1953 task->tk_pid, xprt, 1979 task->tk_pid, xprt,
1954 (xprt_connected(xprt) ? "is" : "is not")); 1980 (xprt_connected(xprt) ? "is" : "is not"));
1955 1981
1956 task->tk_action = call_transmit; 1982 task->tk_action = call_connect_status;
1957 if (!xprt_connected(xprt)) { 1983 if (task->tk_status < 0)
1958 task->tk_action = call_connect_status; 1984 return;
1959 if (task->tk_status < 0) 1985 if (task->tk_flags & RPC_TASK_NOCONNECT) {
1960 return; 1986 rpc_exit(task, -ENOTCONN);
1961 if (task->tk_flags & RPC_TASK_NOCONNECT) { 1987 return;
1962 rpc_exit(task, -ENOTCONN);
1963 return;
1964 }
1965 xprt_connect(task);
1966 } 1988 }
1989 xprt_connect(task);
1967} 1990}
1968 1991
1969/* 1992/*
@@ -2016,6 +2039,7 @@ call_connect_status(struct rpc_task *task)
2016 case 0: 2039 case 0:
2017 clnt->cl_stats->netreconn++; 2040 clnt->cl_stats->netreconn++;
2018 task->tk_action = call_transmit; 2041 task->tk_action = call_transmit;
2042 call_transmit(task);
2019 return; 2043 return;
2020 } 2044 }
2021 rpc_exit(task, status); 2045 rpc_exit(task, status);
@@ -2040,19 +2064,20 @@ call_transmit(struct rpc_task *task)
2040 dprint_status(task); 2064 dprint_status(task);
2041 2065
2042 task->tk_action = call_transmit_status; 2066 task->tk_action = call_transmit_status;
2067 if (!xprt_prepare_transmit(task))
2068 return;
2069 task->tk_status = 0;
2043 if (test_bit(RPC_TASK_NEED_XMIT, &task->tk_runstate)) { 2070 if (test_bit(RPC_TASK_NEED_XMIT, &task->tk_runstate)) {
2044 if (!xprt_prepare_transmit(task)) 2071 if (!xprt_connected(task->tk_xprt)) {
2072 task->tk_status = -ENOTCONN;
2045 return; 2073 return;
2046 task->tk_status = 0;
2047 if (test_bit(RPC_TASK_NEED_XMIT, &task->tk_runstate)) {
2048 if (!xprt_connected(task->tk_xprt)) {
2049 task->tk_status = -ENOTCONN;
2050 return;
2051 }
2052 xprt_transmit(task);
2053 } 2074 }
2075 xprt_transmit(task);
2054 } 2076 }
2055 xprt_end_transmit(task); 2077 xprt_end_transmit(task);
2078 if (rpc_task_need_resched(task))
2079 return;
2080 call_transmit_status(task);
2056} 2081}
2057 2082
2058/* 2083/*
@@ -2067,8 +2092,12 @@ call_transmit_status(struct rpc_task *task)
2067 * Common case: success. Force the compiler to put this 2092 * Common case: success. Force the compiler to put this
2068 * test first. 2093 * test first.
2069 */ 2094 */
2070 if (task->tk_status == 0) { 2095 if (rpc_task_transmitted(task)) {
2071 xprt_request_wait_receive(task); 2096 if (task->tk_status == 0)
2097 xprt_request_wait_receive(task);
2098 if (rpc_task_need_resched(task))
2099 return;
2100 call_status(task);
2072 return; 2101 return;
2073 } 2102 }
2074 2103
@@ -2129,6 +2158,7 @@ call_bc_encode(struct rpc_task *task)
2129{ 2158{
2130 xprt_request_enqueue_transmit(task); 2159 xprt_request_enqueue_transmit(task);
2131 task->tk_action = call_bc_transmit; 2160 task->tk_action = call_bc_transmit;
2161 call_bc_transmit(task);
2132} 2162}
2133 2163
2134/* 2164/*
@@ -2219,6 +2249,7 @@ call_status(struct rpc_task *task)
2219 status = task->tk_status; 2249 status = task->tk_status;
2220 if (status >= 0) { 2250 if (status >= 0) {
2221 task->tk_action = call_decode; 2251 task->tk_action = call_decode;
2252 call_decode(task);
2222 return; 2253 return;
2223 } 2254 }
2224 2255