@@ -207,7 +207,8 @@ static struct inode *nfs_layout_find_inode(struct nfs_client *clp,
207207 * Enforce RFC5661 section 12.5.5.2.1. (Layout Recall and Return Sequencing)
208208 */
209209static u32 pnfs_check_callback_stateid (struct pnfs_layout_hdr * lo ,
210- const nfs4_stateid * new )
210+ const nfs4_stateid * new ,
211+ struct cb_process_state * cps )
211212{
212213 u32 oldseq , newseq ;
213214
@@ -221,28 +222,29 @@ static u32 pnfs_check_callback_stateid(struct pnfs_layout_hdr *lo,
221222
222223 newseq = be32_to_cpu (new -> seqid );
223224 /* Are we already in a layout recall situation? */
224- if (test_bit (NFS_LAYOUT_RETURN_REQUESTED , & lo -> plh_flags ) &&
225- lo -> plh_return_seq != 0 ) {
226- if (newseq < lo -> plh_return_seq )
227- return NFS4ERR_OLD_STATEID ;
228- if (newseq > lo -> plh_return_seq )
229- return NFS4ERR_DELAY ;
230- goto out ;
231- }
225+ if (test_bit (NFS_LAYOUT_RETURN , & lo -> plh_flags ))
226+ return NFS4ERR_DELAY ;
232227
233- /* Check that the stateid matches what we think it should be. */
228+ /*
229+ * Check that the stateid matches what we think it should be.
230+ * Note that if the server sent us a list of referring calls,
231+ * and we know that those have completed, then we trust the
232+ * stateid argument is correct.
233+ */
234234 oldseq = be32_to_cpu (lo -> plh_stateid .seqid );
235- if (newseq > oldseq + 1 )
235+ if (newseq > oldseq + 1 && ! cps -> referring_calls )
236236 return NFS4ERR_DELAY ;
237+
237238 /* Crazy server! */
238239 if (newseq <= oldseq )
239240 return NFS4ERR_OLD_STATEID ;
240- out :
241+
241242 return NFS_OK ;
242243}
243244
244245static u32 initiate_file_draining (struct nfs_client * clp ,
245- struct cb_layoutrecallargs * args )
246+ struct cb_layoutrecallargs * args ,
247+ struct cb_process_state * cps )
246248{
247249 struct inode * ino ;
248250 struct pnfs_layout_hdr * lo ;
@@ -266,7 +268,7 @@ static u32 initiate_file_draining(struct nfs_client *clp,
266268 goto out ;
267269 }
268270 pnfs_get_layout_hdr (lo );
269- rv = pnfs_check_callback_stateid (lo , & args -> cbl_stateid );
271+ rv = pnfs_check_callback_stateid (lo , & args -> cbl_stateid , cps );
270272 if (rv != NFS_OK )
271273 goto unlock ;
272274
@@ -326,10 +328,11 @@ static u32 initiate_bulk_draining(struct nfs_client *clp,
326328}
327329
328330static u32 do_callback_layoutrecall (struct nfs_client * clp ,
329- struct cb_layoutrecallargs * args )
331+ struct cb_layoutrecallargs * args ,
332+ struct cb_process_state * cps )
330333{
331334 if (args -> cbl_recall_type == RETURN_FILE )
332- return initiate_file_draining (clp , args );
335+ return initiate_file_draining (clp , args , cps );
333336 return initiate_bulk_draining (clp , args );
334337}
335338
@@ -340,19 +343,20 @@ __be32 nfs4_callback_layoutrecall(void *argp, void *resp,
340343 u32 res = NFS4ERR_OP_NOT_IN_SESSION ;
341344
342345 if (cps -> clp )
343- res = do_callback_layoutrecall (cps -> clp , args );
346+ res = do_callback_layoutrecall (cps -> clp , args , cps );
344347 return cpu_to_be32 (res );
345348}
346349
347- static void pnfs_recall_all_layouts (struct nfs_client * clp )
350+ static void pnfs_recall_all_layouts (struct nfs_client * clp ,
351+ struct cb_process_state * cps )
348352{
349353 struct cb_layoutrecallargs args ;
350354
351355 /* Pretend we got a CB_LAYOUTRECALL(ALL) */
352356 memset (& args , 0 , sizeof (args ));
353357 args .cbl_recall_type = RETURN_ALL ;
354358 /* FIXME we ignore errors, what should we do? */
355- do_callback_layoutrecall (clp , & args );
359+ do_callback_layoutrecall (clp , & args , cps );
356360}
357361
358362__be32 nfs4_callback_devicenotify (void * argp , void * resp ,
@@ -622,7 +626,7 @@ __be32 nfs4_callback_recallany(void *argp, void *resp,
622626 nfs_expire_unused_delegation_types (cps -> clp , flags );
623627
624628 if (args -> craa_type_mask & BIT (RCA4_TYPE_MASK_FILE_LAYOUT ))
625- pnfs_recall_all_layouts (cps -> clp );
629+ pnfs_recall_all_layouts (cps -> clp , cps );
626630
627631 if (args -> craa_type_mask & BIT (PNFS_FF_RCA4_TYPE_MASK_READ )) {
628632 set_bit (NFS4CLNT_RECALL_ANY_LAYOUT_READ , & cps -> clp -> cl_state );
0 commit comments