diff --git a/core/src/main/java/org/dcache/nfs/v4/OperationCLOSE.java b/core/src/main/java/org/dcache/nfs/v4/OperationCLOSE.java index 9e98d9ff3..4f356b315 100644 --- a/core/src/main/java/org/dcache/nfs/v4/OperationCLOSE.java +++ b/core/src/main/java/org/dcache/nfs/v4/OperationCLOSE.java @@ -47,6 +47,7 @@ public void process(CompoundContext context, nfs_resop4 result) Inode inode = context.currentInode(); stateid4 stateid = Stateids.getCurrentStateidIfNeeded(context, _args.opclose.open_stateid); + context.getFs().close(inode, stateid); NFS4Client client; if (context.getMinorversion() > 0) { client = context.getSession().getClient(); diff --git a/core/src/main/java/org/dcache/nfs/v4/OperationOPEN.java b/core/src/main/java/org/dcache/nfs/v4/OperationOPEN.java index 14d7ea3cc..8a422e52d 100644 --- a/core/src/main/java/org/dcache/nfs/v4/OperationOPEN.java +++ b/core/src/main/java/org/dcache/nfs/v4/OperationOPEN.java @@ -206,6 +206,7 @@ public void process(CompoundContext context, nfs_resop4 result) throws ChimeraNF } context.currentInode(inode); + context.getFs().open(inode, this.getAccessMode(_args.opopen.share_access), result.opopen.resok4.stateid); break; case open_claim_type4.CLAIM_PREVIOUS: @@ -279,11 +280,10 @@ public void process(CompoundContext context, nfs_resop4 result) throws ChimeraNF } - private void checkCanAccess(CompoundContext context, Inode inode, uint32_t share_access) throws IOException { - - int accessMode; + private int getAccessMode(final uint32_t share_access) throws IOException { + final int accessMode; - switch (share_access.value & ~nfs4_prot.OPEN4_SHARE_ACCESS_WANT_DELEG_MASK) { + switch(share_access.value & ~nfs4_prot.OPEN4_SHARE_ACCESS_WANT_DELEG_MASK) { case nfs4_prot.OPEN4_SHARE_ACCESS_READ: accessMode = nfs4_prot.ACCESS4_READ; break; @@ -296,6 +296,13 @@ private void checkCanAccess(CompoundContext context, Inode inode, uint32_t share default: throw new InvalException("Invalid share_access mode: " + share_access.value); } + return accessMode; + } + + + private void checkCanAccess(CompoundContext context, Inode inode, uint32_t share_access) throws IOException { + + int accessMode = getAccessMode(share_access); if (context.getFs().access(inode, accessMode) != accessMode) { throw new AccessException(); diff --git a/core/src/main/java/org/dcache/nfs/vfs/PseudoFs.java b/core/src/main/java/org/dcache/nfs/vfs/PseudoFs.java index b0182b0d1..2b4176e62 100644 --- a/core/src/main/java/org/dcache/nfs/vfs/PseudoFs.java +++ b/core/src/main/java/org/dcache/nfs/vfs/PseudoFs.java @@ -37,6 +37,7 @@ import org.dcache.nfs.status.*; import org.dcache.nfs.v4.acl.Acls; import org.dcache.nfs.v4.xdr.acemask4; +import org.dcache.nfs.v4.xdr.stateid4; import org.dcache.oncrpc4j.rpc.RpcCall; import static org.dcache.nfs.v4.xdr.nfs4_prot.*; @@ -183,6 +184,16 @@ public Inode create(Inode parent, Stat.Type type, String path, Subject subject, return pushExportIndex(parent, _inner.create(parent, type, path, effectiveSubject, mode)); } + @Override + public void open(Inode inode, int mode, stateid4 stateid) throws IOException { + + } + + @Override + public void close(Inode inode, stateid4 stateid) throws IOException { + + } + @Override public Inode getRootInode() throws IOException { /* diff --git a/core/src/main/java/org/dcache/nfs/vfs/VfsCache.java b/core/src/main/java/org/dcache/nfs/vfs/VfsCache.java index 97641633a..b46077e28 100644 --- a/core/src/main/java/org/dcache/nfs/vfs/VfsCache.java +++ b/core/src/main/java/org/dcache/nfs/vfs/VfsCache.java @@ -34,6 +34,7 @@ import javax.security.auth.Subject; import org.dcache.nfs.util.GuavaCacheMXBeanImpl; import org.dcache.nfs.util.Opaque; +import org.dcache.nfs.v4.xdr.stateid4; import static java.util.Objects.requireNonNull; @@ -172,6 +173,16 @@ public Inode create(Inode parent, Stat.Type type, String path, Subject subject, return inode; } + @Override + public void open(Inode inode, int mode, stateid4 stateid) throws IOException { + _inner.open(inode, mode, stateid); + } + + @Override + public void close(Inode inode, stateid4 stateid) throws IOException { + _inner.close(inode, stateid); + } + @Override public Stat getattr(Inode inode) throws IOException { return statFromCacheOrLoad(inode); diff --git a/core/src/main/java/org/dcache/nfs/vfs/VirtualFileSystem.java b/core/src/main/java/org/dcache/nfs/vfs/VirtualFileSystem.java index f4cae7d5c..cebe6c3cb 100644 --- a/core/src/main/java/org/dcache/nfs/vfs/VirtualFileSystem.java +++ b/core/src/main/java/org/dcache/nfs/vfs/VirtualFileSystem.java @@ -25,6 +25,7 @@ import org.dcache.nfs.v4.NfsIdMapping; import org.dcache.nfs.v4.xdr.nfsace4; import org.dcache.nfs.v4.xdr.stable_how4; +import org.dcache.nfs.v4.xdr.stateid4; /** * An interface to file system. @@ -69,6 +70,23 @@ public interface VirtualFileSystem { */ Inode create(Inode parent, Stat.Type type, String name, Subject subject, int mode) throws IOException; + /** + * Notify about file handle opened + * @param inode inode of the object + * @param mode Access mode bitmask like ACCESS4_READ + * @param stateid Open state id + * @throws IOException + */ + void open(Inode inode, int mode, stateid4 stateid) throws IOException; + + /** + * Notify about file handle closed + * @param inode inode of the object + * @param stateid Open state id + * @throws IOException + */ + void close(Inode inode, stateid4 stateid) throws IOException; + /** * Get file system's usage information. * diff --git a/core/src/test/java/org/dcache/nfs/v4/NFS4ClientTest.java b/core/src/test/java/org/dcache/nfs/v4/NFS4ClientTest.java index 953904fb3..2aef19abf 100644 --- a/core/src/test/java/org/dcache/nfs/v4/NFS4ClientTest.java +++ b/core/src/test/java/org/dcache/nfs/v4/NFS4ClientTest.java @@ -30,6 +30,7 @@ import org.dcache.nfs.v4.xdr.nfs_opnum4; import org.dcache.nfs.v4.xdr.nfs_resop4; import org.dcache.nfs.v4.xdr.stateid4; +import org.dcache.nfs.vfs.VirtualFileSystem; import org.junit.Before; import org.junit.Test; @@ -73,6 +74,7 @@ public void testStateCleanOnOpenCloseV41() throws Exception { OperationCLOSE CLOSE = new OperationCLOSE(close_args); result = nfs_resop4.resopFor(nfs_opnum4.OP_CLOSE); context = new CompoundContextBuilder() + .withFs(mock(VirtualFileSystem.class)) .withStateHandler(stateHandler) .withMinorversion(1) .withDeviceManager(mock(NFSv41DeviceManager.class)) @@ -100,6 +102,7 @@ public void testStateCleanOnOpenCloseV40() throws Exception { OperationCLOSE CLOSE = new OperationCLOSE(close_args); result = nfs_resop4.resopFor(nfs_opnum4.OP_CLOSE); context = new CompoundContextBuilder() + .withFs(mock(VirtualFileSystem.class)) .withStateHandler(stateHandler) .withMinorversion(0) .withCall(generateRpcCall()) diff --git a/core/src/test/java/org/dcache/nfs/vfs/DummyVFS.java b/core/src/test/java/org/dcache/nfs/vfs/DummyVFS.java index 83fe2576e..d2d110948 100644 --- a/core/src/test/java/org/dcache/nfs/vfs/DummyVFS.java +++ b/core/src/test/java/org/dcache/nfs/vfs/DummyVFS.java @@ -22,6 +22,7 @@ import com.google.common.jimfs.Configuration; import com.google.common.jimfs.Jimfs; import com.google.common.primitives.Longs; +import org.dcache.nfs.v4.xdr.stateid4; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -208,6 +209,16 @@ public Inode create(Inode parent, Type type, String path, Subject subject, int m return toFileHandle(newInodeNumber); } + @Override + public void open(Inode inode, int mode, stateid4 stateid) throws IOException { + + } + + @Override + public void close(Inode inode, stateid4 stateid) throws IOException { + + } + @Override public FsStat getFsStat() throws IOException { FileStore store = Files.getFileStore(_root);