Set the refcount for a cluster with the given address. Returns a list of any refblocks that can be reused, this happens when a refblock is moved, the old location can be reused.
(&mut self, address: u64, refcount: u64)
| 1896 | // Returns a list of any refblocks that can be reused, this happens when a refblock is moved, |
| 1897 | // the old location can be reused. |
| 1898 | fn set_cluster_refcount(&mut self, address: u64, refcount: u64) -> std::io::Result<Vec<u64>> { |
| 1899 | let mut added_clusters = Vec::new(); |
| 1900 | let mut unref_clusters = Vec::new(); |
| 1901 | let mut refcount_set = false; |
| 1902 | let mut new_cluster = None; |
| 1903 | |
| 1904 | while !refcount_set { |
| 1905 | match self.refcounts.set_cluster_refcount( |
| 1906 | &mut self.raw_file, |
| 1907 | address, |
| 1908 | refcount, |
| 1909 | new_cluster.take(), |
| 1910 | ) { |
| 1911 | Ok(None) => { |
| 1912 | refcount_set = true; |
| 1913 | } |
| 1914 | Ok(Some(freed_cluster)) => { |
| 1915 | // Recursively set the freed refcount block's refcount to 0 |
| 1916 | let mut freed = self.set_cluster_refcount(freed_cluster, 0)?; |
| 1917 | unref_clusters.append(&mut freed); |
| 1918 | refcount_set = true; |
| 1919 | } |
| 1920 | Err(refcount::Error::EvictingRefCounts(e)) => { |
| 1921 | return Err(e); |
| 1922 | } |
| 1923 | Err(refcount::Error::InvalidIndex) => { |
| 1924 | self.set_corrupt_bit_best_effort(); |
| 1925 | return Err(std::io::Error::from_raw_os_error(EINVAL)); |
| 1926 | } |
| 1927 | Err(refcount::Error::NeedCluster(addr)) => { |
| 1928 | // Read the address and call set_cluster_refcount again. |
| 1929 | new_cluster = Some(( |
| 1930 | addr, |
| 1931 | VecCache::from_vec(self.raw_file.read_refcount_block(addr)?), |
| 1932 | )); |
| 1933 | } |
| 1934 | Err(refcount::Error::NeedNewCluster) => { |
| 1935 | // Allocate the cluster and call set_cluster_refcount again. |
| 1936 | let addr = self.get_new_cluster(None)?; |
| 1937 | added_clusters.push(addr); |
| 1938 | new_cluster = Some(( |
| 1939 | addr, |
| 1940 | VecCache::new(self.refcounts.refcounts_per_block() as usize), |
| 1941 | )); |
| 1942 | } |
| 1943 | Err(refcount::Error::ReadingRefCounts(e)) => { |
| 1944 | return Err(e); |
| 1945 | } |
| 1946 | Err(refcount::Error::RefcountOverflow { .. }) => { |
| 1947 | return Err(std::io::Error::from_raw_os_error(EINVAL)); |
| 1948 | } |
| 1949 | Err(refcount::Error::RefblockUnaligned(_)) => { |
| 1950 | self.set_corrupt_bit_best_effort(); |
| 1951 | return Err(io::Error::from_raw_os_error(EIO)); |
| 1952 | } |
| 1953 | } |
| 1954 | } |
| 1955 |