Skip to content

Commit 8c2618a

Browse files
committed
Merge tag 'gfs2-for-5.9' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2
Pull gfs2 updates from Andreas Gruenbacher: - Make sure transactions won't be started recursively in gfs2_block_zero_range (bug introduced in 5.4 when switching to iomap_zero_range) - Fix a glock holder refcount leak introduced in the iopen glock locking scheme rework merged in 5.8. - A few other small improvements (debugging, stack usage, comment fixes). * tag 'gfs2-for-5.9' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2: gfs2: When gfs2_dirty_inode gets a glock error, dump the glock gfs2: Never call gfs2_block_zero_range with an open transaction gfs2: print details on transactions that aren't properly ended gfs2: Fix inaccurate comment fs: Fix typo in comment gfs2: Fix refcount leak in gfs2_glock_poke gfs2: Pass glock holder to gfs2_file_direct_{read,write} gfs2: Add some flags missing from glock output
2 parents 163c3e3 + e28c02b commit 8c2618a

File tree

7 files changed

+82
-62
lines changed

7 files changed

+82
-62
lines changed

fs/gfs2/bmap.c

Lines changed: 39 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1351,9 +1351,15 @@ int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsi
13511351
return ret;
13521352
}
13531353

1354+
/*
1355+
* NOTE: Never call gfs2_block_zero_range with an open transaction because it
1356+
* uses iomap write to perform its actions, which begin their own transactions
1357+
* (iomap_begin, page_prepare, etc.)
1358+
*/
13541359
static int gfs2_block_zero_range(struct inode *inode, loff_t from,
13551360
unsigned int length)
13561361
{
1362+
BUG_ON(current->journal_info);
13571363
return iomap_zero_range(inode, from, length, NULL, &gfs2_iomap_ops);
13581364
}
13591365

@@ -1414,6 +1420,16 @@ static int trunc_start(struct inode *inode, u64 newsize)
14141420
u64 oldsize = inode->i_size;
14151421
int error;
14161422

1423+
if (!gfs2_is_stuffed(ip)) {
1424+
unsigned int blocksize = i_blocksize(inode);
1425+
unsigned int offs = newsize & (blocksize - 1);
1426+
if (offs) {
1427+
error = gfs2_block_zero_range(inode, newsize,
1428+
blocksize - offs);
1429+
if (error)
1430+
return error;
1431+
}
1432+
}
14171433
if (journaled)
14181434
error = gfs2_trans_begin(sdp, RES_DINODE + RES_JDATA, GFS2_JTRUNC_REVOKES);
14191435
else
@@ -1427,19 +1443,10 @@ static int trunc_start(struct inode *inode, u64 newsize)
14271443

14281444
gfs2_trans_add_meta(ip->i_gl, dibh);
14291445

1430-
if (gfs2_is_stuffed(ip)) {
1446+
if (gfs2_is_stuffed(ip))
14311447
gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode) + newsize);
1432-
} else {
1433-
unsigned int blocksize = i_blocksize(inode);
1434-
unsigned int offs = newsize & (blocksize - 1);
1435-
if (offs) {
1436-
error = gfs2_block_zero_range(inode, newsize,
1437-
blocksize - offs);
1438-
if (error)
1439-
goto out;
1440-
}
1448+
else
14411449
ip->i_diskflags |= GFS2_DIF_TRUNC_IN_PROG;
1442-
}
14431450

14441451
i_size_write(inode, newsize);
14451452
ip->i_inode.i_mtime = ip->i_inode.i_ctime = current_time(&ip->i_inode);
@@ -2448,25 +2455,7 @@ int __gfs2_punch_hole(struct file *file, loff_t offset, loff_t length)
24482455
loff_t start, end;
24492456
int error;
24502457

2451-
start = round_down(offset, blocksize);
2452-
end = round_up(offset + length, blocksize) - 1;
2453-
error = filemap_write_and_wait_range(inode->i_mapping, start, end);
2454-
if (error)
2455-
return error;
2456-
2457-
if (gfs2_is_jdata(ip))
2458-
error = gfs2_trans_begin(sdp, RES_DINODE + 2 * RES_JDATA,
2459-
GFS2_JTRUNC_REVOKES);
2460-
else
2461-
error = gfs2_trans_begin(sdp, RES_DINODE, 0);
2462-
if (error)
2463-
return error;
2464-
2465-
if (gfs2_is_stuffed(ip)) {
2466-
error = stuffed_zero_range(inode, offset, length);
2467-
if (error)
2468-
goto out;
2469-
} else {
2458+
if (!gfs2_is_stuffed(ip)) {
24702459
unsigned int start_off, end_len;
24712460

24722461
start_off = offset & (blocksize - 1);
@@ -2489,6 +2478,26 @@ int __gfs2_punch_hole(struct file *file, loff_t offset, loff_t length)
24892478
}
24902479
}
24912480

2481+
start = round_down(offset, blocksize);
2482+
end = round_up(offset + length, blocksize) - 1;
2483+
error = filemap_write_and_wait_range(inode->i_mapping, start, end);
2484+
if (error)
2485+
return error;
2486+
2487+
if (gfs2_is_jdata(ip))
2488+
error = gfs2_trans_begin(sdp, RES_DINODE + 2 * RES_JDATA,
2489+
GFS2_JTRUNC_REVOKES);
2490+
else
2491+
error = gfs2_trans_begin(sdp, RES_DINODE, 0);
2492+
if (error)
2493+
return error;
2494+
2495+
if (gfs2_is_stuffed(ip)) {
2496+
error = stuffed_zero_range(inode, offset, length);
2497+
if (error)
2498+
goto out;
2499+
}
2500+
24922501
if (gfs2_is_jdata(ip)) {
24932502
BUG_ON(!current->journal_info);
24942503
gfs2_journaled_truncate_range(inode, offset, length);

fs/gfs2/file.c

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -781,39 +781,39 @@ static int gfs2_fsync(struct file *file, loff_t start, loff_t end,
781781
return ret ? ret : ret1;
782782
}
783783

784-
static ssize_t gfs2_file_direct_read(struct kiocb *iocb, struct iov_iter *to)
784+
static ssize_t gfs2_file_direct_read(struct kiocb *iocb, struct iov_iter *to,
785+
struct gfs2_holder *gh)
785786
{
786787
struct file *file = iocb->ki_filp;
787788
struct gfs2_inode *ip = GFS2_I(file->f_mapping->host);
788789
size_t count = iov_iter_count(to);
789-
struct gfs2_holder gh;
790790
ssize_t ret;
791791

792792
if (!count)
793793
return 0; /* skip atime */
794794

795-
gfs2_holder_init(ip->i_gl, LM_ST_DEFERRED, 0, &gh);
796-
ret = gfs2_glock_nq(&gh);
795+
gfs2_holder_init(ip->i_gl, LM_ST_DEFERRED, 0, gh);
796+
ret = gfs2_glock_nq(gh);
797797
if (ret)
798798
goto out_uninit;
799799

800800
ret = iomap_dio_rw(iocb, to, &gfs2_iomap_ops, NULL,
801801
is_sync_kiocb(iocb));
802802

803-
gfs2_glock_dq(&gh);
803+
gfs2_glock_dq(gh);
804804
out_uninit:
805-
gfs2_holder_uninit(&gh);
805+
gfs2_holder_uninit(gh);
806806
return ret;
807807
}
808808

809-
static ssize_t gfs2_file_direct_write(struct kiocb *iocb, struct iov_iter *from)
809+
static ssize_t gfs2_file_direct_write(struct kiocb *iocb, struct iov_iter *from,
810+
struct gfs2_holder *gh)
810811
{
811812
struct file *file = iocb->ki_filp;
812813
struct inode *inode = file->f_mapping->host;
813814
struct gfs2_inode *ip = GFS2_I(inode);
814815
size_t len = iov_iter_count(from);
815816
loff_t offset = iocb->ki_pos;
816-
struct gfs2_holder gh;
817817
ssize_t ret;
818818

819819
/*
@@ -824,8 +824,8 @@ static ssize_t gfs2_file_direct_write(struct kiocb *iocb, struct iov_iter *from)
824824
* unfortunately, have the option of only flushing a range like the
825825
* VFS does.
826826
*/
827-
gfs2_holder_init(ip->i_gl, LM_ST_DEFERRED, 0, &gh);
828-
ret = gfs2_glock_nq(&gh);
827+
gfs2_holder_init(ip->i_gl, LM_ST_DEFERRED, 0, gh);
828+
ret = gfs2_glock_nq(gh);
829829
if (ret)
830830
goto out_uninit;
831831

@@ -838,9 +838,9 @@ static ssize_t gfs2_file_direct_write(struct kiocb *iocb, struct iov_iter *from)
838838
if (ret == -ENOTBLK)
839839
ret = 0;
840840
out:
841-
gfs2_glock_dq(&gh);
841+
gfs2_glock_dq(gh);
842842
out_uninit:
843-
gfs2_holder_uninit(&gh);
843+
gfs2_holder_uninit(gh);
844844
return ret;
845845
}
846846

@@ -852,7 +852,7 @@ static ssize_t gfs2_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
852852
ssize_t ret;
853853

854854
if (iocb->ki_flags & IOCB_DIRECT) {
855-
ret = gfs2_file_direct_read(iocb, to);
855+
ret = gfs2_file_direct_read(iocb, to, &gh);
856856
if (likely(ret != -ENOTBLK))
857857
return ret;
858858
iocb->ki_flags &= ~IOCB_DIRECT;
@@ -901,13 +901,12 @@ static ssize_t gfs2_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
901901
struct file *file = iocb->ki_filp;
902902
struct inode *inode = file_inode(file);
903903
struct gfs2_inode *ip = GFS2_I(inode);
904+
struct gfs2_holder gh;
904905
ssize_t ret;
905906

906907
gfs2_size_hint(file, iocb->ki_pos, iov_iter_count(from));
907908

908909
if (iocb->ki_flags & IOCB_APPEND) {
909-
struct gfs2_holder gh;
910-
911910
ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, 0, &gh);
912911
if (ret)
913912
return ret;
@@ -931,7 +930,7 @@ static ssize_t gfs2_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
931930
struct address_space *mapping = file->f_mapping;
932931
ssize_t buffered, ret2;
933932

934-
ret = gfs2_file_direct_write(iocb, from);
933+
ret = gfs2_file_direct_write(iocb, from, &gh);
935934
if (ret < 0 || !iov_iter_count(from))
936935
goto out_unlock;
937936

fs/gfs2/glock.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -790,9 +790,11 @@ static void gfs2_glock_poke(struct gfs2_glock *gl)
790790
struct gfs2_holder gh;
791791
int error;
792792

793-
error = gfs2_glock_nq_init(gl, LM_ST_SHARED, flags, &gh);
793+
gfs2_holder_init(gl, LM_ST_SHARED, flags, &gh);
794+
error = gfs2_glock_nq(&gh);
794795
if (!error)
795796
gfs2_glock_dq(&gh);
797+
gfs2_holder_uninit(&gh);
796798
}
797799

798800
static bool gfs2_try_evict(struct gfs2_glock *gl)
@@ -2106,6 +2108,12 @@ static const char *gflags2str(char *buf, const struct gfs2_glock *gl)
21062108
*p++ = 'o';
21072109
if (test_bit(GLF_BLOCKING, gflags))
21082110
*p++ = 'b';
2111+
if (test_bit(GLF_INODE_CREATING, gflags))
2112+
*p++ = 'c';
2113+
if (test_bit(GLF_PENDING_DELETE, gflags))
2114+
*p++ = 'P';
2115+
if (test_bit(GLF_FREEING, gflags))
2116+
*p++ = 'x';
21092117
*p = 0;
21102118
return buf;
21112119
}

fs/gfs2/log.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1092,7 +1092,7 @@ static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
10921092
* or the total number of used blocks (pinned blocks plus AIL blocks)
10931093
* is greater than thresh2.
10941094
*
1095-
* At mount time thresh1 is 1/3rd of journal size, thresh2 is 2/3rd of
1095+
* At mount time thresh1 is 2/5ths of journal size, thresh2 is 4/5ths of
10961096
* journal size.
10971097
*
10981098
* Returns: errno

fs/gfs2/super.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,7 @@ static void gfs2_dirty_inode(struct inode *inode, int flags)
566566
ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
567567
if (ret) {
568568
fs_err(sdp, "dirty_inode: glock %d\n", ret);
569+
gfs2_dump_glock(NULL, ip->i_gl, true);
569570
return;
570571
}
571572
need_unlock = 1;

fs/gfs2/trans.c

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,28 @@
2525
#include "util.h"
2626
#include "trace_gfs2.h"
2727

28+
static void gfs2_print_trans(struct gfs2_sbd *sdp, const struct gfs2_trans *tr)
29+
{
30+
fs_warn(sdp, "Transaction created at: %pSR\n", (void *)tr->tr_ip);
31+
fs_warn(sdp, "blocks=%u revokes=%u reserved=%u touched=%u\n",
32+
tr->tr_blocks, tr->tr_revokes, tr->tr_reserved,
33+
test_bit(TR_TOUCHED, &tr->tr_flags));
34+
fs_warn(sdp, "Buf %u/%u Databuf %u/%u Revoke %u/%u\n",
35+
tr->tr_num_buf_new, tr->tr_num_buf_rm,
36+
tr->tr_num_databuf_new, tr->tr_num_databuf_rm,
37+
tr->tr_num_revoke, tr->tr_num_revoke_rm);
38+
}
39+
2840
int gfs2_trans_begin(struct gfs2_sbd *sdp, unsigned int blocks,
2941
unsigned int revokes)
3042
{
3143
struct gfs2_trans *tr;
3244
int error;
3345

34-
BUG_ON(current->journal_info);
46+
if (current->journal_info) {
47+
gfs2_print_trans(sdp, current->journal_info);
48+
BUG();
49+
}
3550
BUG_ON(blocks == 0 && revokes == 0);
3651

3752
if (!test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags))
@@ -72,18 +87,6 @@ int gfs2_trans_begin(struct gfs2_sbd *sdp, unsigned int blocks,
7287
return error;
7388
}
7489

75-
static void gfs2_print_trans(struct gfs2_sbd *sdp, const struct gfs2_trans *tr)
76-
{
77-
fs_warn(sdp, "Transaction created at: %pSR\n", (void *)tr->tr_ip);
78-
fs_warn(sdp, "blocks=%u revokes=%u reserved=%u touched=%u\n",
79-
tr->tr_blocks, tr->tr_revokes, tr->tr_reserved,
80-
test_bit(TR_TOUCHED, &tr->tr_flags));
81-
fs_warn(sdp, "Buf %u/%u Databuf %u/%u Revoke %u/%u\n",
82-
tr->tr_num_buf_new, tr->tr_num_buf_rm,
83-
tr->tr_num_databuf_new, tr->tr_num_databuf_rm,
84-
tr->tr_num_revoke, tr->tr_num_revoke_rm);
85-
}
86-
8790
void gfs2_trans_end(struct gfs2_sbd *sdp)
8891
{
8992
struct gfs2_trans *tr = current->journal_info;

include/linux/fs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2650,7 +2650,7 @@ static inline void filemap_set_wb_err(struct address_space *mapping, int err)
26502650
}
26512651

26522652
/**
2653-
* filemap_check_wb_error - has an error occurred since the mark was sampled?
2653+
* filemap_check_wb_err - has an error occurred since the mark was sampled?
26542654
* @mapping: mapping to check for writeback errors
26552655
* @since: previously-sampled errseq_t
26562656
*

0 commit comments

Comments
 (0)