On 06/30, Oleg Nesterov wrote:
>
> On 06/30, Nicholas Piggin wrote:
> >
> > My patch is what actually introduced this ugly
> > bit test, but do we even need it at all? If we do then it's
> > under-commented, I can't see it wouldn't be racy though. Can we just
> > get rid of it entirely?
>
> But then we will need to move io_schedule() down, after test_and_set_bit().
> And we will have the same problem with task->state != RUNNING. Plus more
> complications with "behavior == DROP".

may be someting like this

        for (;;) {
                int intr = 0;

                spin_lock_irq(&q->lock);
                if (signal_pending_state(state, current)) {
                        /* see the comment in prepare_to_wait_event() */
                        list_del_init(&wait->entry);
                        intr = 1;
                } else {
                        if (likely(list_empty(&wait->entry))) {
                                __add_wait_queue_entry_tail(q, wait);
                                SetPageWaiters(page);
                        }
                        set_current_state(state);
                }
                spin_unlock_irq(&q->lock);

                if (behavior == EXCLUSIVE) {
                        if (!test_and_set_bit_lock(bit_nr, &page->flags))
                                break;
                } else {
                        int is_set = test_bit(bit_nr, &page->flags);
                        if (behavior == DROP)
                                put_page(page);
                        if (!is_set)
                                break;
                }

                if (intr) {
                        ret = -EINTR;
                        break;
                }

                io_schedule();

                if (behavior == DROP) {
                        /*
                         * We can no longer safely access page->flags:
                         * even if CONFIG_MEMORY_HOTREMOVE is not enabled,
                         * there is a risk of waiting forever on a page reused
                         * for something that keeps it locked indefinitely.
                         * But best check for -EINTR before breaking.
                         */
                        if (signal_pending_state(state, current))
                                ret = -EINTR;
                        break;
                }
        }

? I dunno...

Oleg.

Reply via email to