diff options
Diffstat (limited to 'fs/gfs2/glops.c')
| -rw-r--r-- | fs/gfs2/glops.c | 148 |
1 files changed, 32 insertions, 116 deletions
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c index 68677fb69a73..2173ccf5034b 100644 --- a/fs/gfs2/glops.c +++ b/fs/gfs2/glops.c @@ -11,6 +11,7 @@ #include <linux/bio.h> #include <linux/posix_acl.h> #include <linux/security.h> +#include <linux/log2.h> #include "gfs2.h" #include "incore.h" @@ -29,8 +30,6 @@ struct workqueue_struct *gfs2_freeze_wq; -extern struct workqueue_struct *gfs2_control_wq; - static void gfs2_ail_error(struct gfs2_glock *gl, const struct buffer_head *bh) { struct gfs2_sbd *sdp = gl->gl_name.ln_sbd; @@ -39,12 +38,12 @@ static void gfs2_ail_error(struct gfs2_glock *gl, const struct buffer_head *bh) "AIL buffer %p: blocknr %llu state 0x%08lx mapping %p page " "state 0x%lx\n", bh, (unsigned long long)bh->b_blocknr, bh->b_state, - bh->b_folio->mapping, bh->b_folio->flags); + bh->b_folio->mapping, bh->b_folio->flags.f); fs_err(sdp, "AIL glock %u:%llu mapping %p\n", gl->gl_name.ln_type, gl->gl_name.ln_number, gfs2_glock2aspace(gl)); gfs2_lm(sdp, "AIL error\n"); - gfs2_withdraw_delayed(sdp); + gfs2_withdraw(sdp); } /** @@ -82,9 +81,6 @@ 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); - - if (gfs2_withdrawing(sdp)) - gfs2_withdraw(sdp); } @@ -168,7 +164,7 @@ void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync) static int gfs2_rgrp_metasync(struct gfs2_glock *gl) { struct gfs2_sbd *sdp = gl->gl_name.ln_sbd; - struct address_space *metamapping = &sdp->sd_aspace; + struct address_space *metamapping = gfs2_aspace(sdp); struct gfs2_rgrpd *rgd = gfs2_glock2rgrp(gl); const unsigned bsize = sdp->sd_sb.sb_bsize; loff_t start = (rgd->rd_addr * bsize) & PAGE_MASK; @@ -177,7 +173,7 @@ static int gfs2_rgrp_metasync(struct gfs2_glock *gl) filemap_fdatawrite_range(metamapping, start, end); error = filemap_fdatawait_range(metamapping, start, end); - WARN_ON_ONCE(error && !gfs2_withdrawing_or_withdrawn(sdp)); + WARN_ON_ONCE(error && !gfs2_withdrawn(sdp)); mapping_set_error(metamapping, error); if (error) gfs2_io_error(sdp); @@ -225,7 +221,7 @@ static int rgrp_go_sync(struct gfs2_glock *gl) static void rgrp_go_inval(struct gfs2_glock *gl, int flags) { struct gfs2_sbd *sdp = gl->gl_name.ln_sbd; - struct address_space *mapping = &sdp->sd_aspace; + struct address_space *mapping = gfs2_aspace(sdp); struct gfs2_rgrpd *rgd = gfs2_glock2rgrp(gl); const unsigned bsize = sdp->sd_sb.sb_bsize; loff_t start, end; @@ -236,6 +232,7 @@ static void rgrp_go_inval(struct gfs2_glock *gl, int flags) end = PAGE_ALIGN((rgd->rd_addr + rgd->rd_length) * bsize) - 1; gfs2_rgrp_brelse(rgd); WARN_ON_ONCE(!(flags & DIO_METADATA)); + gfs2_assert_withdraw(sdp, !atomic_read(&gl->gl_ail_count)); truncate_inode_pages_range(mapping, start, end); } @@ -362,6 +359,8 @@ static void inode_go_inval(struct gfs2_glock *gl, int flags) { struct gfs2_inode *ip = gfs2_glock2inode(gl); + gfs2_assert_withdraw(gl->gl_name.ln_sbd, !atomic_read(&gl->gl_ail_count)); + if (flags & DIO_METADATA) { struct address_space *mapping = gfs2_glock2aspace(gl); truncate_inode_pages(mapping, 0); @@ -385,23 +384,6 @@ static void inode_go_inval(struct gfs2_glock *gl, int flags) gfs2_clear_glop_pending(ip); } -/** - * inode_go_demote_ok - Check to see if it's ok to unlock an inode glock - * @gl: the glock - * - * Returns: 1 if it's ok - */ - -static int inode_go_demote_ok(const struct gfs2_glock *gl) -{ - struct gfs2_sbd *sdp = gl->gl_name.ln_sbd; - - if (sdp->sd_jindex == gl->gl_object || sdp->sd_rindex == gl->gl_object) - return 0; - - return 1; -} - static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) { struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); @@ -410,7 +392,7 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) u16 height, depth; umode_t mode = be32_to_cpu(str->di_mode); struct inode *inode = &ip->i_inode; - bool is_new = inode->i_state & I_NEW; + bool is_new = inode_state_read_once(inode) & I_NEW; if (unlikely(ip->i_no_addr != be64_to_cpu(str->di_num.no_addr))) { gfs2_consist_inode(ip); @@ -467,6 +449,11 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) gfs2_consist_inode(ip); return -EIO; } + if ((ip->i_diskflags & GFS2_DIF_EXHASH) && + depth < ilog2(sdp->sd_hash_ptrs)) { + gfs2_consist_inode(ip); + return -EIO; + } ip->i_depth = (u8)depth; ip->i_entries = be32_to_cpu(str->di_entries); @@ -487,7 +474,7 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) * Returns: errno */ -int gfs2_inode_refresh(struct gfs2_inode *ip) +static int gfs2_inode_refresh(struct gfs2_inode *ip) { struct buffer_head *dibh; int error; @@ -511,11 +498,18 @@ int gfs2_inode_refresh(struct gfs2_inode *ip) static int inode_go_instantiate(struct gfs2_glock *gl) { struct gfs2_inode *ip = gl->gl_object; + struct gfs2_glock *io_gl; + int error; if (!ip) /* no inode to populate - read it in later */ return 0; - return gfs2_inode_refresh(ip); + error = gfs2_inode_refresh(ip); + if (error) + return error; + io_gl = ip->i_iopen_gh.gh_gl; + io_gl->gl_no_formal_ino = ip->i_no_formal_ino; + return 0; } static int inode_go_held(struct gfs2_holder *gh) @@ -611,14 +605,13 @@ static int freeze_go_xmote_bh(struct gfs2_glock *gl) if (test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) { j_gl->gl_ops->go_inval(j_gl, DIO_METADATA); - error = gfs2_find_jhead(sdp->sd_jdesc, &head, false); - if (gfs2_assert_withdraw_delayed(sdp, !error)) + error = gfs2_find_jhead(sdp->sd_jdesc, &head); + if (gfs2_assert_withdraw(sdp, !error)) return error; - if (gfs2_assert_withdraw_delayed(sdp, head.lh_flags & - GFS2_LOG_HEAD_UNMOUNT)) + if (gfs2_assert_withdraw(sdp, head.lh_flags & + GFS2_LOG_HEAD_UNMOUNT)) return -EIO; - sdp->sd_log_sequence = head.lh_sequence + 1; - gfs2_log_pointers_init(sdp, head.lh_blkno); + gfs2_log_pointers_init(sdp, &head); } return 0; } @@ -635,8 +628,7 @@ static void iopen_go_callback(struct gfs2_glock *gl, bool remote) struct gfs2_inode *ip = gl->gl_object; struct gfs2_sbd *sdp = gl->gl_name.ln_sbd; - if (!remote || sb_rdonly(sdp->sd_vfs) || - test_bit(SDF_KILL, &sdp->sd_flags)) + if (!remote || test_bit(SDF_KILL, &sdp->sd_flags)) return; if (gl->gl_demote_state == LM_ST_UNLOCKED && @@ -647,88 +639,18 @@ static void iopen_go_callback(struct gfs2_glock *gl, bool remote) } } -/** - * inode_go_free - wake up anyone waiting for dlm's unlock ast to free it - * @gl: glock being freed - * - * For now, this is only used for the journal inode glock. In withdraw - * situations, we need to wait for the glock to be freed so that we know - * other nodes may proceed with recovery / journal replay. - */ -static void inode_go_free(struct gfs2_glock *gl) -{ - /* Note that we cannot reference gl_object because it's already set - * to NULL by this point in its lifecycle. */ - if (!test_bit(GLF_FREEING, &gl->gl_flags)) - return; - clear_bit_unlock(GLF_FREEING, &gl->gl_flags); - wake_up_bit(&gl->gl_flags, GLF_FREEING); -} - -/** - * nondisk_go_callback - used to signal when a node did a withdraw - * @gl: the nondisk glock - * @remote: true if this came from a different cluster node - * - */ -static void nondisk_go_callback(struct gfs2_glock *gl, bool remote) -{ - struct gfs2_sbd *sdp = gl->gl_name.ln_sbd; - - /* Ignore the callback unless it's from another node, and it's the - live lock. */ - if (!remote || gl->gl_name.ln_number != GFS2_LIVE_LOCK) - return; - - /* First order of business is to cancel the demote request. We don't - * really want to demote a nondisk glock. At best it's just to inform - * us of another node's withdraw. We'll keep it in SH mode. */ - clear_bit(GLF_DEMOTE, &gl->gl_flags); - clear_bit(GLF_PENDING_DEMOTE, &gl->gl_flags); - - /* Ignore the unlock if we're withdrawn, unmounting, or in recovery. */ - if (test_bit(SDF_NORECOVERY, &sdp->sd_flags) || - test_bit(SDF_WITHDRAWN, &sdp->sd_flags) || - test_bit(SDF_REMOTE_WITHDRAW, &sdp->sd_flags)) - return; - - /* We only care when a node wants us to unlock, because that means - * they want a journal recovered. */ - if (gl->gl_demote_state != LM_ST_UNLOCKED) - return; - - if (sdp->sd_args.ar_spectator) { - fs_warn(sdp, "Spectator node cannot recover journals.\n"); - return; - } - - fs_warn(sdp, "Some node has withdrawn; checking for recovery.\n"); - set_bit(SDF_REMOTE_WITHDRAW, &sdp->sd_flags); - /* - * We can't call remote_withdraw directly here or gfs2_recover_journal - * because this is called from the glock unlock function and the - * remote_withdraw needs to enqueue and dequeue the same "live" glock - * we were called from. So we queue it to the control work queue in - * lock_dlm. - */ - queue_delayed_work(gfs2_control_wq, &sdp->sd_control_work, 0); -} - const struct gfs2_glock_operations gfs2_meta_glops = { .go_type = LM_TYPE_META, - .go_flags = GLOF_NONDISK, }; const struct gfs2_glock_operations gfs2_inode_glops = { .go_sync = inode_go_sync, .go_inval = inode_go_inval, - .go_demote_ok = inode_go_demote_ok, .go_instantiate = inode_go_instantiate, .go_held = inode_go_held, .go_dump = inode_go_dump, .go_type = LM_TYPE_INODE, - .go_flags = GLOF_ASPACE | GLOF_LRU | GLOF_LVB, - .go_free = inode_go_free, + .go_flags = GLOF_ASPACE | GLOF_LVB, }; const struct gfs2_glock_operations gfs2_rgrp_glops = { @@ -744,36 +666,30 @@ const struct gfs2_glock_operations gfs2_freeze_glops = { .go_xmote_bh = freeze_go_xmote_bh, .go_callback = freeze_go_callback, .go_type = LM_TYPE_NONDISK, - .go_flags = GLOF_NONDISK, }; const struct gfs2_glock_operations gfs2_iopen_glops = { .go_type = LM_TYPE_IOPEN, .go_callback = iopen_go_callback, .go_dump = inode_go_dump, - .go_flags = GLOF_LRU | GLOF_NONDISK, .go_subclass = 1, }; const struct gfs2_glock_operations gfs2_flock_glops = { .go_type = LM_TYPE_FLOCK, - .go_flags = GLOF_LRU | GLOF_NONDISK, }; const struct gfs2_glock_operations gfs2_nondisk_glops = { .go_type = LM_TYPE_NONDISK, - .go_flags = GLOF_NONDISK, - .go_callback = nondisk_go_callback, }; const struct gfs2_glock_operations gfs2_quota_glops = { .go_type = LM_TYPE_QUOTA, - .go_flags = GLOF_LVB | GLOF_LRU | GLOF_NONDISK, + .go_flags = GLOF_LVB, }; const struct gfs2_glock_operations gfs2_journal_glops = { .go_type = LM_TYPE_JOURNAL, - .go_flags = GLOF_NONDISK, }; const struct gfs2_glock_operations *gfs2_glops_list[] = { |
