aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4state.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/nfs4state.c')
-rw-r--r--fs/nfs/nfs4state.c228
1 files changed, 211 insertions, 17 deletions
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 55148def5540..c351e6b39838 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -51,18 +51,21 @@
51#include <linux/bitops.h> 51#include <linux/bitops.h>
52#include <linux/jiffies.h> 52#include <linux/jiffies.h>
53 53
54#include <linux/sunrpc/clnt.h>
55
54#include "nfs4_fs.h" 56#include "nfs4_fs.h"
55#include "callback.h" 57#include "callback.h"
56#include "delegation.h" 58#include "delegation.h"
57#include "internal.h" 59#include "internal.h"
58#include "pnfs.h" 60#include "pnfs.h"
61#include "netns.h"
59 62
60#define NFSDBG_FACILITY NFSDBG_STATE 63#define NFSDBG_FACILITY NFSDBG_STATE
61 64
62#define OPENOWNER_POOL_SIZE 8 65#define OPENOWNER_POOL_SIZE 8
63 66
64const nfs4_stateid zero_stateid; 67const nfs4_stateid zero_stateid;
65 68static DEFINE_MUTEX(nfs_clid_init_mutex);
66static LIST_HEAD(nfs4_clientid_list); 69static LIST_HEAD(nfs4_clientid_list);
67 70
68int nfs4_init_clientid(struct nfs_client *clp, struct rpc_cred *cred) 71int nfs4_init_clientid(struct nfs_client *clp, struct rpc_cred *cred)
@@ -73,12 +76,13 @@ int nfs4_init_clientid(struct nfs_client *clp, struct rpc_cred *cred)
73 }; 76 };
74 unsigned short port; 77 unsigned short port;
75 int status; 78 int status;
79 struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id);
76 80
77 if (test_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state)) 81 if (test_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state))
78 goto do_confirm; 82 goto do_confirm;
79 port = nfs_callback_tcpport; 83 port = nn->nfs_callback_tcpport;
80 if (clp->cl_addr.ss_family == AF_INET6) 84 if (clp->cl_addr.ss_family == AF_INET6)
81 port = nfs_callback_tcpport6; 85 port = nn->nfs_callback_tcpport6;
82 86
83 status = nfs4_proc_setclientid(clp, NFS4_CALLBACK, port, cred, &clid); 87 status = nfs4_proc_setclientid(clp, NFS4_CALLBACK, port, cred, &clid);
84 if (status != 0) 88 if (status != 0)
@@ -96,6 +100,56 @@ out:
96 return status; 100 return status;
97} 101}
98 102
103/**
104 * nfs40_discover_server_trunking - Detect server IP address trunking (mv0)
105 *
106 * @clp: nfs_client under test
107 * @result: OUT: found nfs_client, or clp
108 * @cred: credential to use for trunking test
109 *
110 * Returns zero, a negative errno, or a negative NFS4ERR status.
111 * If zero is returned, an nfs_client pointer is planted in
112 * "result".
113 *
114 * Note: The returned client may not yet be marked ready.
115 */
116int nfs40_discover_server_trunking(struct nfs_client *clp,
117 struct nfs_client **result,
118 struct rpc_cred *cred)
119{
120 struct nfs4_setclientid_res clid = {
121 .clientid = clp->cl_clientid,
122 .confirm = clp->cl_confirm,
123 };
124 struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id);
125 unsigned short port;
126 int status;
127
128 port = nn->nfs_callback_tcpport;
129 if (clp->cl_addr.ss_family == AF_INET6)
130 port = nn->nfs_callback_tcpport6;
131
132 status = nfs4_proc_setclientid(clp, NFS4_CALLBACK, port, cred, &clid);
133 if (status != 0)
134 goto out;
135 clp->cl_clientid = clid.clientid;
136 clp->cl_confirm = clid.confirm;
137
138 status = nfs40_walk_client_list(clp, result, cred);
139 switch (status) {
140 case -NFS4ERR_STALE_CLIENTID:
141 set_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
142 case 0:
143 /* Sustain the lease, even if it's empty. If the clientid4
144 * goes stale it's of no use for trunking discovery. */
145 nfs4_schedule_state_renewal(*result);
146 break;
147 }
148
149out:
150 return status;
151}
152
99struct rpc_cred *nfs4_get_machine_cred_locked(struct nfs_client *clp) 153struct rpc_cred *nfs4_get_machine_cred_locked(struct nfs_client *clp)
100{ 154{
101 struct rpc_cred *cred = NULL; 155 struct rpc_cred *cred = NULL;
@@ -275,6 +329,33 @@ out:
275 return status; 329 return status;
276} 330}
277 331
332/**
333 * nfs41_discover_server_trunking - Detect server IP address trunking (mv1)
334 *
335 * @clp: nfs_client under test
336 * @result: OUT: found nfs_client, or clp
337 * @cred: credential to use for trunking test
338 *
339 * Returns NFS4_OK, a negative errno, or a negative NFS4ERR status.
340 * If NFS4_OK is returned, an nfs_client pointer is planted in
341 * "result".
342 *
343 * Note: The returned client may not yet be marked ready.
344 */
345int nfs41_discover_server_trunking(struct nfs_client *clp,
346 struct nfs_client **result,
347 struct rpc_cred *cred)
348{
349 int status;
350
351 status = nfs4_proc_exchange_id(clp, cred);
352 if (status != NFS4_OK)
353 return status;
354 set_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
355
356 return nfs41_walk_client_list(clp, result, cred);
357}
358
278struct rpc_cred *nfs4_get_exchange_id_cred(struct nfs_client *clp) 359struct rpc_cred *nfs4_get_exchange_id_cred(struct nfs_client *clp)
279{ 360{
280 struct rpc_cred *cred; 361 struct rpc_cred *cred;
@@ -729,11 +810,8 @@ static void __nfs4_close(struct nfs4_state *state,
729 if (!call_close) { 810 if (!call_close) {
730 nfs4_put_open_state(state); 811 nfs4_put_open_state(state);
731 nfs4_put_state_owner(owner); 812 nfs4_put_state_owner(owner);
732 } else { 813 } else
733 bool roc = pnfs_roc(state->inode); 814 nfs4_do_close(state, gfp_mask, wait);
734
735 nfs4_do_close(state, gfp_mask, wait, roc);
736 }
737} 815}
738 816
739void nfs4_close_state(struct nfs4_state *state, fmode_t fmode) 817void nfs4_close_state(struct nfs4_state *state, fmode_t fmode)
@@ -865,7 +943,7 @@ void nfs4_put_lock_state(struct nfs4_lock_state *lsp)
865 if (list_empty(&state->lock_states)) 943 if (list_empty(&state->lock_states))
866 clear_bit(LK_STATE_IN_USE, &state->flags); 944 clear_bit(LK_STATE_IN_USE, &state->flags);
867 spin_unlock(&state->state_lock); 945 spin_unlock(&state->state_lock);
868 if (lsp->ls_flags & NFS_LOCK_INITIALIZED) { 946 if (test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags)) {
869 if (nfs4_release_lockowner(lsp) == 0) 947 if (nfs4_release_lockowner(lsp) == 0)
870 return; 948 return;
871 } 949 }
@@ -911,17 +989,25 @@ int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl)
911} 989}
912 990
913static bool nfs4_copy_lock_stateid(nfs4_stateid *dst, struct nfs4_state *state, 991static bool nfs4_copy_lock_stateid(nfs4_stateid *dst, struct nfs4_state *state,
914 fl_owner_t fl_owner, pid_t fl_pid) 992 const struct nfs_lockowner *lockowner)
915{ 993{
916 struct nfs4_lock_state *lsp; 994 struct nfs4_lock_state *lsp;
995 fl_owner_t fl_owner;
996 pid_t fl_pid;
917 bool ret = false; 997 bool ret = false;
918 998
999
1000 if (lockowner == NULL)
1001 goto out;
1002
919 if (test_bit(LK_STATE_IN_USE, &state->flags) == 0) 1003 if (test_bit(LK_STATE_IN_USE, &state->flags) == 0)
920 goto out; 1004 goto out;
921 1005
1006 fl_owner = lockowner->l_owner;
1007 fl_pid = lockowner->l_pid;
922 spin_lock(&state->state_lock); 1008 spin_lock(&state->state_lock);
923 lsp = __nfs4_find_lock_state(state, fl_owner, fl_pid, NFS4_ANY_LOCK_TYPE); 1009 lsp = __nfs4_find_lock_state(state, fl_owner, fl_pid, NFS4_ANY_LOCK_TYPE);
924 if (lsp != NULL && (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0) { 1010 if (lsp != NULL && test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags) != 0) {
925 nfs4_stateid_copy(dst, &lsp->ls_stateid); 1011 nfs4_stateid_copy(dst, &lsp->ls_stateid);
926 ret = true; 1012 ret = true;
927 } 1013 }
@@ -946,11 +1032,11 @@ static void nfs4_copy_open_stateid(nfs4_stateid *dst, struct nfs4_state *state)
946 * requests. 1032 * requests.
947 */ 1033 */
948void nfs4_select_rw_stateid(nfs4_stateid *dst, struct nfs4_state *state, 1034void nfs4_select_rw_stateid(nfs4_stateid *dst, struct nfs4_state *state,
949 fmode_t fmode, fl_owner_t fl_owner, pid_t fl_pid) 1035 fmode_t fmode, const struct nfs_lockowner *lockowner)
950{ 1036{
951 if (nfs4_copy_delegation_stateid(dst, state->inode, fmode)) 1037 if (nfs4_copy_delegation_stateid(dst, state->inode, fmode))
952 return; 1038 return;
953 if (nfs4_copy_lock_stateid(dst, state, fl_owner, fl_pid)) 1039 if (nfs4_copy_lock_stateid(dst, state, lockowner))
954 return; 1040 return;
955 nfs4_copy_open_stateid(dst, state); 1041 nfs4_copy_open_stateid(dst, state);
956} 1042}
@@ -1289,7 +1375,7 @@ restart:
1289 if (status >= 0) { 1375 if (status >= 0) {
1290 spin_lock(&state->state_lock); 1376 spin_lock(&state->state_lock);
1291 list_for_each_entry(lock, &state->lock_states, ls_locks) { 1377 list_for_each_entry(lock, &state->lock_states, ls_locks) {
1292 if (!(lock->ls_flags & NFS_LOCK_INITIALIZED)) 1378 if (!test_bit(NFS_LOCK_INITIALIZED, &lock->ls_flags))
1293 pr_warn_ratelimited("NFS: " 1379 pr_warn_ratelimited("NFS: "
1294 "%s: Lock reclaim " 1380 "%s: Lock reclaim "
1295 "failed!\n", __func__); 1381 "failed!\n", __func__);
@@ -1361,7 +1447,7 @@ static void nfs4_clear_open_state(struct nfs4_state *state)
1361 spin_lock(&state->state_lock); 1447 spin_lock(&state->state_lock);
1362 list_for_each_entry(lock, &state->lock_states, ls_locks) { 1448 list_for_each_entry(lock, &state->lock_states, ls_locks) {
1363 lock->ls_seqid.flags = 0; 1449 lock->ls_seqid.flags = 0;
1364 lock->ls_flags &= ~NFS_LOCK_INITIALIZED; 1450 clear_bit(NFS_LOCK_INITIALIZED, &lock->ls_flags);
1365 } 1451 }
1366 spin_unlock(&state->state_lock); 1452 spin_unlock(&state->state_lock);
1367} 1453}
@@ -1595,8 +1681,8 @@ out:
1595 return nfs4_recovery_handle_error(clp, status); 1681 return nfs4_recovery_handle_error(clp, status);
1596} 1682}
1597 1683
1598/* Set NFS4CLNT_LEASE_EXPIRED for all v4.0 errors and for recoverable errors 1684/* Set NFS4CLNT_LEASE_EXPIRED and reclaim reboot state for all v4.0 errors
1599 * on EXCHANGE_ID for v4.1 1685 * and for recoverable errors on EXCHANGE_ID for v4.1
1600 */ 1686 */
1601static int nfs4_handle_reclaim_lease_error(struct nfs_client *clp, int status) 1687static int nfs4_handle_reclaim_lease_error(struct nfs_client *clp, int status)
1602{ 1688{
@@ -1606,8 +1692,12 @@ static int nfs4_handle_reclaim_lease_error(struct nfs_client *clp, int status)
1606 return -ESERVERFAULT; 1692 return -ESERVERFAULT;
1607 /* Lease confirmation error: retry after purging the lease */ 1693 /* Lease confirmation error: retry after purging the lease */
1608 ssleep(1); 1694 ssleep(1);
1695 clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
1696 break;
1609 case -NFS4ERR_STALE_CLIENTID: 1697 case -NFS4ERR_STALE_CLIENTID:
1610 clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); 1698 clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
1699 nfs4_state_clear_reclaim_reboot(clp);
1700 nfs4_state_start_reclaim_reboot(clp);
1611 break; 1701 break;
1612 case -NFS4ERR_CLID_INUSE: 1702 case -NFS4ERR_CLID_INUSE:
1613 pr_err("NFS: Server %s reports our clientid is in use\n", 1703 pr_err("NFS: Server %s reports our clientid is in use\n",
@@ -1698,6 +1788,109 @@ static int nfs4_purge_lease(struct nfs_client *clp)
1698 return 0; 1788 return 0;
1699} 1789}
1700 1790
1791/**
1792 * nfs4_discover_server_trunking - Detect server IP address trunking
1793 *
1794 * @clp: nfs_client under test
1795 * @result: OUT: found nfs_client, or clp
1796 *
1797 * Returns zero or a negative errno. If zero is returned,
1798 * an nfs_client pointer is planted in "result".
1799 *
1800 * Note: since we are invoked in process context, and
1801 * not from inside the state manager, we cannot use
1802 * nfs4_handle_reclaim_lease_error().
1803 */
1804int nfs4_discover_server_trunking(struct nfs_client *clp,
1805 struct nfs_client **result)
1806{
1807 const struct nfs4_state_recovery_ops *ops =
1808 clp->cl_mvops->reboot_recovery_ops;
1809 rpc_authflavor_t *flavors, flav, save;
1810 struct rpc_clnt *clnt;
1811 struct rpc_cred *cred;
1812 int i, len, status;
1813
1814 dprintk("NFS: %s: testing '%s'\n", __func__, clp->cl_hostname);
1815
1816 len = NFS_MAX_SECFLAVORS;
1817 flavors = kcalloc(len, sizeof(*flavors), GFP_KERNEL);
1818 if (flavors == NULL) {
1819 status = -ENOMEM;
1820 goto out;
1821 }
1822 len = rpcauth_list_flavors(flavors, len);
1823 if (len < 0) {
1824 status = len;
1825 goto out_free;
1826 }
1827 clnt = clp->cl_rpcclient;
1828 save = clnt->cl_auth->au_flavor;
1829 i = 0;
1830
1831 mutex_lock(&nfs_clid_init_mutex);
1832 status = -ENOENT;
1833again:
1834 cred = ops->get_clid_cred(clp);
1835 if (cred == NULL)
1836 goto out_unlock;
1837
1838 status = ops->detect_trunking(clp, result, cred);
1839 put_rpccred(cred);
1840 switch (status) {
1841 case 0:
1842 break;
1843
1844 case -EACCES:
1845 if (clp->cl_machine_cred == NULL)
1846 break;
1847 /* Handle case where the user hasn't set up machine creds */
1848 nfs4_clear_machine_cred(clp);
1849 case -NFS4ERR_DELAY:
1850 case -ETIMEDOUT:
1851 case -EAGAIN:
1852 ssleep(1);
1853 dprintk("NFS: %s after status %d, retrying\n",
1854 __func__, status);
1855 goto again;
1856
1857 case -NFS4ERR_CLID_INUSE:
1858 case -NFS4ERR_WRONGSEC:
1859 status = -EPERM;
1860 if (i >= len)
1861 break;
1862
1863 flav = flavors[i++];
1864 if (flav == save)
1865 flav = flavors[i++];
1866 clnt = rpc_clone_client_set_auth(clnt, flav);
1867 if (IS_ERR(clnt)) {
1868 status = PTR_ERR(clnt);
1869 break;
1870 }
1871 clp->cl_rpcclient = clnt;
1872 goto again;
1873
1874 case -NFS4ERR_MINOR_VERS_MISMATCH:
1875 status = -EPROTONOSUPPORT;
1876 break;
1877
1878 case -EKEYEXPIRED:
1879 nfs4_warn_keyexpired(clp->cl_hostname);
1880 case -NFS4ERR_NOT_SAME: /* FixMe: implement recovery
1881 * in nfs4_exchange_id */
1882 status = -EKEYEXPIRED;
1883 }
1884
1885out_unlock:
1886 mutex_unlock(&nfs_clid_init_mutex);
1887out_free:
1888 kfree(flavors);
1889out:
1890 dprintk("NFS: %s: status = %d\n", __func__, status);
1891 return status;
1892}
1893
1701#ifdef CONFIG_NFS_V4_1 1894#ifdef CONFIG_NFS_V4_1
1702void nfs4_schedule_session_recovery(struct nfs4_session *session, int err) 1895void nfs4_schedule_session_recovery(struct nfs4_session *session, int err)
1703{ 1896{
@@ -2008,6 +2201,7 @@ out_error:
2008 pr_warn_ratelimited("NFS: state manager%s%s failed on NFSv4 server %s" 2201 pr_warn_ratelimited("NFS: state manager%s%s failed on NFSv4 server %s"
2009 " with error %d\n", section_sep, section, 2202 " with error %d\n", section_sep, section,
2010 clp->cl_hostname, -status); 2203 clp->cl_hostname, -status);
2204 ssleep(1);
2011 nfs4_end_drain_session(clp); 2205 nfs4_end_drain_session(clp);
2012 nfs4_clear_state_manager_bit(clp); 2206 nfs4_clear_state_manager_bit(clp);
2013} 2207}