ASSERT(list_empty(&fs_info->delayed_iputs));
        set_bit(BTRFS_FS_CLOSING_DONE, &fs_info->flags);
 
+       if (btrfs_check_quota_leak(fs_info)) {
+               WARN_ON(IS_ENABLED(CONFIG_BTRFS_DEBUG));
+               btrfs_err(fs_info, "qgroup reserved space leaked");
+       }
+
        btrfs_free_qgroup_config(fs_info);
        ASSERT(list_empty(&fs_info->delalloc_roots));
 
 
        return ret < 0 ? ret : 0;
 }
 
+static u64 btrfs_qgroup_subvolid(u64 qgroupid)
+{
+       return (qgroupid & ((1ULL << BTRFS_QGROUP_LEVEL_SHIFT) - 1));
+}
+
+/*
+ * Called in close_ctree() when quota is still enabled.  This verifies we don't
+ * leak some reserved space.
+ *
+ * Return false if no reserved space is left.
+ * Return true if some reserved space is leaked.
+ */
+bool btrfs_check_quota_leak(struct btrfs_fs_info *fs_info)
+{
+       struct rb_node *node;
+       bool ret = false;
+
+       if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags))
+               return ret;
+       /*
+        * Since we're unmounting, there is no race and no need to grab qgroup
+        * lock.  And here we don't go post-order to provide a more user
+        * friendly sorted result.
+        */
+       for (node = rb_first(&fs_info->qgroup_tree); node; node = rb_next(node)) {
+               struct btrfs_qgroup *qgroup;
+               int i;
+
+               qgroup = rb_entry(node, struct btrfs_qgroup, node);
+               for (i = 0; i < BTRFS_QGROUP_RSV_LAST; i++) {
+                       if (qgroup->rsv.values[i]) {
+                               ret = true;
+                               btrfs_warn(fs_info,
+               "qgroup %llu/%llu has unreleased space, type %d rsv %llu",
+                                  btrfs_qgroup_level(qgroup->qgroupid),
+                                  btrfs_qgroup_subvolid(qgroup->qgroupid),
+                                  i, qgroup->rsv.values[i]);
+                       }
+               }
+       }
+       return ret;
+}
+
 /*
  * This is called from close_ctree() or open_ctree() or btrfs_quota_disable(),
  * first two are in single-threaded paths.And for the third one, we have set
 
 int btrfs_qgroup_trace_subtree_after_cow(struct btrfs_trans_handle *trans,
                struct btrfs_root *root, struct extent_buffer *eb);
 void btrfs_qgroup_destroy_extent_records(struct btrfs_transaction *trans);
+bool btrfs_check_quota_leak(struct btrfs_fs_info *fs_info);
 
 #endif