diff options
Diffstat (limited to 'fs/btrfs/qgroup.c')
-rw-r--r-- | fs/btrfs/qgroup.c | 75 |
1 files changed, 54 insertions, 21 deletions
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c index fe9d02c45f8e..aee4b1cc3d98 100644 --- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c | |||
@@ -23,13 +23,13 @@ | |||
23 | #include <linux/rbtree.h> | 23 | #include <linux/rbtree.h> |
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <linux/workqueue.h> | 25 | #include <linux/workqueue.h> |
26 | #include <linux/btrfs.h> | ||
26 | 27 | ||
27 | #include "ctree.h" | 28 | #include "ctree.h" |
28 | #include "transaction.h" | 29 | #include "transaction.h" |
29 | #include "disk-io.h" | 30 | #include "disk-io.h" |
30 | #include "locking.h" | 31 | #include "locking.h" |
31 | #include "ulist.h" | 32 | #include "ulist.h" |
32 | #include "ioctl.h" | ||
33 | #include "backref.h" | 33 | #include "backref.h" |
34 | 34 | ||
35 | /* TODO XXX FIXME | 35 | /* TODO XXX FIXME |
@@ -379,6 +379,13 @@ next1: | |||
379 | 379 | ||
380 | ret = add_relation_rb(fs_info, found_key.objectid, | 380 | ret = add_relation_rb(fs_info, found_key.objectid, |
381 | found_key.offset); | 381 | found_key.offset); |
382 | if (ret == -ENOENT) { | ||
383 | printk(KERN_WARNING | ||
384 | "btrfs: orphan qgroup relation 0x%llx->0x%llx\n", | ||
385 | (unsigned long long)found_key.objectid, | ||
386 | (unsigned long long)found_key.offset); | ||
387 | ret = 0; /* ignore the error */ | ||
388 | } | ||
382 | if (ret) | 389 | if (ret) |
383 | goto out; | 390 | goto out; |
384 | next2: | 391 | next2: |
@@ -613,7 +620,9 @@ static int update_qgroup_limit_item(struct btrfs_trans_handle *trans, | |||
613 | key.offset = qgroupid; | 620 | key.offset = qgroupid; |
614 | 621 | ||
615 | path = btrfs_alloc_path(); | 622 | path = btrfs_alloc_path(); |
616 | BUG_ON(!path); | 623 | if (!path) |
624 | return -ENOMEM; | ||
625 | |||
617 | ret = btrfs_search_slot(trans, root, &key, path, 0, 1); | 626 | ret = btrfs_search_slot(trans, root, &key, path, 0, 1); |
618 | if (ret > 0) | 627 | if (ret > 0) |
619 | ret = -ENOENT; | 628 | ret = -ENOENT; |
@@ -654,7 +663,9 @@ static int update_qgroup_info_item(struct btrfs_trans_handle *trans, | |||
654 | key.offset = qgroup->qgroupid; | 663 | key.offset = qgroup->qgroupid; |
655 | 664 | ||
656 | path = btrfs_alloc_path(); | 665 | path = btrfs_alloc_path(); |
657 | BUG_ON(!path); | 666 | if (!path) |
667 | return -ENOMEM; | ||
668 | |||
658 | ret = btrfs_search_slot(trans, root, &key, path, 0, 1); | 669 | ret = btrfs_search_slot(trans, root, &key, path, 0, 1); |
659 | if (ret > 0) | 670 | if (ret > 0) |
660 | ret = -ENOENT; | 671 | ret = -ENOENT; |
@@ -695,7 +706,9 @@ static int update_qgroup_status_item(struct btrfs_trans_handle *trans, | |||
695 | key.offset = 0; | 706 | key.offset = 0; |
696 | 707 | ||
697 | path = btrfs_alloc_path(); | 708 | path = btrfs_alloc_path(); |
698 | BUG_ON(!path); | 709 | if (!path) |
710 | return -ENOMEM; | ||
711 | |||
699 | ret = btrfs_search_slot(trans, root, &key, path, 0, 1); | 712 | ret = btrfs_search_slot(trans, root, &key, path, 0, 1); |
700 | if (ret > 0) | 713 | if (ret > 0) |
701 | ret = -ENOENT; | 714 | ret = -ENOENT; |
@@ -725,33 +738,38 @@ static int btrfs_clean_quota_tree(struct btrfs_trans_handle *trans, | |||
725 | { | 738 | { |
726 | struct btrfs_path *path; | 739 | struct btrfs_path *path; |
727 | struct btrfs_key key; | 740 | struct btrfs_key key; |
741 | struct extent_buffer *leaf = NULL; | ||
728 | int ret; | 742 | int ret; |
729 | 743 | int nr = 0; | |
730 | if (!root) | ||
731 | return -EINVAL; | ||
732 | 744 | ||
733 | path = btrfs_alloc_path(); | 745 | path = btrfs_alloc_path(); |
734 | if (!path) | 746 | if (!path) |
735 | return -ENOMEM; | 747 | return -ENOMEM; |
736 | 748 | ||
737 | while (1) { | 749 | path->leave_spinning = 1; |
738 | key.objectid = 0; | ||
739 | key.offset = 0; | ||
740 | key.type = 0; | ||
741 | 750 | ||
742 | path->leave_spinning = 1; | 751 | key.objectid = 0; |
752 | key.offset = 0; | ||
753 | key.type = 0; | ||
754 | |||
755 | while (1) { | ||
743 | ret = btrfs_search_slot(trans, root, &key, path, -1, 1); | 756 | ret = btrfs_search_slot(trans, root, &key, path, -1, 1); |
744 | if (ret > 0) { | 757 | if (ret < 0) |
745 | if (path->slots[0] == 0) | 758 | goto out; |
746 | break; | 759 | leaf = path->nodes[0]; |
747 | path->slots[0]--; | 760 | nr = btrfs_header_nritems(leaf); |
748 | } else if (ret < 0) { | 761 | if (!nr) |
749 | break; | 762 | break; |
750 | } | 763 | /* |
751 | 764 | * delete the leaf one by one | |
752 | ret = btrfs_del_item(trans, root, path); | 765 | * since the whole tree is going |
766 | * to be deleted. | ||
767 | */ | ||
768 | path->slots[0] = 0; | ||
769 | ret = btrfs_del_items(trans, root, path, 0, nr); | ||
753 | if (ret) | 770 | if (ret) |
754 | goto out; | 771 | goto out; |
772 | |||
755 | btrfs_release_path(path); | 773 | btrfs_release_path(path); |
756 | } | 774 | } |
757 | ret = 0; | 775 | ret = 0; |
@@ -840,6 +858,10 @@ int btrfs_quota_disable(struct btrfs_trans_handle *trans, | |||
840 | int ret = 0; | 858 | int ret = 0; |
841 | 859 | ||
842 | spin_lock(&fs_info->qgroup_lock); | 860 | spin_lock(&fs_info->qgroup_lock); |
861 | if (!fs_info->quota_root) { | ||
862 | spin_unlock(&fs_info->qgroup_lock); | ||
863 | return 0; | ||
864 | } | ||
843 | fs_info->quota_enabled = 0; | 865 | fs_info->quota_enabled = 0; |
844 | fs_info->pending_quota_state = 0; | 866 | fs_info->pending_quota_state = 0; |
845 | quota_root = fs_info->quota_root; | 867 | quota_root = fs_info->quota_root; |
@@ -956,17 +978,28 @@ int btrfs_remove_qgroup(struct btrfs_trans_handle *trans, | |||
956 | struct btrfs_fs_info *fs_info, u64 qgroupid) | 978 | struct btrfs_fs_info *fs_info, u64 qgroupid) |
957 | { | 979 | { |
958 | struct btrfs_root *quota_root; | 980 | struct btrfs_root *quota_root; |
981 | struct btrfs_qgroup *qgroup; | ||
959 | int ret = 0; | 982 | int ret = 0; |
960 | 983 | ||
961 | quota_root = fs_info->quota_root; | 984 | quota_root = fs_info->quota_root; |
962 | if (!quota_root) | 985 | if (!quota_root) |
963 | return -EINVAL; | 986 | return -EINVAL; |
964 | 987 | ||
988 | /* check if there are no relations to this qgroup */ | ||
989 | spin_lock(&fs_info->qgroup_lock); | ||
990 | qgroup = find_qgroup_rb(fs_info, qgroupid); | ||
991 | if (qgroup) { | ||
992 | if (!list_empty(&qgroup->groups) || !list_empty(&qgroup->members)) { | ||
993 | spin_unlock(&fs_info->qgroup_lock); | ||
994 | return -EBUSY; | ||
995 | } | ||
996 | } | ||
997 | spin_unlock(&fs_info->qgroup_lock); | ||
998 | |||
965 | ret = del_qgroup_item(trans, quota_root, qgroupid); | 999 | ret = del_qgroup_item(trans, quota_root, qgroupid); |
966 | 1000 | ||
967 | spin_lock(&fs_info->qgroup_lock); | 1001 | spin_lock(&fs_info->qgroup_lock); |
968 | del_qgroup_rb(quota_root->fs_info, qgroupid); | 1002 | del_qgroup_rb(quota_root->fs_info, qgroupid); |
969 | |||
970 | spin_unlock(&fs_info->qgroup_lock); | 1003 | spin_unlock(&fs_info->qgroup_lock); |
971 | 1004 | ||
972 | return ret; | 1005 | return ret; |