@@ -18,7 +18,7 @@ use utils::eventfd::EventFd;
1818use utils:: net:: mac:: MacAddr ;
1919use utils:: ring_buffer:: RingBuffer ;
2020use utils:: { u64_to_usize, usize_to_u64} ;
21- use vm_memory:: VolatileMemoryError ;
21+ use vm_memory:: { GuestAddress , GuestMemory , VolatileMemoryError } ;
2222
2323use crate :: devices:: virtio:: device:: { DeviceState , IrqTrigger , IrqType , VirtioDevice } ;
2424use crate :: devices:: virtio:: gen:: virtio_blk:: VIRTIO_F_VERSION_1 ;
@@ -156,23 +156,86 @@ impl AvailableDescriptors {
156156
157157 /// Read new descriptor chains from the queue.
158158 pub fn read_new_desc_chains ( & mut self , queue : & mut Queue , mem : & GuestMemoryMmap ) {
159- for _ in 0 ..queue. len ( mem) {
159+ #[ repr( C ) ]
160+ struct AvailRing {
161+ flags : u16 ,
162+ idx : u16 ,
163+ ring : [ u16 ; 256 ] ,
164+ used_event : u16 ,
165+ }
166+ #[ repr( C ) ]
167+ #[ derive( Default , Clone , Copy ) ]
168+ struct Descriptor {
169+ addr : u64 ,
170+ len : u32 ,
171+ flags : u16 ,
172+ next : u16 ,
173+ }
174+
175+ // SAFETY:
176+ // avail_ring in the queue is a valid guest address
177+ let avail_ring: & AvailRing =
178+ unsafe { std:: mem:: transmute ( mem. get_host_address ( queue. avail_ring ) . unwrap ( ) ) } ;
179+
180+ // SAFETY:
181+ // desc_table in the queue is a valid guest address
182+ let desc_table: & [ Descriptor ; 256 ] =
183+ unsafe { std:: mem:: transmute ( mem. get_host_address ( queue. desc_table ) . unwrap ( ) ) } ;
184+
185+ let avail_idx = queue. avail_idx ( mem) ;
186+ let actual_size = queue. actual_size ( ) ;
187+
188+ while queue. next_avail . 0 != avail_idx. 0 {
160189 let Some ( next_iovec_buf) = self . iov_ring . next_available ( ) else {
161190 break ;
162191 } ;
163192
164- match queue. do_pop_unchecked ( mem) {
165- Some ( desc_chain) => {
166- // SAFETY:
167- // This descriptor chain is only processed once.
168- let valid = unsafe { next_iovec_buf. load_descriptor_chain ( desc_chain) . is_ok ( ) } ;
169- self . valid_ring . push ( valid) ;
170- }
171- None => {
172- self . valid_ring . push ( false ) ;
173- }
193+ let avail_index = queue. next_avail . 0 % actual_size;
194+ queue. next_avail += Wrapping ( 1 ) ;
195+
196+ let desc_index = avail_ring. ring [ avail_index as usize ] ;
197+ let mut desc = & desc_table[ desc_index as usize ] ;
198+
199+ next_iovec_buf. clear ( ) ;
200+ next_iovec_buf. head_index = desc_index;
201+
202+ let iov = libc:: iovec {
203+ iov_base : mem. get_host_address ( GuestAddress ( desc. addr ) ) . unwrap ( ) . cast ( ) ,
204+ iov_len : desc. len as usize ,
205+ } ;
206+ next_iovec_buf. vecs . push ( iov) ;
207+ next_iovec_buf. len += desc. len ;
208+ self . valid_ring . push ( true ) ;
209+
210+ while desc. flags & crate :: devices:: virtio:: queue:: VIRTQ_DESC_F_NEXT != 0 {
211+ desc = & desc_table[ desc. next as usize ] ;
212+ let iov = libc:: iovec {
213+ iov_base : mem. get_host_address ( GuestAddress ( desc. addr ) ) . unwrap ( ) . cast ( ) ,
214+ iov_len : desc. len as usize ,
215+ } ;
216+ next_iovec_buf. vecs . push ( iov) ;
217+ next_iovec_buf. len += desc. len ;
218+ self . valid_ring . push ( true ) ;
174219 }
175220 }
221+
222+ // for _ in 0..queue.len(mem) {
223+ // let Some(next_iovec_buf) = self.iov_ring.next_available() else {
224+ // break;
225+ // };
226+ //
227+ // match queue.do_pop_unchecked(mem) {
228+ // Some(desc_chain) => {
229+ // // SAFETY:
230+ // // This descriptor chain is only processed once.
231+ // let valid = unsafe { next_iovec_buf.load_descriptor_chain(desc_chain).is_ok() };
232+ // self.valid_ring.push(valid);
233+ // }
234+ // None => {
235+ // self.valid_ring.push(false);
236+ // }
237+ // }
238+ // }
176239 }
177240
178241 /// Pop first descriptor chain.
0 commit comments