test: add more cases for vfsFifoTest
This commit is contained in:
1 parent
3b72ea3aee
commit
6005863c35
1 file changed
+84
@@ -319,3 +319,87 @@ KTEST(sfsBackedFifoReopenAfterCompletedRoundTripGetsFreshWorkingSession)
|
|||||||
int rfd2 = vfsOpen("/mnt/fifoRoundTrip", oReadOnly);
|
int rfd2 = vfsOpen("/mnt/fifoRoundTrip", oReadOnly);
|
||||||
KT_GE(t, rfd2, 0);
|
KT_GE(t, rfd2, 0);
|
||||||
|
|
||||||
|
/* A genuinely fresh pipe reports "try again" here, exactly like a
|
||||||
|
first-ever open -- a stale, no-longer-attached handle would instead
|
||||||
|
report -1 forever for an entirely different reason (pipeAt finding
|
||||||
|
nothing "used" at that slot), which the write assertion below is
|
||||||
|
what actually tells apart from this one. */
|
||||||
|
char probe[4];
|
||||||
|
KT_EQ(t, vfsRead(rfd2, probe, sizeof(probe)), -1);
|
||||||
|
|
||||||
|
int wfd2 = vfsOpen("/mnt/fifoRoundTrip", oWriteOnly);
|
||||||
|
KT_GE(t, wfd2, 0);
|
||||||
|
KT_EQ(t, vfsWrite(wfd2, "two", 3), 3);
|
||||||
|
char second[4];
|
||||||
|
memset(second, 0, sizeof(second));
|
||||||
|
KT_EQ(t, vfsRead(rfd2, second, sizeof(second)), 3);
|
||||||
|
KT_TRUE(t, memcmp(second, "two", 3) == 0);
|
||||||
|
|
||||||
|
vfsClose(rfd2);
|
||||||
|
vfsClose(wfd2);
|
||||||
|
KT_EQ(t, vfsUnlink("/mnt/fifoRoundTrip"), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
KTEST(sfsBackedFifoBindingSurvivesReformatOfAnUnrelatedInode)
|
||||||
|
{
|
||||||
|
/* sfsTest.c's tests each start with their own sfsFormat(), reusing
|
||||||
|
inode numbers dozens of times a boot. A fifo binding left open
|
||||||
|
ACROSS such a reformat (contrived here, but exactly the shape
|
||||||
|
reclaimOpenFds/sched.c would leave behind for a thread that died
|
||||||
|
without closing its fd -- see sched.c) must never let the fresh
|
||||||
|
filesystem's completely unrelated reuse of the same inode number
|
||||||
|
inherit the old, orphaned session. */
|
||||||
|
KT_TRUE(t, sfsFormat());
|
||||||
|
KT_EQ(t, vfsMkfifo("/mnt/fifoGenA"), 0);
|
||||||
|
int32 firstInode = sfsLookup("/fifoGenA");
|
||||||
|
KT_GE(t, firstInode, 0);
|
||||||
|
|
||||||
|
/* Left deliberately open across the reformat below -- an orphaned
|
||||||
|
session, on purpose, is exactly what must NOT leak into the new one. */
|
||||||
|
int staleRfd = vfsOpen("/mnt/fifoGenA", oReadOnly);
|
||||||
|
KT_GE(t, staleRfd, 0);
|
||||||
|
|
||||||
|
/* A full reformat: every old inode number, including firstInode, now
|
||||||
|
means whatever the fresh, empty filesystem below reassigns it to. */
|
||||||
|
KT_TRUE(t, sfsFormat());
|
||||||
|
KT_EQ(t, vfsMkfifo("/mnt/fifoGenA"), 0);
|
||||||
|
int32 secondInode = sfsLookup("/fifoGenA");
|
||||||
|
KT_GE(t, secondInode, 0);
|
||||||
|
/* Deterministic on a freshly formatted, otherwise-empty filesystem:
|
||||||
|
both are the very first entry created after root, so the numbers
|
||||||
|
collide -- exactly the scenario that makes the generation check
|
||||||
|
necessary rather than merely defensive. */
|
||||||
|
KT_EQ(t, secondInode, firstInode);
|
||||||
|
|
||||||
|
int rfd = vfsOpen("/mnt/fifoGenA", oReadOnly);
|
||||||
|
int wfd = vfsOpen("/mnt/fifoGenA", oWriteOnly);
|
||||||
|
KT_GE(t, rfd, 0);
|
||||||
|
KT_GE(t, wfd, 0);
|
||||||
|
KT_EQ(t, vfsWrite(wfd, "new", 3), 3);
|
||||||
|
|
||||||
|
/* The discriminating check: if the binding table wrongly inherited the
|
||||||
|
pre-reformat session (generation check not actually doing its job),
|
||||||
|
staleRfd would be a SECOND reader attached to the very same
|
||||||
|
underlying pipe wfd just wrote into, and -- read before rfd below --
|
||||||
|
would steal the payload meant for the new session's own reader.
|
||||||
|
Correct isolation means staleRfd's pipe never had any writer at all
|
||||||
|
(it only ever attached as a reader), so it must still report "try
|
||||||
|
again", never the new session's bytes. */
|
||||||
|
char stalePeek[4];
|
||||||
|
KT_EQ(t, vfsRead(staleRfd, stalePeek, sizeof(stalePeek)), -1);
|
||||||
|
|
||||||
|
char buffer[4];
|
||||||
|
memset(buffer, 0, sizeof(buffer));
|
||||||
|
KT_EQ(t, vfsRead(rfd, buffer, sizeof(buffer)), 3);
|
||||||
|
KT_TRUE(t, memcmp(buffer, "new", 3) == 0);
|
||||||
|
|
||||||
|
vfsClose(rfd);
|
||||||
|
vfsClose(wfd);
|
||||||
|
/* The orphaned pre-reformat fd is cleaned up here rather than left to
|
||||||
|
leak a pipe.c slot for the rest of the boot -- vfsClose only ever
|
||||||
|
touches pipe.c state (pipeCloseRead), never re-derefs the long-gone
|
||||||
|
inode, so this is safe regardless of what the fresh filesystem did
|
||||||
|
with the number. */
|
||||||
|
vfsClose(staleRfd);
|
||||||
|
vfsUnlink("/mnt/fifoGenA");
|
||||||
|
}
|
||||||
Reference in new issue
Block a user