Commit 1b5c1e36 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Darrick J. Wong

iomap: pass an iomap_iter to various buffered I/O helpers

Pass the iomap_iter structure instead of individual parameters to
various internal helpers for buffered I/O.
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarDarrick J. Wong <djwong@kernel.org>
Signed-off-by: default avatarDarrick J. Wong <djwong@kernel.org>
parent 57320a01
...@@ -205,10 +205,11 @@ struct iomap_readpage_ctx { ...@@ -205,10 +205,11 @@ struct iomap_readpage_ctx {
struct readahead_control *rac; struct readahead_control *rac;
}; };
static loff_t iomap_read_inline_data(struct inode *inode, struct page *page, static loff_t iomap_read_inline_data(struct iomap_iter *iter,
const struct iomap *iomap) struct page *page)
{ {
size_t size = i_size_read(inode) - iomap->offset; struct iomap *iomap = iomap_iter_srcmap(iter);
size_t size = i_size_read(iter->inode) - iomap->offset;
size_t poff = offset_in_page(iomap->offset); size_t poff = offset_in_page(iomap->offset);
void *addr; void *addr;
...@@ -223,7 +224,7 @@ static loff_t iomap_read_inline_data(struct inode *inode, struct page *page, ...@@ -223,7 +224,7 @@ static loff_t iomap_read_inline_data(struct inode *inode, struct page *page,
if (WARN_ON_ONCE(size > iomap->length)) if (WARN_ON_ONCE(size > iomap->length))
return -EIO; return -EIO;
if (poff > 0) if (poff > 0)
iomap_page_create(inode, page); iomap_page_create(iter->inode, page);
addr = kmap_local_page(page) + poff; addr = kmap_local_page(page) + poff;
memcpy(addr, iomap->inline_data, size); memcpy(addr, iomap->inline_data, size);
...@@ -233,12 +234,14 @@ static loff_t iomap_read_inline_data(struct inode *inode, struct page *page, ...@@ -233,12 +234,14 @@ static loff_t iomap_read_inline_data(struct inode *inode, struct page *page,
return PAGE_SIZE - poff; return PAGE_SIZE - poff;
} }
static inline bool iomap_block_needs_zeroing(struct inode *inode, static inline bool iomap_block_needs_zeroing(struct iomap_iter *iter,
struct iomap *iomap, loff_t pos) loff_t pos)
{ {
return iomap->type != IOMAP_MAPPED || struct iomap *srcmap = iomap_iter_srcmap(iter);
(iomap->flags & IOMAP_F_NEW) ||
pos >= i_size_read(inode); return srcmap->type != IOMAP_MAPPED ||
(srcmap->flags & IOMAP_F_NEW) ||
pos >= i_size_read(iter->inode);
} }
static loff_t iomap_readpage_iter(struct iomap_iter *iter, static loff_t iomap_readpage_iter(struct iomap_iter *iter,
...@@ -254,8 +257,7 @@ static loff_t iomap_readpage_iter(struct iomap_iter *iter, ...@@ -254,8 +257,7 @@ static loff_t iomap_readpage_iter(struct iomap_iter *iter,
sector_t sector; sector_t sector;
if (iomap->type == IOMAP_INLINE) if (iomap->type == IOMAP_INLINE)
return min(iomap_read_inline_data(iter->inode, page, iomap), return min(iomap_read_inline_data(iter, page), length);
length);
/* zero post-eof blocks as the page may be mapped */ /* zero post-eof blocks as the page may be mapped */
iop = iomap_page_create(iter->inode, page); iop = iomap_page_create(iter->inode, page);
...@@ -263,7 +265,7 @@ static loff_t iomap_readpage_iter(struct iomap_iter *iter, ...@@ -263,7 +265,7 @@ static loff_t iomap_readpage_iter(struct iomap_iter *iter,
if (plen == 0) if (plen == 0)
goto done; goto done;
if (iomap_block_needs_zeroing(iter->inode, iomap, pos)) { if (iomap_block_needs_zeroing(iter, pos)) {
zero_user(page, poff, plen); zero_user(page, poff, plen);
iomap_set_range_uptodate(page, poff, plen); iomap_set_range_uptodate(page, poff, plen);
goto done; goto done;
...@@ -538,12 +540,12 @@ iomap_read_page_sync(loff_t block_start, struct page *page, unsigned poff, ...@@ -538,12 +540,12 @@ iomap_read_page_sync(loff_t block_start, struct page *page, unsigned poff,
return submit_bio_wait(&bio); return submit_bio_wait(&bio);
} }
static int static int __iomap_write_begin(struct iomap_iter *iter, loff_t pos,
__iomap_write_begin(struct inode *inode, loff_t pos, unsigned len, int flags, unsigned len, int flags, struct page *page)
struct page *page, struct iomap *srcmap)
{ {
struct iomap_page *iop = iomap_page_create(inode, page); struct iomap *srcmap = iomap_iter_srcmap(iter);
loff_t block_size = i_blocksize(inode); struct iomap_page *iop = iomap_page_create(iter->inode, page);
loff_t block_size = i_blocksize(iter->inode);
loff_t block_start = round_down(pos, block_size); loff_t block_start = round_down(pos, block_size);
loff_t block_end = round_up(pos + len, block_size); loff_t block_end = round_up(pos + len, block_size);
unsigned from = offset_in_page(pos), to = from + len, poff, plen; unsigned from = offset_in_page(pos), to = from + len, poff, plen;
...@@ -553,7 +555,7 @@ __iomap_write_begin(struct inode *inode, loff_t pos, unsigned len, int flags, ...@@ -553,7 +555,7 @@ __iomap_write_begin(struct inode *inode, loff_t pos, unsigned len, int flags,
ClearPageError(page); ClearPageError(page);
do { do {
iomap_adjust_read_range(inode, iop, &block_start, iomap_adjust_read_range(iter->inode, iop, &block_start,
block_end - block_start, &poff, &plen); block_end - block_start, &poff, &plen);
if (plen == 0) if (plen == 0)
break; break;
...@@ -563,7 +565,7 @@ __iomap_write_begin(struct inode *inode, loff_t pos, unsigned len, int flags, ...@@ -563,7 +565,7 @@ __iomap_write_begin(struct inode *inode, loff_t pos, unsigned len, int flags,
(to <= poff || to >= poff + plen)) (to <= poff || to >= poff + plen))
continue; continue;
if (iomap_block_needs_zeroing(inode, srcmap, block_start)) { if (iomap_block_needs_zeroing(iter, block_start)) {
if (WARN_ON_ONCE(flags & IOMAP_WRITE_F_UNSHARE)) if (WARN_ON_ONCE(flags & IOMAP_WRITE_F_UNSHARE))
return -EIO; return -EIO;
zero_user_segments(page, poff, from, to, poff + plen); zero_user_segments(page, poff, from, to, poff + plen);
...@@ -579,55 +581,54 @@ __iomap_write_begin(struct inode *inode, loff_t pos, unsigned len, int flags, ...@@ -579,55 +581,54 @@ __iomap_write_begin(struct inode *inode, loff_t pos, unsigned len, int flags,
return 0; return 0;
} }
static int iomap_write_begin_inline(struct inode *inode, static int iomap_write_begin_inline(struct iomap_iter *iter,
struct page *page, struct iomap *srcmap) struct page *page)
{ {
int ret; int ret;
/* needs more work for the tailpacking case; disable for now */ /* needs more work for the tailpacking case; disable for now */
if (WARN_ON_ONCE(srcmap->offset != 0)) if (WARN_ON_ONCE(iomap_iter_srcmap(iter)->offset != 0))
return -EIO; return -EIO;
ret = iomap_read_inline_data(inode, page, srcmap); ret = iomap_read_inline_data(iter, page);
if (ret < 0) if (ret < 0)
return ret; return ret;
return 0; return 0;
} }
static int static int iomap_write_begin(struct iomap_iter *iter, loff_t pos, unsigned len,
iomap_write_begin(struct inode *inode, loff_t pos, unsigned len, unsigned flags, unsigned flags, struct page **pagep)
struct page **pagep, struct iomap *iomap, struct iomap *srcmap)
{ {
const struct iomap_page_ops *page_ops = iomap->page_ops; const struct iomap_page_ops *page_ops = iter->iomap.page_ops;
struct iomap *srcmap = iomap_iter_srcmap(iter);
struct page *page; struct page *page;
int status = 0; int status = 0;
BUG_ON(pos + len > iomap->offset + iomap->length); BUG_ON(pos + len > iter->iomap.offset + iter->iomap.length);
if (srcmap != iomap) if (srcmap != &iter->iomap)
BUG_ON(pos + len > srcmap->offset + srcmap->length); BUG_ON(pos + len > srcmap->offset + srcmap->length);
if (fatal_signal_pending(current)) if (fatal_signal_pending(current))
return -EINTR; return -EINTR;
if (page_ops && page_ops->page_prepare) { if (page_ops && page_ops->page_prepare) {
status = page_ops->page_prepare(inode, pos, len); status = page_ops->page_prepare(iter->inode, pos, len);
if (status) if (status)
return status; return status;
} }
page = grab_cache_page_write_begin(inode->i_mapping, pos >> PAGE_SHIFT, page = grab_cache_page_write_begin(iter->inode->i_mapping,
AOP_FLAG_NOFS); pos >> PAGE_SHIFT, AOP_FLAG_NOFS);
if (!page) { if (!page) {
status = -ENOMEM; status = -ENOMEM;
goto out_no_page; goto out_no_page;
} }
if (srcmap->type == IOMAP_INLINE) if (srcmap->type == IOMAP_INLINE)
status = iomap_write_begin_inline(inode, page, srcmap); status = iomap_write_begin_inline(iter, page);
else if (iomap->flags & IOMAP_F_BUFFER_HEAD) else if (srcmap->flags & IOMAP_F_BUFFER_HEAD)
status = __block_write_begin_int(page, pos, len, NULL, srcmap); status = __block_write_begin_int(page, pos, len, NULL, srcmap);
else else
status = __iomap_write_begin(inode, pos, len, flags, page, status = __iomap_write_begin(iter, pos, len, flags, page);
srcmap);
if (unlikely(status)) if (unlikely(status))
goto out_unlock; goto out_unlock;
...@@ -638,11 +639,11 @@ iomap_write_begin(struct inode *inode, loff_t pos, unsigned len, unsigned flags, ...@@ -638,11 +639,11 @@ iomap_write_begin(struct inode *inode, loff_t pos, unsigned len, unsigned flags,
out_unlock: out_unlock:
unlock_page(page); unlock_page(page);
put_page(page); put_page(page);
iomap_write_failed(inode, pos, len); iomap_write_failed(iter->inode, pos, len);
out_no_page: out_no_page:
if (page_ops && page_ops->page_done) if (page_ops && page_ops->page_done)
page_ops->page_done(inode, pos, 0, NULL); page_ops->page_done(iter->inode, pos, 0, NULL);
return status; return status;
} }
...@@ -669,9 +670,10 @@ static size_t __iomap_write_end(struct inode *inode, loff_t pos, size_t len, ...@@ -669,9 +670,10 @@ static size_t __iomap_write_end(struct inode *inode, loff_t pos, size_t len,
return copied; return copied;
} }
static size_t iomap_write_end_inline(struct inode *inode, struct page *page, static size_t iomap_write_end_inline(struct iomap_iter *iter, struct page *page,
struct iomap *iomap, loff_t pos, size_t copied) loff_t pos, size_t copied)
{ {
struct iomap *iomap = &iter->iomap;
void *addr; void *addr;
WARN_ON_ONCE(!PageUptodate(page)); WARN_ON_ONCE(!PageUptodate(page));
...@@ -682,26 +684,26 @@ static size_t iomap_write_end_inline(struct inode *inode, struct page *page, ...@@ -682,26 +684,26 @@ static size_t iomap_write_end_inline(struct inode *inode, struct page *page,
memcpy(iomap_inline_data(iomap, pos), addr, copied); memcpy(iomap_inline_data(iomap, pos), addr, copied);
kunmap_local(addr); kunmap_local(addr);
mark_inode_dirty(inode); mark_inode_dirty(iter->inode);
return copied; return copied;
} }
/* Returns the number of bytes copied. May be 0. Cannot be an errno. */ /* Returns the number of bytes copied. May be 0. Cannot be an errno. */
static size_t iomap_write_end(struct inode *inode, loff_t pos, size_t len, static size_t iomap_write_end(struct iomap_iter *iter, loff_t pos, size_t len,
size_t copied, struct page *page, struct iomap *iomap, size_t copied, struct page *page)
struct iomap *srcmap)
{ {
const struct iomap_page_ops *page_ops = iomap->page_ops; const struct iomap_page_ops *page_ops = iter->iomap.page_ops;
loff_t old_size = inode->i_size; struct iomap *srcmap = iomap_iter_srcmap(iter);
loff_t old_size = iter->inode->i_size;
size_t ret; size_t ret;
if (srcmap->type == IOMAP_INLINE) { if (srcmap->type == IOMAP_INLINE) {
ret = iomap_write_end_inline(inode, page, iomap, pos, copied); ret = iomap_write_end_inline(iter, page, pos, copied);
} else if (srcmap->flags & IOMAP_F_BUFFER_HEAD) { } else if (srcmap->flags & IOMAP_F_BUFFER_HEAD) {
ret = block_write_end(NULL, inode->i_mapping, pos, len, copied, ret = block_write_end(NULL, iter->inode->i_mapping, pos, len,
page, NULL); copied, page, NULL);
} else { } else {
ret = __iomap_write_end(inode, pos, len, copied, page); ret = __iomap_write_end(iter->inode, pos, len, copied, page);
} }
/* /*
...@@ -710,26 +712,24 @@ static size_t iomap_write_end(struct inode *inode, loff_t pos, size_t len, ...@@ -710,26 +712,24 @@ static size_t iomap_write_end(struct inode *inode, loff_t pos, size_t len,
* preferably after I/O completion so that no stale data is exposed. * preferably after I/O completion so that no stale data is exposed.
*/ */
if (pos + ret > old_size) { if (pos + ret > old_size) {
i_size_write(inode, pos + ret); i_size_write(iter->inode, pos + ret);
iomap->flags |= IOMAP_F_SIZE_CHANGED; iter->iomap.flags |= IOMAP_F_SIZE_CHANGED;
} }
unlock_page(page); unlock_page(page);
if (old_size < pos) if (old_size < pos)
pagecache_isize_extended(inode, old_size, pos); pagecache_isize_extended(iter->inode, old_size, pos);
if (page_ops && page_ops->page_done) if (page_ops && page_ops->page_done)
page_ops->page_done(inode, pos, ret, page); page_ops->page_done(iter->inode, pos, ret, page);
put_page(page); put_page(page);
if (ret < len) if (ret < len)
iomap_write_failed(inode, pos, len); iomap_write_failed(iter->inode, pos, len);
return ret; return ret;
} }
static loff_t iomap_write_iter(struct iomap_iter *iter, struct iov_iter *i) static loff_t iomap_write_iter(struct iomap_iter *iter, struct iov_iter *i)
{ {
struct iomap *srcmap = iomap_iter_srcmap(iter);
struct iomap *iomap = &iter->iomap;
loff_t length = iomap_length(iter); loff_t length = iomap_length(iter);
loff_t pos = iter->pos; loff_t pos = iter->pos;
ssize_t written = 0; ssize_t written = 0;
...@@ -759,8 +759,7 @@ static loff_t iomap_write_iter(struct iomap_iter *iter, struct iov_iter *i) ...@@ -759,8 +759,7 @@ static loff_t iomap_write_iter(struct iomap_iter *iter, struct iov_iter *i)
break; break;
} }
status = iomap_write_begin(iter->inode, pos, bytes, 0, &page, status = iomap_write_begin(iter, pos, bytes, 0, &page);
iomap, srcmap);
if (unlikely(status)) if (unlikely(status))
break; break;
...@@ -769,8 +768,7 @@ static loff_t iomap_write_iter(struct iomap_iter *iter, struct iov_iter *i) ...@@ -769,8 +768,7 @@ static loff_t iomap_write_iter(struct iomap_iter *iter, struct iov_iter *i)
copied = copy_page_from_iter_atomic(page, offset, bytes, i); copied = copy_page_from_iter_atomic(page, offset, bytes, i);
status = iomap_write_end(iter->inode, pos, bytes, copied, page, status = iomap_write_end(iter, pos, bytes, copied, page);
iomap, srcmap);
if (unlikely(copied != status)) if (unlikely(copied != status))
iov_iter_revert(i, copied - status); iov_iter_revert(i, copied - status);
...@@ -838,13 +836,12 @@ static loff_t iomap_unshare_iter(struct iomap_iter *iter) ...@@ -838,13 +836,12 @@ static loff_t iomap_unshare_iter(struct iomap_iter *iter)
unsigned long bytes = min_t(loff_t, PAGE_SIZE - offset, length); unsigned long bytes = min_t(loff_t, PAGE_SIZE - offset, length);
struct page *page; struct page *page;
status = iomap_write_begin(iter->inode, pos, bytes, status = iomap_write_begin(iter, pos, bytes,
IOMAP_WRITE_F_UNSHARE, &page, iomap, srcmap); IOMAP_WRITE_F_UNSHARE, &page);
if (unlikely(status)) if (unlikely(status))
return status; return status;
status = iomap_write_end(iter->inode, pos, bytes, bytes, page, iomap, status = iomap_write_end(iter, pos, bytes, bytes, page);
srcmap);
if (WARN_ON_ONCE(status == 0)) if (WARN_ON_ONCE(status == 0))
return -EIO; return -EIO;
...@@ -878,22 +875,21 @@ iomap_file_unshare(struct inode *inode, loff_t pos, loff_t len, ...@@ -878,22 +875,21 @@ iomap_file_unshare(struct inode *inode, loff_t pos, loff_t len,
} }
EXPORT_SYMBOL_GPL(iomap_file_unshare); EXPORT_SYMBOL_GPL(iomap_file_unshare);
static s64 iomap_zero(struct inode *inode, loff_t pos, u64 length, static s64 __iomap_zero_iter(struct iomap_iter *iter, loff_t pos, u64 length)
struct iomap *iomap, struct iomap *srcmap)
{ {
struct page *page; struct page *page;
int status; int status;
unsigned offset = offset_in_page(pos); unsigned offset = offset_in_page(pos);
unsigned bytes = min_t(u64, PAGE_SIZE - offset, length); unsigned bytes = min_t(u64, PAGE_SIZE - offset, length);
status = iomap_write_begin(inode, pos, bytes, 0, &page, iomap, srcmap); status = iomap_write_begin(iter, pos, bytes, 0, &page);
if (status) if (status)
return status; return status;
zero_user(page, offset, bytes); zero_user(page, offset, bytes);
mark_page_accessed(page); mark_page_accessed(page);
return iomap_write_end(inode, pos, bytes, bytes, page, iomap, srcmap); return iomap_write_end(iter, pos, bytes, bytes, page);
} }
static loff_t iomap_zero_iter(struct iomap_iter *iter, bool *did_zero) static loff_t iomap_zero_iter(struct iomap_iter *iter, bool *did_zero)
...@@ -914,8 +910,7 @@ static loff_t iomap_zero_iter(struct iomap_iter *iter, bool *did_zero) ...@@ -914,8 +910,7 @@ static loff_t iomap_zero_iter(struct iomap_iter *iter, bool *did_zero)
if (IS_DAX(iter->inode)) if (IS_DAX(iter->inode))
bytes = dax_iomap_zero(pos, length, iomap); bytes = dax_iomap_zero(pos, length, iomap);
else else
bytes = iomap_zero(iter->inode, pos, length, iomap, bytes = __iomap_zero_iter(iter, pos, length);
srcmap);
if (bytes < 0) if (bytes < 0)
return bytes; return bytes;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment