mirror of
				https://git.proxmox.com/git/mirror_zfs.git
				synced 2025-10-26 18:05:04 +03:00 
			
		
		
		
	Add more constraints for block cloning.
- We cannot clone into files with smaller block size if there is more than one block, since we can not grow the block size. - Block size must be power-of-2 if destination offset != 0, since there can be no multiple blocks of non-power-of-2 size. The first should handle the case when destination file has several blocks but still is not bigger than one block of the source file. The second fixes panic in dmu_buf_hold_array_by_dnode() on attempt to concatenate files with equal but non-power-of-2 block sizes. While there, assert that error is reported if we made no progress. Reviewed-by: Pawel Jakub Dawidek <pawel@dawidek.net> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed-by: Rob Norris <rob.norris@klarasystems.com> Reviewed-by: Kay Pedersen <mail@mkwg.de> Reviewed-by: Umer Saleem <usaleem@ixsystems.com> Signed-off-by: Alexander Motin <mav@FreeBSD.org> Sponsored by: iXsystems, Inc. Closes #15251
This commit is contained in:
		
							parent
							
								
									12ce45f260
								
							
						
					
					
						commit
						5cc1876f14
					
				| @ -1172,9 +1172,20 @@ zfs_clone_range(znode_t *inzp, uint64_t *inoffp, znode_t *outzp, | ||||
| 	inblksz = inzp->z_blksz; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * We cannot clone into files with different block size. | ||||
| 	 * We cannot clone into files with different block size if we can't | ||||
| 	 * grow it (block size is already bigger or more than one block). | ||||
| 	 */ | ||||
| 	if (inblksz != outzp->z_blksz && outzp->z_size > inblksz) { | ||||
| 	if (inblksz != outzp->z_blksz && (outzp->z_size > outzp->z_blksz || | ||||
| 	    outzp->z_size > inblksz)) { | ||||
| 		error = SET_ERROR(EINVAL); | ||||
| 		goto unlock; | ||||
| 	} | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Block size must be power-of-2 if destination offset != 0. | ||||
| 	 * There can be no multiple blocks of non-power-of-2 size. | ||||
| 	 */ | ||||
| 	if (outoff != 0 && !ISP2(inblksz)) { | ||||
| 		error = SET_ERROR(EINVAL); | ||||
| 		goto unlock; | ||||
| 	} | ||||
| @ -1358,6 +1369,12 @@ unlock: | ||||
| 		*inoffp += done; | ||||
| 		*outoffp += done; | ||||
| 		*lenp = done; | ||||
| 	} else { | ||||
| 		/*
 | ||||
| 		 * If we made no progress, there must be a good reason. | ||||
| 		 * EOF is handled explicitly above, before the loop. | ||||
| 		 */ | ||||
| 		ASSERT3S(error, !=, 0); | ||||
| 	} | ||||
| 
 | ||||
| 	zfs_exit_two(inzfsvfs, outzfsvfs, FTAG); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Alexander Motin
						Alexander Motin