@@ -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