@@ -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 ,
@@ -363,10 +365,9 @@ func (t *Manager) blobProcess(ctx context.Context, snapshotID, ref string,
363365 err = t .generateBootstrap (ds , snapshotID , layerBlobID , upperDirPath )
364366 if err != nil && ! errdefs .IsAlreadyExists (err ) {
365367 return epilog (err , "generate tarfs data from image layer blob" )
366- } else {
367- msg := fmt .Sprintf ("Nydus tarfs for snapshot %s is ready" , snapshotID )
368- return epilog (nil , msg )
369368 }
369+ msg := fmt .Sprintf ("Nydus tarfs for snapshot %s is ready" , snapshotID )
370+ return epilog (nil , msg )
370371 }
371372 }
372373
@@ -389,7 +390,9 @@ func (t *Manager) blobProcess(ctx context.Context, snapshotID, ref string,
389390 } else {
390391 // Download and convert layer content in background.
391392 // Will retry when the content is actually needed if the background process failed.
392- go process (rc , remote )
393+ go func () {
394+ _ = process (rc , remote )
395+ }()
393396 }
394397
395398 return err
@@ -418,7 +421,7 @@ func (t *Manager) retryPrepareLayer(snapshotID, upperDirPath string, labels map[
418421 case TarfsStatusPrepare :
419422 log .L .Infof ("Another thread is retrying snapshot %s, wait for the result" , snapshotID )
420423 st .mutex .Unlock ()
421- st , err = t .waitLayerReady (snapshotID , false )
424+ _ , err = t .waitLayerReady (snapshotID , false )
422425 return err
423426 case TarfsStatusReady :
424427 log .L .Infof ("Another thread has retried snapshot %s and succeed" , snapshotID )
@@ -622,7 +625,7 @@ func (t *Manager) ExportBlockData(s storage.Snapshot, perLayer bool, labels map[
622625 return updateFields , nil
623626}
624627
625- 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 {
626629 if s == nil {
627630 return errors .New ("snapshot object for MountTarErofs() is nil" )
628631 }
@@ -643,6 +646,7 @@ func (t *Manager) MountTarErofs(snapshotID string, s *storage.Snapshot, labels m
643646 }
644647
645648 var devices []string
649+ var parents []string
646650 // When merging bootstrap, we need to arrange layer bootstrap in order from low to high
647651 for idx := len (s .ParentIDs ) - 1 ; idx >= 0 ; idx -- {
648652 snapshotID := s .ParentIDs [idx ]
@@ -663,10 +667,89 @@ func (t *Manager) MountTarErofs(snapshotID string, s *storage.Snapshot, labels m
663667 st .dataLoopdev = loopdev
664668 }
665669 devices = append (devices , "device=" + st .dataLoopdev .Name ())
670+ parents = append (parents , snapshotID )
671+ }
672+
673+ st .mutex .Unlock ()
674+ }
675+ parentList := strings .Join (parents , "," )
676+ devices = append (devices , "ro" )
677+ mountOpts := strings .Join (devices , "," )
678+
679+ st , err := t .getSnapshotStatus (snapshotID , true )
680+ if err != nil {
681+ return err
682+ }
683+ defer st .mutex .Unlock ()
684+
685+ mountPoint := path .Join (rafs .GetSnapshotDir (), "mnt" )
686+ if len (st .erofsMountPoint ) > 0 {
687+ if st .erofsMountPoint == mountPoint {
688+ log .L .Debugf ("tarfs for snapshot %s has already been mounted at %s" , snapshotID , mountPoint )
689+ return nil
690+ }
691+ return errors .Errorf ("tarfs for snapshot %s has already been mounted at %s" , snapshotID , st .erofsMountPoint )
692+ }
693+
694+ if st .metaLoopdev == nil {
695+ loopdev , err := t .attachLoopdev (mergedBootstrap )
696+ if err != nil {
697+ return errors .Wrapf (err , "attach merged bootstrap %s to loopdev" , mergedBootstrap )
698+ }
699+ st .metaLoopdev = loopdev
700+ }
701+ devName := st .metaLoopdev .Name ()
702+
703+ if err = os .MkdirAll (mountPoint , 0750 ); err != nil {
704+ return errors .Wrapf (err , "create tarfs mount dir %s" , mountPoint )
705+ }
706+
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 )
666727 }
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 ())
667749
668750 st .mutex .Unlock ()
669751 }
752+ devices = append (devices , "ro" )
670753 mountOpts := strings .Join (devices , "," )
671754
672755 st , err := t .getSnapshotStatus (snapshotID , true )
@@ -685,6 +768,7 @@ func (t *Manager) MountTarErofs(snapshotID string, s *storage.Snapshot, labels m
685768 }
686769
687770 if st .metaLoopdev == nil {
771+ mergedBootstrap := t .imageMetaFilePath (upperDirPath )
688772 loopdev , err := t .attachLoopdev (mergedBootstrap )
689773 if err != nil {
690774 return errors .Wrapf (err , "attach merged bootstrap %s to loopdev" , mergedBootstrap )
@@ -767,6 +851,43 @@ func (t *Manager) DetachLayer(snapshotID string) error {
767851 return nil
768852}
769853
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+
770891// This method is called in single threaded mode during startup, so we do not lock `snapshotStatus` objects.
771892func (t * Manager ) RecoverRafsInstance (r * rafs.Rafs ) error {
772893 t .mutex .Lock ()
0 commit comments