diff options
| author | Qu Wenruo <quwenruo@cn.fujitsu.com> | 2015-04-12 04:59:57 -0400 |
|---|---|---|
| committer | Chris Mason <clm@fb.com> | 2015-06-10 12:25:28 -0400 |
| commit | 823ae5b8e340003dacbe7cd08a355efe018c9f1b (patch) | |
| tree | efc852b58959ab5f163078708a14064e0c8cbbd2 /fs/btrfs/qgroup.c | |
| parent | d810ef2be5b8b15c9b6f88f9a09b1b4b16e30871 (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.c | 120 |
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 | */ | ||
| 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 | |||
| 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 | */ |
| 1870 | static int qgroup_adjust_counters(struct btrfs_fs_info *fs_info, | 1990 | static int qgroup_adjust_counters(struct btrfs_fs_info *fs_info, |
