Skip to content

Commit c2131f7

Browse files
committed
Merge tag 'gfs2-v5.13-rc2-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.13-rc2-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2: gfs2: Fix use-after-free in gfs2_glock_shrink_scan gfs2: Fix mmap locking for write faults gfs2: Clean up revokes on normal withdraws gfs2: fix a deadlock on withdraw-during-mount gfs2: fix scheduling while atomic bug in glocks gfs2: Fix I_NEW check in gfs2_dinode_in gfs2: Prevent direct-I/O write fallback errors from getting lost
2 parents 36c7955 + 1ab19c5 commit c2131f7

File tree

8 files changed

+44
-11
lines changed

8 files changed

+44
-11
lines changed

fs/gfs2/file.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -540,9 +540,11 @@ static vm_fault_t gfs2_fault(struct vm_fault *vmf)
540540
struct gfs2_inode *ip = GFS2_I(inode);
541541
struct gfs2_holder gh;
542542
vm_fault_t ret;
543+
u16 state;
543544
int err;
544545

545-
gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &gh);
546+
state = (vmf->flags & FAULT_FLAG_WRITE) ? LM_ST_EXCLUSIVE : LM_ST_SHARED;
547+
gfs2_holder_init(ip->i_gl, state, 0, &gh);
546548
err = gfs2_glock_nq(&gh);
547549
if (err) {
548550
ret = block_page_mkwrite_return(err);
@@ -911,8 +913,11 @@ static ssize_t gfs2_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
911913
current->backing_dev_info = inode_to_bdi(inode);
912914
buffered = iomap_file_buffered_write(iocb, from, &gfs2_iomap_ops);
913915
current->backing_dev_info = NULL;
914-
if (unlikely(buffered <= 0))
916+
if (unlikely(buffered <= 0)) {
917+
if (!ret)
918+
ret = buffered;
915919
goto out_unlock;
920+
}
916921

917922
/*
918923
* We need to ensure that the page cache pages are written to

fs/gfs2/glock.c

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,16 @@ static void finish_xmote(struct gfs2_glock *gl, unsigned int ret)
582582
spin_unlock(&gl->gl_lockref.lock);
583583
}
584584

585+
static bool is_system_glock(struct gfs2_glock *gl)
586+
{
587+
struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
588+
struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode);
589+
590+
if (gl == m_ip->i_gl)
591+
return true;
592+
return false;
593+
}
594+
585595
/**
586596
* do_xmote - Calls the DLM to change the state of a lock
587597
* @gl: The lock state
@@ -671,17 +681,25 @@ __acquires(&gl->gl_lockref.lock)
671681
* to see sd_log_error and withdraw, and in the meantime, requeue the
672682
* work for later.
673683
*
684+
* We make a special exception for some system glocks, such as the
685+
* system statfs inode glock, which needs to be granted before the
686+
* gfs2_quotad daemon can exit, and that exit needs to finish before
687+
* we can unmount the withdrawn file system.
688+
*
674689
* However, if we're just unlocking the lock (say, for unmount, when
675690
* gfs2_gl_hash_clear calls clear_glock) and recovery is complete
676691
* then it's okay to tell dlm to unlock it.
677692
*/
678693
if (unlikely(sdp->sd_log_error && !gfs2_withdrawn(sdp)))
679694
gfs2_withdraw_delayed(sdp);
680-
if (glock_blocked_by_withdraw(gl)) {
681-
if (target != LM_ST_UNLOCKED ||
682-
test_bit(SDF_WITHDRAW_RECOVERY, &sdp->sd_flags)) {
695+
if (glock_blocked_by_withdraw(gl) &&
696+
(target != LM_ST_UNLOCKED ||
697+
test_bit(SDF_WITHDRAW_RECOVERY, &sdp->sd_flags))) {
698+
if (!is_system_glock(gl)) {
683699
gfs2_glock_queue_work(gl, GL_GLOCK_DFT_HOLD);
684700
goto out;
701+
} else {
702+
clear_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags);
685703
}
686704
}
687705

@@ -1466,9 +1484,11 @@ void gfs2_glock_dq(struct gfs2_holder *gh)
14661484
glock_blocked_by_withdraw(gl) &&
14671485
gh->gh_gl != sdp->sd_jinode_gl) {
14681486
sdp->sd_glock_dqs_held++;
1487+
spin_unlock(&gl->gl_lockref.lock);
14691488
might_sleep();
14701489
wait_on_bit(&sdp->sd_flags, SDF_WITHDRAW_RECOVERY,
14711490
TASK_UNINTERRUPTIBLE);
1491+
spin_lock(&gl->gl_lockref.lock);
14721492
}
14731493
if (gh->gh_flags & GL_NOCACHE)
14741494
handle_callback(gl, LM_ST_UNLOCKED, 0, false);
@@ -1775,6 +1795,7 @@ __acquires(&lru_lock)
17751795
while(!list_empty(list)) {
17761796
gl = list_first_entry(list, struct gfs2_glock, gl_lru);
17771797
list_del_init(&gl->gl_lru);
1798+
clear_bit(GLF_LRU, &gl->gl_flags);
17781799
if (!spin_trylock(&gl->gl_lockref.lock)) {
17791800
add_back_to_lru:
17801801
list_add(&gl->gl_lru, &lru_list);
@@ -1820,7 +1841,6 @@ static long gfs2_scan_glock_lru(int nr)
18201841
if (!test_bit(GLF_LOCK, &gl->gl_flags)) {
18211842
list_move(&gl->gl_lru, &dispose);
18221843
atomic_dec(&lru_count);
1823-
clear_bit(GLF_LRU, &gl->gl_flags);
18241844
freed++;
18251845
continue;
18261846
}

fs/gfs2/glops.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,7 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
396396
struct timespec64 atime;
397397
u16 height, depth;
398398
umode_t mode = be32_to_cpu(str->di_mode);
399-
bool is_new = ip->i_inode.i_flags & I_NEW;
399+
bool is_new = ip->i_inode.i_state & I_NEW;
400400

401401
if (unlikely(ip->i_no_addr != be64_to_cpu(str->di_num.no_addr)))
402402
goto corrupt;

fs/gfs2/log.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -926,10 +926,10 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags)
926926
}
927927

928928
/**
929-
* ail_drain - drain the ail lists after a withdraw
929+
* gfs2_ail_drain - drain the ail lists after a withdraw
930930
* @sdp: Pointer to GFS2 superblock
931931
*/
932-
static void ail_drain(struct gfs2_sbd *sdp)
932+
void gfs2_ail_drain(struct gfs2_sbd *sdp)
933933
{
934934
struct gfs2_trans *tr;
935935

@@ -956,6 +956,7 @@ static void ail_drain(struct gfs2_sbd *sdp)
956956
list_del(&tr->tr_list);
957957
gfs2_trans_free(sdp, tr);
958958
}
959+
gfs2_drain_revokes(sdp);
959960
spin_unlock(&sdp->sd_ail_lock);
960961
}
961962

@@ -1162,7 +1163,6 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, u32 flags)
11621163
if (tr && list_empty(&tr->tr_list))
11631164
list_add(&tr->tr_list, &sdp->sd_ail1_list);
11641165
spin_unlock(&sdp->sd_ail_lock);
1165-
ail_drain(sdp); /* frees all transactions */
11661166
tr = NULL;
11671167
goto out_end;
11681168
}

fs/gfs2/log.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,5 +93,6 @@ extern int gfs2_logd(void *data);
9393
extern void gfs2_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd);
9494
extern void gfs2_glock_remove_revoke(struct gfs2_glock *gl);
9595
extern void gfs2_flush_revokes(struct gfs2_sbd *sdp);
96+
extern void gfs2_ail_drain(struct gfs2_sbd *sdp);
9697

9798
#endif /* __LOG_DOT_H__ */

fs/gfs2/lops.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -885,7 +885,7 @@ static void revoke_lo_before_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
885885
gfs2_log_write_page(sdp, page);
886886
}
887887

888-
static void revoke_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
888+
void gfs2_drain_revokes(struct gfs2_sbd *sdp)
889889
{
890890
struct list_head *head = &sdp->sd_log_revokes;
891891
struct gfs2_bufdata *bd;
@@ -900,6 +900,11 @@ static void revoke_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
900900
}
901901
}
902902

903+
static void revoke_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
904+
{
905+
gfs2_drain_revokes(sdp);
906+
}
907+
903908
static void revoke_lo_before_scan(struct gfs2_jdesc *jd,
904909
struct gfs2_log_header_host *head, int pass)
905910
{

fs/gfs2/lops.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ extern void gfs2_log_submit_bio(struct bio **biop, int opf);
2020
extern void gfs2_pin(struct gfs2_sbd *sdp, struct buffer_head *bh);
2121
extern int gfs2_find_jhead(struct gfs2_jdesc *jd,
2222
struct gfs2_log_header_host *head, bool keep_cache);
23+
extern void gfs2_drain_revokes(struct gfs2_sbd *sdp);
2324
static inline unsigned int buf_limit(struct gfs2_sbd *sdp)
2425
{
2526
return sdp->sd_ldptrs;

fs/gfs2/util.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ static void signal_our_withdraw(struct gfs2_sbd *sdp)
131131
if (test_bit(SDF_NORECOVERY, &sdp->sd_flags) || !sdp->sd_jdesc)
132132
return;
133133

134+
gfs2_ail_drain(sdp); /* frees all transactions */
134135
inode = sdp->sd_jdesc->jd_inode;
135136
ip = GFS2_I(inode);
136137
i_gl = ip->i_gl;

0 commit comments

Comments
 (0)