diff options
author | Stephen Rothwell <sfr@canb.auug.org.au> | 2021-09-30 10:47:24 +1000 |
---|---|---|
committer | Stephen Rothwell <sfr@canb.auug.org.au> | 2021-09-30 10:47:24 +1000 |
commit | bea38e4f53d56fed5001c12fb5318b51128dd6d4 (patch) | |
tree | 3d714d79764408d29311c571842ee06a524f919c | |
parent | c64088784bc7415d9f70b89990f80a8c4816bf50 (diff) | |
parent | 11603f0011d0ee6f8d15e5ef7800ec69a92b1ca3 (diff) | |
download | devel-bea38e4f53d56fed5001c12fb5318b51128dd6d4.tar.gz |
Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2.git
-rw-r--r-- | fs/gfs2/file.c | 10 | ||||
-rw-r--r-- | fs/gfs2/glock.c | 23 | ||||
-rw-r--r-- | fs/gfs2/glock.h | 7 | ||||
-rw-r--r-- | fs/gfs2/glops.c | 16 | ||||
-rw-r--r-- | fs/gfs2/incore.h | 1 | ||||
-rw-r--r-- | fs/gfs2/rgrp.c | 41 | ||||
-rw-r--r-- | fs/gfs2/rgrp.h | 1 |
7 files changed, 69 insertions, 30 deletions
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index c559827cb6f915..1ff11328f1708d 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c @@ -213,11 +213,9 @@ void gfs2_set_inode_flags(struct inode *inode) * @inode: The inode * @reqflags: The flags to set * @mask: Indicates which flags are valid - * @fsflags: The FS_* inode flags passed in * */ -static int do_gfs2_set_flags(struct inode *inode, u32 reqflags, u32 mask, - const u32 fsflags) +static int do_gfs2_set_flags(struct inode *inode, u32 reqflags, u32 mask) { struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_sbd *sdp = GFS2_SB(inode); @@ -237,10 +235,6 @@ static int do_gfs2_set_flags(struct inode *inode, u32 reqflags, u32 mask, goto out; error = -EPERM; - if (IS_IMMUTABLE(inode) && (new_flags & GFS2_DIF_IMMUTABLE)) - goto out; - if (IS_APPEND(inode) && (new_flags & GFS2_DIF_APPENDONLY)) - goto out; if (!IS_IMMUTABLE(inode)) { error = gfs2_permission(&init_user_ns, inode, MAY_WRITE); if (error) @@ -313,7 +307,7 @@ int gfs2_fileattr_set(struct user_namespace *mnt_userns, mask &= ~(GFS2_DIF_TOPDIR | GFS2_DIF_INHERIT_JDATA); } - return do_gfs2_set_flags(inode, gfsflags, mask, fsflags); + return do_gfs2_set_flags(inode, gfsflags, mask); } static int gfs2_getlabel(struct file *filp, char __user *label) diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index e0eaa9cf9fb6fc..6dfd33dc206bfd 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c @@ -394,6 +394,7 @@ __acquires(&gl->gl_lockref.lock) { const struct gfs2_glock_operations *glops = gl->gl_ops; struct gfs2_holder *gh, *tmp; + int first; int ret; restart: @@ -401,8 +402,10 @@ restart: if (test_bit(HIF_HOLDER, &gh->gh_iflags)) continue; if (may_grant(gl, gh)) { - if (gh->gh_list.prev == &gl->gl_holders && - glops->go_lock) { + first = gfs2_first_holder(gh); + if (!(gh->gh_flags & GL_SKIP) && + glops->go_lock_needed && + glops->go_lock_needed(gh)) { spin_unlock(&gl->gl_lockref.lock); /* FIXME: eliminate this eventually */ ret = glops->go_lock(gh); @@ -416,14 +419,18 @@ restart: gfs2_holder_wake(gh); goto restart; } - set_bit(HIF_HOLDER, &gh->gh_iflags); - trace_gfs2_promote(gh, 1); - gfs2_holder_wake(gh); - goto restart; } set_bit(HIF_HOLDER, &gh->gh_iflags); - trace_gfs2_promote(gh, 0); + trace_gfs2_promote(gh, first); gfs2_holder_wake(gh); + /* + * If this was the first holder, we may have released + * the gl_lockref.lock, so the holders list may have + * changed. For that reason, we start again at the + * start of the holders queue. + */ + if (first) + goto restart; continue; } if (gh->gh_list.prev == &gl->gl_holders) @@ -2076,6 +2083,8 @@ static const char *hflags2str(char *buf, u16 flags, unsigned long iflags) *p++ = 'H'; if (test_bit(HIF_WAIT, &iflags)) *p++ = 'W'; + if (flags & GL_SKIP) + *p++ = 's'; *p = 0; return buf; } diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h index 31a8f2f649b52f..699c5e95006a98 100644 --- a/fs/gfs2/glock.h +++ b/fs/gfs2/glock.h @@ -325,6 +325,13 @@ static inline void glock_clear_object(struct gfs2_glock *gl, void *object) spin_unlock(&gl->gl_lockref.lock); } +static inline bool gfs2_first_holder(struct gfs2_holder *gh) +{ + struct gfs2_glock *gl = gh->gh_gl; + + return (gh->gh_list.prev == &gl->gl_holders); +} + extern void gfs2_inode_remember_delete(struct gfs2_glock *gl, u64 generation); extern bool gfs2_inode_already_deleted(struct gfs2_glock *gl, u64 generation); diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c index 79c621c7863d28..e0fa8d7f96d3dc 100644 --- a/fs/gfs2/glops.c +++ b/fs/gfs2/glops.c @@ -481,6 +481,17 @@ int gfs2_inode_refresh(struct gfs2_inode *ip) return error; } +static bool inode_go_lock_needed(struct gfs2_holder *gh) +{ + struct gfs2_glock *gl = gh->gh_gl; + + if (!gl->gl_object) + return false; + if (!gfs2_first_holder(gh)) + return false; + return !(gh->gh_flags & GL_SKIP); +} + /** * inode_go_lock - operation done after an inode lock is locked by a process * @gh: The glock holder @@ -495,9 +506,6 @@ static int inode_go_lock(struct gfs2_holder *gh) struct gfs2_inode *ip = gl->gl_object; int error = 0; - if (!ip || (gh->gh_flags & GL_SKIP)) - return 0; - if (test_bit(GIF_INVALID, &ip->i_flags)) { error = gfs2_inode_refresh(ip); if (error) @@ -740,6 +748,7 @@ 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_lock_needed = inode_go_lock_needed, .go_lock = inode_go_lock, .go_dump = inode_go_dump, .go_type = LM_TYPE_INODE, @@ -750,6 +759,7 @@ const struct gfs2_glock_operations gfs2_inode_glops = { const struct gfs2_glock_operations gfs2_rgrp_glops = { .go_sync = rgrp_go_sync, .go_inval = rgrp_go_inval, + .go_lock_needed = gfs2_rgrp_go_lock_needed, .go_lock = gfs2_rgrp_go_lock, .go_dump = gfs2_rgrp_go_dump, .go_type = LM_TYPE_RGRP, diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index 0fe49770166ea5..dc5c9dccb06060 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h @@ -225,6 +225,7 @@ struct gfs2_glock_operations { const char *fs_id_buf); void (*go_callback)(struct gfs2_glock *gl, bool remote); void (*go_free)(struct gfs2_glock *gl); + bool (*go_lock_needed)(struct gfs2_holder *gh); const int go_subclass; const int go_type; const unsigned long go_flags; diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index c3b00ba92ed2e0..9848c5f4fbc4df 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c @@ -1230,7 +1230,7 @@ static int gfs2_rgrp_bh_get(struct gfs2_rgrpd *rgd) rgrp_set_bitmap_flags(rgd); rgd->rd_flags |= (GFS2_RDF_UPTODATE | GFS2_RDF_CHECK); rgd->rd_free_clone = rgd->rd_free; - BUG_ON(rgd->rd_reserved); + GLOCK_BUG_ON(rgd->rd_gl, rgd->rd_reserved); /* max out the rgrp allocation failure point */ rgd->rd_extfail_pt = rgd->rd_free; } @@ -1280,7 +1280,7 @@ static int update_rgrp_lvb(struct gfs2_rgrpd *rgd) rgd->rd_free = be32_to_cpu(rgd->rd_rgl->rl_free); rgrp_set_bitmap_flags(rgd); rgd->rd_free_clone = rgd->rd_free; - BUG_ON(rgd->rd_reserved); + GLOCK_BUG_ON(rgd->rd_gl, rgd->rd_reserved); /* max out the rgrp allocation failure point */ rgd->rd_extfail_pt = rgd->rd_free; rgd->rd_dinodes = be32_to_cpu(rgd->rd_rgl->rl_dinodes); @@ -1288,14 +1288,31 @@ static int update_rgrp_lvb(struct gfs2_rgrpd *rgd) return 0; } +bool gfs2_rgrp_go_lock_needed(struct gfs2_holder *gh) +{ + struct gfs2_rgrpd *rgd = gh->gh_gl->gl_object; + + if (gh->gh_flags & GL_SKIP) + return false; + + if (rgd->rd_bits[0].bi_bh) + return false; + return true; +} + int gfs2_rgrp_go_lock(struct gfs2_holder *gh) { + int ret; + struct gfs2_rgrpd *rgd = gh->gh_gl->gl_object; - struct gfs2_sbd *sdp = rgd->rd_sbd; - if (gh->gh_flags & GL_SKIP && sdp->sd_args.ar_rgrplvb) - return 0; - return gfs2_rgrp_bh_get(rgd); + if (gfs2_glock_is_held_excl(rgd->rd_gl)) + rgrp_lock_local(rgd); + ret = gfs2_rgrp_bh_get(rgd); + if (gfs2_glock_is_held_excl(rgd->rd_gl)) + rgrp_unlock_local(rgd); + + return ret; } /** @@ -2215,7 +2232,7 @@ void gfs2_inplace_release(struct gfs2_inode *ip) struct gfs2_rgrpd *rgd = rs->rs_rgd; spin_lock(&rgd->rd_rsspin); - BUG_ON(rgd->rd_reserved < rs->rs_reserved); + GLOCK_BUG_ON(rgd->rd_gl, rgd->rd_reserved < rs->rs_reserved); rgd->rd_reserved -= rs->rs_reserved; spin_unlock(&rgd->rd_rsspin); rs->rs_reserved = 0; @@ -2476,9 +2493,9 @@ int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *nblocks, spin_unlock(&rbm.rgd->rd_rsspin); goto rgrp_error; } - BUG_ON(rbm.rgd->rd_reserved < *nblocks); - BUG_ON(rbm.rgd->rd_free_clone < *nblocks); - BUG_ON(rbm.rgd->rd_free < *nblocks); + GLOCK_BUG_ON(rbm.rgd->rd_gl, rbm.rgd->rd_reserved < *nblocks); + GLOCK_BUG_ON(rbm.rgd->rd_gl, rbm.rgd->rd_free_clone < *nblocks); + GLOCK_BUG_ON(rbm.rgd->rd_gl, rbm.rgd->rd_free < *nblocks); rbm.rgd->rd_reserved -= *nblocks; rbm.rgd->rd_free_clone -= *nblocks; rbm.rgd->rd_free -= *nblocks; @@ -2765,8 +2782,8 @@ void gfs2_rlist_free(struct gfs2_rgrp_list *rlist) void rgrp_lock_local(struct gfs2_rgrpd *rgd) { - BUG_ON(!gfs2_glock_is_held_excl(rgd->rd_gl) && - !test_bit(SDF_NORECOVERY, &rgd->rd_sbd->sd_flags)); + GLOCK_BUG_ON(rgd->rd_gl, !gfs2_glock_is_held_excl(rgd->rd_gl) && + !test_bit(SDF_NORECOVERY, &rgd->rd_sbd->sd_flags)); mutex_lock(&rgd->rd_mutex); } diff --git a/fs/gfs2/rgrp.h b/fs/gfs2/rgrp.h index a6855fd796e03d..4b62ba5d8e20ab 100644 --- a/fs/gfs2/rgrp.h +++ b/fs/gfs2/rgrp.h @@ -31,6 +31,7 @@ extern struct gfs2_rgrpd *gfs2_rgrpd_get_next(struct gfs2_rgrpd *rgd); extern void gfs2_clear_rgrpd(struct gfs2_sbd *sdp); extern int gfs2_rindex_update(struct gfs2_sbd *sdp); extern void gfs2_free_clones(struct gfs2_rgrpd *rgd); +extern bool gfs2_rgrp_go_lock_needed(struct gfs2_holder *gh); extern int gfs2_rgrp_go_lock(struct gfs2_holder *gh); extern void gfs2_rgrp_brelse(struct gfs2_rgrpd *rgd); |