Commit a4923865 authored by Bob Peterson's avatar Bob Peterson

GFS2: Prevent delete work from occurring on glocks used for create

This patch tries to prevent delete work (queued via iopen callback)
from executing if the glock is currently being used to create
a new inode.
Signed-off-by: default avatarBob Peterson <rpeterso@redhat.com>
Acked-by: default avatarSteven Whitehouse <swhiteho@redhat.com>
parent 2df6f471
...@@ -572,6 +572,12 @@ static void delete_work_func(struct work_struct *work) ...@@ -572,6 +572,12 @@ static void delete_work_func(struct work_struct *work)
struct inode *inode; struct inode *inode;
u64 no_addr = gl->gl_name.ln_number; u64 no_addr = gl->gl_name.ln_number;
/* If someone's using this glock to create a new dinode, the block must
have been freed by another node, then re-used, in which case our
iopen callback is too late after the fact. Ignore it. */
if (test_bit(GLF_INODE_CREATING, &gl->gl_flags))
goto out;
ip = gl->gl_object; ip = gl->gl_object;
/* Note: Unsafe to dereference ip as we don't hold right refs/locks */ /* Note: Unsafe to dereference ip as we don't hold right refs/locks */
...@@ -583,6 +589,7 @@ static void delete_work_func(struct work_struct *work) ...@@ -583,6 +589,7 @@ static void delete_work_func(struct work_struct *work)
d_prune_aliases(inode); d_prune_aliases(inode);
iput(inode); iput(inode);
} }
out:
gfs2_glock_put(gl); gfs2_glock_put(gl);
} }
......
...@@ -328,6 +328,7 @@ enum { ...@@ -328,6 +328,7 @@ enum {
GLF_LRU = 13, GLF_LRU = 13,
GLF_OBJECT = 14, /* Used only for tracing */ GLF_OBJECT = 14, /* Used only for tracing */
GLF_BLOCKING = 15, GLF_BLOCKING = 15,
GLF_INODE_CREATING = 16, /* Inode creation occurring */
}; };
struct gfs2_glock { struct gfs2_glock {
......
...@@ -592,7 +592,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, ...@@ -592,7 +592,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
struct inode *inode = NULL; struct inode *inode = NULL;
struct gfs2_inode *dip = GFS2_I(dir), *ip; struct gfs2_inode *dip = GFS2_I(dir), *ip;
struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
struct gfs2_glock *io_gl; struct gfs2_glock *io_gl = NULL;
int error, free_vfs_inode = 1; int error, free_vfs_inode = 1;
u32 aflags = 0; u32 aflags = 0;
unsigned blocks = 1; unsigned blocks = 1;
...@@ -729,6 +729,8 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, ...@@ -729,6 +729,8 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
if (error) if (error)
goto fail_gunlock2; goto fail_gunlock2;
BUG_ON(test_and_set_bit(GLF_INODE_CREATING, &io_gl->gl_flags));
error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, GL_EXACT, &ip->i_iopen_gh); error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, GL_EXACT, &ip->i_iopen_gh);
if (error) if (error)
goto fail_gunlock2; goto fail_gunlock2;
...@@ -771,12 +773,15 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, ...@@ -771,12 +773,15 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
} }
gfs2_glock_dq_uninit(ghs); gfs2_glock_dq_uninit(ghs);
gfs2_glock_dq_uninit(ghs + 1); gfs2_glock_dq_uninit(ghs + 1);
clear_bit(GLF_INODE_CREATING, &io_gl->gl_flags);
return error; return error;
fail_gunlock3: fail_gunlock3:
gfs2_glock_dq_uninit(&ip->i_iopen_gh); gfs2_glock_dq_uninit(&ip->i_iopen_gh);
gfs2_glock_put(io_gl); gfs2_glock_put(io_gl);
fail_gunlock2: fail_gunlock2:
if (io_gl)
clear_bit(GLF_INODE_CREATING, &io_gl->gl_flags);
gfs2_glock_dq_uninit(ghs + 1); gfs2_glock_dq_uninit(ghs + 1);
fail_free_inode: fail_free_inode:
if (ip->i_gl) if (ip->i_gl)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment