Files
frostbyte/user/disktest.c
T

132 lines
4.3 KiB
C

#include "ulib.h"
#include "fs.h"
static const char* diskPath = "/dev/disk0";
static void printLong(const char* label, long value)
{
print(label);
printDec(value);
print("\n");
}
static int bytesEqual(const char* a, const char* b, unsigned long n)
{
for (unsigned long i = 0; i < n; i++)
if (a[i] != b[i])
return 0;
return 1;
}
int main(void)
{
print("disktest: start, pid=");
printDec(userGetpid());
print("\n");
FbStat st;
if (userStat(diskPath, &st) != 0) {
print("disktest: stat failed\n");
return 1;
}
printLong("disktest: disk size bytes=", (long)st.size);
if (st.size < 64 * 1024) {
print("disktest: FAIL disk suspiciously small\n");
return 1;
}
int fd = (int)userOpen(diskPath, oReadWrite);
if (fd < 0) {
print("disktest: open failed\n");
return 1;
}
long end = userLseek(fd, 0, seekEnd);
printLong("disktest: seekEnd=", end);
if (end != (long)st.size) {
print("disktest: FAIL seekEnd does not match stat size\n");
return 1;
}
/* Unaligned write/read spanning a 512-byte sector boundary: byte offset
50*512 + 500 leaves 12 bytes in sector 50 and spills 8 bytes into
sector 51, exercising the read-modify-write path in vfs.c blockDevRead
/blockDevWrite rather than a single aligned sector transfer. */
const long straddleOffset = 50L * 512 + 500;
const char* straddlePayload = "ABCDEFGHIJKLMNOPQRST"; /* 20 bytes */
const unsigned long straddleLen = 20;
if (userLseek(fd, straddleOffset, seekSet) != straddleOffset) {
print("disktest: FAIL lseek to straddle offset\n");
return 1;
}
long written = userWrite(fd, straddlePayload, straddleLen);
printLong("disktest: straddle write bytes=", written);
if (written != (long)straddleLen) {
print("disktest: FAIL short straddle write\n");
return 1;
}
if (userLseek(fd, straddleOffset, seekSet) != straddleOffset) {
print("disktest: FAIL lseek back to straddle offset\n");
return 1;
}
char straddleBack[20];
long straddleRead = userRead(fd, straddleBack, straddleLen);
if (straddleRead != (long)straddleLen || !bytesEqual(straddleBack, straddlePayload, straddleLen)) {
print("disktest: FAIL straddle round-trip mismatch\n");
return 1;
}
print("disktest: straddle round-trip ok\n");
/* Aligned full-sector write/read at a disjoint offset (sector 55),
proving the non-read-modify-write path also works. */
const long alignedOffset = 55L * 512;
char alignedOut[512];
for (int i = 0; i < 512; i++)
alignedOut[i] = (char)('a' + (i % 26));
if (userLseek(fd, alignedOffset, seekSet) != alignedOffset) {
print("disktest: FAIL lseek to aligned offset\n");
return 1;
}
if (userWrite(fd, alignedOut, sizeof(alignedOut)) != (long)sizeof(alignedOut)) {
print("disktest: FAIL aligned sector write\n");
return 1;
}
if (userLseek(fd, alignedOffset, seekSet) != alignedOffset) {
print("disktest: FAIL lseek back to aligned offset\n");
return 1;
}
char alignedIn[512];
if (userRead(fd, alignedIn, sizeof(alignedIn)) != (long)sizeof(alignedIn) ||
!bytesEqual(alignedIn, alignedOut, sizeof(alignedOut))) {
print("disktest: FAIL aligned sector round-trip mismatch\n");
return 1;
}
print("disktest: aligned sector round-trip ok\n");
/* Overwrite proves the second write actually lands on disk, not just in
a stale in-memory copy: reading back must see the newest data. */
if (userLseek(fd, alignedOffset, seekSet) != alignedOffset)
return 1;
char overwrite[512];
for (int i = 0; i < 512; i++)
overwrite[i] = (char)('A' + (i % 26));
userWrite(fd, overwrite, sizeof(overwrite));
if (userLseek(fd, alignedOffset, seekSet) != alignedOffset)
return 1;
char reread[512];
userRead(fd, reread, sizeof(reread));
if (!bytesEqual(reread, overwrite, sizeof(overwrite)) || bytesEqual(reread, alignedOut, sizeof(alignedOut))) {
print("disktest: FAIL overwrite not reflected\n");
return 1;
}
print("disktest: overwrite round-trip ok\n");
userClose(fd);
print("disktest: done\n");
return 0;
}