aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2007-10-17 09:05:41 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2008-01-25 03:07:30 -0500
commitc41d4f09f13671f98ba4b82fdc94420cdc09be08 (patch)
treed1a9701517d56673c869077520ea59be9d6dce64
parentb8e7cbb65bcc99630e123422c6829ce3c0fcdf14 (diff)
[GFS2] Don't hold page lock when starting transaction
This is an addendum to the new AOPs work which moves the point at which we take the page lock so that we don't get it until the last possible moment. This resolves a conflict between starting transactions and the page lock. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
-rw-r--r--fs/gfs2/ops_address.c51
1 files changed, 25 insertions, 26 deletions
diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c
index 48913e569907..ae782d2cbdec 100644
--- a/fs/gfs2/ops_address.c
+++ b/fs/gfs2/ops_address.c
@@ -657,18 +657,10 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping,
657 if (unlikely(error)) 657 if (unlikely(error))
658 goto out_uninit; 658 goto out_uninit;
659 659
660 error = -ENOMEM;
661 page = __grab_cache_page(mapping, index);
662 *pagep = page;
663 if (!page)
664 goto out_unlock;
665
666 gfs2_write_calc_reserv(ip, len, &data_blocks, &ind_blocks); 660 gfs2_write_calc_reserv(ip, len, &data_blocks, &ind_blocks);
667
668 error = gfs2_write_alloc_required(ip, pos, len, &alloc_required); 661 error = gfs2_write_alloc_required(ip, pos, len, &alloc_required);
669 if (error) 662 if (error)
670 goto out_putpage; 663 goto out_unlock;
671
672 664
673 ip->i_alloc.al_requested = 0; 665 ip->i_alloc.al_requested = 0;
674 if (alloc_required) { 666 if (alloc_required) {
@@ -699,40 +691,47 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping,
699 if (error) 691 if (error)
700 goto out_trans_fail; 692 goto out_trans_fail;
701 693
694 error = -ENOMEM;
695 page = __grab_cache_page(mapping, index);
696 *pagep = page;
697 if (unlikely(!page))
698 goto out_endtrans;
699
702 if (gfs2_is_stuffed(ip)) { 700 if (gfs2_is_stuffed(ip)) {
701 error = 0;
703 if (pos + len > sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)) { 702 if (pos + len > sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)) {
704 error = gfs2_unstuff_dinode(ip, page); 703 error = gfs2_unstuff_dinode(ip, page);
705 if (error == 0) 704 if (error == 0)
706 goto prepare_write; 705 goto prepare_write;
707 } else if (!PageUptodate(page)) 706 } else if (!PageUptodate(page)) {
708 error = stuffed_readpage(ip, page); 707 error = stuffed_readpage(ip, page);
708 }
709 goto out; 709 goto out;
710 } 710 }
711 711
712prepare_write: 712prepare_write:
713 error = block_prepare_write(page, from, to, gfs2_get_block); 713 error = block_prepare_write(page, from, to, gfs2_get_block);
714
715out: 714out:
716 if (error) { 715 if (error == 0)
717 gfs2_trans_end(sdp); 716 return 0;
717
718 page_cache_release(page);
719 if (pos + len > ip->i_inode.i_size)
720 vmtruncate(&ip->i_inode, ip->i_inode.i_size);
721out_endtrans:
722 gfs2_trans_end(sdp);
718out_trans_fail: 723out_trans_fail:
719 if (alloc_required) { 724 if (alloc_required) {
720 gfs2_inplace_release(ip); 725 gfs2_inplace_release(ip);
721out_qunlock: 726out_qunlock:
722 gfs2_quota_unlock(ip); 727 gfs2_quota_unlock(ip);
723out_alloc_put: 728out_alloc_put:
724 gfs2_alloc_put(ip); 729 gfs2_alloc_put(ip);
725 } 730 }
726out_putpage:
727 page_cache_release(page);
728 if (pos + len > ip->i_inode.i_size)
729 vmtruncate(&ip->i_inode, ip->i_inode.i_size);
730out_unlock: 731out_unlock:
731 gfs2_glock_dq_m(1, &ip->i_gh); 732 gfs2_glock_dq(&ip->i_gh);
732out_uninit: 733out_uninit:
733 gfs2_holder_uninit(&ip->i_gh); 734 gfs2_holder_uninit(&ip->i_gh);
734 }
735
736 return error; 735 return error;
737} 736}
738 737