Fix deadlocks that may arise after converting virtio-blk to async

The IRQ part of the driver must NOT share a SpinLock with
the normal part of the driver unless the SpinLock is acquired
with IRQ disabled in the task context.
This commit is contained in:
LI Qing 2024-04-26 11:53:33 +08:00 committed by Tate, Hongliang Tian
parent 349d7baa24
commit c875201c3f
2 changed files with 11 additions and 11 deletions

View File

@ -92,10 +92,7 @@ impl IndirectBlockCache {
return Ok(()); return Ok(());
} }
// TODO: How to determine the number of evictions each time? // TODO: How to determine the number of evictions each time?
// let evict_num = Self::MAX_SIZE / 2;
// FIXME: When we set it to `Self::MAX_SIZE / 2` here,
// running the `/regression/ext2.sh` test may cause a deadlock issue.
let evict_num = 1;
self.evict(evict_num) self.evict(evict_num)
} }

View File

@ -152,10 +152,13 @@ impl DeviceInner {
/// Handles the irq issued from the device /// Handles the irq issued from the device
fn handle_irq(&self) { fn handle_irq(&self) {
info!("Virtio block device handle irq"); info!("Virtio block device handle irq");
// When we enter the IRQs handling function,
// IRQs have already been disabled,
// so there is no need to call `lock_irq_disabled`.
loop { loop {
// Pops the complete request // Pops the complete request
let complete_request = { let complete_request = {
let mut queue = self.queue.lock_irq_disabled(); let mut queue = self.queue.lock();
let Ok((token, _)) = queue.pop_used() else { let Ok((token, _)) = queue.pop_used() else {
return; return;
}; };
@ -198,7 +201,7 @@ impl DeviceInner {
// TODO: Most logic is the same as read and write, there should be a refactor. // TODO: Most logic is the same as read and write, there should be a refactor.
// TODO: Should return an Err instead of panic if the device fails. // TODO: Should return an Err instead of panic if the device fails.
fn request_device_id(&self) -> String { fn request_device_id(&self) -> String {
let id = self.id_allocator.lock().alloc().unwrap(); let id = self.id_allocator.lock_irq_disabled().alloc().unwrap();
let req_slice = { let req_slice = {
let req_slice = DmaStreamSlice::new(&self.block_requests, id * REQ_SIZE, REQ_SIZE); let req_slice = DmaStreamSlice::new(&self.block_requests, id * REQ_SIZE, REQ_SIZE);
let req = BlockReq { let req = BlockReq {
@ -241,7 +244,7 @@ impl DeviceInner {
queue.pop_used_with_token(token).expect("pop used failed"); queue.pop_used_with_token(token).expect("pop used failed");
resp_slice.sync().unwrap(); resp_slice.sync().unwrap();
self.id_allocator.lock().free(id); self.id_allocator.lock_irq_disabled().free(id);
let resp: BlockResp = resp_slice.read_val(0).unwrap(); let resp: BlockResp = resp_slice.read_val(0).unwrap();
match RespStatus::try_from(resp.status).unwrap() { match RespStatus::try_from(resp.status).unwrap() {
RespStatus::Ok => {} RespStatus::Ok => {}
@ -266,7 +269,7 @@ impl DeviceInner {
fn read(&self, bio_request: BioRequest) { fn read(&self, bio_request: BioRequest) {
let dma_streams = Self::dma_stream_map(&bio_request); let dma_streams = Self::dma_stream_map(&bio_request);
let id = self.id_allocator.lock().alloc().unwrap(); let id = self.id_allocator.lock_irq_disabled().alloc().unwrap();
let req_slice = { let req_slice = {
let req_slice = DmaStreamSlice::new(&self.block_requests, id * REQ_SIZE, REQ_SIZE); let req_slice = DmaStreamSlice::new(&self.block_requests, id * REQ_SIZE, REQ_SIZE);
let req = BlockReq { let req = BlockReq {
@ -317,7 +320,7 @@ impl DeviceInner {
// Records the submitted request // Records the submitted request
let submitted_request = SubmittedRequest::new(id as u16, bio_request, dma_streams); let submitted_request = SubmittedRequest::new(id as u16, bio_request, dma_streams);
self.submitted_requests self.submitted_requests
.lock() .lock_irq_disabled()
.insert(token, submitted_request); .insert(token, submitted_request);
return; return;
} }
@ -327,7 +330,7 @@ impl DeviceInner {
fn write(&self, bio_request: BioRequest) { fn write(&self, bio_request: BioRequest) {
let dma_streams = Self::dma_stream_map(&bio_request); let dma_streams = Self::dma_stream_map(&bio_request);
let id = self.id_allocator.lock().alloc().unwrap(); let id = self.id_allocator.lock_irq_disabled().alloc().unwrap();
let req_slice = { let req_slice = {
let req_slice = DmaStreamSlice::new(&self.block_requests, id * REQ_SIZE, REQ_SIZE); let req_slice = DmaStreamSlice::new(&self.block_requests, id * REQ_SIZE, REQ_SIZE);
let req = BlockReq { let req = BlockReq {
@ -377,7 +380,7 @@ impl DeviceInner {
// Records the submitted request // Records the submitted request
let submitted_request = SubmittedRequest::new(id as u16, bio_request, dma_streams); let submitted_request = SubmittedRequest::new(id as u16, bio_request, dma_streams);
self.submitted_requests self.submitted_requests
.lock() .lock_irq_disabled()
.insert(token, submitted_request); .insert(token, submitted_request);
return; return;
} }