Message ID | 163456866523.2614702.2234665737111683988.stgit@warthog.procyon.org.uk (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | fscache: Rewrite index API and management system | expand |
On Mon, 2021-10-18 at 15:51 +0100, David Howells wrote: > 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/fs-writeback.c | 8 ++++++++ > include/linux/fs.h | 3 +++ > include/linux/fscache.h | 1 + > include/linux/writeback.h | 1 + > 4 files changed, 13 insertions(+) > > diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c > index 81ec192ce067..f3122831c4fe 100644 > --- a/fs/fs-writeback.c > +++ b/fs/fs-writeback.c > @@ -1666,6 +1666,13 @@ __writeback_single_inode(struct inode *inode, struct writeback_control *wbc) > > if (mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) > inode->i_state |= I_DIRTY_PAGES; > + else if (unlikely(inode->i_state & I_PINNING_FSCACHE_WB)) { > + if (!(inode->i_state & I_DIRTY_PAGES)) { > + inode->i_state &= ~I_PINNING_FSCACHE_WB; > + wbc->unpinned_fscache_wb = true; > + dirty |= I_PINNING_FSCACHE_WB; /* Cause write_inode */ > + } > + } IDGI: how would I_PINNING_FSCACHE_WB get set in the first place? > > spin_unlock(&inode->i_lock); > > @@ -1675,6 +1682,7 @@ __writeback_single_inode(struct inode *inode, struct writeback_control *wbc) > if (ret == 0) > ret = err; > } > + wbc->unpinned_fscache_wb = false; > trace_writeback_single_inode(inode, wbc, nr_to_write); > return ret; > } > diff --git a/include/linux/fs.h b/include/linux/fs.h > index 197493507744..336739fed3e9 100644 > --- a/include/linux/fs.h > +++ b/include/linux/fs.h > @@ -2420,6 +2420,8 @@ static inline void kiocb_clone(struct kiocb *kiocb, struct kiocb *kiocb_src, > * Used to detect that mark_inode_dirty() should not move > * inode between dirty lists. > * > + * I_PINNING_FSCACHE_WB Inode is pinning an fscache object for writeback. > + * > * Q: What is the difference between I_WILL_FREE and I_FREEING? > */ > #define I_DIRTY_SYNC (1 << 0) > @@ -2442,6 +2444,7 @@ static inline void kiocb_clone(struct kiocb *kiocb, struct kiocb *kiocb_src, > #define I_CREATING (1 << 15) > #define I_DONTCACHE (1 << 16) > #define I_SYNC_QUEUED (1 << 17) > +#define I_PINNING_FSCACHE_WB (1 << 18) > > #define I_DIRTY_INODE (I_DIRTY_SYNC | I_DIRTY_DATASYNC) > #define I_DIRTY (I_DIRTY_INODE | I_DIRTY_PAGES) > diff --git a/include/linux/fscache.h b/include/linux/fscache.h > index 01558d155799..ba4878b56717 100644 > --- a/include/linux/fscache.h > +++ b/include/linux/fscache.h > @@ -19,6 +19,7 @@ > #include <linux/pagemap.h> > #include <linux/pagevec.h> > #include <linux/list_bl.h> > +#include <linux/writeback.h> > #include <linux/netfs.h> > > #if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE) > diff --git a/include/linux/writeback.h b/include/linux/writeback.h > index d1f65adf6a26..2fda288600d3 100644 > --- a/include/linux/writeback.h > +++ b/include/linux/writeback.h > @@ -69,6 +69,7 @@ struct writeback_control { > unsigned for_reclaim:1; /* Invoked from the page allocator */ > unsigned range_cyclic:1; /* range_start is cyclic */ > unsigned for_sync:1; /* sync(2) WB_SYNC_ALL writeback */ > + unsigned unpinned_fscache_wb:1; /* Cleared I_PINNING_FSCACHE_WB */ > > /* > * When writeback IOs are bounced through async layers, only the > >
Jeff Layton <jlayton@redhat.com> wrote:
> IDGI: how would I_PINNING_FSCACHE_WB get set in the first place?
This is used by a later patch, but because this modifies a very commonly used
header file, it was causing mass rebuilds every time I pushed or popped it. I
can merge it back in now, I think.
David
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 81ec192ce067..f3122831c4fe 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -1666,6 +1666,13 @@ __writeback_single_inode(struct inode *inode, struct writeback_control *wbc) if (mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) inode->i_state |= I_DIRTY_PAGES; + else if (unlikely(inode->i_state & I_PINNING_FSCACHE_WB)) { + if (!(inode->i_state & I_DIRTY_PAGES)) { + inode->i_state &= ~I_PINNING_FSCACHE_WB; + wbc->unpinned_fscache_wb = true; + dirty |= I_PINNING_FSCACHE_WB; /* Cause write_inode */ + } + } spin_unlock(&inode->i_lock); @@ -1675,6 +1682,7 @@ __writeback_single_inode(struct inode *inode, struct writeback_control *wbc) if (ret == 0) ret = err; } + wbc->unpinned_fscache_wb = false; trace_writeback_single_inode(inode, wbc, nr_to_write); return ret; } diff --git a/include/linux/fs.h b/include/linux/fs.h index 197493507744..336739fed3e9 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2420,6 +2420,8 @@ static inline void kiocb_clone(struct kiocb *kiocb, struct kiocb *kiocb_src, * Used to detect that mark_inode_dirty() should not move * inode between dirty lists. * + * I_PINNING_FSCACHE_WB Inode is pinning an fscache object for writeback. + * * Q: What is the difference between I_WILL_FREE and I_FREEING? */ #define I_DIRTY_SYNC (1 << 0) @@ -2442,6 +2444,7 @@ static inline void kiocb_clone(struct kiocb *kiocb, struct kiocb *kiocb_src, #define I_CREATING (1 << 15) #define I_DONTCACHE (1 << 16) #define I_SYNC_QUEUED (1 << 17) +#define I_PINNING_FSCACHE_WB (1 << 18) #define I_DIRTY_INODE (I_DIRTY_SYNC | I_DIRTY_DATASYNC) #define I_DIRTY (I_DIRTY_INODE | I_DIRTY_PAGES) diff --git a/include/linux/fscache.h b/include/linux/fscache.h index 01558d155799..ba4878b56717 100644 --- a/include/linux/fscache.h +++ b/include/linux/fscache.h @@ -19,6 +19,7 @@ #include <linux/pagemap.h> #include <linux/pagevec.h> #include <linux/list_bl.h> +#include <linux/writeback.h> #include <linux/netfs.h> #if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE) diff --git a/include/linux/writeback.h b/include/linux/writeback.h index d1f65adf6a26..2fda288600d3 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h @@ -69,6 +69,7 @@ struct writeback_control { unsigned for_reclaim:1; /* Invoked from the page allocator */ unsigned range_cyclic:1; /* range_start is cyclic */ unsigned for_sync:1; /* sync(2) WB_SYNC_ALL writeback */ + unsigned unpinned_fscache_wb:1; /* Cleared I_PINNING_FSCACHE_WB */ /* * When writeback IOs are bounced through async layers, only the
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/fs-writeback.c | 8 ++++++++ include/linux/fs.h | 3 +++ include/linux/fscache.h | 1 + include/linux/writeback.h | 1 + 4 files changed, 13 insertions(+)