[TN#009] Netatalk and ZFS nbmand property
Author
Ralph Böhme
Published on
April 17, 2012
Running the Netatalk test-suite with a volume on a ZFS set with ZFS property nbmand set to on causes nearly all tests to fail. The reason is (and it’s something Oracle hides well under the covers): it modifies POSIX semantics up to a point that POSIX compliant applications fail left and right.
We’ve written and attached a small C program which demonstrates the effect. It opens a file in read/write mode, then forks a child process and in the child process tries to rename the file.
Expected result on a POSIX conforming platform: success.
Actual result with nbmand=on: permission denied.
Usage:
$ gcc -o nbmand-demo nbmand-demo.c
$ cd /path/zfs-set/with/nbmand=off
$ touch file
$ /path/to/nbmand-demo file
… success …
$ cd /path/zfs-set/with/nbmand=on
$ touch file
$ /path/to/nbmand-demo file
… failure …
Therefore it is necessary to turn nbmand to off on any ZFS dataset you use for Netatalk AFP volumes.
nbmand-demo.c
#define _FILE_OFFSET_BITS 64
#include
#include
#include
#include
#include
#include
int main(int argc, char *argv[])
{
const char *file;
struct flock fl;
int fd;
pid_t pid;
if (argc != 2) {
printf("usage: %s FILE\n", argv[0]);
exit(1);
}
file = argv[1];
printf("Press to open file \"%s\": ", file);
getchar();
if ((fd = open(file, O_RDWR)) == -1) {
perror("open");
exit(1);
}
if ((pid = fork()) == -1) {
perror("fork");
exit(1);
}
if (pid == 0) {
/* Child */
printf("Press to rename file \"%s\" -> \"tmp\": ", file);
getchar();
if (rename(file, "tmp") == -1) {
perror("rename");
} else {
printf("renamed.\n");
rename("tmp", file);
}
printf("Press to exit");
getchar();
exit(0);
}
/* Parent */
if (waitpid(pid, NULL, 0) != pid) {
perror("waitpid");
exit(1);
}
close(fd);
return 0;
}