severity 1123504 serious
found 1123504 1.1.0-5
retitle 1123504 thin-provisioning-tools - rust dependency updates


I hope to update rust-termion to version 4 soon, the debian
dependencies in thin-provisioning-tools allow the new version
but the cargo dependencies do not.

The new version of termion is now in sid, so this is now a ftbfs

I also have a couple more rust package updates coming up that
will affect thin-privisioning-tools, I've prepared an updated
debdiff to cover those too.

diff -Nru thin-provisioning-tools-1.1.0/debian/changelog 
thin-provisioning-tools-1.1.0/debian/changelog
--- thin-provisioning-tools-1.1.0/debian/changelog      2025-10-19 
12:15:27.000000000 +0000
+++ thin-provisioning-tools-1.1.0/debian/changelog      2025-12-17 
00:59:31.000000000 +0000
@@ -1,3 +1,12 @@
+thin-provisioning-tools (1.1.0-5.1) UNRELEASED; urgency=medium
+
+  * Non-maintainer upload.
+  * Relax cargo dependencies on termion, fixedbitset, roaring.
+  * Add patch based on upstream commit to deal with changed type of
+    slice entries in fixedbitset.
+
+ -- Peter Michael Green <[email protected]>  Wed, 17 Dec 2025 00:59:31 +0000
+
 thin-provisioning-tools (1.1.0-5) unstable; urgency=medium
 
   * Update rust dependencies, again. (closes: #1117378)
diff -Nru thin-provisioning-tools-1.1.0/debian/.gitignore 
thin-provisioning-tools-1.1.0/debian/.gitignore
--- thin-provisioning-tools-1.1.0/debian/.gitignore     2025-10-19 
12:15:27.000000000 +0000
+++ thin-provisioning-tools-1.1.0/debian/.gitignore     1970-01-01 
00:00:00.000000000 +0000
@@ -1,7 +0,0 @@
-/debhelper*
-/*.debhelper*
-/*.substvars
-/cargo_home/
-/cargo_registry/
-/files
-/thin-provisioning-tools/
diff -Nru thin-provisioning-tools-1.1.0/debian/patches/debian-changes 
thin-provisioning-tools-1.1.0/debian/patches/debian-changes
--- thin-provisioning-tools-1.1.0/debian/patches/debian-changes 2025-10-19 
12:15:27.000000000 +0000
+++ thin-provisioning-tools-1.1.0/debian/patches/debian-changes 2025-12-17 
00:59:31.000000000 +0000
@@ -1,11 +1,7 @@
-diff --git a/.cargo-checksum.json b/.cargo-checksum.json
-new file mode 100644
-index 
0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
-diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
-new file mode 100644
-index 
0000000000000000000000000000000000000000..a3240a084f5f4374c38470467d51462e4d6bf905
+Index: thin-provisioning-tools-1.1.0/.gitlab-ci.yml
+===================================================================
 --- /dev/null
-+++ b/.gitlab-ci.yml
++++ thin-provisioning-tools-1.1.0/.gitlab-ci.yml
 @@ -0,0 +1,6 @@
 +include:
 +- local: debian/pipeline/workflow.yml
@@ -13,10 +9,9 @@
 +- local: debian/pipeline/source.yml
 +- local: debian/pipeline/build.yml
 +- local: debian/pipeline/test.yml
-diff --git a/Cargo.lock b/Cargo.lock
-deleted file mode 100644
-index 
a21223c91a816a1c90ea05632f6c1357213c86ba..0000000000000000000000000000000000000000
---- a/Cargo.lock
+Index: thin-provisioning-tools-1.1.0/Cargo.lock
+===================================================================
+--- thin-provisioning-tools-1.1.0.orig/Cargo.lock
 +++ /dev/null
 @@ -1,1226 +0,0 @@
 -# This file is automatically @generated by Cargo.
@@ -1245,10 +1240,10 @@
 - "quote",
 - "syn 2.0.72",
 -]
-diff --git a/Cargo.toml b/Cargo.toml
-index 
47703bfc3d68581367458a98eee7e8cd18d016fd..3e1e74e476590413ea097d5643a35a2e8e0f310f
 100644
---- a/Cargo.toml
-+++ b/Cargo.toml
+Index: thin-provisioning-tools-1.1.0/Cargo.toml
+===================================================================
+--- thin-provisioning-tools-1.1.0.orig/Cargo.toml
++++ thin-provisioning-tools-1.1.0/Cargo.toml
 @@ -8,7 +8,7 @@ license = "GPL-3.0-only"
  [dependencies]
  atty = "0.2"
@@ -1258,7 +1253,7 @@
  byteorder = "1.4"
  clap = { version = "4.5", default-features = false, features = [
    "std",
-@@ -19,7 +19,7 @@ clap = { version = "4.5", default-features = false, features 
= [
+@@ -19,7 +19,7 @@ clap = { version = "4.5", default-featur
  ] }
  crc32c = "0.6"
  data-encoding = "2.5"
@@ -1278,9 +1273,10 @@
 +quick-xml = ">= 0.36"
  rand = "0.8"
 -rangemap = "1.5"
-+rangemap = "1"
- roaring = "0.10"
+-roaring = "0.10"
 -rio = { git = "https://github.com/jthornber/rio";, branch = "master", optional 
= true }
++rangemap = "1"
++roaring = ">= 0.10"
  safemem = "0.3"
  threadpool = "1.8"
 -thiserror = "1.0"
@@ -1288,13 +1284,14 @@
  tui = { version = "0.19", default-features = false, features = [
    "termion",
  ], optional = true }
- termion = { version = "1.5", optional = true }
+-termion = { version = "1.5", optional = true }
 -udev = "0.7"
++termion = { version = ">= 1.5", optional = true }
 +udev = "0"
  
  [dev-dependencies]
  duct = "0.13"
-@@ -55,7 +54,7 @@ thinp = { path = ".", features = ["devtools"] }
+@@ -55,7 +54,7 @@ thinp = { path = ".", features = ["devto
  
  [features]
  devtools = ["tui", "termion"]
diff -Nru thin-provisioning-tools-1.1.0/debian/patches/fixedbitset-0.5 
thin-provisioning-tools-1.1.0/debian/patches/fixedbitset-0.5
--- thin-provisioning-tools-1.1.0/debian/patches/fixedbitset-0.5        
1970-01-01 00:00:00.000000000 +0000
+++ thin-provisioning-tools-1.1.0/debian/patches/fixedbitset-0.5        
2025-12-17 00:59:31.000000000 +0000
@@ -0,0 +1,309 @@
+This patch is based on the upstream commit described below, adapted
+by Peter Michael Green to support both the old and new versions of
+fixedbitset.
+
+commit af7fdbf6f2d5b1db3ba6d20abf8f6eb5a1dc21a9
+Author: Ming-Hung Tsai <[email protected]>
+Date:   Tue Jun 17 21:18:57 2025 +0800
+
+    [build] Update fixedbitset to v0.5.7
+    
+    Since v0.5, FixedBitSet has used 64-bit blocks where possible,
+    improving performance on set operations.
+
+Index: thin-provisioning-tools-1.1.0/src/era/dump.rs
+===================================================================
+--- thin-provisioning-tools-1.1.0.orig/src/era/dump.rs
++++ thin-provisioning-tools-1.1.0/src/era/dump.rs
+@@ -242,9 +242,11 @@ fn dump_writeset(
+     let mut end: u32 = 0;
+     for (index, entry) in bits.as_slice().iter().enumerate() {
+         let mut n = *entry;
++        let bits_per_block = (std::mem::size_of_val(&n) * 8) as u32;
++        let bits_shift = bits_per_block.trailing_zeros();
+ 
+-        if n == u32::MAX {
+-            end = std::cmp::min(end + 32, ws.nr_bits);
++        if n == !0 {
++            end = std::cmp::min(end + bits_per_block, ws.nr_bits);
+             continue;
+         }
+ 
+@@ -269,7 +271,7 @@ fn dump_writeset(
+         }
+ 
+         // emit the range if it ends before the entry boundary
+-        let endpos = ((index as u32) << 5) + 32;
++        let endpos = (index as u32 + 1) << bits_shift;
+         if end < endpos {
+             if end > begin {
+                 let m = ir::MarkedBlocks {
+Index: thin-provisioning-tools-1.1.0/src/pdata/bitset.rs
+===================================================================
+--- thin-provisioning-tools-1.1.0.orig/src/pdata/bitset.rs
++++ thin-provisioning-tools-1.1.0/src/pdata/bitset.rs
+@@ -7,6 +7,9 @@ use crate::pdata::array::{self, ArrayBlo
+ use crate::pdata::array_walker::{ArrayVisitor, ArrayWalker};
+ use crate::pdata::space_map::*;
+ 
++#[cfg(test)]
++mod tests;
++
+ //------------------------------------------
+ 
+ pub struct CheckedBitSet {
+@@ -89,13 +92,21 @@ impl ArrayVisitor<u64> for BitsetVisitor
+ struct BitsetCollector {
+     bits: Mutex<FixedBitSet>,
+     nr_bits: usize,
++    nr_entries: usize,
++}
++
++fn  elementsize<T>(_v : &[T]) -> usize {
++    std::mem::size_of::<T>()
+ }
+ 
+ impl BitsetCollector {
+     fn new(nr_bits: usize) -> BitsetCollector {
++        let bits = FixedBitSet::with_capacity(nr_bits);
++        let bitsperelement = elementsize(bits.as_slice()) * 8;
+         BitsetCollector {
+-            bits: Mutex::new(FixedBitSet::with_capacity(nr_bits)),
++            bits: Mutex::new(bits),
+             nr_bits,
++            nr_entries: div_up(nr_bits, bitsperelement as usize),
+         }
+     }
+ 
+@@ -104,30 +115,77 @@ impl BitsetCollector {
+     }
+ }
+ 
++//#[cfg(target_pointer_width = "32")]
++fn copy_to_32_bit_slice_le<T: std::convert::TryFrom<u64>>(dest: &mut [T], 
src: &[u64]) where <T as TryFrom<u64>>::Error: std::fmt::Debug {
++    assert!((std::mem::size_of::<T>() * 8) == 32);
++
++    let mut pos = 0;
++    for &val in src {
++        if pos == dest.len() {
++            break;
++        }
++
++        dest[pos] = (val & u32::MAX as u64).try_into().unwrap();
++        pos += 1;
++
++        if pos < dest.len() {
++            dest[pos] = (val >> 32 as u64).try_into().unwrap();
++            pos += 1;
++        }
++    }
++}
++
+ impl ArrayVisitor<u64> for BitsetCollector {
+     fn visit(&self, index: u64, b: ArrayBlock<u64>) -> array::Result<()> {
+-        let mut bitset = self.bits.lock().unwrap();
+-        let mut idx = (index as usize * b.header.max_entries as usize) << 1; 
// index of u32 in bitset array
+-        let idx_end = div_up(self.nr_bits, 32);
+-        let mut dest = bitset.as_mut_slice().iter_mut().skip(idx);
+-        for entry in b.values.iter() {
+-            let lower = (*entry & (u32::MAX as u64)) as u32;
+-            *(dest.next().ok_or_else(|| {
+-                array::value_err(format!("bitset size exceeds limit: {} 
bits", self.nr_bits))
+-            })?) = lower;
+-            idx += 1;
++      let mut bitset = self.bits.lock().unwrap();
++      let bitsperentry = elementsize(bitset.as_slice()) * 8;
++      if bitsperentry == 64 {
++        let begin = index as usize * b.header.max_entries as usize;
++        let end = begin + b.values.len();
+ 
+-            if idx == idx_end {
+-                break;
+-            }
++        if begin >= self.nr_entries || end > self.nr_entries {
++            return Err(array::value_err(format!(
++                "bitset size exceeds limit: {} bits",
++                self.nr_bits
++            )));
++        }
++
++        let src: &[_] = unsafe {
++            std::slice::from_raw_parts(b.values.as_ptr() as *const _, 
b.values.len())
++        };
++        let dest: &mut [_] = &mut bitset.as_mut_slice()[begin..end];
++        dest.copy_from_slice(src);
+ 
+-            let upper = (*entry >> 32) as u32;
+-            *(dest.next().ok_or_else(|| {
+-                array::value_err(format!("bitset size exceeds limit: {} 
bits", self.nr_bits))
+-            })?) = upper;
+-            idx += 1;
++        Ok(())
++      } else {
++        let begin = (index as usize * b.header.max_entries as usize) * 2;
++        let end = begin + b.values.len() * 2;
++
++        /*
++         * For 32-bit targets, FixedBitSet stores its bits as an array of 
32-bit
++         * usize entries, while the source ArrayBlock uses u64. When the 
number of
++         * 32-bit usize entries required to represent the bitset is odd, the 
upper
++         * half of the last u64 in the source is unused during conversion.
++         * The check below ensures the source ArrayBlock fits the allocated
++         * FixedBitSet, allowing at most one unused usize entry from the 
source.
++         *
++         * The check below is safe and correct when `self.nr_entries` is even,
++         * since the estimated size `end` is even as well, making
++         * `end == self.nr_entries + 1` impossible in this case.
++         */
++        if begin >= self.nr_entries || end > self.nr_entries + 1 {
++            return Err(array::value_err(format!(
++                "bitset size exceeds limit: {} bits",
++                self.nr_bits
++            )));
+         }
++
++        let end = std::cmp::min(end, self.nr_entries);
++        let dest = &mut bitset.as_mut_slice()[begin..end];
++        copy_to_32_bit_slice_le(dest, &b.values);
++
+         Ok(())
++      }
+     }
+ }
+ 
+Index: thin-provisioning-tools-1.1.0/src/pdata/bitset/tests.rs
+===================================================================
+--- /dev/null
++++ thin-provisioning-tools-1.1.0/src/pdata/bitset/tests.rs
+@@ -0,0 +1,118 @@
++use super::*;
++
++use anyhow::Result;
++
++use crate::io_engine::core::CoreIoEngine;
++use crate::pdata::array::{calc_max_entries, unpack_array_block, ArrayBlock};
++use crate::pdata::array_builder::ArrayBlockBuilder;
++use crate::write_batcher::WriteBatcher;
++
++struct BitsetBuilder {
++    w: WriteBatcher,
++}
++
++impl BitsetBuilder {
++    fn new(engine: Arc<dyn IoEngine + Send + Sync>) -> Self {
++        let sm = 
Arc::new(Mutex::new(CoreSpaceMap::<u8>::new(engine.get_nr_blocks())));
++        Self {
++            w: WriteBatcher::new(engine, sm, 16),
++        }
++    }
++
++    fn build_bitset_blocks(&mut self, bits: &FixedBitSet) -> Result<Vec<u64>> 
{
++        let nr_entries = div_up(bits.len(), 64);
++        let mut builder = ArrayBlockBuilder::<u64>::new(nr_entries as u64);
++        let mut cur_pos = 0;
++        let mut entry = 0;
++
++        for bit in bits.ones() {
++            let pos = (bit >> 6) as u64;
++            let mask = 1 << (bit & 63);
++            if pos == cur_pos {
++                entry |= mask;
++            } else {
++                builder.push_value(&mut self.w, cur_pos, entry)?;
++                cur_pos = pos;
++                entry = mask;
++            }
++        }
++        builder.push_value(&mut self.w, cur_pos, entry)?;
++
++        let ablocks = builder.complete(&mut self.w)?;
++        self.w.flush()?;
++
++        Ok(ablocks)
++    }
++
++    fn read_bitset_blocks(&mut self, blocks: &[u64]) -> 
Result<Vec<ArrayBlock<u64>>> {
++        let mut ablocks = Vec::with_capacity(blocks.len());
++
++        for &bn in blocks {
++            let b = self.w.engine.read(bn)?;
++            let ablock = unpack_array_block::<u64>(&[bn], b.get_data())?;
++            ablocks.push(ablock);
++        }
++
++        Ok(ablocks)
++    }
++}
++
++fn build_bitset_blocks(expected: &FixedBitSet) -> 
Result<Vec<ArrayBlock<u64>>> {
++    let engine = Arc::new(CoreIoEngine::new(64));
++    let mut t = BitsetBuilder::new(engine);
++    let blocks = t.build_bitset_blocks(expected)?;
++    t.read_bitset_blocks(&blocks)
++}
++
++fn test_bitset_conversion(expected: &FixedBitSet) -> Result<()> {
++    let blocks = build_bitset_blocks(expected)?;
++
++    let collector = BitsetCollector::new(expected.len());
++    for (i, b) in blocks.into_iter().enumerate() {
++        collector.visit(i as u64, b)?;
++    }
++    let actual = collector.get_bitset();
++    assert_eq!(expected.as_slice(), actual.as_slice()); // compare slices to 
facilitate debugging
++
++    Ok(())
++}
++
++#[test]
++fn convert_to_single_entry() {
++    let usize_bits = usize::BITS as usize;
++    let bitset_len = usize_bits;
++    let mut expected = FixedBitSet::with_capacity(bitset_len);
++    expected.insert_range(0..2);
++    expected.insert_range(bitset_len - 2..bitset_len);
++    assert!(test_bitset_conversion(&expected).is_ok());
++}
++
++#[test]
++fn convert_to_multiple_entries() {
++    let usize_bits = usize::BITS as usize;
++    let bitset_len = usize_bits * 2;
++    let mut expected = FixedBitSet::with_capacity(bitset_len);
++    expected.insert_range(0..2);
++    expected.insert_range(usize_bits - 1..usize_bits + 1);
++    assert!(test_bitset_conversion(&expected).is_ok());
++}
++
++#[test]
++fn convert_from_multiple_blocks() {
++    let bits_per_block = calc_max_entries::<u64>() * 64;
++    let bitset_len = bits_per_block * 2 + 1;
++    let mut expected = FixedBitSet::with_capacity(bitset_len);
++    expected.insert_range(0..2);
++    expected.insert_range(bits_per_block - 2..bits_per_block + 1);
++    assert!(test_bitset_conversion(&expected).is_ok());
++}
++
++#[test]
++fn insufficient_collector_size_should_fail() {
++    let expected = FixedBitSet::with_capacity(128);
++    let mut blocks = build_bitset_blocks(&expected).unwrap();
++
++    let collector = BitsetCollector::new(64);
++    let ret = collector.visit(0, blocks.remove(0));
++    assert!(ret.is_err());
++}
+Index: thin-provisioning-tools-1.1.0/Cargo.toml
+===================================================================
+--- thin-provisioning-tools-1.1.0.orig/Cargo.toml
++++ thin-provisioning-tools-1.1.0/Cargo.toml
+@@ -21,7 +21,7 @@ crc32c = "0.6"
+ data-encoding = "2.5"
+ devicemapper = "0.34"
+ exitcode = "1.1.2"
+-fixedbitset = "0.4"
++fixedbitset = ">= 0.4"
+ flate2 = "1.0"
+ iovec = "0.1"
+ indicatif = "0.17"
diff -Nru thin-provisioning-tools-1.1.0/debian/patches/series 
thin-provisioning-tools-1.1.0/debian/patches/series
--- thin-provisioning-tools-1.1.0/debian/patches/series 2025-10-19 
12:15:27.000000000 +0000
+++ thin-provisioning-tools-1.1.0/debian/patches/series 2025-12-17 
00:59:31.000000000 +0000
@@ -1 +1,2 @@
 debian-changes
+fixedbitset-0.5

Reply via email to