diff options
Diffstat (limited to 'fs/ocfs2/file.c')
-rw-r--r-- | fs/ocfs2/file.c | 136 |
1 files changed, 27 insertions, 109 deletions
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index f567cc53d9bc..7bb4fde70054 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
@@ -488,7 +488,7 @@ bail: | |||
488 | } | 488 | } |
489 | 489 | ||
490 | /* | 490 | /* |
491 | * extend allocation only here. | 491 | * extend file allocation only here. |
492 | * we'll update all the disk stuff, and oip->alloc_size | 492 | * we'll update all the disk stuff, and oip->alloc_size |
493 | * | 493 | * |
494 | * expect stuff to be locked, a transaction started and enough data / | 494 | * expect stuff to be locked, a transaction started and enough data / |
@@ -497,107 +497,25 @@ bail: | |||
497 | * Will return -EAGAIN, and a reason if a restart is needed. | 497 | * Will return -EAGAIN, and a reason if a restart is needed. |
498 | * If passed in, *reason will always be set, even in error. | 498 | * If passed in, *reason will always be set, even in error. |
499 | */ | 499 | */ |
500 | int ocfs2_do_extend_allocation(struct ocfs2_super *osb, | 500 | int ocfs2_add_inode_data(struct ocfs2_super *osb, |
501 | struct inode *inode, | 501 | struct inode *inode, |
502 | u32 *logical_offset, | 502 | u32 *logical_offset, |
503 | u32 clusters_to_add, | 503 | u32 clusters_to_add, |
504 | int mark_unwritten, | 504 | int mark_unwritten, |
505 | struct buffer_head *fe_bh, | 505 | struct buffer_head *fe_bh, |
506 | handle_t *handle, | 506 | handle_t *handle, |
507 | struct ocfs2_alloc_context *data_ac, | 507 | struct ocfs2_alloc_context *data_ac, |
508 | struct ocfs2_alloc_context *meta_ac, | 508 | struct ocfs2_alloc_context *meta_ac, |
509 | enum ocfs2_alloc_restarted *reason_ret) | 509 | enum ocfs2_alloc_restarted *reason_ret) |
510 | { | 510 | { |
511 | int status = 0; | ||
512 | int free_extents; | ||
513 | struct ocfs2_dinode *fe = (struct ocfs2_dinode *) fe_bh->b_data; | 511 | struct ocfs2_dinode *fe = (struct ocfs2_dinode *) fe_bh->b_data; |
514 | enum ocfs2_alloc_restarted reason = RESTART_NONE; | 512 | struct ocfs2_extent_list *el = &fe->id2.i_list; |
515 | u32 bit_off, num_bits; | ||
516 | u64 block; | ||
517 | u8 flags = 0; | ||
518 | |||
519 | BUG_ON(!clusters_to_add); | ||
520 | |||
521 | if (mark_unwritten) | ||
522 | flags = OCFS2_EXT_UNWRITTEN; | ||
523 | |||
524 | free_extents = ocfs2_num_free_extents(osb, inode, fe_bh, | ||
525 | OCFS2_DINODE_EXTENT); | ||
526 | if (free_extents < 0) { | ||
527 | status = free_extents; | ||
528 | mlog_errno(status); | ||
529 | goto leave; | ||
530 | } | ||
531 | |||
532 | /* there are two cases which could cause us to EAGAIN in the | ||
533 | * we-need-more-metadata case: | ||
534 | * 1) we haven't reserved *any* | ||
535 | * 2) we are so fragmented, we've needed to add metadata too | ||
536 | * many times. */ | ||
537 | if (!free_extents && !meta_ac) { | ||
538 | mlog(0, "we haven't reserved any metadata!\n"); | ||
539 | status = -EAGAIN; | ||
540 | reason = RESTART_META; | ||
541 | goto leave; | ||
542 | } else if ((!free_extents) | ||
543 | && (ocfs2_alloc_context_bits_left(meta_ac) | ||
544 | < ocfs2_extend_meta_needed(&fe->id2.i_list))) { | ||
545 | mlog(0, "filesystem is really fragmented...\n"); | ||
546 | status = -EAGAIN; | ||
547 | reason = RESTART_META; | ||
548 | goto leave; | ||
549 | } | ||
550 | 513 | ||
551 | status = __ocfs2_claim_clusters(osb, handle, data_ac, 1, | 514 | return ocfs2_add_clusters_in_btree(osb, inode, logical_offset, |
552 | clusters_to_add, &bit_off, &num_bits); | 515 | clusters_to_add, mark_unwritten, |
553 | if (status < 0) { | 516 | fe_bh, el, handle, |
554 | if (status != -ENOSPC) | 517 | data_ac, meta_ac, reason_ret, |
555 | mlog_errno(status); | 518 | OCFS2_DINODE_EXTENT); |
556 | goto leave; | ||
557 | } | ||
558 | |||
559 | BUG_ON(num_bits > clusters_to_add); | ||
560 | |||
561 | /* reserve our write early -- insert_extent may update the inode */ | ||
562 | status = ocfs2_journal_access(handle, inode, fe_bh, | ||
563 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
564 | if (status < 0) { | ||
565 | mlog_errno(status); | ||
566 | goto leave; | ||
567 | } | ||
568 | |||
569 | block = ocfs2_clusters_to_blocks(osb->sb, bit_off); | ||
570 | mlog(0, "Allocating %u clusters at block %u for inode %llu\n", | ||
571 | num_bits, bit_off, (unsigned long long)OCFS2_I(inode)->ip_blkno); | ||
572 | status = ocfs2_insert_extent(osb, handle, inode, fe_bh, | ||
573 | *logical_offset, block, num_bits, | ||
574 | flags, meta_ac, OCFS2_DINODE_EXTENT); | ||
575 | if (status < 0) { | ||
576 | mlog_errno(status); | ||
577 | goto leave; | ||
578 | } | ||
579 | |||
580 | status = ocfs2_journal_dirty(handle, fe_bh); | ||
581 | if (status < 0) { | ||
582 | mlog_errno(status); | ||
583 | goto leave; | ||
584 | } | ||
585 | |||
586 | clusters_to_add -= num_bits; | ||
587 | *logical_offset += num_bits; | ||
588 | |||
589 | if (clusters_to_add) { | ||
590 | mlog(0, "need to alloc once more, clusters = %u, wanted = " | ||
591 | "%u\n", fe->i_clusters, clusters_to_add); | ||
592 | status = -EAGAIN; | ||
593 | reason = RESTART_TRANS; | ||
594 | } | ||
595 | |||
596 | leave: | ||
597 | mlog_exit(status); | ||
598 | if (reason_ret) | ||
599 | *reason_ret = reason; | ||
600 | return status; | ||
601 | } | 519 | } |
602 | 520 | ||
603 | static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start, | 521 | static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start, |
@@ -676,16 +594,16 @@ restarted_transaction: | |||
676 | 594 | ||
677 | prev_clusters = OCFS2_I(inode)->ip_clusters; | 595 | prev_clusters = OCFS2_I(inode)->ip_clusters; |
678 | 596 | ||
679 | status = ocfs2_do_extend_allocation(osb, | 597 | status = ocfs2_add_inode_data(osb, |
680 | inode, | 598 | inode, |
681 | &logical_start, | 599 | &logical_start, |
682 | clusters_to_add, | 600 | clusters_to_add, |
683 | mark_unwritten, | 601 | mark_unwritten, |
684 | bh, | 602 | bh, |
685 | handle, | 603 | handle, |
686 | data_ac, | 604 | data_ac, |
687 | meta_ac, | 605 | meta_ac, |
688 | &why); | 606 | &why); |
689 | if ((status < 0) && (status != -EAGAIN)) { | 607 | if ((status < 0) && (status != -EAGAIN)) { |
690 | if (status != -ENOSPC) | 608 | if (status != -ENOSPC) |
691 | mlog_errno(status); | 609 | mlog_errno(status); |