On Fri, 27 Jun 2014 13:57:39 +0400
Pavel Shilovsky <[email protected]> wrote:

> Signed-off-by: Pavel Shilovsky <[email protected]>
> ---
>  fs/cifs/file.c | 152 
> +++++++++++++++++++++++++++++++--------------------------
>  1 file changed, 82 insertions(+), 70 deletions(-)
> 
> diff --git a/fs/cifs/file.c b/fs/cifs/file.c
> index 6b6df30..69d1763 100644
> --- a/fs/cifs/file.c
> +++ b/fs/cifs/file.c
> @@ -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) {

Reviewed-by:
-- 
Jeff Layton <[email protected]>
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to