Skip to content

Commit c95a57f

Browse files
perseantperseant
authored andcommitted
Add test cases to show whether newfs_lfs creates a file system that
fsck_lfs can understand; and whether orphans (files still in use, after removal, at the time of a system crash) are removed at fs mount time.
1 parent bb4f8ba commit c95a57f

6 files changed

Lines changed: 488 additions & 171 deletions

File tree

tests/fs/lfs/Makefile

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
1-
# $NetBSD: Makefile,v 1.3 2020/08/18 03:02:50 perseant Exp $
1+
# $NetBSD: Makefile,v 1.4 2025/10/13 00:44:35 perseant Exp $
22
#
33

44
.include <bsd.own.mk>
55

66
TESTSDIR= ${TESTSBASE}/fs/lfs
77
WARNS= 4
88

9-
TESTS_C= t_pr t_rfw
9+
10+
TESTS_C= t_basic t_orphan t_pr t_rfw
11+
SRCS.t_basic+= util.c t_basic.c
12+
SRCS.t_orphan+= util.c t_orphan.c
13+
SRCS.t_rfw+= util.c t_rfw.c
1014

1115
LDADD+=-lrumpfs_lfs -lrumpfs_ffs # fs drivers
1216
LDADD+=-lrumpdev_disk -lrumpdev # disk device

tests/fs/lfs/t_basic.c

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/* $NetBSD: t_basic.c,v 1.1 2025/10/13 00:44:35 perseant Exp $ */
2+
3+
#include <sys/types.h>
4+
#include <sys/mount.h>
5+
#include <sys/wait.h>
6+
7+
#include <atf-c.h>
8+
#include <ctype.h>
9+
#include <errno.h>
10+
#include <fcntl.h>
11+
#include <limits.h>
12+
#include <stdio.h>
13+
#include <stdlib.h>
14+
#include <unistd.h>
15+
#include <string.h>
16+
17+
#include <rump/rump.h>
18+
#include <rump/rump_syscalls.h>
19+
20+
#include <ufs/ufs/ufsmount.h>
21+
#include <ufs/lfs/lfs.h>
22+
#include <ufs/lfs/lfs_extern.h>
23+
24+
#include "h_macros.h"
25+
#include "util.h"
26+
27+
#define FSSIZE 10000
28+
29+
/* Actually run the test */
30+
void test(int);
31+
32+
ATF_TC(newfs_fsck32);
33+
ATF_TC_HEAD(newfs_fsck32, tc)
34+
{
35+
atf_tc_set_md_var(tc, "descr",
36+
"LFS32 newfs_lfs produces a filesystem that passes fsck_lfs");
37+
atf_tc_set_md_var(tc, "timeout", "20");
38+
}
39+
40+
ATF_TC(newfs_fsck64);
41+
ATF_TC_HEAD(newfs_fsck64, tc)
42+
{
43+
atf_tc_set_md_var(tc, "descr",
44+
"LFS64 newfs_lfs produces a filesystem that passes fsck_lfs");
45+
atf_tc_set_md_var(tc, "timeout", "20");
46+
}
47+
48+
ATF_TC_BODY(newfs_fsck32, tc)
49+
{
50+
test(32);
51+
}
52+
53+
ATF_TC_BODY(newfs_fsck64, tc)
54+
{
55+
test(64);
56+
}
57+
58+
void test(int width)
59+
{
60+
setvbuf(stdout, NULL, _IONBF, 0);
61+
62+
/*
63+
* Initialize.
64+
*/
65+
66+
/* Create image file larger than filesystem */
67+
create_lfs(FSSIZE, FSSIZE, width, 1);
68+
69+
if (fsck())
70+
atf_tc_fail_errno("fsck found errors after first unmount");
71+
}
72+
73+
ATF_TP_ADD_TCS(tp)
74+
{
75+
76+
ATF_TP_ADD_TC(tp, newfs_fsck32);
77+
ATF_TP_ADD_TC(tp, newfs_fsck64);
78+
return atf_no_error();
79+
}

tests/fs/lfs/t_orphan.c

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
/* $NetBSD: t_orphan.c,v 1.1 2025/10/13 00:44:35 perseant Exp $ */
2+
3+
#include <sys/types.h>
4+
#include <sys/mount.h>
5+
#include <sys/wait.h>
6+
7+
#include <atf-c.h>
8+
#include <ctype.h>
9+
#include <errno.h>
10+
#include <fcntl.h>
11+
#include <limits.h>
12+
#include <stdio.h>
13+
#include <stdlib.h>
14+
#include <string.h>
15+
#include <unistd.h>
16+
#include <string.h>
17+
18+
#include <rump/rump.h>
19+
#include <rump/rump_syscalls.h>
20+
21+
#include <ufs/ufs/ufsmount.h>
22+
#include <ufs/lfs/lfs.h>
23+
#include <ufs/lfs/lfs_extern.h>
24+
25+
#include "h_macros.h"
26+
#include "util.h"
27+
28+
/* Debugging conditions */
29+
/* #define FORCE_SUCCESS */ /* Don't actually revert, everything worked */
30+
/* #define USE_DUMPLFS */ /* Dump the filesystem at certain steps */
31+
32+
#define UNCHANGED_CONTROL MP "/3-a-random-file"
33+
#define FSSIZE 10000 /* In sectors */
34+
#define FILE_SIZE 65000 /* In bytes; a few blocks worth */
35+
#define TMPFILE "filehandle"
36+
37+
/* Actually run the test */
38+
void orphan(int);
39+
40+
ATF_TC(orphan32);
41+
ATF_TC_HEAD(orphan32, tc)
42+
{
43+
atf_tc_set_md_var(tc, "descr",
44+
"LFS32 orphan removal");
45+
atf_tc_set_md_var(tc, "timeout", "20");
46+
}
47+
48+
ATF_TC(orphan64);
49+
ATF_TC_HEAD(orphan64, tc)
50+
{
51+
atf_tc_set_md_var(tc, "descr",
52+
"LFS64 orphan removal");
53+
atf_tc_set_md_var(tc, "timeout", "20");
54+
}
55+
56+
ATF_TC_BODY(orphan32, tc)
57+
{
58+
orphan(32);
59+
}
60+
61+
ATF_TC_BODY(orphan64, tc)
62+
{
63+
orphan(64);
64+
}
65+
66+
void orphan(int width)
67+
{
68+
struct ufs_args args;
69+
struct stat statbuf;
70+
int status;
71+
pid_t childpid;
72+
size_t fh_size;
73+
void *fhp;
74+
FILE *fp;
75+
76+
setvbuf(stdout, NULL, _IONBF, 0);
77+
78+
/*
79+
* Initialize.
80+
*/
81+
82+
/* Create image file */
83+
create_lfs(FSSIZE, FSSIZE, width, 0);
84+
85+
/* Prepare to mount */
86+
memset(&args, 0, sizeof args);
87+
args.fspec = __UNCONST(FAKEBLK);
88+
89+
if ((childpid = fork()) == 0) {
90+
/* Set up rump */
91+
rump_init();
92+
if (rump_sys_mkdir(MP, 0777) == -1)
93+
atf_tc_fail_errno("cannot create mountpoint");
94+
rump_pub_etfs_register(FAKEBLK, IMGNAME, RUMP_ETFS_BLK);
95+
96+
/* Mount filesystem */
97+
fprintf(stderr, "* Mount fs [1]\n");
98+
if (rump_sys_mount(MOUNT_LFS, MP, 0, &args, sizeof args) == -1)
99+
atf_tc_fail_errno("rump_sys_mount failed");
100+
101+
/* Payload */
102+
fprintf(stderr, "* Initial payload\n");
103+
write_file(UNCHANGED_CONTROL, FILE_SIZE, 0);
104+
105+
/* Discover filehandle size and allocate space */
106+
fh_size = 0;
107+
if (rump_sys_getfh(UNCHANGED_CONTROL, NULL, &fh_size) != 0
108+
&& errno != E2BIG)
109+
atf_tc_fail_errno("getfh failed to report fh_size");
110+
fprintf(stderr, "fh_size = %zd\n", fh_size);
111+
fhp = malloc(fh_size);
112+
/* Get a filehandle for our file */
113+
if (rump_sys_getfh(UNCHANGED_CONTROL, fhp, &fh_size) != 0)
114+
atf_tc_fail_errno("rump_sys_getfh failed");
115+
116+
/* Write the filehandle into a temporary file */
117+
fp = fopen(TMPFILE, "wb");
118+
fwrite(fhp, fh_size, 1, fp);
119+
fclose(fp);
120+
121+
/* Make the data go to disk */
122+
rump_sys_sync();
123+
rump_sys_sync();
124+
125+
/* Stat using a file handle and check */
126+
if (rump_sys_fhstat(fhp, fh_size, &statbuf) != 0)
127+
atf_tc_fail_errno("fhstat failed");
128+
129+
/* Sanity check values */
130+
if (statbuf.st_size != FILE_SIZE)
131+
atf_tc_fail("wrong size in initial stat");
132+
if (statbuf.st_nlink <= 0)
133+
atf_tc_fail("file already deleted");
134+
if (statbuf.st_blocks <= 0)
135+
atf_tc_fail("no blocks");
136+
137+
/* Simulate a system crash */
138+
exit(0);
139+
}
140+
141+
/* Wait for child to terminate */
142+
waitpid(childpid, &status, 0);
143+
144+
/* If it died, die ourselves */
145+
if (WEXITSTATUS(status))
146+
exit(WEXITSTATUS(status));
147+
148+
/* Read the file handle from temporary file */
149+
stat(TMPFILE, &statbuf);
150+
fh_size = statbuf.st_size;
151+
fhp = malloc(fh_size);
152+
fp = fopen(TMPFILE, "wb");
153+
fread(fhp, fh_size, 1, fp);
154+
fclose(fp);
155+
156+
/* Set up rump */
157+
rump_init();
158+
if (rump_sys_mkdir(MP, 0777) == -1)
159+
atf_tc_fail_errno("cannot create mountpoint");
160+
rump_pub_etfs_register(FAKEBLK, IMGNAME, RUMP_ETFS_BLK);
161+
162+
/* Remount */
163+
fprintf(stderr, "* Mount fs [2]\n");
164+
if (rump_sys_mount(MOUNT_LFS, MP, 0, &args, sizeof args) == -1)
165+
atf_tc_fail_errno("rump_sys_mount failed[2]");
166+
167+
/*
168+
* At this point the orphans should be deleted.
169+
* Check that our orphaned file in fact was.
170+
*/
171+
172+
/* Stat using a file handle and check */
173+
if (rump_sys_fhstat(fhp, fh_size, &statbuf) == 0)
174+
atf_tc_fail_errno("orphaned file not deleted");
175+
176+
/* Unmount */
177+
if (rump_sys_unmount(MP, 0) != 0)
178+
atf_tc_fail_errno("rump_sys_unmount failed[1]");
179+
180+
/* Fsck */
181+
fprintf(stderr, "* Fsck after final unmount\n");
182+
if (fsck())
183+
atf_tc_fail("fsck found errors after final unmount");
184+
}
185+
186+
ATF_TP_ADD_TCS(tp)
187+
{
188+
189+
ATF_TP_ADD_TC(tp, orphan32);
190+
ATF_TP_ADD_TC(tp, orphan64);
191+
return atf_no_error();
192+
}

0 commit comments

Comments
 (0)