> > > +         if (!dead_swap_page &&
> > > +             (PageTestandClearReferenced(page) || page->age > 0 ||
> > > +              (!page->buffers && page_count(page) > 1) ||
> > > +              page_ramdisk(page))) {
> >             ^^^^^^^^^^^^^^^^^^^^^^
> > >                   del_page_from_inactive_dirty_list(page);
> > >                   add_page_to_active_list(page);
> > >                   continue;
> > 
> > #define page_ramdisk(page) \
> >         (page->buffers && (MAJOR(page->buffers->b_dev) == RAMDISK_MAJOR))
> > 
> > Are you sure that no one will release buffers under your hands?
> 
> Two things can happen:
> 
> 1) the page gets ramdisk buffers _after_ we look at it first,
>    in this case the page isn't freeable and will be moved to
>    the active list on the next page_launder() loop
> 
> 2) the page loses its ramdisk buffers after we look at it,
>    now the page is freeable, but we won't see it again until
>    it is moved from the active list to the inactive_dirty
>    list again
> 
> Any side effects harmful enough to warrant complicating this
> test ?

I mean this: Let's have a page with buffers. It does not care whether the
buffers are on ramdisk or not. 

CPU 0                           CPU 1
is executing the code marked    is executing try_to_free_buffers on
above with ^^^^^^^:             the same page (it can be, because CPU 0
                                did not lock the page)

(page->buffers &&

                                page->buffers = NULL

MAJOR(page->buffers->b_dev) == 
        RAMDISK_MAJOR)) ===> Oops, NULL pointer dereference!



Maybe compiler CSE optimization will eliminate the double load of
page->buffers, but we must not rely on it. If the compiler doesn't
optimize it, it can produce random oopses.

Mikulas

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to