xref: /linux/fs/nfs/nfs40proc.c (revision 1fd1dc41724319406b0aff221a352a400b0ddfc5)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #include <linux/nfs4.h>
3 #include <linux/nfs.h>
4 #include <linux/sunrpc/sched.h>
5 #include <linux/nfs_fs.h>
6 #include "internal.h"
7 #include "nfs4_fs.h"
8 #include "nfs40.h"
9 #include "nfs4session.h"
10 #include "nfs4trace.h"
11 
12 static void nfs40_call_sync_prepare(struct rpc_task *task, void *calldata)
13 {
14 	struct nfs4_call_sync_data *data = calldata;
15 	nfs4_setup_sequence(data->seq_server->nfs_client,
16 				data->seq_args, data->seq_res, task);
17 }
18 
19 static void nfs40_call_sync_done(struct rpc_task *task, void *calldata)
20 {
21 	struct nfs4_call_sync_data *data = calldata;
22 	nfs4_sequence_done(task, data->seq_res);
23 }
24 
25 static void nfs40_sequence_free_slot(struct nfs4_sequence_res *res)
26 {
27 	struct nfs4_slot *slot = res->sr_slot;
28 	struct nfs4_slot_table *tbl;
29 
30 	tbl = slot->table;
31 	spin_lock(&tbl->slot_tbl_lock);
32 	if (!nfs41_wake_and_assign_slot(tbl, slot))
33 		nfs4_free_slot(tbl, slot);
34 	spin_unlock(&tbl->slot_tbl_lock);
35 
36 	res->sr_slot = NULL;
37 }
38 
39 static int nfs40_sequence_done(struct rpc_task *task,
40 			       struct nfs4_sequence_res *res)
41 {
42 	if (res->sr_slot != NULL)
43 		nfs40_sequence_free_slot(res);
44 	return 1;
45 }
46 
47 static void nfs40_clear_delegation_stateid(struct nfs4_state *state)
48 {
49 	if (rcu_access_pointer(NFS_I(state->inode)->delegation) != NULL)
50 		nfs_finish_clear_delegation_stateid(state, NULL);
51 }
52 
53 static int nfs40_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state)
54 {
55 	/* NFSv4.0 doesn't allow for delegation recovery on open expire */
56 	nfs40_clear_delegation_stateid(state);
57 	nfs_state_clear_open_state_flags(state);
58 	return nfs4_open_expired(sp, state);
59 }
60 
61 struct nfs4_renewdata {
62 	struct nfs_client	*client;
63 	unsigned long		timestamp;
64 };
65 
66 /*
67  * nfs4_proc_async_renew(): This is not one of the nfs_rpc_ops; it is a special
68  * standalone procedure for queueing an asynchronous RENEW.
69  */
70 static void nfs4_renew_release(void *calldata)
71 {
72 	struct nfs4_renewdata *data = calldata;
73 	struct nfs_client *clp = data->client;
74 
75 	if (refcount_read(&clp->cl_count) > 1)
76 		nfs4_schedule_state_renewal(clp);
77 	nfs_put_client(clp);
78 	kfree(data);
79 }
80 
81 static void nfs4_renew_done(struct rpc_task *task, void *calldata)
82 {
83 	struct nfs4_renewdata *data = calldata;
84 	struct nfs_client *clp = data->client;
85 	unsigned long timestamp = data->timestamp;
86 
87 	trace_nfs4_renew_async(clp, task->tk_status);
88 	switch (task->tk_status) {
89 	case 0:
90 		break;
91 	case -NFS4ERR_LEASE_MOVED:
92 		nfs4_schedule_lease_moved_recovery(clp);
93 		break;
94 	default:
95 		/* Unless we're shutting down, schedule state recovery! */
96 		if (test_bit(NFS_CS_RENEWD, &clp->cl_res_state) == 0)
97 			return;
98 		if (task->tk_status != NFS4ERR_CB_PATH_DOWN) {
99 			nfs4_schedule_lease_recovery(clp);
100 			return;
101 		}
102 		nfs4_schedule_path_down_recovery(clp);
103 	}
104 	do_renew_lease(clp, timestamp);
105 }
106 
107 static const struct rpc_call_ops nfs4_renew_ops = {
108 	.rpc_call_done = nfs4_renew_done,
109 	.rpc_release = nfs4_renew_release,
110 };
111 
112 static int nfs4_proc_async_renew(struct nfs_client *clp, const struct cred *cred, unsigned renew_flags)
113 {
114 	struct rpc_message msg = {
115 		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_RENEW],
116 		.rpc_argp	= clp,
117 		.rpc_cred	= cred,
118 	};
119 	struct nfs4_renewdata *data;
120 
121 	if (renew_flags == 0)
122 		return 0;
123 	if (!refcount_inc_not_zero(&clp->cl_count))
124 		return -EIO;
125 	data = kmalloc_obj(*data, GFP_NOFS);
126 	if (data == NULL) {
127 		nfs_put_client(clp);
128 		return -ENOMEM;
129 	}
130 	data->client = clp;
131 	data->timestamp = jiffies;
132 	return rpc_call_async(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT,
133 			&nfs4_renew_ops, data);
134 }
135 
136 static int nfs4_proc_renew(struct nfs_client *clp, const struct cred *cred)
137 {
138 	struct rpc_message msg = {
139 		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_RENEW],
140 		.rpc_argp	= clp,
141 		.rpc_cred	= cred,
142 	};
143 	unsigned long now = jiffies;
144 	int status;
145 
146 	status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
147 	if (status < 0)
148 		return status;
149 	do_renew_lease(clp, now);
150 	return 0;
151 }
152 
153 static int nfs40_test_and_free_expired_stateid(struct nfs_server *server,
154 					       nfs4_stateid *stateid,
155 					       const struct cred *cred)
156 {
157 	return -NFS4ERR_BAD_STATEID;
158 }
159 
160 /*
161  * This operation also signals the server that this client is
162  * performing migration recovery.  The server can stop returning
163  * NFS4ERR_LEASE_MOVED to this client.  A RENEW operation is
164  * appended to this compound to identify the client ID which is
165  * performing recovery.
166  */
167 static int _nfs40_proc_get_locations(struct nfs_server *server,
168 				     struct nfs_fh *fhandle,
169 				     struct nfs4_fs_locations *locations,
170 				     struct page *page, const struct cred *cred)
171 {
172 	struct rpc_clnt *clnt = server->client;
173 	struct nfs_client *clp = server->nfs_client;
174 	u32 bitmask[2] = {
175 		[0] = FATTR4_WORD0_FSID | FATTR4_WORD0_FS_LOCATIONS,
176 	};
177 	struct nfs4_fs_locations_arg args = {
178 		.clientid	= clp->cl_clientid,
179 		.fh		= fhandle,
180 		.page		= page,
181 		.bitmask	= bitmask,
182 		.migration	= 1,		/* skip LOOKUP */
183 		.renew		= 1,		/* append RENEW */
184 	};
185 	struct nfs4_fs_locations_res res = {
186 		.fs_locations	= locations,
187 		.migration	= 1,
188 		.renew		= 1,
189 	};
190 	struct rpc_message msg = {
191 		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_FS_LOCATIONS],
192 		.rpc_argp	= &args,
193 		.rpc_resp	= &res,
194 		.rpc_cred	= cred,
195 	};
196 	unsigned long now = jiffies;
197 	int status;
198 
199 	nfs_fattr_init(locations->fattr);
200 	locations->server = server;
201 	locations->nlocations = 0;
202 
203 	nfs4_init_sequence(clp, &args.seq_args, &res.seq_res, 0, 1);
204 	status = nfs4_call_sync_sequence(clnt, server, &msg,
205 					&args.seq_args, &res.seq_res);
206 	if (status)
207 		return status;
208 
209 	renew_lease(server, now);
210 	return 0;
211 }
212 
213 /*
214  * This operation also signals the server that this client is
215  * performing "lease moved" recovery.  The server can stop
216  * returning NFS4ERR_LEASE_MOVED to this client.  A RENEW operation
217  * is appended to this compound to identify the client ID which is
218  * performing recovery.
219  */
220 static int _nfs40_proc_fsid_present(struct inode *inode, const struct cred *cred)
221 {
222 	struct nfs_server *server = NFS_SERVER(inode);
223 	struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
224 	struct rpc_clnt *clnt = server->client;
225 	struct nfs4_fsid_present_arg args = {
226 		.fh		= NFS_FH(inode),
227 		.clientid	= clp->cl_clientid,
228 		.renew		= 1,		/* append RENEW */
229 	};
230 	struct nfs4_fsid_present_res res = {
231 		.renew		= 1,
232 	};
233 	struct rpc_message msg = {
234 		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_FSID_PRESENT],
235 		.rpc_argp	= &args,
236 		.rpc_resp	= &res,
237 		.rpc_cred	= cred,
238 	};
239 	unsigned long now = jiffies;
240 	int status;
241 
242 	res.fh = nfs_alloc_fhandle();
243 	if (res.fh == NULL)
244 		return -ENOMEM;
245 
246 	nfs4_init_sequence(clp, &args.seq_args, &res.seq_res, 0, 1);
247 	status = nfs4_call_sync_sequence(clnt, server, &msg,
248 						&args.seq_args, &res.seq_res);
249 	nfs_free_fhandle(res.fh);
250 	if (status)
251 		return status;
252 
253 	do_renew_lease(clp, now);
254 	return 0;
255 }
256 
257 struct nfs_release_lockowner_data {
258 	struct nfs4_lock_state *lsp;
259 	struct nfs_server *server;
260 	struct nfs_release_lockowner_args args;
261 	struct nfs_release_lockowner_res res;
262 	unsigned long timestamp;
263 };
264 
265 static void nfs4_release_lockowner_prepare(struct rpc_task *task, void *calldata)
266 {
267 	struct nfs_release_lockowner_data *data = calldata;
268 	struct nfs_server *server = data->server;
269 	nfs4_setup_sequence(server->nfs_client, &data->args.seq_args,
270 			   &data->res.seq_res, task);
271 	data->args.lock_owner.clientid = server->nfs_client->cl_clientid;
272 	data->timestamp = jiffies;
273 }
274 
275 static void nfs4_release_lockowner_done(struct rpc_task *task, void *calldata)
276 {
277 	struct nfs_release_lockowner_data *data = calldata;
278 	struct nfs_server *server = data->server;
279 
280 	nfs40_sequence_done(task, &data->res.seq_res);
281 
282 	switch (task->tk_status) {
283 	case 0:
284 		renew_lease(server, data->timestamp);
285 		break;
286 	case -NFS4ERR_STALE_CLIENTID:
287 	case -NFS4ERR_EXPIRED:
288 		nfs4_schedule_lease_recovery(server->nfs_client);
289 		break;
290 	case -NFS4ERR_LEASE_MOVED:
291 	case -NFS4ERR_DELAY:
292 		if (nfs4_async_handle_error(task, server,
293 					    NULL, NULL) == -EAGAIN)
294 			rpc_restart_call_prepare(task);
295 	}
296 }
297 
298 static void nfs4_release_lockowner_release(void *calldata)
299 {
300 	struct nfs_release_lockowner_data *data = calldata;
301 	nfs4_free_lock_state(data->server, data->lsp);
302 	kfree(calldata);
303 }
304 
305 static const struct rpc_call_ops nfs4_release_lockowner_ops = {
306 	.rpc_call_prepare = nfs4_release_lockowner_prepare,
307 	.rpc_call_done = nfs4_release_lockowner_done,
308 	.rpc_release = nfs4_release_lockowner_release,
309 };
310 
311 static void
312 nfs4_release_lockowner(struct nfs_server *server, struct nfs4_lock_state *lsp)
313 {
314 	struct nfs_release_lockowner_data *data;
315 	struct nfs_client *clp = server->nfs_client;
316 	struct rpc_message msg = {
317 		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RELEASE_LOCKOWNER],
318 	};
319 
320 	if (clp->cl_mvops->minor_version != 0)
321 		return;
322 
323 	data = kmalloc_obj(*data);
324 	if (!data)
325 		return;
326 	data->lsp = lsp;
327 	data->server = server;
328 	data->args.lock_owner.clientid = clp->cl_clientid;
329 	data->args.lock_owner.id = lsp->ls_seqid.owner_id;
330 	data->args.lock_owner.s_dev = server->s_dev;
331 
332 	msg.rpc_argp = &data->args;
333 	msg.rpc_resp = &data->res;
334 	nfs4_init_sequence(clp, &data->args.seq_args, &data->res.seq_res, 0, 0);
335 	rpc_call_async(server->client, &msg, 0, &nfs4_release_lockowner_ops, data);
336 }
337 
338 static const struct rpc_call_ops nfs40_call_sync_ops = {
339 	.rpc_call_prepare = nfs40_call_sync_prepare,
340 	.rpc_call_done = nfs40_call_sync_done,
341 };
342 
343 static const struct nfs4_sequence_slot_ops nfs40_sequence_slot_ops = {
344 	.process = nfs40_sequence_done,
345 	.done = nfs40_sequence_done,
346 	.free_slot = nfs40_sequence_free_slot,
347 };
348 
349 static const struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = {
350 	.owner_flag_bit = NFS_OWNER_RECLAIM_REBOOT,
351 	.state_flag_bit	= NFS_STATE_RECLAIM_REBOOT,
352 	.recover_open	= nfs4_open_reclaim,
353 	.recover_lock	= nfs4_lock_reclaim,
354 	.establish_clid = nfs4_init_clientid,
355 	.detect_trunking = nfs40_discover_server_trunking,
356 };
357 
358 static const struct nfs4_state_recovery_ops nfs40_nograce_recovery_ops = {
359 	.owner_flag_bit = NFS_OWNER_RECLAIM_NOGRACE,
360 	.state_flag_bit	= NFS_STATE_RECLAIM_NOGRACE,
361 	.recover_open	= nfs40_open_expired,
362 	.recover_lock	= nfs4_lock_expired,
363 	.establish_clid = nfs4_init_clientid,
364 };
365 
366 static const struct nfs4_state_maintenance_ops nfs40_state_renewal_ops = {
367 	.sched_state_renewal = nfs4_proc_async_renew,
368 	.get_state_renewal_cred = nfs4_get_renew_cred,
369 	.renew_lease = nfs4_proc_renew,
370 };
371 
372 static const struct nfs4_mig_recovery_ops nfs40_mig_recovery_ops = {
373 	.get_locations = _nfs40_proc_get_locations,
374 	.fsid_present = _nfs40_proc_fsid_present,
375 };
376 
377 const struct nfs4_minor_version_ops nfs_v4_0_minor_ops = {
378 	.minor_version = 0,
379 	.init_caps = NFS_CAP_READDIRPLUS
380 		| NFS_CAP_ATOMIC_OPEN
381 		| NFS_CAP_POSIX_LOCK,
382 	.init_client = nfs40_init_client,
383 	.shutdown_client = nfs40_shutdown_client,
384 	.match_stateid = nfs4_match_stateid,
385 	.find_root_sec = nfs4_find_root_sec,
386 	.free_lock_state = nfs4_release_lockowner,
387 	.test_and_free_expired = nfs40_test_and_free_expired_stateid,
388 	.alloc_seqid = nfs_alloc_seqid,
389 	.call_sync_ops = &nfs40_call_sync_ops,
390 	.sequence_slot_ops = &nfs40_sequence_slot_ops,
391 	.reboot_recovery_ops = &nfs40_reboot_recovery_ops,
392 	.nograce_recovery_ops = &nfs40_nograce_recovery_ops,
393 	.state_renewal_ops = &nfs40_state_renewal_ops,
394 	.mig_recovery_ops = &nfs40_mig_recovery_ops,
395 };
396