Skip to content

Commit 628a4d8

Browse files
committed
composefs: new method ensure_object_from_fd
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
1 parent f4e64b3 commit 628a4d8

1 file changed

Lines changed: 32 additions & 0 deletions

File tree

crates/composefs/src/repository.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1341,6 +1341,38 @@ impl<ObjectID: FsVerityHashValue> Repository<ObjectID> {
13411341
Ok(id)
13421342
}
13431343

1344+
/// Store an object from a file descriptor, using reflink (FICLONE) when possible.
1345+
///
1346+
/// Tries FICLONE first for an instant copy-on-write clone (works when the
1347+
/// source fd and the repository are on the same filesystem). Falls back to
1348+
/// a buffered data copy using the caller-provided `buf`. Passing a large
1349+
/// buffer avoids the small default used by `std::io::copy`.
1350+
#[context("Ensuring object from fd exists in repository")]
1351+
pub fn ensure_object_from_fd(
1352+
&self,
1353+
fd: OwnedFd,
1354+
size: u64,
1355+
buf: &mut [u8],
1356+
) -> Result<(ObjectID, ObjectStoreMethod)> {
1357+
let tmpfile = self.create_object_tmpfile()?;
1358+
let src = File::from(fd);
1359+
let mut dst = File::from(tmpfile);
1360+
1361+
if rustix::fs::ioctl_ficlone(&dst, &src).is_err() {
1362+
let mut src = src;
1363+
loop {
1364+
let n = src.read(buf).context("reading from source fd")?;
1365+
if n == 0 {
1366+
break;
1367+
}
1368+
dst.write_all(&buf[..n])
1369+
.context("writing to repository tmpfile")?;
1370+
}
1371+
}
1372+
1373+
self.finalize_object_tmpfile(dst, size)
1374+
}
1375+
13441376
#[context("Opening file '{filename}' with verity verification")]
13451377
fn open_with_verity(&self, filename: &str, expected_verity: &ObjectID) -> Result<OwnedFd> {
13461378
let fd = self

0 commit comments

Comments
 (0)