diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2020-10-23 11:47:42 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2020-10-23 11:47:42 -0700 |
commit | 0adc313c4f20639f7e235b8d6719d96a2024cf91 (patch) | |
tree | 3100bd1b91229bc53a8eb838a1788299837bb056 /fs/gfs2/bmap.c | |
parent | 0613ed91901b5f87afcd28b4560fb0aa37a0db13 (diff) | |
parent | bedb0f056faa94e953e7b3da5a77d25e0008364b (diff) |
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
...
Diffstat (limited to 'fs/gfs2/bmap.c')
-rw-r--r-- | fs/gfs2/bmap.c | 62 |
1 files changed, 43 insertions, 19 deletions
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index 0f69fbd4af66..8dff9cbd0a87 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c @@ -56,7 +56,6 @@ static int gfs2_unstuffer_page(struct gfs2_inode *ip, struct buffer_head *dibh, u64 block, struct page *page) { struct inode *inode = &ip->i_inode; - struct buffer_head *bh; int release = 0; if (!page || page->index) { @@ -80,20 +79,21 @@ static int gfs2_unstuffer_page(struct gfs2_inode *ip, struct buffer_head *dibh, SetPageUptodate(page); } - if (!page_has_buffers(page)) - create_empty_buffers(page, BIT(inode->i_blkbits), - BIT(BH_Uptodate)); + if (gfs2_is_jdata(ip)) { + struct buffer_head *bh; - bh = page_buffers(page); + if (!page_has_buffers(page)) + create_empty_buffers(page, BIT(inode->i_blkbits), + BIT(BH_Uptodate)); - if (!buffer_mapped(bh)) - map_bh(bh, inode->i_sb, block); + bh = page_buffers(page); + if (!buffer_mapped(bh)) + map_bh(bh, inode->i_sb, block); - set_buffer_uptodate(bh); - if (gfs2_is_jdata(ip)) + set_buffer_uptodate(bh); gfs2_trans_add_data(ip->i_gl, bh); - else { - mark_buffer_dirty(bh); + } else { + set_page_dirty(page); gfs2_ordered_add_inode(ip); } @@ -1158,7 +1158,8 @@ static int gfs2_iomap_begin(struct inode *inode, loff_t pos, loff_t length, struct metapath mp = { .mp_aheight = 1, }; int ret; - iomap->flags |= IOMAP_F_BUFFER_HEAD; + if (gfs2_is_jdata(ip)) + iomap->flags |= IOMAP_F_BUFFER_HEAD; trace_gfs2_iomap_start(ip, pos, length, flags); if (gfs2_iomap_need_write_lock(flags)) { @@ -1291,6 +1292,7 @@ int gfs2_block_map(struct inode *inode, sector_t lblock, loff_t length = bh_map->b_size; struct metapath mp = { .mp_aheight = 1, }; struct iomap iomap = { }; + int flags = create ? IOMAP_WRITE : 0; int ret; clear_buffer_mapped(bh_map); @@ -1298,15 +1300,14 @@ int gfs2_block_map(struct inode *inode, sector_t lblock, clear_buffer_boundary(bh_map); trace_gfs2_bmap(ip, bh_map, lblock, create, 1); - if (create) { - ret = gfs2_iomap_get(inode, pos, length, IOMAP_WRITE, &iomap, &mp); - if (!ret && iomap.type == IOMAP_HOLE) + ret = gfs2_iomap_get(inode, pos, length, flags, &iomap, &mp); + if (!ret && iomap.type == IOMAP_HOLE) { + if (create) ret = gfs2_iomap_alloc(inode, &iomap, &mp); - release_metapath(&mp); - } else { - ret = gfs2_iomap_get(inode, pos, length, 0, &iomap, &mp); - release_metapath(&mp); + else + ret = -ENODATA; } + release_metapath(&mp); if (ret) goto out; @@ -2518,3 +2519,26 @@ out: gfs2_trans_end(sdp); return error; } + +static int gfs2_map_blocks(struct iomap_writepage_ctx *wpc, struct inode *inode, + loff_t offset) +{ + struct metapath mp = { .mp_aheight = 1, }; + int ret; + + if (WARN_ON_ONCE(gfs2_is_stuffed(GFS2_I(inode)))) + return -EIO; + + if (offset >= wpc->iomap.offset && + offset < wpc->iomap.offset + wpc->iomap.length) + return 0; + + memset(&wpc->iomap, 0, sizeof(wpc->iomap)); + ret = gfs2_iomap_get(inode, offset, INT_MAX, 0, &wpc->iomap, &mp); + release_metapath(&mp); + return ret; +} + +const struct iomap_writeback_ops gfs2_writeback_ops = { + .map_blocks = gfs2_map_blocks, +}; |