Commit bf2d6369 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'gfs2-v5.8-rc3.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2

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
...@@ -1899,7 +1899,10 @@ bool gfs2_delete_work_queued(const struct gfs2_glock *gl) ...@@ -1899,7 +1899,10 @@ bool gfs2_delete_work_queued(const struct gfs2_glock *gl)
static void flush_delete_work(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); gfs2_glock_queue_work(gl, 0);
} }
......
...@@ -531,8 +531,7 @@ static int freeze_go_sync(struct gfs2_glock *gl) ...@@ -531,8 +531,7 @@ static int freeze_go_sync(struct gfs2_glock *gl)
int error = 0; int error = 0;
struct gfs2_sbd *sdp = gl->gl_name.ln_sbd; struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
if (gl->gl_state == LM_ST_SHARED && !gfs2_withdrawn(sdp) && if (gl->gl_req == LM_ST_EXCLUSIVE && !gfs2_withdrawn(sdp)) {
test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) {
atomic_set(&sdp->sd_freeze_state, SFS_STARTING_FREEZE); atomic_set(&sdp->sd_freeze_state, SFS_STARTING_FREEZE);
error = freeze_super(sdp->sd_vfs); error = freeze_super(sdp->sd_vfs);
if (error) { if (error) {
...@@ -545,8 +544,11 @@ static int freeze_go_sync(struct gfs2_glock *gl) ...@@ -545,8 +544,11 @@ static int freeze_go_sync(struct gfs2_glock *gl)
gfs2_assert_withdraw(sdp, 0); gfs2_assert_withdraw(sdp, 0);
} }
queue_work(gfs2_freeze_wq, &sdp->sd_freeze_work); queue_work(gfs2_freeze_wq, &sdp->sd_freeze_work);
gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_FREEZE | if (test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags))
GFS2_LFC_FREEZE_GO_SYNC); 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; return 0;
} }
......
...@@ -399,7 +399,6 @@ enum { ...@@ -399,7 +399,6 @@ enum {
GIF_QD_LOCKED = 1, GIF_QD_LOCKED = 1,
GIF_ALLOC_FAILED = 2, GIF_ALLOC_FAILED = 2,
GIF_SW_PAGED = 3, GIF_SW_PAGED = 3,
GIF_ORDERED = 4,
GIF_FREE_VFS_INODE = 5, GIF_FREE_VFS_INODE = 5,
GIF_GLOP_PENDING = 6, GIF_GLOP_PENDING = 6,
GIF_DEFERRED_DELETE = 7, GIF_DEFERRED_DELETE = 7,
......
...@@ -207,10 +207,11 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type, ...@@ -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 && if (no_formal_ino && ip->i_no_formal_ino &&
no_formal_ino != ip->i_no_formal_ino) { no_formal_ino != ip->i_no_formal_ino) {
error = -ESTALE;
if (inode->i_state & I_NEW) if (inode->i_state & I_NEW)
goto fail; goto fail;
iput(inode); iput(inode);
return ERR_PTR(-ESTALE); return ERR_PTR(error);
} }
if (inode->i_state & I_NEW) if (inode->i_state & I_NEW)
......
...@@ -613,6 +613,12 @@ static int ip_cmp(void *priv, struct list_head *a, struct list_head *b) ...@@ -613,6 +613,12 @@ static int ip_cmp(void *priv, struct list_head *a, struct list_head *b)
return 0; 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) static void gfs2_ordered_write(struct gfs2_sbd *sdp)
{ {
struct gfs2_inode *ip; struct gfs2_inode *ip;
...@@ -623,8 +629,7 @@ static void gfs2_ordered_write(struct gfs2_sbd *sdp) ...@@ -623,8 +629,7 @@ static void gfs2_ordered_write(struct gfs2_sbd *sdp)
while (!list_empty(&sdp->sd_log_ordered)) { while (!list_empty(&sdp->sd_log_ordered)) {
ip = list_first_entry(&sdp->sd_log_ordered, struct gfs2_inode, i_ordered); ip = list_first_entry(&sdp->sd_log_ordered, struct gfs2_inode, i_ordered);
if (ip->i_inode.i_mapping->nrpages == 0) { if (ip->i_inode.i_mapping->nrpages == 0) {
test_and_clear_bit(GIF_ORDERED, &ip->i_flags); __ordered_del_inode(ip);
list_del(&ip->i_ordered);
continue; continue;
} }
list_move(&ip->i_ordered, &written); list_move(&ip->i_ordered, &written);
...@@ -643,8 +648,7 @@ static void gfs2_ordered_wait(struct gfs2_sbd *sdp) ...@@ -643,8 +648,7 @@ static void gfs2_ordered_wait(struct gfs2_sbd *sdp)
spin_lock(&sdp->sd_ordered_lock); spin_lock(&sdp->sd_ordered_lock);
while (!list_empty(&sdp->sd_log_ordered)) { while (!list_empty(&sdp->sd_log_ordered)) {
ip = list_first_entry(&sdp->sd_log_ordered, struct gfs2_inode, i_ordered); ip = list_first_entry(&sdp->sd_log_ordered, struct gfs2_inode, i_ordered);
list_del(&ip->i_ordered); __ordered_del_inode(ip);
WARN_ON(!test_and_clear_bit(GIF_ORDERED, &ip->i_flags));
if (ip->i_inode.i_mapping->nrpages == 0) if (ip->i_inode.i_mapping->nrpages == 0)
continue; continue;
spin_unlock(&sdp->sd_ordered_lock); spin_unlock(&sdp->sd_ordered_lock);
...@@ -659,8 +663,7 @@ void gfs2_ordered_del_inode(struct gfs2_inode *ip) ...@@ -659,8 +663,7 @@ void gfs2_ordered_del_inode(struct gfs2_inode *ip)
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
spin_lock(&sdp->sd_ordered_lock); spin_lock(&sdp->sd_ordered_lock);
if (test_and_clear_bit(GIF_ORDERED, &ip->i_flags)) __ordered_del_inode(ip);
list_del(&ip->i_ordered);
spin_unlock(&sdp->sd_ordered_lock); spin_unlock(&sdp->sd_ordered_lock);
} }
...@@ -1002,6 +1005,16 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, u32 flags) ...@@ -1002,6 +1005,16 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, u32 flags)
out: out:
if (gfs2_withdrawn(sdp)) { 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 */ ail_drain(sdp); /* frees all transactions */
tr = NULL; tr = NULL;
} }
......
...@@ -53,9 +53,9 @@ static inline void gfs2_ordered_add_inode(struct gfs2_inode *ip) ...@@ -53,9 +53,9 @@ static inline void gfs2_ordered_add_inode(struct gfs2_inode *ip)
if (gfs2_is_jdata(ip) || !gfs2_is_ordered(sdp)) if (gfs2_is_jdata(ip) || !gfs2_is_ordered(sdp))
return; return;
if (!test_bit(GIF_ORDERED, &ip->i_flags)) { if (list_empty(&ip->i_ordered)) {
spin_lock(&sdp->sd_ordered_lock); spin_lock(&sdp->sd_ordered_lock);
if (!test_and_set_bit(GIF_ORDERED, &ip->i_flags)) if (list_empty(&ip->i_ordered))
list_add(&ip->i_ordered, &sdp->sd_log_ordered); list_add(&ip->i_ordered, &sdp->sd_log_ordered);
spin_unlock(&sdp->sd_ordered_lock); spin_unlock(&sdp->sd_ordered_lock);
} }
......
...@@ -39,6 +39,7 @@ static void gfs2_init_inode_once(void *foo) ...@@ -39,6 +39,7 @@ static void gfs2_init_inode_once(void *foo)
atomic_set(&ip->i_sizehint, 0); atomic_set(&ip->i_sizehint, 0);
init_rwsem(&ip->i_rw_mutex); init_rwsem(&ip->i_rw_mutex);
INIT_LIST_HEAD(&ip->i_trunc_list); INIT_LIST_HEAD(&ip->i_trunc_list);
INIT_LIST_HEAD(&ip->i_ordered);
ip->i_qadata = NULL; ip->i_qadata = NULL;
gfs2_holder_mark_uninitialized(&ip->i_rgd_gh); gfs2_holder_mark_uninitialized(&ip->i_rgd_gh);
memset(&ip->i_res, 0, sizeof(ip->i_res)); memset(&ip->i_res, 0, sizeof(ip->i_res));
......
...@@ -1136,7 +1136,18 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc) ...@@ -1136,7 +1136,18 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc)
goto fail_per_node; goto fail_per_node;
} }
if (!sb_rdonly(sb)) { if (sb_rdonly(sb)) {
struct gfs2_holder freeze_gh;
error = gfs2_glock_nq_init(sdp->sd_freeze_gl, LM_ST_SHARED,
LM_FLAG_NOEXP | GL_EXACT,
&freeze_gh);
if (error) {
fs_err(sdp, "can't make FS RO: %d\n", error);
goto fail_per_node;
}
gfs2_glock_dq_uninit(&freeze_gh);
} else {
error = gfs2_make_fs_rw(sdp); error = gfs2_make_fs_rw(sdp);
if (error) { if (error) {
fs_err(sdp, "can't make FS RW: %d\n", error); fs_err(sdp, "can't make FS RW: %d\n", error);
......
...@@ -364,8 +364,8 @@ void gfs2_recover_func(struct work_struct *work) ...@@ -364,8 +364,8 @@ void gfs2_recover_func(struct work_struct *work)
/* Acquire a shared hold on the freeze lock */ /* Acquire a shared hold on the freeze lock */
error = gfs2_glock_nq_init(sdp->sd_freeze_gl, LM_ST_SHARED, error = gfs2_glock_nq_init(sdp->sd_freeze_gl, LM_ST_SHARED,
LM_FLAG_NOEXP | LM_FLAG_PRIORITY, LM_FLAG_NOEXP | LM_FLAG_PRIORITY |
&thaw_gh); GL_EXACT, &thaw_gh);
if (error) if (error)
goto fail_gunlock_ji; goto fail_gunlock_ji;
......
...@@ -167,7 +167,8 @@ int gfs2_make_fs_rw(struct gfs2_sbd *sdp) ...@@ -167,7 +167,8 @@ int gfs2_make_fs_rw(struct gfs2_sbd *sdp)
if (error) if (error)
return error; return error;
error = gfs2_glock_nq_init(sdp->sd_freeze_gl, LM_ST_SHARED, 0, error = gfs2_glock_nq_init(sdp->sd_freeze_gl, LM_ST_SHARED,
LM_FLAG_NOEXP | GL_EXACT,
&freeze_gh); &freeze_gh);
if (error) if (error)
goto fail_threads; goto fail_threads;
...@@ -203,7 +204,6 @@ int gfs2_make_fs_rw(struct gfs2_sbd *sdp) ...@@ -203,7 +204,6 @@ int gfs2_make_fs_rw(struct gfs2_sbd *sdp)
return 0; return 0;
fail: fail:
freeze_gh.gh_flags |= GL_NOCACHE;
gfs2_glock_dq_uninit(&freeze_gh); gfs2_glock_dq_uninit(&freeze_gh);
fail_threads: fail_threads:
if (sdp->sd_quotad_process) if (sdp->sd_quotad_process)
...@@ -430,7 +430,7 @@ static int gfs2_lock_fs_check_clean(struct gfs2_sbd *sdp) ...@@ -430,7 +430,7 @@ static int gfs2_lock_fs_check_clean(struct gfs2_sbd *sdp)
} }
error = gfs2_glock_nq_init(sdp->sd_freeze_gl, LM_ST_EXCLUSIVE, error = gfs2_glock_nq_init(sdp->sd_freeze_gl, LM_ST_EXCLUSIVE,
GL_NOCACHE, &sdp->sd_freeze_gh); LM_FLAG_NOEXP, &sdp->sd_freeze_gh);
if (error) if (error)
goto out; goto out;
...@@ -613,13 +613,15 @@ int gfs2_make_fs_ro(struct gfs2_sbd *sdp) ...@@ -613,13 +613,15 @@ int gfs2_make_fs_ro(struct gfs2_sbd *sdp)
!gfs2_glock_is_locked_by_me(sdp->sd_freeze_gl)) { !gfs2_glock_is_locked_by_me(sdp->sd_freeze_gl)) {
if (!log_write_allowed) { if (!log_write_allowed) {
error = gfs2_glock_nq_init(sdp->sd_freeze_gl, error = gfs2_glock_nq_init(sdp->sd_freeze_gl,
LM_ST_SHARED, GL_NOCACHE | LM_ST_SHARED, LM_FLAG_TRY |
LM_FLAG_TRY, &freeze_gh); LM_FLAG_NOEXP | GL_EXACT,
&freeze_gh);
if (error == GLR_TRYFAILED) if (error == GLR_TRYFAILED)
error = 0; error = 0;
} else { } else {
error = gfs2_glock_nq_init(sdp->sd_freeze_gl, error = gfs2_glock_nq_init(sdp->sd_freeze_gl,
LM_ST_SHARED, GL_NOCACHE, LM_ST_SHARED,
LM_FLAG_NOEXP | GL_EXACT,
&freeze_gh); &freeze_gh);
if (error && !gfs2_withdrawn(sdp)) if (error && !gfs2_withdrawn(sdp))
return error; return error;
...@@ -761,8 +763,8 @@ void gfs2_freeze_func(struct work_struct *work) ...@@ -761,8 +763,8 @@ void gfs2_freeze_func(struct work_struct *work)
struct super_block *sb = sdp->sd_vfs; struct super_block *sb = sdp->sd_vfs;
atomic_inc(&sb->s_active); atomic_inc(&sb->s_active);
error = gfs2_glock_nq_init(sdp->sd_freeze_gl, LM_ST_SHARED, 0, error = gfs2_glock_nq_init(sdp->sd_freeze_gl, LM_ST_SHARED,
&freeze_gh); LM_FLAG_NOEXP | GL_EXACT, &freeze_gh);
if (error) { if (error) {
fs_info(sdp, "GFS2: couldn't get freeze lock : %d\n", error); fs_info(sdp, "GFS2: couldn't get freeze lock : %d\n", error);
gfs2_assert_withdraw(sdp, 0); gfs2_assert_withdraw(sdp, 0);
...@@ -774,8 +776,6 @@ void gfs2_freeze_func(struct work_struct *work) ...@@ -774,8 +776,6 @@ void gfs2_freeze_func(struct work_struct *work)
error); error);
gfs2_assert_withdraw(sdp, 0); gfs2_assert_withdraw(sdp, 0);
} }
if (!test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags))
freeze_gh.gh_flags |= GL_NOCACHE;
gfs2_glock_dq_uninit(&freeze_gh); gfs2_glock_dq_uninit(&freeze_gh);
} }
deactivate_super(sb); deactivate_super(sb);
......
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