On Thu, Dec 12, 2019 at 12:01:32PM -0700, Jens Axboe wrote: > We pass a lot of arguments to iomap_apply(), and subsequently to the > actors that it calls. In preparation for adding one more argument, > switch them to using a struct iomap_data instead. The actor gets a const > version of that, they are not supposed to change anything in it. > > Signed-off-by: Jens Axboe <axboe@xxxxxxxxx> Looks good, only a couple of questions... > --- > fs/dax.c | 25 +++-- > fs/iomap/apply.c | 26 +++--- > fs/iomap/buffered-io.c | 202 +++++++++++++++++++++++++---------------- > fs/iomap/direct-io.c | 57 +++++++----- > fs/iomap/fiemap.c | 48 ++++++---- > fs/iomap/seek.c | 64 ++++++++----- > fs/iomap/swapfile.c | 27 +++--- > include/linux/iomap.h | 15 ++- > 8 files changed, 278 insertions(+), 186 deletions(-) > > diff --git a/fs/dax.c b/fs/dax.c > index 1f1f0201cad1..d1c32dbbdf24 100644 > --- a/fs/dax.c > +++ b/fs/dax.c > @@ -1090,13 +1090,16 @@ int __dax_zero_page_range(struct block_device *bdev, > EXPORT_SYMBOL_GPL(__dax_zero_page_range); > > static loff_t > -dax_iomap_actor(struct inode *inode, loff_t pos, loff_t length, void *data, > - struct iomap *iomap, struct iomap *srcmap) > +dax_iomap_actor(const struct iomap_data *data, struct iomap *iomap, I wonder, is 'struct iomap_ctx' a better name for the context structure? > + struct iomap *srcmap) > { > struct block_device *bdev = iomap->bdev; > struct dax_device *dax_dev = iomap->dax_dev; > - struct iov_iter *iter = data; > + struct iov_iter *iter = data->priv; > + loff_t pos = data->pos; > + loff_t length = pos + data->len; > loff_t end = pos + length, done = 0; > + struct inode *inode = data->inode; > ssize_t ret = 0; > size_t xfer; > int id; > @@ -1197,22 +1200,26 @@ dax_iomap_rw(struct kiocb *iocb, struct iov_iter *iter, > { > struct address_space *mapping = iocb->ki_filp->f_mapping; > struct inode *inode = mapping->host; > - loff_t pos = iocb->ki_pos, ret = 0, done = 0; > - unsigned flags = 0; > + loff_t ret = 0, done = 0; > + struct iomap_data data = { > + .inode = inode, > + .pos = iocb->ki_pos, > + .priv = iter, > + }; > > if (iov_iter_rw(iter) == WRITE) { > lockdep_assert_held_write(&inode->i_rwsem); > - flags |= IOMAP_WRITE; > + data.flags |= IOMAP_WRITE; > } else { > lockdep_assert_held(&inode->i_rwsem); > } > > while (iov_iter_count(iter)) { > - ret = iomap_apply(inode, pos, iov_iter_count(iter), flags, ops, > - iter, dax_iomap_actor); > + data.len = iov_iter_count(iter); > + ret = iomap_apply(&data, ops, dax_iomap_actor); > if (ret <= 0) > break; > - pos += ret; > + data.pos += ret; > done += ret; > } > > diff --git a/fs/iomap/apply.c b/fs/iomap/apply.c > index 76925b40b5fd..e76148db03b8 100644 > --- a/fs/iomap/apply.c > +++ b/fs/iomap/apply.c > @@ -21,15 +21,16 @@ > * iomap_end call. > */ > loff_t > -iomap_apply(struct inode *inode, loff_t pos, loff_t length, unsigned flags, > - const struct iomap_ops *ops, void *data, iomap_actor_t actor) > +iomap_apply(struct iomap_data *data, const struct iomap_ops *ops, > + iomap_actor_t actor) > { > struct iomap iomap = { .type = IOMAP_HOLE }; > struct iomap srcmap = { .type = IOMAP_HOLE }; > loff_t written = 0, ret; > u64 end; > > - trace_iomap_apply(inode, pos, length, flags, ops, actor, _RET_IP_); > + trace_iomap_apply(data->inode, data->pos, data->len, data->flags, ops, > + actor, _RET_IP_); > > /* > * Need to map a range from start position for length bytes. This can > @@ -43,17 +44,18 @@ iomap_apply(struct inode *inode, loff_t pos, loff_t length, unsigned flags, > * expose transient stale data. If the reserve fails, we can safely > * back out at this point as there is nothing to undo. > */ > - ret = ops->iomap_begin(inode, pos, length, flags, &iomap, &srcmap); > + ret = ops->iomap_begin(data->inode, data->pos, data->len, data->flags, > + &iomap, &srcmap); ...and second, what do people think about about passing "const struct iomap_ctx *ctx" to iomap_begin and iomap_end to reduce the argument counts there too? (That's definitely a separate patch though, and I might just do that on my own if nobody beats me to it...) --D > if (ret) > return ret; > - if (WARN_ON(iomap.offset > pos)) > + if (WARN_ON(iomap.offset > data->pos)) > return -EIO; > if (WARN_ON(iomap.length == 0)) > return -EIO; > > - trace_iomap_apply_dstmap(inode, &iomap); > + trace_iomap_apply_dstmap(data->inode, &iomap); > if (srcmap.type != IOMAP_HOLE) > - trace_iomap_apply_srcmap(inode, &srcmap); > + trace_iomap_apply_srcmap(data->inode, &srcmap); > > /* > * Cut down the length to the one actually provided by the filesystem, > @@ -62,8 +64,8 @@ iomap_apply(struct inode *inode, loff_t pos, loff_t length, unsigned flags, > end = iomap.offset + iomap.length; > if (srcmap.type != IOMAP_HOLE) > end = min(end, srcmap.offset + srcmap.length); > - if (pos + length > end) > - length = end - pos; > + if (data->pos + data->len > end) > + data->len = end - data->pos; > > /* > * Now that we have guaranteed that the space allocation will succeed, > @@ -77,7 +79,7 @@ iomap_apply(struct inode *inode, loff_t pos, loff_t length, unsigned flags, > * iomap into the actors so that they don't need to have special > * handling for the two cases. > */ > - written = actor(inode, pos, length, data, &iomap, > + written = actor(data, &iomap, > srcmap.type != IOMAP_HOLE ? &srcmap : &iomap); > > /* > @@ -85,9 +87,9 @@ iomap_apply(struct inode *inode, loff_t pos, loff_t length, unsigned flags, > * should not fail unless the filesystem has had a fatal error. > */ > if (ops->iomap_end) { > - ret = ops->iomap_end(inode, pos, length, > + ret = ops->iomap_end(data->inode, data->pos, data->len, > written > 0 ? written : 0, > - flags, &iomap); > + data->flags, &iomap); > } > > return written ? written : ret; > diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c > index 828444e14d09..0a1a195ed1cc 100644 > --- a/fs/iomap/buffered-io.c > +++ b/fs/iomap/buffered-io.c > @@ -248,14 +248,15 @@ static inline bool iomap_block_needs_zeroing(struct inode *inode, > } > > static loff_t > -iomap_readpage_actor(struct inode *inode, loff_t pos, loff_t length, void *data, > - struct iomap *iomap, struct iomap *srcmap) > +iomap_readpage_actor(const struct iomap_data *data, struct iomap *iomap, > + struct iomap *srcmap) > { > - struct iomap_readpage_ctx *ctx = data; > + struct iomap_readpage_ctx *ctx = data->priv; > + struct inode *inode = data->inode; > struct page *page = ctx->cur_page; > struct iomap_page *iop = iomap_page_create(inode, page); > bool same_page = false, is_contig = false; > - loff_t orig_pos = pos; > + loff_t pos = data->pos, orig_pos = data->pos; > unsigned poff, plen; > sector_t sector; > > @@ -266,7 +267,7 @@ iomap_readpage_actor(struct inode *inode, loff_t pos, loff_t length, void *data, > } > > /* zero post-eof blocks as the page may be mapped */ > - iomap_adjust_read_range(inode, iop, &pos, length, &poff, &plen); > + iomap_adjust_read_range(inode, iop, &pos, data->len, &poff, &plen); > if (plen == 0) > goto done; > > @@ -302,7 +303,7 @@ iomap_readpage_actor(struct inode *inode, loff_t pos, loff_t length, void *data, > > if (!ctx->bio || !is_contig || bio_full(ctx->bio, plen)) { > gfp_t gfp = mapping_gfp_constraint(page->mapping, GFP_KERNEL); > - int nr_vecs = (length + PAGE_SIZE - 1) >> PAGE_SHIFT; > + int nr_vecs = (data->len + PAGE_SIZE - 1) >> PAGE_SHIFT; > > if (ctx->bio) > submit_bio(ctx->bio); > @@ -333,16 +334,20 @@ int > iomap_readpage(struct page *page, const struct iomap_ops *ops) > { > struct iomap_readpage_ctx ctx = { .cur_page = page }; > - struct inode *inode = page->mapping->host; > + struct iomap_data data = { > + .inode = page->mapping->host, > + .priv = &ctx, > + .flags = 0 > + }; > unsigned poff; > loff_t ret; > > trace_iomap_readpage(page->mapping->host, 1); > > for (poff = 0; poff < PAGE_SIZE; poff += ret) { > - ret = iomap_apply(inode, page_offset(page) + poff, > - PAGE_SIZE - poff, 0, ops, &ctx, > - iomap_readpage_actor); > + data.pos = page_offset(page) + poff; > + data.len = PAGE_SIZE - poff; > + ret = iomap_apply(&data, ops, iomap_readpage_actor); > if (ret <= 0) { > WARN_ON_ONCE(ret == 0); > SetPageError(page); > @@ -396,28 +401,34 @@ iomap_next_page(struct inode *inode, struct list_head *pages, loff_t pos, > } > > static loff_t > -iomap_readpages_actor(struct inode *inode, loff_t pos, loff_t length, > - void *data, struct iomap *iomap, struct iomap *srcmap) > +iomap_readpages_actor(const struct iomap_data *data, struct iomap *iomap, > + struct iomap *srcmap) > { > - struct iomap_readpage_ctx *ctx = data; > + struct iomap_readpage_ctx *ctx = data->priv; > loff_t done, ret; > > - for (done = 0; done < length; done += ret) { > - if (ctx->cur_page && offset_in_page(pos + done) == 0) { > + for (done = 0; done < data->len; done += ret) { > + struct iomap_data rp_data = { > + .inode = data->inode, > + .pos = data->pos + done, > + .len = data->len - done, > + .priv = ctx, > + }; > + > + if (ctx->cur_page && offset_in_page(rp_data.pos) == 0) { > if (!ctx->cur_page_in_bio) > unlock_page(ctx->cur_page); > put_page(ctx->cur_page); > ctx->cur_page = NULL; > } > if (!ctx->cur_page) { > - ctx->cur_page = iomap_next_page(inode, ctx->pages, > - pos, length, &done); > + ctx->cur_page = iomap_next_page(data->inode, ctx->pages, > + data->pos, data->len, &done); > if (!ctx->cur_page) > break; > ctx->cur_page_in_bio = false; > } > - ret = iomap_readpage_actor(inode, pos + done, length - done, > - ctx, iomap, srcmap); > + ret = iomap_readpage_actor(&rp_data, iomap, srcmap); > } > > return done; > @@ -431,21 +442,27 @@ iomap_readpages(struct address_space *mapping, struct list_head *pages, > .pages = pages, > .is_readahead = true, > }; > - loff_t pos = page_offset(list_entry(pages->prev, struct page, lru)); > + struct iomap_data data = { > + .inode = mapping->host, > + .priv = &ctx, > + .flags = 0 > + }; > loff_t last = page_offset(list_entry(pages->next, struct page, lru)); > - loff_t length = last - pos + PAGE_SIZE, ret = 0; > + loff_t ret = 0; > + > + data.pos = page_offset(list_entry(pages->prev, struct page, lru)); > + data.len = last - data.pos + PAGE_SIZE; > > - trace_iomap_readpages(mapping->host, nr_pages); > + trace_iomap_readpages(data.inode, nr_pages); > > - while (length > 0) { > - ret = iomap_apply(mapping->host, pos, length, 0, ops, > - &ctx, iomap_readpages_actor); > + while (data.len > 0) { > + ret = iomap_apply(&data, ops, iomap_readpages_actor); > if (ret <= 0) { > WARN_ON_ONCE(ret == 0); > goto done; > } > - pos += ret; > - length -= ret; > + data.pos += ret; > + data.len -= ret; > } > ret = 0; > done: > @@ -796,10 +813,13 @@ iomap_write_end(struct inode *inode, loff_t pos, unsigned len, unsigned copied, > } > > static loff_t > -iomap_write_actor(struct inode *inode, loff_t pos, loff_t length, void *data, > - struct iomap *iomap, struct iomap *srcmap) > +iomap_write_actor(const struct iomap_data *data, struct iomap *iomap, > + struct iomap *srcmap) > { > - struct iov_iter *i = data; > + struct inode *inode = data->inode; > + struct iov_iter *i = data->priv; > + loff_t length = data->len; > + loff_t pos = data->pos; > long status = 0; > ssize_t written = 0; > > @@ -879,15 +899,20 @@ ssize_t > iomap_file_buffered_write(struct kiocb *iocb, struct iov_iter *iter, > const struct iomap_ops *ops) > { > - struct inode *inode = iocb->ki_filp->f_mapping->host; > - loff_t pos = iocb->ki_pos, ret = 0, written = 0; > + struct iomap_data data = { > + .inode = iocb->ki_filp->f_mapping->host, > + .pos = iocb->ki_pos, > + .priv = iter, > + .flags = IOMAP_WRITE > + }; > + loff_t ret = 0, written = 0; > > while (iov_iter_count(iter)) { > - ret = iomap_apply(inode, pos, iov_iter_count(iter), > - IOMAP_WRITE, ops, iter, iomap_write_actor); > + data.len = iov_iter_count(iter); > + ret = iomap_apply(&data, ops, iomap_write_actor); > if (ret <= 0) > break; > - pos += ret; > + data.pos += ret; > written += ret; > } > > @@ -896,9 +921,11 @@ iomap_file_buffered_write(struct kiocb *iocb, struct iov_iter *iter, > EXPORT_SYMBOL_GPL(iomap_file_buffered_write); > > static loff_t > -iomap_unshare_actor(struct inode *inode, loff_t pos, loff_t length, void *data, > - struct iomap *iomap, struct iomap *srcmap) > +iomap_unshare_actor(const struct iomap_data *data, struct iomap *iomap, > + struct iomap *srcmap) > { > + loff_t pos = data->pos; > + loff_t length = data->len; > long status = 0; > ssize_t written = 0; > > @@ -914,13 +941,13 @@ iomap_unshare_actor(struct inode *inode, loff_t pos, loff_t length, void *data, > unsigned long bytes = min_t(loff_t, PAGE_SIZE - offset, length); > struct page *page; > > - status = iomap_write_begin(inode, pos, bytes, > + status = iomap_write_begin(data->inode, pos, bytes, > IOMAP_WRITE_F_UNSHARE, &page, iomap, srcmap); > if (unlikely(status)) > return status; > > - status = iomap_write_end(inode, pos, bytes, bytes, page, iomap, > - srcmap); > + status = iomap_write_end(data->inode, pos, bytes, bytes, page, > + iomap, srcmap); > if (unlikely(status <= 0)) { > if (WARN_ON_ONCE(status == 0)) > return -EIO; > @@ -933,7 +960,7 @@ iomap_unshare_actor(struct inode *inode, loff_t pos, loff_t length, void *data, > written += status; > length -= status; > > - balance_dirty_pages_ratelimited(inode->i_mapping); > + balance_dirty_pages_ratelimited(data->inode->i_mapping); > } while (length); > > return written; > @@ -943,15 +970,20 @@ int > iomap_file_unshare(struct inode *inode, loff_t pos, loff_t len, > const struct iomap_ops *ops) > { > + struct iomap_data data = { > + .inode = inode, > + .pos = pos, > + .len = len, > + .flags = IOMAP_WRITE, > + }; > loff_t ret; > > - while (len) { > - ret = iomap_apply(inode, pos, len, IOMAP_WRITE, ops, NULL, > - iomap_unshare_actor); > + while (data.len) { > + ret = iomap_apply(&data, ops, iomap_unshare_actor); > if (ret <= 0) > return ret; > - pos += ret; > - len -= ret; > + data.pos += ret; > + data.len -= ret; > } > > return 0; > @@ -982,16 +1014,18 @@ static int iomap_dax_zero(loff_t pos, unsigned offset, unsigned bytes, > } > > static loff_t > -iomap_zero_range_actor(struct inode *inode, loff_t pos, loff_t count, > - void *data, struct iomap *iomap, struct iomap *srcmap) > +iomap_zero_range_actor(const struct iomap_data *data, struct iomap *iomap, > + struct iomap *srcmap) > { > - bool *did_zero = data; > + bool *did_zero = data->priv; > + loff_t count = data->len; > + loff_t pos = data->pos; > loff_t written = 0; > int status; > > /* already zeroed? we're done. */ > if (srcmap->type == IOMAP_HOLE || srcmap->type == IOMAP_UNWRITTEN) > - return count; > + return data->len; > > do { > unsigned offset, bytes; > @@ -999,11 +1033,11 @@ iomap_zero_range_actor(struct inode *inode, loff_t pos, loff_t count, > offset = offset_in_page(pos); > bytes = min_t(loff_t, PAGE_SIZE - offset, count); > > - if (IS_DAX(inode)) > + if (IS_DAX(data->inode)) > status = iomap_dax_zero(pos, offset, bytes, iomap); > else > - status = iomap_zero(inode, pos, offset, bytes, iomap, > - srcmap); > + status = iomap_zero(data->inode, pos, offset, bytes, > + iomap, srcmap); > if (status < 0) > return status; > > @@ -1021,16 +1055,22 @@ int > iomap_zero_range(struct inode *inode, loff_t pos, loff_t len, bool *did_zero, > const struct iomap_ops *ops) > { > + struct iomap_data data = { > + .inode = inode, > + .pos = pos, > + .len = len, > + .priv = did_zero, > + .flags = IOMAP_ZERO > + }; > loff_t ret; > > - while (len > 0) { > - ret = iomap_apply(inode, pos, len, IOMAP_ZERO, > - ops, did_zero, iomap_zero_range_actor); > + while (data.len > 0) { > + ret = iomap_apply(&data, ops, iomap_zero_range_actor); > if (ret <= 0) > return ret; > > - pos += ret; > - len -= ret; > + data.pos += ret; > + data.len -= ret; > } > > return 0; > @@ -1052,57 +1092,59 @@ iomap_truncate_page(struct inode *inode, loff_t pos, bool *did_zero, > EXPORT_SYMBOL_GPL(iomap_truncate_page); > > static loff_t > -iomap_page_mkwrite_actor(struct inode *inode, loff_t pos, loff_t length, > - void *data, struct iomap *iomap, struct iomap *srcmap) > +iomap_page_mkwrite_actor(const struct iomap_data *data, > + struct iomap *iomap, struct iomap *srcmap) > { > - struct page *page = data; > + struct page *page = data->priv; > int ret; > > if (iomap->flags & IOMAP_F_BUFFER_HEAD) { > - ret = __block_write_begin_int(page, pos, length, NULL, iomap); > + ret = __block_write_begin_int(page, data->pos, data->len, NULL, > + iomap); > if (ret) > return ret; > - block_commit_write(page, 0, length); > + block_commit_write(page, 0, data->len); > } else { > WARN_ON_ONCE(!PageUptodate(page)); > - iomap_page_create(inode, page); > + iomap_page_create(data->inode, page); > set_page_dirty(page); > } > > - return length; > + return data->len; > } > > vm_fault_t iomap_page_mkwrite(struct vm_fault *vmf, const struct iomap_ops *ops) > { > struct page *page = vmf->page; > - struct inode *inode = file_inode(vmf->vma->vm_file); > - unsigned long length; > - loff_t offset, size; > + struct iomap_data data = { > + .inode = file_inode(vmf->vma->vm_file), > + .pos = page_offset(page), > + .flags = IOMAP_WRITE | IOMAP_FAULT, > + .priv = page, > + }; > ssize_t ret; > + loff_t size; > > lock_page(page); > - size = i_size_read(inode); > - offset = page_offset(page); > - if (page->mapping != inode->i_mapping || offset > size) { > + size = i_size_read(data.inode); > + if (page->mapping != data.inode->i_mapping || data.pos > size) { > /* We overload EFAULT to mean page got truncated */ > ret = -EFAULT; > goto out_unlock; > } > > /* page is wholly or partially inside EOF */ > - if (offset > size - PAGE_SIZE) > - length = offset_in_page(size); > + if (data.pos > size - PAGE_SIZE) > + data.len = offset_in_page(size); > else > - length = PAGE_SIZE; > + data.len = PAGE_SIZE; > > - while (length > 0) { > - ret = iomap_apply(inode, offset, length, > - IOMAP_WRITE | IOMAP_FAULT, ops, page, > - iomap_page_mkwrite_actor); > + while (data.len > 0) { > + ret = iomap_apply(&data, ops, iomap_page_mkwrite_actor); > if (unlikely(ret <= 0)) > goto out_unlock; > - offset += ret; > - length -= ret; > + data.pos += ret; > + data.len -= ret; > } > > wait_for_stable_page(page); > diff --git a/fs/iomap/direct-io.c b/fs/iomap/direct-io.c > index 23837926c0c5..e561ca9329ac 100644 > --- a/fs/iomap/direct-io.c > +++ b/fs/iomap/direct-io.c > @@ -364,24 +364,27 @@ iomap_dio_inline_actor(struct inode *inode, loff_t pos, loff_t length, > } > > static loff_t > -iomap_dio_actor(struct inode *inode, loff_t pos, loff_t length, > - void *data, struct iomap *iomap, struct iomap *srcmap) > +iomap_dio_actor(const struct iomap_data *data, struct iomap *iomap, > + struct iomap *srcmap) > { > - struct iomap_dio *dio = data; > + struct iomap_dio *dio = data->priv; > > switch (iomap->type) { > case IOMAP_HOLE: > if (WARN_ON_ONCE(dio->flags & IOMAP_DIO_WRITE)) > return -EIO; > - return iomap_dio_hole_actor(length, dio); > + return iomap_dio_hole_actor(data->len, dio); > case IOMAP_UNWRITTEN: > if (!(dio->flags & IOMAP_DIO_WRITE)) > - return iomap_dio_hole_actor(length, dio); > - return iomap_dio_bio_actor(inode, pos, length, dio, iomap); > + return iomap_dio_hole_actor(data->len, dio); > + return iomap_dio_bio_actor(data->inode, data->pos, data->len, > + dio, iomap); > case IOMAP_MAPPED: > - return iomap_dio_bio_actor(inode, pos, length, dio, iomap); > + return iomap_dio_bio_actor(data->inode, data->pos, data->len, > + dio, iomap); > case IOMAP_INLINE: > - return iomap_dio_inline_actor(inode, pos, length, dio, iomap); > + return iomap_dio_inline_actor(data->inode, data->pos, data->len, > + dio, iomap); > default: > WARN_ON_ONCE(1); > return -EIO; > @@ -404,16 +407,19 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter, > { > struct address_space *mapping = iocb->ki_filp->f_mapping; > struct inode *inode = file_inode(iocb->ki_filp); > - size_t count = iov_iter_count(iter); > - loff_t pos = iocb->ki_pos; > - loff_t end = iocb->ki_pos + count - 1, ret = 0; > - unsigned int flags = IOMAP_DIRECT; > + struct iomap_data data = { > + .inode = inode, > + .pos = iocb->ki_pos, > + .len = iov_iter_count(iter), > + .flags = IOMAP_DIRECT > + }; > + loff_t end = data.pos + data.len - 1, ret = 0; > struct blk_plug plug; > struct iomap_dio *dio; > > lockdep_assert_held(&inode->i_rwsem); > > - if (!count) > + if (!data.len) > return 0; > > if (WARN_ON(is_sync_kiocb(iocb) && !wait_for_completion)) > @@ -436,14 +442,16 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter, > dio->submit.cookie = BLK_QC_T_NONE; > dio->submit.last_queue = NULL; > > + data.priv = dio; > + > if (iov_iter_rw(iter) == READ) { > - if (pos >= dio->i_size) > + if (data.pos >= dio->i_size) > goto out_free_dio; > > if (iter_is_iovec(iter)) > dio->flags |= IOMAP_DIO_DIRTY; > } else { > - flags |= IOMAP_WRITE; > + data.flags |= IOMAP_WRITE; > dio->flags |= IOMAP_DIO_WRITE; > > /* for data sync or sync, we need sync completion processing */ > @@ -461,14 +469,14 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter, > } > > if (iocb->ki_flags & IOCB_NOWAIT) { > - if (filemap_range_has_page(mapping, pos, end)) { > + if (filemap_range_has_page(mapping, data.pos, end)) { > ret = -EAGAIN; > goto out_free_dio; > } > - flags |= IOMAP_NOWAIT; > + data.flags |= IOMAP_NOWAIT; > } > > - ret = filemap_write_and_wait_range(mapping, pos, end); > + ret = filemap_write_and_wait_range(mapping, data.pos, end); > if (ret) > goto out_free_dio; > > @@ -479,7 +487,7 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter, > * pretty crazy thing to do, so we don't support it 100%. > */ > ret = invalidate_inode_pages2_range(mapping, > - pos >> PAGE_SHIFT, end >> PAGE_SHIFT); > + data.pos >> PAGE_SHIFT, end >> PAGE_SHIFT); > if (ret) > dio_warn_stale_pagecache(iocb->ki_filp); > ret = 0; > @@ -495,8 +503,7 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter, > > blk_start_plug(&plug); > do { > - ret = iomap_apply(inode, pos, count, flags, ops, dio, > - iomap_dio_actor); > + ret = iomap_apply(&data, ops, iomap_dio_actor); > if (ret <= 0) { > /* magic error code to fall back to buffered I/O */ > if (ret == -ENOTBLK) { > @@ -505,18 +512,18 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter, > } > break; > } > - pos += ret; > + data.pos += ret; > > - if (iov_iter_rw(iter) == READ && pos >= dio->i_size) { > + if (iov_iter_rw(iter) == READ && data.pos >= dio->i_size) { > /* > * We only report that we've read data up to i_size. > * Revert iter to a state corresponding to that as > * some callers (such as splice code) rely on it. > */ > - iov_iter_revert(iter, pos - dio->i_size); > + iov_iter_revert(iter, data.pos - dio->i_size); > break; > } > - } while ((count = iov_iter_count(iter)) > 0); > + } while ((data.len = iov_iter_count(iter)) > 0); > blk_finish_plug(&plug); > > if (ret < 0) > diff --git a/fs/iomap/fiemap.c b/fs/iomap/fiemap.c > index bccf305ea9ce..4075fbe0e3f5 100644 > --- a/fs/iomap/fiemap.c > +++ b/fs/iomap/fiemap.c > @@ -43,20 +43,20 @@ static int iomap_to_fiemap(struct fiemap_extent_info *fi, > } > > static loff_t > -iomap_fiemap_actor(struct inode *inode, loff_t pos, loff_t length, void *data, > - struct iomap *iomap, struct iomap *srcmap) > +iomap_fiemap_actor(const struct iomap_data *data, struct iomap *iomap, > + struct iomap *srcmap) > { > - struct fiemap_ctx *ctx = data; > - loff_t ret = length; > + struct fiemap_ctx *ctx = data->priv; > + loff_t ret = data->len; > > if (iomap->type == IOMAP_HOLE) > - return length; > + return data->len; > > ret = iomap_to_fiemap(ctx->fi, &ctx->prev, 0); > ctx->prev = *iomap; > switch (ret) { > case 0: /* success */ > - return length; > + return data->len; > case 1: /* extent array full */ > return 0; > default: > @@ -68,6 +68,13 @@ int iomap_fiemap(struct inode *inode, struct fiemap_extent_info *fi, > loff_t start, loff_t len, const struct iomap_ops *ops) > { > struct fiemap_ctx ctx; > + struct iomap_data data = { > + .inode = inode, > + .pos = start, > + .len = len, > + .flags = IOMAP_REPORT, > + .priv = &ctx > + }; > loff_t ret; > > memset(&ctx, 0, sizeof(ctx)); > @@ -84,9 +91,8 @@ int iomap_fiemap(struct inode *inode, struct fiemap_extent_info *fi, > return ret; > } > > - while (len > 0) { > - ret = iomap_apply(inode, start, len, IOMAP_REPORT, ops, &ctx, > - iomap_fiemap_actor); > + while (data.len > 0) { > + ret = iomap_apply(&data, ops, iomap_fiemap_actor); > /* inode with no (attribute) mapping will give ENOENT */ > if (ret == -ENOENT) > break; > @@ -95,8 +101,8 @@ int iomap_fiemap(struct inode *inode, struct fiemap_extent_info *fi, > if (ret == 0) > break; > > - start += ret; > - len -= ret; > + data.pos += ret; > + data.len -= ret; > } > > if (ctx.prev.type != IOMAP_HOLE) { > @@ -110,13 +116,14 @@ int iomap_fiemap(struct inode *inode, struct fiemap_extent_info *fi, > EXPORT_SYMBOL_GPL(iomap_fiemap); > > static loff_t > -iomap_bmap_actor(struct inode *inode, loff_t pos, loff_t length, > - void *data, struct iomap *iomap, struct iomap *srcmap) > +iomap_bmap_actor(const struct iomap_data *data, struct iomap *iomap, > + struct iomap *srcmap) > { > - sector_t *bno = data, addr; > + sector_t *bno = data->priv, addr; > > if (iomap->type == IOMAP_MAPPED) { > - addr = (pos - iomap->offset + iomap->addr) >> inode->i_blkbits; > + addr = (data->pos - iomap->offset + iomap->addr) >> > + data->inode->i_blkbits; > if (addr > INT_MAX) > WARN(1, "would truncate bmap result\n"); > else > @@ -131,16 +138,19 @@ iomap_bmap(struct address_space *mapping, sector_t bno, > const struct iomap_ops *ops) > { > struct inode *inode = mapping->host; > - loff_t pos = bno << inode->i_blkbits; > - unsigned blocksize = i_blocksize(inode); > + struct iomap_data data = { > + .inode = inode, > + .pos = bno << inode->i_blkbits, > + .len = i_blocksize(inode), > + .priv = &bno > + }; > int ret; > > if (filemap_write_and_wait(mapping)) > return 0; > > bno = 0; > - ret = iomap_apply(inode, pos, blocksize, 0, ops, &bno, > - iomap_bmap_actor); > + ret = iomap_apply(&data, ops, iomap_bmap_actor); > if (ret) > return 0; > return bno; > diff --git a/fs/iomap/seek.c b/fs/iomap/seek.c > index 89f61d93c0bc..288bee0b5d9b 100644 > --- a/fs/iomap/seek.c > +++ b/fs/iomap/seek.c > @@ -118,21 +118,23 @@ page_cache_seek_hole_data(struct inode *inode, loff_t offset, loff_t length, > > > static loff_t > -iomap_seek_hole_actor(struct inode *inode, loff_t offset, loff_t length, > - void *data, struct iomap *iomap, struct iomap *srcmap) > +iomap_seek_hole_actor(const struct iomap_data *data, struct iomap *iomap, > + struct iomap *srcmap) > { > + loff_t offset = data->pos; > + > switch (iomap->type) { > case IOMAP_UNWRITTEN: > - offset = page_cache_seek_hole_data(inode, offset, length, > - SEEK_HOLE); > + offset = page_cache_seek_hole_data(data->inode, offset, > + data->len, SEEK_HOLE); > if (offset < 0) > - return length; > + return data->len; > /* fall through */ > case IOMAP_HOLE: > - *(loff_t *)data = offset; > + *(loff_t *)data->priv = offset; > return 0; > default: > - return length; > + return data->len; > } > } > > @@ -140,23 +142,28 @@ loff_t > iomap_seek_hole(struct inode *inode, loff_t offset, const struct iomap_ops *ops) > { > loff_t size = i_size_read(inode); > - loff_t length = size - offset; > + struct iomap_data data = { > + .inode = inode, > + .len = size - offset, > + .priv = &offset, > + .flags = IOMAP_REPORT > + }; > loff_t ret; > > /* Nothing to be found before or beyond the end of the file. */ > if (offset < 0 || offset >= size) > return -ENXIO; > > - while (length > 0) { > - ret = iomap_apply(inode, offset, length, IOMAP_REPORT, ops, > - &offset, iomap_seek_hole_actor); > + while (data.len > 0) { > + data.pos = offset; > + ret = iomap_apply(&data, ops, iomap_seek_hole_actor); > if (ret < 0) > return ret; > if (ret == 0) > break; > > offset += ret; > - length -= ret; > + data.len -= ret; > } > > return offset; > @@ -164,20 +171,22 @@ iomap_seek_hole(struct inode *inode, loff_t offset, const struct iomap_ops *ops) > EXPORT_SYMBOL_GPL(iomap_seek_hole); > > static loff_t > -iomap_seek_data_actor(struct inode *inode, loff_t offset, loff_t length, > - void *data, struct iomap *iomap, struct iomap *srcmap) > +iomap_seek_data_actor(const struct iomap_data *data, struct iomap *iomap, > + struct iomap *srcmap) > { > + loff_t offset = data->pos; > + > switch (iomap->type) { > case IOMAP_HOLE: > - return length; > + return data->len; > case IOMAP_UNWRITTEN: > - offset = page_cache_seek_hole_data(inode, offset, length, > - SEEK_DATA); > + offset = page_cache_seek_hole_data(data->inode, offset, > + data->len, SEEK_DATA); > if (offset < 0) > - return length; > + return data->len; > /*FALLTHRU*/ > default: > - *(loff_t *)data = offset; > + *(loff_t *)data->priv = offset; > return 0; > } > } > @@ -186,26 +195,31 @@ loff_t > iomap_seek_data(struct inode *inode, loff_t offset, const struct iomap_ops *ops) > { > loff_t size = i_size_read(inode); > - loff_t length = size - offset; > + struct iomap_data data = { > + .inode = inode, > + .len = size - offset, > + .priv = &offset, > + .flags = IOMAP_REPORT > + }; > loff_t ret; > > /* Nothing to be found before or beyond the end of the file. */ > if (offset < 0 || offset >= size) > return -ENXIO; > > - while (length > 0) { > - ret = iomap_apply(inode, offset, length, IOMAP_REPORT, ops, > - &offset, iomap_seek_data_actor); > + while (data.len > 0) { > + data.pos = offset; > + ret = iomap_apply(&data, ops, iomap_seek_data_actor); > if (ret < 0) > return ret; > if (ret == 0) > break; > > offset += ret; > - length -= ret; > + data.len -= ret; > } > > - if (length <= 0) > + if (data.len <= 0) > return -ENXIO; > return offset; > } > diff --git a/fs/iomap/swapfile.c b/fs/iomap/swapfile.c > index a648dbf6991e..d911ab4b69ea 100644 > --- a/fs/iomap/swapfile.c > +++ b/fs/iomap/swapfile.c > @@ -75,11 +75,10 @@ static int iomap_swapfile_add_extent(struct iomap_swapfile_info *isi) > * swap only cares about contiguous page-aligned physical extents and makes no > * distinction between written and unwritten extents. > */ > -static loff_t iomap_swapfile_activate_actor(struct inode *inode, loff_t pos, > - loff_t count, void *data, struct iomap *iomap, > - struct iomap *srcmap) > +static loff_t iomap_swapfile_activate_actor(const struct iomap_data *data, > + struct iomap *iomap, struct iomap *srcmap) > { > - struct iomap_swapfile_info *isi = data; > + struct iomap_swapfile_info *isi = data->priv; > int error; > > switch (iomap->type) { > @@ -125,7 +124,7 @@ static loff_t iomap_swapfile_activate_actor(struct inode *inode, loff_t pos, > return error; > memcpy(&isi->iomap, iomap, sizeof(isi->iomap)); > } > - return count; > + return data->len; > } > > /* > @@ -142,8 +141,13 @@ int iomap_swapfile_activate(struct swap_info_struct *sis, > }; > struct address_space *mapping = swap_file->f_mapping; > struct inode *inode = mapping->host; > - loff_t pos = 0; > - loff_t len = ALIGN_DOWN(i_size_read(inode), PAGE_SIZE); > + struct iomap_data data = { > + .inode = inode, > + .pos = 0, > + .len = ALIGN_DOWN(i_size_read(inode), PAGE_SIZE), > + .priv = &isi, > + .flags = IOMAP_REPORT > + }; > loff_t ret; > > /* > @@ -154,14 +158,13 @@ int iomap_swapfile_activate(struct swap_info_struct *sis, > if (ret) > return ret; > > - while (len > 0) { > - ret = iomap_apply(inode, pos, len, IOMAP_REPORT, > - ops, &isi, iomap_swapfile_activate_actor); > + while (data.len > 0) { > + ret = iomap_apply(&data, ops, iomap_swapfile_activate_actor); > if (ret <= 0) > return ret; > > - pos += ret; > - len -= ret; > + data.pos += ret; + data.len -= ret; > } > > if (isi.iomap.length) { > diff --git a/include/linux/iomap.h b/include/linux/iomap.h > index 8b09463dae0d..30f40145a9e9 100644 > --- a/include/linux/iomap.h > +++ b/include/linux/iomap.h > @@ -145,11 +145,18 @@ struct iomap_ops { > /* > * Main iomap iterator function. > */ > -typedef loff_t (*iomap_actor_t)(struct inode *inode, loff_t pos, loff_t len, > - void *data, struct iomap *iomap, struct iomap *srcmap); > +struct iomap_data { > + struct inode *inode; > + loff_t pos; > + loff_t len; > + void *priv; > + unsigned flags; > +}; > + > +typedef loff_t (*iomap_actor_t)(const struct iomap_data *data, > + struct iomap *iomap, struct iomap *srcmap); > > -loff_t iomap_apply(struct inode *inode, loff_t pos, loff_t length, > - unsigned flags, const struct iomap_ops *ops, void *data, > +loff_t iomap_apply(struct iomap_data *data, const struct iomap_ops *ops, > iomap_actor_t actor); > > ssize_t iomap_file_buffered_write(struct kiocb *iocb, struct iov_iter *from, > -- > 2.24.1 >