Commit 603c5fc5 authored by Tigran Mkrtchyan's avatar Tigran Mkrtchyan
Browse files

pnfs: add layoutStats and layoutError methods to device manager

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
parent cb0eaf97
......@@ -27,8 +27,10 @@ import java.util.Set;
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;
......@@ -91,6 +93,24 @@ public interface NFSv41DeviceManager {
*/
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.
......
......@@ -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;
......@@ -34,8 +36,15 @@ public class OperationLAYOUTERROR extends AbstractNFSv4Operation {
}
@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;
}
}
......@@ -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;
......@@ -34,8 +36,15 @@ public class OperationLAYOUTSTATS extends AbstractNFSv4Operation {
}
@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;
}
}
......@@ -94,8 +94,12 @@ import java.util.ArrayList;
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;
......@@ -623,6 +627,42 @@ public class CompoundBuilder {
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);
......
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());
}
}
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());
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment