Fix flock lost-wakeup bugs, replace RwMutex -> Mutex

This commit is contained in:
Ruize Tang
2024-10-24 17:34:49 +08:00
committed by Tate, Hongliang Tian
parent d977fe54c6
commit e5fd8e7477

View File

@ -2,7 +2,7 @@
use alloc::fmt; use alloc::fmt;
use core::ptr; use core::ptr;
use ostd::sync::WaitQueue; use ostd::sync::{WaitQueue, Waiter};
use crate::{ use crate::{
fs::{file_handle::FileLike, inode_handle::InodeHandle}, fs::{file_handle::FileLike, inode_handle::InodeHandle},
@ -62,12 +62,6 @@ impl FlockItem {
false false
} }
/// Waits until the lock can be acquired.
pub fn wait(&self) {
let cond = || None::<()>;
self.waitqueue.wait_until(cond);
}
/// Wakes all threads that are waiting for this lock. /// Wakes all threads that are waiting for this lock.
pub fn wake_all(&self) { pub fn wake_all(&self) {
self.waitqueue.wake_all(); self.waitqueue.wake_all();
@ -102,14 +96,14 @@ impl Debug for FlockItem {
/// Represents a list of non-POSIX file advisory locks (FLOCK). /// Represents a list of non-POSIX file advisory locks (FLOCK).
/// The list is used to manage file locks and resolve conflicts between them. /// The list is used to manage file locks and resolve conflicts between them.
pub struct FlockList { pub struct FlockList {
inner: RwMutex<VecDeque<FlockItem>>, inner: Mutex<VecDeque<FlockItem>>,
} }
impl FlockList { impl FlockList {
/// Creates a new FlockList. /// Creates a new FlockList.
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
inner: RwMutex::new(VecDeque::new()), inner: Mutex::new(VecDeque::new()),
} }
} }
@ -123,14 +117,15 @@ impl FlockList {
req_lock, is_nonblocking req_lock, is_nonblocking
); );
loop { loop {
let conflict_lock; let (waiter, waker);
{ {
let mut list = self.inner.write(); let mut list = self.inner.lock();
if let Some(existing_lock) = list.iter().find(|l| req_lock.conflict_with(l)) { if let Some(existing_lock) = list.iter().find(|l| req_lock.conflict_with(l)) {
if is_nonblocking { if is_nonblocking {
return_errno_with_message!(Errno::EAGAIN, "the file is locked"); return_errno_with_message!(Errno::EAGAIN, "the file is locked");
} }
conflict_lock = existing_lock.clone(); (waiter, waker) = Waiter::new_pair();
existing_lock.waitqueue.enqueue(waker);
} else { } else {
match list.iter().position(|l| req_lock.same_owner_with(l)) { match list.iter().position(|l| req_lock.same_owner_with(l)) {
Some(idx) => { Some(idx) => {
@ -143,7 +138,7 @@ impl FlockList {
return Ok(()); return Ok(());
} }
} }
conflict_lock.wait(); waiter.wait();
} }
} }
@ -157,7 +152,7 @@ impl FlockList {
"unlock with owner: {:?}", "unlock with owner: {:?}",
req_owner as *const InodeHandle<R> req_owner as *const InodeHandle<R>
); );
let mut list = self.inner.write(); let mut list = self.inner.lock();
list.retain(|lock| { list.retain(|lock| {
if let Some(owner) = lock.owner() { if let Some(owner) = lock.owner() {
if ptr::eq( if ptr::eq(