Page MenuHomeFreeBSD

tests: Add better pjdfstest integration
Needs ReviewPublic

Authored by markj on Apr 23 2026, 5:00 PM.
Tags
None
Referenced Files
Unknown Object (File)
Thu, Jun 4, 12:33 PM
Unknown Object (File)
Sat, May 30, 12:27 PM
Unknown Object (File)
Wed, May 20, 7:14 AM
Unknown Object (File)
Wed, May 20, 1:13 AM
Unknown Object (File)
Mon, May 18, 12:16 PM
Unknown Object (File)
Mon, May 18, 12:08 PM
Unknown Object (File)
Sun, May 17, 8:20 PM
Unknown Object (File)
Sun, May 17, 8:13 PM
Subscribers

Details

Reviewers
asomers
Group Reviewers
tests
Summary

Use ATF to wrap the new reimplementation of pjdfstest that came out of
GSOC 2022: https://github.com/saidsay-so/pjdfstest

So far I added tests for UFS, tmpfs and ZFS. More filesystems and
filesystem option combinations should be added. The result mostly
works, but see the comments below.

The p9fs tests don't really work properly: they need a 9pfs share to be
provided by the hypervisor, which itself is not a big deal, but we also
need the hypervisor to be running as the root user, which I avoid. I
think the solution there will be to implement a INET/unix socket
transport for p9fs, and then add a simple 9p server to the base system
and use that for testing.

This version of pjdfstest requires a pjdfstest user, which we currently
don't have. The current plan is for the pjdfstest package to create the
user upon installation.

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Skipped
Unit
Tests Skipped
Build Status
Buildable 72496
Build 69379: arc lint + arc unit

Event Timeline

markj requested review of this revision.Apr 23 2026, 5:00 PM

It would also be nice if pjdfstest would fail if there is a new optional feature not listed in the configuration. Currently, if someone adds a new feature to pjdfstest, these tests won't enable it unless someone remembers to come along and update the configurations.

As I mentioned by email, some tests need more than one unprivileged user. Some need up to three. We can't really eliminate that need, but we can change the configured users.

tests/sys/fs/pjdfstest/tmpfs.sh
31–32

You should be able to remove these lines. The rmdir part will be handled by ATF itself, and the umount step will be handled by the cleanup.

tests/sys/fs/pjdfstest/ufs.sh
22

You should probably remove the stat_st_birthtime feature for UFS1.

37–38

As in the tmpfs case, I think you can delete these lines.

60

Fixing UFS1 would probably require changing the on-disk format, which we can't do. So I guess what we want is to either mark specific test cases as expected failures , or else add a feature flag for "64-bit timestamps". Either way, that's a new feature request for pjdfstest.

Looking at the failures myself just now, I see that one is for times > 2038, and one for birthtimes. I think it would probably be more useful for pjdfstest to have an "expected failure" feature.

tests/sys/fs/pjdfstest/zfs.sh
13

Instead of using an md device, what about using a file-backed pool?

44–45

And delete these too.

Instead of putting all of these test programs under tests/sys/fs/pjdfstest , would it be possible to put them under separate directories for each file system? Like tests/sys/fs/tmpfs/pjdfstest.sh ? That would simplify running regression tests for a particular file system, for developers who aren't familiar with pjdfstest.

tests/sys/fs/pjdfstest/p9fs.sh
28

I agree that it would be super-nice if we could have a 9pfs server in userspace, so we wouldn't need to configure the hypervisor specially.

tests/sys/fs/pjdfstest/tmpfs.sh
31–32

I did this on purpose: if unmount fails I want that to be caught as a test failure, in case it's caused by a refcount leak or something like that.

tests/sys/fs/pjdfstest/ufs.sh
37–38

Same as above, it was deliberate.

60

Yeah, I think having an explicit list of expected failures would be nice.

tests/sys/fs/pjdfstest/zfs.sh
13

Sure, but is there any advantage to one over the other? Should we test both?

Instead of putting all of these test programs under tests/sys/fs/pjdfstest , would it be possible to put them under separate directories for each file system? Like tests/sys/fs/tmpfs/pjdfstest.sh ? That would simplify running regression tests for a particular file system, for developers who aren't familiar with pjdfstest.

Yeah, I could do that... I'm skeptical though that there can ever be one place that contains all regression tests you might want to run for a particular filesystem. How do you run all zfs tests for instance? There are some tests in sbin/bectl and usr.sbin/makefs that have found ZFS bugs. My stance on this problem is that in general you should just run the entire test suite, and we should focus on making that relatively fast and easy to do. To make it fast I've been trying to make tests run in parallel whenever possible, and to make it easy(ier) I wrote bricoler (https://github.com/markjdb/bricoler).

Instead of putting all of these test programs under tests/sys/fs/pjdfstest , would it be possible to put them under separate directories for each file system? Like tests/sys/fs/tmpfs/pjdfstest.sh ? That would simplify running regression tests for a particular file system, for developers who aren't familiar with pjdfstest.

Yeah, I could do that... I'm skeptical though that there can ever be one place that contains all regression tests you might want to run for a particular filesystem. How do you run all zfs tests for instance? There are some tests in sbin/bectl and usr.sbin/makefs that have found ZFS bugs. My stance on this problem is that in general you should just run the entire test suite, and we should focus on making that relatively fast and easy to do. To make it fast I've been trying to make tests run in parallel whenever possible, and to make it easy(ier) I wrote bricoler (https://github.com/markjdb/bricoler).

Ok, we can do it this way if you prefer, then.

tests/sys/fs/pjdfstest/tmpfs.sh
31–32

Ok, makes sense.

tests/sys/fs/pjdfstest/ufs.sh
60
tests/sys/fs/pjdfstest/zfs.sh
13

The only advantages of using file-backed pools are that they are easier to setup and are less likely to interfere with other tests that might use mdconfig. I don't think we need to test both.

Use a file-backed vdev instead

As I mentioned by email, some tests need more than one unprivileged user. Some need up to three. We can't really eliminate that need, but we can change the configured users.

Hmm, so we have "nobody" and "tests"... I guess we could just use another system user, maybe "daemon"? Alternately, the port could create a pjdfstest user, or we could require the test runner to configure one somehow (i.e., skip the tests unless a pjdfstest user exists).

As I mentioned by email, some tests need more than one unprivileged user. Some need up to three. We can't really eliminate that need, but we can change the configured users.

Hmm, so we have "nobody" and "tests"... I guess we could just use another system user, maybe "daemon"? Alternately, the port could create a pjdfstest user, or we could require the test runner to configure one somehow (i.e., skip the tests unless a pjdfstest user exists).

I'm in favor of creating that user in the port.

This revision is now accepted and ready to land.Apr 23 2026, 8:55 PM

As I mentioned by email, some tests need more than one unprivileged user. Some need up to three. We can't really eliminate that need, but we can change the configured users.

Hmm, so we have "nobody" and "tests"... I guess we could just use another system user, maybe "daemon"? Alternately, the port could create a pjdfstest user, or we could require the test runner to configure one somehow (i.e., skip the tests unless a pjdfstest user exists).

I'm in favor of creating that user in the port.

Yeah, I think that makes the most sense.

One more related question: should the rewrite call itself pjdfstest, or something else? Is it going to replace the upstream implementation?

This revision now requires review to proceed.Apr 27 2026, 1:37 PM

Yes, the plan is that this will replace the sh-based implementation. So I don't want to completely rename it. Or I suppose we could just retire the sh-based implementation, and call this one "pjdfstest2" or something.
Also, while this diff LGTM, you shouldn't commit it just yet, until we resolve all of the issues you opened on Github. That's because some of those might change the config file format.

tests/sys/fs/pjdfstest/ufs.sh
61

Is the birthtime failure related to 64-bit timestamps? Or is that due to "not having a birthtime field"?

Yes, the plan is that this will replace the sh-based implementation. So I don't want to completely rename it. Or I suppose we could just retire the sh-based implementation, and call this one "pjdfstest2" or something.

pjdfstest2 seems fine. I have no real preference, just wondering.

Also, while this diff LGTM, you shouldn't commit it just yet, until we resolve all of the issues you opened on Github. That's because some of those might change the config file format.

Sure, no rush. I wasn't going to commit this until pjdfstest is available as a binary package.

markj added a reviewer: tests.

Allow parallel test runs by default now that pjdfstest handles it.

Please note that the new version requires _rust_. That's a pretty large dependency to require for CI, which doesn't exist already today.
This is part of the reason why I was more keen on doing python+pytest integration: python is more common in CI and pytest is on the docket for kyua integration (it's on my TODO list because I want the atf_python stuff to go away...).

tests/sys/fs/pjdfstest/ufs.sh
2

Please don't add shebangs to ATF tests: the build process automatically adds its own shebang which uses the appropriately pathed atf-sh .

tests/sys/fs/pjdfstest/zfs.sh
37
49
87

Why is this the only test where the directory is cleaned up after the fact?

markj marked an inline comment as done.

Address some comments

Please note that the new version requires _rust_. That's a pretty large dependency to require for CI, which doesn't exist already today.
This is part of the reason why I was more keen on doing python+pytest integration: python is more common in CI and pytest is on the docket for kyua integration (it's on my TODO list because I want the atf_python stuff to go away...).

I don't follow: the tests require a compiled rust executable, which will be available via the ports tree. There is no dependency on rust itself.

tests/sys/fs/pjdfstest/zfs.sh
37

Why? Quoting isn't needed around assignments like this, the shell won't perform expansion here.

87

This test creates an extra directory.

asomers requested changes to this revision.May 7 2026, 2:45 PM
asomers added inline comments.
tests/sys/fs/pjdfstest/p9fs.sh
22

Since you have a dedicated test file system, and aren't merely using /tmp , I suggest enabling the remount tests, here and for the other file systems too.

tests/sys/fs/pjdfstest/tmpfs.sh
44

require.progs here, too

This revision now requires changes to proceed.May 7 2026, 2:45 PM
markj marked 2 inline comments as done.May 7 2026, 3:39 PM
markj added inline comments.
tests/sys/fs/pjdfstest/p9fs.sh
22

This doesn't trivially work:

open::erofs_named                                                         FAILED                                                                               
        called `Result::unwrap()` on an `Err` value: Failed to remount: mount: tmpfs: Device busy

I presume pjdfstest has its cwd set to some path under the mount?

tests/sys/fs/pjdfstest/p9fs.sh
22

I saw that with UFS too, but not ZFS. I have a theory, but I'm not sure of the best way to handle it. My theory is that on certain file systems, close triggers some kind of asynchronous task that flushes data to disk, and prevents the file system from being remounted read-only. ZFS either doesn't do that, or else the remount operation waits for such tasks to complete.
Should we consider that a file system bug, and require all file systems to handle it the way that ZFS does? Or do we switch the test to use "unmount -f", which works?

tests/sys/fs/pjdfstest/p9fs.sh
22

I see this on tmpfs and ufs, so I think there must be something else going on.

tests/sys/fs/pjdfstest/p9fs.sh
22

Just revisiting this: shall I look into remount issue? I haven't tried to debug it.

Rebase, drop p9fs tests for now.

@asomers I retried the tests with the pjdfstest built from ports. All of the tests pass except the UFS1 one:

root@freebsd:/tmp/kyua.uO4a2P/2/work # pjdfstest -c pjdfstest.toml -p mnt
utimensat::utime_now_write_perm                                               ok
utimensat::changes_timestamps::regular                                        ok
utimensat::changes_timestamps::socket                                         ok
utimensat::subsecond                                                          ok
utimensat::utime_now_nobody                                                   ok
utimensat::changes_timestamps::dir                                            ok
utimensat::nobody                                                             ok
utimensat::utime_now_root                                                     ok
utimensat::order                                                              ok
utimensat::follow_symlink                                                     ok
utimensat::root                                                               ok
Abort trap
root@freebsd:/tmp/kyua.uO4a2P/2/work # echo $?
134