Skip to content

Commit

Permalink
Merge tag 'gfs2-v6.7-rc1-fixes' of git://git.kernel.org/pub/scm/linux…
Browse files Browse the repository at this point in the history
…/kernel/git/gfs2/linux-gfs2

Pull gfs2 updates from Andreas Gruenbacher:

 - Add support for non-blocking lookup (MAY_NOT_BLOCK / LOOKUP_RCU)

 - Various minor fixes and cleanups

* tag 'gfs2-v6.7-rc1-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2:
  gfs2: Fix freeze consistency check in log_write_header
  gfs2: Refcounting fix in gfs2_thaw_super
  gfs2: Minor gfs2_{freeze,thaw}_super cleanup
  gfs2: Use wait_event_freezable_timeout() for freezable kthread
  gfs2: Add missing set_freezable() for freezable kthread
  gfs2: Remove use of error flag in journal reads
  gfs2: Lift withdraw check out of gfs2_ail1_empty
  gfs2: Rename gfs2_withdrawn to gfs2_withdrawing_or_withdrawn
  gfs2: Mark withdraws as unlikely
  gfs2: Minor gfs2_ail1_empty cleanup
  gfs2: use is_subdir()
  gfs2: d_obtain_alias(ERR_PTR(...)) will do the right thing
  gfs2: Use GL_NOBLOCK flag for non-blocking lookups
  gfs2: Add GL_NOBLOCK flag
  gfs2: rgrp: fix kernel-doc warnings
  gfs2: fix kernel BUG in gfs2_quota_cleanup
  gfs2: Fix inode_go_instantiate description
  gfs2: Fix kernel NULL pointer dereference in gfs2_rgrp_dump
  • Loading branch information
torvalds committed Jan 10, 2024
2 parents affc5af + e345b87 commit bfed9a9
Show file tree
Hide file tree
Showing 21 changed files with 182 additions and 151 deletions.
2 changes: 1 addition & 1 deletion fs/gfs2/aops.c
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,7 @@ static int gfs2_read_folio(struct file *file, struct folio *folio)
error = mpage_read_folio(folio, gfs2_block_map);
}

if (unlikely(gfs2_withdrawn(sdp)))
if (gfs2_withdrawing_or_withdrawn(sdp))
return -EIO;

return error;
Expand Down
23 changes: 14 additions & 9 deletions fs/gfs2/dentry.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,21 +32,25 @@

static int gfs2_drevalidate(struct dentry *dentry, unsigned int flags)
{
struct dentry *parent;
struct dentry *parent = NULL;
struct gfs2_sbd *sdp;
struct gfs2_inode *dip;
struct inode *inode;
struct inode *dinode, *inode;
struct gfs2_holder d_gh;
struct gfs2_inode *ip = NULL;
int error, valid = 0;
int had_lock = 0;

if (flags & LOOKUP_RCU)
return -ECHILD;

parent = dget_parent(dentry);
sdp = GFS2_SB(d_inode(parent));
dip = GFS2_I(d_inode(parent));
if (flags & LOOKUP_RCU) {
dinode = d_inode_rcu(READ_ONCE(dentry->d_parent));
if (!dinode)
return -ECHILD;
} else {
parent = dget_parent(dentry);
dinode = d_inode(parent);
}
sdp = GFS2_SB(dinode);
dip = GFS2_I(dinode);
inode = d_inode(dentry);

if (inode) {
Expand All @@ -62,7 +66,8 @@ static int gfs2_drevalidate(struct dentry *dentry, unsigned int flags)

had_lock = (gfs2_glock_is_locked_by_me(dip->i_gl) != NULL);
if (!had_lock) {
error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh);
error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED,
flags & LOOKUP_RCU ? GL_NOBLOCK : 0, &d_gh);
if (error)
goto out;
}
Expand Down
2 changes: 0 additions & 2 deletions fs/gfs2/export.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,6 @@ static struct dentry *gfs2_get_dentry(struct super_block *sb,
return ERR_PTR(-ESTALE);
inode = gfs2_lookup_by_inum(sdp, inum->no_addr, inum->no_formal_ino,
GFS2_BLKST_DINODE);
if (IS_ERR(inode))
return ERR_CAST(inode);
return d_obtain_alias(inode);
}

Expand Down
2 changes: 1 addition & 1 deletion fs/gfs2/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -1442,7 +1442,7 @@ static int gfs2_lock(struct file *file, int cmd, struct file_lock *fl)

if (!(fl->fl_flags & FL_POSIX))
return -ENOLCK;
if (unlikely(gfs2_withdrawn(sdp))) {
if (gfs2_withdrawing_or_withdrawn(sdp)) {
if (fl->fl_type == F_UNLCK)
locks_lock_file_wait(file, fl);
return -EIO;
Expand Down
47 changes: 42 additions & 5 deletions fs/gfs2/glock.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ static bool glock_blocked_by_withdraw(struct gfs2_glock *gl)
{
struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;

if (likely(!gfs2_withdrawn(sdp)))
if (!gfs2_withdrawing_or_withdrawn(sdp))
return false;
if (gl->gl_ops->go_flags & GLOF_NONDISK)
return false;
Expand Down Expand Up @@ -278,7 +278,7 @@ static void __gfs2_glock_put(struct gfs2_glock *gl)
GLOCK_BUG_ON(gl, !list_empty(&gl->gl_holders));
if (mapping) {
truncate_inode_pages_final(mapping);
if (!gfs2_withdrawn(sdp))
if (!gfs2_withdrawing_or_withdrawn(sdp))
GLOCK_BUG_ON(gl, !mapping_empty(mapping));
}
trace_gfs2_glock_put(gl);
Expand Down Expand Up @@ -516,6 +516,23 @@ static inline struct gfs2_holder *find_first_waiter(const struct gfs2_glock *gl)
return NULL;
}

/**
* find_last_waiter - find the last gh that's waiting for the glock
* @gl: the glock
*
* This also is a fast way of finding out if there are any waiters.
*/

static inline struct gfs2_holder *find_last_waiter(const struct gfs2_glock *gl)
{
struct gfs2_holder *gh;

if (list_empty(&gl->gl_holders))
return NULL;
gh = list_last_entry(&gl->gl_holders, struct gfs2_holder, gh_list);
return test_bit(HIF_HOLDER, &gh->gh_iflags) ? NULL : gh;
}

/**
* state_change - record that the glock is now in a different state
* @gl: the glock
Expand Down Expand Up @@ -757,7 +774,7 @@ __acquires(&gl->gl_lockref.lock)
* gfs2_gl_hash_clear calls clear_glock) and recovery is complete
* then it's okay to tell dlm to unlock it.
*/
if (unlikely(sdp->sd_log_error && !gfs2_withdrawn(sdp)))
if (unlikely(sdp->sd_log_error) && !gfs2_withdrawing_or_withdrawn(sdp))
gfs2_withdraw_delayed(sdp);
if (glock_blocked_by_withdraw(gl) &&
(target != LM_ST_UNLOCKED ||
Expand Down Expand Up @@ -794,7 +811,7 @@ __acquires(&gl->gl_lockref.lock)
gfs2_glock_queue_work(gl, 0);
} else if (ret) {
fs_err(sdp, "lm_lock ret %d\n", ret);
GLOCK_BUG_ON(gl, !gfs2_withdrawn(sdp));
GLOCK_BUG_ON(gl, !gfs2_withdrawing_or_withdrawn(sdp));
}
} else { /* lock_nolock */
finish_xmote(gl, target);
Expand Down Expand Up @@ -1555,11 +1572,30 @@ __acquires(&gl->gl_lockref.lock)
int gfs2_glock_nq(struct gfs2_holder *gh)
{
struct gfs2_glock *gl = gh->gh_gl;
int error = 0;
int error;

if (glock_blocked_by_withdraw(gl) && !(gh->gh_flags & LM_FLAG_NOEXP))
return -EIO;

if (gh->gh_flags & GL_NOBLOCK) {
struct gfs2_holder *current_gh;

error = -ECHILD;
spin_lock(&gl->gl_lockref.lock);
if (find_last_waiter(gl))
goto unlock;
current_gh = find_first_holder(gl);
if (!may_grant(gl, current_gh, gh))
goto unlock;
set_bit(HIF_HOLDER, &gh->gh_iflags);
list_add_tail(&gh->gh_list, &gl->gl_holders);
trace_gfs2_promote(gh);
error = 0;
unlock:
spin_unlock(&gl->gl_lockref.lock);
return error;
}

if (test_bit(GLF_LRU, &gl->gl_flags))
gfs2_glock_remove_from_lru(gl);

Expand All @@ -1575,6 +1611,7 @@ int gfs2_glock_nq(struct gfs2_holder *gh)
run_queue(gl, 1);
spin_unlock(&gl->gl_lockref.lock);

error = 0;
if (!(gh->gh_flags & GL_ASYNC))
error = gfs2_glock_wait(gh);

Expand Down
1 change: 1 addition & 0 deletions fs/gfs2/glock.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ enum {
#define GL_SKIP 0x0100
#define GL_NOPID 0x0200
#define GL_NOCACHE 0x0400
#define GL_NOBLOCK 0x0800

/*
* lm_async_cb return flags
Expand Down
4 changes: 2 additions & 2 deletions fs/gfs2/glops.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,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_withdrawn(sdp));
WARN_ON_ONCE(error && !gfs2_withdrawing_or_withdrawn(sdp));
mapping_set_error(metamapping, error);
if (error)
gfs2_io_error(sdp);
Expand Down Expand Up @@ -494,7 +494,7 @@ int gfs2_inode_refresh(struct gfs2_inode *ip)

/**
* inode_go_instantiate - read in an inode if necessary
* @gh: The glock holder
* @gl: The glock
*
* Returns: errno
*/
Expand Down
8 changes: 4 additions & 4 deletions fs/gfs2/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1882,10 +1882,10 @@ int gfs2_permission(struct mnt_idmap *idmap, struct inode *inode,
WARN_ON_ONCE(!may_not_block);
return -ECHILD;
}
if (gfs2_glock_is_locked_by_me(gl) == NULL) {
if (may_not_block)
return -ECHILD;
error = gfs2_glock_nq_init(gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
if (gfs2_glock_is_locked_by_me(ip->i_gl) == NULL) {
int noblock = may_not_block ? GL_NOBLOCK : 0;
error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED,
LM_FLAG_ANY | noblock, &i_gh);
if (error)
return error;
}
Expand Down
8 changes: 4 additions & 4 deletions fs/gfs2/lock_dlm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1122,7 +1122,7 @@ static void gdlm_recover_prep(void *arg)
struct gfs2_sbd *sdp = arg;
struct lm_lockstruct *ls = &sdp->sd_lockstruct;

if (gfs2_withdrawn(sdp)) {
if (gfs2_withdrawing_or_withdrawn(sdp)) {
fs_err(sdp, "recover_prep ignored due to withdraw.\n");
return;
}
Expand All @@ -1148,7 +1148,7 @@ static void gdlm_recover_slot(void *arg, struct dlm_slot *slot)
struct lm_lockstruct *ls = &sdp->sd_lockstruct;
int jid = slot->slot - 1;

if (gfs2_withdrawn(sdp)) {
if (gfs2_withdrawing_or_withdrawn(sdp)) {
fs_err(sdp, "recover_slot jid %d ignored due to withdraw.\n",
jid);
return;
Expand Down Expand Up @@ -1177,7 +1177,7 @@ static void gdlm_recover_done(void *arg, struct dlm_slot *slots, int num_slots,
struct gfs2_sbd *sdp = arg;
struct lm_lockstruct *ls = &sdp->sd_lockstruct;

if (gfs2_withdrawn(sdp)) {
if (gfs2_withdrawing_or_withdrawn(sdp)) {
fs_err(sdp, "recover_done ignored due to withdraw.\n");
return;
}
Expand Down Expand Up @@ -1208,7 +1208,7 @@ static void gdlm_recovery_result(struct gfs2_sbd *sdp, unsigned int jid,
{
struct lm_lockstruct *ls = &sdp->sd_lockstruct;

if (gfs2_withdrawn(sdp)) {
if (gfs2_withdrawing_or_withdrawn(sdp)) {
fs_err(sdp, "recovery_result jid %d ignored due to withdraw.\n",
jid);
return;
Expand Down
Loading

0 comments on commit bfed9a9

Please sign in to comment.