Skip to content

Commit 7bbc22a

Browse files
committed
file tracker: improve spec compatibility in open_downgrade
Motivation: rfc 8881 requires that open_downgrade accepts only modes that was specified by one of the opens. IOW: open(R) + open(W) can be downgraded to R or W. open(RW) + open(R) can NOT be downgraded to W, as open(W) was never seen https://datatracker.ietf.org/doc/html/rfc8881#section-18.18.3 Modification: In FileTracker a bitmap introduced to that keeps track of seen opens: bit 1: OPEN4_SHARE_ACCESS_READ bit 2: OPEN4_SHARE_ACCESS_WRITE bit 3: OPEN4_SHARE_ACCESS_BOTH Result: better compatibility with spec Acked-by: Lea Morschel Target: master
1 parent 46e4185 commit 7bbc22a

File tree

1 file changed

+44
-0
lines changed

1 file changed

+44
-0
lines changed

core/src/main/java/org/dcache/nfs/v4/FileTracker.java

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,37 @@ private static class OpenState {
6262
private int shareAccess;
6363
private int shareDeny;
6464

65+
/**
66+
* Bitmask of share_access that have been seen by the open.
67+
* The bit position represents seen open mode.
68+
* <pre>
69+
* 1: OPEN4_SHARE_ACCESS_READ
70+
* 2: OPEN4_SHARE_ACCESS_WRITE
71+
* 3: OPEN4_SHARE_ACCESS_BOTH
72+
* </pre>
73+
*/
74+
private int shareAccessSeen;
75+
76+
/**
77+
* Bitmask of share_deny that have been seen by the open.
78+
* The bit position represents seen open mode.
79+
* <pre>
80+
* 1: OPEN4_SHARE_ACCESS_READ
81+
* 2: OPEN4_SHARE_ACCESS_WRITE
82+
* 3: OPEN4_SHARE_ACCESS_BOTH
83+
* </pre>
84+
*/
85+
private int shareDenySeen;
86+
6587
public OpenState(NFS4Client client, StateOwner owner, stateid4 stateid, int shareAccess, int shareDeny) {
6688
this.client = client;
6789
this.stateid = stateid;
6890
this.shareAccess = shareAccess;
6991
this.shareDeny = shareDeny;
92+
93+
// initialize seen bitmaps with the current share modes, if set
94+
this.shareAccessSeen = shareAccess == 0 ? 0 : 1 << (shareAccess & nfs4_prot.OPEN4_SHARE_ACCESS_BOTH) - 1;
95+
this.shareDenySeen = shareDeny == 0 ? 0 : 1 << (shareDeny & nfs4_prot.OPEN4_SHARE_DENY_BOTH) - 1;
7096
this.owner = owner;
7197
}
7298

@@ -133,6 +159,14 @@ public stateid4 addOpen(NFS4Client client, StateOwner owner, Inode inode, int sh
133159
os.getOwner().equals(owner)) {
134160
os.shareAccess |= shareAccess;
135161
os.shareDeny |= shareDeny;
162+
163+
if (shareAccess != 0) {
164+
os.shareAccessSeen |= 1 << ((shareAccess & nfs4_prot.OPEN4_SHARE_ACCESS_BOTH) - 1);
165+
}
166+
if (shareDeny != 0) {
167+
os.shareDenySeen |= 1 << ((shareDeny & nfs4_prot.OPEN4_SHARE_ACCESS_BOTH) - 1);
168+
}
169+
136170
os.stateid.seqid++;
137171
//we need to return copy to avoid modification by concurrent opens
138172
return new stateid4(os.stateid.other, os.stateid.seqid);
@@ -177,6 +211,7 @@ public stateid4 downgradeOpen(NFS4Client client, stateid4 stateid, Inode inode,
177211
.findFirst()
178212
.orElseThrow(BadStateidException::new);
179213

214+
180215
if ((os.shareAccess & shareAccess) != shareAccess) {
181216
throw new InvalException("downgrading to not owned share_access mode");
182217
}
@@ -185,6 +220,15 @@ public stateid4 downgradeOpen(NFS4Client client, stateid4 stateid, Inode inode,
185220
throw new InvalException("downgrading to not owned share_deny mode");
186221
}
187222

223+
// check if we are downgrading to a mode that has been seen
224+
if ((os.shareAccessSeen & (1 << (shareAccess - 1))) == 0) {
225+
throw new InvalException("downgrading to not seen share_access mode");
226+
}
227+
228+
if ((os.shareDenySeen & (1 << (shareDeny - 1))) != 0) {
229+
throw new InvalException("downgrading to not seen share_deny mode");
230+
}
231+
188232
os.shareAccess = shareAccess;
189233
os.shareDeny = shareDeny;
190234

0 commit comments

Comments
 (0)