1 /* $NetBSD: t_union.c,v 1.8 2011/08/07 06:01:51 hannken Exp $ */
15 #include <rump/rump.h>
16 #include <rump/rump_syscalls.h>
18 #include <miscfs/union/union.h>
20 #include "../../h_macros.h"
21 #include "../common/h_fsmacros.h"
23 #define MSTR "magic bus"
26 xput_tfile(const char *mp
, const char *path
)
28 char pathb
[MAXPATHLEN
];
35 RL(fd
= rump_sys_open(pathb
, O_CREAT
| O_RDWR
, 0777));
36 if (rump_sys_write(fd
, MSTR
, sizeof(MSTR
)) != sizeof(MSTR
))
37 atf_tc_fail_errno("write to testfile");
38 RL(rump_sys_close(fd
));
42 xread_tfile(const char *mp
, const char *path
)
44 char pathb
[MAXPATHLEN
];
52 fd
= rump_sys_open(pathb
, O_RDONLY
);
55 if (rump_sys_read(fd
, buf
, sizeof(buf
)) == -1)
56 atf_tc_fail_errno("read tfile");
57 RL(rump_sys_close(fd
));
58 if (strcmp(buf
, MSTR
) == 0)
64 * Mount a unionfs for testing. Before calling, "mp" contains
65 * the upper layer. Lowerpath is constructed so that the directory
69 mountunion(const char *mp
, char *lowerpath
)
71 struct union_args unionargs
;
73 sprintf(lowerpath
, "/lower");
74 rump_sys_mkdir(lowerpath
, 0777);
76 /* mount the union with our testfs as the upper layer */
77 memset(&unionargs
, 0, sizeof(unionargs
));
78 unionargs
.target
= lowerpath
;
79 unionargs
.mntflags
= UNMNT_BELOW
;
81 if (rump_sys_mount(MOUNT_UNION
, mp
, 0,
82 &unionargs
, sizeof(unionargs
)) == -1) {
83 if (errno
== EOPNOTSUPP
) {
84 atf_tc_skip("fs does not support VOP_WHITEOUT");
86 atf_tc_fail_errno("union mount");
99 printf("0x%x\n", status
);
100 RL(rump_sys_mount(MOUNT_RUMPFS
, "/", status
| MNT_UPDATE
, NULL
, 0));
104 #define TFILE "tensti"
105 #define TDIR "testdir"
106 #define TDFILE TDIR "/indir"
109 basic(const atf_tc_t
*tc
, const char *mp
)
111 char lowerpath
[MAXPATHLEN
];
115 int error
, fd
, dsize
;
117 mountunion(mp
, lowerpath
);
119 /* create a file in the lower layer */
120 xput_tfile(lowerpath
, TFILE
);
122 /* first, test we can read the old file from the new namespace */
123 error
= xread_tfile(mp
, TFILE
);
125 atf_tc_fail("union compare failed: %d (%s)",
126 error
, strerror(error
));
128 /* then, test upper layer writes don't affect the lower layer */
129 xput_tfile(mp
, "kiekko");
130 if ((error
= xread_tfile(lowerpath
, "kiekko")) != ENOENT
)
131 atf_tc_fail("invisibility failed: %d (%s)",
132 error
, strerror(error
));
134 /* check that we can whiteout stuff in the upper layer */
136 RL(rump_sys_unlink(TFILE
));
137 ATF_REQUIRE_ERRNO(ENOENT
, rump_sys_stat(TFILE
, &sb
) == -1);
140 /* check that the removed node is not in the directory listing */
141 RL(fd
= rump_sys_open(mp
, O_RDONLY
));
142 RL(dsize
= rump_sys_getdents(fd
, dbuf
, sizeof(dbuf
)));
143 for (dp
= (struct dirent
*)dbuf
;
144 (char *)dp
< dbuf
+ dsize
;
145 dp
= _DIRENT_NEXT(dp
)) {
146 if (strcmp(dp
->d_name
, TFILE
) == 0 && dp
->d_type
!= DT_WHT
)
147 atf_tc_fail("removed file non-white-outed");
149 RL(rump_sys_close(fd
));
151 RL(rump_sys_unmount(mp
, 0));
155 whiteout(const atf_tc_t
*tc
, const char *mp
)
157 char lower
[MAXPATHLEN
];
162 * XXX: use ffs here to make sure any screwups in rumpfs don't
165 RL(ffs_fstest_newfs(tc
, &fsarg
, "daimage", 1024*1024*5, NULL
));
166 RL(ffs_fstest_mount(tc
, fsarg
, "/lower", 0));
168 /* create a file in the lower layer */
169 RL(rump_sys_chdir("/lower"));
170 RL(rump_sys_mkdir(TDIR
, 0777));
171 RL(rump_sys_mkdir(TDFILE
, 0777));
172 RL(rump_sys_chdir("/"));
174 RL(ffs_fstest_unmount(tc
, "/lower", 0));
175 RL(ffs_fstest_mount(tc
, fsarg
, "/lower", MNT_RDONLY
));
177 mountunion(mp
, lower
);
180 ATF_REQUIRE_ERRNO(ENOTEMPTY
, rump_sys_rmdir(TDIR
) == -1);
181 RL(rump_sys_rmdir(TDFILE
));
182 RL(rump_sys_rmdir(TDIR
));
183 ATF_REQUIRE_ERRNO(ENOENT
, rump_sys_stat(TDFILE
, &sb
) == -1);
184 ATF_REQUIRE_ERRNO(ENOENT
, rump_sys_stat(TDIR
, &sb
) == -1);
186 RL(rump_sys_mkdir(TDIR
, 0777));
187 RL(rump_sys_stat(TDIR
, &sb
));
188 ATF_REQUIRE_ERRNO(ENOENT
, rump_sys_stat(TDFILE
, &sb
) == -1);
191 RL(rump_sys_unmount(mp
, 0));
194 ATF_TC_FSAPPLY(basic
, "check basic union functionality");
195 ATF_TC_FSAPPLY(whiteout
, "create whiteout in upper layer");
200 ATF_TP_FSAPPLY(basic
);
201 ATF_TP_FSAPPLY(whiteout
);
203 return atf_no_error();