mirror of
				https://git.proxmox.com/git/mirror_zfs.git
				synced 2025-10-26 18:05:04 +03:00 
			
		
		
		
	Fix scn_queue races on very old pools
Code for pools before version 11 uses dmu_objset_find_dp() to scan for children datasets/clones. It calls enqueue_clones_cb() and enqueue_cb() callbacks in parallel from multiple taskq threads. It ends up bad for scan_ds_queue_insert(), corrupting scn_queue AVL-tree. Fix it by introducing a mutex to protect those two scan_ds_queue_insert() calls. All other calls are done from the sync thread and so serialized. Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed-by: Brian Atkinson <batkinson@lanl.gov> Signed-off-by: Alexander Motin <mav@FreeBSD.org> Sponsored by: iXsystems, Inc. Closes #16162
This commit is contained in:
		
							parent
							
								
									6724746596
								
							
						
					
					
						commit
						41f2a9c81f
					
				| @ -173,6 +173,7 @@ typedef struct dsl_scan { | |||||||
| 	dsl_scan_phys_t scn_phys;	/* on disk representation of scan */ | 	dsl_scan_phys_t scn_phys;	/* on disk representation of scan */ | ||||||
| 	dsl_scan_phys_t scn_phys_cached; | 	dsl_scan_phys_t scn_phys_cached; | ||||||
| 	avl_tree_t scn_queue;		/* queue of datasets to scan */ | 	avl_tree_t scn_queue;		/* queue of datasets to scan */ | ||||||
|  | 	kmutex_t scn_queue_lock;	/* serializes scn_queue inserts */ | ||||||
| 	uint64_t scn_queues_pending;	/* outstanding data to issue */ | 	uint64_t scn_queues_pending;	/* outstanding data to issue */ | ||||||
| 	/* members needed for syncing error scrub status to disk */ | 	/* members needed for syncing error scrub status to disk */ | ||||||
| 	dsl_errorscrub_phys_t errorscrub_phys; | 	dsl_errorscrub_phys_t errorscrub_phys; | ||||||
|  | |||||||
| @ -491,6 +491,7 @@ dsl_scan_init(dsl_pool_t *dp, uint64_t txg) | |||||||
| 
 | 
 | ||||||
| 	avl_create(&scn->scn_queue, scan_ds_queue_compare, sizeof (scan_ds_t), | 	avl_create(&scn->scn_queue, scan_ds_queue_compare, sizeof (scan_ds_t), | ||||||
| 	    offsetof(scan_ds_t, sds_node)); | 	    offsetof(scan_ds_t, sds_node)); | ||||||
|  | 	mutex_init(&scn->scn_queue_lock, NULL, MUTEX_DEFAULT, NULL); | ||||||
| 	avl_create(&scn->scn_prefetch_queue, scan_prefetch_queue_compare, | 	avl_create(&scn->scn_prefetch_queue, scan_prefetch_queue_compare, | ||||||
| 	    sizeof (scan_prefetch_issue_ctx_t), | 	    sizeof (scan_prefetch_issue_ctx_t), | ||||||
| 	    offsetof(scan_prefetch_issue_ctx_t, spic_avl_node)); | 	    offsetof(scan_prefetch_issue_ctx_t, spic_avl_node)); | ||||||
| @ -646,6 +647,7 @@ dsl_scan_fini(dsl_pool_t *dp) | |||||||
| 
 | 
 | ||||||
| 		scan_ds_queue_clear(scn); | 		scan_ds_queue_clear(scn); | ||||||
| 		avl_destroy(&scn->scn_queue); | 		avl_destroy(&scn->scn_queue); | ||||||
|  | 		mutex_destroy(&scn->scn_queue_lock); | ||||||
| 		scan_ds_prefetch_queue_clear(scn); | 		scan_ds_prefetch_queue_clear(scn); | ||||||
| 		avl_destroy(&scn->scn_prefetch_queue); | 		avl_destroy(&scn->scn_prefetch_queue); | ||||||
| 
 | 
 | ||||||
| @ -2727,8 +2729,10 @@ enqueue_clones_cb(dsl_pool_t *dp, dsl_dataset_t *hds, void *arg) | |||||||
| 			return (err); | 			return (err); | ||||||
| 		ds = prev; | 		ds = prev; | ||||||
| 	} | 	} | ||||||
|  | 	mutex_enter(&scn->scn_queue_lock); | ||||||
| 	scan_ds_queue_insert(scn, ds->ds_object, | 	scan_ds_queue_insert(scn, ds->ds_object, | ||||||
| 	    dsl_dataset_phys(ds)->ds_prev_snap_txg); | 	    dsl_dataset_phys(ds)->ds_prev_snap_txg); | ||||||
|  | 	mutex_exit(&scn->scn_queue_lock); | ||||||
| 	dsl_dataset_rele(ds, FTAG); | 	dsl_dataset_rele(ds, FTAG); | ||||||
| 	return (0); | 	return (0); | ||||||
| } | } | ||||||
| @ -2919,8 +2923,10 @@ enqueue_cb(dsl_pool_t *dp, dsl_dataset_t *hds, void *arg) | |||||||
| 		ds = prev; | 		ds = prev; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	mutex_enter(&scn->scn_queue_lock); | ||||||
| 	scan_ds_queue_insert(scn, ds->ds_object, | 	scan_ds_queue_insert(scn, ds->ds_object, | ||||||
| 	    dsl_dataset_phys(ds)->ds_prev_snap_txg); | 	    dsl_dataset_phys(ds)->ds_prev_snap_txg); | ||||||
|  | 	mutex_exit(&scn->scn_queue_lock); | ||||||
| 	dsl_dataset_rele(ds, FTAG); | 	dsl_dataset_rele(ds, FTAG); | ||||||
| 	return (0); | 	return (0); | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Alexander Motin
						Alexander Motin