aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/volumes.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/volumes.c')
-rw-r--r--fs/btrfs/volumes.c84
1 files changed, 84 insertions, 0 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index c22784b989b7..0c7f478cf645 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -728,6 +728,90 @@ error:
728 return ret; 728 return ret;
729} 729}
730 730
731/* helper to account the used device space in the range */
732int btrfs_account_dev_extents_size(struct btrfs_device *device, u64 start,
733 u64 end, u64 *length)
734{
735 struct btrfs_key key;
736 struct btrfs_root *root = device->dev_root;
737 struct btrfs_dev_extent *dev_extent;
738 struct btrfs_path *path;
739 u64 extent_end;
740 int ret;
741 int slot;
742 struct extent_buffer *l;
743
744 *length = 0;
745
746 if (start >= device->total_bytes)
747 return 0;
748
749 path = btrfs_alloc_path();
750 if (!path)
751 return -ENOMEM;
752 path->reada = 2;
753
754 key.objectid = device->devid;
755 key.offset = start;
756 key.type = BTRFS_DEV_EXTENT_KEY;
757
758 ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
759 if (ret < 0)
760 goto out;
761 if (ret > 0) {
762 ret = btrfs_previous_item(root, path, key.objectid, key.type);
763 if (ret < 0)
764 goto out;
765 }
766
767 while (1) {
768 l = path->nodes[0];
769 slot = path->slots[0];
770 if (slot >= btrfs_header_nritems(l)) {
771 ret = btrfs_next_leaf(root, path);
772 if (ret == 0)
773 continue;
774 if (ret < 0)
775 goto out;
776
777 break;
778 }
779 btrfs_item_key_to_cpu(l, &key, slot);
780
781 if (key.objectid < device->devid)
782 goto next;
783
784 if (key.objectid > device->devid)
785 break;
786
787 if (btrfs_key_type(&key) != BTRFS_DEV_EXTENT_KEY)
788 goto next;
789
790 dev_extent = btrfs_item_ptr(l, slot, struct btrfs_dev_extent);
791 extent_end = key.offset + btrfs_dev_extent_length(l,
792 dev_extent);
793 if (key.offset <= start && extent_end > end) {
794 *length = end - start + 1;
795 break;
796 } else if (key.offset <= start && extent_end > start)
797 *length += extent_end - start;
798 else if (key.offset > start && extent_end <= end)
799 *length += extent_end - key.offset;
800 else if (key.offset > start && key.offset <= end) {
801 *length += end - key.offset + 1;
802 break;
803 } else if (key.offset > end)
804 break;
805
806next:
807 path->slots[0]++;
808 }
809 ret = 0;
810out:
811 btrfs_free_path(path);
812 return ret;
813}
814
731/* 815/*
732 * find_free_dev_extent - find free space in the specified device 816 * find_free_dev_extent - find free space in the specified device
733 * @trans: transaction handler 817 * @trans: transaction handler