@@ -57,6 +57,7 @@ const (
5757)
5858
5959type Manager struct {
60+ RemountMap map [string ]* rafs.Rafs // Scratch space to store rafs instances needing remount on startup
6061 snapshotMap map [string ]* snapshotStatus // tarfs snapshots status, indexed by snapshot ID
6162 mutex sync.Mutex
6263 mutexLoopDev sync.Mutex
@@ -87,6 +88,7 @@ type snapshotStatus struct {
8788func NewManager (insecure , checkTarfsHint bool , cacheDirPath , nydusImagePath string , maxConcurrentProcess int64 ) * Manager {
8889 return & Manager {
8990 snapshotMap : map [string ]* snapshotStatus {},
91+ RemountMap : map [string ]* rafs.Rafs {},
9092 cacheDirPath : cacheDirPath ,
9193 nydusImagePath : nydusImagePath ,
9294 insecure : insecure ,
@@ -623,7 +625,7 @@ func (t *Manager) ExportBlockData(s storage.Snapshot, perLayer bool, labels map[
623625 return updateFields , nil
624626}
625627
626- func (t * Manager ) MountTarErofs (snapshotID string , s * storage.Snapshot , labels map [string ]string , rafs * rafs.Rafs ) error {
628+ func (t * Manager ) MountErofs (snapshotID string , s * storage.Snapshot , labels map [string ]string , rafs * rafs.Rafs ) error {
627629 if s == nil {
628630 return errors .New ("snapshot object for MountTarErofs() is nil" )
629631 }
@@ -644,6 +646,7 @@ func (t *Manager) MountTarErofs(snapshotID string, s *storage.Snapshot, labels m
644646 }
645647
646648 var devices []string
649+ var parents []string
647650 // When merging bootstrap, we need to arrange layer bootstrap in order from low to high
648651 for idx := len (s .ParentIDs ) - 1 ; idx >= 0 ; idx -- {
649652 snapshotID := s .ParentIDs [idx ]
@@ -664,10 +667,13 @@ func (t *Manager) MountTarErofs(snapshotID string, s *storage.Snapshot, labels m
664667 st .dataLoopdev = loopdev
665668 }
666669 devices = append (devices , "device=" + st .dataLoopdev .Name ())
670+ parents = append (parents , snapshotID )
667671 }
668672
669673 st .mutex .Unlock ()
670674 }
675+ parentList := strings .Join (parents , "," )
676+ devices = append (devices , "ro" )
671677 mountOpts := strings .Join (devices , "," )
672678
673679 st , err := t .getSnapshotStatus (snapshotID )
@@ -698,6 +704,83 @@ func (t *Manager) MountTarErofs(snapshotID string, s *storage.Snapshot, labels m
698704 return errors .Wrapf (err , "create tarfs mount dir %s" , mountPoint )
699705 }
700706
707+ err = unix .Mount (devName , mountPoint , "erofs" , 0 , mountOpts )
708+ if err != nil {
709+ return errors .Wrapf (err , "mount erofs at %s with opts %s" , mountPoint , mountOpts )
710+ }
711+ st .erofsMountPoint = mountPoint
712+ rafs .SetMountpoint (mountPoint )
713+ rafs .AddAnnotation (label .NydusTarfsParents , parentList )
714+ return nil
715+ }
716+
717+ func (t * Manager ) RemountErofs (snapshotID string , rafs * rafs.Rafs ) error {
718+ upperDirPath := path .Join (rafs .GetSnapshotDir (), "fs" )
719+
720+ log .L .Infof ("remount EROFS for tarfs snapshot %s at %s" , snapshotID , upperDirPath )
721+ var parents []string
722+ if parentList , ok := rafs .Annotations [label .NydusTarfsParents ]; ok {
723+ parents = strings .Split (parentList , "," )
724+ } else {
725+ if ! config .GetTarfsMountOnHost () {
726+ rafs .SetMountpoint (upperDirPath )
727+ }
728+ return nil
729+ }
730+
731+ var devices []string
732+ for idx := 0 ; idx < len (parents ); idx ++ {
733+ snapshotID := parents [idx ]
734+ st , err := t .waitLayerReady (snapshotID , true )
735+ if err != nil {
736+ return errors .Wrapf (err , "wait for tarfs conversion task" )
737+ }
738+
739+ if st .dataLoopdev == nil {
740+ blobTarFilePath := t .layerTarFilePath (st .blobID )
741+ loopdev , err := t .attachLoopdev (blobTarFilePath )
742+ if err != nil {
743+ st .mutex .Unlock ()
744+ return errors .Wrapf (err , "attach layer tar file %s to loopdev" , blobTarFilePath )
745+ }
746+ st .dataLoopdev = loopdev
747+ }
748+ devices = append (devices , "device=" + st .dataLoopdev .Name ())
749+
750+ st .mutex .Unlock ()
751+ }
752+ devices = append (devices , "ro" )
753+ mountOpts := strings .Join (devices , "," )
754+
755+ st , err := t .getSnapshotStatus (snapshotID )
756+ if err != nil {
757+ return err
758+ }
759+ defer st .mutex .Unlock ()
760+
761+ mountPoint := path .Join (rafs .GetSnapshotDir (), "mnt" )
762+ if len (st .erofsMountPoint ) > 0 {
763+ if st .erofsMountPoint == mountPoint {
764+ log .L .Debugf ("tarfs for snapshot %s has already been mounted at %s" , snapshotID , mountPoint )
765+ return nil
766+ }
767+ return errors .Errorf ("tarfs for snapshot %s has already been mounted at %s" , snapshotID , st .erofsMountPoint )
768+ }
769+
770+ if st .metaLoopdev == nil {
771+ mergedBootstrap := t .imageMetaFilePath (upperDirPath )
772+ loopdev , err := t .attachLoopdev (mergedBootstrap )
773+ if err != nil {
774+ return errors .Wrapf (err , "attach merged bootstrap %s to loopdev" , mergedBootstrap )
775+ }
776+ st .metaLoopdev = loopdev
777+ }
778+ devName := st .metaLoopdev .Name ()
779+
780+ if err = os .MkdirAll (mountPoint , 0750 ); err != nil {
781+ return errors .Wrapf (err , "create tarfs mount dir %s" , mountPoint )
782+ }
783+
701784 err = unix .Mount (devName , mountPoint , "erofs" , 0 , mountOpts )
702785 if err != nil {
703786 return errors .Wrapf (err , "mount erofs at %s with opts %s" , mountPoint , mountOpts )
@@ -768,6 +851,43 @@ func (t *Manager) DetachLayer(snapshotID string) error {
768851 return nil
769852}
770853
854+ func (t * Manager ) RecoverSnapshoInfo (ctx context.Context , id string , info snapshots.Info , upperPath string ) error {
855+ t .mutex .Lock ()
856+ defer t .mutex .Unlock ()
857+ log .L .Infof ("recover tarfs snapshot %s with path %s" , id , upperPath )
858+
859+ if _ , ok := t .snapshotMap [id ]; ok {
860+ // RecoverSnapshotInfo() is called after RecoverRafsInstance(), so there may be some snapshots already exist.
861+ return nil
862+ }
863+
864+ layerMetaFilePath := t .layerMetaFilePath (upperPath )
865+ if _ , err := os .Stat (layerMetaFilePath ); err == nil {
866+ layerDigest := digest .Digest (info .Labels [label .CRILayerDigest ])
867+ if layerDigest .Validate () != nil {
868+ return errors .Errorf ("not found layer digest label" )
869+ }
870+ ctx , cancel := context .WithCancel (context .Background ())
871+ t .snapshotMap [id ] = & snapshotStatus {
872+ status : TarfsStatusReady ,
873+ blobID : layerDigest .Hex (),
874+ cancel : cancel ,
875+ ctx : ctx ,
876+ }
877+ } else {
878+ ctx , cancel := context .WithCancel (context .Background ())
879+ wg := & sync.WaitGroup {}
880+ wg .Add (1 )
881+ t .snapshotMap [id ] = & snapshotStatus {
882+ status : TarfsStatusFailed ,
883+ wg : wg ,
884+ cancel : cancel ,
885+ ctx : ctx ,
886+ }
887+ }
888+ return nil
889+ }
890+
771891// This method is called in single threaded mode during startup, so we do not lock `snapshotStatus` objects.
772892func (t * Manager ) RecoverRafsInstance (r * rafs.Rafs ) error {
773893 t .mutex .Lock ()
@@ -793,6 +913,11 @@ func (t *Manager) RecoverRafsInstance(r *rafs.Rafs) error {
793913 if ! mounted || err != nil {
794914 mountPoint = ""
795915 }
916+ if ! mounted && err == nil {
917+ if _ , ok := r .Annotations [label .NydusTarfsParents ]; ok {
918+ t .RemountMap [r .SnapshotID ] = r
919+ }
920+ }
796921 t .snapshotMap [r .SnapshotID ] = & snapshotStatus {
797922 status : TarfsStatusReady ,
798923 blobID : layerDigest .Hex (),
0 commit comments