New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement open file descriptor locks in fcntl #1195
Changes from 13 commits
08be41e
360bdfb
b56fb4c
2ae45b8
8252142
ef01f46
6075ce0
87f33c3
2d90033
3332c08
1478315
4c4df3c
5e2d14b
f7f1d09
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -65,13 +65,15 @@ fn test_readlink() { | |
|
||
#[cfg(any(target_os = "linux", target_os = "android"))] | ||
mod linux_android { | ||
use std::fs::File; | ||
use std::io::prelude::*; | ||
use std::io::SeekFrom; | ||
use std::io::{BufRead, BufReader, SeekFrom}; | ||
use std::os::unix::prelude::*; | ||
|
||
use libc::loff_t; | ||
|
||
use nix::fcntl::*; | ||
use nix::sys::stat::fstat; | ||
use nix::sys::uio::IoVec; | ||
use nix::unistd::{close, pipe, read, write}; | ||
|
||
|
@@ -197,6 +199,72 @@ mod linux_android { | |
let mut buf = [0u8; 200]; | ||
assert_eq!(100, read(fd, &mut buf).unwrap()); | ||
} | ||
|
||
// This test is disabled for the target architectures below | ||
// due to OFD locks not being available in the kernel/libc | ||
// versions used in the CI environment. | ||
#[test] | ||
#[cfg(not(any(target_arch = "aarch64", | ||
target_arch = "arm", | ||
target_arch = "armv7", | ||
target_arch = "x86", | ||
target_arch = "mips", | ||
target_arch = "mips64", | ||
target_arch = "mips64el", | ||
target_arch = "powerpc64", | ||
target_arch = "powerpc64le")))] | ||
fn test_ofd_locks() { | ||
let tmp = NamedTempFile::new().unwrap(); | ||
|
||
let fd = tmp.as_raw_fd(); | ||
let inode = fstat(fd).expect("fstat failed").st_ino as usize; | ||
|
||
let mut flock = libc::flock { | ||
l_type: libc::F_WRLCK as libc::c_short, | ||
l_whence: libc::SEEK_SET as libc::c_short, | ||
l_start: 0, | ||
l_len: 0, | ||
l_pid: 0, | ||
}; | ||
fcntl(fd, FcntlArg::F_OFD_SETLKW(&flock)).expect("write lock failed"); | ||
assert_eq!( | ||
Some(("OFDLCK".to_string(), "WRITE".to_string())), | ||
lock_info(inode) | ||
); | ||
|
||
flock.l_type = libc::F_UNLCK as libc::c_short; | ||
fcntl(fd, FcntlArg::F_OFD_SETLKW(&flock)).expect("write unlock failed"); | ||
assert_eq!(None, lock_info(inode)); | ||
|
||
flock.l_type = libc::F_RDLCK as libc::c_short; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It looks like this test is doing two separate things: setting and clearing a write lock, and setting and clearing a read lock. Please split it up into two separate tests. That will make it easier to debug. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||
fcntl(fd, FcntlArg::F_OFD_SETLKW(&flock)).expect("read lock failed"); | ||
assert_eq!( | ||
Some(("OFDLCK".to_string(), "READ".to_string())), | ||
lock_info(inode) | ||
); | ||
|
||
flock.l_type = libc::F_UNLCK as libc::c_short; | ||
fcntl(fd, FcntlArg::F_OFD_SETLKW(&flock)).expect("read unlock failed"); | ||
assert_eq!(None, lock_info(inode)); | ||
} | ||
|
||
fn lock_info(inode: usize) -> Option<(String, String)> { | ||
let file = File::open("/proc/locks").expect("open /proc/locks failed"); | ||
let buf = BufReader::new(file); | ||
|
||
for line in buf.lines() { | ||
let line = line.unwrap(); | ||
let parts: Vec<_> = line.split_whitespace().collect(); | ||
let lock_type = parts[1]; | ||
let lock_access = parts[3]; | ||
let ino_parts: Vec<_> = parts[5].split(':').collect(); | ||
let ino: usize = ino_parts[2].parse().unwrap(); | ||
if ino == inode { | ||
return Some((lock_type.to_string(), lock_access.to_string())); | ||
} | ||
} | ||
None | ||
} | ||
} | ||
|
||
#[cfg(any(target_os = "linux", | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's probably related to the fact that CI for these platforms runs under QEMU.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've amended the comment.