diff options
Diffstat (limited to 'fs/btrfs/qgroup.c')
-rw-r--r-- | fs/btrfs/qgroup.c | 63 |
1 files changed, 41 insertions, 22 deletions
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c index 5279fdae7142..9e119552ed32 100644 --- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c | |||
@@ -1463,6 +1463,7 @@ struct btrfs_qgroup_extent_record | |||
1463 | u64 bytenr = record->bytenr; | 1463 | u64 bytenr = record->bytenr; |
1464 | 1464 | ||
1465 | assert_spin_locked(&delayed_refs->lock); | 1465 | assert_spin_locked(&delayed_refs->lock); |
1466 | trace_btrfs_qgroup_insert_dirty_extent(record); | ||
1466 | 1467 | ||
1467 | while (*p) { | 1468 | while (*p) { |
1468 | parent_node = *p; | 1469 | parent_node = *p; |
@@ -1594,6 +1595,9 @@ static int qgroup_update_counters(struct btrfs_fs_info *fs_info, | |||
1594 | cur_old_count = btrfs_qgroup_get_old_refcnt(qg, seq); | 1595 | cur_old_count = btrfs_qgroup_get_old_refcnt(qg, seq); |
1595 | cur_new_count = btrfs_qgroup_get_new_refcnt(qg, seq); | 1596 | cur_new_count = btrfs_qgroup_get_new_refcnt(qg, seq); |
1596 | 1597 | ||
1598 | trace_qgroup_update_counters(qg->qgroupid, cur_old_count, | ||
1599 | cur_new_count); | ||
1600 | |||
1597 | /* Rfer update part */ | 1601 | /* Rfer update part */ |
1598 | if (cur_old_count == 0 && cur_new_count > 0) { | 1602 | if (cur_old_count == 0 && cur_new_count > 0) { |
1599 | qg->rfer += num_bytes; | 1603 | qg->rfer += num_bytes; |
@@ -1683,6 +1687,9 @@ btrfs_qgroup_account_extent(struct btrfs_trans_handle *trans, | |||
1683 | goto out_free; | 1687 | goto out_free; |
1684 | BUG_ON(!fs_info->quota_root); | 1688 | BUG_ON(!fs_info->quota_root); |
1685 | 1689 | ||
1690 | trace_btrfs_qgroup_account_extent(bytenr, num_bytes, nr_old_roots, | ||
1691 | nr_new_roots); | ||
1692 | |||
1686 | qgroups = ulist_alloc(GFP_NOFS); | 1693 | qgroups = ulist_alloc(GFP_NOFS); |
1687 | if (!qgroups) { | 1694 | if (!qgroups) { |
1688 | ret = -ENOMEM; | 1695 | ret = -ENOMEM; |
@@ -1752,6 +1759,8 @@ int btrfs_qgroup_account_extents(struct btrfs_trans_handle *trans, | |||
1752 | record = rb_entry(node, struct btrfs_qgroup_extent_record, | 1759 | record = rb_entry(node, struct btrfs_qgroup_extent_record, |
1753 | node); | 1760 | node); |
1754 | 1761 | ||
1762 | trace_btrfs_qgroup_account_extents(record); | ||
1763 | |||
1755 | if (!ret) { | 1764 | if (!ret) { |
1756 | /* | 1765 | /* |
1757 | * Use (u64)-1 as time_seq to do special search, which | 1766 | * Use (u64)-1 as time_seq to do special search, which |
@@ -1842,8 +1851,10 @@ out: | |||
1842 | } | 1851 | } |
1843 | 1852 | ||
1844 | /* | 1853 | /* |
1845 | * copy the acounting information between qgroups. This is necessary when a | 1854 | * Copy the acounting information between qgroups. This is necessary |
1846 | * snapshot or a subvolume is created | 1855 | * when a snapshot or a subvolume is created. Throwing an error will |
1856 | * cause a transaction abort so we take extra care here to only error | ||
1857 | * when a readonly fs is a reasonable outcome. | ||
1847 | */ | 1858 | */ |
1848 | int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans, | 1859 | int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans, |
1849 | struct btrfs_fs_info *fs_info, u64 srcid, u64 objectid, | 1860 | struct btrfs_fs_info *fs_info, u64 srcid, u64 objectid, |
@@ -1873,15 +1884,15 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans, | |||
1873 | 2 * inherit->num_excl_copies; | 1884 | 2 * inherit->num_excl_copies; |
1874 | for (i = 0; i < nums; ++i) { | 1885 | for (i = 0; i < nums; ++i) { |
1875 | srcgroup = find_qgroup_rb(fs_info, *i_qgroups); | 1886 | srcgroup = find_qgroup_rb(fs_info, *i_qgroups); |
1876 | if (!srcgroup) { | ||
1877 | ret = -EINVAL; | ||
1878 | goto out; | ||
1879 | } | ||
1880 | 1887 | ||
1881 | if ((srcgroup->qgroupid >> 48) <= (objectid >> 48)) { | 1888 | /* |
1882 | ret = -EINVAL; | 1889 | * Zero out invalid groups so we can ignore |
1883 | goto out; | 1890 | * them later. |
1884 | } | 1891 | */ |
1892 | if (!srcgroup || | ||
1893 | ((srcgroup->qgroupid >> 48) <= (objectid >> 48))) | ||
1894 | *i_qgroups = 0ULL; | ||
1895 | |||
1885 | ++i_qgroups; | 1896 | ++i_qgroups; |
1886 | } | 1897 | } |
1887 | } | 1898 | } |
@@ -1916,17 +1927,19 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans, | |||
1916 | */ | 1927 | */ |
1917 | if (inherit) { | 1928 | if (inherit) { |
1918 | i_qgroups = (u64 *)(inherit + 1); | 1929 | i_qgroups = (u64 *)(inherit + 1); |
1919 | for (i = 0; i < inherit->num_qgroups; ++i) { | 1930 | for (i = 0; i < inherit->num_qgroups; ++i, ++i_qgroups) { |
1931 | if (*i_qgroups == 0) | ||
1932 | continue; | ||
1920 | ret = add_qgroup_relation_item(trans, quota_root, | 1933 | ret = add_qgroup_relation_item(trans, quota_root, |
1921 | objectid, *i_qgroups); | 1934 | objectid, *i_qgroups); |
1922 | if (ret) | 1935 | if (ret && ret != -EEXIST) |
1923 | goto out; | 1936 | goto out; |
1924 | ret = add_qgroup_relation_item(trans, quota_root, | 1937 | ret = add_qgroup_relation_item(trans, quota_root, |
1925 | *i_qgroups, objectid); | 1938 | *i_qgroups, objectid); |
1926 | if (ret) | 1939 | if (ret && ret != -EEXIST) |
1927 | goto out; | 1940 | goto out; |
1928 | ++i_qgroups; | ||
1929 | } | 1941 | } |
1942 | ret = 0; | ||
1930 | } | 1943 | } |
1931 | 1944 | ||
1932 | 1945 | ||
@@ -1987,17 +2000,22 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans, | |||
1987 | 2000 | ||
1988 | i_qgroups = (u64 *)(inherit + 1); | 2001 | i_qgroups = (u64 *)(inherit + 1); |
1989 | for (i = 0; i < inherit->num_qgroups; ++i) { | 2002 | for (i = 0; i < inherit->num_qgroups; ++i) { |
1990 | ret = add_relation_rb(quota_root->fs_info, objectid, | 2003 | if (*i_qgroups) { |
1991 | *i_qgroups); | 2004 | ret = add_relation_rb(quota_root->fs_info, objectid, |
1992 | if (ret) | 2005 | *i_qgroups); |
1993 | goto unlock; | 2006 | if (ret) |
2007 | goto unlock; | ||
2008 | } | ||
1994 | ++i_qgroups; | 2009 | ++i_qgroups; |
1995 | } | 2010 | } |
1996 | 2011 | ||
1997 | for (i = 0; i < inherit->num_ref_copies; ++i) { | 2012 | for (i = 0; i < inherit->num_ref_copies; ++i, i_qgroups += 2) { |
1998 | struct btrfs_qgroup *src; | 2013 | struct btrfs_qgroup *src; |
1999 | struct btrfs_qgroup *dst; | 2014 | struct btrfs_qgroup *dst; |
2000 | 2015 | ||
2016 | if (!i_qgroups[0] || !i_qgroups[1]) | ||
2017 | continue; | ||
2018 | |||
2001 | src = find_qgroup_rb(fs_info, i_qgroups[0]); | 2019 | src = find_qgroup_rb(fs_info, i_qgroups[0]); |
2002 | dst = find_qgroup_rb(fs_info, i_qgroups[1]); | 2020 | dst = find_qgroup_rb(fs_info, i_qgroups[1]); |
2003 | 2021 | ||
@@ -2008,12 +2026,14 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans, | |||
2008 | 2026 | ||
2009 | dst->rfer = src->rfer - level_size; | 2027 | dst->rfer = src->rfer - level_size; |
2010 | dst->rfer_cmpr = src->rfer_cmpr - level_size; | 2028 | dst->rfer_cmpr = src->rfer_cmpr - level_size; |
2011 | i_qgroups += 2; | ||
2012 | } | 2029 | } |
2013 | for (i = 0; i < inherit->num_excl_copies; ++i) { | 2030 | for (i = 0; i < inherit->num_excl_copies; ++i, i_qgroups += 2) { |
2014 | struct btrfs_qgroup *src; | 2031 | struct btrfs_qgroup *src; |
2015 | struct btrfs_qgroup *dst; | 2032 | struct btrfs_qgroup *dst; |
2016 | 2033 | ||
2034 | if (!i_qgroups[0] || !i_qgroups[1]) | ||
2035 | continue; | ||
2036 | |||
2017 | src = find_qgroup_rb(fs_info, i_qgroups[0]); | 2037 | src = find_qgroup_rb(fs_info, i_qgroups[0]); |
2018 | dst = find_qgroup_rb(fs_info, i_qgroups[1]); | 2038 | dst = find_qgroup_rb(fs_info, i_qgroups[1]); |
2019 | 2039 | ||
@@ -2024,7 +2044,6 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans, | |||
2024 | 2044 | ||
2025 | dst->excl = src->excl + level_size; | 2045 | dst->excl = src->excl + level_size; |
2026 | dst->excl_cmpr = src->excl_cmpr + level_size; | 2046 | dst->excl_cmpr = src->excl_cmpr + level_size; |
2027 | i_qgroups += 2; | ||
2028 | } | 2047 | } |
2029 | 2048 | ||
2030 | unlock: | 2049 | unlock: |