[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>
This commit is contained in:
parent
b8e7cbb65b
commit
c41d4f09f1
@ -657,18 +657,10 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping,
|
|||||||
if (unlikely(error))
|
if (unlikely(error))
|
||||||
goto out_uninit;
|
goto out_uninit;
|
||||||
|
|
||||||
error = -ENOMEM;
|
|
||||||
page = __grab_cache_page(mapping, index);
|
|
||||||
*pagep = page;
|
|
||||||
if (!page)
|
|
||||||
goto out_unlock;
|
|
||||||
|
|
||||||
gfs2_write_calc_reserv(ip, len, &data_blocks, &ind_blocks);
|
gfs2_write_calc_reserv(ip, len, &data_blocks, &ind_blocks);
|
||||||
|
|
||||||
error = gfs2_write_alloc_required(ip, pos, len, &alloc_required);
|
error = gfs2_write_alloc_required(ip, pos, len, &alloc_required);
|
||||||
if (error)
|
if (error)
|
||||||
goto out_putpage;
|
goto out_unlock;
|
||||||
|
|
||||||
|
|
||||||
ip->i_alloc.al_requested = 0;
|
ip->i_alloc.al_requested = 0;
|
||||||
if (alloc_required) {
|
if (alloc_required) {
|
||||||
@ -699,40 +691,47 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping,
|
|||||||
if (error)
|
if (error)
|
||||||
goto out_trans_fail;
|
goto out_trans_fail;
|
||||||
|
|
||||||
|
error = -ENOMEM;
|
||||||
|
page = __grab_cache_page(mapping, index);
|
||||||
|
*pagep = page;
|
||||||
|
if (unlikely(!page))
|
||||||
|
goto out_endtrans;
|
||||||
|
|
||||||
if (gfs2_is_stuffed(ip)) {
|
if (gfs2_is_stuffed(ip)) {
|
||||||
|
error = 0;
|
||||||
if (pos + len > sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)) {
|
if (pos + len > sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)) {
|
||||||
error = gfs2_unstuff_dinode(ip, page);
|
error = gfs2_unstuff_dinode(ip, page);
|
||||||
if (error == 0)
|
if (error == 0)
|
||||||
goto prepare_write;
|
goto prepare_write;
|
||||||
} else if (!PageUptodate(page))
|
} else if (!PageUptodate(page)) {
|
||||||
error = stuffed_readpage(ip, page);
|
error = stuffed_readpage(ip, page);
|
||||||
|
}
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
prepare_write:
|
prepare_write:
|
||||||
error = block_prepare_write(page, from, to, gfs2_get_block);
|
error = block_prepare_write(page, from, to, gfs2_get_block);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (error) {
|
if (error == 0)
|
||||||
gfs2_trans_end(sdp);
|
return 0;
|
||||||
out_trans_fail:
|
|
||||||
if (alloc_required) {
|
|
||||||
gfs2_inplace_release(ip);
|
|
||||||
out_qunlock:
|
|
||||||
gfs2_quota_unlock(ip);
|
|
||||||
out_alloc_put:
|
|
||||||
gfs2_alloc_put(ip);
|
|
||||||
}
|
|
||||||
out_putpage:
|
|
||||||
page_cache_release(page);
|
|
||||||
if (pos + len > ip->i_inode.i_size)
|
|
||||||
vmtruncate(&ip->i_inode, ip->i_inode.i_size);
|
|
||||||
out_unlock:
|
|
||||||
gfs2_glock_dq_m(1, &ip->i_gh);
|
|
||||||
out_uninit:
|
|
||||||
gfs2_holder_uninit(&ip->i_gh);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
page_cache_release(page);
|
||||||
|
if (pos + len > ip->i_inode.i_size)
|
||||||
|
vmtruncate(&ip->i_inode, ip->i_inode.i_size);
|
||||||
|
out_endtrans:
|
||||||
|
gfs2_trans_end(sdp);
|
||||||
|
out_trans_fail:
|
||||||
|
if (alloc_required) {
|
||||||
|
gfs2_inplace_release(ip);
|
||||||
|
out_qunlock:
|
||||||
|
gfs2_quota_unlock(ip);
|
||||||
|
out_alloc_put:
|
||||||
|
gfs2_alloc_put(ip);
|
||||||
|
}
|
||||||
|
out_unlock:
|
||||||
|
gfs2_glock_dq(&ip->i_gh);
|
||||||
|
out_uninit:
|
||||||
|
gfs2_holder_uninit(&ip->i_gh);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user