aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2/file.c
diff options
context:
space:
mode:
authorMark Fasheh <mark.fasheh@oracle.com>2007-01-17 16:07:24 -0500
committerMark Fasheh <mark.fasheh@oracle.com>2007-04-26 18:01:58 -0400
commitabf8b1569415bb4a8915a4884943ecd39c510957 (patch)
treed2d1e9fb20fbe1fa9126fe843cab2a283c7a2c6c /fs/ocfs2/file.c
parent3a0782d09c07aa3ec767ba6089cd15cfbfbfc508 (diff)
ocfs2: abstract out allocation locking
Right now, file allocation for ocfs2 is done within ocfs2_extend_file(), which is either called from ->setattr() (for an i_size change), or at the top of ocfs2_file_aio_write(). Inodes on file systems with sparse file support will want to do their allocation during the actual write call. In either case the cluster locking decisions are the same. We abstract out that code into a new function, ocfs2_lock_allocators() which will be used by a later patch to enable writing to sparse files. This also provides a nice cleanup of ocfs2_extend_allocation(). Signed-off-by: Mark Fasheh <mark.fasheh@oracle.com>
Diffstat (limited to 'fs/ocfs2/file.c')
-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