@@ -89,40 +89,6 @@ func NewImageStore(rootDir string, cacheDir string, dedupe, commit bool, log zlo
89
89
return imgStore
90
90
}
91
91
92
- // RLock read-lock.
93
- func (is * ImageStore ) RLock (lockStart * time.Time ) {
94
- * lockStart = time .Now ()
95
-
96
- is .lock .RLock ()
97
- }
98
-
99
- // RUnlock read-unlock.
100
- func (is * ImageStore ) RUnlock (lockStart * time.Time ) {
101
- is .lock .RUnlock ()
102
-
103
- lockEnd := time .Now ()
104
- // includes time spent in acquiring and holding a lock
105
- latency := lockEnd .Sub (* lockStart )
106
- monitoring .ObserveStorageLockLatency (is .metrics , latency , is .RootDir (), storageConstants .RLOCK ) // histogram
107
- }
108
-
109
- // Lock write-lock.
110
- func (is * ImageStore ) Lock (lockStart * time.Time ) {
111
- * lockStart = time .Now ()
112
-
113
- is .lock .Lock ()
114
- }
115
-
116
- // Unlock write-unlock.
117
- func (is * ImageStore ) Unlock (lockStart * time.Time ) {
118
- is .lock .Unlock ()
119
-
120
- lockEnd := time .Now ()
121
- // includes time spent in acquiring and holding a lock
122
- latency := lockEnd .Sub (* lockStart )
123
- monitoring .ObserveStorageLockLatency (is .metrics , latency , is .RootDir (), storageConstants .RWLOCK ) // histogram
124
- }
125
-
126
92
// RLock read-lock for specific repo.
127
93
func (is * ImageStore ) RLockRepo (repo string , lockStart * time.Time ) {
128
94
* lockStart = time .Now ()
@@ -296,13 +262,12 @@ func (is *ImageStore) ValidateRepo(name string) (bool, error) {
296
262
297
263
// GetRepositories returns a list of all the repositories under this store.
298
264
func (is * ImageStore ) GetRepositories () ([]string , error ) {
299
- var lockLatency time.Time
300
-
265
+ // Ideally this function would lock while walking in order to avoid concurrency issues
266
+ // but we can't lock everything as we don't have a valid list of all repositories
267
+ // let's assume the result of this function is a best effort and some repos may be
268
+ // added or removed by the time it returns
301
269
dir := is .rootDir
302
270
303
- is .RLock (& lockLatency )
304
- defer is .RUnlock (& lockLatency )
305
-
306
271
stores := make ([]string , 0 )
307
272
308
273
err := is .storeDriver .Walk (dir , func (fileInfo driver.FileInfo ) error {
@@ -342,13 +307,12 @@ func (is *ImageStore) GetRepositories() ([]string, error) {
342
307
343
308
// GetNextRepository returns next repository under this store.
344
309
func (is * ImageStore ) GetNextRepository (repo string ) (string , error ) {
345
- var lockLatency time.Time
346
-
310
+ // Ideally this function would lock while walking in order to avoid concurrency issues
311
+ // but we can't lock everything as we don't have a valid list of all repositories
312
+ // let's assume the result of this function is a best effort and some repos may be
313
+ // added or removed by the time it returns
347
314
dir := is .rootDir
348
315
349
- is .RLock (& lockLatency )
350
- defer is .RUnlock (& lockLatency )
351
-
352
316
_ , err := is .storeDriver .List (dir )
353
317
if err != nil {
354
318
if errors .As (err , & driver.PathNotFoundError {}) {
@@ -1190,8 +1154,6 @@ func (is *ImageStore) BlobPath(repo string, digest godigest.Digest) string {
1190
1154
}
1191
1155
1192
1156
func (is * ImageStore ) GetAllDedupeReposCandidates (digest godigest.Digest ) ([]string , error ) {
1193
- var lockLatency time.Time
1194
-
1195
1157
if err := digest .Validate (); err != nil {
1196
1158
return nil , err
1197
1159
}
@@ -1200,9 +1162,6 @@ func (is *ImageStore) GetAllDedupeReposCandidates(digest godigest.Digest) ([]str
1200
1162
return nil , nil //nolint:nilnil
1201
1163
}
1202
1164
1203
- is .RLock (& lockLatency )
1204
- defer is .RUnlock (& lockLatency )
1205
-
1206
1165
blobsPaths , err := is .cache .GetAllBlobs (digest )
1207
1166
if err != nil {
1208
1167
return nil , err
@@ -1799,41 +1758,62 @@ func (is *ImageStore) GetAllBlobs(repo string) ([]godigest.Digest, error) {
1799
1758
return ret , nil
1800
1759
}
1801
1760
1802
- func (is * ImageStore ) GetNextDigestWithBlobPaths (repos []string , lastDigests []godigest.Digest ,
1761
+ func (is * ImageStore ) GetNextDigestWithBlobPaths (allRepos []string , lastDigests []godigest.Digest ,
1803
1762
) (godigest.Digest , []string , []string , error ) {
1804
1763
var lockLatency time.Time
1805
1764
1806
1765
dir := is .rootDir
1807
1766
1808
- is .RLock (& lockLatency )
1809
- defer is .RUnlock (& lockLatency )
1767
+ for _ , repo := range allRepos {
1768
+ is .RLockRepo (repo , & lockLatency )
1769
+ defer is .RUnlockRepo (repo , & lockLatency )
1770
+ }
1810
1771
1811
1772
var duplicateBlobs , duplicateRepos []string
1812
1773
1813
1774
var digest godigest.Digest
1814
1775
1815
- var repo string
1816
-
1817
1776
err := is .storeDriver .Walk (dir , func (fileInfo driver.FileInfo ) error {
1818
1777
// skip blobs under .sync and .uploads
1819
1778
if strings .HasSuffix (fileInfo .Path (), syncConstants .SyncBlobUploadDir ) ||
1820
1779
strings .HasSuffix (fileInfo .Path (), storageConstants .BlobUploadDir ) {
1821
1780
return driver .ErrSkipDir
1822
1781
}
1823
1782
1783
+ if strings .HasSuffix (fileInfo .Path (), ispec .ImageLayoutFile ) ||
1784
+ strings .HasSuffix (fileInfo .Path (), ispec .ImageIndexFile ) ||
1785
+ strings .HasSuffix (fileInfo .Path (), ".db" ) {
1786
+ return nil
1787
+ }
1788
+
1789
+ // the path is always under root dir because the walk function walks the root dir
1790
+ rel , _ := filepath .Rel (is .rootDir , fileInfo .Path ())
1791
+
1824
1792
if fileInfo .IsDir () {
1825
- // skip repositories not found in repos
1826
- repo = path . Base ( fileInfo . Path ())
1827
- if ! zcommon . Contains ( repos , repo ) && repo != ispec . ImageBlobsDir {
1828
- candidateAlgorithm := godigest . Algorithm ( repo )
1793
+ if fileInfo . Path () == is . rootDir || zcommon . Contains ( allRepos , rel ) {
1794
+ // this is the root directory or a repo, go deeped into subfolders
1795
+ return nil
1796
+ }
1829
1797
1830
- if ! candidateAlgorithm .Available () {
1831
- return driver .ErrSkipDir
1832
- }
1798
+ // attempt to determine is the base folder
1799
+ lastFolderInPath := path .Base (rel )
1800
+ if lastFolderInPath == ispec .ImageBlobsDir {
1801
+ // this is the blobs dir, go deeper into subfolders
1802
+ return nil
1803
+ }
1804
+
1805
+ // this is not the root dir, a repo, or a blobs dir
1806
+ // it is also unclear if we are under a repo, as this could be .trivy
1807
+ // skip entire directory if the base name does not match a valid hash algorithm
1808
+ candidateAlgorithm := godigest .Algorithm (lastFolderInPath )
1809
+ if ! candidateAlgorithm .Available () {
1810
+ return driver .ErrSkipDir
1811
+ } else {
1812
+ // this is the folder sha256 or similar
1813
+ return nil
1833
1814
}
1834
1815
}
1835
1816
1836
- repo = path .Dir (path .Dir (fileInfo .Path ()))
1837
1817
digestHash := path .Base (fileInfo .Path ())
1838
1818
digestAlgorithm := godigest .Algorithm (path .Base (path .Dir (fileInfo .Path ())))
1839
1819
@@ -1853,6 +1833,7 @@ func (is *ImageStore) GetNextDigestWithBlobPaths(repos []string, lastDigests []g
1853
1833
if blobDigest == digest {
1854
1834
duplicateBlobs = append (duplicateBlobs , fileInfo .Path ())
1855
1835
1836
+ repo := path .Dir (path .Dir (path .Dir (rel )))
1856
1837
if ! zcommon .Contains (duplicateRepos , repo ) {
1857
1838
duplicateRepos = append (duplicateRepos , repo )
1858
1839
}
@@ -2047,8 +2028,10 @@ func (is *ImageStore) RunDedupeForDigest(ctx context.Context, digest godigest.Di
2047
2028
) error {
2048
2029
var lockLatency time.Time
2049
2030
2050
- is .Lock (& lockLatency )
2051
- defer is .Unlock (& lockLatency )
2031
+ for _ , repo := range duplicateRepos {
2032
+ is .LockRepo (repo , & lockLatency )
2033
+ defer is .UnlockRepo (repo , & lockLatency )
2034
+ }
2052
2035
2053
2036
if dedupe {
2054
2037
return is .dedupeBlobs (ctx , digest , duplicateBlobs )
0 commit comments