diff options
Diffstat (limited to 'fs/btrfs/volumes.c')
-rw-r--r-- | fs/btrfs/volumes.c | 84 |
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 */ | ||
732 | int 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 | |||
806 | next: | ||
807 | path->slots[0]++; | ||
808 | } | ||
809 | ret = 0; | ||
810 | out: | ||
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 |