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