@@ -90,17 +90,6 @@ const (
9090
9191 tocArtifact = "toc"
9292 fsVerityDigestsArtifact = "fs-verity-digests"
93-
94- // idLength represents the number of random characters
95- // which can be used to create the unique link identifier
96- // for every layer. If this value is too long then the
97- // page size limit for the mount command may be exceeded.
98- // The idLength should be selected such that following equation
99- // is true (512 is a buffer for label metadata, 128 is the
100- // number of lowers we want to be able to use without having
101- // to use bind mounts to get all the way to the kernel limit).
102- // ((idLength + len(linkDir) + 1) * 128) <= (pageSize - 512)
103- idLength = 26
10493)
10594
10695type overlayOptions struct {
@@ -327,16 +316,10 @@ func Init(home string, options graphdriver.Options) (graphdriver.Driver, error)
327316 runhome := filepath .Join (options .RunRoot , filepath .Base (home ))
328317
329318 // Create the driver home dir
330- if err := os .MkdirAll (path . Join ( home , linkDir ) , 0o755 ); err != nil {
319+ if err := os .MkdirAll (home , 0o755 ); err != nil {
331320 return nil , err
332321 }
333322
334- if options .ImageStore != "" {
335- if err := idtools .MkdirAllAs (path .Join (options .ImageStore , linkDir ), 0o755 , 0 , 0 ); err != nil {
336- return nil , err
337- }
338- }
339-
340323 if err := os .MkdirAll (runhome , 0o700 ); err != nil {
341324 return nil , err
342325 }
@@ -1038,7 +1021,7 @@ func (d *Driver) getLayerPermissions(parent string, uidMaps, gidMaps []idtools.I
10381021}
10391022
10401023func (d * Driver ) create (id , parent string , opts * graphdriver.CreateOpts , readOnly bool ) (retErr error ) {
1041- dir , homedir , _ := d .dir2 (id , readOnly )
1024+ dir , _ , _ := d .dir2 (id , readOnly )
10421025
10431026 disableQuota := readOnly
10441027
@@ -1050,11 +1033,6 @@ func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts, readOnl
10501033 gidMaps = opts .IDMappings .GIDs ()
10511034 }
10521035
1053- // Make the link directory if it does not exist
1054- if err := idtools .MkdirAllAs (path .Join (homedir , linkDir ), 0o755 , 0 , 0 ); err != nil {
1055- return err
1056- }
1057-
10581036 idPair , forcedSt , st , err := d .getLayerPermissions (parent , uidMaps , gidMaps )
10591037 if err != nil {
10601038 return err
@@ -1066,8 +1044,7 @@ func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts, readOnl
10661044
10671045 if err := fileutils .Lexists (dir ); err == nil {
10681046 logrus .Warnf ("Trying to create a layer %#v while directory %q already exists; removing it first" , id , dir )
1069- // Don’t just os.RemoveAll(dir) here; d.Remove also removes the link in linkDir,
1070- // so that we can’t end up with two symlinks in linkDir pointing to the same layer.
1047+ // Don't just os.RemoveAll(dir) here; d.Remove also handles proper cleanup.
10711048 if err := d .Remove (id ); err != nil {
10721049 return fmt .Errorf ("removing a pre-existing layer directory %q: %w" , dir , err )
10731050 }
@@ -1119,18 +1096,6 @@ func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts, readOnl
11191096 }
11201097 }
11211098
1122- lid := generateID (idLength )
1123-
1124- linkBase := path .Join (".." , id , "diff" )
1125- if err := os .Symlink (linkBase , path .Join (homedir , linkDir , lid )); err != nil {
1126- return err
1127- }
1128-
1129- // Write link id to link file
1130- if err := os .WriteFile (path .Join (dir , "link" ), []byte (lid ), 0o644 ); err != nil {
1131- return err
1132- }
1133-
11341099 if err := idtools .MkdirAs (path .Join (dir , "work" ), 0o700 , forcedSt .IDs .UID , forcedSt .IDs .GID ); err != nil {
11351100 return err
11361101 }
@@ -1190,22 +1155,7 @@ func (d *Driver) getLower(parent string) (string, error) {
11901155 return "" , err
11911156 }
11921157
1193- // Read Parent link fileA
1194- parentLink , err := os .ReadFile (path .Join (parentDir , "link" ))
1195- if err != nil {
1196- if ! os .IsNotExist (err ) {
1197- return "" , err
1198- }
1199- logrus .Warnf ("Can't read parent link %q because it does not exist. Going through storage to recreate the missing links." , path .Join (parentDir , "link" ))
1200- if err := d .recreateSymlinks (); err != nil {
1201- return "" , fmt .Errorf ("recreating the links: %w" , err )
1202- }
1203- parentLink , err = os .ReadFile (path .Join (parentDir , "link" ))
1204- if err != nil {
1205- return "" , err
1206- }
1207- }
1208- lowers := []string {path .Join (linkDir , string (parentLink ))}
1158+ lowers := []string {path .Join (parent , "diff" )}
12091159
12101160 parentLower , err := os .ReadFile (path .Join (parentDir , lowerFile ))
12111161 if err == nil {
@@ -1266,24 +1216,15 @@ func (d *Driver) getLowerDirs(id string) ([]string, error) {
12661216 for s := range strings .SplitSeq (string (lowers ), ":" ) {
12671217 lower := d .dir (s )
12681218 lp , err := os .Readlink (lower )
1269- // if the link does not exist, we lost the symlinks during a sudden reboot.
1270- // Let's go ahead and recreate those symlinks.
12711219 if err != nil {
1272- if os .IsNotExist (err ) {
1273- logrus .Warnf ("Can't read link %q because it does not exist. A storage corruption might have occurred, attempting to recreate the missing symlinks. It might be best wipe the storage to avoid further errors due to storage corruption." , lower )
1274- if err := d .recreateSymlinks (); err != nil {
1275- return nil , fmt .Errorf ("recreating the missing symlinks: %w" , err )
1276- }
1277- // let's call Readlink on lower again now that we have recreated the missing symlinks
1278- lp , err = os .Readlink (lower )
1279- if err != nil {
1280- return nil , err
1281- }
1282- } else {
1283- return nil , err
1220+ if errors .Is (err , syscall .EINVAL ) {
1221+ // Not a symlink: new format, lower is already the diff path.
1222+ lowersArray = append (lowersArray , lower )
1223+ continue
12841224 }
1225+ return nil , err
12851226 }
1286- lowersArray = append (lowersArray , path . Clean ( d .dir (path .Join ("link" , lp ) )))
1227+ lowersArray = append (lowersArray , d .dir (path .Join ("link" , lp )))
12871228 }
12881229 } else if ! os .IsNotExist (err ) {
12891230 return nil , err
@@ -1393,112 +1334,6 @@ func (d *Driver) DeferredRemove(id string) (tempdir.CleanupTempDirFunc, error) {
13931334 return t .Cleanup , nil
13941335}
13951336
1396- // recreateSymlinks goes through the driver's home directory and checks if the diff directory
1397- // under each layer has a symlink created for it under the linkDir. If the symlink does not
1398- // exist, it creates them
1399- func (d * Driver ) recreateSymlinks () error {
1400- // We have at most 3 corrective actions per layer, so 10 iterations is plenty.
1401- const maxIterations = 10
1402-
1403- // List all the directories under the home directory
1404- dirs , err := os .ReadDir (d .home )
1405- if err != nil {
1406- return fmt .Errorf ("reading driver home directory %q: %w" , d .home , err )
1407- }
1408- // This makes the link directory if it doesn't exist
1409- if err := idtools .MkdirAllAs (path .Join (d .home , linkDir ), 0o755 , 0 , 0 ); err != nil {
1410- return err
1411- }
1412- // Keep looping as long as we take some corrective action in each iteration
1413- var errs error
1414- madeProgress := true
1415- iterations := 0
1416- for madeProgress {
1417- errs = nil
1418- madeProgress = false
1419- // Check that for each layer, there's a link in "l" with the name in
1420- // the layer's "link" file that points to the layer's "diff" directory.
1421- for _ , dir := range dirs {
1422- // Skip over the linkDir, stagingDir, tempDirName and anything that is not a directory
1423- if dir .Name () == linkDir || dir .Name () == stagingDir || dir .Name () == tempDirName || ! dir .IsDir () {
1424- continue
1425- }
1426- // Read the "link" file under each layer to get the name of the symlink
1427- data , err := os .ReadFile (path .Join (d .dir (dir .Name ()), "link" ))
1428- if err != nil {
1429- errs = errors .Join (errs , fmt .Errorf ("reading name of symlink for %q: %w" , dir .Name (), err ))
1430- continue
1431- }
1432- linkPath := path .Join (d .home , linkDir , strings .Trim (string (data ), "\n " ))
1433- // Check if the symlink exists, and if it doesn't, create it again with the
1434- // name we got from the "link" file
1435- err = fileutils .Lexists (linkPath )
1436- if err != nil && os .IsNotExist (err ) {
1437- if err := os .Symlink (path .Join (".." , dir .Name (), "diff" ), linkPath ); err != nil {
1438- errs = errors .Join (errs , err )
1439- continue
1440- }
1441- madeProgress = true
1442- } else if err != nil {
1443- errs = errors .Join (errs , err )
1444- continue
1445- }
1446- }
1447-
1448- // linkDirFullPath is the full path to the linkDir
1449- linkDirFullPath := filepath .Join (d .home , "l" )
1450- // Now check if we somehow lost a "link" file, by making sure
1451- // that each symlink we have corresponds to one.
1452- links , err := os .ReadDir (linkDirFullPath )
1453- if err != nil {
1454- errs = errors .Join (errs , err )
1455- continue
1456- }
1457- // Go through all of the symlinks in the "l" directory
1458- for _ , link := range links {
1459- // Read the symlink's target, which should be "../$layer/diff"
1460- target , err := os .Readlink (filepath .Join (linkDirFullPath , link .Name ()))
1461- if err != nil {
1462- errs = errors .Join (errs , err )
1463- continue
1464- }
1465- targetComponents := strings .Split (target , string (os .PathSeparator ))
1466- if len (targetComponents ) != 3 || targetComponents [0 ] != ".." || targetComponents [2 ] != "diff" {
1467- errs = errors .Join (errs , fmt .Errorf ("link target of %q looks weird: %q" , link , target ))
1468- // force the link to be recreated on the next pass
1469- if err := os .Remove (filepath .Join (linkDirFullPath , link .Name ())); err != nil {
1470- if ! os .IsNotExist (err ) {
1471- errs = errors .Join (errs , fmt .Errorf ("removing link %q: %w" , link , err ))
1472- } // else don’t report any error, but also don’t set madeProgress.
1473- continue
1474- }
1475- madeProgress = true
1476- continue
1477- }
1478- // Reconstruct the name of the target's link file and check that
1479- // it has the basename of our symlink in it.
1480- targetID := targetComponents [1 ]
1481- linkFile := filepath .Join (d .dir (targetID ), "link" )
1482- data , err := os .ReadFile (linkFile )
1483- if err != nil || string (data ) != link .Name () {
1484- // NOTE: If two or more links point to the same target, we will update linkFile
1485- // with every value of link.Name(), and set madeProgress = true every time.
1486- if err := os .WriteFile (linkFile , []byte (link .Name ()), 0o644 ); err != nil {
1487- errs = errors .Join (errs , fmt .Errorf ("correcting link for layer %s: %w" , targetID , err ))
1488- continue
1489- }
1490- madeProgress = true
1491- }
1492- }
1493- iterations ++
1494- if iterations >= maxIterations {
1495- errs = errors .Join (errs , fmt .Errorf ("reached %d iterations in overlay graph driver’s recreateSymlink, giving up" , iterations ))
1496- break
1497- }
1498- }
1499- return errs
1500- }
1501-
15021337// Get creates and mounts the required file system for the given id and returns the mount path.
15031338func (d * Driver ) Get (id string , options graphdriver.MountOpts ) (string , error ) {
15041339 return d .get (id , false , options )
@@ -1692,45 +1527,25 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO
16921527 continue
16931528 }
16941529
1695- lower := ""
1696- newpath := path .Join (d .home , l )
1697- if st , err := os .Stat (newpath ); err != nil {
1698- for _ , p := range d .getAllImageStores () {
1699- lower = path .Join (p , d .name , l )
1700- if st2 , err2 := os .Stat (lower ); err2 == nil {
1701- if ! permsKnown {
1702- perms = st2 .Mode ()
1703- permsKnown = true
1704- }
1705- break
1706- }
1707- lower = ""
1708- }
1709- // if it is a "not found" error, that means the symlinks were lost in a sudden reboot
1710- // so call the recreateSymlinks function to go through all the layer dirs and recreate
1711- // the symlinks with the name from their respective "link" files
1712- if lower == "" && os .IsNotExist (err ) {
1713- logrus .Warnf ("Can't stat lower layer %q because it does not exist. Going through storage to recreate the missing symlinks." , newpath )
1714- if err := d .recreateSymlinks (); err != nil {
1715- return "" , fmt .Errorf ("recreating the missing symlinks: %w" , err )
1716- }
1717- lower = newpath
1718- } else if lower == "" {
1719- return "" , fmt .Errorf ("can't stat lower layer %q: %w" , newpath , err )
1530+ lower := d .dir (l )
1531+ lp , err := os .Readlink (lower )
1532+ if err != nil {
1533+ if ! errors .Is (err , syscall .EINVAL ) {
1534+ return "" , fmt .Errorf ("can't resolve lower layer %q: %w" , lower , err )
17201535 }
1536+ // Not a symlink: lower is already the diff path.
17211537 } else {
1722- if ! permsKnown {
1723- perms = st .Mode ()
1724- permsKnown = true
1725- }
1726- lower = newpath
1538+ lower = d .dir (path .Join ("link" , lp ))
17271539 }
1728-
1729- linkContent , err := os .Readlink (lower )
1730- if err != nil {
1731- return "" , err
1540+ if st , err := os .Stat (lower ); err != nil {
1541+ return "" , fmt .Errorf ("can't stat lower layer %q: %w" , lower , err )
1542+ } else if ! permsKnown {
1543+ perms = st .Mode ()
1544+ permsKnown = true
17321545 }
1733- lowerID := filepath .Base (filepath .Dir (linkContent ))
1546+
1547+ // lowerID is the layer directory name, used for composefs blob lookup.
1548+ lowerID := filepath .Base (filepath .Dir (lower ))
17341549 composefsMount , err := maybeAddComposefsMount (lowerID , i + 1 , readWrite )
17351550 if err != nil {
17361551 return "" , err
0 commit comments