diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
index dae3dc4..0a7b807 100644
--- a/fs/gfs2/aops.c
+++ b/fs/gfs2/aops.c
@@ -158,6 +158,7 @@ static int gfs2_writepages(struct address_space *mapping,
 			   struct writeback_control *wbc)
 {
 	struct gfs2_sbd *sdp = gfs2_mapping2sbd(mapping);
+	long initial_nr_to_write = wbc->nr_to_write;
 	struct iomap_writepage_ctx wpc = {
 		.inode		= mapping->host,
 		.wbc		= wbc,
@@ -166,13 +167,13 @@ static int gfs2_writepages(struct address_space *mapping,
 	int ret;
 
 	/*
-	 * Even if we didn't write enough pages here, we might still be holding
+	 * Even if we didn't write any pages here, we might still be holding
 	 * dirty pages in the ail. We forcibly flush the ail because we don't
 	 * want balance_dirty_pages() to loop indefinitely trying to write out
 	 * pages held in the ail that it can't find.
 	 */
 	ret = iomap_writepages(&wpc);
-	if (ret == 0 && wbc->nr_to_write > 0)
+	if (ret == 0 && wbc->nr_to_write == initial_nr_to_write)
 		set_bit(SDF_FORCE_AIL_FLUSH, &sdp->sd_flags);
 	return ret;
 }
@@ -582,7 +583,7 @@ static void gfs2_discard(struct gfs2_sbd *sdp, struct buffer_head *bh)
 	struct gfs2_bufdata *bd;
 
 	lock_buffer(bh);
-	gfs2_log_lock(sdp);
+	spin_lock(&sdp->sd_log_lock);
 	clear_buffer_dirty(bh);
 	bd = bh->b_private;
 	if (bd) {
@@ -598,7 +599,7 @@ static void gfs2_discard(struct gfs2_sbd *sdp, struct buffer_head *bh)
 	clear_buffer_mapped(bh);
 	clear_buffer_req(bh);
 	clear_buffer_new(bh);
-	gfs2_log_unlock(sdp);
+	spin_unlock(&sdp->sd_log_lock);
 	unlock_buffer(bh);
 }
 
@@ -666,7 +667,7 @@ bool gfs2_release_folio(struct folio *folio, gfp_t gfp_mask)
 	 * again.
 	 */
 
-	gfs2_log_lock(sdp);
+	spin_lock(&sdp->sd_log_lock);
 	bh = head;
 	do {
 		if (atomic_read(&bh->b_count))
@@ -698,12 +699,12 @@ bool gfs2_release_folio(struct folio *folio, gfp_t gfp_mask)
 
 		bh = bh->b_this_page;
 	} while (bh != head);
-	gfs2_log_unlock(sdp);
+	spin_unlock(&sdp->sd_log_lock);
 
 	return try_to_free_buffers(folio);
 
 cannot_release:
-	gfs2_log_unlock(sdp);
+	spin_unlock(&sdp->sd_log_lock);
 	return false;
 }
 
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index 1cd8ec0..b3d7fcd 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -1539,7 +1539,7 @@ more_rgrps:
 			revokes = jblocks_rqsted;
 			if (meta)
 				revokes += end - start;
-			else if (ip->i_depth)
+			else if (ip->i_diskflags & GFS2_DIF_EXHASH)
 				revokes += sdp->sd_inptrs;
 			ret = gfs2_trans_begin(sdp, jblocks_rqsted, revokes);
 			if (ret)
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index ba61649..28f3242 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -64,7 +64,7 @@ static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync,
 	struct buffer_head *bh;
 	const unsigned long b_state = (1UL << BH_Dirty)|(1UL << BH_Pinned)|(1UL << BH_Lock);
 
-	gfs2_log_lock(sdp);
+	spin_lock(&sdp->sd_log_lock);
 	spin_lock(&sdp->sd_ail_lock);
 	list_for_each_entry_safe_reverse(bd, tmp, head, bd_ail_gl_list) {
 		if (nr_revokes == 0)
@@ -80,7 +80,7 @@ static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync,
 	}
 	GLOCK_BUG_ON(gl, !fsync && atomic_read(&gl->gl_ail_count));
 	spin_unlock(&sdp->sd_ail_lock);
-	gfs2_log_unlock(sdp);
+	spin_unlock(&sdp->sd_log_lock);
 }
 
 
@@ -109,10 +109,10 @@ static int gfs2_ail_empty_gl(struct gfs2_glock *gl)
 		 * If none of these conditions are true, our revokes are all
 		 * flushed and we can return.
 		 */
-		gfs2_log_lock(sdp);
+		spin_lock(&sdp->sd_log_lock);
 		have_revokes = !list_empty(&sdp->sd_log_revokes);
 		log_in_flight = atomic_read(&sdp->sd_log_in_flight);
-		gfs2_log_unlock(sdp);
+		spin_unlock(&sdp->sd_log_lock);
 		if (have_revokes)
 			goto flush;
 		if (log_in_flight)
@@ -457,6 +457,11 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
 	ip->i_depth = (u8)depth;
 	ip->i_entries = be32_to_cpu(str->di_entries);
 
+	if (!S_ISDIR(inode->i_mode) && (ip->i_diskflags & GFS2_DIF_EXHASH)) {
+		gfs2_consist_inode(ip);
+		return -EIO;
+	}
+
 	if (gfs2_is_stuffed(ip) && inode->i_size > gfs2_max_stuffed_size(ip)) {
 		gfs2_consist_inode(ip);
 		return -EIO;
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 8344040..e9bf487 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -892,7 +892,7 @@ retry:
 		goto fail_gunlock4;
 
 	mark_inode_dirty(inode);
-	d_instantiate(dentry, inode);
+	d_instantiate_new(dentry, inode);
 	/* After instantiate, errors should result in evict which will destroy
 	 * both inode and iopen glocks properly. */
 	if (file) {
@@ -904,7 +904,6 @@ retry:
 	gfs2_glock_dq_uninit(&gh);
 	gfs2_glock_put(io_gl);
 	gfs2_qa_put(dip);
-	unlock_new_inode(inode);
 	return error;
 
 fail_gunlock4:
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index 347df29..78bba8c 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -72,7 +72,7 @@ unsigned int gfs2_struct2blk(struct gfs2_sbd *sdp, unsigned int nstruct)
  *
  */
 
-void gfs2_remove_from_ail(struct gfs2_bufdata *bd)
+static void gfs2_remove_from_ail(struct gfs2_bufdata *bd)
 {
 	bd->bd_tr = NULL;
 	list_del_init(&bd->bd_ail_st_list);
@@ -467,8 +467,9 @@ void gfs2_log_release(struct gfs2_sbd *sdp, unsigned int blks)
 {
 	atomic_add(blks, &sdp->sd_log_blks_free);
 	trace_gfs2_log_blocks(sdp, blks);
-	gfs2_assert_withdraw(sdp, atomic_read(&sdp->sd_log_blks_free) <=
-				  sdp->sd_jdesc->jd_blocks);
+	gfs2_assert_withdraw(sdp, !sdp->sd_jdesc ||
+			atomic_read(&sdp->sd_log_blks_free) <=
+			sdp->sd_jdesc->jd_blocks);
 	if (atomic_read(&sdp->sd_log_blks_needed))
 		wake_up(&sdp->sd_log_waitq);
 }
@@ -800,9 +801,9 @@ void gfs2_flush_revokes(struct gfs2_sbd *sdp)
 	/* number of revokes we still have room for */
 	unsigned int max_revokes = atomic_read(&sdp->sd_log_revokes_available);
 
-	gfs2_log_lock(sdp);
+	spin_lock(&sdp->sd_log_lock);
 	gfs2_ail1_empty(sdp, max_revokes);
-	gfs2_log_unlock(sdp);
+	spin_unlock(&sdp->sd_log_lock);
 }
 
 /**
@@ -983,49 +984,90 @@ static void empty_ail1_list(struct gfs2_sbd *sdp)
 	}
 }
 
+static void gfs2_trans_drain_list(struct gfs2_sbd *sdp, struct list_head *list)
+{
+	struct gfs2_bufdata *bd;
+
+	while (!list_empty(list)) {
+		bd = list_first_entry(list, struct gfs2_bufdata, bd_list);
+		struct buffer_head *bh = bd->bd_bh;
+
+		WARN_ON_ONCE(!buffer_pinned(bh));
+		clear_buffer_pinned(bh);
+		trace_gfs2_pin(bd, 0);
+		atomic_dec(&sdp->sd_log_pinned);
+		list_del_init(&bd->bd_list);
+		brelse(bh);
+	}
+}
+
 /**
- * trans_drain - drain the buf and databuf queue for a failed transaction
+ * gfs2_trans_drain - drain the buf and databuf queue for a failed transaction
+ * @sdp: the filesystem
  * @tr: the transaction to drain
  *
  * When this is called, we're taking an error exit for a log write that failed
  * but since we bypassed the after_commit functions, we need to remove the
  * items from the buf and databuf queue.
  */
-static void trans_drain(struct gfs2_trans *tr)
+static void gfs2_trans_drain(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
 {
-	struct gfs2_bufdata *bd;
-	struct list_head *head;
-
 	if (!tr)
 		return;
+	gfs2_trans_drain_list(sdp, &tr->tr_buf);
+	gfs2_trans_drain_list(sdp, &tr->tr_databuf);
+}
 
-	head = &tr->tr_buf;
-	while (!list_empty(head)) {
-		bd = list_first_entry(head, struct gfs2_bufdata, bd_list);
+void gfs2_remove_from_journal(struct buffer_head *bh, int meta)
+{
+	struct address_space *mapping = bh->b_folio->mapping;
+	struct gfs2_sbd *sdp = gfs2_mapping2sbd(mapping);
+	struct gfs2_bufdata *bd = bh->b_private;
+	struct gfs2_trans *tr = current->journal_info;
+	int was_pinned = 0;
+
+	if (test_clear_buffer_pinned(bh)) {
+		trace_gfs2_pin(bd, 0);
+		atomic_dec(&sdp->sd_log_pinned);
 		list_del_init(&bd->bd_list);
-		if (!list_empty(&bd->bd_ail_st_list))
-			gfs2_remove_from_ail(bd);
-		kmem_cache_free(gfs2_bufdata_cachep, bd);
+		if (tr) {
+			if (meta == REMOVE_META)
+				tr->tr_num_buf_rm++;
+			else
+				tr->tr_num_databuf_rm++;
+			set_bit(TR_TOUCHED, &tr->tr_flags);
+		}
+		was_pinned = 1;
+		brelse(bh);
 	}
-	head = &tr->tr_databuf;
-	while (!list_empty(head)) {
-		bd = list_first_entry(head, struct gfs2_bufdata, bd_list);
-		list_del_init(&bd->bd_list);
-		if (!list_empty(&bd->bd_ail_st_list))
+	if (bd) {
+		if (bd->bd_tr) {
+			if (tr)
+				gfs2_trans_add_revoke(sdp, bd);
+			else
+				 gfs2_remove_from_ail(bd);
+		} else if (was_pinned) {
+			bh->b_private = NULL;
+			kmem_cache_free(gfs2_bufdata_cachep, bd);
+		} else if (!list_empty(&bd->bd_ail_st_list) &&
+			   !list_empty(&bd->bd_ail_gl_list)) {
 			gfs2_remove_from_ail(bd);
-		kmem_cache_free(gfs2_bufdata_cachep, bd);
+		}
 	}
+	clear_buffer_dirty(bh);
+	clear_buffer_uptodate(bh);
 }
 
 /**
- * gfs2_log_flush - flush incore transaction(s)
+ * __gfs2_log_flush - flush incore transaction(s)
  * @sdp: The filesystem
  * @gl: The glock structure to flush.  If NULL, flush the whole incore log
  * @flags: The log header flags: GFS2_LOG_HEAD_FLUSH_* and debug flags
  *
  */
 
-void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, u32 flags)
+static void __gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl,
+			     u32 flags)
 {
 	struct gfs2_trans *tr = NULL;
 	unsigned int reserved_blocks = 0, used_blocks = 0;
@@ -1033,7 +1075,6 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, u32 flags)
 	unsigned int first_log_head;
 	unsigned int reserved_revokes = 0;
 
-	down_write(&sdp->sd_log_flush_lock);
 	trace_gfs2_log_flush(sdp, 1, flags);
 
 repeat:
@@ -1110,7 +1151,7 @@ repeat:
 		goto out_withdraw;
 	lops_after_commit(sdp, tr);
 
-	gfs2_log_lock(sdp);
+	spin_lock(&sdp->sd_log_lock);
 	sdp->sd_log_blks_reserved = 0;
 
 	spin_lock(&sdp->sd_ail_lock);
@@ -1119,7 +1160,7 @@ repeat:
 		tr = NULL;
 	}
 	spin_unlock(&sdp->sd_ail_lock);
-	gfs2_log_unlock(sdp);
+	spin_unlock(&sdp->sd_log_lock);
 
 	if (!(flags & GFS2_LOG_HEAD_FLUSH_NORMAL)) {
 		if (!sdp->sd_log_idle) {
@@ -1145,13 +1186,16 @@ out:
 		gfs2_assert_withdraw(sdp, used_blocks < reserved_blocks);
 		gfs2_log_release(sdp, reserved_blocks - used_blocks);
 	}
-	up_write(&sdp->sd_log_flush_lock);
 	gfs2_trans_free(sdp, tr);
 	trace_gfs2_log_flush(sdp, 0, flags);
 	return;
 
 out_withdraw:
-	trans_drain(tr);
+	if (sdp->sd_jdesc->jd_log_bio) {
+		bio_io_error(sdp->sd_jdesc->jd_log_bio);
+		sdp->sd_jdesc->jd_log_bio = NULL;
+	}
+	gfs2_trans_drain(sdp, tr);
 	/**
 	 * If the tr_list is empty, we're withdrawing during a log
 	 * flush that targets a transaction, but the transaction was
@@ -1166,6 +1210,13 @@ out_withdraw:
 	goto out_end;
 }
 
+void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, u32 flags)
+{
+	down_write(&sdp->sd_log_flush_lock);
+	__gfs2_log_flush(sdp, gl, flags);
+	up_write(&sdp->sd_log_flush_lock);
+}
+
 /**
  * gfs2_merge_trans - Merge a new transaction into a cached transaction
  * @sdp: the filesystem
@@ -1200,7 +1251,7 @@ static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
 	unsigned int unused;
 	unsigned int maxres;
 
-	gfs2_log_lock(sdp);
+	spin_lock(&sdp->sd_log_lock);
 
 	if (sdp->sd_log_tr) {
 		gfs2_merge_trans(sdp, tr);
@@ -1218,7 +1269,7 @@ static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
 		gfs2_log_release(sdp, unused);
 	sdp->sd_log_blks_reserved = reserved;
 
-	gfs2_log_unlock(sdp);
+	spin_unlock(&sdp->sd_log_lock);
 }
 
 static inline int gfs2_jrnl_flush_reqd(struct gfs2_sbd *sdp)
@@ -1297,19 +1348,25 @@ int gfs2_logd(void *data)
 			break;
 
 		if (gfs2_jrnl_flush_reqd(sdp) || t == 0) {
+			down_write(&sdp->sd_log_flush_lock);
 			gfs2_ail1_empty(sdp, 0);
-			gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL |
-						  GFS2_LFC_LOGD_JFLUSH_REQD);
+			__gfs2_log_flush(sdp, NULL,
+					 GFS2_LOG_HEAD_FLUSH_NORMAL |
+					 GFS2_LFC_LOGD_JFLUSH_REQD);
+			up_write(&sdp->sd_log_flush_lock);
 		}
 
 		if (test_bit(SDF_FORCE_AIL_FLUSH, &sdp->sd_flags) ||
 		    gfs2_ail_flush_reqd(sdp)) {
 			clear_bit(SDF_FORCE_AIL_FLUSH, &sdp->sd_flags);
+			down_write(&sdp->sd_log_flush_lock);
 			gfs2_ail1_start(sdp);
 			gfs2_ail1_wait(sdp);
 			gfs2_ail1_empty(sdp, 0);
-			gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL |
-						  GFS2_LFC_LOGD_AIL_FLUSH_REQD);
+			__gfs2_log_flush(sdp, NULL,
+					 GFS2_LOG_HEAD_FLUSH_NORMAL |
+					 GFS2_LFC_LOGD_AIL_FLUSH_REQD);
+			up_write(&sdp->sd_log_flush_lock);
 		}
 
 		t = gfs2_tune_get(sdp, gt_logd_secs) * HZ;
diff --git a/fs/gfs2/log.h b/fs/gfs2/log.h
index fc30ebd..10beda6 100644
--- a/fs/gfs2/log.h
+++ b/fs/gfs2/log.h
@@ -20,30 +20,6 @@
  */
 #define GFS2_LOG_FLUSH_MIN_BLOCKS 4
 
-/**
- * gfs2_log_lock - acquire the right to mess with the log manager
- * @sdp: the filesystem
- *
- */
-
-static inline void gfs2_log_lock(struct gfs2_sbd *sdp)
-__acquires(&sdp->sd_log_lock)
-{
-	spin_lock(&sdp->sd_log_lock);
-}
-
-/**
- * gfs2_log_unlock - release the right to mess with the log manager
- * @sdp: the filesystem
- *
- */
-
-static inline void gfs2_log_unlock(struct gfs2_sbd *sdp)
-__releases(&sdp->sd_log_lock)
-{
-	spin_unlock(&sdp->sd_log_lock);
-}
-
 static inline void gfs2_ordered_add_inode(struct gfs2_inode *ip)
 {
 	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
@@ -61,7 +37,6 @@ static inline void gfs2_ordered_add_inode(struct gfs2_inode *ip)
 
 void gfs2_ordered_del_inode(struct gfs2_inode *ip);
 unsigned int gfs2_struct2blk(struct gfs2_sbd *sdp, unsigned int nstruct);
-void gfs2_remove_from_ail(struct gfs2_bufdata *bd);
 bool gfs2_log_is_empty(struct gfs2_sbd *sdp);
 void gfs2_log_release_revokes(struct gfs2_sbd *sdp, unsigned int revokes);
 void gfs2_log_release(struct gfs2_sbd *sdp, unsigned int blks);
@@ -72,6 +47,7 @@ void gfs2_log_reserve(struct gfs2_sbd *sdp, struct gfs2_trans *tr,
 void gfs2_write_log_header(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd,
 			   u64 seq, u32 tail, u32 lblock, u32 flags,
 			   blk_opf_t op_flags);
+void gfs2_remove_from_journal(struct buffer_head *bh, int meta);
 void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl,
 		    u32 type);
 void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *trans);
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c
index e03928d..6dabe73 100644
--- a/fs/gfs2/lops.c
+++ b/fs/gfs2/lops.c
@@ -648,19 +648,19 @@ static void gfs2_before_commit(struct gfs2_sbd *sdp, unsigned int limit,
 	unsigned n;
 	__be64 *ptr;
 
-	gfs2_log_lock(sdp);
+	spin_lock(&sdp->sd_log_lock);
 	list_sort(NULL, blist, blocknr_cmp);
 	bd1 = bd2 = list_prepare_entry(bd1, blist, bd_list);
 	while(total) {
 		num = total;
 		if (total > limit)
 			num = limit;
-		gfs2_log_unlock(sdp);
+		spin_unlock(&sdp->sd_log_lock);
 		page = gfs2_get_log_desc(sdp,
 					 is_databuf ? GFS2_LOG_DESC_JDATA :
 					 GFS2_LOG_DESC_METADATA, num + 1, num);
 		ld = page_address(page);
-		gfs2_log_lock(sdp);
+		spin_lock(&sdp->sd_log_lock);
 		ptr = (__be64 *)(ld + 1);
 
 		n = 0;
@@ -674,14 +674,14 @@ static void gfs2_before_commit(struct gfs2_sbd *sdp, unsigned int limit,
 				break;
 		}
 
-		gfs2_log_unlock(sdp);
+		spin_unlock(&sdp->sd_log_lock);
 		gfs2_log_write_page(sdp, page);
-		gfs2_log_lock(sdp);
+		spin_lock(&sdp->sd_log_lock);
 
 		n = 0;
 		list_for_each_entry_continue(bd2, blist, bd_list) {
 			get_bh(bd2->bd_bh);
-			gfs2_log_unlock(sdp);
+			spin_unlock(&sdp->sd_log_lock);
 			lock_buffer(bd2->bd_bh);
 
 			if (buffer_escaped(bd2->bd_bh)) {
@@ -698,7 +698,7 @@ static void gfs2_before_commit(struct gfs2_sbd *sdp, unsigned int limit,
 			} else {
 				gfs2_log_write_bh(sdp, bd2->bd_bh);
 			}
-			gfs2_log_lock(sdp);
+			spin_lock(&sdp->sd_log_lock);
 			if (++n >= num)
 				break;
 		}
@@ -706,7 +706,7 @@ static void gfs2_before_commit(struct gfs2_sbd *sdp, unsigned int limit,
 		BUG_ON(total < num);
 		total -= num;
 	}
-	gfs2_log_unlock(sdp);
+	spin_unlock(&sdp->sd_log_lock);
 }
 
 static void buf_lo_before_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c
index 3c8e455..d407dd4 100644
--- a/fs/gfs2/meta_io.c
+++ b/fs/gfs2/meta_io.c
@@ -338,41 +338,6 @@ int gfs2_meta_wait(struct gfs2_sbd *sdp, struct buffer_head *bh)
 	return 0;
 }
 
-void gfs2_remove_from_journal(struct buffer_head *bh, int meta)
-{
-	struct address_space *mapping = bh->b_folio->mapping;
-	struct gfs2_sbd *sdp = gfs2_mapping2sbd(mapping);
-	struct gfs2_bufdata *bd = bh->b_private;
-	struct gfs2_trans *tr = current->journal_info;
-	int was_pinned = 0;
-
-	if (test_clear_buffer_pinned(bh)) {
-		trace_gfs2_pin(bd, 0);
-		atomic_dec(&sdp->sd_log_pinned);
-		list_del_init(&bd->bd_list);
-		if (meta == REMOVE_META)
-			tr->tr_num_buf_rm++;
-		else
-			tr->tr_num_databuf_rm++;
-		set_bit(TR_TOUCHED, &tr->tr_flags);
-		was_pinned = 1;
-		brelse(bh);
-	}
-	if (bd) {
-		if (bd->bd_tr) {
-			gfs2_trans_add_revoke(sdp, bd);
-		} else if (was_pinned) {
-			bh->b_private = NULL;
-			kmem_cache_free(gfs2_bufdata_cachep, bd);
-		} else if (!list_empty(&bd->bd_ail_st_list) &&
-					!list_empty(&bd->bd_ail_gl_list)) {
-			gfs2_remove_from_ail(bd);
-		}
-	}
-	clear_buffer_dirty(bh);
-	clear_buffer_uptodate(bh);
-}
-
 /**
  * gfs2_ail1_wipe - remove deleted/freed buffers from the ail1 list
  * @sdp: superblock
@@ -391,7 +356,7 @@ static void gfs2_ail1_wipe(struct gfs2_sbd *sdp, u64 bstart, u32 blen)
 	struct buffer_head *bh;
 	u64 end = bstart + blen;
 
-	gfs2_log_lock(sdp);
+	spin_lock(&sdp->sd_log_lock);
 	spin_lock(&sdp->sd_ail_lock);
 	list_for_each_entry_safe(tr, s, &sdp->sd_ail1_list, tr_list) {
 		list_for_each_entry_safe(bd, bs, &tr->tr_ail1_list,
@@ -404,7 +369,7 @@ static void gfs2_ail1_wipe(struct gfs2_sbd *sdp, u64 bstart, u32 blen)
 		}
 	}
 	spin_unlock(&sdp->sd_ail_lock);
-	gfs2_log_unlock(sdp);
+	spin_unlock(&sdp->sd_log_lock);
 }
 
 static struct buffer_head *gfs2_getjdatabuf(struct gfs2_inode *ip, u64 blkno)
@@ -456,11 +421,11 @@ void gfs2_journal_wipe(struct gfs2_inode *ip, u64 bstart, u32 blen)
 		}
 		if (bh) {
 			lock_buffer(bh);
-			gfs2_log_lock(sdp);
+			spin_lock(&sdp->sd_log_lock);
 			spin_lock(&sdp->sd_ail_lock);
 			gfs2_remove_from_journal(bh, ty);
 			spin_unlock(&sdp->sd_ail_lock);
-			gfs2_log_unlock(sdp);
+			spin_unlock(&sdp->sd_log_lock);
 			unlock_buffer(bh);
 			brelse(bh);
 		}
diff --git a/fs/gfs2/meta_io.h b/fs/gfs2/meta_io.h
index 2fe5dec..ec76215 100644
--- a/fs/gfs2/meta_io.h
+++ b/fs/gfs2/meta_io.h
@@ -59,7 +59,6 @@ enum {
 	REMOVE_META = 1,
 };
 
-void gfs2_remove_from_journal(struct buffer_head *bh, int meta);
 void gfs2_journal_wipe(struct gfs2_inode *ip, u64 bstart, u32 blen);
 int gfs2_meta_buffer(struct gfs2_inode *ip, u32 mtype, u64 num,
 		     struct buffer_head **bhp);
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 441774c..5988a16 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -2529,7 +2529,7 @@ void __gfs2_free_blocks(struct gfs2_inode *ip, struct gfs2_rgrpd *rgd,
 	rgrp_unlock_local(rgd);
 
 	/* Directories keep their data in the metadata address space */
-	if (meta || ip->i_depth || gfs2_is_jdata(ip))
+	if (meta || (ip->i_diskflags & GFS2_DIF_EXHASH) || gfs2_is_jdata(ip))
 		gfs2_journal_wipe(ip, bstart, blen);
 }
 
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
index f5fab69..a2ea121 100644
--- a/fs/gfs2/super.c
+++ b/fs/gfs2/super.c
@@ -596,6 +596,9 @@ restart:
 	}
 	spin_unlock(&sdp->sd_jindex_spin);
 
+	/* Wait for withdraw to complete */
+	flush_work(&sdp->sd_withdraw_work);
+
 	if (!sb_rdonly(sb))
 		gfs2_make_fs_ro(sdp);
 	else {
@@ -605,8 +608,6 @@ restart:
 		gfs2_quota_cleanup(sdp);
 	}
 
-	flush_work(&sdp->sd_withdraw_work);
-
 	/*  At this point, we're through modifying the disk  */
 
 	/*  Release stuff  */
@@ -1241,6 +1242,9 @@ static enum evict_behavior evict_should_delete(struct inode *inode,
 	struct gfs2_sbd *sdp = sb->s_fs_info;
 	int ret;
 
+	if (inode->i_nlink)
+		return EVICT_SHOULD_SKIP_DELETE;
+
 	if (gfs2_holder_initialized(&ip->i_iopen_gh) &&
 	    test_bit(GLF_DEFER_DELETE, &ip->i_iopen_gh.gh_gl->gl_flags))
 		return EVICT_SHOULD_DEFER_DELETE;
@@ -1279,12 +1283,18 @@ static enum evict_behavior evict_should_delete(struct inode *inode,
 /**
  * evict_unlinked_inode - delete the pieces of an unlinked evicted inode
  * @inode: The inode to evict
+ * @gh: The glock holder structure
  */
-static int evict_unlinked_inode(struct inode *inode)
+static int evict_unlinked_inode(struct inode *inode, struct gfs2_holder *gh)
 {
 	struct gfs2_inode *ip = GFS2_I(inode);
+	struct gfs2_glock *gl = ip->i_gl;
 	int ret;
 
+	/* The inode glock must be held exclusively and be instantiated. */
+	BUG_ON(!gfs2_holder_initialized(gh) ||
+	       test_bit(GLF_INSTANTIATE_NEEDED, &gl->gl_flags));
+
 	if (S_ISDIR(inode->i_mode) &&
 	    (ip->i_diskflags & GFS2_DIF_EXHASH)) {
 		ret = gfs2_dir_exhash_dealloc(ip);
@@ -1317,44 +1327,97 @@ static int evict_unlinked_inode(struct inode *inode)
 	 */
 
 	ret = gfs2_dinode_dealloc(ip);
-	if (!ret && ip->i_gl)
-		gfs2_inode_remember_delete(ip->i_gl, ip->i_no_formal_ino);
+	if (!ret)
+		gfs2_inode_remember_delete(gl, ip->i_no_formal_ino);
 
 out:
 	return ret;
 }
 
+static int gfs2_truncate_inode_pages(struct inode *inode)
+{
+	struct gfs2_inode *ip = GFS2_I(inode);
+	struct gfs2_sbd *sdp = GFS2_SB(inode);
+	struct address_space *mapping = &inode->i_data;
+	bool need_trans = gfs2_is_jdata(ip) && mapping->nrpages;
+	int ret = 0;
+
+	/*
+	 * Truncating a jdata inode address space may create revokes in
+	 * truncate_inode_pages() -> gfs2_invalidate_folio() -> ... ->
+	 * gfs2_remove_from_journal(), so we need a transaction here.
+	 *
+	 * During a withdraw, no new transactions can be created.  We still
+	 * take the log flush lock to prevent truncate from racing with
+	 * gfs2_log_flush().
+	 */
+	if (need_trans) {
+		ret = gfs2_trans_begin(sdp, 0, sdp->sd_jdesc->jd_blocks);
+		if (ret)
+			down_read(&sdp->sd_log_flush_lock);
+	}
+	truncate_inode_pages(mapping, 0);
+	if (need_trans) {
+		if (ret)
+			up_read(&sdp->sd_log_flush_lock);
+		else
+			gfs2_trans_end(sdp);
+	}
+	return ret;
+}
+
+static void gfs2_truncate_inode_pages_final(struct inode *inode)
+{
+	struct gfs2_inode *ip = GFS2_I(inode);
+	struct gfs2_sbd *sdp = GFS2_SB(inode);
+	struct address_space *mapping = &inode->i_data;
+	bool need_lock = gfs2_is_jdata(ip) && mapping->nrpages;
+
+	if (need_lock)
+		down_read(&sdp->sd_log_flush_lock);
+	truncate_inode_pages_final(mapping);
+	if (need_lock)
+		up_read(&sdp->sd_log_flush_lock);
+}
+
 /*
  * evict_linked_inode - evict an inode whose dinode has not been unlinked
  * @inode: The inode to evict
+ * @gh: The glock holder structure
  */
-static int evict_linked_inode(struct inode *inode)
+static int evict_linked_inode(struct inode *inode, struct gfs2_holder *gh)
 {
 	struct super_block *sb = inode->i_sb;
 	struct gfs2_sbd *sdp = sb->s_fs_info;
 	struct gfs2_inode *ip = GFS2_I(inode);
-	struct address_space *metamapping;
+	struct gfs2_glock *gl = ip->i_gl;
+	struct address_space *metamapping = gfs2_glock2aspace(gl);
 	int ret;
 
-	gfs2_log_flush(sdp, ip->i_gl, GFS2_LOG_HEAD_FLUSH_NORMAL |
+	if (!(test_bit(GLF_DIRTY, &gl->gl_flags) || inode->i_flags & I_DIRTY))
+		goto clean;
+
+	/* The inode glock must be held exclusively and be instantiated. */
+	if (!gfs2_holder_initialized(gh))
+		ret = gfs2_glock_nq_init(gl, LM_ST_EXCLUSIVE, 0, gh);
+	else
+		ret = gfs2_instantiate(gh);
+	if (ret)
+		return ret;
+
+	gfs2_log_flush(sdp, gl, GFS2_LOG_HEAD_FLUSH_NORMAL |
 		       GFS2_LFC_EVICT_INODE);
-	metamapping = gfs2_glock2aspace(ip->i_gl);
-	if (test_bit(GLF_DIRTY, &ip->i_gl->gl_flags)) {
+	if (test_bit(GLF_DIRTY, &gl->gl_flags)) {
 		filemap_fdatawrite(metamapping);
 		filemap_fdatawait(metamapping);
 	}
 	write_inode_now(inode, 1);
-	gfs2_ail_flush(ip->i_gl, 0);
-
-	ret = gfs2_trans_begin(sdp, 0, sdp->sd_jdesc->jd_blocks);
-	if (ret)
-		return ret;
+	gfs2_ail_flush(gl, 0);
 
-	/* Needs to be done before glock release & also in a transaction */
-	truncate_inode_pages(&inode->i_data, 0);
+clean:
+	ret = gfs2_truncate_inode_pages(inode);
 	truncate_inode_pages(metamapping, 0);
-	gfs2_trans_end(sdp);
-	return 0;
+	return ret;
 }
 
 /**
@@ -1388,7 +1451,7 @@ static void gfs2_evict_inode(struct inode *inode)
 	int ret;
 
 	gfs2_holder_mark_uninitialized(&gh);
-	if (inode->i_nlink || sb_rdonly(sb) || !ip->i_no_addr)
+	if (sb_rdonly(sb) || !ip->i_no_addr || !ip->i_gl)
 		goto out;
 
 	/*
@@ -1413,19 +1476,19 @@ static void gfs2_evict_inode(struct inode *inode)
 		behavior = EVICT_SHOULD_SKIP_DELETE;
 	}
 	if (behavior == EVICT_SHOULD_DELETE)
-		ret = evict_unlinked_inode(inode);
+		ret = evict_unlinked_inode(inode, &gh);
 	else
-		ret = evict_linked_inode(inode);
+		ret = evict_linked_inode(inode, &gh);
 
 	if (gfs2_rs_active(&ip->i_res))
 		gfs2_rs_deltree(&ip->i_res);
 
-	if (ret && ret != GLR_TRYFAILED && ret != -EROFS)
+	if (ret && !gfs2_withdrawn(sdp) && ret != -EROFS)
 		fs_warn(sdp, "gfs2_evict_inode: %d\n", ret);
 out:
 	if (gfs2_holder_initialized(&gh))
 		gfs2_glock_dq_uninit(&gh);
-	truncate_inode_pages_final(&inode->i_data);
+	gfs2_truncate_inode_pages_final(inode);
 	if (ip->i_qadata)
 		gfs2_assert_warn(sdp, ip->i_qadata->qa_ref == 0);
 	gfs2_rs_deltree(&ip->i_res);
diff --git a/fs/gfs2/trans.c b/fs/gfs2/trans.c
index 95f2632..65cbe06 100644
--- a/fs/gfs2/trans.c
+++ b/fs/gfs2/trans.c
@@ -176,7 +176,6 @@ static struct gfs2_bufdata *gfs2_alloc_bufdata(struct gfs2_glock *gl,
 	INIT_LIST_HEAD(&bd->bd_list);
 	INIT_LIST_HEAD(&bd->bd_ail_st_list);
 	INIT_LIST_HEAD(&bd->bd_ail_gl_list);
-	bh->b_private = bd;
 	return bd;
 }
 
@@ -205,17 +204,20 @@ void gfs2_trans_add_data(struct gfs2_glock *gl, struct buffer_head *bh)
 		set_bit(TR_TOUCHED, &tr->tr_flags);
 		goto out;
 	}
-	gfs2_log_lock(sdp);
+	spin_lock(&sdp->sd_log_lock);
 	bd = bh->b_private;
 	if (bd == NULL) {
-		gfs2_log_unlock(sdp);
+		spin_unlock(&sdp->sd_log_lock);
 		unlock_buffer(bh);
-		if (bh->b_private == NULL)
-			bd = gfs2_alloc_bufdata(gl, bh);
-		else
-			bd = bh->b_private;
+		bd = gfs2_alloc_bufdata(gl, bh);
 		lock_buffer(bh);
-		gfs2_log_lock(sdp);
+		spin_lock(&sdp->sd_log_lock);
+		if (bh->b_private) {
+			kmem_cache_free(gfs2_bufdata_cachep, bd);
+			bd = bh->b_private;
+		} else {
+			bh->b_private = bd;
+		}
 	}
 	gfs2_assert(sdp, bd->bd_gl == gl);
 	set_bit(TR_TOUCHED, &tr->tr_flags);
@@ -226,7 +228,7 @@ void gfs2_trans_add_data(struct gfs2_glock *gl, struct buffer_head *bh)
 		tr->tr_num_databuf_new++;
 		list_add_tail(&bd->bd_list, &tr->tr_databuf);
 	}
-	gfs2_log_unlock(sdp);
+	spin_unlock(&sdp->sd_log_lock);
 out:
 	unlock_buffer(bh);
 }
@@ -266,19 +268,20 @@ void gfs2_trans_add_meta(struct gfs2_glock *gl, struct buffer_head *bh)
 		set_bit(TR_TOUCHED, &tr->tr_flags);
 		goto out;
 	}
-	gfs2_log_lock(sdp);
+	spin_lock(&sdp->sd_log_lock);
 	bd = bh->b_private;
 	if (bd == NULL) {
-		gfs2_log_unlock(sdp);
+		spin_unlock(&sdp->sd_log_lock);
 		unlock_buffer(bh);
-		folio_lock(bh->b_folio);
-		if (bh->b_private == NULL)
-			bd = gfs2_alloc_bufdata(gl, bh);
-		else
-			bd = bh->b_private;
-		folio_unlock(bh->b_folio);
+		bd = gfs2_alloc_bufdata(gl, bh);
 		lock_buffer(bh);
-		gfs2_log_lock(sdp);
+		spin_lock(&sdp->sd_log_lock);
+		if (bh->b_private) {
+			kmem_cache_free(gfs2_bufdata_cachep, bd);
+			bd = bh->b_private;
+		} else {
+			bh->b_private = bd;
+		}
 	}
 	gfs2_assert(sdp, bd->bd_gl == gl);
 	set_bit(TR_TOUCHED, &tr->tr_flags);
@@ -309,7 +312,7 @@ void gfs2_trans_add_meta(struct gfs2_glock *gl, struct buffer_head *bh)
 	list_add(&bd->bd_list, &tr->tr_buf);
 	tr->tr_num_buf_new++;
 out_unlock:
-	gfs2_log_unlock(sdp);
+	spin_unlock(&sdp->sd_log_lock);
 out:
 	unlock_buffer(bh);
 }
@@ -329,7 +332,7 @@ void gfs2_trans_remove_revoke(struct gfs2_sbd *sdp, u64 blkno, unsigned int len)
 	struct gfs2_bufdata *bd, *tmp;
 	unsigned int n = len;
 
-	gfs2_log_lock(sdp);
+	spin_lock(&sdp->sd_log_lock);
 	list_for_each_entry_safe(bd, tmp, &sdp->sd_log_revokes, bd_list) {
 		if ((bd->bd_blkno >= blkno) && (bd->bd_blkno < (blkno + len))) {
 			list_del_init(&bd->bd_list);
@@ -343,7 +346,7 @@ void gfs2_trans_remove_revoke(struct gfs2_sbd *sdp, u64 blkno, unsigned int len)
 				break;
 		}
 	}
-	gfs2_log_unlock(sdp);
+	spin_unlock(&sdp->sd_log_lock);
 }
 
 void gfs2_trans_free(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
diff --git a/fs/gfs2/util.c b/fs/gfs2/util.c
index 0260320..83b8bb6 100644
--- a/fs/gfs2/util.c
+++ b/fs/gfs2/util.c
@@ -123,9 +123,8 @@ static void do_withdraw(struct gfs2_sbd *sdp)
 		return;
 	}
 	clear_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags);
-	up_write(&sdp->sd_log_flush_lock);
-
 	gfs2_ail_drain(sdp); /* frees all transactions */
+	up_write(&sdp->sd_log_flush_lock);
 
 	wake_up(&sdp->sd_logd_waitq);
 	wake_up(&sdp->sd_quota_wait);
