Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a4923865 authored by Bob Peterson's avatar Bob Peterson
Browse files

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
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -572,6 +572,12 @@ static void delete_work_func(struct work_struct *work)
	struct inode *inode;
	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;
	/* 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)
		d_prune_aliases(inode);
		iput(inode);
	}
out:
	gfs2_glock_put(gl);
}

+1 −0
Original line number Diff line number Diff line
@@ -328,6 +328,7 @@ enum {
	GLF_LRU				= 13,
	GLF_OBJECT			= 14, /* Used only for tracing */
	GLF_BLOCKING			= 15,
	GLF_INODE_CREATING		= 16, /* Inode creation occurring */
};

struct gfs2_glock {
+6 −1
Original line number Diff line number Diff line
@@ -592,7 +592,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
	struct inode *inode = NULL;
	struct gfs2_inode *dip = GFS2_I(dir), *ip;
	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;
	u32 aflags = 0;
	unsigned blocks = 1;
@@ -729,6 +729,8 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
	if (error)
		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);
	if (error)
		goto fail_gunlock2;
@@ -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 + 1);
	clear_bit(GLF_INODE_CREATING, &io_gl->gl_flags);
	return error;

fail_gunlock3:
	gfs2_glock_dq_uninit(&ip->i_iopen_gh);
	gfs2_glock_put(io_gl);
fail_gunlock2:
	if (io_gl)
		clear_bit(GLF_INODE_CREATING, &io_gl->gl_flags);
	gfs2_glock_dq_uninit(ghs + 1);
fail_free_inode:
	if (ip->i_gl)