aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/file.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@fusionio.com>2013-02-05 19:24:44 -0500
committerChris Mason <chris.mason@fusionio.com>2013-02-05 19:24:44 -0500
commit24f8ebe9189c91f1b3ecfaadd27ef0cb7c74907f (patch)
tree80856cf81ec5cb377f7d871233dad0f0283a0c97 /fs/btrfs/file.c
parent3c911608085bf2d5a0822c418129f96a2a89d1b5 (diff)
parent59fe4f41976f6331b695ff049296d082cf621823 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/josef/btrfs-next.git for-chris into for-linus
Diffstat (limited to 'fs/btrfs/file.c')
-rw-r--r--fs/btrfs/file.c35
1 files changed, 27 insertions, 8 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 20452c110d7d..b06d289f998f 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -293,15 +293,24 @@ static int __btrfs_run_defrag_inode(struct btrfs_fs_info *fs_info,
293 struct btrfs_key key; 293 struct btrfs_key key;
294 struct btrfs_ioctl_defrag_range_args range; 294 struct btrfs_ioctl_defrag_range_args range;
295 int num_defrag; 295 int num_defrag;
296 int index;
297 int ret;
296 298
297 /* get the inode */ 299 /* get the inode */
298 key.objectid = defrag->root; 300 key.objectid = defrag->root;
299 btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY); 301 btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY);
300 key.offset = (u64)-1; 302 key.offset = (u64)-1;
303
304 index = srcu_read_lock(&fs_info->subvol_srcu);
305
301 inode_root = btrfs_read_fs_root_no_name(fs_info, &key); 306 inode_root = btrfs_read_fs_root_no_name(fs_info, &key);
302 if (IS_ERR(inode_root)) { 307 if (IS_ERR(inode_root)) {
303 kmem_cache_free(btrfs_inode_defrag_cachep, defrag); 308 ret = PTR_ERR(inode_root);
304 return PTR_ERR(inode_root); 309 goto cleanup;
310 }
311 if (btrfs_root_refs(&inode_root->root_item) == 0) {
312 ret = -ENOENT;
313 goto cleanup;
305 } 314 }
306 315
307 key.objectid = defrag->ino; 316 key.objectid = defrag->ino;
@@ -309,9 +318,10 @@ static int __btrfs_run_defrag_inode(struct btrfs_fs_info *fs_info,
309 key.offset = 0; 318 key.offset = 0;
310 inode = btrfs_iget(fs_info->sb, &key, inode_root, NULL); 319 inode = btrfs_iget(fs_info->sb, &key, inode_root, NULL);
311 if (IS_ERR(inode)) { 320 if (IS_ERR(inode)) {
312 kmem_cache_free(btrfs_inode_defrag_cachep, defrag); 321 ret = PTR_ERR(inode);
313 return PTR_ERR(inode); 322 goto cleanup;
314 } 323 }
324 srcu_read_unlock(&fs_info->subvol_srcu, index);
315 325
316 /* do a chunk of defrag */ 326 /* do a chunk of defrag */
317 clear_bit(BTRFS_INODE_IN_DEFRAG, &BTRFS_I(inode)->runtime_flags); 327 clear_bit(BTRFS_INODE_IN_DEFRAG, &BTRFS_I(inode)->runtime_flags);
@@ -346,6 +356,10 @@ static int __btrfs_run_defrag_inode(struct btrfs_fs_info *fs_info,
346 356
347 iput(inode); 357 iput(inode);
348 return 0; 358 return 0;
359cleanup:
360 srcu_read_unlock(&fs_info->subvol_srcu, index);
361 kmem_cache_free(btrfs_inode_defrag_cachep, defrag);
362 return ret;
349} 363}
350 364
351/* 365/*
@@ -1595,9 +1609,10 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
1595 if (err < 0 && num_written > 0) 1609 if (err < 0 && num_written > 0)
1596 num_written = err; 1610 num_written = err;
1597 } 1611 }
1598out: 1612
1599 if (sync) 1613 if (sync)
1600 atomic_dec(&BTRFS_I(inode)->sync_writers); 1614 atomic_dec(&BTRFS_I(inode)->sync_writers);
1615out:
1601 sb_end_write(inode->i_sb); 1616 sb_end_write(inode->i_sb);
1602 current->backing_dev_info = NULL; 1617 current->backing_dev_info = NULL;
1603 return num_written ? num_written : err; 1618 return num_written ? num_written : err;
@@ -2242,6 +2257,7 @@ static int find_desired_extent(struct inode *inode, loff_t *offset, int origin)
2242 if (lockend <= lockstart) 2257 if (lockend <= lockstart)
2243 lockend = lockstart + root->sectorsize; 2258 lockend = lockstart + root->sectorsize;
2244 2259
2260 lockend--;
2245 len = lockend - lockstart + 1; 2261 len = lockend - lockstart + 1;
2246 2262
2247 len = max_t(u64, len, root->sectorsize); 2263 len = max_t(u64, len, root->sectorsize);
@@ -2308,9 +2324,12 @@ static int find_desired_extent(struct inode *inode, loff_t *offset, int origin)
2308 } 2324 }
2309 } 2325 }
2310 2326
2311 *offset = start; 2327 if (!test_bit(EXTENT_FLAG_PREALLOC,
2312 free_extent_map(em); 2328 &em->flags)) {
2313 break; 2329 *offset = start;
2330 free_extent_map(em);
2331 break;
2332 }
2314 } 2333 }
2315 } 2334 }
2316 2335