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