diff options
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 148 |
1 files changed, 135 insertions, 13 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index fb9bd7832b6d..512c3d1da083 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -90,13 +90,14 @@ static noinline int cow_file_range(struct inode *inode, | |||
90 | unsigned long *nr_written, int unlock); | 90 | unsigned long *nr_written, int unlock); |
91 | 91 | ||
92 | static int btrfs_init_inode_security(struct btrfs_trans_handle *trans, | 92 | static int btrfs_init_inode_security(struct btrfs_trans_handle *trans, |
93 | struct inode *inode, struct inode *dir) | 93 | struct inode *inode, struct inode *dir, |
94 | const struct qstr *qstr) | ||
94 | { | 95 | { |
95 | int err; | 96 | int err; |
96 | 97 | ||
97 | err = btrfs_init_acl(trans, inode, dir); | 98 | err = btrfs_init_acl(trans, inode, dir); |
98 | if (!err) | 99 | if (!err) |
99 | err = btrfs_xattr_security_init(trans, inode, dir); | 100 | err = btrfs_xattr_security_init(trans, inode, dir, qstr); |
100 | return err; | 101 | return err; |
101 | } | 102 | } |
102 | 103 | ||
@@ -1913,7 +1914,7 @@ static int btrfs_clean_io_failures(struct inode *inode, u64 start) | |||
1913 | 1914 | ||
1914 | private = 0; | 1915 | private = 0; |
1915 | if (count_range_bits(&BTRFS_I(inode)->io_failure_tree, &private, | 1916 | if (count_range_bits(&BTRFS_I(inode)->io_failure_tree, &private, |
1916 | (u64)-1, 1, EXTENT_DIRTY)) { | 1917 | (u64)-1, 1, EXTENT_DIRTY, 0)) { |
1917 | ret = get_state_private(&BTRFS_I(inode)->io_failure_tree, | 1918 | ret = get_state_private(&BTRFS_I(inode)->io_failure_tree, |
1918 | start, &private_failure); | 1919 | start, &private_failure); |
1919 | if (ret == 0) { | 1920 | if (ret == 0) { |
@@ -4704,7 +4705,7 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry, | |||
4704 | if (IS_ERR(inode)) | 4705 | if (IS_ERR(inode)) |
4705 | goto out_unlock; | 4706 | goto out_unlock; |
4706 | 4707 | ||
4707 | err = btrfs_init_inode_security(trans, inode, dir); | 4708 | err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name); |
4708 | if (err) { | 4709 | if (err) { |
4709 | drop_inode = 1; | 4710 | drop_inode = 1; |
4710 | goto out_unlock; | 4711 | goto out_unlock; |
@@ -4765,7 +4766,7 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry, | |||
4765 | if (IS_ERR(inode)) | 4766 | if (IS_ERR(inode)) |
4766 | goto out_unlock; | 4767 | goto out_unlock; |
4767 | 4768 | ||
4768 | err = btrfs_init_inode_security(trans, inode, dir); | 4769 | err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name); |
4769 | if (err) { | 4770 | if (err) { |
4770 | drop_inode = 1; | 4771 | drop_inode = 1; |
4771 | goto out_unlock; | 4772 | goto out_unlock; |
@@ -4806,9 +4807,6 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir, | |||
4806 | int err; | 4807 | int err; |
4807 | int drop_inode = 0; | 4808 | int drop_inode = 0; |
4808 | 4809 | ||
4809 | if (inode->i_nlink == 0) | ||
4810 | return -ENOENT; | ||
4811 | |||
4812 | /* do not allow sys_link's with other subvols of the same device */ | 4810 | /* do not allow sys_link's with other subvols of the same device */ |
4813 | if (root->objectid != BTRFS_I(inode)->root->objectid) | 4811 | if (root->objectid != BTRFS_I(inode)->root->objectid) |
4814 | return -EPERM; | 4812 | return -EPERM; |
@@ -4821,10 +4819,11 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir, | |||
4821 | goto fail; | 4819 | goto fail; |
4822 | 4820 | ||
4823 | /* | 4821 | /* |
4824 | * 1 item for inode ref | 4822 | * 2 items for inode and inode ref |
4825 | * 2 items for dir items | 4823 | * 2 items for dir items |
4824 | * 1 item for parent inode | ||
4826 | */ | 4825 | */ |
4827 | trans = btrfs_start_transaction(root, 3); | 4826 | trans = btrfs_start_transaction(root, 5); |
4828 | if (IS_ERR(trans)) { | 4827 | if (IS_ERR(trans)) { |
4829 | err = PTR_ERR(trans); | 4828 | err = PTR_ERR(trans); |
4830 | goto fail; | 4829 | goto fail; |
@@ -4893,7 +4892,7 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
4893 | 4892 | ||
4894 | drop_on_err = 1; | 4893 | drop_on_err = 1; |
4895 | 4894 | ||
4896 | err = btrfs_init_inode_security(trans, inode, dir); | 4895 | err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name); |
4897 | if (err) | 4896 | if (err) |
4898 | goto out_fail; | 4897 | goto out_fail; |
4899 | 4898 | ||
@@ -5280,6 +5279,128 @@ out: | |||
5280 | return em; | 5279 | return em; |
5281 | } | 5280 | } |
5282 | 5281 | ||
5282 | struct extent_map *btrfs_get_extent_fiemap(struct inode *inode, struct page *page, | ||
5283 | size_t pg_offset, u64 start, u64 len, | ||
5284 | int create) | ||
5285 | { | ||
5286 | struct extent_map *em; | ||
5287 | struct extent_map *hole_em = NULL; | ||
5288 | u64 range_start = start; | ||
5289 | u64 end; | ||
5290 | u64 found; | ||
5291 | u64 found_end; | ||
5292 | int err = 0; | ||
5293 | |||
5294 | em = btrfs_get_extent(inode, page, pg_offset, start, len, create); | ||
5295 | if (IS_ERR(em)) | ||
5296 | return em; | ||
5297 | if (em) { | ||
5298 | /* | ||
5299 | * if our em maps to a hole, there might | ||
5300 | * actually be delalloc bytes behind it | ||
5301 | */ | ||
5302 | if (em->block_start != EXTENT_MAP_HOLE) | ||
5303 | return em; | ||
5304 | else | ||
5305 | hole_em = em; | ||
5306 | } | ||
5307 | |||
5308 | /* check to see if we've wrapped (len == -1 or similar) */ | ||
5309 | end = start + len; | ||
5310 | if (end < start) | ||
5311 | end = (u64)-1; | ||
5312 | else | ||
5313 | end -= 1; | ||
5314 | |||
5315 | em = NULL; | ||
5316 | |||
5317 | /* ok, we didn't find anything, lets look for delalloc */ | ||
5318 | found = count_range_bits(&BTRFS_I(inode)->io_tree, &range_start, | ||
5319 | end, len, EXTENT_DELALLOC, 1); | ||
5320 | found_end = range_start + found; | ||
5321 | if (found_end < range_start) | ||
5322 | found_end = (u64)-1; | ||
5323 | |||
5324 | /* | ||
5325 | * we didn't find anything useful, return | ||
5326 | * the original results from get_extent() | ||
5327 | */ | ||
5328 | if (range_start > end || found_end <= start) { | ||
5329 | em = hole_em; | ||
5330 | hole_em = NULL; | ||
5331 | goto out; | ||
5332 | } | ||
5333 | |||
5334 | /* adjust the range_start to make sure it doesn't | ||
5335 | * go backwards from the start they passed in | ||
5336 | */ | ||
5337 | range_start = max(start,range_start); | ||
5338 | found = found_end - range_start; | ||
5339 | |||
5340 | if (found > 0) { | ||
5341 | u64 hole_start = start; | ||
5342 | u64 hole_len = len; | ||
5343 | |||
5344 | em = alloc_extent_map(GFP_NOFS); | ||
5345 | if (!em) { | ||
5346 | err = -ENOMEM; | ||
5347 | goto out; | ||
5348 | } | ||
5349 | /* | ||
5350 | * when btrfs_get_extent can't find anything it | ||
5351 | * returns one huge hole | ||
5352 | * | ||
5353 | * make sure what it found really fits our range, and | ||
5354 | * adjust to make sure it is based on the start from | ||
5355 | * the caller | ||
5356 | */ | ||
5357 | if (hole_em) { | ||
5358 | u64 calc_end = extent_map_end(hole_em); | ||
5359 | |||
5360 | if (calc_end <= start || (hole_em->start > end)) { | ||
5361 | free_extent_map(hole_em); | ||
5362 | hole_em = NULL; | ||
5363 | } else { | ||
5364 | hole_start = max(hole_em->start, start); | ||
5365 | hole_len = calc_end - hole_start; | ||
5366 | } | ||
5367 | } | ||
5368 | em->bdev = NULL; | ||
5369 | if (hole_em && range_start > hole_start) { | ||
5370 | /* our hole starts before our delalloc, so we | ||
5371 | * have to return just the parts of the hole | ||
5372 | * that go until the delalloc starts | ||
5373 | */ | ||
5374 | em->len = min(hole_len, | ||
5375 | range_start - hole_start); | ||
5376 | em->start = hole_start; | ||
5377 | em->orig_start = hole_start; | ||
5378 | /* | ||
5379 | * don't adjust block start at all, | ||
5380 | * it is fixed at EXTENT_MAP_HOLE | ||
5381 | */ | ||
5382 | em->block_start = hole_em->block_start; | ||
5383 | em->block_len = hole_len; | ||
5384 | } else { | ||
5385 | em->start = range_start; | ||
5386 | em->len = found; | ||
5387 | em->orig_start = range_start; | ||
5388 | em->block_start = EXTENT_MAP_DELALLOC; | ||
5389 | em->block_len = found; | ||
5390 | } | ||
5391 | } else if (hole_em) { | ||
5392 | return hole_em; | ||
5393 | } | ||
5394 | out: | ||
5395 | |||
5396 | free_extent_map(hole_em); | ||
5397 | if (err) { | ||
5398 | free_extent_map(em); | ||
5399 | return ERR_PTR(err); | ||
5400 | } | ||
5401 | return em; | ||
5402 | } | ||
5403 | |||
5283 | static struct extent_map *btrfs_new_extent_direct(struct inode *inode, | 5404 | static struct extent_map *btrfs_new_extent_direct(struct inode *inode, |
5284 | u64 start, u64 len) | 5405 | u64 start, u64 len) |
5285 | { | 5406 | { |
@@ -5934,6 +6055,7 @@ static void btrfs_submit_direct(int rw, struct bio *bio, struct inode *inode, | |||
5934 | if (!skip_sum) { | 6055 | if (!skip_sum) { |
5935 | dip->csums = kmalloc(sizeof(u32) * bio->bi_vcnt, GFP_NOFS); | 6056 | dip->csums = kmalloc(sizeof(u32) * bio->bi_vcnt, GFP_NOFS); |
5936 | if (!dip->csums) { | 6057 | if (!dip->csums) { |
6058 | kfree(dip); | ||
5937 | ret = -ENOMEM; | 6059 | ret = -ENOMEM; |
5938 | goto free_ordered; | 6060 | goto free_ordered; |
5939 | } | 6061 | } |
@@ -6102,7 +6224,7 @@ out: | |||
6102 | static int btrfs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | 6224 | static int btrfs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, |
6103 | __u64 start, __u64 len) | 6225 | __u64 start, __u64 len) |
6104 | { | 6226 | { |
6105 | return extent_fiemap(inode, fieinfo, start, len, btrfs_get_extent); | 6227 | return extent_fiemap(inode, fieinfo, start, len, btrfs_get_extent_fiemap); |
6106 | } | 6228 | } |
6107 | 6229 | ||
6108 | int btrfs_readpage(struct file *file, struct page *page) | 6230 | int btrfs_readpage(struct file *file, struct page *page) |
@@ -6982,7 +7104,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry, | |||
6982 | if (IS_ERR(inode)) | 7104 | if (IS_ERR(inode)) |
6983 | goto out_unlock; | 7105 | goto out_unlock; |
6984 | 7106 | ||
6985 | err = btrfs_init_inode_security(trans, inode, dir); | 7107 | err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name); |
6986 | if (err) { | 7108 | if (err) { |
6987 | drop_inode = 1; | 7109 | drop_inode = 1; |
6988 | goto out_unlock; | 7110 | goto out_unlock; |