linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
From: David Hildenbrand <david@redhat.com>
To: Alistair Popple <apopple@nvidia.com>, akpm@linux-foundation.org
Cc: willy@infradead.org, dhowells@redhat.com, hughd@google.com,
	linux-kernel@vger.kernel.org, linux-mm@kvack.org,
	jglisse@redhat.com, jgg@nvidia.com, rcampbell@nvidia.com,
	jhubbard@nvidia.com
Subject: Re: [PATCH v4] mm/migrate.c: Rework migration_entry_wait() to not take a pageref
Date: Mon, 22 Nov 2021 19:15:27 +0100	[thread overview]
Message-ID: <d2697d9e-92b7-649f-5afa-313350578286@redhat.com> (raw)
In-Reply-To: <20211118020754.954425-1-apopple@nvidia.com>

On 18.11.21 03:07, Alistair Popple wrote:
> This fixes the FIXME in migrate_vma_check_page().
> 
> Before migrating a page migration code will take a reference and check
> there are no unexpected page references, failing the migration if there
> are. When a thread faults on a migration entry it will take a temporary
> reference to the page to wait for the page to become unlocked signifying
> the migration entry has been removed.
> 
> This reference is dropped just prior to waiting on the page lock,
> however the extra reference can cause migration failures so it is
> desirable to avoid taking it.
> 
> As migration code already has a reference to the migrating page an extra
> reference to wait on PG_locked is unnecessary so long as the reference
> can't be dropped whilst setting up the wait.
> 
> When faulting on a migration entry the ptl is taken to check the
> migration entry. Removing a migration entry also requires the ptl, and
> migration code won't drop its page reference until after the migration
> entry has been removed. Therefore retaining the ptl of a migration entry
> is sufficient to ensure the page has a reference. Reworking
> migration_entry_wait() to hold the ptl until the wait setup is complete
> means the extra page reference is no longer needed.
> 

I really like this, thanks for this work!

[...]

> +#ifdef CONFIG_MIGRATION
> +/**
> + * migration_entry_wait_on_locked - Wait for a migration entry to be removed
> + * @folio: folio referenced by the migration entry.
> + * @ptep: mapped pte pointer. This function will return with the ptep unmapped.
> + * @ptl: already locked ptl. This function will drop the lock.
> + *
> + * Wait for a migration entry referencing the given page to be removed. This is
> + * equivalent to put_and_wait_on_page_locked(page, TASK_UNINTERRUPTIBLE) except
> + * this can be called without taking a reference on the page. Instead this
> + * should be called while holding the ptl for the migration entry referencing
> + * the page.
> + *
> + * Returns after unmapping and unlocking the pte/ptl with pte_unmap_unlock().

You could maybe make it clear that callers have to pass the ptep only
for PTE migration entries. For a PMD migration entry, pass NULL.

> + *
> + * This follows the same logic as wait_on_page_bit_common() so see the comments

s/wait_on_page_bit_common/folio_wait_bit_common/ ?

> + * there.
> + */
> +void migration_entry_wait_on_locked(struct folio *folio, pte_t *ptep,
> +				spinlock_t *ptl)
> +{
> +	struct wait_page_queue wait_page;
> +	wait_queue_entry_t *wait = &wait_page.wait;
> +	bool thrashing = false;
> +	bool delayacct = false;
> +	unsigned long pflags;
> +	wait_queue_head_t *q;
> +
> +	q = folio_waitqueue(folio);
> +	if (!folio_test_uptodate(folio) && folio_test_workingset(folio)) {
> +		if (!folio_test_swapbacked(folio)) {
> +			delayacct_thrashing_start();
> +			delayacct = true;
> +		}
> +		psi_memstall_enter(&pflags);
> +		thrashing = true;
> +	}
> +
> +	init_wait(wait);
> +	wait->func = wake_page_function;
> +	wait_page.folio = folio;
> +	wait_page.bit_nr = PG_locked;
> +	wait->flags = 0;
> +
> +	spin_lock_irq(&q->lock);
> +	folio_set_waiters(folio);
> +	if (!folio_trylock_flag(folio, PG_locked, wait))
> +		__add_wait_queue_entry_tail(q, wait);
> +	spin_unlock_irq(&q->lock);
> +
> +	/*
> +	 * If a migration entry exists for the page the migration path must hold
> +	 * a valid reference to the page, and it must take the ptl to remove the
> +	 * migration entry. So the page is valid until the ptl is dropped.
> +	 */
> +	if (ptep)
> +		pte_unmap_unlock(ptep, ptl);
> +	else
> +		spin_unlock(ptl);
> +
> +	for (;;) {
> +		unsigned int flags;
> +
> +		set_current_state(TASK_UNINTERRUPTIBLE);
> +
> +		/* Loop until we've been woken or interrupted */
> +		flags = smp_load_acquire(&wait->flags);
> +		if (!(flags & WQ_FLAG_WOKEN)) {
> +			if (signal_pending_state(TASK_UNINTERRUPTIBLE, current))
> +				break;
> +
> +			io_schedule();
> +			continue;
> +		}
> +		break;
> +	}
> +
> +	finish_wait(q, wait);
> +
> +	if (thrashing) {
> +		if (delayacct)
> +			delayacct_thrashing_end();
> +		psi_memstall_leave(&pflags);
> +	}
> +}
> +#endif
> +

I'm fairly new to the glory details of core migration entry and page bit
waiting code, but it makes sense to me and removing the temporary extra
references is very nice! Feel free to add my

Acked-by: David Hildenbrand <david@redhat.com>

-- 
Thanks,

David / dhildenb



  reply	other threads:[~2021-11-22 18:15 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-11-18  2:07 Alistair Popple
2021-11-22 18:15 ` David Hildenbrand [this message]
2021-11-22 23:28   ` Alistair Popple

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=d2697d9e-92b7-649f-5afa-313350578286@redhat.com \
    --to=david@redhat.com \
    --cc=akpm@linux-foundation.org \
    --cc=apopple@nvidia.com \
    --cc=dhowells@redhat.com \
    --cc=hughd@google.com \
    --cc=jgg@nvidia.com \
    --cc=jglisse@redhat.com \
    --cc=jhubbard@nvidia.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=rcampbell@nvidia.com \
    --cc=willy@infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox