• Miklos Szeredi's avatar
    fuse: allow splice to move pages · ce534fb0
    Miklos Szeredi authored
    When splicing buffers to the fuse device with SPLICE_F_MOVE, try to
    move pages from the pipe buffer into the page cache.  This allows
    populating the fuse filesystem's cache without ever touching the page
    contents, i.e. zero copy read capability.
    
    The following steps are performed when trying to move a page into the
    page cache:
    
     - buf->ops->confirm() to make sure the new page is uptodate
     - buf->ops->steal() to try to remove the new page from it's previous place
     - remove_from_page_cache() on the old page
     - add_to_page_cache_locked() on the new page
    
    If any of the above steps fail (non fatally) then the code falls back
    to copying the page.  In particular ->steal() will fail if there are
    external references (other than the page cache and the pipe buffer) to
    the page.
    
    Also since the remove_from_page_cache() + add_to_page_cache_locked()
    are non-atomic it is possible that the page cache is repopulated in
    between the two and add_to_page_cache_locked() will fail.  This could
    be fixed by creating a new atomic replace_page_cache_page() function.
    
    fuse_readpages_end() needed to be reworked so it works even if
    page->mapping is NULL for some or all pages which can happen if the
    add_to_page_cache_locked() failed.
    
    A number of sanity checks were added to make sure the stolen pages
    don't have weird flags set, etc...  These could be moved into generic
    splice/steal code.
    Signed-off-by: default avatarMiklos Szeredi <mszeredi@suse.cz>
    ce534fb0
dev.c 34.5 KB