Skip to content

Commit 304c91b

Browse files
committed
Attempt to auto-retry on sense
1 parent f63f50b commit 304c91b

13 files changed

+248
-22
lines changed

Library/DiscUtils.Iscsi/BasicHeaderSegment.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public int ReadFrom(ReadOnlySpan<byte> buffer)
4444
OpCode = (OpCode)(buffer[0] & 0x3F);
4545
FinalPdu = (buffer[1] & 0x80) != 0;
4646
TotalAhsLength = buffer[4];
47-
DataSegmentLength = EndianUtilities.ToInt32BigEndian(buffer.Slice(4)) & 0x00FFFFFF;
47+
DataSegmentLength = (buffer[5] << 16) | (buffer[6] << 8) | buffer[7];
4848
InitiatorTaskTag = EndianUtilities.ToUInt32BigEndian(buffer.Slice(16));
4949
return 48;
5050
}

Library/DiscUtils.Iscsi/Connection.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,12 @@ public int Send(ScsiCommand cmd, ReadOnlySpan<byte> outBuffer, Span<byte> inBuff
201201
{
202202
var senseLength = EndianUtilities.ToUInt16BigEndian(pdu.ContentData, 0);
203203
var senseData = pdu.ContentData.AsSpan(2, senseLength).ToArray();
204+
205+
//if (ScsiSenseParser.TryParse(senseData, out var sense) && sense.IndicatesRetryRequired)
206+
//{
207+
// return Send(cmd, outBuffer, inBuffer);
208+
//}
209+
204210
throw new ScsiCommandException(resp.Status, senseData);
205211
}
206212

Library/DiscUtils.Iscsi/Disk.cs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ namespace DiscUtils.Iscsi;
3434
public class Disk : VirtualDisk
3535
{
3636
private readonly FileAccess _access;
37-
private LunCapacity _capacity;
3837
private readonly long _lun;
3938
private readonly Session _session;
4039

@@ -54,9 +53,9 @@ public override int BlockSize
5453
{
5554
get
5655
{
57-
_capacity ??= _session.GetCapacity(_lun);
56+
_stream ??= new DiskStream(_session, _lun, _access);
5857

59-
return _capacity.BlockSize;
58+
return _stream.BlockSize;
6059
}
6160
}
6261

@@ -72,9 +71,9 @@ public override long Capacity
7271
{
7372
get
7473
{
75-
_capacity ??= _session.GetCapacity(_lun);
74+
_stream ??= new DiskStream(_session, _lun, _access);
7675

77-
return _capacity.BlockSize * _capacity.LogicalBlockCount;
76+
return _stream.Length;
7877
}
7978
}
8079

Library/DiscUtils.Iscsi/DiskStream.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public DiskStream(Session session, long lun, FileAccess access)
4545
_session = session;
4646
_lun = lun;
4747

48-
var capacity = session.GetCapacity(lun);
48+
var capacity = session.ReadCapacity16(lun);
4949
_blockSize = capacity.BlockSize;
5050
_length = capacity.LogicalBlockCount * capacity.BlockSize;
5151
CanWrite = access != FileAccess.Read;
@@ -61,6 +61,8 @@ public DiskStream(Session session, long lun, FileAccess access)
6161
public override IEnumerable<StreamExtent> Extents
6262
=> SingleValueEnumerable.Get(new StreamExtent(0, _length));
6363

64+
public int BlockSize => _blockSize;
65+
6466
public override long Length => _length;
6567

6668
public override long Position

Library/DiscUtils.Iscsi/ScsiInquiryCommand.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public override int ReadFrom(ReadOnlySpan<byte> buffer)
5959
public override void WriteTo(Span<byte> buffer)
6060
{
6161
buffer.Slice(0, 10).Clear();
62-
buffer[0] = 0x12; // OpCode
62+
buffer[0] = (byte)ScsiOpCode.Inquiry; // OpCode
6363
buffer[1] = (byte)(_askForPage ? 0x01 : 0x00);
6464
buffer[2] = _pageCode;
6565
EndianUtilities.WriteBytesBigEndian((ushort)_expected, buffer.Slice(3));
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
5+
namespace DiscUtils.Iscsi;
6+
7+
#pragma warning disable CA1069 // Enums values should not be duplicated
8+
9+
public enum ScsiOpServiceAction : byte
10+
{
11+
// Common service actions for 0x9E
12+
ReadCapacity16 = 0x10, // SA=0x10 for opcode 0x9E
13+
GetLBAStatus = 0x12,
14+
Read16 = 0x88, // effectively READ(16)
15+
Write16 = 0x8A, // effectively WRITE(16)
16+
}
17+
18+
/// <summary>
19+
/// SCSI Command Descriptor Block (CDB) opcodes from SPC, SBC, SSC, MMC.
20+
/// Only the commonly used standard commands are included.
21+
/// </summary>
22+
public enum ScsiOpCode : byte
23+
{
24+
// -------------------------
25+
// 6-byte CDB commands
26+
// -------------------------
27+
TestUnitReady = 0x00,
28+
RezeroUnit = 0x01, // legacy
29+
RequestSense = 0x03,
30+
FormatUnit = 0x04,
31+
Read6 = 0x08,
32+
Write6 = 0x0A,
33+
Seek6 = 0x0B,
34+
Inquiry = 0x12,
35+
ModeSelect6 = 0x15,
36+
ModeSense6 = 0x1A,
37+
StartStopUnit = 0x1B,
38+
ReceiveDiagnosticResults = 0x1C,
39+
SendDiagnostic = 0x1D,
40+
PreventAllowMediumRemoval = 0x1E,
41+
42+
// -------------------------
43+
// 10-byte CDB commands
44+
// -------------------------
45+
ReadCapacity10 = 0x25,
46+
Read10 = 0x28,
47+
Write10 = 0x2A,
48+
Seek10 = 0x2B,
49+
WriteVerify10 = 0x2E,
50+
Verify10 = 0x2F,
51+
SynchronizeCache10 = 0x35,
52+
WriteBuffer = 0x3B,
53+
ReadBuffer = 0x3C,
54+
ReadLong10 = 0x3E,
55+
WriteLong10 = 0x3F,
56+
57+
// -------------------------
58+
// Service Action opcodes (0x9E, 0x9F)
59+
// -------------------------
60+
ServiceActionIn = 0x9E,
61+
ServiceActionOut = 0x9F,
62+
63+
// -------------------------
64+
// 12-byte CDB commands
65+
// -------------------------
66+
Read12 = 0xA8,
67+
Write12 = 0xAA,
68+
WriteVerify12 = 0xAE,
69+
Verify12 = 0xAF,
70+
71+
// -------------------------
72+
// 16-byte CDB commands
73+
// -------------------------
74+
Read16 = 0x88,
75+
Write16 = 0x8A,
76+
Verify16 = 0x8F,
77+
WriteVerify16 = 0x8E,
78+
SynchronizeCache16 = 0x91,
79+
WriteAtomic16 = 0x9C,
80+
81+
// -------------------------
82+
// SPC (control / management)
83+
// -------------------------
84+
ReportLuns = 0xA0,
85+
ReportSupportedOpCodes = 0xA3,
86+
ReportSupportedTaskManagement = 0xA4,
87+
ReportIdentifiers = 0xA1,
88+
PersistentReserveIn = 0x5E,
89+
PersistentReserveOut = 0x5F,
90+
ReadAttribute = 0x8C,
91+
WriteAttribute = 0x8D,
92+
ModeSelect10 = 0x55,
93+
ModeSense10 = 0x5A,
94+
95+
// -------------------------
96+
// Block Commands (SBC)
97+
// -------------------------
98+
ReadDefectData10 = 0x37,
99+
ReadDefectData12 = 0xB7,
100+
CompareAndWrite = 0x89,
101+
OrWrite = 0x8B,
102+
WriteSame10 = 0x41,
103+
WriteSame16 = 0x93,
104+
WriteStream16 = 0x9B,
105+
ReadStream16 = 0x9A,
106+
107+
// -------------------------
108+
// Synchronization / cache
109+
// -------------------------
110+
SynchronizeCache = 0x35,
111+
112+
// -------------------------
113+
// MMC (optical media)
114+
// -------------------------
115+
ReadTocPmaAtip = 0x43,
116+
ReadDiscInformation = 0x51,
117+
ReadTrackInformation = 0x52,
118+
ReserveTrack = 0x53,
119+
SendOpcInformation = 0x54,
120+
121+
// -------------------------
122+
// SSC (tape devices)
123+
// -------------------------
124+
Locate = 0x2B,
125+
ReadPosition = 0x34,
126+
LoadUnload = 0x1B,
127+
Space = 0x11,
128+
WriteFilemarks = 0x10
129+
}

Library/DiscUtils.Iscsi/ScsiReadCapacityCommand.cs renamed to Library/DiscUtils.Iscsi/ScsiReadCapacity10Command.cs

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,17 @@
2020
// DEALINGS IN THE SOFTWARE.
2121
//
2222

23+
using DiscUtils.Streams;
2324
using System;
2425

2526
namespace DiscUtils.Iscsi;
2627

27-
internal class ScsiReadCapacityCommand : ScsiCommand
28+
internal class ScsiReadCapacity10Command : ScsiCommand
2829
{
2930
public const int ResponseDataLength = 8;
3031

31-
public ScsiReadCapacityCommand(ulong targetLun)
32-
: base(targetLun) {}
32+
public ScsiReadCapacity10Command(ulong targetLun)
33+
: base(targetLun) { }
3334

3435
public override int Size => 10;
3536

@@ -43,6 +44,32 @@ public override int ReadFrom(ReadOnlySpan<byte> buffer)
4344
public override void WriteTo(Span<byte> buffer)
4445
{
4546
buffer.Slice(0, 10).Clear();
46-
buffer[0] = 0x25; // OpCode
47+
buffer[0] = (byte)ScsiOpCode.ReadCapacity10; // OpCode
4748
}
48-
}
49+
}
50+
51+
internal class ScsiReadCapacity16Command : ScsiCommand
52+
{
53+
public const int ResponseDataLength = 32;
54+
55+
public ScsiReadCapacity16Command(ulong targetLun)
56+
: base(targetLun) { }
57+
58+
public override int Size => 16;
59+
60+
public override TaskAttributes TaskAttributes => TaskAttributes.Simple;
61+
62+
public override int ReadFrom(ReadOnlySpan<byte> buffer)
63+
{
64+
throw new NotImplementedException();
65+
}
66+
67+
public override void WriteTo(Span<byte> buffer)
68+
{
69+
buffer.Slice(0, 16).Clear();
70+
buffer[0] = (byte)ScsiOpCode.ServiceActionIn; // OpCode
71+
buffer[1] = (byte)ScsiOpServiceAction.ReadCapacity16; // OpCode
72+
EndianUtilities.WriteBytesBigEndian(32, buffer.Slice(10));
73+
}
74+
}
75+

Library/DiscUtils.Iscsi/ScsiReadCapacityResponse.cs renamed to Library/DiscUtils.Iscsi/ScsiReadCapacity10Response.cs

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
namespace DiscUtils.Iscsi;
2626

27-
internal class ScsiReadCapacityResponse : ScsiResponse
27+
internal class ScsiReadCapacity10Response : ScsiResponse
2828
{
2929
private bool _truncated;
3030

@@ -47,4 +47,30 @@ public override void ReadFrom(byte[] buffer, int offset, int count)
4747
NumLogicalBlocks = EndianUtilities.ToUInt32BigEndian(buffer, offset);
4848
LogicalBlockSize = EndianUtilities.ToUInt32BigEndian(buffer, offset + 4);
4949
}
50-
}
50+
}
51+
52+
internal class ScsiReadCapacity16Response : ScsiResponse
53+
{
54+
private bool _truncated;
55+
56+
public uint LogicalBlockSize { get; private set; }
57+
58+
public override uint NeededDataLength => 12;
59+
60+
public long NumLogicalBlocks { get; private set; }
61+
62+
public override bool Truncated => _truncated;
63+
64+
public override void ReadFrom(byte[] buffer, int offset, int count)
65+
{
66+
if (count < 8)
67+
{
68+
_truncated = true;
69+
return;
70+
}
71+
72+
NumLogicalBlocks = EndianUtilities.ToInt64BigEndian(buffer, offset);
73+
LogicalBlockSize = EndianUtilities.ToUInt32BigEndian(buffer, offset + 8);
74+
}
75+
}
76+

Library/DiscUtils.Iscsi/ScsiReadCommand.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public override int ReadFrom(ReadOnlySpan<byte> buffer)
4646

4747
public override void WriteTo(Span<byte> buffer)
4848
{
49-
buffer[0] = 0x28; // OpCode: READ(10)
49+
buffer[0] = (byte)ScsiOpCode.Read10; // OpCode: READ(10)
5050
buffer[1] = 0;
5151
EndianUtilities.WriteBytesBigEndian(_logicalBlockAddress, buffer.Slice(2));
5252
buffer[6] = 0;

Library/DiscUtils.Iscsi/ScsiReportLunsCommand.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public override int ReadFrom(ReadOnlySpan<byte> buffer)
4646

4747
public override void WriteTo(Span<byte> buffer)
4848
{
49-
buffer[0] = 0xA0;
49+
buffer[0] = (byte)ScsiOpCode.ReportLuns;
5050
buffer[1] = 0; // Reserved
5151
buffer[2] = 0; // Report Type = 0
5252
buffer[3] = 0; // Reserved

0 commit comments

Comments
 (0)