Skip to content

Commit

Permalink
pnfs: add layoutStats and layoutError methods to device manager
Browse files Browse the repository at this point in the history
Motivation:
When client want's to inform metadata server about errors or statistics
in its interactions with the layout, then LAYOUTERROR and LAYOUTSTATS
operations are called. This information have to be propagated to the pnfs
device manager.

Modification:
Add NFSv41DeviceManager#layoutError and NFSv41DeviceManager#layoutStats
methods. Update corresponding operations to pass requests to device manager.

Result:
Layout usage errors and statistics available to the pnfs device manager.

Acked-by: Paul Millar
Target: master
  • Loading branch information
kofemann committed Jul 10, 2019
1 parent cb0eaf9 commit 603c5fc
Show file tree
Hide file tree
Showing 6 changed files with 243 additions and 4 deletions.
20 changes: 20 additions & 0 deletions core/src/main/java/org/dcache/nfs/v4/NFSv41DeviceManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@
import org.dcache.nfs.v4.xdr.GETDEVICEINFO4args;
import org.dcache.nfs.v4.xdr.GETDEVICELIST4args;
import org.dcache.nfs.v4.xdr.LAYOUTCOMMIT4args;
import org.dcache.nfs.v4.xdr.LAYOUTERROR4args;
import org.dcache.nfs.v4.xdr.LAYOUTGET4args;
import org.dcache.nfs.v4.xdr.LAYOUTRETURN4args;
import org.dcache.nfs.v4.xdr.LAYOUTSTATS4args;
import org.dcache.nfs.v4.xdr.device_addr4;
import org.dcache.nfs.v4.xdr.deviceid4;
import org.dcache.nfs.v4.xdr.layouttype4;
Expand Down Expand Up @@ -91,6 +93,24 @@ public Layout layoutGet(CompoundContext context, LAYOUTGET4args args)
*/
public OptionalLong layoutCommit(CompoundContext context, LAYOUTCOMMIT4args args) throws IOException;

/**
* Inform about layout usage.
*
* @param contex the context of the nfs request.
* @param args layout stats operation arguments.
* @throws IOException if NFS error or some other I/O error occurs.
*/
public void layoutStats(CompoundContext contex, LAYOUTSTATS4args args) throws IOException;

/**
* Inform about errors in interactions with the layout.
*
* @param contex the context of the nfs request.
* @param args layout error operation arguments.
* @throws IOException if NFS error or some other I/O error occurs.
*/
public void layoutError(CompoundContext contex, LAYOUTERROR4args args) throws IOException;

/**
* Returns the array of layout types supported by this device manager.
* @return supported layout types.
Expand Down
13 changes: 11 additions & 2 deletions core/src/main/java/org/dcache/nfs/v4/OperationLAYOUTERROR.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@
*/
package org.dcache.nfs.v4;

import java.io.IOException;
import org.dcache.nfs.nfsstat;
import org.dcache.nfs.status.NotSuppException;
import org.dcache.nfs.v4.xdr.nfs_argop4;
import org.dcache.nfs.v4.xdr.nfs_opnum4;
import org.dcache.nfs.v4.xdr.nfs_resop4;
Expand All @@ -34,8 +36,15 @@ public OperationLAYOUTERROR(nfs_argop4 args) {
}

@Override
public void process(CompoundContext context, nfs_resop4 result) {
result.oplayouterror.status = nfsstat.NFSERR_NOTSUPP;
public void process(CompoundContext context, nfs_resop4 result) throws IOException {

final NFSv41DeviceManager pnfsDeviceManager = context
.getDeviceManager()
.orElseThrow(() -> new NotSuppException("pNFS device manager not configured"));

pnfsDeviceManager.layoutError(context, _args.oplayouterror);

result.oplayouterror.status = nfsstat.NFS_OK;
}

}
13 changes: 11 additions & 2 deletions core/src/main/java/org/dcache/nfs/v4/OperationLAYOUTSTATS.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@
*/
package org.dcache.nfs.v4;

import java.io.IOException;
import org.dcache.nfs.nfsstat;
import org.dcache.nfs.status.NotSuppException;
import org.dcache.nfs.v4.xdr.nfs_argop4;
import org.dcache.nfs.v4.xdr.nfs_opnum4;
import org.dcache.nfs.v4.xdr.nfs_resop4;
Expand All @@ -34,8 +36,15 @@ public OperationLAYOUTSTATS(nfs_argop4 args) {
}

@Override
public void process(CompoundContext context, nfs_resop4 result) {
result.oplayoutstats.status = nfsstat.NFSERR_NOTSUPP;
public void process(CompoundContext context, nfs_resop4 result) throws IOException {

final NFSv41DeviceManager pnfsDeviceManager = context
.getDeviceManager()
.orElseThrow(() -> new NotSuppException("pNFS device manager not configured"));

pnfsDeviceManager.layoutStats(context, _args.oplayoutstats);

result.oplayoutstats.status = nfsstat.NFS_OK;
}

}
40 changes: 40 additions & 0 deletions core/src/main/java/org/dcache/nfs/v4/client/CompoundBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,12 @@
import java.util.List;
import java.util.OptionalLong;
import org.dcache.nfs.v4.xdr.LAYOUTCOMMIT4args;
import org.dcache.nfs.v4.xdr.LAYOUTERROR4args;
import org.dcache.nfs.v4.xdr.LAYOUTSTATS4args;
import org.dcache.nfs.v4.xdr.LOCKU4args;
import org.dcache.nfs.v4.xdr.RECLAIM_COMPLETE4args;
import org.dcache.nfs.v4.xdr.device_error4;
import org.dcache.nfs.v4.xdr.io_info4;
import org.dcache.nfs.v4.xdr.layoutupdate4;
import org.dcache.nfs.v4.xdr.newoffset4;
import org.dcache.nfs.v4.xdr.newtime4;
Expand Down Expand Up @@ -623,6 +627,42 @@ public CompoundBuilder withLayoutcommit(long offset, long length,
return this;
}

public CompoundBuilder withLayoutStats(long offset, long length, stateid4 stateid,
io_info4 readInfo, io_info4 writeInfo, deviceid4 deviceid,
layoutupdate4 layoutupdate) {

nfs_argop4 op = new nfs_argop4();
op.argop = nfs_opnum4.OP_LAYOUTSTATS;
op.oplayoutstats = new LAYOUTSTATS4args();

op.oplayoutstats.lsa_offset = new offset4(offset);
op.oplayoutstats.lsa_length = new length4(length);
op.oplayoutstats.lsa_stateid = stateid;
op.oplayoutstats.lsa_read = readInfo;
op.oplayoutstats.lsa_write = writeInfo;
op.oplayoutstats.lsa_deviceid = deviceid;
op.oplayoutstats.lsa_layoutupdate = layoutupdate;

ops.add(op);
return this;
}

public CompoundBuilder withLayoutError(long offset, long length, stateid4 stateid,
device_error4[] errors) {

nfs_argop4 op = new nfs_argop4();
op.argop = nfs_opnum4.OP_LAYOUTERROR;
op.oplayouterror = new LAYOUTERROR4args();

op.oplayouterror.lea_offset = new offset4(offset);
op.oplayouterror.lea_length = new length4(length);
op.oplayouterror.lea_stateid = stateid;
op.oplayouterror.lea_errors = errors;

ops.add(op);
return this;
}

public COMPOUND4args build() {
final COMPOUND4args compound4args = new COMPOUND4args();
compound4args.tag = new utf8str_cs(tag);
Expand Down
71 changes: 71 additions & 0 deletions core/src/test/java/org/dcache/nfs/v4/OperationLAYOUTERRORTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package org.dcache.nfs.v4;

import java.io.IOException;
import org.dcache.nfs.status.NotSuppException;
import org.dcache.nfs.v4.client.CompoundBuilder;
import org.dcache.nfs.v4.xdr.COMPOUND4args;
import org.dcache.nfs.v4.xdr.device_error4;
import org.dcache.nfs.vfs.VirtualFileSystem;
import org.junit.Test;
import org.junit.Before;

import static org.dcache.nfs.v4.NfsTestUtils.execute;
import static org.dcache.nfs.v4.NfsTestUtils.generateRpcCall;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;


public class OperationLAYOUTERRORTest {

private NFSv4StateHandler sh;
private VirtualFileSystem vfs;
private NFSv41DeviceManager dm;

@Before
public void setUp() throws Exception {
sh = new NFSv4StateHandler();
vfs = mock(VirtualFileSystem.class);
dm = mock(NFSv41DeviceManager.class);
}

@Test(expected = NotSuppException.class)
public void testNoPnfsConfigured() throws IOException {

COMPOUND4args layoutError = new CompoundBuilder()
.withLayoutError(0, 100, Stateids.OneStateId(), new device_error4[]{})
.build();

CompoundContext context = new CompoundContextBuilder()
.withStateHandler(sh)
.withFs(vfs)
.withMinorversion(1)
.withCall(generateRpcCall())
.build();

execute(context, layoutError);
}

@Test
public void testStatsPropagation() throws IOException {

COMPOUND4args layoutError = new CompoundBuilder()
.withLayoutError(0, 100, Stateids.OneStateId(), new device_error4[]{})
.build();

CompoundContext context = new CompoundContextBuilder()
.withStateHandler(sh)
.withFs(vfs)
.withDeviceManager(dm)
.withMinorversion(1)
.withCall(generateRpcCall())
.build();

execute(context, layoutError);

verify(dm).layoutError(any(), any());
}

}
90 changes: 90 additions & 0 deletions core/src/test/java/org/dcache/nfs/v4/OperationLAYOUTSTATSTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package org.dcache.nfs.v4;

import java.io.IOException;
import org.dcache.nfs.status.NotSuppException;
import org.dcache.nfs.v4.client.CompoundBuilder;
import org.dcache.nfs.v4.xdr.COMPOUND4args;
import org.dcache.nfs.v4.xdr.deviceid4;
import org.dcache.nfs.v4.xdr.io_info4;
import org.dcache.nfs.v4.xdr.layouttype4;
import org.dcache.nfs.v4.xdr.layoutupdate4;
import org.dcache.nfs.vfs.VirtualFileSystem;
import org.junit.Test;
import org.junit.Before;

import static org.dcache.nfs.v4.NfsTestUtils.execute;
import static org.dcache.nfs.v4.NfsTestUtils.generateRpcCall;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

public class OperationLAYOUTSTATSTest {

private NFSv4StateHandler sh;
private VirtualFileSystem vfs;
private NFSv41DeviceManager dm;

@Before
public void setUp() throws Exception {
sh = new NFSv4StateHandler();
vfs = mock(VirtualFileSystem.class);
dm = mock(NFSv41DeviceManager.class);
}

@Test(expected = NotSuppException.class)
public void testNoPnfsConfigured() throws IOException {

io_info4 ioInfo = new io_info4();
ioInfo.ii_bytes = 0;
ioInfo.ii_count = 0;

deviceid4 deviceId = new deviceid4(new byte[] {0x1});
layoutupdate4 update = new layoutupdate4();
update.lou_type = layouttype4.LAYOUT4_BLOCK_VOLUME.getValue();
update.lou_body = new byte[0];

COMPOUND4args layoutStats = new CompoundBuilder()
.withLayoutStats(0, 100, Stateids.OneStateId(), ioInfo, ioInfo, deviceId, update)
.build();

CompoundContext context = new CompoundContextBuilder()
.withStateHandler(sh)
.withFs(vfs)
.withMinorversion(1)
.withCall(generateRpcCall())
.build();

execute(context, layoutStats);
}

@Test
public void testStatsPropagation() throws IOException {

io_info4 ioInfo = new io_info4();
ioInfo.ii_bytes = 0;
ioInfo.ii_count = 0;

deviceid4 deviceId = new deviceid4(new byte[]{0x1});
layoutupdate4 update = new layoutupdate4();
update.lou_type = layouttype4.LAYOUT4_BLOCK_VOLUME.getValue();
update.lou_body = new byte[0];

COMPOUND4args layoutStats = new CompoundBuilder()
.withLayoutStats(0, 100, Stateids.OneStateId(), ioInfo, ioInfo, deviceId, update)
.build();

CompoundContext context = new CompoundContextBuilder()
.withStateHandler(sh)
.withFs(vfs)
.withDeviceManager(dm)
.withMinorversion(1)
.withCall(generateRpcCall())
.build();

execute(context, layoutStats);
verify(dm).layoutStats(any(), any());
}

}

0 comments on commit 603c5fc

Please sign in to comment.