fusefs: fix two bugs regarding fcntl file locks
1) F_SETLKW (blocking) operations would be sent to the FUSE server as F_SETLK (non-blocking). 2) Release operations, F_SETLK with lk_type = F_UNLCK, would simply return EINVAL. PR: 253500 Reported by: John Millikin <jmillikin@gmail.com> MFC after: 2 weeks
This commit is contained in:
parent
6ceacebdf5
commit
929acdb19a
@ -437,10 +437,14 @@ fuse_vnop_advlock(struct vop_advlock_args *ap)
|
||||
op = FUSE_GETLK;
|
||||
break;
|
||||
case F_SETLK:
|
||||
op = FUSE_SETLK;
|
||||
if (flags & F_WAIT)
|
||||
op = FUSE_SETLKW;
|
||||
else
|
||||
op = FUSE_SETLK;
|
||||
break;
|
||||
case F_SETLKW:
|
||||
op = FUSE_SETLKW;
|
||||
case F_UNLCK:
|
||||
op = FUSE_SETLK;
|
||||
flags |= F_UNLCK;
|
||||
break;
|
||||
default:
|
||||
return EINVAL;
|
||||
|
@ -210,6 +210,16 @@ TEST_F(FlushWithLocks, unlock_on_close)
|
||||
ResultOf([=](auto in) {
|
||||
return (in.header.opcode == FUSE_SETLK &&
|
||||
in.header.nodeid == ino &&
|
||||
in.body.setlk.lk.type == F_RDLCK &&
|
||||
in.body.setlk.fh == FH);
|
||||
}, Eq(true)),
|
||||
_)
|
||||
).WillOnce(Invoke(ReturnErrno(0)));
|
||||
EXPECT_CALL(*m_mock, process(
|
||||
ResultOf([=](auto in) {
|
||||
return (in.header.opcode == FUSE_SETLK &&
|
||||
in.header.nodeid == ino &&
|
||||
in.body.setlk.lk.type == F_UNLCK &&
|
||||
in.body.setlk.fh == FH);
|
||||
}, Eq(true)),
|
||||
_)
|
||||
@ -224,7 +234,7 @@ TEST_F(FlushWithLocks, unlock_on_close)
|
||||
fl.l_type = F_RDLCK;
|
||||
fl.l_whence = SEEK_SET;
|
||||
fl.l_sysid = 0;
|
||||
ASSERT_NE(-1, fcntl(fd, F_SETLKW, &fl)) << strerror(errno);
|
||||
ASSERT_NE(-1, fcntl(fd, F_SETLK, &fl)) << strerror(errno);
|
||||
|
||||
fd2 = open(FULLPATH, O_WRONLY);
|
||||
ASSERT_LE(0, fd2) << strerror(errno);
|
||||
|
@ -72,6 +72,23 @@ void expect_setlk(uint64_t ino, pid_t pid, uint64_t start, uint64_t end,
|
||||
return (in.header.opcode == FUSE_SETLK &&
|
||||
in.header.nodeid == ino &&
|
||||
in.body.setlk.fh == FH &&
|
||||
in.body.setlk.owner == (uint32_t)pid &&
|
||||
in.body.setlk.lk.start == start &&
|
||||
in.body.setlk.lk.end == end &&
|
||||
in.body.setlk.lk.type == type &&
|
||||
in.body.setlk.lk.pid == (uint64_t)pid);
|
||||
}, Eq(true)),
|
||||
_)
|
||||
).WillOnce(Invoke(ReturnErrno(err)));
|
||||
}
|
||||
void expect_setlkw(uint64_t ino, pid_t pid, uint64_t start, uint64_t end,
|
||||
uint32_t type, int err)
|
||||
{
|
||||
EXPECT_CALL(*m_mock, process(
|
||||
ResultOf([=](auto in) {
|
||||
return (in.header.opcode == FUSE_SETLKW &&
|
||||
in.header.nodeid == ino &&
|
||||
in.body.setlkw.fh == FH &&
|
||||
in.body.setlkw.owner == (uint32_t)pid &&
|
||||
in.body.setlkw.lk.start == start &&
|
||||
in.body.setlkw.lk.end == end &&
|
||||
@ -343,6 +360,32 @@ TEST_F(SetlkFallback, local)
|
||||
leak(fd);
|
||||
}
|
||||
|
||||
/* Clear a lock with FUSE_SETLK */
|
||||
TEST_F(Setlk, clear)
|
||||
{
|
||||
const char FULLPATH[] = "mountpoint/some_file.txt";
|
||||
const char RELPATH[] = "some_file.txt";
|
||||
uint64_t ino = 42;
|
||||
struct flock fl;
|
||||
int fd;
|
||||
pid_t pid = 1234;
|
||||
|
||||
expect_lookup(RELPATH, ino);
|
||||
expect_open(ino, 0, 1);
|
||||
expect_setlk(ino, pid, 10, 1009, F_UNLCK, 0);
|
||||
|
||||
fd = open(FULLPATH, O_RDWR);
|
||||
ASSERT_LE(0, fd) << strerror(errno);
|
||||
fl.l_start = 10;
|
||||
fl.l_len = 1000;
|
||||
fl.l_pid = pid;
|
||||
fl.l_type = F_UNLCK;
|
||||
fl.l_whence = SEEK_SET;
|
||||
fl.l_sysid = 0;
|
||||
ASSERT_NE(-1, fcntl(fd, F_SETLK, &fl)) << strerror(errno);
|
||||
leak(fd);
|
||||
}
|
||||
|
||||
/* Set a new lock with FUSE_SETLK */
|
||||
TEST_F(Setlk, set)
|
||||
{
|
||||
@ -465,7 +508,7 @@ TEST_F(Setlkw, set)
|
||||
|
||||
expect_lookup(RELPATH, ino);
|
||||
expect_open(ino, 0, 1);
|
||||
expect_setlk(ino, pid, 10, 1009, F_RDLCK, 0);
|
||||
expect_setlkw(ino, pid, 10, 1009, F_RDLCK, 0);
|
||||
|
||||
fd = open(FULLPATH, O_RDWR);
|
||||
ASSERT_LE(0, fd) << strerror(errno);
|
||||
|
@ -206,6 +206,16 @@ TEST_F(ReleaseWithLocks, unlock_on_close)
|
||||
ResultOf([=](auto in) {
|
||||
return (in.header.opcode == FUSE_SETLK &&
|
||||
in.header.nodeid == ino &&
|
||||
in.body.setlk.lk.type == F_RDLCK &&
|
||||
in.body.setlk.fh == FH);
|
||||
}, Eq(true)),
|
||||
_)
|
||||
).WillOnce(Invoke(ReturnErrno(0)));
|
||||
EXPECT_CALL(*m_mock, process(
|
||||
ResultOf([=](auto in) {
|
||||
return (in.header.opcode == FUSE_SETLK &&
|
||||
in.header.nodeid == ino &&
|
||||
in.body.setlk.lk.type == F_UNLCK &&
|
||||
in.body.setlk.fh == FH);
|
||||
}, Eq(true)),
|
||||
_)
|
||||
@ -221,7 +231,7 @@ TEST_F(ReleaseWithLocks, unlock_on_close)
|
||||
fl.l_type = F_RDLCK;
|
||||
fl.l_whence = SEEK_SET;
|
||||
fl.l_sysid = 0;
|
||||
ASSERT_NE(-1, fcntl(fd, F_SETLKW, &fl)) << strerror(errno);
|
||||
ASSERT_NE(-1, fcntl(fd, F_SETLK, &fl)) << strerror(errno);
|
||||
|
||||
ASSERT_EQ(0, close(fd)) << strerror(errno);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user