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>
if (unlikely(error))
goto out_uninit;
if (unlikely(error))
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);
if (error)
error = gfs2_write_alloc_required(ip, pos, len, &alloc_required);
if (error)
ip->i_alloc.al_requested = 0;
if (alloc_required) {
ip->i_alloc.al_requested = 0;
if (alloc_required) {
if (error)
goto out_trans_fail;
if (error)
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)) {
if (pos + len > sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)) {
error = gfs2_unstuff_dinode(ip, page);
if (error == 0)
goto prepare_write;
if (pos + len > sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)) {
error = gfs2_unstuff_dinode(ip, page);
if (error == 0)
goto prepare_write;
- } else if (!PageUptodate(page))
+ } else if (!PageUptodate(page)) {
error = stuffed_readpage(ip, page);
error = stuffed_readpage(ip, page);
goto out;
}
prepare_write:
error = block_prepare_write(page, from, to, gfs2_get_block);
goto out;
}
prepare_write:
error = block_prepare_write(page, from, to, gfs2_get_block);
- if (error) {
- gfs2_trans_end(sdp);
+ if (error == 0)
+ return 0;
+
+ 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);
- if (alloc_required) {
- gfs2_inplace_release(ip);
+ if (alloc_required) {
+ gfs2_inplace_release(ip);
- 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);
+ gfs2_alloc_put(ip);
+ }
- gfs2_glock_dq_m(1, &ip->i_gh);
+ gfs2_glock_dq(&ip->i_gh);
- gfs2_holder_uninit(&ip->i_gh);
- }
-
+ gfs2_holder_uninit(&ip->i_gh);