forked from openzfs/zfs
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This commit contains a few things. However, the most important thing was correcting the race condition between spa_sync() when it updates spa_syncing_txg and the call to dmu_buf_undirty. I originally was grabing the SPA config lock as a RW_READER, but that was complete nonesense as the same config lock was grabbed as a reader in spa_sync() when updating spa_syncing_txg. The main issue is there is a race condition when checking if a dirtry record's TXG is syncing and trying to undirty it. Without any synchronization, the ASSERT: ASSERT(db->db_objset == dmu_objset_pool(db->db_objset)->dp_meta_objset || txg != spa_syncing_txg(dmu_objset_spa(db->db_objset)) in dbuf_undirty can be true if a dirty record's TXG is being moved over to the syncing phase after the check in dmu_buf_undirty. The ASSERT is states that dbuf_undirty can only be called in open context. We were abusing this by trying to undirty a dirty record that may in fact have moved over to the syncing context. In order to resolve this, we now will wait for any previous dirty records for the dbuf to sync out if there is an associated ARC buf for it. This is necessary to make sure we can destroy the ARC buf and force all future readers to read from the direct IO write BP. This does mean there is a performance penalty for mixing buffered and direct writes together, but in reality no one should be doing that anyways. This is the least heavy handed way to not have to implement synchronization while still keeping TXG consistency valid with mixed IO writes. In the event of an IO error with direct IO writes, we still can call dbuf_undirty as all direct IO writes happen in open context. While also adding this wait condition for mixed writes, I did add another wait condition for reads with direct IO reads. If a user is mixing buffered and direct reads together, the direct read will wait for the buffered read to complete and read out of the ARC. We do this so we do not issue down a second read down to disk when one to the ARC is already taking place. For both of these I added a new kstat in dbuf.c so we can monitor when they occur. Also, I reverted the interface for dbuf_undirty back to its original format. I also changed grabbing a direct IO BP to be a function in dbuf.c and no longer a static function in dmu_direct.c. This way the same logic can be used in dbuf_read() and dmu_read_abd(). This makes the code cleaner to read in both as oppose to only dbuf_read_abd(). I also did some general clean up of the code. Nothing major but just some stray spaces and changing IO to be I/O. Signed-off-by: Brian Atkinson <[email protected]>
- Loading branch information
1 parent
9a54a4b
commit 31983d2
Showing
7 changed files
with
139 additions
and
183 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.