aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/qgroup.c54
1 files changed, 32 insertions, 22 deletions
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
index 5279fdae7142..7173360eea7a 100644
--- a/fs/btrfs/qgroup.c
+++ b/fs/btrfs/qgroup.c
@@ -1842,8 +1842,10 @@ out:
1842} 1842}
1843 1843
1844/* 1844/*
1845 * copy the acounting information between qgroups. This is necessary when a 1845 * Copy the acounting information between qgroups. This is necessary
1846 * snapshot or a subvolume is created 1846 * when a snapshot or a subvolume is created. Throwing an error will
1847 * cause a transaction abort so we take extra care here to only error
1848 * when a readonly fs is a reasonable outcome.
1847 */ 1849 */
1848int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans, 1850int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans,
1849 struct btrfs_fs_info *fs_info, u64 srcid, u64 objectid, 1851 struct btrfs_fs_info *fs_info, u64 srcid, u64 objectid,
@@ -1873,15 +1875,15 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans,
1873 2 * inherit->num_excl_copies; 1875 2 * inherit->num_excl_copies;
1874 for (i = 0; i < nums; ++i) { 1876 for (i = 0; i < nums; ++i) {
1875 srcgroup = find_qgroup_rb(fs_info, *i_qgroups); 1877 srcgroup = find_qgroup_rb(fs_info, *i_qgroups);
1876 if (!srcgroup) {
1877 ret = -EINVAL;
1878 goto out;
1879 }
1880 1878
1881 if ((srcgroup->qgroupid >> 48) <= (objectid >> 48)) { 1879 /*
1882 ret = -EINVAL; 1880 * Zero out invalid groups so we can ignore
1883 goto out; 1881 * them later.
1884 } 1882 */
1883 if (!srcgroup ||
1884 ((srcgroup->qgroupid >> 48) <= (objectid >> 48)))
1885 *i_qgroups = 0ULL;
1886
1885 ++i_qgroups; 1887 ++i_qgroups;
1886 } 1888 }
1887 } 1889 }
@@ -1916,17 +1918,19 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans,
1916 */ 1918 */
1917 if (inherit) { 1919 if (inherit) {
1918 i_qgroups = (u64 *)(inherit + 1); 1920 i_qgroups = (u64 *)(inherit + 1);
1919 for (i = 0; i < inherit->num_qgroups; ++i) { 1921 for (i = 0; i < inherit->num_qgroups; ++i, ++i_qgroups) {
1922 if (*i_qgroups == 0)
1923 continue;
1920 ret = add_qgroup_relation_item(trans, quota_root, 1924 ret = add_qgroup_relation_item(trans, quota_root,
1921 objectid, *i_qgroups); 1925 objectid, *i_qgroups);
1922 if (ret) 1926 if (ret && ret != -EEXIST)
1923 goto out; 1927 goto out;
1924 ret = add_qgroup_relation_item(trans, quota_root, 1928 ret = add_qgroup_relation_item(trans, quota_root,
1925 *i_qgroups, objectid); 1929 *i_qgroups, objectid);
1926 if (ret) 1930 if (ret && ret != -EEXIST)
1927 goto out; 1931 goto out;
1928 ++i_qgroups;
1929 } 1932 }
1933 ret = 0;
1930 } 1934 }
1931 1935
1932 1936
@@ -1987,17 +1991,22 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans,
1987 1991
1988 i_qgroups = (u64 *)(inherit + 1); 1992 i_qgroups = (u64 *)(inherit + 1);
1989 for (i = 0; i < inherit->num_qgroups; ++i) { 1993 for (i = 0; i < inherit->num_qgroups; ++i) {
1990 ret = add_relation_rb(quota_root->fs_info, objectid, 1994 if (*i_qgroups) {
1991 *i_qgroups); 1995 ret = add_relation_rb(quota_root->fs_info, objectid,
1992 if (ret) 1996 *i_qgroups);
1993 goto unlock; 1997 if (ret)
1998 goto unlock;
1999 }
1994 ++i_qgroups; 2000 ++i_qgroups;
1995 } 2001 }
1996 2002
1997 for (i = 0; i < inherit->num_ref_copies; ++i) { 2003 for (i = 0; i < inherit->num_ref_copies; ++i, i_qgroups += 2) {
1998 struct btrfs_qgroup *src; 2004 struct btrfs_qgroup *src;
1999 struct btrfs_qgroup *dst; 2005 struct btrfs_qgroup *dst;
2000 2006
2007 if (!i_qgroups[0] || !i_qgroups[1])
2008 continue;
2009
2001 src = find_qgroup_rb(fs_info, i_qgroups[0]); 2010 src = find_qgroup_rb(fs_info, i_qgroups[0]);
2002 dst = find_qgroup_rb(fs_info, i_qgroups[1]); 2011 dst = find_qgroup_rb(fs_info, i_qgroups[1]);
2003 2012
@@ -2008,12 +2017,14 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans,
2008 2017
2009 dst->rfer = src->rfer - level_size; 2018 dst->rfer = src->rfer - level_size;
2010 dst->rfer_cmpr = src->rfer_cmpr - level_size; 2019 dst->rfer_cmpr = src->rfer_cmpr - level_size;
2011 i_qgroups += 2;
2012 } 2020 }
2013 for (i = 0; i < inherit->num_excl_copies; ++i) { 2021 for (i = 0; i < inherit->num_excl_copies; ++i, i_qgroups += 2) {
2014 struct btrfs_qgroup *src; 2022 struct btrfs_qgroup *src;
2015 struct btrfs_qgroup *dst; 2023 struct btrfs_qgroup *dst;
2016 2024
2025 if (!i_qgroups[0] || !i_qgroups[1])
2026 continue;
2027
2017 src = find_qgroup_rb(fs_info, i_qgroups[0]); 2028 src = find_qgroup_rb(fs_info, i_qgroups[0]);
2018 dst = find_qgroup_rb(fs_info, i_qgroups[1]); 2029 dst = find_qgroup_rb(fs_info, i_qgroups[1]);
2019 2030
@@ -2024,7 +2035,6 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans,
2024 2035
2025 dst->excl = src->excl + level_size; 2036 dst->excl = src->excl + level_size;
2026 dst->excl_cmpr = src->excl_cmpr + level_size; 2037 dst->excl_cmpr = src->excl_cmpr + level_size;
2027 i_qgroups += 2;
2028 } 2038 }
2029 2039
2030unlock: 2040unlock: