Skip to content

Commit 6e1889d

Browse files
committed
Merge branch 'main' into fricounet/token-renewals
Signed-off-by: Baptiste Girard-Carrabin <baptiste.girardcarrabin@datadoghq.com>
2 parents 8023a75 + 3b3747c commit 6e1889d

File tree

14 files changed

+341
-22
lines changed

14 files changed

+341
-22
lines changed

config/daemonconfig/daemonconfig.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ type BackendConfig struct {
112112
}
113113

114114
type DeviceConfig struct {
115+
ID string `json:"id,omitempty"`
115116
Backend struct {
116117
BackendType string `json:"type"`
117118
Config BackendConfig `json:"config"`

config/daemonconfig/fuse.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,17 @@ func LoadFuseConfig(p string) (*FuseDaemonConfig, error) {
6060
return &cfg, nil
6161
}
6262

63-
func (c *FuseDaemonConfig) Supplement(host, repo, _ string, params map[string]string) {
63+
func (c *FuseDaemonConfig) Supplement(host, repo, snapshotID string, params map[string]string) {
6464
if host != "" {
6565
c.Device.Backend.Config.Host = host
6666
}
6767
if repo != "" {
6868
c.Device.Backend.Config.Repo = repo
6969
}
70+
// Temporary fix while https://github.com/containerd/nydus-snapshotter/issues/712 is being addressed
71+
if snapshotID != "" {
72+
c.Device.ID = "/" + snapshotID
73+
}
7074
c.Device.Cache.Config.WorkDir = params[CacheDir]
7175
}
7276

pkg/cache/manager.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"context"
1111
"os"
1212
"path"
13+
"strings"
1314
"time"
1415

1516
"github.com/pkg/errors"
@@ -120,3 +121,32 @@ func (m *Manager) RemoveBlobCache(blobID string) error {
120121
}
121122
return nil
122123
}
124+
125+
// extractBlobIDFromFilename extracts the blob ID from a cache filename
126+
// Cache files can have formats like:
127+
// - <blobID>
128+
// - <blobID>.blob.data
129+
// - <blobID>.chunk_map
130+
// - <blobID>.blob.meta
131+
// - <blobID>.image.disk
132+
// - <blobID>.layer.disk
133+
func ExtractBlobIDFromFilename(filename string) string {
134+
// Remove known suffixes
135+
suffixes := []string{
136+
dataFileSuffix,
137+
dataFileSuffix + chunkMapFileSuffix,
138+
chunkMapFileSuffix,
139+
metaFileSuffix,
140+
imageDiskFileSuffix,
141+
layerDiskFileSuffix,
142+
}
143+
144+
for _, suffix := range suffixes {
145+
if strings.HasSuffix(filename, suffix) {
146+
return strings.TrimSuffix(filename, suffix)
147+
}
148+
}
149+
150+
// If no suffix matches, assume it's already a blob ID
151+
return filename
152+
}

pkg/cache/manager_test.go

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
* Copyright (c) 2025. Nydus Developers. All rights reserved.
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
package cache
8+
9+
import (
10+
"testing"
11+
12+
"github.com/stretchr/testify/assert"
13+
)
14+
15+
func TestExtractBlobIDFromFilename(t *testing.T) {
16+
tests := map[string]struct {
17+
filename string
18+
expected string
19+
}{
20+
"plain blob ID": {
21+
filename: "abc123def456",
22+
expected: "abc123def456",
23+
},
24+
"blob with .blob.data suffix": {
25+
filename: "abc123def456.blob.data",
26+
expected: "abc123def456",
27+
},
28+
"blob with .chunk_map suffix": {
29+
filename: "abc123def456.chunk_map",
30+
expected: "abc123def456",
31+
},
32+
"blob with .blob.meta suffix": {
33+
filename: "abc123def456.blob.meta",
34+
expected: "abc123def456",
35+
},
36+
"blob with .image.disk suffix": {
37+
filename: "abc123def456.image.disk",
38+
expected: "abc123def456",
39+
},
40+
"blob with .layer.disk suffix": {
41+
filename: "abc123def456.layer.disk",
42+
expected: "abc123def456",
43+
},
44+
"blob with combined .blob.data.chunk_map suffix": {
45+
filename: "abc123def456.blob.data.chunk_map",
46+
expected: "abc123def456",
47+
},
48+
"real sha256 hash": {
49+
filename: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
50+
expected: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
51+
},
52+
"real sha256 hash with .blob.data": {
53+
filename: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.blob.data",
54+
expected: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
55+
},
56+
"real sha256 hash with .chunk_map": {
57+
filename: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.chunk_map",
58+
expected: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
59+
},
60+
"real sha256 hash with .blob.data.chunk_map": {
61+
filename: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.blob.data.chunk_map",
62+
expected: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
63+
},
64+
"empty filename": {
65+
filename: "",
66+
expected: "",
67+
},
68+
"filename with unknown suffix": {
69+
filename: "abc123def456.unknown",
70+
expected: "abc123def456.unknown",
71+
},
72+
"filename with multiple dots but no known suffix": {
73+
filename: "abc.def.ghi",
74+
expected: "abc.def.ghi",
75+
},
76+
".blob.data.chunk_map is matched before .blob.data or .chunk_map": {
77+
filename: "test.blob.data.chunk_map",
78+
expected: "test",
79+
},
80+
}
81+
82+
for name, tc := range tests {
83+
t.Run(name, func(t *testing.T) {
84+
result := ExtractBlobIDFromFilename(tc.filename)
85+
assert.Equal(t, tc.expected, result)
86+
})
87+
}
88+
}

pkg/daemon/daemon.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,10 @@ func (d *Daemon) AddRafsInstance(r *rafs.Rafs) {
151151
r.DaemonID = d.ID()
152152
}
153153

154+
func (d *Daemon) UpdateRafsInstance(r *rafs.Rafs) {
155+
d.RafsCache.Add(r)
156+
}
157+
154158
func (d *Daemon) RemoveRafsInstance(snapshotID string) {
155159
d.RafsCache.Remove(snapshotID)
156160
d.DecRef()

pkg/filesystem/fs.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import (
4242
"github.com/containerd/nydus-snapshotter/pkg/signature"
4343
"github.com/containerd/nydus-snapshotter/pkg/stargz"
4444
"github.com/containerd/nydus-snapshotter/pkg/tarfs"
45+
"github.com/containerd/nydus-snapshotter/pkg/utils/erofs"
4546
)
4647

4748
type Filesystem struct {
@@ -268,6 +269,45 @@ func (fs *Filesystem) WaitUntilReady(snapshotID string) error {
268269
return err
269270
}
270271

272+
// For shared daemons, we need to use the correct cache ID to query metrics.
273+
// For fscache, the cache is registered with fscacheID (a digest), not the raw snapshot ID.
274+
// For fusedev, the cache is registered with the snapshot ID.
275+
sid := ""
276+
if d.IsSharedDaemon() {
277+
if rafs.GetFsDriver() == config.FsDriverFscache {
278+
// For fscache, use the fscache ID from annotations if available
279+
if fscacheID, ok := rafs.Annotations[racache.AnnoFsCacheID]; ok && fscacheID != "" {
280+
sid = fscacheID
281+
} else {
282+
// Fallback: compute fscacheID if not in annotations yet
283+
sid = erofs.FscacheID(rafs.SnapshotID)
284+
}
285+
} else {
286+
// For fusedev, use the snapshot ID directly
287+
sid = rafs.SnapshotID
288+
}
289+
}
290+
291+
cacheMetrics, err := d.GetCacheMetrics(sid)
292+
if err != nil {
293+
return errors.Wrapf(err, "failed to get cache metric")
294+
}
295+
log.L.Debugf("Found %d underlying files for rafs instance %s", len(cacheMetrics.UnderlyingFiles), rafs.SnapshotID)
296+
297+
// Lock the daemon's RafsCache when modifying rafs fields to prevent
298+
// race conditions with concurrent reads (e.g., during cache cleanup)
299+
d.RafsCache.Lock()
300+
rafs.UnderlyingFiles = cacheMetrics.UnderlyingFiles
301+
d.RafsCache.Unlock()
302+
303+
fsManager, err := fs.getManager(rafs.GetFsDriver())
304+
if err != nil {
305+
return errors.Wrap(err, "failed to get manager")
306+
}
307+
err = fsManager.UpdateRafsInstance(rafs)
308+
if err != nil {
309+
return errors.Wrap(err, "failed to update rafs instance")
310+
}
271311
log.L.Debugf("Nydus remote snapshot %s is ready", snapshotID)
272312
}
273313

@@ -603,6 +643,24 @@ func (fs *Filesystem) RemoveCache(blobDigest string) error {
603643
return fs.cacheMgr.RemoveBlobCache(blobID)
604644
}
605645

646+
// WalkManagers iterates over all enabled managers and calls the provided function
647+
func (fs *Filesystem) WalkManagers(fn func(*manager.Manager) error) error {
648+
for _, mgr := range fs.enabledManagers {
649+
if err := fn(mgr); err != nil {
650+
return err
651+
}
652+
}
653+
return nil
654+
}
655+
656+
// GetCacheConfig returns the cache directory from the cache manager
657+
func (fs *Filesystem) GetCacheDir() (string, error) {
658+
if fs.cacheMgr == nil {
659+
return "", errors.New("cache manager is not initialized")
660+
}
661+
return fs.cacheMgr.CacheDir(), nil
662+
}
663+
606664
// Try to stop all the running daemons if they are not referenced by any snapshots
607665
// Clean up resources along with the daemons.
608666
func (fs *Filesystem) Teardown(ctx context.Context) error {

pkg/manager/manager.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,10 @@ func (m *Manager) AddRafsInstance(r *rafs.Rafs) error {
146146
return m.store.AddRafsInstance(r)
147147
}
148148

149+
func (m *Manager) UpdateRafsInstance(r *rafs.Rafs) error {
150+
return m.store.UpdateRafsInstance(r)
151+
}
152+
149153
func (m *Manager) RemoveRafsInstance(snapshotID string) error {
150154
return m.store.DeleteRafsInstance(snapshotID)
151155
}

pkg/manager/store.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ type Store interface {
2525
CleanupDaemons(ctx context.Context) error
2626

2727
AddRafsInstance(r *rafs.Rafs) error
28+
UpdateRafsInstance(r *rafs.Rafs) error
2829
DeleteRafsInstance(snapshotID string) error
2930
WalkRafsInstances(ctx context.Context, cb func(*rafs.Rafs) error) error
3031

pkg/metrics/data/snapshotter.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,4 +79,25 @@ var (
7979
Help: "Thread counts of snapshotter.",
8080
},
8181
)
82+
83+
CacheBlobsDeleted = prometheus.NewCounter(
84+
prometheus.CounterOpts{
85+
Name: "snapshotter_cache_blobs_deleted_total",
86+
Help: "Total number of cache blobs deleted during cleanup.",
87+
},
88+
)
89+
90+
CacheBlobsInUse = prometheus.NewGauge(
91+
prometheus.GaugeOpts{
92+
Name: "snapshotter_cache_blobs_in_use",
93+
Help: "Number of cache blobs currently in use by running daemons.",
94+
},
95+
)
96+
97+
CacheBlobDeletionErrors = prometheus.NewCounter(
98+
prometheus.CounterOpts{
99+
Name: "snapshotter_cache_blob_deletion_errors_total",
100+
Help: "Total number of errors encountered while deleting cache blobs.",
101+
},
102+
)
82103
)

pkg/metrics/registry/registry.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,10 @@ func init() {
4444
data.CachePrefetchCumulativeTimeMillis,
4545
data.CachePrefetchTotalDurationMillis,
4646
data.CacheBufferedBackendSize,
47-
data.CredentialRenewals,
47+
data.CacheBlobsDeleted,
48+
data.CacheBlobsInUse,
49+
data.CacheBlobDeletionErrors,
50+
data.CredentialRenewals,
4851
data.CredentialStoreEntries,
4952
)
5053

0 commit comments

Comments
 (0)