mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2025-01-19 01:56:21 +07:00
Changes for Linux 5.2:
- Add some extra hooks to the iomap buffered write path to enable gfs2 journalled writes. - SPDX conversion - Various refactoring. -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEUzaAxoMeQq6m2jMV+H93GTRKtOsFAlzMUJsACgkQ+H93GTRK tOsyHxAAjnAAO2ABOt2x9fdsZbuc/3Ox1C0388J21uUOm6lgtKCFm/snVmvC7BMa t9bFOS8Y7RLgHclCkEHy0irsHVVuQl+6XyYrjFaPzkoRnVgViZM5aZGSNkBRiBEM xVAog5IFLTx59NT41B4pn9y361BFwfHiFRsDgtSVNlv8UsbKdpAMBMX9ezjNLgWI H5qJZXfzk5LyNG/jsOe+srwVXsboILvPAiDNP95g2KzrXZMvnf8MsMvAe9cSO9SD ERHn9nX5b4hiwiL12lCl10QOsROmElzP82GHJBctFDzdfOfSRuRZw69lFSzf/2CT xVypJBm7xVBJ7K50x8KlF1aSLqnxHi/wszS6BaowoMtkPbJRx+FC7M8FCnNr5WtF DxJduFBUchbNKt1o2x98Evoqjx6eVp92XsCdjsJ05LQo7cxlwECfYhjruwyg/h16 qdE+6KmUwOOiqMQ6Z8kvrejpuIq2rcHlJydDojN+lIbbzmtge8ob/q/A1J8FT6k9 pzVW3y1h7yvgi0ClaQu2DCfx2is2Bd4y0w1b/Y/0jkV9aVbtPqt0akqcaLtAUgc9 25CkJL0sc7QB88Kd3sP9k4aGlQ2TAx52+3TWDo+CBbfPHBTMDWnGB1nE742WLO4v neH+wSzLP/6U9JkxyRpiYHD+6zLAzq2xTZeiRSXYuzrRqVxaurY= =Qumg -----END PGP SIGNATURE----- Merge tag 'iomap-5.2-merge-2' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux Pull iomap updates from Darrick Wong: "Nothing particularly exciting here, just adding some callouts for gfs2 and cleaning a few things. Summary: - Add some extra hooks to the iomap buffered write path to enable gfs2 journalled writes - SPDX conversion - Various refactoring" * tag 'iomap-5.2-merge-2' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux: iomap: move iomap_read_inline_data around iomap: Add a page_prepare callback iomap: Fix use-after-free error in page_done callback fs: Turn __generic_write_end into a void function iomap: Clean up __generic_write_end calling iomap: convert to SPDX identifier
This commit is contained in:
commit
d8456eaf31
@ -2085,7 +2085,7 @@ int block_write_begin(struct address_space *mapping, loff_t pos, unsigned len,
|
||||
}
|
||||
EXPORT_SYMBOL(block_write_begin);
|
||||
|
||||
int __generic_write_end(struct inode *inode, loff_t pos, unsigned copied,
|
||||
void __generic_write_end(struct inode *inode, loff_t pos, unsigned copied,
|
||||
struct page *page)
|
||||
{
|
||||
loff_t old_size = inode->i_size;
|
||||
@ -2104,7 +2104,6 @@ int __generic_write_end(struct inode *inode, loff_t pos, unsigned copied,
|
||||
}
|
||||
|
||||
unlock_page(page);
|
||||
put_page(page);
|
||||
|
||||
if (old_size < pos)
|
||||
pagecache_isize_extended(inode, old_size, pos);
|
||||
@ -2116,7 +2115,6 @@ int __generic_write_end(struct inode *inode, loff_t pos, unsigned copied,
|
||||
*/
|
||||
if (i_size_changed)
|
||||
mark_inode_dirty(inode);
|
||||
return copied;
|
||||
}
|
||||
|
||||
int block_write_end(struct file *file, struct address_space *mapping,
|
||||
@ -2160,7 +2158,9 @@ int generic_write_end(struct file *file, struct address_space *mapping,
|
||||
struct page *page, void *fsdata)
|
||||
{
|
||||
copied = block_write_end(file, mapping, pos, len, copied, page, fsdata);
|
||||
return __generic_write_end(mapping->host, pos, copied, page);
|
||||
__generic_write_end(mapping->host, pos, copied, page);
|
||||
put_page(page);
|
||||
return copied;
|
||||
}
|
||||
EXPORT_SYMBOL(generic_write_end);
|
||||
|
||||
|
@ -965,15 +965,20 @@ static void gfs2_write_unlock(struct inode *inode)
|
||||
gfs2_glock_dq_uninit(&ip->i_gh);
|
||||
}
|
||||
|
||||
static void gfs2_iomap_journaled_page_done(struct inode *inode, loff_t pos,
|
||||
unsigned copied, struct page *page,
|
||||
struct iomap *iomap)
|
||||
static void gfs2_iomap_page_done(struct inode *inode, loff_t pos,
|
||||
unsigned copied, struct page *page,
|
||||
struct iomap *iomap)
|
||||
{
|
||||
struct gfs2_inode *ip = GFS2_I(inode);
|
||||
|
||||
gfs2_page_add_databufs(ip, page, offset_in_page(pos), copied);
|
||||
if (page)
|
||||
gfs2_page_add_databufs(ip, page, offset_in_page(pos), copied);
|
||||
}
|
||||
|
||||
static const struct iomap_page_ops gfs2_iomap_page_ops = {
|
||||
.page_done = gfs2_iomap_page_done,
|
||||
};
|
||||
|
||||
static int gfs2_iomap_begin_write(struct inode *inode, loff_t pos,
|
||||
loff_t length, unsigned flags,
|
||||
struct iomap *iomap,
|
||||
@ -1051,7 +1056,7 @@ static int gfs2_iomap_begin_write(struct inode *inode, loff_t pos,
|
||||
}
|
||||
}
|
||||
if (!gfs2_is_stuffed(ip) && gfs2_is_jdata(ip))
|
||||
iomap->page_done = gfs2_iomap_journaled_page_done;
|
||||
iomap->page_ops = &gfs2_iomap_page_ops;
|
||||
return 0;
|
||||
|
||||
out_trans_end:
|
||||
|
@ -44,7 +44,7 @@ static inline int __sync_blockdev(struct block_device *bdev, int wait)
|
||||
extern void guard_bio_eod(int rw, struct bio *bio);
|
||||
extern int __block_write_begin_int(struct page *page, loff_t pos, unsigned len,
|
||||
get_block_t *get_block, struct iomap *iomap);
|
||||
int __generic_write_end(struct inode *inode, loff_t pos, unsigned copied,
|
||||
void __generic_write_end(struct inode *inode, loff_t pos, unsigned copied,
|
||||
struct page *page);
|
||||
|
||||
/*
|
||||
|
105
fs/iomap.c
105
fs/iomap.c
@ -1,15 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2010 Red Hat, Inc.
|
||||
* Copyright (c) 2016-2018 Christoph Hellwig.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/compiler.h>
|
||||
@ -248,26 +240,6 @@ iomap_read_page_end_io(struct bio_vec *bvec, int error)
|
||||
iomap_read_finish(iop, page);
|
||||
}
|
||||
|
||||
static void
|
||||
iomap_read_inline_data(struct inode *inode, struct page *page,
|
||||
struct iomap *iomap)
|
||||
{
|
||||
size_t size = i_size_read(inode);
|
||||
void *addr;
|
||||
|
||||
if (PageUptodate(page))
|
||||
return;
|
||||
|
||||
BUG_ON(page->index);
|
||||
BUG_ON(size > PAGE_SIZE - offset_in_page(iomap->inline_data));
|
||||
|
||||
addr = kmap_atomic(page);
|
||||
memcpy(addr, iomap->inline_data, size);
|
||||
memset(addr + size, 0, PAGE_SIZE - size);
|
||||
kunmap_atomic(addr);
|
||||
SetPageUptodate(page);
|
||||
}
|
||||
|
||||
static void
|
||||
iomap_read_end_io(struct bio *bio)
|
||||
{
|
||||
@ -289,6 +261,26 @@ struct iomap_readpage_ctx {
|
||||
struct list_head *pages;
|
||||
};
|
||||
|
||||
static void
|
||||
iomap_read_inline_data(struct inode *inode, struct page *page,
|
||||
struct iomap *iomap)
|
||||
{
|
||||
size_t size = i_size_read(inode);
|
||||
void *addr;
|
||||
|
||||
if (PageUptodate(page))
|
||||
return;
|
||||
|
||||
BUG_ON(page->index);
|
||||
BUG_ON(size > PAGE_SIZE - offset_in_page(iomap->inline_data));
|
||||
|
||||
addr = kmap_atomic(page);
|
||||
memcpy(addr, iomap->inline_data, size);
|
||||
memset(addr + size, 0, PAGE_SIZE - size);
|
||||
kunmap_atomic(addr);
|
||||
SetPageUptodate(page);
|
||||
}
|
||||
|
||||
static loff_t
|
||||
iomap_readpage_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
|
||||
struct iomap *iomap)
|
||||
@ -665,6 +657,7 @@ static int
|
||||
iomap_write_begin(struct inode *inode, loff_t pos, unsigned len, unsigned flags,
|
||||
struct page **pagep, struct iomap *iomap)
|
||||
{
|
||||
const struct iomap_page_ops *page_ops = iomap->page_ops;
|
||||
pgoff_t index = pos >> PAGE_SHIFT;
|
||||
struct page *page;
|
||||
int status = 0;
|
||||
@ -674,9 +667,17 @@ iomap_write_begin(struct inode *inode, loff_t pos, unsigned len, unsigned flags,
|
||||
if (fatal_signal_pending(current))
|
||||
return -EINTR;
|
||||
|
||||
if (page_ops && page_ops->page_prepare) {
|
||||
status = page_ops->page_prepare(inode, pos, len, iomap);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
||||
page = grab_cache_page_write_begin(inode->i_mapping, index, flags);
|
||||
if (!page)
|
||||
return -ENOMEM;
|
||||
if (!page) {
|
||||
status = -ENOMEM;
|
||||
goto out_no_page;
|
||||
}
|
||||
|
||||
if (iomap->type == IOMAP_INLINE)
|
||||
iomap_read_inline_data(inode, page, iomap);
|
||||
@ -684,15 +685,21 @@ iomap_write_begin(struct inode *inode, loff_t pos, unsigned len, unsigned flags,
|
||||
status = __block_write_begin_int(page, pos, len, NULL, iomap);
|
||||
else
|
||||
status = __iomap_write_begin(inode, pos, len, page, iomap);
|
||||
if (unlikely(status)) {
|
||||
unlock_page(page);
|
||||
put_page(page);
|
||||
page = NULL;
|
||||
|
||||
iomap_write_failed(inode, pos, len);
|
||||
}
|
||||
if (unlikely(status))
|
||||
goto out_unlock;
|
||||
|
||||
*pagep = page;
|
||||
return 0;
|
||||
|
||||
out_unlock:
|
||||
unlock_page(page);
|
||||
put_page(page);
|
||||
iomap_write_failed(inode, pos, len);
|
||||
|
||||
out_no_page:
|
||||
if (page_ops && page_ops->page_done)
|
||||
page_ops->page_done(inode, pos, 0, NULL, iomap);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -738,13 +745,11 @@ __iomap_write_end(struct inode *inode, loff_t pos, unsigned len,
|
||||
* uptodate page as a zero-length write, and force the caller to redo
|
||||
* the whole thing.
|
||||
*/
|
||||
if (unlikely(copied < len && !PageUptodate(page))) {
|
||||
copied = 0;
|
||||
} else {
|
||||
iomap_set_range_uptodate(page, offset_in_page(pos), len);
|
||||
iomap_set_page_dirty(page);
|
||||
}
|
||||
return __generic_write_end(inode, pos, copied, page);
|
||||
if (unlikely(copied < len && !PageUptodate(page)))
|
||||
return 0;
|
||||
iomap_set_range_uptodate(page, offset_in_page(pos), len);
|
||||
iomap_set_page_dirty(page);
|
||||
return copied;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -761,7 +766,6 @@ iomap_write_end_inline(struct inode *inode, struct page *page,
|
||||
kunmap_atomic(addr);
|
||||
|
||||
mark_inode_dirty(inode);
|
||||
__generic_write_end(inode, pos, copied, page);
|
||||
return copied;
|
||||
}
|
||||
|
||||
@ -769,19 +773,22 @@ static int
|
||||
iomap_write_end(struct inode *inode, loff_t pos, unsigned len,
|
||||
unsigned copied, struct page *page, struct iomap *iomap)
|
||||
{
|
||||
const struct iomap_page_ops *page_ops = iomap->page_ops;
|
||||
int ret;
|
||||
|
||||
if (iomap->type == IOMAP_INLINE) {
|
||||
ret = iomap_write_end_inline(inode, page, iomap, pos, copied);
|
||||
} else if (iomap->flags & IOMAP_F_BUFFER_HEAD) {
|
||||
ret = generic_write_end(NULL, inode->i_mapping, pos, len,
|
||||
copied, page, NULL);
|
||||
ret = block_write_end(NULL, inode->i_mapping, pos, len, copied,
|
||||
page, NULL);
|
||||
} else {
|
||||
ret = __iomap_write_end(inode, pos, len, copied, page, iomap);
|
||||
}
|
||||
|
||||
if (iomap->page_done)
|
||||
iomap->page_done(inode, pos, copied, page, iomap);
|
||||
__generic_write_end(inode, pos, ret, page);
|
||||
if (page_ops && page_ops->page_done)
|
||||
page_ops->page_done(inode, pos, copied, page, iomap);
|
||||
put_page(page);
|
||||
|
||||
if (ret < len)
|
||||
iomap_write_failed(inode, pos, len);
|
||||
|
@ -53,6 +53,8 @@ struct vm_fault;
|
||||
*/
|
||||
#define IOMAP_NULL_ADDR -1ULL /* addr is not valid */
|
||||
|
||||
struct iomap_page_ops;
|
||||
|
||||
struct iomap {
|
||||
u64 addr; /* disk offset of mapping, bytes */
|
||||
loff_t offset; /* file offset of mapping, bytes */
|
||||
@ -63,12 +65,22 @@ struct iomap {
|
||||
struct dax_device *dax_dev; /* dax_dev for dax operations */
|
||||
void *inline_data;
|
||||
void *private; /* filesystem private */
|
||||
const struct iomap_page_ops *page_ops;
|
||||
};
|
||||
|
||||
/*
|
||||
* Called when finished processing a page in the mapping returned in
|
||||
* this iomap. At least for now this is only supported in the buffered
|
||||
* write path.
|
||||
*/
|
||||
/*
|
||||
* When a filesystem sets page_ops in an iomap mapping it returns, page_prepare
|
||||
* and page_done will be called for each page written to. This only applies to
|
||||
* buffered writes as unbuffered writes will not typically have pages
|
||||
* associated with them.
|
||||
*
|
||||
* When page_prepare succeeds, page_done will always be called to do any
|
||||
* cleanup work necessary. In that page_done call, @page will be NULL if the
|
||||
* associated page could not be obtained.
|
||||
*/
|
||||
struct iomap_page_ops {
|
||||
int (*page_prepare)(struct inode *inode, loff_t pos, unsigned len,
|
||||
struct iomap *iomap);
|
||||
void (*page_done)(struct inode *inode, loff_t pos, unsigned copied,
|
||||
struct page *page, struct iomap *iomap);
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user