Changeset View
Changeset View
Standalone View
Standalone View
tests/sys/fs/fusefs/locks.cc
Show First 20 Lines • Show All 222 Lines • ▼ Show 20 Lines | TEST_F(GetlkFallback, local) | ||||
expect_lookup(RELPATH, ino); | expect_lookup(RELPATH, ino); | ||||
expect_open(ino, 0, 1); | expect_open(ino, 0, 1); | ||||
fd = open(FULLPATH, O_RDWR); | fd = open(FULLPATH, O_RDWR); | ||||
ASSERT_LE(0, fd) << strerror(errno); | ASSERT_LE(0, fd) << strerror(errno); | ||||
fl.l_start = 10; | fl.l_start = 10; | ||||
fl.l_len = 1000; | fl.l_len = 1000; | ||||
fl.l_pid = getpid(); | fl.l_pid = 0; | ||||
fl.l_type = F_RDLCK; | fl.l_type = F_RDLCK; | ||||
fl.l_whence = SEEK_SET; | fl.l_whence = SEEK_SET; | ||||
fl.l_sysid = 0; | fl.l_sysid = 0; | ||||
ASSERT_NE(-1, fcntl(fd, F_GETLK, &fl)) << strerror(errno); | ASSERT_NE(-1, fcntl(fd, F_GETLK, &fl)) << strerror(errno); | ||||
leak(fd); | leak(fd); | ||||
} | } | ||||
/* | /* | ||||
* If the filesystem has no locks that fit the description, the filesystem | * If the filesystem has no locks that fit the description, the filesystem | ||||
* should return F_UNLCK | * should return F_UNLCK | ||||
*/ | */ | ||||
TEST_F(Getlk, no_locks) | TEST_F(Getlk, no_locks) | ||||
{ | { | ||||
const char FULLPATH[] = "mountpoint/some_file.txt"; | const char FULLPATH[] = "mountpoint/some_file.txt"; | ||||
const char RELPATH[] = "some_file.txt"; | const char RELPATH[] = "some_file.txt"; | ||||
uint64_t ino = 42; | uint64_t ino = 42; | ||||
struct flock fl; | struct flock fl; | ||||
int fd; | int fd; | ||||
pid_t pid = 1234; | pid_t pid = getpid(); | ||||
expect_lookup(RELPATH, ino); | expect_lookup(RELPATH, ino); | ||||
expect_open(ino, 0, 1); | expect_open(ino, 0, 1); | ||||
EXPECT_CALL(*m_mock, process( | EXPECT_CALL(*m_mock, process( | ||||
ResultOf([=](auto in) { | ResultOf([=](auto in) { | ||||
return (in.header.opcode == FUSE_GETLK && | return (in.header.opcode == FUSE_GETLK && | ||||
in.header.nodeid == ino && | in.header.nodeid == ino && | ||||
in.body.getlk.fh == FH && | in.body.getlk.fh == FH && | ||||
/* | |||||
* Though it seems useless, libfuse expects the | |||||
* owner and pid fields to be set during | |||||
* FUSE_GETLK. | |||||
*/ | |||||
in.body.getlk.owner == (uint32_t)pid && | in.body.getlk.owner == (uint32_t)pid && | ||||
in.body.getlk.lk.pid == (uint64_t)pid && | |||||
in.body.getlk.lk.start == 10 && | in.body.getlk.lk.start == 10 && | ||||
in.body.getlk.lk.end == 1009 && | in.body.getlk.lk.end == 1009 && | ||||
in.body.getlk.lk.type == F_RDLCK && | in.body.getlk.lk.type == F_RDLCK); | ||||
in.body.getlk.lk.pid == (uint64_t)pid); | |||||
}, Eq(true)), | }, Eq(true)), | ||||
_) | _) | ||||
).WillOnce(Invoke(ReturnImmediate([=](auto in, auto& out) { | ).WillOnce(Invoke(ReturnImmediate([=](auto in, auto& out) { | ||||
SET_OUT_HEADER_LEN(out, getlk); | SET_OUT_HEADER_LEN(out, getlk); | ||||
out.body.getlk.lk = in.body.getlk.lk; | out.body.getlk.lk = in.body.getlk.lk; | ||||
out.body.getlk.lk.type = F_UNLCK; | out.body.getlk.lk.type = F_UNLCK; | ||||
}))); | }))); | ||||
fd = open(FULLPATH, O_RDWR); | fd = open(FULLPATH, O_RDWR); | ||||
ASSERT_LE(0, fd) << strerror(errno); | ASSERT_LE(0, fd) << strerror(errno); | ||||
fl.l_start = 10; | fl.l_start = 10; | ||||
fl.l_len = 1000; | fl.l_len = 1000; | ||||
fl.l_pid = pid; | fl.l_pid = 0; | ||||
emaste: Can you explain this part of the change (i.e., 0 instead of pid which was fake) | |||||
Done Inline ActionsWhen I first wrote the test I thought that the caller of fcntl was supposed to set pid. But that was wrong. The kernel is supposed to set it, and we verify it on return. asomers: When I first wrote the test I thought that the caller of fcntl was supposed to set pid. But… | |||||
fl.l_type = F_RDLCK; | fl.l_type = F_RDLCK; | ||||
fl.l_whence = SEEK_SET; | fl.l_whence = SEEK_SET; | ||||
fl.l_sysid = 0; | fl.l_sysid = 0; | ||||
ASSERT_NE(-1, fcntl(fd, F_GETLK, &fl)) << strerror(errno); | ASSERT_NE(-1, fcntl(fd, F_GETLK, &fl)) << strerror(errno); | ||||
ASSERT_EQ(F_UNLCK, fl.l_type); | ASSERT_EQ(F_UNLCK, fl.l_type); | ||||
leak(fd); | leak(fd); | ||||
} | } | ||||
/* A different pid does have a lock */ | /* A different pid does have a lock */ | ||||
TEST_F(Getlk, lock_exists) | TEST_F(Getlk, lock_exists) | ||||
{ | { | ||||
const char FULLPATH[] = "mountpoint/some_file.txt"; | const char FULLPATH[] = "mountpoint/some_file.txt"; | ||||
const char RELPATH[] = "some_file.txt"; | const char RELPATH[] = "some_file.txt"; | ||||
uint64_t ino = 42; | uint64_t ino = 42; | ||||
struct flock fl; | struct flock fl; | ||||
int fd; | int fd; | ||||
pid_t pid = 1234; | pid_t pid = getpid(); | ||||
pid_t pid2 = 1235; | pid_t pid2 = 1235; | ||||
expect_lookup(RELPATH, ino); | expect_lookup(RELPATH, ino); | ||||
expect_open(ino, 0, 1); | expect_open(ino, 0, 1); | ||||
EXPECT_CALL(*m_mock, process( | EXPECT_CALL(*m_mock, process( | ||||
ResultOf([=](auto in) { | ResultOf([=](auto in) { | ||||
return (in.header.opcode == FUSE_GETLK && | return (in.header.opcode == FUSE_GETLK && | ||||
in.header.nodeid == ino && | in.header.nodeid == ino && | ||||
in.body.getlk.fh == FH && | in.body.getlk.fh == FH && | ||||
/* | |||||
* Though it seems useless, libfuse expects the | |||||
* owner and pid fields to be set during | |||||
* FUSE_GETLK. | |||||
*/ | |||||
in.body.getlk.owner == (uint32_t)pid && | in.body.getlk.owner == (uint32_t)pid && | ||||
in.body.getlk.lk.pid == (uint64_t)pid && | |||||
in.body.getlk.lk.start == 10 && | in.body.getlk.lk.start == 10 && | ||||
in.body.getlk.lk.end == 1009 && | in.body.getlk.lk.end == 1009 && | ||||
in.body.getlk.lk.type == F_RDLCK && | in.body.getlk.lk.type == F_RDLCK); | ||||
in.body.getlk.lk.pid == (uint64_t)pid); | |||||
}, Eq(true)), | }, Eq(true)), | ||||
_) | _) | ||||
).WillOnce(Invoke(ReturnImmediate([=](auto in __unused, auto& out) { | ).WillOnce(Invoke(ReturnImmediate([=](auto in __unused, auto& out) { | ||||
SET_OUT_HEADER_LEN(out, getlk); | SET_OUT_HEADER_LEN(out, getlk); | ||||
out.body.getlk.lk.start = 100; | out.body.getlk.lk.start = 100; | ||||
out.body.getlk.lk.end = 199; | out.body.getlk.lk.end = 199; | ||||
out.body.getlk.lk.type = F_WRLCK; | out.body.getlk.lk.type = F_WRLCK; | ||||
out.body.getlk.lk.pid = (uint32_t)pid2;; | out.body.getlk.lk.pid = (uint32_t)pid2;; | ||||
}))); | }))); | ||||
fd = open(FULLPATH, O_RDWR); | fd = open(FULLPATH, O_RDWR); | ||||
ASSERT_LE(0, fd) << strerror(errno); | ASSERT_LE(0, fd) << strerror(errno); | ||||
fl.l_start = 10; | fl.l_start = 10; | ||||
fl.l_len = 1000; | fl.l_len = 1000; | ||||
fl.l_pid = pid; | fl.l_pid = 0; | ||||
fl.l_type = F_RDLCK; | fl.l_type = F_RDLCK; | ||||
fl.l_whence = SEEK_SET; | fl.l_whence = SEEK_SET; | ||||
fl.l_sysid = 0; | fl.l_sysid = 0; | ||||
ASSERT_NE(-1, fcntl(fd, F_GETLK, &fl)) << strerror(errno); | ASSERT_NE(-1, fcntl(fd, F_GETLK, &fl)) << strerror(errno); | ||||
EXPECT_EQ(100, fl.l_start); | EXPECT_EQ(100, fl.l_start); | ||||
EXPECT_EQ(100, fl.l_len); | EXPECT_EQ(100, fl.l_len); | ||||
EXPECT_EQ(pid2, fl.l_pid); | EXPECT_EQ(pid2, fl.l_pid); | ||||
EXPECT_EQ(F_WRLCK, fl.l_type); | EXPECT_EQ(F_WRLCK, fl.l_type); | ||||
Show All 32 Lines | |||||
/* Clear a lock with FUSE_SETLK */ | /* Clear a lock with FUSE_SETLK */ | ||||
TEST_F(Setlk, clear) | TEST_F(Setlk, clear) | ||||
{ | { | ||||
const char FULLPATH[] = "mountpoint/some_file.txt"; | const char FULLPATH[] = "mountpoint/some_file.txt"; | ||||
const char RELPATH[] = "some_file.txt"; | const char RELPATH[] = "some_file.txt"; | ||||
uint64_t ino = 42; | uint64_t ino = 42; | ||||
struct flock fl; | struct flock fl; | ||||
int fd; | int fd; | ||||
pid_t pid = 1234; | pid_t pid = getpid(); | ||||
expect_lookup(RELPATH, ino); | expect_lookup(RELPATH, ino); | ||||
expect_open(ino, 0, 1); | expect_open(ino, 0, 1); | ||||
expect_setlk(ino, pid, 10, 1009, F_UNLCK, 0); | expect_setlk(ino, pid, 10, 1009, F_UNLCK, 0); | ||||
fd = open(FULLPATH, O_RDWR); | fd = open(FULLPATH, O_RDWR); | ||||
ASSERT_LE(0, fd) << strerror(errno); | ASSERT_LE(0, fd) << strerror(errno); | ||||
fl.l_start = 10; | fl.l_start = 10; | ||||
fl.l_len = 1000; | fl.l_len = 1000; | ||||
fl.l_pid = pid; | fl.l_pid = 0; | ||||
fl.l_type = F_UNLCK; | fl.l_type = F_UNLCK; | ||||
fl.l_whence = SEEK_SET; | fl.l_whence = SEEK_SET; | ||||
fl.l_sysid = 0; | fl.l_sysid = 0; | ||||
ASSERT_NE(-1, fcntl(fd, F_SETLK, &fl)) << strerror(errno); | ASSERT_NE(-1, fcntl(fd, F_SETLK, &fl)) << strerror(errno); | ||||
leak(fd); | leak(fd); | ||||
} | } | ||||
/* Set a new lock with FUSE_SETLK */ | /* Set a new lock with FUSE_SETLK */ | ||||
TEST_F(Setlk, set) | TEST_F(Setlk, set) | ||||
{ | { | ||||
const char FULLPATH[] = "mountpoint/some_file.txt"; | const char FULLPATH[] = "mountpoint/some_file.txt"; | ||||
const char RELPATH[] = "some_file.txt"; | const char RELPATH[] = "some_file.txt"; | ||||
uint64_t ino = 42; | uint64_t ino = 42; | ||||
struct flock fl; | struct flock fl; | ||||
int fd; | int fd; | ||||
pid_t pid = 1234; | pid_t pid = getpid(); | ||||
expect_lookup(RELPATH, ino); | expect_lookup(RELPATH, ino); | ||||
expect_open(ino, 0, 1); | expect_open(ino, 0, 1); | ||||
expect_setlk(ino, pid, 10, 1009, F_RDLCK, 0); | expect_setlk(ino, pid, 10, 1009, F_RDLCK, 0); | ||||
fd = open(FULLPATH, O_RDWR); | fd = open(FULLPATH, O_RDWR); | ||||
ASSERT_LE(0, fd) << strerror(errno); | ASSERT_LE(0, fd) << strerror(errno); | ||||
fl.l_start = 10; | fl.l_start = 10; | ||||
fl.l_len = 1000; | fl.l_len = 1000; | ||||
fl.l_pid = pid; | fl.l_pid = 0; | ||||
fl.l_type = F_RDLCK; | fl.l_type = F_RDLCK; | ||||
fl.l_whence = SEEK_SET; | fl.l_whence = SEEK_SET; | ||||
fl.l_sysid = 0; | fl.l_sysid = 0; | ||||
ASSERT_NE(-1, fcntl(fd, F_SETLK, &fl)) << strerror(errno); | ASSERT_NE(-1, fcntl(fd, F_SETLK, &fl)) << strerror(errno); | ||||
leak(fd); | leak(fd); | ||||
} | } | ||||
/* l_len = 0 is a flag value that means to lock until EOF */ | /* l_len = 0 is a flag value that means to lock until EOF */ | ||||
TEST_F(Setlk, set_eof) | TEST_F(Setlk, set_eof) | ||||
{ | { | ||||
const char FULLPATH[] = "mountpoint/some_file.txt"; | const char FULLPATH[] = "mountpoint/some_file.txt"; | ||||
const char RELPATH[] = "some_file.txt"; | const char RELPATH[] = "some_file.txt"; | ||||
uint64_t ino = 42; | uint64_t ino = 42; | ||||
struct flock fl; | struct flock fl; | ||||
int fd; | int fd; | ||||
pid_t pid = 1234; | pid_t pid = getpid(); | ||||
expect_lookup(RELPATH, ino); | expect_lookup(RELPATH, ino); | ||||
expect_open(ino, 0, 1); | expect_open(ino, 0, 1); | ||||
expect_setlk(ino, pid, 10, OFFSET_MAX, F_RDLCK, 0); | expect_setlk(ino, pid, 10, OFFSET_MAX, F_RDLCK, 0); | ||||
fd = open(FULLPATH, O_RDWR); | fd = open(FULLPATH, O_RDWR); | ||||
ASSERT_LE(0, fd) << strerror(errno); | ASSERT_LE(0, fd) << strerror(errno); | ||||
fl.l_start = 10; | fl.l_start = 10; | ||||
fl.l_len = 0; | fl.l_len = 0; | ||||
fl.l_pid = pid; | fl.l_pid = 0; | ||||
fl.l_type = F_RDLCK; | fl.l_type = F_RDLCK; | ||||
fl.l_whence = SEEK_SET; | fl.l_whence = SEEK_SET; | ||||
fl.l_sysid = 0; | fl.l_sysid = 0; | ||||
ASSERT_NE(-1, fcntl(fd, F_SETLK, &fl)) << strerror(errno); | ASSERT_NE(-1, fcntl(fd, F_SETLK, &fl)) << strerror(errno); | ||||
leak(fd); | leak(fd); | ||||
} | } | ||||
/* Fail to set a new lock with FUSE_SETLK due to a conflict */ | /* Fail to set a new lock with FUSE_SETLK due to a conflict */ | ||||
TEST_F(Setlk, eagain) | TEST_F(Setlk, eagain) | ||||
{ | { | ||||
const char FULLPATH[] = "mountpoint/some_file.txt"; | const char FULLPATH[] = "mountpoint/some_file.txt"; | ||||
const char RELPATH[] = "some_file.txt"; | const char RELPATH[] = "some_file.txt"; | ||||
uint64_t ino = 42; | uint64_t ino = 42; | ||||
struct flock fl; | struct flock fl; | ||||
int fd; | int fd; | ||||
pid_t pid = 1234; | pid_t pid = getpid(); | ||||
expect_lookup(RELPATH, ino); | expect_lookup(RELPATH, ino); | ||||
expect_open(ino, 0, 1); | expect_open(ino, 0, 1); | ||||
expect_setlk(ino, pid, 10, 1009, F_RDLCK, EAGAIN); | expect_setlk(ino, pid, 10, 1009, F_RDLCK, EAGAIN); | ||||
fd = open(FULLPATH, O_RDWR); | fd = open(FULLPATH, O_RDWR); | ||||
ASSERT_LE(0, fd) << strerror(errno); | ASSERT_LE(0, fd) << strerror(errno); | ||||
fl.l_start = 10; | fl.l_start = 10; | ||||
fl.l_len = 1000; | fl.l_len = 1000; | ||||
fl.l_pid = pid; | fl.l_pid = 0; | ||||
fl.l_type = F_RDLCK; | fl.l_type = F_RDLCK; | ||||
fl.l_whence = SEEK_SET; | fl.l_whence = SEEK_SET; | ||||
fl.l_sysid = 0; | fl.l_sysid = 0; | ||||
ASSERT_EQ(-1, fcntl(fd, F_SETLK, &fl)); | ASSERT_EQ(-1, fcntl(fd, F_SETLK, &fl)); | ||||
ASSERT_EQ(EAGAIN, errno); | ASSERT_EQ(EAGAIN, errno); | ||||
leak(fd); | leak(fd); | ||||
} | } | ||||
Show All 11 Lines | TEST_F(SetlkwFallback, local) | ||||
expect_lookup(RELPATH, ino); | expect_lookup(RELPATH, ino); | ||||
expect_open(ino, 0, 1); | expect_open(ino, 0, 1); | ||||
fd = open(FULLPATH, O_RDWR); | fd = open(FULLPATH, O_RDWR); | ||||
ASSERT_LE(0, fd) << strerror(errno); | ASSERT_LE(0, fd) << strerror(errno); | ||||
fl.l_start = 10; | fl.l_start = 10; | ||||
fl.l_len = 1000; | fl.l_len = 1000; | ||||
fl.l_pid = getpid(); | fl.l_pid = 0; | ||||
fl.l_type = F_RDLCK; | fl.l_type = F_RDLCK; | ||||
fl.l_whence = SEEK_SET; | fl.l_whence = SEEK_SET; | ||||
fl.l_sysid = 0; | fl.l_sysid = 0; | ||||
ASSERT_NE(-1, fcntl(fd, F_SETLKW, &fl)) << strerror(errno); | ASSERT_NE(-1, fcntl(fd, F_SETLKW, &fl)) << strerror(errno); | ||||
leak(fd); | leak(fd); | ||||
} | } | ||||
/* | /* | ||||
* Set a new lock with FUSE_SETLK. If the lock is not available, then the | * Set a new lock with FUSE_SETLK. If the lock is not available, then the | ||||
* command should block. But to the kernel, that's the same as just being | * command should block. But to the kernel, that's the same as just being | ||||
* slow, so we don't need a separate test method | * slow, so we don't need a separate test method | ||||
*/ | */ | ||||
TEST_F(Setlkw, set) | TEST_F(Setlkw, set) | ||||
{ | { | ||||
const char FULLPATH[] = "mountpoint/some_file.txt"; | const char FULLPATH[] = "mountpoint/some_file.txt"; | ||||
const char RELPATH[] = "some_file.txt"; | const char RELPATH[] = "some_file.txt"; | ||||
uint64_t ino = 42; | uint64_t ino = 42; | ||||
struct flock fl; | struct flock fl; | ||||
int fd; | int fd; | ||||
pid_t pid = 1234; | pid_t pid = getpid(); | ||||
expect_lookup(RELPATH, ino); | expect_lookup(RELPATH, ino); | ||||
expect_open(ino, 0, 1); | expect_open(ino, 0, 1); | ||||
expect_setlkw(ino, pid, 10, 1009, F_RDLCK, 0); | expect_setlkw(ino, pid, 10, 1009, F_RDLCK, 0); | ||||
fd = open(FULLPATH, O_RDWR); | fd = open(FULLPATH, O_RDWR); | ||||
ASSERT_LE(0, fd) << strerror(errno); | ASSERT_LE(0, fd) << strerror(errno); | ||||
fl.l_start = 10; | fl.l_start = 10; | ||||
fl.l_len = 1000; | fl.l_len = 1000; | ||||
fl.l_pid = pid; | fl.l_pid = 0; | ||||
fl.l_type = F_RDLCK; | fl.l_type = F_RDLCK; | ||||
fl.l_whence = SEEK_SET; | fl.l_whence = SEEK_SET; | ||||
fl.l_sysid = 0; | fl.l_sysid = 0; | ||||
ASSERT_NE(-1, fcntl(fd, F_SETLKW, &fl)) << strerror(errno); | ASSERT_NE(-1, fcntl(fd, F_SETLKW, &fl)) << strerror(errno); | ||||
leak(fd); | leak(fd); | ||||
} | } |
Can you explain this part of the change (i.e., 0 instead of pid which was fake)