* [Cluster-devel] [GFS2 PATCH] GFS2: Increase i_writecount during gfs2_setattr_size [not found] <2055011372.29570526.1369749816847.JavaMail.root@redhat.com> @ 2013-05-28 14:04 ` Bob Peterson 2013-05-28 14:20 ` Steven Whitehouse 0 siblings, 1 reply; 4+ messages in thread From: Bob Peterson @ 2013-05-28 14:04 UTC (permalink / raw) To: cluster-devel.redhat.com Hi, 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. Regards, Bob Peterson Red Hat File Systems Signed-off-by: Bob Peterson <rpeterso@redhat.com> --- diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index 1dc9a13..3f8ad82 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c @@ -1286,17 +1286,26 @@ int gfs2_setattr_size(struct inode *inode, u64 newsize) if (ret) return ret; + ret = get_write_access(inode); + if (ret) + return ret; + inode_dio_wait(inode); ret = gfs2_rs_alloc(GFS2_I(inode)); if (ret) - return ret; + goto out; oldsize = inode->i_size; - if (newsize >= oldsize) - return do_grow(inode, newsize); + if (newsize >= oldsize) { + 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) diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index acd1676..ad0dc38 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c @@ -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 */ file_update_time(vma->vm_file); + ret = get_write_access(inode); + if (ret) + goto out; + ret = gfs2_rs_alloc(ip); if (ret) - return ret; + goto out_write_access; gfs2_size_hint(vma->vm_file, pos, PAGE_CACHE_SIZE); gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); ret = gfs2_glock_nq(&gh); if (ret) - goto out; + goto out_uninit; set_bit(GLF_DIRTY, &ip->i_gl->gl_flags); set_bit(GIF_SW_PAGED, &ip->i_flags); @@ -480,12 +484,15 @@ out_quota_unlock: gfs2_quota_unlock(ip); out_unlock: gfs2_glock_dq(&gh); -out: +out_uninit: gfs2_holder_uninit(&gh); if (ret == 0) { set_page_dirty(page); wait_for_stable_page(page); } +out_write_access: + put_write_access(inode); +out: sb_end_pagefault(inode->i_sb); return block_page_mkwrite_return(ret); } @@ -594,10 +601,10 @@ static int gfs2_release(struct inode *inode, struct file *file) kfree(file->private_data); file->private_data = NULL; - if ((file->f_mode & FMODE_WRITE) && - (atomic_read(&inode->i_writecount) == 1)) - gfs2_rs_delete(ip); + if (!(file->f_mode & FMODE_WRITE)) + return 0; + gfs2_rs_delete(ip); return 0; } diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index 5232525..9809156 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c @@ -638,8 +638,10 @@ void gfs2_rs_deltree(struct gfs2_blkreserv *rs) */ void gfs2_rs_delete(struct gfs2_inode *ip) { + struct inode *inode = &ip->i_inode; + 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); BUG_ON(ip->i_res->rs_free); kmem_cache_free(gfs2_rsrv_cachep, ip->i_res); ^ permalink raw reply related [flat|nested] 4+ messages in thread
* [Cluster-devel] [GFS2 PATCH] GFS2: Increase i_writecount during gfs2_setattr_size 2013-05-28 14:04 ` [Cluster-devel] [GFS2 PATCH] GFS2: Increase i_writecount during gfs2_setattr_size Bob Peterson @ 2013-05-28 14:20 ` Steven Whitehouse 2013-05-28 16:54 ` Bob Peterson 0 siblings, 1 reply; 4+ messages in thread From: Steven Whitehouse @ 2013-05-28 14:20 UTC (permalink / raw) To: cluster-devel.redhat.com Hi, On Tue, 2013-05-28 at 10:04 -0400, Bob Peterson wrote: > Hi, > > 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. > > Regards, > > Bob Peterson > Red Hat File Systems > > Signed-off-by: Bob Peterson <rpeterso@redhat.com> > --- > diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c > index 1dc9a13..3f8ad82 100644 > --- a/fs/gfs2/bmap.c > +++ b/fs/gfs2/bmap.c > @@ -1286,17 +1286,26 @@ int gfs2_setattr_size(struct inode *inode, u64 newsize) > if (ret) > return ret; > > + ret = get_write_access(inode); > + if (ret) > + return ret; > + > inode_dio_wait(inode); > > ret = gfs2_rs_alloc(GFS2_I(inode)); > if (ret) > - return ret; > + goto out; > > oldsize = inode->i_size; > - if (newsize >= oldsize) > - return do_grow(inode, newsize); > + if (newsize >= oldsize) { > + 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) > diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c > index acd1676..ad0dc38 100644 > --- a/fs/gfs2/file.c > +++ b/fs/gfs2/file.c > @@ -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 */ > file_update_time(vma->vm_file); > > + ret = get_write_access(inode); > + if (ret) > + goto out; > + > ret = gfs2_rs_alloc(ip); > if (ret) > - return ret; > + goto out_write_access; > > gfs2_size_hint(vma->vm_file, pos, PAGE_CACHE_SIZE); > > gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); > ret = gfs2_glock_nq(&gh); > if (ret) > - goto out; > + goto out_uninit; > > set_bit(GLF_DIRTY, &ip->i_gl->gl_flags); > set_bit(GIF_SW_PAGED, &ip->i_flags); > @@ -480,12 +484,15 @@ out_quota_unlock: > gfs2_quota_unlock(ip); > out_unlock: > gfs2_glock_dq(&gh); > -out: > +out_uninit: > gfs2_holder_uninit(&gh); > if (ret == 0) { > set_page_dirty(page); > wait_for_stable_page(page); > } > +out_write_access: > + put_write_access(inode); > +out: > sb_end_pagefault(inode->i_sb); > return block_page_mkwrite_return(ret); > } > @@ -594,10 +601,10 @@ static int gfs2_release(struct inode *inode, struct file *file) > kfree(file->private_data); > file->private_data = NULL; > > - if ((file->f_mode & FMODE_WRITE) && > - (atomic_read(&inode->i_writecount) == 1)) > - gfs2_rs_delete(ip); > + if (!(file->f_mode & FMODE_WRITE)) > + return 0; > > + gfs2_rs_delete(ip); > return 0; > } > > diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c > index 5232525..9809156 100644 > --- a/fs/gfs2/rgrp.c > +++ b/fs/gfs2/rgrp.c > @@ -638,8 +638,10 @@ void gfs2_rs_deltree(struct gfs2_blkreserv *rs) > */ > void gfs2_rs_delete(struct gfs2_inode *ip) > { > + struct inode *inode = &ip->i_inode; > + > 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); > BUG_ON(ip->i_res->rs_free); > kmem_cache_free(gfs2_rsrv_cachep, ip->i_res); > Are there any other callers of gfs2_rs_delete where it is no appropriate to have this new test? I assume that the issue is that this writecount test needs to be under the i_rw_mutex? Steve. ^ permalink raw reply [flat|nested] 4+ messages in thread
* [Cluster-devel] [GFS2 PATCH] GFS2: Increase i_writecount during gfs2_setattr_size 2013-05-28 14:20 ` Steven Whitehouse @ 2013-05-28 16:54 ` Bob Peterson 2013-05-29 10:44 ` Steven Whitehouse 0 siblings, 1 reply; 4+ messages in thread From: Bob Peterson @ 2013-05-28 16:54 UTC (permalink / raw) To: cluster-devel.redhat.com ----- Original Message ----- | > --- a/fs/gfs2/rgrp.c | > +++ b/fs/gfs2/rgrp.c | > @@ -638,8 +638,10 @@ void gfs2_rs_deltree(struct gfs2_blkreserv *rs) | > */ | > void gfs2_rs_delete(struct gfs2_inode *ip) | > { | > + struct inode *inode = &ip->i_inode; | > + | > 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); | > BUG_ON(ip->i_res->rs_free); | > kmem_cache_free(gfs2_rsrv_cachep, ip->i_res); | > | | Are there any other callers of gfs2_rs_delete where it is no appropriate | to have this new test? | | I assume that the issue is that this writecount test needs to be under | the i_rw_mutex? | | Steve. Hi, Nope. It's okay for reservations to go in and out of a rgrp reservations tree; it happens all the time. What we really need to protect is where it's freed from cache (kmem_cache_free) which only happens in function gfs2_rs_deltree, where it's now protected by this patch. And yes, it needs to be done under the i_rw_mutex. The bigger question is whether there are other places besides functions gfs2_setattr_size and gfs2_page_mkwrite that should be calling get_write_access to ensure this protection. These are the only two we've seen in actual practice, and I wanted the patch to be as minimal as possible. Regards, Bob Peterson Red Hat File Systems ^ permalink raw reply [flat|nested] 4+ messages in thread
* [Cluster-devel] [GFS2 PATCH] GFS2: Increase i_writecount during gfs2_setattr_size 2013-05-28 16:54 ` Bob Peterson @ 2013-05-29 10:44 ` Steven Whitehouse 0 siblings, 0 replies; 4+ messages in thread From: Steven Whitehouse @ 2013-05-29 10:44 UTC (permalink / raw) To: cluster-devel.redhat.com Hi, On Tue, 2013-05-28 at 12:54 -0400, Bob Peterson wrote: > ----- Original Message ----- > | > --- a/fs/gfs2/rgrp.c > | > +++ b/fs/gfs2/rgrp.c > | > @@ -638,8 +638,10 @@ void gfs2_rs_deltree(struct gfs2_blkreserv *rs) > | > */ > | > void gfs2_rs_delete(struct gfs2_inode *ip) > | > { > | > + struct inode *inode = &ip->i_inode; > | > + > | > 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); > | > BUG_ON(ip->i_res->rs_free); > | > kmem_cache_free(gfs2_rsrv_cachep, ip->i_res); > | > > | > | Are there any other callers of gfs2_rs_delete where it is no appropriate > | to have this new test? > | > | I assume that the issue is that this writecount test needs to be under > | the i_rw_mutex? > | > | Steve. > > Hi, > > Nope. It's okay for reservations to go in and out of a rgrp reservations tree; > it happens all the time. What we really need to protect is where it's > freed from cache (kmem_cache_free) which only happens in function > gfs2_rs_deltree, where it's now protected by this patch. And yes, it > needs to be done under the i_rw_mutex. > Ok, sounds good. I've applied the patch to the -nmw tree. > The bigger question is whether there are other places besides functions > gfs2_setattr_size and gfs2_page_mkwrite that should be calling > get_write_access to ensure this protection. These are the only two > we've seen in actual practice, and I wanted the patch to be as > minimal as possible. > > Regards, > > Bob Peterson > Red Hat File Systems Yes, looks good. If there are other places, they are likely to be those where we write to internal files via an interface other than the vfs. The quotactl interface comes to mind, and perhaps also statfs too. From userspace, if we have an open file descriptor, then there should generally not be a problem, Steve. ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2013-05-29 10:44 UTC | newest] Thread overview: 4+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- [not found] <2055011372.29570526.1369749816847.JavaMail.root@redhat.com> 2013-05-28 14:04 ` [Cluster-devel] [GFS2 PATCH] GFS2: Increase i_writecount during gfs2_setattr_size Bob Peterson 2013-05-28 14:20 ` Steven Whitehouse 2013-05-28 16:54 ` Bob Peterson 2013-05-29 10:44 ` Steven Whitehouse
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).