@@ -803,10 +803,15 @@ type engineConfig struct {
803803
804804// Pebble is a wrapper around a Pebble database instance.
805805type Pebble struct {
806- cfg engineConfig
807- db * pebble.DB
808- closed atomic.Bool
809- auxDir string
806+ cfg engineConfig
807+ db * pebble.DB
808+ closed atomic.Bool
809+ auxDir string
810+ auxiliarySize struct {
811+ mu sync.Mutex
812+ computedAt time.Time
813+ size int64
814+ }
810815 ballastPath string
811816 properties roachpb.StoreProperties
812817
@@ -1919,37 +1924,11 @@ func (p *Pebble) Capacity() (roachpb.StoreCapacity, error) {
19191924 m := p .db .Metrics ()
19201925 totalUsedBytes := int64 (m .DiskSpaceUsage ())
19211926
1922- // We don't have incremental accounting of the disk space usage of files
1923- // in the auxiliary directory. Walk the auxiliary directory and all its
1924- // subdirectories, adding to the total used bytes.
1925- if errOuter := filepath .Walk (p .auxDir , func (path string , info os.FileInfo , err error ) error {
1926- if err != nil {
1927- // This can happen if CockroachDB removes files out from under us -
1928- // just keep going to get the best estimate we can.
1929- if oserror .IsNotExist (err ) {
1930- return nil
1931- }
1932- // Special-case: if the store-dir is configured using the root of some fs,
1933- // e.g. "/mnt/db", we might have special fs-created files like lost+found
1934- // that we can't read, so just ignore them rather than crashing.
1935- if oserror .IsPermission (err ) && filepath .Base (path ) == "lost+found" {
1936- return nil
1937- }
1938- return err
1939- }
1940- if path == p .ballastPath {
1941- // Skip the ballast. Counting it as used is likely to confuse
1942- // users, and it's more akin to space that is just unavailable
1943- // like disk space often restricted to a root user.
1944- return nil
1945- }
1946- if info .Mode ().IsRegular () {
1947- totalUsedBytes += info .Size ()
1948- }
1949- return nil
1950- }); errOuter != nil {
1951- return roachpb.StoreCapacity {}, errOuter
1927+ auxiliarySize , err := p .auxiliaryDirSize ()
1928+ if err != nil {
1929+ return roachpb.StoreCapacity {}, err
19521930 }
1931+ totalUsedBytes += auxiliarySize
19531932
19541933 // If no size limitation have been placed on the store size or if the
19551934 // limitation is greater than what's available, just return the actual
@@ -1982,6 +1961,54 @@ func (p *Pebble) Capacity() (roachpb.StoreCapacity, error) {
19821961 }, nil
19831962}
19841963
1964+ // auxiliaryDirSize computes the size of the auxiliary directory. There are
1965+ // multiple Cockroach subsystems that write into the auxiliary directory, and
1966+ // they don't incrementally account for their disk space usage. This function
1967+ // walks the auxiliary directory and all its subdirectories, summing the file
1968+ // sizes. This walk can be expensive, so we cache the result and only recompute
1969+ // if it's over 1 minute stale.
1970+ //
1971+ // TODO(jackson): Eventually we should update the various subsystems writing
1972+ // into the auxiliary directory to incrementally account for their disk space
1973+ // usage. See #96344.
1974+ func (p * Pebble ) auxiliaryDirSize () (int64 , error ) {
1975+ p .auxiliarySize .mu .Lock ()
1976+ defer p .auxiliarySize .mu .Unlock ()
1977+ if time .Since (p .auxiliarySize .computedAt ) < time .Minute {
1978+ return p .auxiliarySize .size , nil
1979+ }
1980+
1981+ p .auxiliarySize .size = 0
1982+ err := filepath .Walk (p .auxDir , func (path string , info os.FileInfo , err error ) error {
1983+ if err != nil {
1984+ // This can happen if CockroachDB removes files out from under us -
1985+ // just keep going to get the best estimate we can.
1986+ if oserror .IsNotExist (err ) {
1987+ return nil
1988+ }
1989+ // Special-case: if the store-dir is configured using the root of some fs,
1990+ // e.g. "/mnt/db", we might have special fs-created files like lost+found
1991+ // that we can't read, so just ignore them rather than crashing.
1992+ if oserror .IsPermission (err ) && filepath .Base (path ) == "lost+found" {
1993+ return nil
1994+ }
1995+ return err
1996+ }
1997+ if path == p .ballastPath {
1998+ // Skip the ballast. Counting it as used is likely to confuse
1999+ // users, and it's more akin to space that is just unavailable
2000+ // like disk space often restricted to a root user.
2001+ return nil
2002+ }
2003+ if info .Mode ().IsRegular () {
2004+ p .auxiliarySize .size += info .Size ()
2005+ }
2006+ return nil
2007+ })
2008+ p .auxiliarySize .computedAt = time .Now ()
2009+ return p .auxiliarySize .size , err
2010+ }
2011+
19852012// Flush implements the Engine interface.
19862013func (p * Pebble ) Flush () error {
19872014 return p .db .Flush ()
0 commit comments