@@ -153,22 +153,26 @@ int nfs42_proc_deallocate(struct file *filep, loff_t offset, loff_t len)
153
153
}
154
154
155
155
static int handle_async_copy (struct nfs42_copy_res * res ,
156
- struct nfs_server * server ,
156
+ struct nfs_server * dst_server ,
157
+ struct nfs_server * src_server ,
157
158
struct file * src ,
158
159
struct file * dst ,
159
- nfs4_stateid * src_stateid )
160
+ nfs4_stateid * src_stateid ,
161
+ bool * restart )
160
162
{
161
163
struct nfs4_copy_state * copy , * tmp_copy ;
162
164
int status = NFS4_OK ;
163
165
bool found_pending = false;
164
- 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 );
165
168
166
169
copy = kzalloc (sizeof (struct nfs4_copy_state ), GFP_NOFS );
167
170
if (!copy )
168
171
return - ENOMEM ;
169
172
170
- spin_lock (& server -> nfs_client -> cl_lock );
171
- 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 ,
172
176
copies ) {
173
177
if (memcmp (& res -> write_res .stateid , & tmp_copy -> stateid ,
174
178
NFS4_STATEID_SIZE ))
@@ -178,27 +182,40 @@ static int handle_async_copy(struct nfs42_copy_res *res,
178
182
break ;
179
183
}
180
184
if (found_pending ) {
181
- spin_unlock (& server -> nfs_client -> cl_lock );
185
+ spin_unlock (& dst_server -> nfs_client -> cl_lock );
182
186
kfree (copy );
183
187
copy = tmp_copy ;
184
188
goto out ;
185
189
}
186
190
187
191
memcpy (& copy -> stateid , & res -> write_res .stateid , NFS4_STATEID_SIZE );
188
192
init_completion (& copy -> completion );
189
- copy -> parent_state = ctx -> state ;
193
+ copy -> parent_dst_state = dst_ctx -> state ;
194
+ copy -> parent_src_state = src_ctx -> state ;
195
+
196
+ list_add_tail (& copy -> copies , & dst_server -> ss_copies );
197
+ spin_unlock (& dst_server -> nfs_client -> cl_lock );
190
198
191
- list_add_tail (& copy -> copies , & server -> ss_copies );
192
- spin_unlock (& server -> nfs_client -> cl_lock );
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
+ }
193
204
194
205
status = wait_for_completion_interruptible (& copy -> completion );
195
- spin_lock (& server -> nfs_client -> cl_lock );
206
+ spin_lock (& dst_server -> nfs_client -> cl_lock );
196
207
list_del_init (& copy -> copies );
197
- 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
+ }
198
214
if (status == - ERESTARTSYS ) {
199
215
goto out_cancel ;
200
- } else if (copy -> flags ) {
216
+ } else if (copy -> flags || copy -> error == NFS4ERR_PARTNER_NO_AUTH ) {
201
217
status = - EAGAIN ;
218
+ * restart = true;
202
219
goto out_cancel ;
203
220
}
204
221
out :
@@ -247,15 +264,18 @@ static ssize_t _nfs42_proc_copy(struct file *src,
247
264
struct nfs42_copy_args * args ,
248
265
struct nfs42_copy_res * res ,
249
266
struct nl4_server * nss ,
250
- nfs4_stateid * cnr_stateid )
267
+ nfs4_stateid * cnr_stateid ,
268
+ bool * restart )
251
269
{
252
270
struct rpc_message msg = {
253
271
.rpc_proc = & nfs4_procedures [NFSPROC4_CLNT_COPY ],
254
272
.rpc_argp = args ,
255
273
.rpc_resp = res ,
256
274
};
257
275
struct inode * dst_inode = file_inode (dst );
258
- 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 );
259
279
loff_t pos_src = args -> src_pos ;
260
280
loff_t pos_dst = args -> dst_pos ;
261
281
size_t count = args -> count ;
@@ -291,13 +311,15 @@ static ssize_t _nfs42_proc_copy(struct file *src,
291
311
if (!res -> commit_res .verf )
292
312
return - ENOMEM ;
293
313
}
314
+ set_bit (NFS_CLNT_SRC_SSC_COPY_STATE ,
315
+ & src_lock -> open_context -> state -> flags );
294
316
set_bit (NFS_CLNT_DST_SSC_COPY_STATE ,
295
317
& dst_lock -> open_context -> state -> flags );
296
318
297
- status = nfs4_call_sync (server -> client , server , & msg ,
319
+ status = nfs4_call_sync (dst_server -> client , dst_server , & msg ,
298
320
& args -> seq_args , & res -> seq_res , 0 );
299
321
if (status == - ENOTSUPP )
300
- server -> caps &= ~NFS_CAP_COPY ;
322
+ dst_server -> caps &= ~NFS_CAP_COPY ;
301
323
if (status )
302
324
goto out ;
303
325
@@ -309,8 +331,8 @@ static ssize_t _nfs42_proc_copy(struct file *src,
309
331
}
310
332
311
333
if (!res -> synchronous ) {
312
- status = handle_async_copy (res , server , src , dst ,
313
- & args -> src_stateid );
334
+ status = handle_async_copy (res , dst_server , src_server , src ,
335
+ dst , & args -> src_stateid , restart );
314
336
if (status )
315
337
return status ;
316
338
}
@@ -358,6 +380,7 @@ ssize_t nfs42_proc_copy(struct file *src, loff_t pos_src,
358
380
.stateid = & args .dst_stateid ,
359
381
};
360
382
ssize_t err , err2 ;
383
+ bool restart = false;
361
384
362
385
src_lock = nfs_get_lock_context (nfs_file_open_context (src ));
363
386
if (IS_ERR (src_lock ))
@@ -378,7 +401,7 @@ ssize_t nfs42_proc_copy(struct file *src, loff_t pos_src,
378
401
err = _nfs42_proc_copy (src , src_lock ,
379
402
dst , dst_lock ,
380
403
& args , & res ,
381
- nss , cnr_stateid );
404
+ nss , cnr_stateid , & restart );
382
405
inode_unlock (file_inode (dst ));
383
406
384
407
if (err >= 0 )
@@ -388,8 +411,11 @@ ssize_t nfs42_proc_copy(struct file *src, loff_t pos_src,
388
411
err = - EOPNOTSUPP ;
389
412
break ;
390
413
} else if (err == - EAGAIN ) {
391
- dst_exception .retry = 1 ;
392
- continue ;
414
+ if (!restart ) {
415
+ dst_exception .retry = 1 ;
416
+ continue ;
417
+ }
418
+ break ;
393
419
} else if (err == - NFS4ERR_OFFLOAD_NO_REQS && !args .sync ) {
394
420
args .sync = true;
395
421
dst_exception .retry = 1 ;
0 commit comments