[Cluster-devel] [PATCH v8 06/10] iomap: Add page_write_end iomap hook

Andreas Grünbacher andreas.gruenbacher at gmail.com
Tue Jun 5 07:56:29 UTC 2018


2018-06-04 21:31 GMT+02:00 Andreas Gruenbacher <agruenba at redhat.com>:
> Add a page_write_end hook called when done writing to a page, for
> filesystems that implement data journaling: in that case, pages are
> written to the journal before being written back to their proper on-disk
> locations.

> The new hook is bypassed for IOMAP_INLINE mappings.

Oops, no longer true of course.

> Signed-off-by: Andreas Gruenbacher <agruenba at redhat.com>
> ---
>  fs/iomap.c            | 58 ++++++++++++++++++++++++++++++++-----------
>  include/linux/iomap.h |  8 ++++++
>  2 files changed, 52 insertions(+), 14 deletions(-)
>
> diff --git a/fs/iomap.c b/fs/iomap.c
> index 48cd67227811..3b34c957d2fd 100644
> --- a/fs/iomap.c
> +++ b/fs/iomap.c
> @@ -181,16 +181,22 @@ iomap_write_begin(struct inode *inode, loff_t pos, unsigned len, unsigned flags,
>
>  static int
>  iomap_write_end(struct inode *inode, loff_t pos, unsigned len,
> -               unsigned copied, struct page *page, struct iomap *iomap)
> +               unsigned copied, struct page *page, struct iomap *iomap,
> +               const struct iomap_ops *ops)
>  {
> +       typeof(ops->page_write_end) page_write_end = ops->page_write_end;
>         int ret;
>
>         if (iomap->type == IOMAP_INLINE) {
>                 iomap_write_inline_data(inode, page, iomap, pos, copied);
>                 __generic_write_end(inode, pos, copied, page);
> +               if (page_write_end)
> +                       page_write_end(inode, pos, copied, page, iomap);
>                 return copied;
>         }
>
> +       if (page_write_end)
> +               page_write_end(inode, pos, copied, page, iomap);
>         ret = generic_write_end(NULL, inode->i_mapping, pos, len,
>                         copied, page, NULL);
>         if (ret < len)
> @@ -198,11 +204,17 @@ iomap_write_end(struct inode *inode, loff_t pos, unsigned len,
>         return ret;
>  }
>
> +struct iomap_write_args {
> +       const struct iomap_ops *ops;
> +       struct iov_iter *iter;
> +};
> +
>  static loff_t
>  iomap_write_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
>                 struct iomap *iomap)
>  {
> -       struct iov_iter *i = data;
> +       struct iomap_write_args *args = data;
> +       struct iov_iter *i = args->iter;
>         long status = 0;
>         ssize_t written = 0;
>         unsigned int flags = AOP_FLAG_NOFS;
> @@ -248,7 +260,7 @@ iomap_write_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
>                 flush_dcache_page(page);
>
>                 status = iomap_write_end(inode, pos, bytes, copied, page,
> -                               iomap);
> +                               iomap, args->ops);
>                 if (unlikely(status < 0))
>                         break;
>                 copied = status;
> @@ -285,10 +297,14 @@ iomap_file_buffered_write(struct kiocb *iocb, struct iov_iter *iter,
>  {
>         struct inode *inode = iocb->ki_filp->f_mapping->host;
>         loff_t pos = iocb->ki_pos, ret = 0, written = 0;
> +       struct iomap_write_args args = {
> +               .ops = ops,
> +               .iter = iter,
> +       };
>
>         while (iov_iter_count(iter)) {
>                 ret = iomap_apply(inode, pos, iov_iter_count(iter),
> -                               IOMAP_WRITE, ops, iter, iomap_write_actor);
> +                               IOMAP_WRITE, ops, &args, iomap_write_actor);
>                 if (ret <= 0)
>                         break;
>                 pos += ret;
> @@ -319,6 +335,7 @@ static loff_t
>  iomap_dirty_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
>                 struct iomap *iomap)
>  {
> +       const struct iomap_ops *ops = data;
>         long status = 0;
>         ssize_t written = 0;
>
> @@ -342,7 +359,8 @@ iomap_dirty_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
>
>                 WARN_ON_ONCE(!PageUptodate(page));
>
> -               status = iomap_write_end(inode, pos, bytes, bytes, page, iomap);
> +               status = iomap_write_end(inode, pos, bytes, bytes, page, iomap,
> +                               ops);
>                 if (unlikely(status <= 0)) {
>                         if (WARN_ON_ONCE(status == 0))
>                                 return -EIO;
> @@ -368,8 +386,8 @@ iomap_file_dirty(struct inode *inode, loff_t pos, loff_t len,
>         loff_t ret;
>
>         while (len) {
> -               ret = iomap_apply(inode, pos, len, IOMAP_WRITE, ops, NULL,
> -                               iomap_dirty_actor);
> +               ret = iomap_apply(inode, pos, len, IOMAP_WRITE, ops,
> +                               (void *)ops, iomap_dirty_actor);
>                 if (ret <= 0)
>                         return ret;
>                 pos += ret;
> @@ -381,7 +399,8 @@ iomap_file_dirty(struct inode *inode, loff_t pos, loff_t len,
>  EXPORT_SYMBOL_GPL(iomap_file_dirty);
>
>  static int iomap_zero(struct inode *inode, loff_t pos, unsigned offset,
> -               unsigned bytes, struct iomap *iomap)
> +               unsigned bytes, const struct iomap_ops *ops,
> +               struct iomap *iomap)
>  {
>         struct page *page;
>         int status;
> @@ -394,7 +413,8 @@ static int iomap_zero(struct inode *inode, loff_t pos, unsigned offset,
>         zero_user(page, offset, bytes);
>         mark_page_accessed(page);
>
> -       return iomap_write_end(inode, pos, bytes, bytes, page, iomap);
> +       return iomap_write_end(inode, pos, bytes, bytes, page, iomap,
> +                       ops);
>  }
>
>  static int iomap_dax_zero(loff_t pos, unsigned offset, unsigned bytes,
> @@ -407,11 +427,16 @@ static int iomap_dax_zero(loff_t pos, unsigned offset, unsigned bytes,
>                         offset, bytes);
>  }
>
> +struct iomap_zero_range_args {
> +       const struct iomap_ops *ops;
> +       bool *did_zero;
> +};
> +
>  static loff_t
>  iomap_zero_range_actor(struct inode *inode, loff_t pos, loff_t count,
>                 void *data, struct iomap *iomap)
>  {
> -       bool *did_zero = data;
> +       struct iomap_zero_range_args *args = data;
>         loff_t written = 0;
>         int status;
>
> @@ -428,15 +453,16 @@ iomap_zero_range_actor(struct inode *inode, loff_t pos, loff_t count,
>                 if (IS_DAX(inode))
>                         status = iomap_dax_zero(pos, offset, bytes, iomap);
>                 else
> -                       status = iomap_zero(inode, pos, offset, bytes, iomap);
> +                       status = iomap_zero(inode, pos, offset, bytes,
> +                                       args->ops, iomap);
>                 if (status < 0)
>                         return status;
>
>                 pos += bytes;
>                 count -= bytes;
>                 written += bytes;
> -               if (did_zero)
> -                       *did_zero = true;
> +               if (args->did_zero)
> +                       *args->did_zero = true;
>         } while (count > 0);
>
>         return written;
> @@ -446,11 +472,15 @@ int
>  iomap_zero_range(struct inode *inode, loff_t pos, loff_t len, bool *did_zero,
>                 const struct iomap_ops *ops)
>  {
> +       struct iomap_zero_range_args args = {
> +               .ops = ops,
> +               .did_zero = did_zero,
> +       };
>         loff_t ret;
>
>         while (len > 0) {
>                 ret = iomap_apply(inode, pos, len, IOMAP_ZERO,
> -                               ops, did_zero, iomap_zero_range_actor);
> +                               ops, &args, iomap_zero_range_actor);
>                 if (ret <= 0)
>                         return ret;
>
> diff --git a/include/linux/iomap.h b/include/linux/iomap.h
> index c61113c71a60..ac7f1b2c1cbe 100644
> --- a/include/linux/iomap.h
> +++ b/include/linux/iomap.h
> @@ -8,6 +8,7 @@ struct fiemap_extent_info;
>  struct inode;
>  struct iov_iter;
>  struct kiocb;
> +struct page;
>  struct vm_area_struct;
>  struct vm_fault;
>
> @@ -71,6 +72,13 @@ struct iomap_ops {
>         int (*iomap_begin)(struct inode *inode, loff_t pos, loff_t length,
>                         unsigned flags, struct iomap *iomap);
>
> +       /*
> +        * Called when done writing to a page (optional; skipped for
> +        * IOMAP_INLINE mappings).

The comment needs updating too, of course.

> +        */
> +       void (*page_write_end)(struct inode *inode, loff_t pos, unsigned copied,
> +                       struct page *page, struct iomap *iomap);
> +
>         /*
>          * Commit and/or unreserve space previous allocated using iomap_begin.
>          * Written indicates the length of the successful write operation which
> --
> 2.17.0
>

With those two changes, is this commit okay as well?

Thanks,
Andreas




More information about the Cluster-devel mailing list