CIFS: Separate page processing from writepages
authorPavel Shilovsky <pshilovsky@samba.org>
Thu, 19 Jun 2014 11:01:03 +0000 (15:01 +0400)
committerSteve French <smfrench@gmail.com>
Sat, 2 Aug 2014 06:23:01 +0000 (01:23 -0500)
Signed-off-by: Pavel Shilovsky <pshilovsky@samba.org>
Reviewed-by: Jeff Layton <jlayton@samba.org>
Signed-off-by: Steve French <smfrench@gmail.com>
fs/cifs/file.c

index 6b6df30cfd899bab81de7d0fd6587fc2cd569848..69d176396d04af6eb40daded4224573b3b91162f 100644 (file)
@@ -1878,6 +1878,86 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
        return rc;
 }
 
+static unsigned int
+wdata_prepare_pages(struct cifs_writedata *wdata, unsigned int found_pages,
+                   struct address_space *mapping,
+                   struct writeback_control *wbc,
+                   pgoff_t end, pgoff_t *index, pgoff_t *next, bool *done)
+{
+       unsigned int nr_pages = 0, i;
+       struct page *page;
+
+       for (i = 0; i < found_pages; i++) {
+               page = wdata->pages[i];
+               /*
+                * At this point we hold neither mapping->tree_lock nor
+                * lock on the page itself: the page may be truncated or
+                * invalidated (changing page->mapping to NULL), or even
+                * swizzled back from swapper_space to tmpfs file
+                * mapping
+                */
+
+               if (nr_pages == 0)
+                       lock_page(page);
+               else if (!trylock_page(page))
+                       break;
+
+               if (unlikely(page->mapping != mapping)) {
+                       unlock_page(page);
+                       break;
+               }
+
+               if (!wbc->range_cyclic && page->index > end) {
+                       *done = true;
+                       unlock_page(page);
+                       break;
+               }
+
+               if (*next && (page->index != *next)) {
+                       /* Not next consecutive page */
+                       unlock_page(page);
+                       break;
+               }
+
+               if (wbc->sync_mode != WB_SYNC_NONE)
+                       wait_on_page_writeback(page);
+
+               if (PageWriteback(page) ||
+                               !clear_page_dirty_for_io(page)) {
+                       unlock_page(page);
+                       break;
+               }
+
+               /*
+                * This actually clears the dirty bit in the radix tree.
+                * See cifs_writepage() for more commentary.
+                */
+               set_page_writeback(page);
+               if (page_offset(page) >= i_size_read(mapping->host)) {
+                       *done = true;
+                       unlock_page(page);
+                       end_page_writeback(page);
+                       break;
+               }
+
+               wdata->pages[i] = page;
+               *next = page->index + 1;
+               ++nr_pages;
+       }
+
+       /* reset index to refind any pages skipped */
+       if (nr_pages == 0)
+               *index = wdata->pages[0]->index + 1;
+
+       /* put any pages we aren't going to use */
+       for (i = nr_pages; i < found_pages; i++) {
+               page_cache_release(wdata->pages[i]);
+               wdata->pages[i] = NULL;
+       }
+
+       return nr_pages;
+}
+
 static int cifs_writepages(struct address_space *mapping,
                           struct writeback_control *wbc)
 {
@@ -1886,7 +1966,6 @@ static int cifs_writepages(struct address_space *mapping,
        pgoff_t end, index;
        struct cifs_writedata *wdata;
        struct TCP_Server_Info *server;
-       struct page *page;
        int rc = 0;
 
        /*
@@ -1944,75 +2023,8 @@ retry:
                        break;
                }
 
-               nr_pages = 0;
-               for (i = 0; i < found_pages; i++) {
-                       page = wdata->pages[i];
-                       /*
-                        * At this point we hold neither mapping->tree_lock nor
-                        * lock on the page itself: the page may be truncated or
-                        * invalidated (changing page->mapping to NULL), or even
-                        * swizzled back from swapper_space to tmpfs file
-                        * mapping
-                        */
-
-                       if (nr_pages == 0)
-                               lock_page(page);
-                       else if (!trylock_page(page))
-                               break;
-
-                       if (unlikely(page->mapping != mapping)) {
-                               unlock_page(page);
-                               break;
-                       }
-
-                       if (!wbc->range_cyclic && page->index > end) {
-                               done = true;
-                               unlock_page(page);
-                               break;
-                       }
-
-                       if (next && (page->index != next)) {
-                               /* Not next consecutive page */
-                               unlock_page(page);
-                               break;
-                       }
-
-                       if (wbc->sync_mode != WB_SYNC_NONE)
-                               wait_on_page_writeback(page);
-
-                       if (PageWriteback(page) ||
-                                       !clear_page_dirty_for_io(page)) {
-                               unlock_page(page);
-                               break;
-                       }
-
-                       /*
-                        * This actually clears the dirty bit in the radix tree.
-                        * See cifs_writepage() for more commentary.
-                        */
-                       set_page_writeback(page);
-
-                       if (page_offset(page) >= i_size_read(mapping->host)) {
-                               done = true;
-                               unlock_page(page);
-                               end_page_writeback(page);
-                               break;
-                       }
-
-                       wdata->pages[i] = page;
-                       next = page->index + 1;
-                       ++nr_pages;
-               }
-
-               /* reset index to refind any pages skipped */
-               if (nr_pages == 0)
-                       index = wdata->pages[0]->index + 1;
-
-               /* put any pages we aren't going to use */
-               for (i = nr_pages; i < found_pages; i++) {
-                       page_cache_release(wdata->pages[i]);
-                       wdata->pages[i] = NULL;
-               }
+               nr_pages = wdata_prepare_pages(wdata, found_pages, mapping, wbc,
+                                              end, &index, &next, &done);
 
                /* nothing to write? */
                if (nr_pages == 0) {