mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-13 08:39:52 +00:00
GFS2: Increase i_writecount during gfs2_setattr_size
This patch calls get_write_access in a few functions. This merely increases inode->i_writecount for the duration of the function. That will ensure that any file closes won't delete the inode's multi-block reservation while the function is running. Signed-off-by: Bob Peterson <rpeterso@redhat.com> Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
This commit is contained in:
parent
4a58681205
commit
2b3dcf3581
@ -1286,17 +1286,26 @@ int gfs2_setattr_size(struct inode *inode, u64 newsize)
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
ret = get_write_access(inode);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
inode_dio_wait(inode);
|
inode_dio_wait(inode);
|
||||||
|
|
||||||
ret = gfs2_rs_alloc(GFS2_I(inode));
|
ret = gfs2_rs_alloc(GFS2_I(inode));
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
goto out;
|
||||||
|
|
||||||
oldsize = inode->i_size;
|
oldsize = inode->i_size;
|
||||||
if (newsize >= oldsize)
|
if (newsize >= oldsize) {
|
||||||
return do_grow(inode, newsize);
|
ret = do_grow(inode, newsize);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
return do_shrink(inode, oldsize, newsize);
|
ret = do_shrink(inode, oldsize, newsize);
|
||||||
|
out:
|
||||||
|
put_write_access(inode);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int gfs2_truncatei_resume(struct gfs2_inode *ip)
|
int gfs2_truncatei_resume(struct gfs2_inode *ip)
|
||||||
|
@ -402,16 +402,20 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
|
|||||||
/* Update file times before taking page lock */
|
/* Update file times before taking page lock */
|
||||||
file_update_time(vma->vm_file);
|
file_update_time(vma->vm_file);
|
||||||
|
|
||||||
|
ret = get_write_access(inode);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
|
||||||
ret = gfs2_rs_alloc(ip);
|
ret = gfs2_rs_alloc(ip);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
goto out_write_access;
|
||||||
|
|
||||||
gfs2_size_hint(vma->vm_file, pos, PAGE_CACHE_SIZE);
|
gfs2_size_hint(vma->vm_file, pos, PAGE_CACHE_SIZE);
|
||||||
|
|
||||||
gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
|
gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
|
||||||
ret = gfs2_glock_nq(&gh);
|
ret = gfs2_glock_nq(&gh);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out_uninit;
|
||||||
|
|
||||||
set_bit(GLF_DIRTY, &ip->i_gl->gl_flags);
|
set_bit(GLF_DIRTY, &ip->i_gl->gl_flags);
|
||||||
set_bit(GIF_SW_PAGED, &ip->i_flags);
|
set_bit(GIF_SW_PAGED, &ip->i_flags);
|
||||||
@ -480,12 +484,15 @@ out_quota_unlock:
|
|||||||
gfs2_quota_unlock(ip);
|
gfs2_quota_unlock(ip);
|
||||||
out_unlock:
|
out_unlock:
|
||||||
gfs2_glock_dq(&gh);
|
gfs2_glock_dq(&gh);
|
||||||
out:
|
out_uninit:
|
||||||
gfs2_holder_uninit(&gh);
|
gfs2_holder_uninit(&gh);
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
set_page_dirty(page);
|
set_page_dirty(page);
|
||||||
wait_for_stable_page(page);
|
wait_for_stable_page(page);
|
||||||
}
|
}
|
||||||
|
out_write_access:
|
||||||
|
put_write_access(inode);
|
||||||
|
out:
|
||||||
sb_end_pagefault(inode->i_sb);
|
sb_end_pagefault(inode->i_sb);
|
||||||
return block_page_mkwrite_return(ret);
|
return block_page_mkwrite_return(ret);
|
||||||
}
|
}
|
||||||
@ -594,10 +601,10 @@ static int gfs2_release(struct inode *inode, struct file *file)
|
|||||||
kfree(file->private_data);
|
kfree(file->private_data);
|
||||||
file->private_data = NULL;
|
file->private_data = NULL;
|
||||||
|
|
||||||
if ((file->f_mode & FMODE_WRITE) &&
|
if (!(file->f_mode & FMODE_WRITE))
|
||||||
(atomic_read(&inode->i_writecount) == 1))
|
return 0;
|
||||||
gfs2_rs_delete(ip);
|
|
||||||
|
|
||||||
|
gfs2_rs_delete(ip);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -638,8 +638,10 @@ void gfs2_rs_deltree(struct gfs2_blkreserv *rs)
|
|||||||
*/
|
*/
|
||||||
void gfs2_rs_delete(struct gfs2_inode *ip)
|
void gfs2_rs_delete(struct gfs2_inode *ip)
|
||||||
{
|
{
|
||||||
|
struct inode *inode = &ip->i_inode;
|
||||||
|
|
||||||
down_write(&ip->i_rw_mutex);
|
down_write(&ip->i_rw_mutex);
|
||||||
if (ip->i_res) {
|
if (ip->i_res && atomic_read(&inode->i_writecount) <= 1) {
|
||||||
gfs2_rs_deltree(ip->i_res);
|
gfs2_rs_deltree(ip->i_res);
|
||||||
BUG_ON(ip->i_res->rs_free);
|
BUG_ON(ip->i_res->rs_free);
|
||||||
kmem_cache_free(gfs2_rsrv_cachep, ip->i_res);
|
kmem_cache_free(gfs2_rsrv_cachep, ip->i_res);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user