Page MenuHomeFreeBSD

Fix a swap block allocation race.
ClosedPublic

Authored by markj on Feb 13 2020, 5:24 PM.
Tags
None
Referenced Files
Unknown Object (File)
Tue, Mar 11, 12:30 PM
Unknown Object (File)
Fri, Feb 21, 10:52 AM
Unknown Object (File)
Fri, Feb 21, 9:27 AM
Unknown Object (File)
Fri, Feb 21, 6:13 AM
Unknown Object (File)
Fri, Feb 21, 5:21 AM
Unknown Object (File)
Jan 29 2025, 5:19 PM
Unknown Object (File)
Jan 29 2025, 1:39 AM
Unknown Object (File)
Jan 28 2025, 8:19 AM
Subscribers

Details

Summary

putpages' allocation of swap blocks is done under the global sw_dev
lock. Previously it would drop that lock before inserting the allocated
blocks into the object's trie, creating a window in which swap blocks
are allocated but are not visible to swapoff. This can cause
swp_pager_strategy() to fail and panic the system.

Fix the problem bluntly, by allocating swap blocks under the object
lock.

Diff Detail

Repository
rS FreeBSD src repository - subversion
Lint
Lint Not Applicable
Unit
Tests Not Applicable

Event Timeline

Wake up sleepers when incrementing nsw_wcount_async.

jeff added inline comments.
sys/vm/swap_pager.c
1457 ↗(On Diff #68263)

We should generalize my lockless limit/counting semaphore in uma.

1482–1483 ↗(On Diff #68263)

Unrelated but it's unfortunate that this is required. How many places actually inspect that we can't pass NULL?

1502 ↗(On Diff #68263)

Wouldn't need the double loop if we allocated the buf first. Why did it need to move?

This revision is now accepted and ready to land.Feb 13 2020, 11:03 PM
sys/vm/swap_pager.c
1482–1483 ↗(On Diff #68263)

I'm actually not sure that this is really required, though at least nfs_strategy() assumes that the creds are not equal to NOCRED (NFSNEWCRED will trigger a page fault), and yes it is in principle possible to swap over NFS. The buffer cache seems to handle null credentials. I don't see why we bother setting b_rcred though.

1502 ↗(On Diff #68263)

It doesn't really need to move. It is just more cleanup to do if the swap block allocation fails and I liked having all of the initialization happen in one block. Maybe I will change it to avoid the extra loop.

This revision was automatically updated to reflect the committed changes.