netfilter: fix nf_conntrack_bridge/ipv6 link error
[linux-2.6-microblaze.git] / fs / iomap.c
index abdd18e..23ef63f 100644 (file)
@@ -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,6 +240,26 @@ iomap_read_page_end_io(struct bio_vec *bvec, int error)
        iomap_read_finish(iop, page);
 }
 
+static void
+iomap_read_end_io(struct bio *bio)
+{
+       int error = blk_status_to_errno(bio->bi_status);
+       struct bio_vec *bvec;
+       struct bvec_iter_all iter_all;
+
+       bio_for_each_segment_all(bvec, bio, iter_all)
+               iomap_read_page_end_io(bvec, error);
+       bio_put(bio);
+}
+
+struct iomap_readpage_ctx {
+       struct page             *cur_page;
+       bool                    cur_page_in_bio;
+       bool                    is_readahead;
+       struct bio              *bio;
+       struct list_head        *pages;
+};
+
 static void
 iomap_read_inline_data(struct inode *inode, struct page *page,
                struct iomap *iomap)
@@ -268,27 +280,6 @@ iomap_read_inline_data(struct inode *inode, struct page *page,
        SetPageUptodate(page);
 }
 
-static void
-iomap_read_end_io(struct bio *bio)
-{
-       int error = blk_status_to_errno(bio->bi_status);
-       struct bio_vec *bvec;
-       int i;
-       struct bvec_iter_all iter_all;
-
-       bio_for_each_segment_all(bvec, bio, i, iter_all)
-               iomap_read_page_end_io(bvec, error);
-       bio_put(bio);
-}
-
-struct iomap_readpage_ctx {
-       struct page             *cur_page;
-       bool                    cur_page_in_bio;
-       bool                    is_readahead;
-       struct bio              *bio;
-       struct list_head        *pages;
-};
-
 static loff_t
 iomap_readpage_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
                struct iomap *iomap)
@@ -665,6 +656,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 +666,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 +684,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 +744,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 +765,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 +772,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);
@@ -1592,9 +1598,8 @@ static void iomap_dio_bio_end_io(struct bio *bio)
                if (!bio_flagged(bio, BIO_NO_PAGE_REF)) {
                        struct bvec_iter_all iter_all;
                        struct bio_vec *bvec;
-                       int i;
 
-                       bio_for_each_segment_all(bvec, bio, i, iter_all)
+                       bio_for_each_segment_all(bvec, bio, iter_all)
                                put_page(bvec->bv_page);
                }
                bio_put(bio);