Skip to content

Commit 0adc313

Browse files
committed
Merge tag 'gfs2-for-5.10' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2
Pull gfs2 updates from Andreas Gruenbacher: - Use iomap for non-journaled buffered I/O. This largely eliminates buffer heads on filesystems where the block size matches the page size. Many thanks to Christoph Hellwig for this patch! - Fixes for some more journaled data filesystem bugs, found by running xfstests with data journaling on for all files (chattr +j $MNT) (Bob Peterson) - gfs2_evict_inode refactoring (Bob Peterson) - Use the statfs data in the journal during recovery instead of reading it in from the local statfs inodes (Abhi Das) - Several other minor fixes by various people * tag 'gfs2-for-5.10' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2: (30 commits) gfs2: Recover statfs info in journal head gfs2: lookup local statfs inodes prior to journal recovery gfs2: Add fields for statfs info in struct gfs2_log_header_host gfs2: Ignore subsequent errors after withdraw in rgrp_go_sync gfs2: Eliminate gl_vm gfs2: Only access gl_delete for iopen glocks gfs2: Fix comments to glock_hash_walk gfs2: eliminate GLF_QUEUED flag in favor of list_empty(gl_holders) gfs2: Ignore journal log writes for jdata holes gfs2: simplify gfs2_block_map gfs2: Only set PageChecked if we have a transaction gfs2: don't lock sd_ail_lock in gfs2_releasepage gfs2: make gfs2_ail1_empty_one return the count of active items gfs2: Wipe jdata and ail1 in gfs2_journal_wipe, formerly gfs2_meta_wipe gfs2: enhance log_blocks trace point to show log blocks free gfs2: add missing log_blocks trace points in gfs2_write_revokes gfs2: rename gfs2_write_full_page to gfs2_write_jdata_page, remove parm gfs2: add validation checks for size of superblock gfs2: use-after-free in sysfs deregistration gfs2: Fix NULL pointer dereference in gfs2_rgrp_dump ...
2 parents 0613ed9 + bedb0f0 commit 0adc313

22 files changed

Lines changed: 675 additions & 301 deletions

fs/gfs2/aops.c

Lines changed: 36 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -91,22 +91,13 @@ static int gfs2_writepage(struct page *page, struct writeback_control *wbc)
9191
struct inode *inode = page->mapping->host;
9292
struct gfs2_inode *ip = GFS2_I(inode);
9393
struct gfs2_sbd *sdp = GFS2_SB(inode);
94-
loff_t i_size = i_size_read(inode);
95-
pgoff_t end_index = i_size >> PAGE_SHIFT;
96-
unsigned offset;
94+
struct iomap_writepage_ctx wpc = { };
9795

9896
if (gfs2_assert_withdraw(sdp, gfs2_glock_is_held_excl(ip->i_gl)))
9997
goto out;
10098
if (current->journal_info)
10199
goto redirty;
102-
/* Is the page fully outside i_size? (truncate in progress) */
103-
offset = i_size & (PAGE_SIZE-1);
104-
if (page->index > end_index || (page->index == end_index && !offset)) {
105-
page->mapping->a_ops->invalidatepage(page, 0, PAGE_SIZE);
106-
goto out;
107-
}
108-
109-
return nobh_writepage(page, gfs2_get_block_noalloc, wbc);
100+
return iomap_writepage(page, wbc, &wpc, &gfs2_writeback_ops);
110101

111102
redirty:
112103
redirty_page_for_writepage(wbc, page);
@@ -115,11 +106,16 @@ static int gfs2_writepage(struct page *page, struct writeback_control *wbc)
115106
return 0;
116107
}
117108

118-
/* This is the same as calling block_write_full_page, but it also
109+
/**
110+
* gfs2_write_jdata_page - gfs2 jdata-specific version of block_write_full_page
111+
* @page: The page to write
112+
* @wbc: The writeback control
113+
*
114+
* This is the same as calling block_write_full_page, but it also
119115
* writes pages outside of i_size
120116
*/
121-
static int gfs2_write_full_page(struct page *page, get_block_t *get_block,
122-
struct writeback_control *wbc)
117+
static int gfs2_write_jdata_page(struct page *page,
118+
struct writeback_control *wbc)
123119
{
124120
struct inode * const inode = page->mapping->host;
125121
loff_t i_size = i_size_read(inode);
@@ -137,7 +133,7 @@ static int gfs2_write_full_page(struct page *page, get_block_t *get_block,
137133
if (page->index == end_index && offset)
138134
zero_user_segment(page, offset, PAGE_SIZE);
139135

140-
return __block_write_full_page(inode, page, get_block, wbc,
136+
return __block_write_full_page(inode, page, gfs2_get_block_noalloc, wbc,
141137
end_buffer_async_write);
142138
}
143139

@@ -166,7 +162,7 @@ static int __gfs2_jdata_writepage(struct page *page, struct writeback_control *w
166162
}
167163
gfs2_page_add_databufs(ip, page, 0, sdp->sd_vfs->s_blocksize);
168164
}
169-
return gfs2_write_full_page(page, gfs2_get_block_noalloc, wbc);
165+
return gfs2_write_jdata_page(page, wbc);
170166
}
171167

172168
/**
@@ -208,17 +204,18 @@ static int gfs2_writepages(struct address_space *mapping,
208204
struct writeback_control *wbc)
209205
{
210206
struct gfs2_sbd *sdp = gfs2_mapping2sbd(mapping);
211-
int ret = mpage_writepages(mapping, wbc, gfs2_get_block_noalloc);
207+
struct iomap_writepage_ctx wpc = { };
208+
int ret;
212209

213210
/*
214211
* Even if we didn't write any pages here, we might still be holding
215212
* dirty pages in the ail. We forcibly flush the ail because we don't
216213
* want balance_dirty_pages() to loop indefinitely trying to write out
217214
* pages held in the ail that it can't find.
218215
*/
216+
ret = iomap_writepages(mapping, wbc, &wpc, &gfs2_writeback_ops);
219217
if (ret == 0)
220218
set_bit(SDF_FORCE_AIL_FLUSH, &sdp->sd_flags);
221-
222219
return ret;
223220
}
224221

@@ -470,12 +467,13 @@ static int stuffed_readpage(struct gfs2_inode *ip, struct page *page)
470467

471468
static int __gfs2_readpage(void *file, struct page *page)
472469
{
473-
struct gfs2_inode *ip = GFS2_I(page->mapping->host);
474-
struct gfs2_sbd *sdp = GFS2_SB(page->mapping->host);
470+
struct inode *inode = page->mapping->host;
471+
struct gfs2_inode *ip = GFS2_I(inode);
472+
struct gfs2_sbd *sdp = GFS2_SB(inode);
475473
int error;
476474

477-
if (i_blocksize(page->mapping->host) == PAGE_SIZE &&
478-
!page_has_buffers(page)) {
475+
if (!gfs2_is_jdata(ip) ||
476+
(i_blocksize(inode) == PAGE_SIZE && !page_has_buffers(page))) {
479477
error = iomap_readpage(page, &gfs2_iomap_ops);
480478
} else if (gfs2_is_stuffed(ip)) {
481479
error = stuffed_readpage(ip, page);
@@ -563,8 +561,12 @@ static void gfs2_readahead(struct readahead_control *rac)
563561
struct inode *inode = rac->mapping->host;
564562
struct gfs2_inode *ip = GFS2_I(inode);
565563

566-
if (!gfs2_is_stuffed(ip))
564+
if (gfs2_is_stuffed(ip))
565+
;
566+
else if (gfs2_is_jdata(ip))
567567
mpage_readahead(rac, gfs2_block_map);
568+
else
569+
iomap_readahead(rac, &gfs2_iomap_ops);
568570
}
569571

570572
/**
@@ -621,7 +623,8 @@ void adjust_fs_space(struct inode *inode)
621623

622624
static int jdata_set_page_dirty(struct page *page)
623625
{
624-
SetPageChecked(page);
626+
if (current->journal_info)
627+
SetPageChecked(page);
625628
return __set_page_dirty_buffers(page);
626629
}
627630

@@ -663,8 +666,11 @@ static void gfs2_discard(struct gfs2_sbd *sdp, struct buffer_head *bh)
663666
if (bd) {
664667
if (!list_empty(&bd->bd_list) && !buffer_pinned(bh))
665668
list_del_init(&bd->bd_list);
666-
else
669+
else {
670+
spin_lock(&sdp->sd_ail_lock);
667671
gfs2_remove_from_journal(bh, REMOVE_JDATA);
672+
spin_unlock(&sdp->sd_ail_lock);
673+
}
668674
}
669675
bh->b_bdev = NULL;
670676
clear_buffer_mapped(bh);
@@ -736,7 +742,6 @@ int gfs2_releasepage(struct page *page, gfp_t gfp_mask)
736742
*/
737743

738744
gfs2_log_lock(sdp);
739-
spin_lock(&sdp->sd_ail_lock);
740745
head = bh = page_buffers(page);
741746
do {
742747
if (atomic_read(&bh->b_count))
@@ -748,7 +753,6 @@ int gfs2_releasepage(struct page *page, gfp_t gfp_mask)
748753
goto cannot_release;
749754
bh = bh->b_this_page;
750755
} while(bh != head);
751-
spin_unlock(&sdp->sd_ail_lock);
752756

753757
head = bh = page_buffers(page);
754758
do {
@@ -774,7 +778,6 @@ int gfs2_releasepage(struct page *page, gfp_t gfp_mask)
774778
return try_to_free_buffers(page);
775779

776780
cannot_release:
777-
spin_unlock(&sdp->sd_ail_lock);
778781
gfs2_log_unlock(sdp);
779782
return 0;
780783
}
@@ -784,12 +787,13 @@ static const struct address_space_operations gfs2_aops = {
784787
.writepages = gfs2_writepages,
785788
.readpage = gfs2_readpage,
786789
.readahead = gfs2_readahead,
790+
.set_page_dirty = iomap_set_page_dirty,
791+
.releasepage = iomap_releasepage,
792+
.invalidatepage = iomap_invalidatepage,
787793
.bmap = gfs2_bmap,
788-
.invalidatepage = gfs2_invalidatepage,
789-
.releasepage = gfs2_releasepage,
790794
.direct_IO = noop_direct_IO,
791-
.migratepage = buffer_migrate_page,
792-
.is_partially_uptodate = block_is_partially_uptodate,
795+
.migratepage = iomap_migrate_page,
796+
.is_partially_uptodate = iomap_is_partially_uptodate,
793797
.error_remove_page = generic_error_remove_page,
794798
};
795799

fs/gfs2/bmap.c

Lines changed: 43 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ static int gfs2_unstuffer_page(struct gfs2_inode *ip, struct buffer_head *dibh,
5656
u64 block, struct page *page)
5757
{
5858
struct inode *inode = &ip->i_inode;
59-
struct buffer_head *bh;
6059
int release = 0;
6160

6261
if (!page || page->index) {
@@ -80,20 +79,21 @@ static int gfs2_unstuffer_page(struct gfs2_inode *ip, struct buffer_head *dibh,
8079
SetPageUptodate(page);
8180
}
8281

83-
if (!page_has_buffers(page))
84-
create_empty_buffers(page, BIT(inode->i_blkbits),
85-
BIT(BH_Uptodate));
82+
if (gfs2_is_jdata(ip)) {
83+
struct buffer_head *bh;
8684

87-
bh = page_buffers(page);
85+
if (!page_has_buffers(page))
86+
create_empty_buffers(page, BIT(inode->i_blkbits),
87+
BIT(BH_Uptodate));
8888

89-
if (!buffer_mapped(bh))
90-
map_bh(bh, inode->i_sb, block);
89+
bh = page_buffers(page);
90+
if (!buffer_mapped(bh))
91+
map_bh(bh, inode->i_sb, block);
9192

92-
set_buffer_uptodate(bh);
93-
if (gfs2_is_jdata(ip))
93+
set_buffer_uptodate(bh);
9494
gfs2_trans_add_data(ip->i_gl, bh);
95-
else {
96-
mark_buffer_dirty(bh);
95+
} else {
96+
set_page_dirty(page);
9797
gfs2_ordered_add_inode(ip);
9898
}
9999

@@ -1158,7 +1158,8 @@ static int gfs2_iomap_begin(struct inode *inode, loff_t pos, loff_t length,
11581158
struct metapath mp = { .mp_aheight = 1, };
11591159
int ret;
11601160

1161-
iomap->flags |= IOMAP_F_BUFFER_HEAD;
1161+
if (gfs2_is_jdata(ip))
1162+
iomap->flags |= IOMAP_F_BUFFER_HEAD;
11621163

11631164
trace_gfs2_iomap_start(ip, pos, length, flags);
11641165
if (gfs2_iomap_need_write_lock(flags)) {
@@ -1291,22 +1292,22 @@ int gfs2_block_map(struct inode *inode, sector_t lblock,
12911292
loff_t length = bh_map->b_size;
12921293
struct metapath mp = { .mp_aheight = 1, };
12931294
struct iomap iomap = { };
1295+
int flags = create ? IOMAP_WRITE : 0;
12941296
int ret;
12951297

12961298
clear_buffer_mapped(bh_map);
12971299
clear_buffer_new(bh_map);
12981300
clear_buffer_boundary(bh_map);
12991301
trace_gfs2_bmap(ip, bh_map, lblock, create, 1);
13001302

1301-
if (create) {
1302-
ret = gfs2_iomap_get(inode, pos, length, IOMAP_WRITE, &iomap, &mp);
1303-
if (!ret && iomap.type == IOMAP_HOLE)
1303+
ret = gfs2_iomap_get(inode, pos, length, flags, &iomap, &mp);
1304+
if (!ret && iomap.type == IOMAP_HOLE) {
1305+
if (create)
13041306
ret = gfs2_iomap_alloc(inode, &iomap, &mp);
1305-
release_metapath(&mp);
1306-
} else {
1307-
ret = gfs2_iomap_get(inode, pos, length, 0, &iomap, &mp);
1308-
release_metapath(&mp);
1307+
else
1308+
ret = -ENODATA;
13091309
}
1310+
release_metapath(&mp);
13101311
if (ret)
13111312
goto out;
13121313

@@ -2518,3 +2519,26 @@ int __gfs2_punch_hole(struct file *file, loff_t offset, loff_t length)
25182519
gfs2_trans_end(sdp);
25192520
return error;
25202521
}
2522+
2523+
static int gfs2_map_blocks(struct iomap_writepage_ctx *wpc, struct inode *inode,
2524+
loff_t offset)
2525+
{
2526+
struct metapath mp = { .mp_aheight = 1, };
2527+
int ret;
2528+
2529+
if (WARN_ON_ONCE(gfs2_is_stuffed(GFS2_I(inode))))
2530+
return -EIO;
2531+
2532+
if (offset >= wpc->iomap.offset &&
2533+
offset < wpc->iomap.offset + wpc->iomap.length)
2534+
return 0;
2535+
2536+
memset(&wpc->iomap, 0, sizeof(wpc->iomap));
2537+
ret = gfs2_iomap_get(inode, offset, INT_MAX, 0, &wpc->iomap, &mp);
2538+
release_metapath(&mp);
2539+
return ret;
2540+
}
2541+
2542+
const struct iomap_writeback_ops gfs2_writeback_ops = {
2543+
.map_blocks = gfs2_map_blocks,
2544+
};

fs/gfs2/bmap.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ static inline void gfs2_write_calc_reserv(const struct gfs2_inode *ip,
4444
}
4545

4646
extern const struct iomap_ops gfs2_iomap_ops;
47+
extern const struct iomap_writeback_ops gfs2_writeback_ops;
4748

4849
extern int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page);
4950
extern int gfs2_block_map(struct inode *inode, sector_t lblock,

0 commit comments

Comments
 (0)