mirror of
				https://git.proxmox.com/git/mirror_zfs.git
				synced 2025-10-26 18:05:04 +03:00 
			
		
		
		
	txg_wait_synced_flags: add TXG_WAIT_SUSPEND flag to not wait if pool suspended
This allows a caller to request a wait for txg sync, with an appropriate error return if the pool is suspended or becomes suspended during the wait. To support this, txg_wait_kick() is added to signal the sync condvar, which wakes up the waiters, causing them to loop and reconsider their wait conditions again. zio_suspend() now calls this to trigger the break if the pool suspends while waiting. Sponsored-by: Klara, Inc. Sponsored-by: Wasabi Technology, Inc. Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed-by: Alexander Motin <mav@FreeBSD.org> Reviewed-by: Paul Dagnelie <paul.dagnelie@klarasystems.com> Signed-off-by: Rob Norris <rob.norris@klarasystems.com> Closes #17355
This commit is contained in:
		
							parent
							
								
									8487945034
								
							
						
					
					
						commit
						468d22d60c
					
				| @ -25,6 +25,7 @@ | |||||||
|  */ |  */ | ||||||
| /*
 | /*
 | ||||||
|  * Copyright (c) 2012, 2017 by Delphix. All rights reserved. |  * Copyright (c) 2012, 2017 by Delphix. All rights reserved. | ||||||
|  |  * Copyright (c) 2025, Klara, Inc. | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #ifndef _SYS_TXG_H | #ifndef _SYS_TXG_H | ||||||
| @ -78,6 +79,9 @@ typedef enum { | |||||||
| 
 | 
 | ||||||
| 	/* If a signal arrives while waiting, abort and return EINTR */ | 	/* If a signal arrives while waiting, abort and return EINTR */ | ||||||
| 	TXG_WAIT_SIGNAL = (1 << 0), | 	TXG_WAIT_SIGNAL = (1 << 0), | ||||||
|  | 
 | ||||||
|  | 	/* If the pool suspends while waiting, abort and return ESHUTDOWN. */ | ||||||
|  | 	TXG_WAIT_SUSPEND = (1 << 1), | ||||||
| } txg_wait_flag_t; | } txg_wait_flag_t; | ||||||
| 
 | 
 | ||||||
| struct dsl_pool; | struct dsl_pool; | ||||||
| @ -111,6 +115,11 @@ extern int txg_wait_synced_flags(struct dsl_pool *dp, uint64_t txg, | |||||||
|  */ |  */ | ||||||
| extern void txg_wait_synced(struct dsl_pool *dp, uint64_t txg); | extern void txg_wait_synced(struct dsl_pool *dp, uint64_t txg); | ||||||
| 
 | 
 | ||||||
|  | /*
 | ||||||
|  |  * Wake all threads waiting in txg_wait_synced_flags() so they can reevaluate. | ||||||
|  |  */ | ||||||
|  | extern void txg_wait_kick(struct dsl_pool *dp); | ||||||
|  | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Wait until the given transaction group, or one after it, is |  * Wait until the given transaction group, or one after it, is | ||||||
|  * the open transaction group.  Try to make this happen as soon |  * the open transaction group.  Try to make this happen as soon | ||||||
|  | |||||||
| @ -23,6 +23,7 @@ | |||||||
|  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. |  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. | ||||||
|  * Portions Copyright 2011 Martin Matuska |  * Portions Copyright 2011 Martin Matuska | ||||||
|  * Copyright (c) 2012, 2019 by Delphix. All rights reserved. |  * Copyright (c) 2012, 2019 by Delphix. All rights reserved. | ||||||
|  |  * Copyright (c) 2025, Klara, Inc. | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #include <sys/zfs_context.h> | #include <sys/zfs_context.h> | ||||||
| @ -705,7 +706,7 @@ txg_wait_synced_flags(dsl_pool_t *dp, uint64_t txg, txg_wait_flag_t flags) | |||||||
| 	int error = 0; | 	int error = 0; | ||||||
| 	tx_state_t *tx = &dp->dp_tx; | 	tx_state_t *tx = &dp->dp_tx; | ||||||
| 
 | 
 | ||||||
| 	ASSERT0(flags & ~TXG_WAIT_SIGNAL); | 	ASSERT0(flags & ~(TXG_WAIT_SIGNAL | TXG_WAIT_SUSPEND)); | ||||||
| 	ASSERT(!dsl_pool_config_held(dp)); | 	ASSERT(!dsl_pool_config_held(dp)); | ||||||
| 
 | 
 | ||||||
| 	mutex_enter(&tx->tx_sync_lock); | 	mutex_enter(&tx->tx_sync_lock); | ||||||
| @ -723,6 +724,15 @@ txg_wait_synced_flags(dsl_pool_t *dp, uint64_t txg, txg_wait_flag_t flags) | |||||||
| 	 * else interesting happens, we'll set an error and break out. | 	 * else interesting happens, we'll set an error and break out. | ||||||
| 	 */ | 	 */ | ||||||
| 	while (tx->tx_synced_txg < txg) { | 	while (tx->tx_synced_txg < txg) { | ||||||
|  | 		if ((flags & TXG_WAIT_SUSPEND) && spa_suspended(dp->dp_spa)) { | ||||||
|  | 			/*
 | ||||||
|  | 			 * Pool suspended and the caller does not want to | ||||||
|  | 			 * block; inform them immediately. | ||||||
|  | 			 */ | ||||||
|  | 			error = SET_ERROR(ESHUTDOWN); | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		dprintf("broadcasting sync more " | 		dprintf("broadcasting sync more " | ||||||
| 		    "tx_synced=%llu waiting=%llu dp=%px\n", | 		    "tx_synced=%llu waiting=%llu dp=%px\n", | ||||||
| 		    (u_longlong_t)tx->tx_synced_txg, | 		    (u_longlong_t)tx->tx_synced_txg, | ||||||
| @ -756,6 +766,15 @@ txg_wait_synced(dsl_pool_t *dp, uint64_t txg) | |||||||
| 	VERIFY0(txg_wait_synced_flags(dp, txg, TXG_WAIT_NONE)); | 	VERIFY0(txg_wait_synced_flags(dp, txg, TXG_WAIT_NONE)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void | ||||||
|  | txg_wait_kick(dsl_pool_t *dp) | ||||||
|  | { | ||||||
|  | 	tx_state_t *tx = &dp->dp_tx; | ||||||
|  | 	mutex_enter(&tx->tx_sync_lock); | ||||||
|  | 	cv_broadcast(&tx->tx_sync_done_cv); | ||||||
|  | 	mutex_exit(&tx->tx_sync_lock); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Wait for the specified open transaction group.  Set should_quiesce |  * Wait for the specified open transaction group.  Set should_quiesce | ||||||
|  * when the current open txg should be quiesced immediately. |  * when the current open txg should be quiesced immediately. | ||||||
|  | |||||||
| @ -2714,6 +2714,8 @@ zio_suspend(spa_t *spa, zio_t *zio, zio_suspend_reason_t reason) | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	mutex_exit(&spa->spa_suspend_lock); | 	mutex_exit(&spa->spa_suspend_lock); | ||||||
|  | 
 | ||||||
|  | 	txg_wait_kick(spa->spa_dsl_pool); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int | int | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Rob Norris
						Rob Norris