File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff 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
You can’t perform that action at this time.
0 commit comments