(&mut self)
| 1960 | } |
| 1961 | |
| 1962 | fn sync_caches(&mut self) -> std::io::Result<()> { |
| 1963 | // Write out all dirty L2 tables. |
| 1964 | for (l1_index, l2_table) in self.l2_cache.iter_mut().filter(|(_k, v)| v.dirty()) { |
| 1965 | // The index must be valid from when we inserted it. |
| 1966 | let addr = self.l1_table[*l1_index]; |
| 1967 | if addr != 0 { |
| 1968 | self.raw_file |
| 1969 | .write_pointer_table_direct(addr, l2_table.iter())?; |
| 1970 | } else { |
| 1971 | self.set_corrupt_bit_best_effort(); |
| 1972 | return Err(std::io::Error::from_raw_os_error(EINVAL)); |
| 1973 | } |
| 1974 | l2_table.mark_clean(); |
| 1975 | } |
| 1976 | // Write the modified refcount blocks. |
| 1977 | self.refcounts.flush_blocks(&mut self.raw_file)?; |
| 1978 | // Make sure metadata(file len) and all data clusters are written. |
| 1979 | self.raw_file.file_mut().sync_all()?; |
| 1980 | |
| 1981 | // Push L1 table and refcount table last as all the clusters they point to are now |
| 1982 | // guaranteed to be valid. |
| 1983 | let mut sync_required = if self.l1_table.dirty() { |
| 1984 | // Write L1 table with OFLAG_COPIED bits |
| 1985 | let refcounts = &mut self.refcounts; |
| 1986 | self.raw_file.write_pointer_table( |
| 1987 | self.header.l1_table_offset, |
| 1988 | self.l1_table.iter(), |
| 1989 | |raw_file, l2_addr| { |
| 1990 | if l2_addr == 0 { |
| 1991 | Ok(0) |
| 1992 | } else { |
| 1993 | let refcount = refcounts |
| 1994 | .get_cluster_refcount(raw_file, l2_addr) |
| 1995 | .map_err(|e| std::io::Error::other(Error::GettingRefcount(e)))?; |
| 1996 | Ok(l1_entry_make(l2_addr, refcount == 1)) |
| 1997 | } |
| 1998 | }, |
| 1999 | )?; |
| 2000 | self.l1_table.mark_clean(); |
| 2001 | true |
| 2002 | } else { |
| 2003 | false |
| 2004 | }; |
| 2005 | sync_required |= self.refcounts.flush_table(&mut self.raw_file)?; |
| 2006 | if sync_required { |
| 2007 | self.raw_file.file_mut().sync_data()?; |
| 2008 | } |
| 2009 | |
| 2010 | Ok(()) |
| 2011 | } |
| 2012 | } |
| 2013 | |
| 2014 | impl AsRawFd for QcowFile { |
no test coverage detected