Probe sparse support for a regular file using fallocate().
(fd: libc::c_int)
| 360 | |
| 361 | /// Probe sparse support for a regular file using fallocate(). |
| 362 | fn probe_file_sparse_support(fd: libc::c_int) -> bool { |
| 363 | // SAFETY: FFI call with valid fd |
| 364 | let file_size = unsafe { libc::lseek(fd, 0, libc::SEEK_END) }; |
| 365 | if file_size < 0 { |
| 366 | let err = io::Error::last_os_error(); |
| 367 | warn!("Failed to get file size for sparse probe: {err}"); |
| 368 | return false; |
| 369 | } |
| 370 | |
| 371 | // SAFETY: FFI call with valid fd, probing past EOF is safe with KEEP_SIZE |
| 372 | let punch_hole = |
| 373 | unsafe { libc::fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, file_size, 1) } |
| 374 | == 0; |
| 375 | |
| 376 | if !punch_hole { |
| 377 | let err = io::Error::last_os_error(); |
| 378 | if err.raw_os_error() == Some(libc::EOPNOTSUPP) { |
| 379 | debug!("File does not support FALLOC_FL_PUNCH_HOLE: {err}"); |
| 380 | } else { |
| 381 | debug!("PUNCH_HOLE probe returned unexpected error: {err}"); |
| 382 | } |
| 383 | } |
| 384 | |
| 385 | // SAFETY: FFI call with valid fd, probing past EOF is safe with KEEP_SIZE |
| 386 | let zero_range = |
| 387 | unsafe { libc::fallocate(fd, FALLOC_FL_ZERO_RANGE | FALLOC_FL_KEEP_SIZE, file_size, 1) } |
| 388 | == 0; |
| 389 | |
| 390 | if !zero_range { |
| 391 | let err = io::Error::last_os_error(); |
| 392 | if err.raw_os_error() == Some(libc::EOPNOTSUPP) { |
| 393 | debug!("File does not support FALLOC_FL_ZERO_RANGE: {err}"); |
| 394 | } |
| 395 | } |
| 396 | |
| 397 | let supported = punch_hole || zero_range; |
| 398 | info!( |
| 399 | "Probed file sparse support: punch_hole={punch_hole}, zero_range={zero_range} => {supported}" |
| 400 | ); |
| 401 | supported |
| 402 | } |
| 403 | |
| 404 | /// Probe sparse support for a block device. |
| 405 | /// |
no outgoing calls
no test coverage detected