aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ocfs2/file.c104
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 */
491static 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
541out:
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
483static int ocfs2_extend_allocation(struct inode *inode, 556static 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,
523restart_all: 596restart_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