aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/qgroup.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/qgroup.c')
-rw-r--r--fs/btrfs/qgroup.c75
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;
384next2: 391next2:
@@ -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;