aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/qgroup.c
diff options
context:
space:
mode:
authorQu Wenruo <quwenruo@cn.fujitsu.com>2015-04-12 04:59:57 -0400
committerChris Mason <clm@fb.com>2015-06-10 12:25:28 -0400
commit823ae5b8e340003dacbe7cd08a355efe018c9f1b (patch)
treeefc852b58959ab5f163078708a14064e0c8cbbd2 /fs/btrfs/qgroup.c
parentd810ef2be5b8b15c9b6f88f9a09b1b4b16e30871 (diff)
btrfs: qgroup: Add function qgroup_update_counters().
Add function qgroup_update_counters(), which will update related qgroups' rfer/excl according to old/new_roots. This is one of the two core functions for the new qgroup implement. This is based on btrfs_adjust_coutners() but with clearer logic and comment. Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com> Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs/btrfs/qgroup.c')
-rw-r--r--fs/btrfs/qgroup.c120
1 files changed, 120 insertions, 0 deletions
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
index 81773176d01f..2f185eee2387 100644
--- a/fs/btrfs/qgroup.c
+++ b/fs/btrfs/qgroup.c
@@ -1865,6 +1865,126 @@ static int qgroup_update_refcnt(struct btrfs_fs_info *fs_info,
1865} 1865}
1866 1866
1867/* 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 */
1902static 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
1987/*
1868 * This adjusts the counters for all referenced qgroups if need be. 1988 * This adjusts the counters for all referenced qgroups if need be.
1869 */ 1989 */
1870static int qgroup_adjust_counters(struct btrfs_fs_info *fs_info, 1990static int qgroup_adjust_counters(struct btrfs_fs_info *fs_info,