Commit 721068de authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull gfs2 update from Andreas Gruenbacher:

 - Convert the writepage address space operation to writepages (Matthew
   Wilcox)

 - A syzkaller fix (by Julian Sun) and a minor cleanup (Andreas
   Gruenbacher)

* tag 'gfs2-v6.10-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2:
  gfs2: Remove gfs2_aspace_writepage()
  gfs2: Remove gfs2_jdata_writepage()
  gfs2: Remove __gfs2_writepage()
  gfs2: Add gfs2_aspace_writepages()
  gfs2: fix double destroy_workqueue error
  gfs2: Minor gfs2_glock_cb cleanup
parents a1fb2fcb 6888c1e8
Loading
Loading
Loading
Loading
+0 −30
Original line number Diff line number Diff line
@@ -138,35 +138,6 @@ static int __gfs2_jdata_write_folio(struct folio *folio,
	return gfs2_write_jdata_folio(folio, wbc);
}

/**
 * gfs2_jdata_writepage - Write complete page
 * @page: Page to write
 * @wbc: The writeback control
 *
 * Returns: errno
 *
 */

static int gfs2_jdata_writepage(struct page *page, struct writeback_control *wbc)
{
	struct folio *folio = page_folio(page);
	struct inode *inode = page->mapping->host;
	struct gfs2_inode *ip = GFS2_I(inode);
	struct gfs2_sbd *sdp = GFS2_SB(inode);

	if (gfs2_assert_withdraw(sdp, ip->i_gl->gl_state == LM_ST_EXCLUSIVE))
		goto out;
	if (folio_test_checked(folio) || current->journal_info)
		goto out_ignore;
	return __gfs2_jdata_write_folio(folio, wbc);

out_ignore:
	folio_redirty_for_writepage(wbc, folio);
out:
	folio_unlock(folio);
	return 0;
}

/**
 * gfs2_writepages - Write a bunch of dirty pages back to disk
 * @mapping: The mapping to write
@@ -748,7 +719,6 @@ static const struct address_space_operations gfs2_aops = {
};

static const struct address_space_operations gfs2_jdata_aops = {
	.writepage = gfs2_jdata_writepage,
	.writepages = gfs2_jdata_writepages,
	.read_folio = gfs2_read_folio,
	.readahead = gfs2_readahead,
+6 −3
Original line number Diff line number Diff line
@@ -1885,14 +1885,16 @@ void gfs2_glock_dq_m(unsigned int num_gh, struct gfs2_holder *ghs)
void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state)
{
	unsigned long delay = 0;
	unsigned long holdtime;
	unsigned long now = jiffies;

	gfs2_glock_hold(gl);
	spin_lock(&gl->gl_lockref.lock);
	holdtime = gl->gl_tchange + gl->gl_hold_time;
	if (!list_empty(&gl->gl_holders) &&
	    gl->gl_name.ln_type == LM_TYPE_INODE) {
		unsigned long now = jiffies;
		unsigned long holdtime;

		holdtime = gl->gl_tchange + gl->gl_hold_time;

		if (time_before(now, holdtime))
			delay = holdtime - now;
		if (test_bit(GLF_HAVE_REPLY, &gl->gl_flags))
@@ -2249,6 +2251,7 @@ void gfs2_gl_hash_clear(struct gfs2_sbd *sdp)
	gfs2_free_dead_glocks(sdp);
	glock_hash_walk(dump_glock_func, sdp);
	destroy_workqueue(sdp->sd_glock_wq);
	sdp->sd_glock_wq = NULL;
}

static const char *state2str(unsigned state)
+2 −10
Original line number Diff line number Diff line
@@ -80,15 +80,6 @@ void gfs2_remove_from_ail(struct gfs2_bufdata *bd)
	brelse(bd->bd_bh);
}

static int __gfs2_writepage(struct folio *folio, struct writeback_control *wbc,
		       void *data)
{
	struct address_space *mapping = data;
	int ret = mapping->a_ops->writepage(&folio->page, wbc);
	mapping_set_error(mapping, ret);
	return ret;
}

/**
 * gfs2_ail1_start_one - Start I/O on a transaction
 * @sdp: The superblock
@@ -140,7 +131,7 @@ __acquires(&sdp->sd_ail_lock)
		if (!mapping)
			continue;
		spin_unlock(&sdp->sd_ail_lock);
		ret = write_cache_pages(mapping, wbc, __gfs2_writepage, mapping);
		ret = mapping->a_ops->writepages(mapping, wbc);
		if (need_resched()) {
			blk_finish_plug(plug);
			cond_resched();
@@ -149,6 +140,7 @@ __acquires(&sdp->sd_ail_lock)
		spin_lock(&sdp->sd_ail_lock);
		if (ret == -ENODATA) /* if a jdata write into a new hole */
			ret = 0; /* ignore it */
		mapping_set_error(mapping, ret);
		if (ret || wbc->nr_to_write <= 0)
			break;
		return -EBUSY;
+17 −7
Original line number Diff line number Diff line
@@ -30,9 +30,9 @@
#include "util.h"
#include "trace_gfs2.h"

static int gfs2_aspace_writepage(struct page *page, struct writeback_control *wbc)
static void gfs2_aspace_write_folio(struct folio *folio,
		struct writeback_control *wbc)
{
	struct folio *folio = page_folio(page);
	struct buffer_head *bh, *head;
	int nr_underway = 0;
	blk_opf_t write_flags = REQ_META | REQ_PRIO | wbc_to_write_flags(wbc);
@@ -66,8 +66,8 @@ static int gfs2_aspace_writepage(struct page *page, struct writeback_control *wb
	} while ((bh = bh->b_this_page) != head);

	/*
	 * The page and its buffers are protected by PageWriteback(), so we can
	 * drop the bh refcounts early.
	 * The folio and its buffers are protected from truncation by
	 * the writeback flag, so we can drop the bh refcounts early.
	 */
	BUG_ON(folio_test_writeback(folio));
	folio_start_writeback(folio);
@@ -84,21 +84,31 @@ static int gfs2_aspace_writepage(struct page *page, struct writeback_control *wb

	if (nr_underway == 0)
		folio_end_writeback(folio);
}

	return 0;
static int gfs2_aspace_writepages(struct address_space *mapping,
		struct writeback_control *wbc)
{
	struct folio *folio = NULL;
	int error;

	while ((folio = writeback_iter(mapping, wbc, folio, &error)))
		gfs2_aspace_write_folio(folio, wbc);

	return error;
}

const struct address_space_operations gfs2_meta_aops = {
	.dirty_folio	= block_dirty_folio,
	.invalidate_folio = block_invalidate_folio,
	.writepage = gfs2_aspace_writepage,
	.writepages = gfs2_aspace_writepages,
	.release_folio = gfs2_release_folio,
};

const struct address_space_operations gfs2_rgrp_aops = {
	.dirty_folio	= block_dirty_folio,
	.invalidate_folio = block_invalidate_folio,
	.writepage = gfs2_aspace_writepage,
	.writepages = gfs2_aspace_writepages,
	.release_folio = gfs2_release_folio,
};

+2 −1
Original line number Diff line number Diff line
@@ -1307,6 +1307,7 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc)
fail_delete_wq:
	destroy_workqueue(sdp->sd_delete_wq);
fail_glock_wq:
	if (sdp->sd_glock_wq)
		destroy_workqueue(sdp->sd_glock_wq);
fail_free:
	free_sbd(sdp);