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.c78
1 files changed, 48 insertions, 30 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index f1a77449d032..c0c0dc8f07fa 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -4203,6 +4203,49 @@ out:
4203 return ret; 4203 return ret;
4204} 4204}
4205 4205
4206static int maybe_insert_hole(struct btrfs_root *root, struct inode *inode,
4207 u64 offset, u64 len)
4208{
4209 struct btrfs_trans_handle *trans;
4210 int ret;
4211
4212 /*
4213 * Still need to make sure the inode looks like it's been updated so
4214 * that any holes get logged if we fsync.
4215 */
4216 if (btrfs_fs_incompat(root->fs_info, NO_HOLES)) {
4217 BTRFS_I(inode)->last_trans = root->fs_info->generation;
4218 BTRFS_I(inode)->last_sub_trans = root->log_transid;
4219 BTRFS_I(inode)->last_log_commit = root->last_log_commit;
4220 return 0;
4221 }
4222
4223 /*
4224 * 1 - for the one we're dropping
4225 * 1 - for the one we're adding
4226 * 1 - for updating the inode.
4227 */
4228 trans = btrfs_start_transaction(root, 3);
4229 if (IS_ERR(trans))
4230 return PTR_ERR(trans);
4231
4232 ret = btrfs_drop_extents(trans, root, inode, offset, offset + len, 1);
4233 if (ret) {
4234 btrfs_abort_transaction(trans, root, ret);
4235 btrfs_end_transaction(trans, root);
4236 return ret;
4237 }
4238
4239 ret = btrfs_insert_file_extent(trans, root, btrfs_ino(inode), offset,
4240 0, 0, len, 0, len, 0, 0, 0);
4241 if (ret)
4242 btrfs_abort_transaction(trans, root, ret);
4243 else
4244 btrfs_update_inode(trans, root, inode);
4245 btrfs_end_transaction(trans, root);
4246 return ret;
4247}
4248
4206/* 4249/*
4207 * This function puts in dummy file extents for the area we're creating a hole 4250 * This function puts in dummy file extents for the area we're creating a hole
4208 * for. So if we are truncating this file to a larger size we need to insert 4251 * for. So if we are truncating this file to a larger size we need to insert
@@ -4211,7 +4254,6 @@ out:
4211 */ 4254 */
4212int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size) 4255int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size)
4213{ 4256{
4214 struct btrfs_trans_handle *trans;
4215 struct btrfs_root *root = BTRFS_I(inode)->root; 4257 struct btrfs_root *root = BTRFS_I(inode)->root;
4216 struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; 4258 struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
4217 struct extent_map *em = NULL; 4259 struct extent_map *em = NULL;
@@ -4266,31 +4308,10 @@ int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size)
4266 struct extent_map *hole_em; 4308 struct extent_map *hole_em;
4267 hole_size = last_byte - cur_offset; 4309 hole_size = last_byte - cur_offset;
4268 4310
4269 trans = btrfs_start_transaction(root, 3); 4311 err = maybe_insert_hole(root, inode, cur_offset,
4270 if (IS_ERR(trans)) { 4312 hole_size);
4271 err = PTR_ERR(trans); 4313 if (err)
4272 break;
4273 }
4274
4275 err = btrfs_drop_extents(trans, root, inode,
4276 cur_offset,
4277 cur_offset + hole_size, 1);
4278 if (err) {
4279 btrfs_abort_transaction(trans, root, err);
4280 btrfs_end_transaction(trans, root);
4281 break;
4282 }
4283
4284 err = btrfs_insert_file_extent(trans, root,
4285 btrfs_ino(inode), cur_offset, 0,
4286 0, hole_size, 0, hole_size,
4287 0, 0, 0);
4288 if (err) {
4289 btrfs_abort_transaction(trans, root, err);
4290 btrfs_end_transaction(trans, root);
4291 break; 4314 break;
4292 }
4293
4294 btrfs_drop_extent_cache(inode, cur_offset, 4315 btrfs_drop_extent_cache(inode, cur_offset,
4295 cur_offset + hole_size - 1, 0); 4316 cur_offset + hole_size - 1, 0);
4296 hole_em = alloc_extent_map(); 4317 hole_em = alloc_extent_map();
@@ -4309,7 +4330,7 @@ int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size)
4309 hole_em->ram_bytes = hole_size; 4330 hole_em->ram_bytes = hole_size;
4310 hole_em->bdev = root->fs_info->fs_devices->latest_bdev; 4331 hole_em->bdev = root->fs_info->fs_devices->latest_bdev;
4311 hole_em->compress_type = BTRFS_COMPRESS_NONE; 4332 hole_em->compress_type = BTRFS_COMPRESS_NONE;
4312 hole_em->generation = trans->transid; 4333 hole_em->generation = root->fs_info->generation;
4313 4334
4314 while (1) { 4335 while (1) {
4315 write_lock(&em_tree->lock); 4336 write_lock(&em_tree->lock);
@@ -4322,17 +4343,14 @@ int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size)
4322 hole_size - 1, 0); 4343 hole_size - 1, 0);
4323 } 4344 }
4324 free_extent_map(hole_em); 4345 free_extent_map(hole_em);
4325next:
4326 btrfs_update_inode(trans, root, inode);
4327 btrfs_end_transaction(trans, root);
4328 } 4346 }
4347next:
4329 free_extent_map(em); 4348 free_extent_map(em);
4330 em = NULL; 4349 em = NULL;
4331 cur_offset = last_byte; 4350 cur_offset = last_byte;
4332 if (cur_offset >= block_end) 4351 if (cur_offset >= block_end)
4333 break; 4352 break;
4334 } 4353 }
4335
4336 free_extent_map(em); 4354 free_extent_map(em);
4337 unlock_extent_cached(io_tree, hole_start, block_end - 1, &cached_state, 4355 unlock_extent_cached(io_tree, hole_start, block_end - 1, &cached_state,
4338 GFP_NOFS); 4356 GFP_NOFS);