On Sat, Jul 02, 2022 at 12:50:47AM +1000, Imran Khan wrote: > Kick fsnotify only if an event is not already scheduled for target > kernfs node. commit b8f35fa1188b ("kernfs: Change kernfs_notify_list to > llist.") changed kernfs_notify_list to a llist. > Prior to this list was a singly linked list, protected by > kernfs_notify_lock. Whenever a kernfs_node was added to the list > its ->attr.notify_next was set to head of the list and upon removal > ->attr.notify_next was reset to NULL. Addition to kernfs_notify_list > would only happen if kernfs_node was not already in the list i.e. > if ->attr.notify_next was NULL. commit b8f35fa1188b ("kernfs: Change > kernfs_notify_list to llist.") removed this checking and this was wrong > as it resulted in multiple additions for same kernfs_node. > > So far this bug only got reflected with some console related setting. > Nathan found this issue when console was specified both in DT and in > kernel command line and Marek found this issue when earlycon was enabled. > > This patch avoids adding an already added kernfs_node into notify list. > > Reported-by: Nathan Chancellor <nathan@xxxxxxxxxx> > Reported-by: Marek Szyprowski <m.szyprowski@xxxxxxxxxxx> This should also include: Reported-by: Michael Walle <michael@xxxxxxxx> > Tested-by: Marek Szyprowski <m.szyprowski@xxxxxxxxxxx> > Fixes: b8f35fa1188b ("kernfs: Change kernfs_notify_list to llist.") > Signed-off-by: Imran Khan <imran.f.khan@xxxxxxxxxx> For the ARCH=um case that I noticed: Tested-by: Nathan Chancellor <nathan@xxxxxxxxxx> > --- > fs/kernfs/file.c | 9 ++++++--- > 1 file changed, 6 insertions(+), 3 deletions(-) > > diff --git a/fs/kernfs/file.c b/fs/kernfs/file.c > index bb933221b4bae..e8ec054e11c63 100644 > --- a/fs/kernfs/file.c > +++ b/fs/kernfs/file.c > @@ -917,6 +917,7 @@ static void kernfs_notify_workfn(struct work_struct *work) > if (free == NULL) > return; > > + free->next = NULL; > attr = llist_entry(free, struct kernfs_elem_attr, notify_next); > kn = attribute_to_node(attr, struct kernfs_node, attr); > root = kernfs_root(kn); > @@ -992,9 +993,11 @@ void kernfs_notify(struct kernfs_node *kn) > rcu_read_unlock(); > > /* schedule work to kick fsnotify */ > - kernfs_get(kn); > - llist_add(&kn->attr.notify_next, &kernfs_notify_list); > - schedule_work(&kernfs_notify_work); > + if (kn->attr.notify_next.next != NULL) { > + kernfs_get(kn); > + llist_add(&kn->attr.notify_next, &kernfs_notify_list); > + schedule_work(&kernfs_notify_work); > + } > } > EXPORT_SYMBOL_GPL(kernfs_notify); > > > base-commit: 6cc11d2a1759275b856e464265823d94aabd5eaf > -- > 2.30.2 >