generic/035

generic/035 checks that a file/directory that is open but has been overwritten will have nlink = 0. This test fails for NFS files because in order to properly implement remove-on-last-close NFS uses a process called silly-renaming where the file is renamed on the server. Silly-renaming isn’t used for directories, so when an open directory is deleted, operations on that directory return -ESTALE.

QA output created by 035
overwriting regular file:
nlink is 1, should be 0
overwriting dire

generic/071

generic/071 tests extent pre-allocation beyond the file’s size using FALLOC_FL_KEEP_SIZE, but NFS’s ALLOCATE operation does not support this. See https://tools.ietf.org/html/draft-ietf-nfsv4-minorversion2-41#section-15.1.3. NFSv4.2 will return the file’s size updated by the allocation.

generic/087

generic/087 checks that setting the file access and modification times to the current time and to a specific timestamp is allowed when expected. This test failes (at least on Fedora 24) because it uses uid 99 (nobody) instead of uid 65534 (nfsnobody).

We can easily fix this up by explicitly setting our anonuid and anongid back to uid 99 when setting up the test’s exports:

exportfs -ua
exportfs -o rw,insecure,anonuid=99,anongid=99 *:/exports
exportfs -o rw,insecure,anonuid=99,anongid=99 *:/exports/xfstests
exportfs -o rw,insecure,anonuid=99,anongid=99 *:/exports/scratch

generic/285

generic/285 tests for the proper functioning of SEEK_HOLE and SEEK_DATA, however it failes on NFS with an exported xfs filesystem because src/seek_sanity_test.c uses an allocation unit size based on the value of the NFS mount’s st_blksize. That size is typically much larger than the allocation unit of the underlying filesystem, and so triggers preallocation strategies in XFS that cause the test to fail. There’s a pending patch to discover the correct allocation unit size http://marc.info/?l=fstests&m=147731717027998&w=2

generic/294

generic/294 checks for proper return codes for creating files on read-only mounts:

@@ -1,5 +1,6 @@
 QA output created by 294
-mknod: SCRATCH_MNT/294.test/testnode: File exists
-mkdir: cannot create directory 'SCRATCH_MNT/294.test/testdir': File exists
+mknod: SCRATCH_MNT/294.test/testnode: Operation not permitted
+mknod: SCRATCH_MNT/294.test/testnode: Read-only file system
+mkdir: cannot create directory 'SCRATCH_MNT/294.test/testdir': Read-only file system
 touch: cannot touch 'SCRATCH_MNT/294.test/testtarget': Read-only file system
 ln: creating symbolic link 'SCRATCH_MNT/294.test/testlink': File exists

So creating a directory on ro returns EROFS insteand of EEXIST.

The reason is that we bail out early in nfs_lookup(), since we want lookups with create intent to happen atomically with the create. See https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=fd6840714d9cf6e93f1d42b904860a94df316b85. This bypasses historically-retained behavior in VFS to defer EROFS until it can be determined if the file exists or not.

generic/306

generic/306 checks for proper behavior on read-only mounts.. but NFS fails this. It appears that a remount,ro of the scratch filesystem also causes the test filesystem to switch to ro if both filesystems are exported with the same fsid.

[root@localhost xfstests]# mount -ov4.2,sec=sys localhost:/exports/scratch /mnt/scratch/
[root@localhost xfstests]# mount -ov4.2,sec=sys localhost:/exports/xfstests /mnt/xfstests/
[root@localhost xfstests]# mount | grep nfs4
localhost:/exports/scratch on /mnt/scratch type nfs4 (rw,relatime,seclabel,vers=4.2,rsize=524288,wsize=524288,namlen=255,hard,proto=tcp6,port=0,timeo=600,retrans=2,sec=sys,clientaddr=::1,local_lock=none,addr=::1)
localhost:/exports/xfstests on /mnt/xfstests type nfs4 (rw,relatime,seclabel,vers=4.2,rsize=524288,wsize=524288,namlen=255,hard,proto=tcp6,port=0,timeo=600,retrans=2,sec=sys,clientaddr=::1,local_lock=none,addr=::1)
[root@localhost xfstests]# mount -o remount,ro /mnt/scratch/
[root@localhost xfstests]# mount | grep nfs4
localhost:/exports/scratch on /mnt/scratch type nfs4 (ro,relatime,seclabel,vers=4.2,rsize=524288,wsize=524288,namlen=255,hard,proto=tcp6,port=0,timeo=600,retrans=2,sec=sys,clientaddr=::1,local_lock=none,addr=::1)
localhost:/exports/xfstests on /mnt/xfstests type nfs4 (ro,relatime,seclabel,vers=4.2,rsize=524288,wsize=524288,namlen=255,hard,proto=tcp6,port=0,timeo=600,retrans=2,sec=sys,clientaddr=::1,local_lock=none,addr=::1)

After a quick look, it seems the superblocks are shared as MS_RDONLY is in NFS_MS_MASK. The behavior isn’t reproduced with the nosharecache option. Also, explicitly setting separate fsid for each export should clear up the problem as well.

Update..

Setting separate fsid values is only going to work if the exported directories on the same filesystem are exported from the v4 root. This is because knfsd’s “if (nfsd_mountpoint(dentry, exp))” is only flagging to look up an export on the v4 root during LOOKUP.

So, to sum up, fixing generic/306 means either mounting with nosharecache, or separate fsid values on exports on fsid=0 if using the same filesystem for the export.

generic/350

Well, this is a blockdev test. I am not exactly sure why it is failing on my test machine, probably something to do with virtual hardware. It fails like this:

[root@localhost xfstests]# . common/scsi_debug
[root@localhost xfstests]# _get_scsi_debug_dev 512 512 0 4 "lbpws=1 lbpws10=1"
/dev/sda
[root@localhost xfstests]# /usr/sbin/xfs_io -c "fpunch 512k 1m" /dev/sda
[root@localhost xfstests]# strace -f /usr/sbin/xfs_io -c "fpunch 512k 1m" /dev/sda
execve("/usr/sbin/xfs_io", ["/usr/sbin/xfs_io", "-c", "fpunch 512k 1m", "/dev/sda"], [/* 26 vars */]) = 0
...
open("/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = 4
fstat(4, {st_mode=S_IFREG|0644, st_size=2997, ...}) = 0
read(4, "# Locale name alias data base.\n#"..., 4096) = 2997
read(4, "", 4096)                       = 0
close(4)                                = 0
open("/usr/share/locale/en_US.UTF-8/LC_MESSAGES/xfsprogs.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en_US.utf8/LC_MESSAGES/xfsprogs.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en_US/LC_MESSAGES/xfsprogs.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en.UTF-8/LC_MESSAGES/xfsprogs.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en.utf8/LC_MESSAGES/xfsprogs.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en/LC_MESSAGES/xfsprogs.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
fallocate(3, FALLOC_FL_KEEP_SIZE|FALLOC_FL_PUNCH_HOLE, 524288, 1048576) = -1 ENODEV (No such device)
dup(2)                                  = 4
fcntl(4, F_GETFL)                       = 0x8002 (flags O_RDWR|O_LARGEFILE)
open("/usr/share/locale/en_US.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en_US.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en_US/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
fstat(4, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
write(4, "fallocate: No such device\n", 26fallocate: No such device
) = 26
close(4)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++

I think it’s probably safe to just exclude any of the blockdev tests for our purposes. That ends up excluding only three tests.