Commit bf2d6369 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull gfs2 fixes from Andreas Gruenbacher:
 "Various gfs2 fixes"

* tag 'gfs2-v5.8-rc3.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2:
  gfs2: The freeze glock should never be frozen
  gfs2: When freezing gfs2, use GL_EXACT and not GL_NOCACHE
  gfs2: read-only mounts should grab the sd_freeze_gl glock
  gfs2: freeze should work on read-only mounts
  gfs2: eliminate GIF_ORDERED in favor of list_empty
  gfs2: Don't sleep during glock hash walk
  gfs2: fix trans slab error when withdraw occurs inside log_flush
  gfs2: Don't return NULL from gfs2_inode_lookup
parents 1d428714 c860f8ff
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -1899,7 +1899,10 @@ bool gfs2_delete_work_queued(const struct gfs2_glock *gl)

static void flush_delete_work(struct gfs2_glock *gl)
{
	flush_delayed_work(&gl->gl_delete);
	if (cancel_delayed_work(&gl->gl_delete)) {
		queue_delayed_work(gfs2_delete_workqueue,
				   &gl->gl_delete, 0);
	}
	gfs2_glock_queue_work(gl, 0);
}

+6 −4
Original line number Diff line number Diff line
@@ -531,8 +531,7 @@ static int freeze_go_sync(struct gfs2_glock *gl)
	int error = 0;
	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;

	if (gl->gl_state == LM_ST_SHARED && !gfs2_withdrawn(sdp) &&
	    test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) {
	if (gl->gl_req == LM_ST_EXCLUSIVE && !gfs2_withdrawn(sdp)) {
		atomic_set(&sdp->sd_freeze_state, SFS_STARTING_FREEZE);
		error = freeze_super(sdp->sd_vfs);
		if (error) {
@@ -545,8 +544,11 @@ static int freeze_go_sync(struct gfs2_glock *gl)
			gfs2_assert_withdraw(sdp, 0);
		}
		queue_work(gfs2_freeze_wq, &sdp->sd_freeze_work);
		if (test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags))
			gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_FREEZE |
				       GFS2_LFC_FREEZE_GO_SYNC);
		else /* read-only mounts */
			atomic_set(&sdp->sd_freeze_state, SFS_FROZEN);
	}
	return 0;
}
+0 −1
Original line number Diff line number Diff line
@@ -399,7 +399,6 @@ enum {
	GIF_QD_LOCKED		= 1,
	GIF_ALLOC_FAILED	= 2,
	GIF_SW_PAGED		= 3,
	GIF_ORDERED		= 4,
	GIF_FREE_VFS_INODE      = 5,
	GIF_GLOP_PENDING	= 6,
	GIF_DEFERRED_DELETE	= 7,
+2 −1
Original line number Diff line number Diff line
@@ -207,10 +207,11 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type,

	if (no_formal_ino && ip->i_no_formal_ino &&
	    no_formal_ino != ip->i_no_formal_ino) {
		error = -ESTALE;
		if (inode->i_state & I_NEW)
			goto fail;
		iput(inode);
		return ERR_PTR(-ESTALE);
		return ERR_PTR(error);
	}

	if (inode->i_state & I_NEW)
+19 −6
Original line number Diff line number Diff line
@@ -613,6 +613,12 @@ static int ip_cmp(void *priv, struct list_head *a, struct list_head *b)
	return 0;
}

static void __ordered_del_inode(struct gfs2_inode *ip)
{
	if (!list_empty(&ip->i_ordered))
		list_del_init(&ip->i_ordered);
}

static void gfs2_ordered_write(struct gfs2_sbd *sdp)
{
	struct gfs2_inode *ip;
@@ -623,8 +629,7 @@ static void gfs2_ordered_write(struct gfs2_sbd *sdp)
	while (!list_empty(&sdp->sd_log_ordered)) {
		ip = list_first_entry(&sdp->sd_log_ordered, struct gfs2_inode, i_ordered);
		if (ip->i_inode.i_mapping->nrpages == 0) {
			test_and_clear_bit(GIF_ORDERED, &ip->i_flags);
			list_del(&ip->i_ordered);
			__ordered_del_inode(ip);
			continue;
		}
		list_move(&ip->i_ordered, &written);
@@ -643,8 +648,7 @@ static void gfs2_ordered_wait(struct gfs2_sbd *sdp)
	spin_lock(&sdp->sd_ordered_lock);
	while (!list_empty(&sdp->sd_log_ordered)) {
		ip = list_first_entry(&sdp->sd_log_ordered, struct gfs2_inode, i_ordered);
		list_del(&ip->i_ordered);
		WARN_ON(!test_and_clear_bit(GIF_ORDERED, &ip->i_flags));
		__ordered_del_inode(ip);
		if (ip->i_inode.i_mapping->nrpages == 0)
			continue;
		spin_unlock(&sdp->sd_ordered_lock);
@@ -659,8 +663,7 @@ void gfs2_ordered_del_inode(struct gfs2_inode *ip)
	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);

	spin_lock(&sdp->sd_ordered_lock);
	if (test_and_clear_bit(GIF_ORDERED, &ip->i_flags))
		list_del(&ip->i_ordered);
	__ordered_del_inode(ip);
	spin_unlock(&sdp->sd_ordered_lock);
}

@@ -1002,6 +1005,16 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, u32 flags)

out:
	if (gfs2_withdrawn(sdp)) {
		/**
		 * If the tr_list is empty, we're withdrawing during a log
		 * flush that targets a transaction, but the transaction was
		 * never queued onto any of the ail lists. Here we add it to
		 * ail1 just so that ail_drain() will find and free it.
		 */
		spin_lock(&sdp->sd_ail_lock);
		if (tr && list_empty(&tr->tr_list))
			list_add(&tr->tr_list, &sdp->sd_ail1_list);
		spin_unlock(&sdp->sd_ail_lock);
		ail_drain(sdp); /* frees all transactions */
		tr = NULL;
	}
Loading