On Mon, Jun 26, 2023 at 1:17 PM Suren Baghdasaryan <surenb@xxxxxxxxxx> wrote: > > kernfs_ops.release operation can be called from kernfs_drain_open_files > which is not tied to the file's real lifecycle. Introduce a new kernfs_ops > free operation which is called only when the last fput() of the file is > performed and therefore is strictly tied to the file's lifecycle. This > operation will be used for freeing resources tied to the file, like > waitqueues used for polling the file. While this patchset touches kernfs, cgroups and psi areas (3 different maintainers), I think cgroups are the most relevant area for it, so IMHO Tejun's tree would be the right one to get them once reviewed and acknowledged. Thanks! > > Signed-off-by: Suren Baghdasaryan <surenb@xxxxxxxxxx> > --- > fs/kernfs/file.c | 8 +++++--- > include/linux/kernfs.h | 5 +++++ > 2 files changed, 10 insertions(+), 3 deletions(-) > > diff --git a/fs/kernfs/file.c b/fs/kernfs/file.c > index 40c4661f15b7..acc52d23d8f6 100644 > --- a/fs/kernfs/file.c > +++ b/fs/kernfs/file.c > @@ -766,7 +766,7 @@ static int kernfs_fop_open(struct inode *inode, struct file *file) > > /* used from release/drain to ensure that ->release() is called exactly once */ > static void kernfs_release_file(struct kernfs_node *kn, > - struct kernfs_open_file *of) > + struct kernfs_open_file *of, bool final) > { > /* > * @of is guaranteed to have no other file operations in flight and > @@ -787,6 +787,8 @@ static void kernfs_release_file(struct kernfs_node *kn, > of->released = true; > of_on(of)->nr_to_release--; > } > + if (final && kn->attr.ops->free) > + kn->attr.ops->free(of); > } > > static int kernfs_fop_release(struct inode *inode, struct file *filp) > @@ -798,7 +800,7 @@ static int kernfs_fop_release(struct inode *inode, struct file *filp) > struct mutex *mutex; > > mutex = kernfs_open_file_mutex_lock(kn); > - kernfs_release_file(kn, of); > + kernfs_release_file(kn, of, true); > mutex_unlock(mutex); > } > > @@ -852,7 +854,7 @@ void kernfs_drain_open_files(struct kernfs_node *kn) > } > > if (kn->flags & KERNFS_HAS_RELEASE) > - kernfs_release_file(kn, of); > + kernfs_release_file(kn, of, false); > } > > WARN_ON_ONCE(on->nr_mmapped || on->nr_to_release); > diff --git a/include/linux/kernfs.h b/include/linux/kernfs.h > index 73f5c120def8..a7e404ff31bb 100644 > --- a/include/linux/kernfs.h > +++ b/include/linux/kernfs.h > @@ -273,6 +273,11 @@ struct kernfs_ops { > */ > int (*open)(struct kernfs_open_file *of); > void (*release)(struct kernfs_open_file *of); > + /* > + * Free resources tied to the lifecycle of the file, like a > + * waitqueue used for polling. > + */ > + void (*free)(struct kernfs_open_file *of); > > /* > * Read is handled by either seq_file or raw_read(). > -- > 2.41.0.162.gfafddb0af9-goog >