@@ -210,4 +210,45 @@ describe('OPEN operation', () => {
210210 expect ( openRes . status ) . toBe ( Nfsv4Stat . NFS4ERR_NOTSUPP ) ;
211211 await stop ( ) ;
212212 } ) ;
213+
214+ test ( 'allows seqid=0 to reset open-owner state after desync' , async ( ) => {
215+ const { client, stop} = await setupNfsClientServerTestbed ( ) ;
216+ const openOwner = nfs . OpenOwner ( BigInt ( 1 ) , new Uint8Array ( [ 1 , 2 , 3 , 4 ] ) ) ;
217+ const claim = nfs . OpenClaimNull ( 'file.txt' ) ;
218+ const openReq1 = nfs . OPEN (
219+ 0 ,
220+ Nfsv4OpenAccess . OPEN4_SHARE_ACCESS_READ ,
221+ Nfsv4OpenDeny . OPEN4_SHARE_DENY_NONE ,
222+ openOwner ,
223+ nfs . OpenHowNoCreate ( ) ,
224+ claim ,
225+ ) ;
226+ const response1 = await client . compound ( [ nfs . PUTROOTFH ( ) , openReq1 ] ) ;
227+ expect ( response1 . status ) . toBe ( Nfsv4Stat . NFS4_OK ) ;
228+ const openRes1 = response1 . resarray [ 1 ] as msg . Nfsv4OpenResponse ;
229+ expect ( openRes1 . status ) . toBe ( Nfsv4Stat . NFS4_OK ) ;
230+ const openReq2 = nfs . OPEN (
231+ 100 ,
232+ Nfsv4OpenAccess . OPEN4_SHARE_ACCESS_READ ,
233+ Nfsv4OpenDeny . OPEN4_SHARE_DENY_NONE ,
234+ openOwner ,
235+ nfs . OpenHowNoCreate ( ) ,
236+ claim ,
237+ ) ;
238+ const response2 = await client . compound ( [ nfs . PUTROOTFH ( ) , openReq2 ] ) ;
239+ const openRes2 = response2 . resarray [ 1 ] as msg . Nfsv4OpenResponse ;
240+ expect ( openRes2 . status ) . toBe ( Nfsv4Stat . NFS4ERR_BAD_SEQID ) ;
241+ const openReq3 = nfs . OPEN (
242+ 0 ,
243+ Nfsv4OpenAccess . OPEN4_SHARE_ACCESS_READ ,
244+ Nfsv4OpenDeny . OPEN4_SHARE_DENY_NONE ,
245+ openOwner ,
246+ nfs . OpenHowNoCreate ( ) ,
247+ claim ,
248+ ) ;
249+ const response3 = await client . compound ( [ nfs . PUTROOTFH ( ) , openReq3 ] ) ;
250+ const openRes3 = response3 . resarray [ 1 ] as msg . Nfsv4OpenResponse ;
251+ expect ( openRes3 . status ) . toBe ( Nfsv4Stat . NFS4_OK ) ;
252+ await stop ( ) ;
253+ } ) ;
213254} ) ;
0 commit comments