diff options
Diffstat (limited to 'fs/ocfs2/suballoc.c')
-rw-r--r-- | fs/ocfs2/suballoc.c | 103 |
1 files changed, 97 insertions, 6 deletions
diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index 72c198a004df..d2d278fb9819 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c | |||
@@ -46,6 +46,11 @@ | |||
46 | 46 | ||
47 | #include "buffer_head_io.h" | 47 | #include "buffer_head_io.h" |
48 | 48 | ||
49 | #define NOT_ALLOC_NEW_GROUP 0 | ||
50 | #define ALLOC_NEW_GROUP 1 | ||
51 | |||
52 | #define OCFS2_MAX_INODES_TO_STEAL 1024 | ||
53 | |||
49 | static inline void ocfs2_debug_bg(struct ocfs2_group_desc *bg); | 54 | static inline void ocfs2_debug_bg(struct ocfs2_group_desc *bg); |
50 | static inline void ocfs2_debug_suballoc_inode(struct ocfs2_dinode *fe); | 55 | static inline void ocfs2_debug_suballoc_inode(struct ocfs2_dinode *fe); |
51 | static inline u16 ocfs2_find_victim_chain(struct ocfs2_chain_list *cl); | 56 | static inline u16 ocfs2_find_victim_chain(struct ocfs2_chain_list *cl); |
@@ -106,7 +111,7 @@ static inline void ocfs2_block_to_cluster_group(struct inode *inode, | |||
106 | u64 *bg_blkno, | 111 | u64 *bg_blkno, |
107 | u16 *bg_bit_off); | 112 | u16 *bg_bit_off); |
108 | 113 | ||
109 | void ocfs2_free_alloc_context(struct ocfs2_alloc_context *ac) | 114 | static void ocfs2_free_ac_resource(struct ocfs2_alloc_context *ac) |
110 | { | 115 | { |
111 | struct inode *inode = ac->ac_inode; | 116 | struct inode *inode = ac->ac_inode; |
112 | 117 | ||
@@ -117,9 +122,17 @@ void ocfs2_free_alloc_context(struct ocfs2_alloc_context *ac) | |||
117 | mutex_unlock(&inode->i_mutex); | 122 | mutex_unlock(&inode->i_mutex); |
118 | 123 | ||
119 | iput(inode); | 124 | iput(inode); |
125 | ac->ac_inode = NULL; | ||
120 | } | 126 | } |
121 | if (ac->ac_bh) | 127 | if (ac->ac_bh) { |
122 | brelse(ac->ac_bh); | 128 | brelse(ac->ac_bh); |
129 | ac->ac_bh = NULL; | ||
130 | } | ||
131 | } | ||
132 | |||
133 | void ocfs2_free_alloc_context(struct ocfs2_alloc_context *ac) | ||
134 | { | ||
135 | ocfs2_free_ac_resource(ac); | ||
123 | kfree(ac); | 136 | kfree(ac); |
124 | } | 137 | } |
125 | 138 | ||
@@ -391,7 +404,8 @@ bail: | |||
391 | static int ocfs2_reserve_suballoc_bits(struct ocfs2_super *osb, | 404 | static int ocfs2_reserve_suballoc_bits(struct ocfs2_super *osb, |
392 | struct ocfs2_alloc_context *ac, | 405 | struct ocfs2_alloc_context *ac, |
393 | int type, | 406 | int type, |
394 | u32 slot) | 407 | u32 slot, |
408 | int alloc_new_group) | ||
395 | { | 409 | { |
396 | int status; | 410 | int status; |
397 | u32 bits_wanted = ac->ac_bits_wanted; | 411 | u32 bits_wanted = ac->ac_bits_wanted; |
@@ -420,6 +434,7 @@ static int ocfs2_reserve_suballoc_bits(struct ocfs2_super *osb, | |||
420 | } | 434 | } |
421 | 435 | ||
422 | ac->ac_inode = alloc_inode; | 436 | ac->ac_inode = alloc_inode; |
437 | ac->ac_alloc_slot = slot; | ||
423 | 438 | ||
424 | fe = (struct ocfs2_dinode *) bh->b_data; | 439 | fe = (struct ocfs2_dinode *) bh->b_data; |
425 | if (!OCFS2_IS_VALID_DINODE(fe)) { | 440 | if (!OCFS2_IS_VALID_DINODE(fe)) { |
@@ -446,6 +461,14 @@ static int ocfs2_reserve_suballoc_bits(struct ocfs2_super *osb, | |||
446 | goto bail; | 461 | goto bail; |
447 | } | 462 | } |
448 | 463 | ||
464 | if (alloc_new_group != ALLOC_NEW_GROUP) { | ||
465 | mlog(0, "Alloc File %u Full: wanted=%u, free_bits=%u, " | ||
466 | "and we don't alloc a new group for it.\n", | ||
467 | slot, bits_wanted, free_bits); | ||
468 | status = -ENOSPC; | ||
469 | goto bail; | ||
470 | } | ||
471 | |||
449 | status = ocfs2_block_group_alloc(osb, alloc_inode, bh); | 472 | status = ocfs2_block_group_alloc(osb, alloc_inode, bh); |
450 | if (status < 0) { | 473 | if (status < 0) { |
451 | if (status != -ENOSPC) | 474 | if (status != -ENOSPC) |
@@ -490,7 +513,8 @@ int ocfs2_reserve_new_metadata(struct ocfs2_super *osb, | |||
490 | (*ac)->ac_group_search = ocfs2_block_group_search; | 513 | (*ac)->ac_group_search = ocfs2_block_group_search; |
491 | 514 | ||
492 | status = ocfs2_reserve_suballoc_bits(osb, (*ac), | 515 | status = ocfs2_reserve_suballoc_bits(osb, (*ac), |
493 | EXTENT_ALLOC_SYSTEM_INODE, slot); | 516 | EXTENT_ALLOC_SYSTEM_INODE, |
517 | slot, ALLOC_NEW_GROUP); | ||
494 | if (status < 0) { | 518 | if (status < 0) { |
495 | if (status != -ENOSPC) | 519 | if (status != -ENOSPC) |
496 | mlog_errno(status); | 520 | mlog_errno(status); |
@@ -508,10 +532,42 @@ bail: | |||
508 | return status; | 532 | return status; |
509 | } | 533 | } |
510 | 534 | ||
535 | static int ocfs2_steal_inode_from_other_nodes(struct ocfs2_super *osb, | ||
536 | struct ocfs2_alloc_context *ac) | ||
537 | { | ||
538 | int i, status = -ENOSPC; | ||
539 | s16 slot = ocfs2_get_inode_steal_slot(osb); | ||
540 | |||
541 | /* Start to steal inodes from the first slot after ours. */ | ||
542 | if (slot == OCFS2_INVALID_SLOT) | ||
543 | slot = osb->slot_num + 1; | ||
544 | |||
545 | for (i = 0; i < osb->max_slots; i++, slot++) { | ||
546 | if (slot == osb->max_slots) | ||
547 | slot = 0; | ||
548 | |||
549 | if (slot == osb->slot_num) | ||
550 | continue; | ||
551 | |||
552 | status = ocfs2_reserve_suballoc_bits(osb, ac, | ||
553 | INODE_ALLOC_SYSTEM_INODE, | ||
554 | slot, NOT_ALLOC_NEW_GROUP); | ||
555 | if (status >= 0) { | ||
556 | ocfs2_set_inode_steal_slot(osb, slot); | ||
557 | break; | ||
558 | } | ||
559 | |||
560 | ocfs2_free_ac_resource(ac); | ||
561 | } | ||
562 | |||
563 | return status; | ||
564 | } | ||
565 | |||
511 | int ocfs2_reserve_new_inode(struct ocfs2_super *osb, | 566 | int ocfs2_reserve_new_inode(struct ocfs2_super *osb, |
512 | struct ocfs2_alloc_context **ac) | 567 | struct ocfs2_alloc_context **ac) |
513 | { | 568 | { |
514 | int status; | 569 | int status; |
570 | s16 slot = ocfs2_get_inode_steal_slot(osb); | ||
515 | 571 | ||
516 | *ac = kzalloc(sizeof(struct ocfs2_alloc_context), GFP_KERNEL); | 572 | *ac = kzalloc(sizeof(struct ocfs2_alloc_context), GFP_KERNEL); |
517 | if (!(*ac)) { | 573 | if (!(*ac)) { |
@@ -525,9 +581,43 @@ int ocfs2_reserve_new_inode(struct ocfs2_super *osb, | |||
525 | 581 | ||
526 | (*ac)->ac_group_search = ocfs2_block_group_search; | 582 | (*ac)->ac_group_search = ocfs2_block_group_search; |
527 | 583 | ||
584 | /* | ||
585 | * slot is set when we successfully steal inode from other nodes. | ||
586 | * It is reset in 3 places: | ||
587 | * 1. when we flush the truncate log | ||
588 | * 2. when we complete local alloc recovery. | ||
589 | * 3. when we successfully allocate from our own slot. | ||
590 | * After it is set, we will go on stealing inodes until we find the | ||
591 | * need to check our slots to see whether there is some space for us. | ||
592 | */ | ||
593 | if (slot != OCFS2_INVALID_SLOT && | ||
594 | atomic_read(&osb->s_num_inodes_stolen) < OCFS2_MAX_INODES_TO_STEAL) | ||
595 | goto inode_steal; | ||
596 | |||
597 | atomic_set(&osb->s_num_inodes_stolen, 0); | ||
528 | status = ocfs2_reserve_suballoc_bits(osb, *ac, | 598 | status = ocfs2_reserve_suballoc_bits(osb, *ac, |
529 | INODE_ALLOC_SYSTEM_INODE, | 599 | INODE_ALLOC_SYSTEM_INODE, |
530 | osb->slot_num); | 600 | osb->slot_num, ALLOC_NEW_GROUP); |
601 | if (status >= 0) { | ||
602 | status = 0; | ||
603 | |||
604 | /* | ||
605 | * Some inodes must be freed by us, so try to allocate | ||
606 | * from our own next time. | ||
607 | */ | ||
608 | if (slot != OCFS2_INVALID_SLOT) | ||
609 | ocfs2_init_inode_steal_slot(osb); | ||
610 | goto bail; | ||
611 | } else if (status < 0 && status != -ENOSPC) { | ||
612 | mlog_errno(status); | ||
613 | goto bail; | ||
614 | } | ||
615 | |||
616 | ocfs2_free_ac_resource(*ac); | ||
617 | |||
618 | inode_steal: | ||
619 | status = ocfs2_steal_inode_from_other_nodes(osb, *ac); | ||
620 | atomic_inc(&osb->s_num_inodes_stolen); | ||
531 | if (status < 0) { | 621 | if (status < 0) { |
532 | if (status != -ENOSPC) | 622 | if (status != -ENOSPC) |
533 | mlog_errno(status); | 623 | mlog_errno(status); |
@@ -557,7 +647,8 @@ int ocfs2_reserve_cluster_bitmap_bits(struct ocfs2_super *osb, | |||
557 | 647 | ||
558 | status = ocfs2_reserve_suballoc_bits(osb, ac, | 648 | status = ocfs2_reserve_suballoc_bits(osb, ac, |
559 | GLOBAL_BITMAP_SYSTEM_INODE, | 649 | GLOBAL_BITMAP_SYSTEM_INODE, |
560 | OCFS2_INVALID_SLOT); | 650 | OCFS2_INVALID_SLOT, |
651 | ALLOC_NEW_GROUP); | ||
561 | if (status < 0 && status != -ENOSPC) { | 652 | if (status < 0 && status != -ENOSPC) { |
562 | mlog_errno(status); | 653 | mlog_errno(status); |
563 | goto bail; | 654 | goto bail; |