From mboxrd@z Thu Jan 1 00:00:00 1970 From: Bob Peterson Date: Thu, 22 Oct 2015 14:30:21 -0500 Subject: [Cluster-devel] [GFS2 PATCH v3 13/14] GFS2: Hold onto iopen glock longer when dinode creation fails In-Reply-To: <1445542222-30672-1-git-send-email-rpeterso@redhat.com> References: <1445542222-30672-1-git-send-email-rpeterso@redhat.com> Message-ID: <1445542222-30672-14-git-send-email-rpeterso@redhat.com> List-Id: To: cluster-devel.redhat.com MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit This patch allows function gfs2_create_inode to keep hold of the iopen glock longer in cases where the creation of a new dinode fails. This prevents some nasty timing windows where a dinode is being created and reused. Signed-off-by: Bob Peterson --- fs/gfs2/inode.c | 19 ++++++++++++------- fs/gfs2/main.c | 2 ++ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 631d4ef..a878767 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -673,7 +673,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, struct posix_acl *default_acl, *acl; struct gfs2_holder ghs[2]; struct inode *inode = NULL; - struct gfs2_inode *dip = GFS2_I(dir), *ip; + struct gfs2_inode *dip = GFS2_I(dir), *ip = NULL; struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); struct gfs2_glock *io_gl; int error, free_vfs_inode = 0; @@ -839,16 +839,16 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, } if (error) - goto fail_gunlock3; + goto fail_gunlock2; error = security_inode_init_security(&ip->i_inode, &dip->i_inode, name, &gfs2_initxattrs, NULL); if (error) - goto fail_gunlock3; + goto fail_gunlock2; error = link_dinode(dip, name, ip, &da); if (error) - goto fail_gunlock3; + goto fail_gunlock2; mark_inode_dirty(inode); d_instantiate(dentry, inode); @@ -864,9 +864,6 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, gfs2_glock_dq_uninit(ghs + 1); return error; -fail_gunlock3: - if (ip->i_iopen_gh.gh_gl) /* if holder is linked to the glock */ - gfs2_glock_put(ip->i_iopen_gh.gh_gl); fail_gunlock2: gfs2_glock_dq_uninit(ghs + 1); fail_free_inode: @@ -883,6 +880,14 @@ fail_free_acls: posix_acl_release(acl); fail_free_vfs_inode: free_vfs_inode = 1; + /* We hold off until the very end to release the iopen glock. That + * keeps other processes from acquiring it in EX mode and deleting + * it while we're still using it. Since gfs2_delete_inode already + * handles the iopen vs. inode glocks in any order, the lock order + * does not matter. It must be done before iput, though, otherwise + * we might get a segfault trying to dereference it. */ + if (ip && ip->i_iopen_gh.gh_gl) /* if holder is linked to the glock */ + gfs2_glock_put(ip->i_iopen_gh.gh_gl); fail_gunlock: gfs2_dir_no_add(&da); gfs2_glock_dq_uninit(ghs); diff --git a/fs/gfs2/main.c b/fs/gfs2/main.c index 241a399..a8bd5b6 100644 --- a/fs/gfs2/main.c +++ b/fs/gfs2/main.c @@ -43,6 +43,8 @@ static void gfs2_init_inode_once(void *foo) INIT_LIST_HEAD(&ip->i_trunc_list); ip->i_res = NULL; ip->i_hash_cache = NULL; + ip->i_iopen_gh.gh_gl = NULL; + INIT_LIST_HEAD(&ip->i_iopen_gh.gh_list); } static void gfs2_init_glock_once(void *foo) -- 2.4.3