lkml.org 
[lkml]   [2021]   [Oct]   [18]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Subject[PATCH 40/67] vfs, fscache: Force ->write_inode() to occur if cookie pinned for writeback
    From
    Date
    Use an inode flag, I_PINNING_FSCACHE_WB, to indicate that a cookie is
    pinned in use by that inode for the purposes of writeback.

    Pinning is necessary because the in-use pin from the open file is released
    before the writeback takes place, but if the resources aren't pinned, the
    dirty data can't be written to the cache.

    Signed-off-by: David Howells <dhowells@redhat.com>
    ---

    fs/fscache/io.c | 38 ++++++++++++++++++++++++++++++++++++++
    include/linux/fscache.h | 41 +++++++++++++++++++++++++++++++++++++++++
    2 files changed, 79 insertions(+)

    diff --git a/fs/fscache/io.c b/fs/fscache/io.c
    index ef4b0606019d..25976413fe34 100644
    --- a/fs/fscache/io.c
    +++ b/fs/fscache/io.c
    @@ -214,3 +214,41 @@ int __fscache_fallback_write_page(struct fscache_cookie *cookie, struct page *pa
    return ret;
    }
    EXPORT_SYMBOL(__fscache_fallback_write_page);
    +
    +/**
    + * fscache_set_page_dirty - Mark page dirty and pin a cache object for writeback
    + * @page: The page being dirtied
    + * @cookie: The cookie referring to the cache object
    + *
    + * Set the dirty flag on a page and pin an in-use cache object in memory when
    + * dirtying a page so that writeback can later write to it. This is intended
    + * to be called from the filesystem's ->set_page_dirty() method.
    + *
    + * Returns 1 if PG_dirty was set on the page, 0 otherwise.
    + */
    +int fscache_set_page_dirty(struct page *page, struct fscache_cookie *cookie)
    +{
    + struct inode *inode = page->mapping->host;
    + bool need_use = false;
    +
    + _enter("");
    +
    + if (!__set_page_dirty_nobuffers(page))
    + return 0;
    + if (!fscache_cookie_valid(cookie))
    + return 1;
    +
    + if (!(inode->i_state & I_PINNING_FSCACHE_WB)) {
    + spin_lock(&inode->i_lock);
    + if (!(inode->i_state & I_PINNING_FSCACHE_WB)) {
    + inode->i_state |= I_PINNING_FSCACHE_WB;
    + need_use = true;
    + }
    + spin_unlock(&inode->i_lock);
    +
    + if (need_use)
    + fscache_use_cookie(cookie, true);
    + }
    + return 1;
    +}
    +EXPORT_SYMBOL(fscache_set_page_dirty);
    diff --git a/include/linux/fscache.h b/include/linux/fscache.h
    index fa7eef2674bf..abf5413c3151 100644
    --- a/include/linux/fscache.h
    +++ b/include/linux/fscache.h
    @@ -512,6 +512,47 @@ int fscache_write(struct netfs_cache_resources *cres,

    #endif /* FSCACHE_USE_NEW_IO_API */

    +#if __fscache_available
    +extern int fscache_set_page_dirty(struct page *page, struct fscache_cookie *cookie);
    +#else
    +#define fscache_set_page_dirty(PAGE, COOKIE) (__set_page_dirty_nobuffers((PAGE)))
    +#endif
    +
    +/**
    + * fscache_unpin_writeback - Unpin writeback resources
    + * @wbc: The writeback control
    + * @cookie: The cookie referring to the cache object
    + *
    + * Unpin the writeback resources pinned by fscache_set_page_dirty(). This is
    + * intended to be called by the netfs's ->write_inode() method.
    + */
    +static inline void fscache_unpin_writeback(struct writeback_control *wbc,
    + struct fscache_cookie *cookie)
    +{
    + if (wbc->unpinned_fscache_wb)
    + fscache_unuse_cookie(cookie, NULL, NULL);
    +}
    +
    +/**
    + * fscache_clear_inode_writeback - Clear writeback resources pinned by an inode
    + * @cookie: The cookie referring to the cache object
    + * @inode: The inode to clean up
    + * @aux: Auxiliary data to apply to the inode
    + *
    + * Clear any writeback resources held by an inode when the inode is evicted.
    + * This must be called before clear_inode() is called.
    + */
    +static inline void fscache_clear_inode_writeback(struct fscache_cookie *cookie,
    + struct inode *inode,
    + const void *aux)
    +{
    + if (inode->i_state & I_PINNING_FSCACHE_WB) {
    + loff_t i_size = i_size_read(inode);
    + fscache_unuse_cookie(cookie, aux, &i_size);
    + }
    +
    +}
    +
    #ifdef FSCACHE_USE_FALLBACK_IO_API

    /**

    \
     
     \ /
      Last update: 2021-10-18 17:04    [W:2.511 / U:0.008 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site