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
nfs40_call_sync_prepare(struct rpc_task * task,void * calldata)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
nfs40_call_sync_done(struct rpc_task * task,void * calldata)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
nfs40_sequence_free_slot(struct nfs4_sequence_res * res)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
nfs40_sequence_done(struct rpc_task * task,struct nfs4_sequence_res * res)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
nfs40_clear_delegation_stateid(struct nfs4_state * state)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
nfs40_open_expired(struct nfs4_state_owner * sp,struct nfs4_state * state)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 */
nfs4_renew_release(void * calldata)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
nfs4_renew_done(struct rpc_task * task,void * calldata)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
nfs4_proc_async_renew(struct nfs_client * clp,const struct cred * cred,unsigned renew_flags)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
nfs4_proc_renew(struct nfs_client * clp,const struct cred * cred)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
nfs40_test_and_free_expired_stateid(struct nfs_server * server,nfs4_stateid * stateid,const struct cred * cred)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 */
_nfs40_proc_get_locations(struct nfs_server * server,struct nfs_fh * fhandle,struct nfs4_fs_locations * locations,struct page * page,const struct cred * cred)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 */
_nfs40_proc_fsid_present(struct inode * inode,const struct cred * cred)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
nfs4_release_lockowner_prepare(struct rpc_task * task,void * calldata)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
nfs4_release_lockowner_done(struct rpc_task * task,void * calldata)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
nfs4_release_lockowner_release(void * calldata)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
nfs4_release_lockowner(struct nfs_server * server,struct nfs4_lock_state * lsp)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