3
3
* Copyright (c) 2014 Anna Schumaker <[email protected] >
4
4
*/
5
5
#include <linux/fs.h>
6
+ #include <linux/sunrpc/addr.h>
6
7
#include <linux/sunrpc/sched.h>
7
8
#include <linux/nfs.h>
8
9
#include <linux/nfs3.h>
15
16
#include "pnfs.h"
16
17
#include "nfs4session.h"
17
18
#include "internal.h"
19
+ #include "delegation.h"
18
20
19
21
#define NFSDBG_FACILITY NFSDBG_PROC
20
22
static int nfs42_do_offload_cancel_async (struct file * dst , nfs4_stateid * std );
21
23
24
+ static void nfs42_set_netaddr (struct file * filep , struct nfs42_netaddr * naddr )
25
+ {
26
+ struct nfs_client * clp = (NFS_SERVER (file_inode (filep )))-> nfs_client ;
27
+ unsigned short port = 2049 ;
28
+
29
+ rcu_read_lock ();
30
+ naddr -> netid_len = scnprintf (naddr -> netid ,
31
+ sizeof (naddr -> netid ), "%s" ,
32
+ rpc_peeraddr2str (clp -> cl_rpcclient ,
33
+ RPC_DISPLAY_NETID ));
34
+ naddr -> addr_len = scnprintf (naddr -> addr ,
35
+ sizeof (naddr -> addr ),
36
+ "%s.%u.%u" ,
37
+ rpc_peeraddr2str (clp -> cl_rpcclient ,
38
+ RPC_DISPLAY_ADDR ),
39
+ port >> 8 , port & 255 );
40
+ rcu_read_unlock ();
41
+ }
42
+
22
43
static int _nfs42_proc_fallocate (struct rpc_message * msg , struct file * filep ,
23
44
struct nfs_lock_context * lock , loff_t offset , loff_t len )
24
45
{
@@ -132,22 +153,26 @@ int nfs42_proc_deallocate(struct file *filep, loff_t offset, loff_t len)
132
153
}
133
154
134
155
static int handle_async_copy (struct nfs42_copy_res * res ,
135
- struct nfs_server * server ,
156
+ struct nfs_server * dst_server ,
157
+ struct nfs_server * src_server ,
136
158
struct file * src ,
137
159
struct file * dst ,
138
- nfs4_stateid * src_stateid )
160
+ nfs4_stateid * src_stateid ,
161
+ bool * restart )
139
162
{
140
163
struct nfs4_copy_state * copy , * tmp_copy ;
141
164
int status = NFS4_OK ;
142
165
bool found_pending = false;
143
- struct nfs_open_context * ctx = nfs_file_open_context (dst );
166
+ struct nfs_open_context * dst_ctx = nfs_file_open_context (dst );
167
+ struct nfs_open_context * src_ctx = nfs_file_open_context (src );
144
168
145
169
copy = kzalloc (sizeof (struct nfs4_copy_state ), GFP_NOFS );
146
170
if (!copy )
147
171
return - ENOMEM ;
148
172
149
- spin_lock (& server -> nfs_client -> cl_lock );
150
- list_for_each_entry (tmp_copy , & server -> nfs_client -> pending_cb_stateids ,
173
+ spin_lock (& dst_server -> nfs_client -> cl_lock );
174
+ list_for_each_entry (tmp_copy ,
175
+ & dst_server -> nfs_client -> pending_cb_stateids ,
151
176
copies ) {
152
177
if (memcmp (& res -> write_res .stateid , & tmp_copy -> stateid ,
153
178
NFS4_STATEID_SIZE ))
@@ -157,40 +182,55 @@ static int handle_async_copy(struct nfs42_copy_res *res,
157
182
break ;
158
183
}
159
184
if (found_pending ) {
160
- spin_unlock (& server -> nfs_client -> cl_lock );
185
+ spin_unlock (& dst_server -> nfs_client -> cl_lock );
161
186
kfree (copy );
162
187
copy = tmp_copy ;
163
188
goto out ;
164
189
}
165
190
166
191
memcpy (& copy -> stateid , & res -> write_res .stateid , NFS4_STATEID_SIZE );
167
192
init_completion (& copy -> completion );
168
- copy -> parent_state = ctx -> state ;
193
+ copy -> parent_dst_state = dst_ctx -> state ;
194
+ copy -> parent_src_state = src_ctx -> state ;
169
195
170
- list_add_tail (& copy -> copies , & server -> ss_copies );
171
- spin_unlock (& server -> nfs_client -> cl_lock );
196
+ list_add_tail (& copy -> copies , & dst_server -> ss_copies );
197
+ spin_unlock (& dst_server -> nfs_client -> cl_lock );
198
+
199
+ if (dst_server != src_server ) {
200
+ spin_lock (& src_server -> nfs_client -> cl_lock );
201
+ list_add_tail (& copy -> src_copies , & src_server -> ss_copies );
202
+ spin_unlock (& src_server -> nfs_client -> cl_lock );
203
+ }
172
204
173
205
status = wait_for_completion_interruptible (& copy -> completion );
174
- spin_lock (& server -> nfs_client -> cl_lock );
206
+ spin_lock (& dst_server -> nfs_client -> cl_lock );
175
207
list_del_init (& copy -> copies );
176
- spin_unlock (& server -> nfs_client -> cl_lock );
208
+ spin_unlock (& dst_server -> nfs_client -> cl_lock );
209
+ if (dst_server != src_server ) {
210
+ spin_lock (& src_server -> nfs_client -> cl_lock );
211
+ list_del_init (& copy -> src_copies );
212
+ spin_unlock (& src_server -> nfs_client -> cl_lock );
213
+ }
177
214
if (status == - ERESTARTSYS ) {
178
215
goto out_cancel ;
179
- } else if (copy -> flags ) {
216
+ } else if (copy -> flags || copy -> error == NFS4ERR_PARTNER_NO_AUTH ) {
180
217
status = - EAGAIN ;
218
+ * restart = true;
181
219
goto out_cancel ;
182
220
}
183
221
out :
184
222
res -> write_res .count = copy -> count ;
185
223
memcpy (& res -> write_res .verifier , & copy -> verf , sizeof (copy -> verf ));
186
224
status = - copy -> error ;
187
225
226
+ out_free :
188
227
kfree (copy );
189
228
return status ;
190
229
out_cancel :
191
230
nfs42_do_offload_cancel_async (dst , & copy -> stateid );
192
- kfree (copy );
193
- return status ;
231
+ if (!nfs42_files_from_same_server (src , dst ))
232
+ nfs42_do_offload_cancel_async (src , src_stateid );
233
+ goto out_free ;
194
234
}
195
235
196
236
static int process_copy_commit (struct file * dst , loff_t pos_dst ,
@@ -222,25 +262,34 @@ static ssize_t _nfs42_proc_copy(struct file *src,
222
262
struct file * dst ,
223
263
struct nfs_lock_context * dst_lock ,
224
264
struct nfs42_copy_args * args ,
225
- struct nfs42_copy_res * res )
265
+ struct nfs42_copy_res * res ,
266
+ struct nl4_server * nss ,
267
+ nfs4_stateid * cnr_stateid ,
268
+ bool * restart )
226
269
{
227
270
struct rpc_message msg = {
228
271
.rpc_proc = & nfs4_procedures [NFSPROC4_CLNT_COPY ],
229
272
.rpc_argp = args ,
230
273
.rpc_resp = res ,
231
274
};
232
275
struct inode * dst_inode = file_inode (dst );
233
- struct nfs_server * server = NFS_SERVER (dst_inode );
276
+ struct inode * src_inode = file_inode (src );
277
+ struct nfs_server * dst_server = NFS_SERVER (dst_inode );
278
+ struct nfs_server * src_server = NFS_SERVER (src_inode );
234
279
loff_t pos_src = args -> src_pos ;
235
280
loff_t pos_dst = args -> dst_pos ;
236
281
size_t count = args -> count ;
237
282
ssize_t status ;
238
283
239
- status = nfs4_set_rw_stateid (& args -> src_stateid , src_lock -> open_context ,
240
- src_lock , FMODE_READ );
241
- if (status )
242
- return status ;
243
-
284
+ if (nss ) {
285
+ args -> cp_src = nss ;
286
+ nfs4_stateid_copy (& args -> src_stateid , cnr_stateid );
287
+ } else {
288
+ status = nfs4_set_rw_stateid (& args -> src_stateid ,
289
+ src_lock -> open_context , src_lock , FMODE_READ );
290
+ if (status )
291
+ return status ;
292
+ }
244
293
status = nfs_filemap_write_and_wait_range (file_inode (src )-> i_mapping ,
245
294
pos_src , pos_src + (loff_t )count - 1 );
246
295
if (status )
@@ -262,13 +311,15 @@ static ssize_t _nfs42_proc_copy(struct file *src,
262
311
if (!res -> commit_res .verf )
263
312
return - ENOMEM ;
264
313
}
314
+ set_bit (NFS_CLNT_SRC_SSC_COPY_STATE ,
315
+ & src_lock -> open_context -> state -> flags );
265
316
set_bit (NFS_CLNT_DST_SSC_COPY_STATE ,
266
317
& dst_lock -> open_context -> state -> flags );
267
318
268
- status = nfs4_call_sync (server -> client , server , & msg ,
319
+ status = nfs4_call_sync (dst_server -> client , dst_server , & msg ,
269
320
& args -> seq_args , & res -> seq_res , 0 );
270
321
if (status == - ENOTSUPP )
271
- server -> caps &= ~NFS_CAP_COPY ;
322
+ dst_server -> caps &= ~NFS_CAP_COPY ;
272
323
if (status )
273
324
goto out ;
274
325
@@ -280,8 +331,8 @@ static ssize_t _nfs42_proc_copy(struct file *src,
280
331
}
281
332
282
333
if (!res -> synchronous ) {
283
- status = handle_async_copy (res , server , src , dst ,
284
- & args -> src_stateid );
334
+ status = handle_async_copy (res , dst_server , src_server , src ,
335
+ dst , & args -> src_stateid , restart );
285
336
if (status )
286
337
return status ;
287
338
}
@@ -304,8 +355,9 @@ static ssize_t _nfs42_proc_copy(struct file *src,
304
355
}
305
356
306
357
ssize_t nfs42_proc_copy (struct file * src , loff_t pos_src ,
307
- struct file * dst , loff_t pos_dst ,
308
- size_t count )
358
+ struct file * dst , loff_t pos_dst , size_t count ,
359
+ struct nl4_server * nss ,
360
+ nfs4_stateid * cnr_stateid , bool sync )
309
361
{
310
362
struct nfs_server * server = NFS_SERVER (file_inode (dst ));
311
363
struct nfs_lock_context * src_lock ;
@@ -316,7 +368,7 @@ ssize_t nfs42_proc_copy(struct file *src, loff_t pos_src,
316
368
.dst_fh = NFS_FH (file_inode (dst )),
317
369
.dst_pos = pos_dst ,
318
370
.count = count ,
319
- .sync = false ,
371
+ .sync = sync ,
320
372
};
321
373
struct nfs42_copy_res res ;
322
374
struct nfs4_exception src_exception = {
@@ -328,6 +380,7 @@ ssize_t nfs42_proc_copy(struct file *src, loff_t pos_src,
328
380
.stateid = & args .dst_stateid ,
329
381
};
330
382
ssize_t err , err2 ;
383
+ bool restart = false;
331
384
332
385
src_lock = nfs_get_lock_context (nfs_file_open_context (src ));
333
386
if (IS_ERR (src_lock ))
@@ -347,21 +400,33 @@ ssize_t nfs42_proc_copy(struct file *src, loff_t pos_src,
347
400
inode_lock (file_inode (dst ));
348
401
err = _nfs42_proc_copy (src , src_lock ,
349
402
dst , dst_lock ,
350
- & args , & res );
403
+ & args , & res ,
404
+ nss , cnr_stateid , & restart );
351
405
inode_unlock (file_inode (dst ));
352
406
353
407
if (err >= 0 )
354
408
break ;
355
- if (err == - ENOTSUPP ) {
409
+ if (err == - ENOTSUPP &&
410
+ nfs42_files_from_same_server (src , dst )) {
356
411
err = - EOPNOTSUPP ;
357
412
break ;
358
413
} else if (err == - EAGAIN ) {
359
- dst_exception .retry = 1 ;
360
- continue ;
414
+ if (!restart ) {
415
+ dst_exception .retry = 1 ;
416
+ continue ;
417
+ }
418
+ break ;
361
419
} else if (err == - NFS4ERR_OFFLOAD_NO_REQS && !args .sync ) {
362
420
args .sync = true;
363
421
dst_exception .retry = 1 ;
364
422
continue ;
423
+ } else if ((err == - ESTALE ||
424
+ err == - NFS4ERR_OFFLOAD_DENIED ||
425
+ err == - ENOTSUPP ) &&
426
+ !nfs42_files_from_same_server (src , dst )) {
427
+ nfs42_do_offload_cancel_async (src , & args .src_stateid );
428
+ err = - EOPNOTSUPP ;
429
+ break ;
365
430
}
366
431
367
432
err2 = nfs4_handle_exception (server , err , & src_exception );
@@ -459,6 +524,76 @@ static int nfs42_do_offload_cancel_async(struct file *dst,
459
524
return status ;
460
525
}
461
526
527
+ int _nfs42_proc_copy_notify (struct file * src , struct file * dst ,
528
+ struct nfs42_copy_notify_args * args ,
529
+ struct nfs42_copy_notify_res * res )
530
+ {
531
+ struct nfs_server * src_server = NFS_SERVER (file_inode (src ));
532
+ struct rpc_message msg = {
533
+ .rpc_proc = & nfs4_procedures [NFSPROC4_CLNT_COPY_NOTIFY ],
534
+ .rpc_argp = args ,
535
+ .rpc_resp = res ,
536
+ };
537
+ int status ;
538
+ struct nfs_open_context * ctx ;
539
+ struct nfs_lock_context * l_ctx ;
540
+
541
+ ctx = get_nfs_open_context (nfs_file_open_context (src ));
542
+ l_ctx = nfs_get_lock_context (ctx );
543
+ if (IS_ERR (l_ctx ))
544
+ return PTR_ERR (l_ctx );
545
+
546
+ status = nfs4_set_rw_stateid (& args -> cna_src_stateid , ctx , l_ctx ,
547
+ FMODE_READ );
548
+ nfs_put_lock_context (l_ctx );
549
+ if (status )
550
+ return status ;
551
+
552
+ status = nfs4_call_sync (src_server -> client , src_server , & msg ,
553
+ & args -> cna_seq_args , & res -> cnr_seq_res , 0 );
554
+ if (status == - ENOTSUPP )
555
+ src_server -> caps &= ~NFS_CAP_COPY_NOTIFY ;
556
+
557
+ put_nfs_open_context (nfs_file_open_context (src ));
558
+ return status ;
559
+ }
560
+
561
+ int nfs42_proc_copy_notify (struct file * src , struct file * dst ,
562
+ struct nfs42_copy_notify_res * res )
563
+ {
564
+ struct nfs_server * src_server = NFS_SERVER (file_inode (src ));
565
+ struct nfs42_copy_notify_args * args ;
566
+ struct nfs4_exception exception = {
567
+ .inode = file_inode (src ),
568
+ };
569
+ int status ;
570
+
571
+ if (!(src_server -> caps & NFS_CAP_COPY_NOTIFY ))
572
+ return - EOPNOTSUPP ;
573
+
574
+ args = kzalloc (sizeof (struct nfs42_copy_notify_args ), GFP_NOFS );
575
+ if (args == NULL )
576
+ return - ENOMEM ;
577
+
578
+ args -> cna_src_fh = NFS_FH (file_inode (src )),
579
+ args -> cna_dst .nl4_type = NL4_NETADDR ;
580
+ nfs42_set_netaddr (dst , & args -> cna_dst .u .nl4_addr );
581
+ exception .stateid = & args -> cna_src_stateid ;
582
+
583
+ do {
584
+ status = _nfs42_proc_copy_notify (src , dst , args , res );
585
+ if (status == - ENOTSUPP ) {
586
+ status = - EOPNOTSUPP ;
587
+ goto out ;
588
+ }
589
+ status = nfs4_handle_exception (src_server , status , & exception );
590
+ } while (exception .retry );
591
+
592
+ out :
593
+ kfree (args );
594
+ return status ;
595
+ }
596
+
462
597
static loff_t _nfs42_proc_llseek (struct file * filep ,
463
598
struct nfs_lock_context * lock , loff_t offset , int whence )
464
599
{
0 commit comments