Skip to content

Commit 80cf524

Browse files
committed
core: Make support for "stateless stateids" configurable.
Commit c8d57f2 introduced support for stateless stateids. This may not be desirable, as this breaks the inherent sequence order of stateids, adding extra requirements for logging/journaling and advanced VirtualFileSystems. Moreover, this may leave the macOS NFSv4.0 client in a state where all stateids remain "stateless". Make support for this feature configurable by adding a flag to NFSv4StateHandler and move the support logic into NFSv4StateHandler. Also fix OperationREAD and OperationWRITE to get the NFSv4StateHandler only once per call from the context. Signed-off-by: Christian Kohlschütter <christian@kohlschutter.com>
1 parent c8d57f2 commit 80cf524

File tree

3 files changed

+49
-8
lines changed

3 files changed

+49
-8
lines changed

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

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ public class NFSv4StateHandler {
109109
*/
110110
private final Clock _clock;
111111

112+
private boolean supportStateless = true;
113+
112114
public NFSv4StateHandler() {
113115
this(Duration.ofSeconds(NFSv4Defaults.NFS4_LEASE_TIME), 0, new EphemeralClientRecoveryStore());
114116
}
@@ -500,4 +502,40 @@ public Duration getLeaseTime() {
500502
return _leaseTime;
501503
}
502504

505+
/**
506+
* Checks if stateless stateids are supported.
507+
*
508+
* @return true if supported.
509+
*/
510+
public boolean isSupportStateless() {
511+
return supportStateless;
512+
}
513+
514+
/**
515+
* Enables/disables support for stateless stateids.
516+
*
517+
* @param supportStateless flag.
518+
*/
519+
public void setSupportStateless(boolean supportStateless) {
520+
this.supportStateless = supportStateless;
521+
}
522+
523+
/**
524+
* Checks if the given stateid is stateless. If so but stateless stateids are not supported, a
525+
* {@link BadStateidException} is thrown.
526+
*
527+
* @param stateid The stateid.
528+
* @return {@code true} if stateless.
529+
* @throws BadStateidException if stateless but not supported.
530+
* @see #setSupportStateless(boolean)
531+
*/
532+
public boolean checkStatelessAndSupported(stateid4 stateid) throws BadStateidException {
533+
if (Stateids.isStateLess(stateid)) {
534+
if (supportStateless) {
535+
return true;
536+
}
537+
throw new BadStateidException();
538+
}
539+
return false;
540+
}
503541
}

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

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,9 @@ public void process(CompoundContext context, nfs_resop4 result) throws IOExcepti
4949

5050
stateid4 stateid = Stateids.getCurrentStateidIfNeeded(context, _args.opread.stateid);
5151
var inode = context.currentInode();
52-
if (Stateids.isStateLess(stateid)) {
52+
53+
NFSv4StateHandler stateHandler = context.getStateHandler();
54+
if (stateHandler.checkStatelessAndSupported(stateid)) {
5355
// Anonymous access as per RFC 7530
5456
// https://datatracker.ietf.org/doc/html/rfc7530#section-9.1.4.3
5557
// we only check file access rights.
@@ -64,13 +66,13 @@ public void process(CompoundContext context, nfs_resop4 result) throws IOExcepti
6466
*
6567
* With introduction of sessions in v4.1 update of the lease time done through SEQUENCE operations.
6668
*/
67-
context.getStateHandler().updateClientLeaseTime(stateid);
68-
client = context.getStateHandler().getClientIdByStateId(stateid);
69+
stateHandler.updateClientLeaseTime(stateid);
70+
client = stateHandler.getClientIdByStateId(stateid);
6971
} else {
7072
client = context.getSession().getClient();
7173
}
7274

73-
int shareAccess = context.getStateHandler().getFileTracker().getShareAccess(client, inode, stateid);
75+
int shareAccess = stateHandler.getFileTracker().getShareAccess(client, inode, stateid);
7476
if ((shareAccess & nfs4_prot.OPEN4_SHARE_ACCESS_READ) == 0) {
7577
throw new OpenModeException("Invalid open mode");
7678
}

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ public void process(CompoundContext context, nfs_resop4 result) throws ChimeraNF
6868
}
6969

7070
var inode = context.currentInode();
71-
if (Stateids.isStateLess(stateid)) {
71+
NFSv4StateHandler stateHandler = context.getStateHandler();
72+
if (stateHandler.checkStatelessAndSupported(stateid)) {
7273
// Anonymous access as per RFC 7530
7374
// https://datatracker.ietf.org/doc/html/rfc7530#section-9.1.4.3
7475
// we only check file access rights.
@@ -85,13 +86,13 @@ public void process(CompoundContext context, nfs_resop4 result) throws ChimeraNF
8586
*
8687
* With introduction of sessions in v4.1 update of the lease time done through SEQUENCE operations.
8788
*/
88-
context.getStateHandler().updateClientLeaseTime(stateid);
89-
client = context.getStateHandler().getClientIdByStateId(stateid);
89+
stateHandler.updateClientLeaseTime(stateid);
90+
client = stateHandler.getClientIdByStateId(stateid);
9091
} else {
9192
client = context.getSession().getClient();
9293
}
9394

94-
int shareAccess = context.getStateHandler().getFileTracker().getShareAccess(client, inode, stateid);
95+
int shareAccess = stateHandler.getFileTracker().getShareAccess(client, inode, stateid);
9596
if ((shareAccess & nfs4_prot.OPEN4_SHARE_ACCESS_WRITE) == 0) {
9697
throw new OpenModeException("Invalid open mode");
9798
}

0 commit comments

Comments
 (0)