@@ -803,28 +803,58 @@ fn have_required_join_capabilities() -> Result<bool> {
803803 && effective. contains ( & caps:: Capability :: CAP_SYS_CHROOT ) )
804804}
805805
806+ const OVERLAY_ARGS_RO_PREFIX : & str = "ro" ;
807+ const OVERLAY_ARGS_INDEX : & str = "index" ;
808+ const OVERLAY_ARGS_INDEX_ON : & str = "index=on" ;
809+ const OVERLAY_ARGS_METACOPY : & str = "metacopy" ;
810+ const OVERLAY_ARGS_METACOPY_ON : & str = "metacopy=on" ;
811+
806812/// A struct for holding the options that will be included
807813/// in the overlayfs mount command when mounting an environment.
808814#[ derive( Default ) ]
809815pub ( crate ) struct OverlayMountOptions {
810- pub ( crate ) read_only : bool ,
816+ /// Specifies that the overlay file system is mounted as read-only
817+ pub read_only : bool ,
818+ /// When true, inodes are indexed in the mount so that
819+ /// files which share the same inode (hardlinks) are broken
820+ /// in the final mount and changes to one file don't affect
821+ /// the other.
822+ ///
823+ /// This is the desired default behavior for
824+ /// spfs, since we rely on hardlinks for deduplication but
825+ /// expect that file to be able to appear in mutliple places
826+ /// as separate files that just so happen to share the same content.
827+ break_hardlinks : bool ,
828+ /// When true, overlayfs will use extended file attributes to avoid
829+ /// copying file data when only the metadata of a file has changed.
830+ /// https://www.kernel.org/doc/html/latest/filesystems/overlayfs.html#metadata-only-copy-up
831+ metadata_copy_up : bool ,
811832}
812833
813834impl OverlayMountOptions {
814835 /// Create the mount options for a runtime state
815836 fn new ( rt : & runtime:: Runtime ) -> Self {
816837 Self {
817838 read_only : !rt. status . editable ,
839+ break_hardlinks : true ,
840+ metadata_copy_up : true ,
818841 }
819842 }
820843
821844 /// Return the options that should be included in the mount request.
822- pub ( crate ) fn options ( & self ) -> Vec < & str > {
845+ pub fn to_options ( & self ) -> Vec < & ' static str > {
846+ let params = runtime:: overlayfs:: overlayfs_available_options ( ) ;
847+ let mut opts = Vec :: new ( ) ;
823848 if self . read_only {
824- vec ! [ OVERLAY_ARGS_RO_PREFIX ]
825- } else {
826- Vec :: default ( )
849+ opts. push ( OVERLAY_ARGS_RO_PREFIX ) ;
827850 }
851+ if self . break_hardlinks && params. contains ( OVERLAY_ARGS_INDEX ) {
852+ opts. push ( OVERLAY_ARGS_INDEX_ON ) ;
853+ }
854+ if self . metadata_copy_up && params. contains ( OVERLAY_ARGS_METACOPY ) {
855+ opts. push ( OVERLAY_ARGS_METACOPY_ON ) ;
856+ }
857+ opts
828858 }
829859}
830860
@@ -842,7 +872,7 @@ pub(crate) fn get_overlay_args<P: AsRef<Path>>(
842872 let mut args = String :: with_capacity ( 4096 ) ;
843873
844874 let mount_options = OverlayMountOptions :: new ( rt) ;
845- for option in mount_options. options ( ) {
875+ for option in mount_options. to_options ( ) {
846876 args. push_str ( option) ;
847877 args. push ( ',' ) ;
848878 }
@@ -875,8 +905,6 @@ pub(crate) fn get_overlay_args<P: AsRef<Path>>(
875905 Ok ( args)
876906}
877907
878- pub ( crate ) const OVERLAY_ARGS_RO_PREFIX : & str = "ro" ;
879-
880908#[ cfg( feature = "fuse-backend" ) ]
881909fn get_fuse_args ( config : & runtime:: Config , owner : & IsRootUser , read_only : bool ) -> String {
882910 use fuser:: MountOption :: * ;
0 commit comments