@@ -3313,6 +3313,75 @@ nfs4_wait_on_layoutreturn(struct inode *inode, struct rpc_task *task)
3313
3313
return pnfs_wait_on_layoutreturn (inode , task );
3314
3314
}
3315
3315
3316
+ /*
3317
+ * Update the seqid of an open stateid
3318
+ */
3319
+ static void nfs4_sync_open_stateid (nfs4_stateid * dst ,
3320
+ struct nfs4_state * state )
3321
+ {
3322
+ __be32 seqid_open ;
3323
+ u32 dst_seqid ;
3324
+ int seq ;
3325
+
3326
+ for (;;) {
3327
+ if (!nfs4_valid_open_stateid (state ))
3328
+ break ;
3329
+ seq = read_seqbegin (& state -> seqlock );
3330
+ if (!nfs4_state_match_open_stateid_other (state , dst )) {
3331
+ nfs4_stateid_copy (dst , & state -> open_stateid );
3332
+ if (read_seqretry (& state -> seqlock , seq ))
3333
+ continue ;
3334
+ break ;
3335
+ }
3336
+ seqid_open = state -> open_stateid .seqid ;
3337
+ if (read_seqretry (& state -> seqlock , seq ))
3338
+ continue ;
3339
+
3340
+ dst_seqid = be32_to_cpu (dst -> seqid );
3341
+ if ((s32 )(dst_seqid - be32_to_cpu (seqid_open )) < 0 )
3342
+ dst -> seqid = seqid_open ;
3343
+ break ;
3344
+ }
3345
+ }
3346
+
3347
+ /*
3348
+ * Update the seqid of an open stateid after receiving
3349
+ * NFS4ERR_OLD_STATEID
3350
+ */
3351
+ static bool nfs4_refresh_open_old_stateid (nfs4_stateid * dst ,
3352
+ struct nfs4_state * state )
3353
+ {
3354
+ __be32 seqid_open ;
3355
+ u32 dst_seqid ;
3356
+ bool ret ;
3357
+ int seq ;
3358
+
3359
+ for (;;) {
3360
+ ret = false;
3361
+ if (!nfs4_valid_open_stateid (state ))
3362
+ break ;
3363
+ seq = read_seqbegin (& state -> seqlock );
3364
+ if (!nfs4_state_match_open_stateid_other (state , dst )) {
3365
+ if (read_seqretry (& state -> seqlock , seq ))
3366
+ continue ;
3367
+ break ;
3368
+ }
3369
+ seqid_open = state -> open_stateid .seqid ;
3370
+ if (read_seqretry (& state -> seqlock , seq ))
3371
+ continue ;
3372
+
3373
+ dst_seqid = be32_to_cpu (dst -> seqid );
3374
+ if ((s32 )(dst_seqid - be32_to_cpu (seqid_open )) >= 0 )
3375
+ dst -> seqid = cpu_to_be32 (dst_seqid + 1 );
3376
+ else
3377
+ dst -> seqid = seqid_open ;
3378
+ ret = true;
3379
+ break ;
3380
+ }
3381
+
3382
+ return ret ;
3383
+ }
3384
+
3316
3385
struct nfs4_closedata {
3317
3386
struct inode * inode ;
3318
3387
struct nfs4_state * state ;
@@ -3387,7 +3456,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
3387
3456
break ;
3388
3457
case - NFS4ERR_OLD_STATEID :
3389
3458
/* Did we race with OPEN? */
3390
- if (nfs4_refresh_open_stateid (& calldata -> arg .stateid ,
3459
+ if (nfs4_refresh_open_old_stateid (& calldata -> arg .stateid ,
3391
3460
state ))
3392
3461
goto out_restart ;
3393
3462
goto out_release ;
@@ -3456,8 +3525,8 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
3456
3525
} else if (is_rdwr )
3457
3526
calldata -> arg .fmode |= FMODE_READ |FMODE_WRITE ;
3458
3527
3459
- if (! nfs4_valid_open_stateid ( state ) ||
3460
- ! nfs4_refresh_open_stateid ( & calldata -> arg . stateid , state ))
3528
+ nfs4_sync_open_stateid ( & calldata -> arg . stateid , state );
3529
+ if (! nfs4_valid_open_stateid ( state ))
3461
3530
call_close = 0 ;
3462
3531
spin_unlock (& state -> owner -> so_lock );
3463
3532
0 commit comments