diff options
| -rw-r--r-- | fs/ocfs2/file.c | 104 |
1 files changed, 77 insertions, 27 deletions
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index edc0b617f409..3bcf3629265e 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
| @@ -480,13 +480,86 @@ leave: | |||
| 480 | return status; | 480 | return status; |
| 481 | } | 481 | } |
| 482 | 482 | ||
| 483 | /* | ||
| 484 | * For a given allocation, determine which allocators will need to be | ||
| 485 | * accessed, and lock them, reserving the appropriate number of bits. | ||
| 486 | * | ||
| 487 | * Called from ocfs2_extend_allocation() for file systems which don't | ||
| 488 | * support holes, and from ocfs2_prepare_write() for file systems | ||
| 489 | * which understand sparse inodes. | ||
| 490 | */ | ||
| 491 | static int ocfs2_lock_allocators(struct inode *inode, struct ocfs2_dinode *di, | ||
| 492 | u32 clusters_to_add, | ||
| 493 | struct ocfs2_alloc_context **data_ac, | ||
| 494 | struct ocfs2_alloc_context **meta_ac) | ||
| 495 | { | ||
| 496 | int ret, num_free_extents; | ||
| 497 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | ||
| 498 | |||
| 499 | *meta_ac = NULL; | ||
| 500 | *data_ac = NULL; | ||
| 501 | |||
| 502 | mlog(0, "extend inode %llu, i_size = %lld, di->i_clusters = %u, " | ||
| 503 | "clusters_to_add = %u\n", | ||
| 504 | (unsigned long long)OCFS2_I(inode)->ip_blkno, i_size_read(inode), | ||
| 505 | le32_to_cpu(di->i_clusters), clusters_to_add); | ||
| 506 | |||
| 507 | num_free_extents = ocfs2_num_free_extents(osb, inode, di); | ||
| 508 | if (num_free_extents < 0) { | ||
| 509 | ret = num_free_extents; | ||
| 510 | mlog_errno(ret); | ||
| 511 | goto out; | ||
| 512 | } | ||
| 513 | |||
| 514 | /* | ||
| 515 | * Sparse allocation file systems need to be more conservative | ||
| 516 | * with reserving room for expansion - the actual allocation | ||
| 517 | * happens while we've got a journal handle open so re-taking | ||
| 518 | * a cluster lock (because we ran out of room for another | ||
| 519 | * extent) will violate ordering rules. | ||
| 520 | * | ||
| 521 | * Most of the time we'll only be seeing this 1 page at a time | ||
| 522 | * anyway. | ||
| 523 | */ | ||
| 524 | if (!num_free_extents || | ||
| 525 | (ocfs2_sparse_alloc(osb) && num_free_extents < clusters_to_add)) { | ||
| 526 | ret = ocfs2_reserve_new_metadata(osb, di, meta_ac); | ||
| 527 | if (ret < 0) { | ||
| 528 | if (ret != -ENOSPC) | ||
| 529 | mlog_errno(ret); | ||
| 530 | goto out; | ||
| 531 | } | ||
| 532 | } | ||
| 533 | |||
| 534 | ret = ocfs2_reserve_clusters(osb, clusters_to_add, data_ac); | ||
| 535 | if (ret < 0) { | ||
| 536 | if (ret != -ENOSPC) | ||
| 537 | mlog_errno(ret); | ||
| 538 | goto out; | ||
| 539 | } | ||
| 540 | |||
| 541 | out: | ||
| 542 | if (ret) { | ||
| 543 | if (*meta_ac) { | ||
| 544 | ocfs2_free_alloc_context(*meta_ac); | ||
| 545 | *meta_ac = NULL; | ||
| 546 | } | ||
| 547 | |||
| 548 | /* | ||
| 549 | * We cannot have an error and a non null *data_ac. | ||
| 550 | */ | ||
| 551 | } | ||
| 552 | |||
| 553 | return ret; | ||
| 554 | } | ||
| 555 | |||
| 483 | static int ocfs2_extend_allocation(struct inode *inode, | 556 | static int ocfs2_extend_allocation(struct inode *inode, |
| 484 | u32 clusters_to_add) | 557 | u32 clusters_to_add) |
| 485 | { | 558 | { |
| 486 | int status = 0; | 559 | int status = 0; |
| 487 | int restart_func = 0; | 560 | int restart_func = 0; |
| 488 | int drop_alloc_sem = 0; | 561 | int drop_alloc_sem = 0; |
| 489 | int credits, num_free_extents; | 562 | int credits; |
| 490 | u32 prev_clusters, logical_start; | 563 | u32 prev_clusters, logical_start; |
| 491 | struct buffer_head *bh = NULL; | 564 | struct buffer_head *bh = NULL; |
| 492 | struct ocfs2_dinode *fe = NULL; | 565 | struct ocfs2_dinode *fe = NULL; |
| @@ -523,36 +596,13 @@ static int ocfs2_extend_allocation(struct inode *inode, | |||
| 523 | restart_all: | 596 | restart_all: |
| 524 | BUG_ON(le32_to_cpu(fe->i_clusters) != OCFS2_I(inode)->ip_clusters); | 597 | BUG_ON(le32_to_cpu(fe->i_clusters) != OCFS2_I(inode)->ip_clusters); |
| 525 | 598 | ||
| 526 | mlog(0, "extend inode %llu, i_size = %lld, fe->i_clusters = %u, " | 599 | status = ocfs2_lock_allocators(inode, fe, clusters_to_add, &data_ac, |
| 527 | "clusters_to_add = %u\n", | 600 | &meta_ac); |
| 528 | (unsigned long long)OCFS2_I(inode)->ip_blkno, i_size_read(inode), | 601 | if (status) { |
| 529 | fe->i_clusters, clusters_to_add); | ||
| 530 | |||
| 531 | num_free_extents = ocfs2_num_free_extents(osb, | ||
| 532 | inode, | ||
| 533 | fe); | ||
| 534 | if (num_free_extents < 0) { | ||
| 535 | status = num_free_extents; | ||
| 536 | mlog_errno(status); | 602 | mlog_errno(status); |
| 537 | goto leave; | 603 | goto leave; |
| 538 | } | 604 | } |
| 539 | 605 | ||
| 540 | if (!num_free_extents) { | ||
| 541 | status = ocfs2_reserve_new_metadata(osb, fe, &meta_ac); | ||
| 542 | if (status < 0) { | ||
| 543 | if (status != -ENOSPC) | ||
| 544 | mlog_errno(status); | ||
| 545 | goto leave; | ||
| 546 | } | ||
| 547 | } | ||
| 548 | |||
| 549 | status = ocfs2_reserve_clusters(osb, clusters_to_add, &data_ac); | ||
| 550 | if (status < 0) { | ||
| 551 | if (status != -ENOSPC) | ||
| 552 | mlog_errno(status); | ||
| 553 | goto leave; | ||
| 554 | } | ||
| 555 | |||
| 556 | /* blocks peope in read/write from reading our allocation | 606 | /* blocks peope in read/write from reading our allocation |
| 557 | * until we're done changing it. We depend on i_mutex to block | 607 | * until we're done changing it. We depend on i_mutex to block |
| 558 | * other extend/truncate calls while we're here. Ordering wrt | 608 | * other extend/truncate calls while we're here. Ordering wrt |
