Commit 721068de authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'gfs2-v6.10-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2

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
...@@ -138,35 +138,6 @@ static int __gfs2_jdata_write_folio(struct folio *folio, ...@@ -138,35 +138,6 @@ static int __gfs2_jdata_write_folio(struct folio *folio,
return gfs2_write_jdata_folio(folio, wbc); 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 * gfs2_writepages - Write a bunch of dirty pages back to disk
* @mapping: The mapping to write * @mapping: The mapping to write
...@@ -748,7 +719,6 @@ static const struct address_space_operations gfs2_aops = { ...@@ -748,7 +719,6 @@ static const struct address_space_operations gfs2_aops = {
}; };
static const struct address_space_operations gfs2_jdata_aops = { static const struct address_space_operations gfs2_jdata_aops = {
.writepage = gfs2_jdata_writepage,
.writepages = gfs2_jdata_writepages, .writepages = gfs2_jdata_writepages,
.read_folio = gfs2_read_folio, .read_folio = gfs2_read_folio,
.readahead = gfs2_readahead, .readahead = gfs2_readahead,
......
...@@ -1885,14 +1885,16 @@ void gfs2_glock_dq_m(unsigned int num_gh, struct gfs2_holder *ghs) ...@@ -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) void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state)
{ {
unsigned long delay = 0; unsigned long delay = 0;
unsigned long holdtime;
unsigned long now = jiffies;
gfs2_glock_hold(gl); gfs2_glock_hold(gl);
spin_lock(&gl->gl_lockref.lock); spin_lock(&gl->gl_lockref.lock);
holdtime = gl->gl_tchange + gl->gl_hold_time;
if (!list_empty(&gl->gl_holders) && if (!list_empty(&gl->gl_holders) &&
gl->gl_name.ln_type == LM_TYPE_INODE) { 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)) if (time_before(now, holdtime))
delay = holdtime - now; delay = holdtime - now;
if (test_bit(GLF_HAVE_REPLY, &gl->gl_flags)) if (test_bit(GLF_HAVE_REPLY, &gl->gl_flags))
...@@ -2249,6 +2251,7 @@ void gfs2_gl_hash_clear(struct gfs2_sbd *sdp) ...@@ -2249,6 +2251,7 @@ void gfs2_gl_hash_clear(struct gfs2_sbd *sdp)
gfs2_free_dead_glocks(sdp); gfs2_free_dead_glocks(sdp);
glock_hash_walk(dump_glock_func, sdp); glock_hash_walk(dump_glock_func, sdp);
destroy_workqueue(sdp->sd_glock_wq); destroy_workqueue(sdp->sd_glock_wq);
sdp->sd_glock_wq = NULL;
} }
static const char *state2str(unsigned state) static const char *state2str(unsigned state)
......
...@@ -80,15 +80,6 @@ void gfs2_remove_from_ail(struct gfs2_bufdata *bd) ...@@ -80,15 +80,6 @@ void gfs2_remove_from_ail(struct gfs2_bufdata *bd)
brelse(bd->bd_bh); 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 * gfs2_ail1_start_one - Start I/O on a transaction
* @sdp: The superblock * @sdp: The superblock
...@@ -140,7 +131,7 @@ __acquires(&sdp->sd_ail_lock) ...@@ -140,7 +131,7 @@ __acquires(&sdp->sd_ail_lock)
if (!mapping) if (!mapping)
continue; continue;
spin_unlock(&sdp->sd_ail_lock); 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()) { if (need_resched()) {
blk_finish_plug(plug); blk_finish_plug(plug);
cond_resched(); cond_resched();
...@@ -149,6 +140,7 @@ __acquires(&sdp->sd_ail_lock) ...@@ -149,6 +140,7 @@ __acquires(&sdp->sd_ail_lock)
spin_lock(&sdp->sd_ail_lock); spin_lock(&sdp->sd_ail_lock);
if (ret == -ENODATA) /* if a jdata write into a new hole */ if (ret == -ENODATA) /* if a jdata write into a new hole */
ret = 0; /* ignore it */ ret = 0; /* ignore it */
mapping_set_error(mapping, ret);
if (ret || wbc->nr_to_write <= 0) if (ret || wbc->nr_to_write <= 0)
break; break;
return -EBUSY; return -EBUSY;
......
...@@ -30,9 +30,9 @@ ...@@ -30,9 +30,9 @@
#include "util.h" #include "util.h"
#include "trace_gfs2.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; struct buffer_head *bh, *head;
int nr_underway = 0; int nr_underway = 0;
blk_opf_t write_flags = REQ_META | REQ_PRIO | wbc_to_write_flags(wbc); 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 ...@@ -66,8 +66,8 @@ static int gfs2_aspace_writepage(struct page *page, struct writeback_control *wb
} while ((bh = bh->b_this_page) != head); } while ((bh = bh->b_this_page) != head);
/* /*
* The page and its buffers are protected by PageWriteback(), so we can * The folio and its buffers are protected from truncation by
* drop the bh refcounts early. * the writeback flag, so we can drop the bh refcounts early.
*/ */
BUG_ON(folio_test_writeback(folio)); BUG_ON(folio_test_writeback(folio));
folio_start_writeback(folio); folio_start_writeback(folio);
...@@ -84,21 +84,31 @@ static int gfs2_aspace_writepage(struct page *page, struct writeback_control *wb ...@@ -84,21 +84,31 @@ static int gfs2_aspace_writepage(struct page *page, struct writeback_control *wb
if (nr_underway == 0) if (nr_underway == 0)
folio_end_writeback(folio); 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 = { const struct address_space_operations gfs2_meta_aops = {
.dirty_folio = block_dirty_folio, .dirty_folio = block_dirty_folio,
.invalidate_folio = block_invalidate_folio, .invalidate_folio = block_invalidate_folio,
.writepage = gfs2_aspace_writepage, .writepages = gfs2_aspace_writepages,
.release_folio = gfs2_release_folio, .release_folio = gfs2_release_folio,
}; };
const struct address_space_operations gfs2_rgrp_aops = { const struct address_space_operations gfs2_rgrp_aops = {
.dirty_folio = block_dirty_folio, .dirty_folio = block_dirty_folio,
.invalidate_folio = block_invalidate_folio, .invalidate_folio = block_invalidate_folio,
.writepage = gfs2_aspace_writepage, .writepages = gfs2_aspace_writepages,
.release_folio = gfs2_release_folio, .release_folio = gfs2_release_folio,
}; };
......
...@@ -1307,6 +1307,7 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc) ...@@ -1307,6 +1307,7 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc)
fail_delete_wq: fail_delete_wq:
destroy_workqueue(sdp->sd_delete_wq); destroy_workqueue(sdp->sd_delete_wq);
fail_glock_wq: fail_glock_wq:
if (sdp->sd_glock_wq)
destroy_workqueue(sdp->sd_glock_wq); destroy_workqueue(sdp->sd_glock_wq);
fail_free: fail_free:
free_sbd(sdp); free_sbd(sdp);
......
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