@@ -1864,6 +1864,126 @@ static int qgroup_update_refcnt(struct btrfs_fs_info *fs_info,
18641864 return 0 ;
18651865}
18661866
1867+ /*
1868+ * Update qgroup rfer/excl counters.
1869+ * Rfer update is easy, codes can explain themselves.
1870+ * Excl update is tricky, the update is split into 2 part.
1871+ * Part 1: Possible exclusive <-> sharing detect:
1872+ * | A | !A |
1873+ * -------------------------------------
1874+ * B | * | - |
1875+ * -------------------------------------
1876+ * !B | + | ** |
1877+ * -------------------------------------
1878+ *
1879+ * Conditions:
1880+ * A: cur_old_roots < nr_old_roots (not exclusive before)
1881+ * !A: cur_old_roots == nr_old_roots (possible exclusive before)
1882+ * B: cur_new_roots < nr_new_roots (not exclusive now)
1883+ * !B: cur_new_roots == nr_new_roots (possible exclsuive now)
1884+ *
1885+ * Results:
1886+ * +: Possible sharing -> exclusive -: Possible exclusive -> sharing
1887+ * *: Definitely not changed. **: Possible unchanged.
1888+ *
1889+ * For !A and !B condition, the exception is cur_old/new_roots == 0 case.
1890+ *
1891+ * To make the logic clear, we first use condition A and B to split
1892+ * combination into 4 results.
1893+ *
1894+ * Then, for result "+" and "-", check old/new_roots == 0 case, as in them
1895+ * only on variant maybe 0.
1896+ *
1897+ * Lastly, check result **, since there are 2 variants maybe 0, split them
1898+ * again(2x2).
1899+ * But this time we don't need to consider other things, the codes and logic
1900+ * is easy to understand now.
1901+ */
1902+ static int qgroup_update_counters (struct btrfs_fs_info * fs_info ,
1903+ struct ulist * qgroups ,
1904+ u64 nr_old_roots ,
1905+ u64 nr_new_roots ,
1906+ u64 num_bytes , u64 seq )
1907+ {
1908+ struct ulist_node * unode ;
1909+ struct ulist_iterator uiter ;
1910+ struct btrfs_qgroup * qg ;
1911+ u64 cur_new_count , cur_old_count ;
1912+
1913+ ULIST_ITER_INIT (& uiter );
1914+ while ((unode = ulist_next (qgroups , & uiter ))) {
1915+ bool dirty = false;
1916+
1917+ qg = u64_to_ptr (unode -> aux );
1918+ cur_old_count = btrfs_qgroup_get_old_refcnt (qg , seq );
1919+ cur_new_count = btrfs_qgroup_get_new_refcnt (qg , seq );
1920+
1921+ /* Rfer update part */
1922+ if (cur_old_count == 0 && cur_new_count > 0 ) {
1923+ qg -> rfer += num_bytes ;
1924+ qg -> rfer_cmpr += num_bytes ;
1925+ dirty = true;
1926+ }
1927+ if (cur_old_count > 0 && cur_new_count == 0 ) {
1928+ qg -> rfer -= num_bytes ;
1929+ qg -> rfer_cmpr -= num_bytes ;
1930+ dirty = true;
1931+ }
1932+
1933+ /* Excl update part */
1934+ /* Exclusive/none -> shared case */
1935+ if (cur_old_count == nr_old_roots &&
1936+ cur_new_count < nr_new_roots ) {
1937+ /* Exclusive -> shared */
1938+ if (cur_old_count != 0 ) {
1939+ qg -> excl -= num_bytes ;
1940+ qg -> excl_cmpr -= num_bytes ;
1941+ dirty = true;
1942+ }
1943+ }
1944+
1945+ /* Shared -> exclusive/none case */
1946+ if (cur_old_count < nr_old_roots &&
1947+ cur_new_count == nr_new_roots ) {
1948+ /* Shared->exclusive */
1949+ if (cur_new_count != 0 ) {
1950+ qg -> excl += num_bytes ;
1951+ qg -> excl_cmpr += num_bytes ;
1952+ dirty = true;
1953+ }
1954+ }
1955+
1956+ /* Exclusive/none -> exclusive/none case */
1957+ if (cur_old_count == nr_old_roots &&
1958+ cur_new_count == nr_new_roots ) {
1959+ if (cur_old_count == 0 ) {
1960+ /* None -> exclusive/none */
1961+
1962+ if (cur_new_count != 0 ) {
1963+ /* None -> exclusive */
1964+ qg -> excl += num_bytes ;
1965+ qg -> excl_cmpr += num_bytes ;
1966+ dirty = true;
1967+ }
1968+ /* None -> none, nothing changed */
1969+ } else {
1970+ /* Exclusive -> exclusive/none */
1971+
1972+ if (cur_new_count == 0 ) {
1973+ /* Exclusive -> none */
1974+ qg -> excl -= num_bytes ;
1975+ qg -> excl_cmpr -= num_bytes ;
1976+ dirty = true;
1977+ }
1978+ /* Exclusive -> exclusive, nothing changed */
1979+ }
1980+ }
1981+ if (dirty )
1982+ qgroup_dirty (fs_info , qg );
1983+ }
1984+ return 0 ;
1985+ }
1986+
18671987/*
18681988 * This adjusts the counters for all referenced qgroups if need be.
18691989 */
0 commit comments