Skip to content

Commit e719340

Browse files
committed
Merge tag 'gfs2-v5.7-rc1.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2
Pull gfs2 fixes from Andreas Gruenbacher: "Various gfs2 fixes. Fixes for bugs prior to v5.7: - Fix random block reads when reading fragmented journals (v5.2) - Fix a possible random memory access in gfs2_walk_metadata (v5.3) Fixes for v5.7: - Fix several overlooked gfs2_qa_get / gfs2_qa_put imbalances - Fix several bugs in the new filesystem withdraw logic" * tag 'gfs2-v5.7-rc1.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2: Revert "gfs2: Don't demote a glock until its revokes are written" gfs2: If go_sync returns error, withdraw but skip invalidate gfs2: Grab glock reference sooner in gfs2_add_revoke gfs2: don't call quota_unhold if quotas are not locked gfs2: move privileged user check to gfs2_quota_lock_check gfs2: remove check for quotas on in gfs2_quota_check gfs2: Change BUG_ON to an assert_withdraw in gfs2_quota_change gfs2: Fix problems regarding gfs2_qa_get and _put gfs2: More gfs2_find_jhead fixes gfs2: Another gfs2_walk_metadata fix gfs2: Fix use-after-free in gfs2_logd after withdraw gfs2: Fix BUG during unmount after file system withdraw gfs2: Fix error exit in do_xmote gfs2: fix withdraw sequence deadlock
2 parents 152036d + b14c949 commit e719340

File tree

10 files changed

+49
-39
lines changed

10 files changed

+49
-39
lines changed

fs/gfs2/bmap.c

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -528,10 +528,12 @@ static int gfs2_walk_metadata(struct inode *inode, struct metapath *mp,
528528

529529
/* Advance in metadata tree. */
530530
(mp->mp_list[hgt])++;
531-
if (mp->mp_list[hgt] >= sdp->sd_inptrs) {
532-
if (!hgt)
531+
if (hgt) {
532+
if (mp->mp_list[hgt] >= sdp->sd_inptrs)
533+
goto lower_metapath;
534+
} else {
535+
if (mp->mp_list[hgt] >= sdp->sd_diptrs)
533536
break;
534-
goto lower_metapath;
535537
}
536538

537539
fill_up_metapath:
@@ -876,10 +878,9 @@ static int gfs2_iomap_get(struct inode *inode, loff_t pos, loff_t length,
876878
ret = -ENOENT;
877879
goto unlock;
878880
} else {
879-
/* report a hole */
880881
iomap->offset = pos;
881882
iomap->length = length;
882-
goto do_alloc;
883+
goto hole_found;
883884
}
884885
}
885886
iomap->length = size;
@@ -933,8 +934,6 @@ static int gfs2_iomap_get(struct inode *inode, loff_t pos, loff_t length,
933934
return ret;
934935

935936
do_alloc:
936-
iomap->addr = IOMAP_NULL_ADDR;
937-
iomap->type = IOMAP_HOLE;
938937
if (flags & IOMAP_REPORT) {
939938
if (pos >= size)
940939
ret = -ENOENT;
@@ -956,6 +955,9 @@ static int gfs2_iomap_get(struct inode *inode, loff_t pos, loff_t length,
956955
if (pos < size && height == ip->i_height)
957956
ret = gfs2_hole_size(inode, lblock, len, mp, iomap);
958957
}
958+
hole_found:
959+
iomap->addr = IOMAP_NULL_ADDR;
960+
iomap->type = IOMAP_HOLE;
959961
goto out;
960962
}
961963

fs/gfs2/glock.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -613,7 +613,7 @@ __acquires(&gl->gl_lockref.lock)
613613
fs_err(sdp, "Error %d syncing glock \n", ret);
614614
gfs2_dump_glock(NULL, gl, true);
615615
}
616-
return;
616+
goto skip_inval;
617617
}
618618
}
619619
if (test_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags)) {
@@ -633,6 +633,7 @@ __acquires(&gl->gl_lockref.lock)
633633
clear_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags);
634634
}
635635

636+
skip_inval:
636637
gfs2_glock_hold(gl);
637638
/*
638639
* Check for an error encountered since we called go_sync and go_inval.
@@ -722,9 +723,6 @@ __acquires(&gl->gl_lockref.lock)
722723
goto out_unlock;
723724
if (nonblock)
724725
goto out_sched;
725-
smp_mb();
726-
if (atomic_read(&gl->gl_revokes) != 0)
727-
goto out_sched;
728726
set_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags);
729727
GLOCK_BUG_ON(gl, gl->gl_demote_state == LM_ST_EXCLUSIVE);
730728
gl->gl_target = gl->gl_demote_state;

fs/gfs2/inode.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -622,7 +622,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
622622
error = finish_no_open(file, NULL);
623623
}
624624
gfs2_glock_dq_uninit(ghs);
625-
return error;
625+
goto fail;
626626
} else if (error != -ENOENT) {
627627
goto fail_gunlock;
628628
}
@@ -764,9 +764,11 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
764764
error = finish_open(file, dentry, gfs2_open_common);
765765
}
766766
gfs2_glock_dq_uninit(ghs);
767+
gfs2_qa_put(ip);
767768
gfs2_glock_dq_uninit(ghs + 1);
768769
clear_bit(GLF_INODE_CREATING, &io_gl->gl_flags);
769770
gfs2_glock_put(io_gl);
771+
gfs2_qa_put(dip);
770772
return error;
771773

772774
fail_gunlock3:
@@ -776,7 +778,6 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
776778
clear_bit(GLF_INODE_CREATING, &io_gl->gl_flags);
777779
gfs2_glock_put(io_gl);
778780
fail_free_inode:
779-
gfs2_qa_put(ip);
780781
if (ip->i_gl) {
781782
glock_clear_object(ip->i_gl, ip);
782783
gfs2_glock_put(ip->i_gl);
@@ -1005,7 +1006,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
10051006
out_child:
10061007
gfs2_glock_dq(ghs);
10071008
out_parent:
1008-
gfs2_qa_put(ip);
1009+
gfs2_qa_put(dip);
10091010
gfs2_holder_uninit(ghs);
10101011
gfs2_holder_uninit(ghs + 1);
10111012
return error;

fs/gfs2/log.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -669,13 +669,13 @@ void gfs2_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
669669
struct buffer_head *bh = bd->bd_bh;
670670
struct gfs2_glock *gl = bd->bd_gl;
671671

672+
sdp->sd_log_num_revoke++;
673+
if (atomic_inc_return(&gl->gl_revokes) == 1)
674+
gfs2_glock_hold(gl);
672675
bh->b_private = NULL;
673676
bd->bd_blkno = bh->b_blocknr;
674677
gfs2_remove_from_ail(bd); /* drops ref on bh */
675678
bd->bd_bh = NULL;
676-
sdp->sd_log_num_revoke++;
677-
if (atomic_inc_return(&gl->gl_revokes) == 1)
678-
gfs2_glock_hold(gl);
679679
set_bit(GLF_LFLUSH, &gl->gl_flags);
680680
list_add(&bd->bd_list, &sdp->sd_log_revokes);
681681
}
@@ -1131,6 +1131,10 @@ int gfs2_logd(void *data)
11311131

11321132
while (!kthread_should_stop()) {
11331133

1134+
if (gfs2_withdrawn(sdp)) {
1135+
msleep_interruptible(HZ);
1136+
continue;
1137+
}
11341138
/* Check for errors writing to the journal */
11351139
if (sdp->sd_log_error) {
11361140
gfs2_lm(sdp,
@@ -1139,6 +1143,7 @@ int gfs2_logd(void *data)
11391143
"prevent further damage.\n",
11401144
sdp->sd_fsname, sdp->sd_log_error);
11411145
gfs2_withdraw(sdp);
1146+
continue;
11421147
}
11431148

11441149
did_flush = false;

fs/gfs2/lops.c

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ static struct bio *gfs2_log_alloc_bio(struct gfs2_sbd *sdp, u64 blkno,
263263
struct super_block *sb = sdp->sd_vfs;
264264
struct bio *bio = bio_alloc(GFP_NOIO, BIO_MAX_PAGES);
265265

266-
bio->bi_iter.bi_sector = blkno << (sb->s_blocksize_bits - 9);
266+
bio->bi_iter.bi_sector = blkno << sdp->sd_fsb2bb_shift;
267267
bio_set_dev(bio, sb->s_bdev);
268268
bio->bi_end_io = end_io;
269269
bio->bi_private = sdp;
@@ -509,7 +509,7 @@ int gfs2_find_jhead(struct gfs2_jdesc *jd, struct gfs2_log_header_host *head,
509509
unsigned int bsize = sdp->sd_sb.sb_bsize, off;
510510
unsigned int bsize_shift = sdp->sd_sb.sb_bsize_shift;
511511
unsigned int shift = PAGE_SHIFT - bsize_shift;
512-
unsigned int readahead_blocks = BIO_MAX_PAGES << shift;
512+
unsigned int max_bio_size = 2 * 1024 * 1024;
513513
struct gfs2_journal_extent *je;
514514
int sz, ret = 0;
515515
struct bio *bio = NULL;
@@ -537,12 +537,17 @@ int gfs2_find_jhead(struct gfs2_jdesc *jd, struct gfs2_log_header_host *head,
537537
off = 0;
538538
}
539539

540-
if (!bio || (bio_chained && !off)) {
540+
if (!bio || (bio_chained && !off) ||
541+
bio->bi_iter.bi_size >= max_bio_size) {
541542
/* start new bio */
542543
} else {
543-
sz = bio_add_page(bio, page, bsize, off);
544-
if (sz == bsize)
545-
goto block_added;
544+
sector_t sector = dblock << sdp->sd_fsb2bb_shift;
545+
546+
if (bio_end_sector(bio) == sector) {
547+
sz = bio_add_page(bio, page, bsize, off);
548+
if (sz == bsize)
549+
goto block_added;
550+
}
546551
if (off) {
547552
unsigned int blocks =
548553
(PAGE_SIZE - off) >> bsize_shift;
@@ -568,7 +573,7 @@ int gfs2_find_jhead(struct gfs2_jdesc *jd, struct gfs2_log_header_host *head,
568573
off += bsize;
569574
if (off == PAGE_SIZE)
570575
page = NULL;
571-
if (blocks_submitted < blocks_read + readahead_blocks) {
576+
if (blocks_submitted < 2 * max_bio_size >> bsize_shift) {
572577
/* Keep at least one bio in flight */
573578
continue;
574579
}

fs/gfs2/meta_io.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno, int flags,
252252
int num = 0;
253253

254254
if (unlikely(gfs2_withdrawn(sdp)) &&
255-
(!sdp->sd_jdesc || (blkno != sdp->sd_jdesc->jd_no_addr))) {
255+
(!sdp->sd_jdesc || gl != sdp->sd_jinode_gl)) {
256256
*bhp = NULL;
257257
return -EIO;
258258
}

fs/gfs2/quota.c

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1051,8 +1051,7 @@ int gfs2_quota_lock(struct gfs2_inode *ip, kuid_t uid, kgid_t gid)
10511051
u32 x;
10521052
int error = 0;
10531053

1054-
if (capable(CAP_SYS_RESOURCE) ||
1055-
sdp->sd_args.ar_quota != GFS2_QUOTA_ON)
1054+
if (sdp->sd_args.ar_quota != GFS2_QUOTA_ON)
10561055
return 0;
10571056

10581057
error = gfs2_quota_hold(ip, uid, gid);
@@ -1125,7 +1124,7 @@ void gfs2_quota_unlock(struct gfs2_inode *ip)
11251124
int found;
11261125

11271126
if (!test_and_clear_bit(GIF_QD_LOCKED, &ip->i_flags))
1128-
goto out;
1127+
return;
11291128

11301129
for (x = 0; x < ip->i_qadata->qa_qd_num; x++) {
11311130
struct gfs2_quota_data *qd;
@@ -1162,7 +1161,6 @@ void gfs2_quota_unlock(struct gfs2_inode *ip)
11621161
qd_unlock(qda[x]);
11631162
}
11641163

1165-
out:
11661164
gfs2_quota_unhold(ip);
11671165
}
11681166

@@ -1210,9 +1208,6 @@ int gfs2_quota_check(struct gfs2_inode *ip, kuid_t uid, kgid_t gid,
12101208
if (!test_bit(GIF_QD_LOCKED, &ip->i_flags))
12111209
return 0;
12121210

1213-
if (sdp->sd_args.ar_quota != GFS2_QUOTA_ON)
1214-
return 0;
1215-
12161211
for (x = 0; x < ip->i_qadata->qa_qd_num; x++) {
12171212
qd = ip->i_qadata->qa_qd[x];
12181213

@@ -1270,7 +1265,9 @@ void gfs2_quota_change(struct gfs2_inode *ip, s64 change,
12701265
if (ip->i_diskflags & GFS2_DIF_SYSTEM)
12711266
return;
12721267

1273-
BUG_ON(ip->i_qadata->qa_ref <= 0);
1268+
if (gfs2_assert_withdraw(sdp, ip->i_qadata &&
1269+
ip->i_qadata->qa_ref > 0))
1270+
return;
12741271
for (x = 0; x < ip->i_qadata->qa_qd_num; x++) {
12751272
qd = ip->i_qadata->qa_qd[x];
12761273

fs/gfs2/quota.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ static inline int gfs2_quota_lock_check(struct gfs2_inode *ip,
4444
int ret;
4545

4646
ap->allowed = UINT_MAX; /* Assume we are permitted a whole lot */
47-
if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF)
47+
if (capable(CAP_SYS_RESOURCE) ||
48+
sdp->sd_args.ar_quota == GFS2_QUOTA_OFF)
4849
return 0;
4950
ret = gfs2_quota_lock(ip, NO_UID_QUOTA_CHANGE, NO_GID_QUOTA_CHANGE);
5051
if (ret)

fs/gfs2/super.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1404,7 +1404,6 @@ static void gfs2_evict_inode(struct inode *inode)
14041404
if (ip->i_qadata)
14051405
gfs2_assert_warn(sdp, ip->i_qadata->qa_ref == 0);
14061406
gfs2_rs_delete(ip, NULL);
1407-
gfs2_qa_put(ip);
14081407
gfs2_ordered_del_inode(ip);
14091408
clear_inode(inode);
14101409
gfs2_dir_hash_inval(ip);

fs/gfs2/util.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,12 @@ static void signal_our_withdraw(struct gfs2_sbd *sdp)
119119
if (!sb_rdonly(sdp->sd_vfs))
120120
ret = gfs2_make_fs_ro(sdp);
121121

122+
if (sdp->sd_lockstruct.ls_ops->lm_lock == NULL) { /* lock_nolock */
123+
if (!ret)
124+
ret = -EIO;
125+
clear_bit(SDF_WITHDRAW_RECOVERY, &sdp->sd_flags);
126+
goto skip_recovery;
127+
}
122128
/*
123129
* Drop the glock for our journal so another node can recover it.
124130
*/
@@ -159,10 +165,6 @@ static void signal_our_withdraw(struct gfs2_sbd *sdp)
159165
wait_on_bit(&gl->gl_flags, GLF_FREEING, TASK_UNINTERRUPTIBLE);
160166
}
161167

162-
if (sdp->sd_lockstruct.ls_ops->lm_lock == NULL) { /* lock_nolock */
163-
clear_bit(SDF_WITHDRAW_RECOVERY, &sdp->sd_flags);
164-
goto skip_recovery;
165-
}
166168
/*
167169
* Dequeue the "live" glock, but keep a reference so it's never freed.
168170
*/

0 commit comments

Comments
 (0)