Skip to content

Commit bfed9a9

Browse files
committed
Merge tag 'gfs2-v6.7-rc1-fixes' of git://git.kernel.org/pub/scm/linux/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
2 parents affc5af + e345b87 commit bfed9a9

21 files changed

Lines changed: 182 additions & 151 deletions

fs/gfs2/aops.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,7 @@ static int gfs2_read_folio(struct file *file, struct folio *folio)
459459
error = mpage_read_folio(folio, gfs2_block_map);
460460
}
461461

462-
if (unlikely(gfs2_withdrawn(sdp)))
462+
if (gfs2_withdrawing_or_withdrawn(sdp))
463463
return -EIO;
464464

465465
return error;

fs/gfs2/dentry.c

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,21 +32,25 @@
3232

3333
static int gfs2_drevalidate(struct dentry *dentry, unsigned int flags)
3434
{
35-
struct dentry *parent;
35+
struct dentry *parent = NULL;
3636
struct gfs2_sbd *sdp;
3737
struct gfs2_inode *dip;
38-
struct inode *inode;
38+
struct inode *dinode, *inode;
3939
struct gfs2_holder d_gh;
4040
struct gfs2_inode *ip = NULL;
4141
int error, valid = 0;
4242
int had_lock = 0;
4343

44-
if (flags & LOOKUP_RCU)
45-
return -ECHILD;
46-
47-
parent = dget_parent(dentry);
48-
sdp = GFS2_SB(d_inode(parent));
49-
dip = GFS2_I(d_inode(parent));
44+
if (flags & LOOKUP_RCU) {
45+
dinode = d_inode_rcu(READ_ONCE(dentry->d_parent));
46+
if (!dinode)
47+
return -ECHILD;
48+
} else {
49+
parent = dget_parent(dentry);
50+
dinode = d_inode(parent);
51+
}
52+
sdp = GFS2_SB(dinode);
53+
dip = GFS2_I(dinode);
5054
inode = d_inode(dentry);
5155

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

6367
had_lock = (gfs2_glock_is_locked_by_me(dip->i_gl) != NULL);
6468
if (!had_lock) {
65-
error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh);
69+
error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED,
70+
flags & LOOKUP_RCU ? GL_NOBLOCK : 0, &d_gh);
6671
if (error)
6772
goto out;
6873
}

fs/gfs2/export.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,6 @@ static struct dentry *gfs2_get_dentry(struct super_block *sb,
138138
return ERR_PTR(-ESTALE);
139139
inode = gfs2_lookup_by_inum(sdp, inum->no_addr, inum->no_formal_ino,
140140
GFS2_BLKST_DINODE);
141-
if (IS_ERR(inode))
142-
return ERR_CAST(inode);
143141
return d_obtain_alias(inode);
144142
}
145143

fs/gfs2/file.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1442,7 +1442,7 @@ static int gfs2_lock(struct file *file, int cmd, struct file_lock *fl)
14421442

14431443
if (!(fl->fl_flags & FL_POSIX))
14441444
return -ENOLCK;
1445-
if (unlikely(gfs2_withdrawn(sdp))) {
1445+
if (gfs2_withdrawing_or_withdrawn(sdp)) {
14461446
if (fl->fl_type == F_UNLCK)
14471447
locks_lock_file_wait(file, fl);
14481448
return -EIO;

fs/gfs2/glock.c

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ static bool glock_blocked_by_withdraw(struct gfs2_glock *gl)
156156
{
157157
struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
158158

159-
if (likely(!gfs2_withdrawn(sdp)))
159+
if (!gfs2_withdrawing_or_withdrawn(sdp))
160160
return false;
161161
if (gl->gl_ops->go_flags & GLOF_NONDISK)
162162
return false;
@@ -278,7 +278,7 @@ static void __gfs2_glock_put(struct gfs2_glock *gl)
278278
GLOCK_BUG_ON(gl, !list_empty(&gl->gl_holders));
279279
if (mapping) {
280280
truncate_inode_pages_final(mapping);
281-
if (!gfs2_withdrawn(sdp))
281+
if (!gfs2_withdrawing_or_withdrawn(sdp))
282282
GLOCK_BUG_ON(gl, !mapping_empty(mapping));
283283
}
284284
trace_gfs2_glock_put(gl);
@@ -516,6 +516,23 @@ static inline struct gfs2_holder *find_first_waiter(const struct gfs2_glock *gl)
516516
return NULL;
517517
}
518518

519+
/**
520+
* find_last_waiter - find the last gh that's waiting for the glock
521+
* @gl: the glock
522+
*
523+
* This also is a fast way of finding out if there are any waiters.
524+
*/
525+
526+
static inline struct gfs2_holder *find_last_waiter(const struct gfs2_glock *gl)
527+
{
528+
struct gfs2_holder *gh;
529+
530+
if (list_empty(&gl->gl_holders))
531+
return NULL;
532+
gh = list_last_entry(&gl->gl_holders, struct gfs2_holder, gh_list);
533+
return test_bit(HIF_HOLDER, &gh->gh_iflags) ? NULL : gh;
534+
}
535+
519536
/**
520537
* state_change - record that the glock is now in a different state
521538
* @gl: the glock
@@ -757,7 +774,7 @@ __acquires(&gl->gl_lockref.lock)
757774
* gfs2_gl_hash_clear calls clear_glock) and recovery is complete
758775
* then it's okay to tell dlm to unlock it.
759776
*/
760-
if (unlikely(sdp->sd_log_error && !gfs2_withdrawn(sdp)))
777+
if (unlikely(sdp->sd_log_error) && !gfs2_withdrawing_or_withdrawn(sdp))
761778
gfs2_withdraw_delayed(sdp);
762779
if (glock_blocked_by_withdraw(gl) &&
763780
(target != LM_ST_UNLOCKED ||
@@ -794,7 +811,7 @@ __acquires(&gl->gl_lockref.lock)
794811
gfs2_glock_queue_work(gl, 0);
795812
} else if (ret) {
796813
fs_err(sdp, "lm_lock ret %d\n", ret);
797-
GLOCK_BUG_ON(gl, !gfs2_withdrawn(sdp));
814+
GLOCK_BUG_ON(gl, !gfs2_withdrawing_or_withdrawn(sdp));
798815
}
799816
} else { /* lock_nolock */
800817
finish_xmote(gl, target);
@@ -1555,11 +1572,30 @@ __acquires(&gl->gl_lockref.lock)
15551572
int gfs2_glock_nq(struct gfs2_holder *gh)
15561573
{
15571574
struct gfs2_glock *gl = gh->gh_gl;
1558-
int error = 0;
1575+
int error;
15591576

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

1580+
if (gh->gh_flags & GL_NOBLOCK) {
1581+
struct gfs2_holder *current_gh;
1582+
1583+
error = -ECHILD;
1584+
spin_lock(&gl->gl_lockref.lock);
1585+
if (find_last_waiter(gl))
1586+
goto unlock;
1587+
current_gh = find_first_holder(gl);
1588+
if (!may_grant(gl, current_gh, gh))
1589+
goto unlock;
1590+
set_bit(HIF_HOLDER, &gh->gh_iflags);
1591+
list_add_tail(&gh->gh_list, &gl->gl_holders);
1592+
trace_gfs2_promote(gh);
1593+
error = 0;
1594+
unlock:
1595+
spin_unlock(&gl->gl_lockref.lock);
1596+
return error;
1597+
}
1598+
15631599
if (test_bit(GLF_LRU, &gl->gl_flags))
15641600
gfs2_glock_remove_from_lru(gl);
15651601

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

1614+
error = 0;
15781615
if (!(gh->gh_flags & GL_ASYNC))
15791616
error = gfs2_glock_wait(gh);
15801617

fs/gfs2/glock.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ enum {
8484
#define GL_SKIP 0x0100
8585
#define GL_NOPID 0x0200
8686
#define GL_NOCACHE 0x0400
87+
#define GL_NOBLOCK 0x0800
8788

8889
/*
8990
* lm_async_cb return flags

fs/gfs2/glops.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ static int gfs2_rgrp_metasync(struct gfs2_glock *gl)
174174

175175
filemap_fdatawrite_range(metamapping, start, end);
176176
error = filemap_fdatawait_range(metamapping, start, end);
177-
WARN_ON_ONCE(error && !gfs2_withdrawn(sdp));
177+
WARN_ON_ONCE(error && !gfs2_withdrawing_or_withdrawn(sdp));
178178
mapping_set_error(metamapping, error);
179179
if (error)
180180
gfs2_io_error(sdp);
@@ -494,7 +494,7 @@ int gfs2_inode_refresh(struct gfs2_inode *ip)
494494

495495
/**
496496
* inode_go_instantiate - read in an inode if necessary
497-
* @gh: The glock holder
497+
* @gl: The glock
498498
*
499499
* Returns: errno
500500
*/

fs/gfs2/inode.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1882,10 +1882,10 @@ int gfs2_permission(struct mnt_idmap *idmap, struct inode *inode,
18821882
WARN_ON_ONCE(!may_not_block);
18831883
return -ECHILD;
18841884
}
1885-
if (gfs2_glock_is_locked_by_me(gl) == NULL) {
1886-
if (may_not_block)
1887-
return -ECHILD;
1888-
error = gfs2_glock_nq_init(gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
1885+
if (gfs2_glock_is_locked_by_me(ip->i_gl) == NULL) {
1886+
int noblock = may_not_block ? GL_NOBLOCK : 0;
1887+
error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED,
1888+
LM_FLAG_ANY | noblock, &i_gh);
18891889
if (error)
18901890
return error;
18911891
}

fs/gfs2/lock_dlm.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1122,7 +1122,7 @@ static void gdlm_recover_prep(void *arg)
11221122
struct gfs2_sbd *sdp = arg;
11231123
struct lm_lockstruct *ls = &sdp->sd_lockstruct;
11241124

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

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

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

1211-
if (gfs2_withdrawn(sdp)) {
1211+
if (gfs2_withdrawing_or_withdrawn(sdp)) {
12121212
fs_err(sdp, "recovery_result jid %d ignored due to withdraw.\n",
12131213
jid);
12141214
return;

0 commit comments

Comments
 (0)