]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
Revert "xfs: factor mapping out of xfs_do_writepage"
authorWengang Wang <wen.gang.wang@oracle.com>
Tue, 29 Jan 2019 03:18:40 +0000 (19:18 -0800)
committerBrian Maly <brian.maly@oracle.com>
Wed, 30 Jan 2019 03:58:07 +0000 (22:58 -0500)
This reverts commit 40a82631dc131f1b7f61b2a2fe6351c382aaf04f.

These commits are very possibly to cause SIGBUS issue. (We can't verify
that in customer's environment). Revert them.

Orabug: 29279692

Signed-off-by: Wengang Wang <wen.gang.wang@oracle.com>
Reviewed-by: Shan Hai <shan.hai@oracle.com>
Signed-off-by: Brian Maly <brian.maly@oracle.com>
fs/xfs/xfs_aops.c

index fc26695a88df2384bcfb8ff8531bb80dd0552846..e10ef89b0a42e3e69f6a4832143d84c7215fda02 100644 (file)
@@ -753,127 +753,6 @@ xfs_writepage_submit(
        return status;
 }
 
-static int
-xfs_writepage_map(
-       struct xfs_writepage_ctx *wpc,
-       struct inode            *inode,
-       struct page             *page,
-       loff_t                  offset,
-       __uint64_t              end_offset)
-{
-       struct buffer_head      *bh, *head;
-       ssize_t                 len = 1 << inode->i_blkbits;
-       int                     error = 0;
-       int                     uptodate = 1;
-       int                     count = 0;
-
-       bh = head = page_buffers(page);
-       offset = page_offset(page);
-
-       do {
-               if (offset >= end_offset)
-                       break;
-               if (!buffer_uptodate(bh))
-                       uptodate = 0;
-
-               /*
-                * set_page_dirty dirties all buffers in a page, independent
-                * of their state.  The dirty state however is entirely
-                * meaningless for holes (!mapped && uptodate), so skip
-                * buffers covering holes here.
-                */
-               if (!buffer_mapped(bh) && buffer_uptodate(bh)) {
-                       wpc->imap_valid = false;
-                       continue;
-               }
-
-               if (buffer_unwritten(bh)) {
-                       if (wpc->io_type != XFS_IO_UNWRITTEN) {
-                               wpc->io_type = XFS_IO_UNWRITTEN;
-                               wpc->imap_valid = false;
-                       }
-               } else if (buffer_delay(bh)) {
-                       if (wpc->io_type != XFS_IO_DELALLOC) {
-                               wpc->io_type = XFS_IO_DELALLOC;
-                               wpc->imap_valid = false;
-                       }
-               } else if (buffer_uptodate(bh)) {
-                       if (wpc->io_type != XFS_IO_OVERWRITE) {
-                               wpc->io_type = XFS_IO_OVERWRITE;
-                               wpc->imap_valid = false;
-                       }
-               } else {
-                       if (PageUptodate(page))
-                               ASSERT(buffer_mapped(bh));
-                       /*
-                        * This buffer is not uptodate and will not be
-                        * written to disk.  Ensure that we will put any
-                        * subsequent writeable buffers into a new
-                        * ioend.
-                        */
-                       wpc->imap_valid = false;
-                       continue;
-               }
-
-               if (wpc->imap_valid)
-                       wpc->imap_valid = xfs_imap_valid(inode, &wpc->imap,
-                                                        offset);
-               if (!wpc->imap_valid) {
-                       error = xfs_map_blocks(inode, offset, &wpc->imap,
-                                            wpc->io_type);
-                       if (error)
-                               goto out_error;
-                       wpc->imap_valid = xfs_imap_valid(inode, &wpc->imap,
-                                                        offset);
-               }
-               if (wpc->imap_valid) {
-                       lock_buffer(bh);
-                       if (wpc->io_type != XFS_IO_OVERWRITE)
-                               xfs_map_at_offset(inode, bh, &wpc->imap, offset);
-                       xfs_add_to_ioend(inode, bh, offset, wpc);
-                       count++;
-               }
-
-               if (!wpc->iohead)
-                       wpc->iohead = wpc->ioend;
-
-       } while (offset += len, ((bh = bh->b_this_page) != head));
-
-       if (uptodate && bh == head)
-               SetPageUptodate(page);
-
-       xfs_start_page_writeback(page, 1, count);
-       ASSERT(wpc->iohead || !count);
-       return 0;
-
-out_error:
-       /*
-        * On error, we have to fail the iohead here because we locked buffers
-        * in the ioend chain. If we don't do this, we'll deadlock invalidating
-        * the page as that tries to lock the buffers on the page. Also, because
-        * we may have set pages under writeback, we have to make sure we run
-        * IO completion to mark the error state of the IO appropriately, so we
-        * can't cancel the ioend directly here. That means we have to mark this
-        * page as under writeback if we included any buffers from it in the
-        * ioend chain so that completion treats it correctly.
-        *
-        * If we didn't include the page in the ioend, then we can simply
-        * discard and unlock it as there are no other users of the page or it's
-        * buffers right now. The caller will still need to trigger submission
-        * of outstanding ioends on the writepage context so they are treated
-        * correctly on error.
-        */
-       if (count)
-               xfs_start_page_writeback(page, 0, count);
-       else {
-               xfs_aops_discard_page(page);
-               ClearPageUptodate(page);
-               unlock_page(page);
-       }
-       mapping_set_error(page->mapping, error);
-       return error;
-}
-
 /*
  * Write out a dirty page.
  *
@@ -890,9 +769,13 @@ xfs_do_writepage(
 {
        struct xfs_writepage_ctx *wpc = data;
        struct inode            *inode = page->mapping->host;
+       struct buffer_head      *bh, *head;
        loff_t                  offset;
        __uint64_t              end_offset;
        pgoff_t                 end_index;
+       ssize_t                 len;
+       int                     err, uptodate = 1;
+       int                     count = 0;
 
        trace_xfs_writepage(inode, page, 0, 0);
 
@@ -985,7 +868,112 @@ xfs_do_writepage(
                end_offset = offset;
        }
 
-       return xfs_writepage_map(wpc, inode, page, offset, end_offset);
+       len = 1 << inode->i_blkbits;
+
+       bh = head = page_buffers(page);
+       offset = page_offset(page);
+
+       do {
+               if (offset >= end_offset)
+                       break;
+               if (!buffer_uptodate(bh))
+                       uptodate = 0;
+
+               /*
+                * set_page_dirty dirties all buffers in a page, independent
+                * of their state.  The dirty state however is entirely
+                * meaningless for holes (!mapped && uptodate), so skip
+                * buffers covering holes here.
+                */
+               if (!buffer_mapped(bh) && buffer_uptodate(bh)) {
+                       wpc->imap_valid = false;
+                       continue;
+               }
+
+               if (buffer_unwritten(bh)) {
+                       if (wpc->io_type != XFS_IO_UNWRITTEN) {
+                               wpc->io_type = XFS_IO_UNWRITTEN;
+                               wpc->imap_valid = false;
+                       }
+               } else if (buffer_delay(bh)) {
+                       if (wpc->io_type != XFS_IO_DELALLOC) {
+                               wpc->io_type = XFS_IO_DELALLOC;
+                               wpc->imap_valid = false;
+                       }
+               } else if (buffer_uptodate(bh)) {
+                       if (wpc->io_type != XFS_IO_OVERWRITE) {
+                               wpc->io_type = XFS_IO_OVERWRITE;
+                               wpc->imap_valid = false;
+                       }
+               } else {
+                       if (PageUptodate(page))
+                               ASSERT(buffer_mapped(bh));
+                       /*
+                        * This buffer is not uptodate and will not be
+                        * written to disk.  Ensure that we will put any
+                        * subsequent writeable buffers into a new
+                        * ioend.
+                        */
+                       wpc->imap_valid = 0;
+                       continue;
+               }
+
+               if (wpc->imap_valid)
+                       wpc->imap_valid = xfs_imap_valid(inode, &wpc->imap, offset);
+               if (!wpc->imap_valid) {
+                       err = xfs_map_blocks(inode, offset, &wpc->imap,
+                                            wpc->io_type);
+                       if (err)
+                               goto error;
+                       wpc->imap_valid = xfs_imap_valid(inode, &wpc->imap, offset);
+               }
+               if (wpc->imap_valid) {
+                       lock_buffer(bh);
+                       if (wpc->io_type != XFS_IO_OVERWRITE)
+                               xfs_map_at_offset(inode, bh, &wpc->imap, offset);
+                       xfs_add_to_ioend(inode, bh, offset, wpc);
+                       count++;
+               }
+
+               if (!wpc->iohead)
+                       wpc->iohead = wpc->ioend;
+
+       } while (offset += len, ((bh = bh->b_this_page) != head));
+
+       if (uptodate && bh == head)
+               SetPageUptodate(page);
+
+       xfs_start_page_writeback(page, 1, count);
+
+       ASSERT(wpc->iohead || !count);
+       return 0;
+
+error:
+       /*
+        * On error, we have to fail the iohead here because we buffers locked
+        * in the ioend chain. If we don't do this, we'll deadlock invalidating
+        * the page as that tries to lock the buffers on the page. Also, because
+        * we may have set pages under writeback, we have to make sure we run
+        * IO completion to mark the error state of the IO appropriately, so we
+        * can't cancel the ioend directly here. That means we have to mark this
+        * page as under writeback if we included any buffers from it in the
+        * ioend chain so that completion treats it correctly.
+        *
+        * If we didn't include the page in the ioend, then we can simply
+        * discard and unlock it as there are no other users of the page or it's
+        * buffers right now. The caller will still need to trigger submission
+        * of outstanding ioends on the writepage context so they are treated
+        * correctly on error.
+        */
+       if (count)
+               xfs_start_page_writeback(page, 0, count);
+       else {
+               xfs_aops_discard_page(page);
+               ClearPageUptodate(page);
+               unlock_page(page);
+       }
+       mapping_set_error(page->mapping, err);
+       return err;
 
 redirty:
        redirty_page_for_writepage(wbc, page);