aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext4')
-rw-r--r--fs/ext4/extents_status.c50
1 files changed, 24 insertions, 26 deletions
diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c
index eeb893122d8d..cce152c3c8dc 100644
--- a/fs/ext4/extents_status.c
+++ b/fs/ext4/extents_status.c
@@ -142,9 +142,8 @@
142 142
143static struct kmem_cache *ext4_es_cachep; 143static struct kmem_cache *ext4_es_cachep;
144 144
145static int __es_insert_extent(struct ext4_es_tree *tree, 145static int __es_insert_extent(struct inode *inode, struct extent_status *newes);
146 struct extent_status *newes); 146static int __es_remove_extent(struct inode *inode, ext4_lblk_t lblk,
147static int __es_remove_extent(struct ext4_es_tree *tree, ext4_lblk_t lblk,
148 ext4_lblk_t end); 147 ext4_lblk_t end);
149 148
150int __init ext4_init_es(void) 149int __init ext4_init_es(void)
@@ -285,7 +284,8 @@ out:
285} 284}
286 285
287static struct extent_status * 286static struct extent_status *
288ext4_es_alloc_extent(ext4_lblk_t lblk, ext4_lblk_t len, ext4_fsblk_t pblk) 287ext4_es_alloc_extent(struct inode *inode, ext4_lblk_t lblk, ext4_lblk_t len,
288 ext4_fsblk_t pblk)
289{ 289{
290 struct extent_status *es; 290 struct extent_status *es;
291 es = kmem_cache_alloc(ext4_es_cachep, GFP_ATOMIC); 291 es = kmem_cache_alloc(ext4_es_cachep, GFP_ATOMIC);
@@ -297,7 +297,7 @@ ext4_es_alloc_extent(ext4_lblk_t lblk, ext4_lblk_t len, ext4_fsblk_t pblk)
297 return es; 297 return es;
298} 298}
299 299
300static void ext4_es_free_extent(struct extent_status *es) 300static void ext4_es_free_extent(struct inode *inode, struct extent_status *es)
301{ 301{
302 kmem_cache_free(ext4_es_cachep, es); 302 kmem_cache_free(ext4_es_cachep, es);
303} 303}
@@ -326,8 +326,9 @@ static int ext4_es_can_be_merged(struct extent_status *es1,
326} 326}
327 327
328static struct extent_status * 328static struct extent_status *
329ext4_es_try_to_merge_left(struct ext4_es_tree *tree, struct extent_status *es) 329ext4_es_try_to_merge_left(struct inode *inode, struct extent_status *es)
330{ 330{
331 struct ext4_es_tree *tree = &EXT4_I(inode)->i_es_tree;
331 struct extent_status *es1; 332 struct extent_status *es1;
332 struct rb_node *node; 333 struct rb_node *node;
333 334
@@ -339,7 +340,7 @@ ext4_es_try_to_merge_left(struct ext4_es_tree *tree, struct extent_status *es)
339 if (ext4_es_can_be_merged(es1, es)) { 340 if (ext4_es_can_be_merged(es1, es)) {
340 es1->es_len += es->es_len; 341 es1->es_len += es->es_len;
341 rb_erase(&es->rb_node, &tree->root); 342 rb_erase(&es->rb_node, &tree->root);
342 ext4_es_free_extent(es); 343 ext4_es_free_extent(inode, es);
343 es = es1; 344 es = es1;
344 } 345 }
345 346
@@ -347,8 +348,9 @@ ext4_es_try_to_merge_left(struct ext4_es_tree *tree, struct extent_status *es)
347} 348}
348 349
349static struct extent_status * 350static struct extent_status *
350ext4_es_try_to_merge_right(struct ext4_es_tree *tree, struct extent_status *es) 351ext4_es_try_to_merge_right(struct inode *inode, struct extent_status *es)
351{ 352{
353 struct ext4_es_tree *tree = &EXT4_I(inode)->i_es_tree;
352 struct extent_status *es1; 354 struct extent_status *es1;
353 struct rb_node *node; 355 struct rb_node *node;
354 356
@@ -360,15 +362,15 @@ ext4_es_try_to_merge_right(struct ext4_es_tree *tree, struct extent_status *es)
360 if (ext4_es_can_be_merged(es, es1)) { 362 if (ext4_es_can_be_merged(es, es1)) {
361 es->es_len += es1->es_len; 363 es->es_len += es1->es_len;
362 rb_erase(node, &tree->root); 364 rb_erase(node, &tree->root);
363 ext4_es_free_extent(es1); 365 ext4_es_free_extent(inode, es1);
364 } 366 }
365 367
366 return es; 368 return es;
367} 369}
368 370
369static int __es_insert_extent(struct ext4_es_tree *tree, 371static int __es_insert_extent(struct inode *inode, struct extent_status *newes)
370 struct extent_status *newes)
371{ 372{
373 struct ext4_es_tree *tree = &EXT4_I(inode)->i_es_tree;
372 struct rb_node **p = &tree->root.rb_node; 374 struct rb_node **p = &tree->root.rb_node;
373 struct rb_node *parent = NULL; 375 struct rb_node *parent = NULL;
374 struct extent_status *es; 376 struct extent_status *es;
@@ -389,14 +391,14 @@ static int __es_insert_extent(struct ext4_es_tree *tree,
389 ext4_es_is_unwritten(es)) 391 ext4_es_is_unwritten(es))
390 ext4_es_store_pblock(es, 392 ext4_es_store_pblock(es,
391 newes->es_pblk); 393 newes->es_pblk);
392 es = ext4_es_try_to_merge_left(tree, es); 394 es = ext4_es_try_to_merge_left(inode, es);
393 goto out; 395 goto out;
394 } 396 }
395 p = &(*p)->rb_left; 397 p = &(*p)->rb_left;
396 } else if (newes->es_lblk > ext4_es_end(es)) { 398 } else if (newes->es_lblk > ext4_es_end(es)) {
397 if (ext4_es_can_be_merged(es, newes)) { 399 if (ext4_es_can_be_merged(es, newes)) {
398 es->es_len += newes->es_len; 400 es->es_len += newes->es_len;
399 es = ext4_es_try_to_merge_right(tree, es); 401 es = ext4_es_try_to_merge_right(inode, es);
400 goto out; 402 goto out;
401 } 403 }
402 p = &(*p)->rb_right; 404 p = &(*p)->rb_right;
@@ -406,7 +408,7 @@ static int __es_insert_extent(struct ext4_es_tree *tree,
406 } 408 }
407 } 409 }
408 410
409 es = ext4_es_alloc_extent(newes->es_lblk, newes->es_len, 411 es = ext4_es_alloc_extent(inode, newes->es_lblk, newes->es_len,
410 newes->es_pblk); 412 newes->es_pblk);
411 if (!es) 413 if (!es)
412 return -ENOMEM; 414 return -ENOMEM;
@@ -430,7 +432,6 @@ int ext4_es_insert_extent(struct inode *inode, ext4_lblk_t lblk,
430 ext4_lblk_t len, ext4_fsblk_t pblk, 432 ext4_lblk_t len, ext4_fsblk_t pblk,
431 unsigned long long status) 433 unsigned long long status)
432{ 434{
433 struct ext4_es_tree *tree;
434 struct extent_status newes; 435 struct extent_status newes;
435 ext4_lblk_t end = lblk + len - 1; 436 ext4_lblk_t end = lblk + len - 1;
436 int err = 0; 437 int err = 0;
@@ -447,11 +448,10 @@ int ext4_es_insert_extent(struct inode *inode, ext4_lblk_t lblk,
447 trace_ext4_es_insert_extent(inode, &newes); 448 trace_ext4_es_insert_extent(inode, &newes);
448 449
449 write_lock(&EXT4_I(inode)->i_es_lock); 450 write_lock(&EXT4_I(inode)->i_es_lock);
450 tree = &EXT4_I(inode)->i_es_tree; 451 err = __es_remove_extent(inode, lblk, end);
451 err = __es_remove_extent(tree, lblk, end);
452 if (err != 0) 452 if (err != 0)
453 goto error; 453 goto error;
454 err = __es_insert_extent(tree, &newes); 454 err = __es_insert_extent(inode, &newes);
455 455
456error: 456error:
457 write_unlock(&EXT4_I(inode)->i_es_lock); 457 write_unlock(&EXT4_I(inode)->i_es_lock);
@@ -521,9 +521,10 @@ out:
521 return found; 521 return found;
522} 522}
523 523
524static int __es_remove_extent(struct ext4_es_tree *tree, ext4_lblk_t lblk, 524static int __es_remove_extent(struct inode *inode, ext4_lblk_t lblk,
525 ext4_lblk_t end) 525 ext4_lblk_t end)
526{ 526{
527 struct ext4_es_tree *tree = &EXT4_I(inode)->i_es_tree;
527 struct rb_node *node; 528 struct rb_node *node;
528 struct extent_status *es; 529 struct extent_status *es;
529 struct extent_status orig_es; 530 struct extent_status orig_es;
@@ -561,7 +562,7 @@ static int __es_remove_extent(struct ext4_es_tree *tree, ext4_lblk_t lblk,
561 ext4_es_store_pblock(&newes, block); 562 ext4_es_store_pblock(&newes, block);
562 } 563 }
563 ext4_es_store_status(&newes, ext4_es_status(&orig_es)); 564 ext4_es_store_status(&newes, ext4_es_status(&orig_es));
564 err = __es_insert_extent(tree, &newes); 565 err = __es_insert_extent(inode, &newes);
565 if (err) { 566 if (err) {
566 es->es_lblk = orig_es.es_lblk; 567 es->es_lblk = orig_es.es_lblk;
567 es->es_len = orig_es.es_len; 568 es->es_len = orig_es.es_len;
@@ -590,7 +591,7 @@ static int __es_remove_extent(struct ext4_es_tree *tree, ext4_lblk_t lblk,
590 while (es && ext4_es_end(es) <= end) { 591 while (es && ext4_es_end(es) <= end) {
591 node = rb_next(&es->rb_node); 592 node = rb_next(&es->rb_node);
592 rb_erase(&es->rb_node, &tree->root); 593 rb_erase(&es->rb_node, &tree->root);
593 ext4_es_free_extent(es); 594 ext4_es_free_extent(inode, es);
594 if (!node) { 595 if (!node) {
595 es = NULL; 596 es = NULL;
596 break; 597 break;
@@ -622,7 +623,6 @@ out:
622int ext4_es_remove_extent(struct inode *inode, ext4_lblk_t lblk, 623int ext4_es_remove_extent(struct inode *inode, ext4_lblk_t lblk,
623 ext4_lblk_t len) 624 ext4_lblk_t len)
624{ 625{
625 struct ext4_es_tree *tree;
626 ext4_lblk_t end; 626 ext4_lblk_t end;
627 int err = 0; 627 int err = 0;
628 628
@@ -633,10 +633,8 @@ int ext4_es_remove_extent(struct inode *inode, ext4_lblk_t lblk,
633 end = lblk + len - 1; 633 end = lblk + len - 1;
634 BUG_ON(end < lblk); 634 BUG_ON(end < lblk);
635 635
636 tree = &EXT4_I(inode)->i_es_tree;
637
638 write_lock(&EXT4_I(inode)->i_es_lock); 636 write_lock(&EXT4_I(inode)->i_es_lock);
639 err = __es_remove_extent(tree, lblk, end); 637 err = __es_remove_extent(inode, lblk, end);
640 write_unlock(&EXT4_I(inode)->i_es_lock); 638 write_unlock(&EXT4_I(inode)->i_es_lock);
641 ext4_es_print_tree(inode); 639 ext4_es_print_tree(inode);
642 return err; 640 return err;