On Wed, Mar 8, 2023 at 10:14 AM Takashi Iwai <tiwai@xxxxxxx> wrote: > > On Wed, 08 Mar 2023 10:08:24 +0100, > Patrik Jakobsson wrote: > > > > On Wed, Mar 8, 2023 at 7:36 AM Takashi Iwai <tiwai@xxxxxxx> wrote: > > > > > > The recent fix for the deferred I/O by the commit > > > 3efc61d95259 ("fbdev: Fix invalid page access after closing deferred I/O devices") > > > caused a regression when the same fb device is opened/closed while > > > it's being used. It resulted in a frozen screen even if something > > > is redrawn there after the close. The breakage is because the patch > > > was made under a wrong assumption of a single open; in the current > > > code, fb_deferred_io_release() cleans up the page mapping of the > > > pageref list and it calls cancel_delayed_work_sync() unconditionally, > > > where both are no correct behavior for multiple opens. > > > > > > This patch adds a refcount for the opens of the device, and applies > > > the cleanup only when all files get closed. > > > > > > Fixes: 3efc61d95259 ("fbdev: Fix invalid page access after closing deferred I/O devices") > > > Cc: <stable@xxxxxxxxxxxxxxx> > > > Signed-off-by: Takashi Iwai <tiwai@xxxxxxx> > > > --- > > > drivers/video/fbdev/core/fb_defio.c | 16 +++++++++++++--- > > > include/linux/fb.h | 1 + > > > 2 files changed, 14 insertions(+), 3 deletions(-) > > > > > > diff --git a/drivers/video/fbdev/core/fb_defio.c b/drivers/video/fbdev/core/fb_defio.c > > > index aa5f059d0222..9dcec9e020b6 100644 > > > --- a/drivers/video/fbdev/core/fb_defio.c > > > +++ b/drivers/video/fbdev/core/fb_defio.c > > > @@ -305,17 +305,19 @@ void fb_deferred_io_open(struct fb_info *info, > > > struct inode *inode, > > > struct file *file) > > > { > > > + struct fb_deferred_io *fbdefio = info->fbdefio; > > > + > > > file->f_mapping->a_ops = &fb_deferred_io_aops; > > > + fbdefio->opens++; > > > } > > > EXPORT_SYMBOL_GPL(fb_deferred_io_open); > > > > > > -void fb_deferred_io_release(struct fb_info *info) > > > +static void fb_deferred_io_release_internal(struct fb_info *info) > > > > Maybe a better name would be fb_deferred_io_lastclose() to be more in > > line with DRM? > > Sounds good. > > > > { > > > struct fb_deferred_io *fbdefio = info->fbdefio; > > > struct page *page; > > > int i; > > > > > > - BUG_ON(!fbdefio); > > > > Should the BUG_ON be put back into fb_deferred_io_release()? > > It can be, but honestly speaking, such a BUG_ON() is utterly useless. > It should be WARN_ON() and return, if the sanity check is inevitably > needed. I agree. It's rather pointless since it's already checked in fb_release(). > > > > cancel_delayed_work_sync(&info->deferred_work); > > > > > > /* clear out the mapping that we setup */ > > > @@ -324,13 +326,21 @@ void fb_deferred_io_release(struct fb_info *info) > > > page->mapping = NULL; > > > } > > > } > > > + > > > +void fb_deferred_io_release(struct fb_info *info) > > > +{ > > > + struct fb_deferred_io *fbdefio = info->fbdefio; > > > + > > > + if (!--fbdefio->opens) > > > + fb_deferred_io_release_internal(info); > > > > I think this can race so we need locking. > > This one is fine, as it's always called inside the fb lock in the > caller side. Maybe worth to comment in the code. Ah, yes, fb_release() locks around everything. Then we are fine. A comment would be nice. > > > > +} > > > EXPORT_SYMBOL_GPL(fb_deferred_io_release); > > > > > > void fb_deferred_io_cleanup(struct fb_info *info) > > > { > > > struct fb_deferred_io *fbdefio = info->fbdefio; > > > > > > - fb_deferred_io_release(info); > > > + fb_deferred_io_release_internal(info); > > > > > > kvfree(info->pagerefs); > > > mutex_destroy(&fbdefio->lock); > > > diff --git a/include/linux/fb.h b/include/linux/fb.h > > > index d8d20514ea05..29674a29d1c4 100644 > > > --- a/include/linux/fb.h > > > +++ b/include/linux/fb.h > > > @@ -212,6 +212,7 @@ struct fb_deferred_io { > > > /* delay between mkwrite and deferred handler */ > > > unsigned long delay; > > > bool sort_pagereflist; /* sort pagelist by offset */ > > > + int opens; /* number of opened files */ > > > > I would prefer the name num_opens (or open_count as in DRM) instead of > > opens since it can be interpreted as a verb. > > I don't mind either way. I'd choose the latter. > > > Also, don't we need it to be atomic_t? > > It's always in the fb lock, so that should be fine with the standard > int. Yes > > > thanks, > > Takashi