diff options
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 132 |
1 files changed, 128 insertions, 4 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index fb9bd7832b6d..9007bbd01dbf 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -1913,7 +1913,7 @@ static int btrfs_clean_io_failures(struct inode *inode, u64 start) | |||
1913 | 1913 | ||
1914 | private = 0; | 1914 | private = 0; |
1915 | if (count_range_bits(&BTRFS_I(inode)->io_failure_tree, &private, | 1915 | if (count_range_bits(&BTRFS_I(inode)->io_failure_tree, &private, |
1916 | (u64)-1, 1, EXTENT_DIRTY)) { | 1916 | (u64)-1, 1, EXTENT_DIRTY, 0)) { |
1917 | ret = get_state_private(&BTRFS_I(inode)->io_failure_tree, | 1917 | ret = get_state_private(&BTRFS_I(inode)->io_failure_tree, |
1918 | start, &private_failure); | 1918 | start, &private_failure); |
1919 | if (ret == 0) { | 1919 | if (ret == 0) { |
@@ -4821,10 +4821,11 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir, | |||
4821 | goto fail; | 4821 | goto fail; |
4822 | 4822 | ||
4823 | /* | 4823 | /* |
4824 | * 1 item for inode ref | 4824 | * 2 items for inode and inode ref |
4825 | * 2 items for dir items | 4825 | * 2 items for dir items |
4826 | * 1 item for parent inode | ||
4826 | */ | 4827 | */ |
4827 | trans = btrfs_start_transaction(root, 3); | 4828 | trans = btrfs_start_transaction(root, 5); |
4828 | if (IS_ERR(trans)) { | 4829 | if (IS_ERR(trans)) { |
4829 | err = PTR_ERR(trans); | 4830 | err = PTR_ERR(trans); |
4830 | goto fail; | 4831 | goto fail; |
@@ -5280,6 +5281,128 @@ out: | |||
5280 | return em; | 5281 | return em; |
5281 | } | 5282 | } |
5282 | 5283 | ||
5284 | struct extent_map *btrfs_get_extent_fiemap(struct inode *inode, struct page *page, | ||
5285 | size_t pg_offset, u64 start, u64 len, | ||
5286 | int create) | ||
5287 | { | ||
5288 | struct extent_map *em; | ||
5289 | struct extent_map *hole_em = NULL; | ||
5290 | u64 range_start = start; | ||
5291 | u64 end; | ||
5292 | u64 found; | ||
5293 | u64 found_end; | ||
5294 | int err = 0; | ||
5295 | |||
5296 | em = btrfs_get_extent(inode, page, pg_offset, start, len, create); | ||
5297 | if (IS_ERR(em)) | ||
5298 | return em; | ||
5299 | if (em) { | ||
5300 | /* | ||
5301 | * if our em maps to a hole, there might | ||
5302 | * actually be delalloc bytes behind it | ||
5303 | */ | ||
5304 | if (em->block_start != EXTENT_MAP_HOLE) | ||
5305 | return em; | ||
5306 | else | ||
5307 | hole_em = em; | ||
5308 | } | ||
5309 | |||
5310 | /* check to see if we've wrapped (len == -1 or similar) */ | ||
5311 | end = start + len; | ||
5312 | if (end < start) | ||
5313 | end = (u64)-1; | ||
5314 | else | ||
5315 | end -= 1; | ||
5316 | |||
5317 | em = NULL; | ||
5318 | |||
5319 | /* ok, we didn't find anything, lets look for delalloc */ | ||
5320 | found = count_range_bits(&BTRFS_I(inode)->io_tree, &range_start, | ||
5321 | end, len, EXTENT_DELALLOC, 1); | ||
5322 | found_end = range_start + found; | ||
5323 | if (found_end < range_start) | ||
5324 | found_end = (u64)-1; | ||
5325 | |||
5326 | /* | ||
5327 | * we didn't find anything useful, return | ||
5328 | * the original results from get_extent() | ||
5329 | */ | ||
5330 | if (range_start > end || found_end <= start) { | ||
5331 | em = hole_em; | ||
5332 | hole_em = NULL; | ||
5333 | goto out; | ||
5334 | } | ||
5335 | |||
5336 | /* adjust the range_start to make sure it doesn't | ||
5337 | * go backwards from the start they passed in | ||
5338 | */ | ||
5339 | range_start = max(start,range_start); | ||
5340 | found = found_end - range_start; | ||
5341 | |||
5342 | if (found > 0) { | ||
5343 | u64 hole_start = start; | ||
5344 | u64 hole_len = len; | ||
5345 | |||
5346 | em = alloc_extent_map(GFP_NOFS); | ||
5347 | if (!em) { | ||
5348 | err = -ENOMEM; | ||
5349 | goto out; | ||
5350 | } | ||
5351 | /* | ||
5352 | * when btrfs_get_extent can't find anything it | ||
5353 | * returns one huge hole | ||
5354 | * | ||
5355 | * make sure what it found really fits our range, and | ||
5356 | * adjust to make sure it is based on the start from | ||
5357 | * the caller | ||
5358 | */ | ||
5359 | if (hole_em) { | ||
5360 | u64 calc_end = extent_map_end(hole_em); | ||
5361 | |||
5362 | if (calc_end <= start || (hole_em->start > end)) { | ||
5363 | free_extent_map(hole_em); | ||
5364 | hole_em = NULL; | ||
5365 | } else { | ||
5366 | hole_start = max(hole_em->start, start); | ||
5367 | hole_len = calc_end - hole_start; | ||
5368 | } | ||
5369 | } | ||
5370 | em->bdev = NULL; | ||
5371 | if (hole_em && range_start > hole_start) { | ||
5372 | /* our hole starts before our delalloc, so we | ||
5373 | * have to return just the parts of the hole | ||
5374 | * that go until the delalloc starts | ||
5375 | */ | ||
5376 | em->len = min(hole_len, | ||
5377 | range_start - hole_start); | ||
5378 | em->start = hole_start; | ||
5379 | em->orig_start = hole_start; | ||
5380 | /* | ||
5381 | * don't adjust block start at all, | ||
5382 | * it is fixed at EXTENT_MAP_HOLE | ||
5383 | */ | ||
5384 | em->block_start = hole_em->block_start; | ||
5385 | em->block_len = hole_len; | ||
5386 | } else { | ||
5387 | em->start = range_start; | ||
5388 | em->len = found; | ||
5389 | em->orig_start = range_start; | ||
5390 | em->block_start = EXTENT_MAP_DELALLOC; | ||
5391 | em->block_len = found; | ||
5392 | } | ||
5393 | } else if (hole_em) { | ||
5394 | return hole_em; | ||
5395 | } | ||
5396 | out: | ||
5397 | |||
5398 | free_extent_map(hole_em); | ||
5399 | if (err) { | ||
5400 | free_extent_map(em); | ||
5401 | return ERR_PTR(err); | ||
5402 | } | ||
5403 | return em; | ||
5404 | } | ||
5405 | |||
5283 | static struct extent_map *btrfs_new_extent_direct(struct inode *inode, | 5406 | static struct extent_map *btrfs_new_extent_direct(struct inode *inode, |
5284 | u64 start, u64 len) | 5407 | u64 start, u64 len) |
5285 | { | 5408 | { |
@@ -5934,6 +6057,7 @@ static void btrfs_submit_direct(int rw, struct bio *bio, struct inode *inode, | |||
5934 | if (!skip_sum) { | 6057 | if (!skip_sum) { |
5935 | dip->csums = kmalloc(sizeof(u32) * bio->bi_vcnt, GFP_NOFS); | 6058 | dip->csums = kmalloc(sizeof(u32) * bio->bi_vcnt, GFP_NOFS); |
5936 | if (!dip->csums) { | 6059 | if (!dip->csums) { |
6060 | kfree(dip); | ||
5937 | ret = -ENOMEM; | 6061 | ret = -ENOMEM; |
5938 | goto free_ordered; | 6062 | goto free_ordered; |
5939 | } | 6063 | } |
@@ -6102,7 +6226,7 @@ out: | |||
6102 | static int btrfs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | 6226 | static int btrfs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, |
6103 | __u64 start, __u64 len) | 6227 | __u64 start, __u64 len) |
6104 | { | 6228 | { |
6105 | return extent_fiemap(inode, fieinfo, start, len, btrfs_get_extent); | 6229 | return extent_fiemap(inode, fieinfo, start, len, btrfs_get_extent_fiemap); |
6106 | } | 6230 | } |
6107 | 6231 | ||
6108 | int btrfs_readpage(struct file *file, struct page *page) | 6232 | int btrfs_readpage(struct file *file, struct page *page) |