---- 在 星期四, 2020-10-15 12:57:41 Al Viro <viro@xxxxxxxxxxxxxxxxxx> 撰写 ---- > On Thu, Oct 15, 2020 at 11:42:51AM +0800, Chengguang Xu wrote: > > ---- 在 星期四, 2020-10-15 11:25:01 Al Viro <viro@xxxxxxxxxxxxxxxxxx> 撰写 ---- > > > On Sat, Oct 10, 2020 at 10:23:51PM +0800, Chengguang Xu wrote: > > > > Currently there is no notification api for kernel about modification > > > > of vfs inode, in some use cases like overlayfs, this kind of notification > > > > will be very helpful to implement containerized syncfs functionality. > > > > As the first attempt, we introduce marking inode dirty notification so that > > > > overlay's inode could mark itself dirty as well and then only sync dirty > > > > overlay inode while syncfs. > > > > > > Who's responsible for removing the crap from notifier chain? And how does > > > that affect the lifetime of inode? > > > > In this case, overlayfs unregisters call back from the notifier chain of upper inode > > when evicting it's own inode. It will not affect the lifetime of upper inode because > > overlayfs inode holds a reference of upper inode that means upper inode will not be > > evicted while overlayfs inode is still alive. > > Let me see if I've got it right: > * your chain contains 1 (for upper inodes) or 0 (everything else, i.e. the > vast majority of inodes) recepients > * recepient pins the inode for as long as the recepient exists > > That looks like a massive overkill, especially since all you are propagating is > dirtying the suckers. All you really need is one bit in your inode + hash table > indexed by the address of struct inode (well, middle bits thereof, as usual). > With entries embedded into overlayfs-private part of overlayfs inode. And callback > to be called stored in that entry... > Hi AI, Jack, Amir Based on your feedback, I would to change the inode dirty notification something like below, is it acceptable? diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 1492271..48473d9 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -2249,6 +2249,14 @@ void __mark_inode_dirty(struct inode *inode, int flags) trace_writeback_mark_inode_dirty(inode, flags); + if (inode->state & I_OVL_INUSE) { + struct inode *ovl_inode; + + ovl_inode = ilookup5(NULL, (unsigned long)inode, ovl_inode_test, inode); + if (ovl_inode) + __mark_inode_dirty(ovl_inode, flags); + } + /* * Don't do this for I_DIRTY_PAGES - that doesn't actually * dirty the inode itself diff --git a/fs/inode.c b/fs/inode.c index 72c4c34..ed6c85e 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -820,7 +820,7 @@ static struct inode *find_inode(struct super_block *sb, repeat: hlist_for_each_entry(inode, head, i_hash) { - if (inode->i_sb != sb) + if (sb && inode->i_sb != sb) continue; if (!test(inode, data)) continue; Thanks, Chengguang