mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-09 05:16:47 +00:00
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:
parent
349d7baa24
commit
c875201c3f
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user