diff options
Diffstat (limited to 'fs/btrfs/ordered-data.c')
-rw-r--r-- | fs/btrfs/ordered-data.c | 56 |
1 files changed, 52 insertions, 4 deletions
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index 52889da69113..1744ba8b2754 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include "extent_io.h" | 13 | #include "extent_io.h" |
14 | #include "disk-io.h" | 14 | #include "disk-io.h" |
15 | #include "compression.h" | 15 | #include "compression.h" |
16 | #include "delalloc-space.h" | ||
16 | 17 | ||
17 | static struct kmem_cache *btrfs_ordered_extent_cache; | 18 | static struct kmem_cache *btrfs_ordered_extent_cache; |
18 | 19 | ||
@@ -924,14 +925,16 @@ out: | |||
924 | * be reclaimed before their checksum is actually put into the btree | 925 | * be reclaimed before their checksum is actually put into the btree |
925 | */ | 926 | */ |
926 | int btrfs_find_ordered_sum(struct inode *inode, u64 offset, u64 disk_bytenr, | 927 | int btrfs_find_ordered_sum(struct inode *inode, u64 offset, u64 disk_bytenr, |
927 | u32 *sum, int len) | 928 | u8 *sum, int len) |
928 | { | 929 | { |
930 | struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); | ||
929 | struct btrfs_ordered_sum *ordered_sum; | 931 | struct btrfs_ordered_sum *ordered_sum; |
930 | struct btrfs_ordered_extent *ordered; | 932 | struct btrfs_ordered_extent *ordered; |
931 | struct btrfs_ordered_inode_tree *tree = &BTRFS_I(inode)->ordered_tree; | 933 | struct btrfs_ordered_inode_tree *tree = &BTRFS_I(inode)->ordered_tree; |
932 | unsigned long num_sectors; | 934 | unsigned long num_sectors; |
933 | unsigned long i; | 935 | unsigned long i; |
934 | u32 sectorsize = btrfs_inode_sectorsize(inode); | 936 | u32 sectorsize = btrfs_inode_sectorsize(inode); |
937 | const u16 csum_size = btrfs_super_csum_size(fs_info->super_copy); | ||
935 | int index = 0; | 938 | int index = 0; |
936 | 939 | ||
937 | ordered = btrfs_lookup_ordered_extent(inode, offset); | 940 | ordered = btrfs_lookup_ordered_extent(inode, offset); |
@@ -947,10 +950,10 @@ int btrfs_find_ordered_sum(struct inode *inode, u64 offset, u64 disk_bytenr, | |||
947 | num_sectors = ordered_sum->len >> | 950 | num_sectors = ordered_sum->len >> |
948 | inode->i_sb->s_blocksize_bits; | 951 | inode->i_sb->s_blocksize_bits; |
949 | num_sectors = min_t(int, len - index, num_sectors - i); | 952 | num_sectors = min_t(int, len - index, num_sectors - i); |
950 | memcpy(sum + index, ordered_sum->sums + i, | 953 | memcpy(sum + index, ordered_sum->sums + i * csum_size, |
951 | num_sectors); | 954 | num_sectors * csum_size); |
952 | 955 | ||
953 | index += (int)num_sectors; | 956 | index += (int)num_sectors * csum_size; |
954 | if (index == len) | 957 | if (index == len) |
955 | goto out; | 958 | goto out; |
956 | disk_bytenr += num_sectors * sectorsize; | 959 | disk_bytenr += num_sectors * sectorsize; |
@@ -962,6 +965,51 @@ out: | |||
962 | return index; | 965 | return index; |
963 | } | 966 | } |
964 | 967 | ||
968 | /* | ||
969 | * btrfs_flush_ordered_range - Lock the passed range and ensures all pending | ||
970 | * ordered extents in it are run to completion. | ||
971 | * | ||
972 | * @tree: IO tree used for locking out other users of the range | ||
973 | * @inode: Inode whose ordered tree is to be searched | ||
974 | * @start: Beginning of range to flush | ||
975 | * @end: Last byte of range to lock | ||
976 | * @cached_state: If passed, will return the extent state responsible for the | ||
977 | * locked range. It's the caller's responsibility to free the cached state. | ||
978 | * | ||
979 | * This function always returns with the given range locked, ensuring after it's | ||
980 | * called no order extent can be pending. | ||
981 | */ | ||
982 | void btrfs_lock_and_flush_ordered_range(struct extent_io_tree *tree, | ||
983 | struct btrfs_inode *inode, u64 start, | ||
984 | u64 end, | ||
985 | struct extent_state **cached_state) | ||
986 | { | ||
987 | struct btrfs_ordered_extent *ordered; | ||
988 | struct extent_state *cachedp = NULL; | ||
989 | |||
990 | if (cached_state) | ||
991 | cachedp = *cached_state; | ||
992 | |||
993 | while (1) { | ||
994 | lock_extent_bits(tree, start, end, &cachedp); | ||
995 | ordered = btrfs_lookup_ordered_range(inode, start, | ||
996 | end - start + 1); | ||
997 | if (!ordered) { | ||
998 | /* | ||
999 | * If no external cached_state has been passed then | ||
1000 | * decrement the extra ref taken for cachedp since we | ||
1001 | * aren't exposing it outside of this function | ||
1002 | */ | ||
1003 | if (!cached_state) | ||
1004 | refcount_dec(&cachedp->refs); | ||
1005 | break; | ||
1006 | } | ||
1007 | unlock_extent_cached(tree, start, end, &cachedp); | ||
1008 | btrfs_start_ordered_extent(&inode->vfs_inode, ordered, 1); | ||
1009 | btrfs_put_ordered_extent(ordered); | ||
1010 | } | ||
1011 | } | ||
1012 | |||
965 | int __init ordered_data_init(void) | 1013 | int __init ordered_data_init(void) |
966 | { | 1014 | { |
967 | btrfs_ordered_extent_cache = kmem_cache_create("btrfs_ordered_extent", | 1015 | btrfs_ordered_extent_cache = kmem_cache_create("btrfs_ordered_extent", |