@@ -153,22 +153,26 @@ int nfs42_proc_deallocate(struct file *filep, loff_t offset, loff_t len)
153153}
154154
155155static 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 ,
157158 struct file * src ,
158159 struct file * dst ,
159- nfs4_stateid * src_stateid )
160+ nfs4_stateid * src_stateid ,
161+ bool * restart )
160162{
161163 struct nfs4_copy_state * copy , * tmp_copy ;
162164 int status = NFS4_OK ;
163165 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 );
165168
166169 copy = kzalloc (sizeof (struct nfs4_copy_state ), GFP_NOFS );
167170 if (!copy )
168171 return - ENOMEM ;
169172
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 ,
172176 copies ) {
173177 if (memcmp (& res -> write_res .stateid , & tmp_copy -> stateid ,
174178 NFS4_STATEID_SIZE ))
@@ -178,27 +182,40 @@ static int handle_async_copy(struct nfs42_copy_res *res,
178182 break ;
179183 }
180184 if (found_pending ) {
181- spin_unlock (& server -> nfs_client -> cl_lock );
185+ spin_unlock (& dst_server -> nfs_client -> cl_lock );
182186 kfree (copy );
183187 copy = tmp_copy ;
184188 goto out ;
185189 }
186190
187191 memcpy (& copy -> stateid , & res -> write_res .stateid , NFS4_STATEID_SIZE );
188192 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 );
190198
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+ }
193204
194205 status = wait_for_completion_interruptible (& copy -> completion );
195- spin_lock (& server -> nfs_client -> cl_lock );
206+ spin_lock (& dst_server -> nfs_client -> cl_lock );
196207 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+ }
198214 if (status == - ERESTARTSYS ) {
199215 goto out_cancel ;
200- } else if (copy -> flags ) {
216+ } else if (copy -> flags || copy -> error == NFS4ERR_PARTNER_NO_AUTH ) {
201217 status = - EAGAIN ;
218+ * restart = true;
202219 goto out_cancel ;
203220 }
204221out :
@@ -247,15 +264,18 @@ static ssize_t _nfs42_proc_copy(struct file *src,
247264 struct nfs42_copy_args * args ,
248265 struct nfs42_copy_res * res ,
249266 struct nl4_server * nss ,
250- nfs4_stateid * cnr_stateid )
267+ nfs4_stateid * cnr_stateid ,
268+ bool * restart )
251269{
252270 struct rpc_message msg = {
253271 .rpc_proc = & nfs4_procedures [NFSPROC4_CLNT_COPY ],
254272 .rpc_argp = args ,
255273 .rpc_resp = res ,
256274 };
257275 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 );
259279 loff_t pos_src = args -> src_pos ;
260280 loff_t pos_dst = args -> dst_pos ;
261281 size_t count = args -> count ;
@@ -291,13 +311,15 @@ static ssize_t _nfs42_proc_copy(struct file *src,
291311 if (!res -> commit_res .verf )
292312 return - ENOMEM ;
293313 }
314+ set_bit (NFS_CLNT_SRC_SSC_COPY_STATE ,
315+ & src_lock -> open_context -> state -> flags );
294316 set_bit (NFS_CLNT_DST_SSC_COPY_STATE ,
295317 & dst_lock -> open_context -> state -> flags );
296318
297- status = nfs4_call_sync (server -> client , server , & msg ,
319+ status = nfs4_call_sync (dst_server -> client , dst_server , & msg ,
298320 & args -> seq_args , & res -> seq_res , 0 );
299321 if (status == - ENOTSUPP )
300- server -> caps &= ~NFS_CAP_COPY ;
322+ dst_server -> caps &= ~NFS_CAP_COPY ;
301323 if (status )
302324 goto out ;
303325
@@ -309,8 +331,8 @@ static ssize_t _nfs42_proc_copy(struct file *src,
309331 }
310332
311333 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 );
314336 if (status )
315337 return status ;
316338 }
@@ -358,6 +380,7 @@ ssize_t nfs42_proc_copy(struct file *src, loff_t pos_src,
358380 .stateid = & args .dst_stateid ,
359381 };
360382 ssize_t err , err2 ;
383+ bool restart = false;
361384
362385 src_lock = nfs_get_lock_context (nfs_file_open_context (src ));
363386 if (IS_ERR (src_lock ))
@@ -378,7 +401,7 @@ ssize_t nfs42_proc_copy(struct file *src, loff_t pos_src,
378401 err = _nfs42_proc_copy (src , src_lock ,
379402 dst , dst_lock ,
380403 & args , & res ,
381- nss , cnr_stateid );
404+ nss , cnr_stateid , & restart );
382405 inode_unlock (file_inode (dst ));
383406
384407 if (err >= 0 )
@@ -388,8 +411,11 @@ ssize_t nfs42_proc_copy(struct file *src, loff_t pos_src,
388411 err = - EOPNOTSUPP ;
389412 break ;
390413 } else if (err == - EAGAIN ) {
391- dst_exception .retry = 1 ;
392- continue ;
414+ if (!restart ) {
415+ dst_exception .retry = 1 ;
416+ continue ;
417+ }
418+ break ;
393419 } else if (err == - NFS4ERR_OFFLOAD_NO_REQS && !args .sync ) {
394420 args .sync = true;
395421 dst_exception .retry = 1 ;
0 commit comments