github.com/Prakhar-Agarwal-byte/moby@v0.0.0-20231027092010-a14e3e8ab87e/pkg/fileutils/fileutils_linux.go (about) 1 package fileutils 2 3 import ( 4 "context" 5 "fmt" 6 "io" 7 "os" 8 9 "github.com/containerd/log" 10 "golang.org/x/sys/unix" 11 ) 12 13 // GetTotalUsedFds Returns the number of used File Descriptors by 14 // reading it via /proc filesystem. 15 func GetTotalUsedFds() int { 16 name := fmt.Sprintf("/proc/%d/fd", os.Getpid()) 17 18 // Fast-path for Linux 6.2 (since [f1f1f2569901ec5b9d425f2e91c09a0e320768f3]). 19 // From the [Linux docs]: 20 // 21 // "The number of open files for the process is stored in 'size' member of 22 // stat() output for /proc/<pid>/fd for fast access." 23 // 24 // [Linux docs]: https://docs.kernel.org/filesystems/proc.html#proc-pid-fd-list-of-symlinks-to-open-files: 25 // [f1f1f2569901ec5b9d425f2e91c09a0e320768f3]: https://github.com/torvalds/linux/commit/f1f1f2569901ec5b9d425f2e91c09a0e320768f3 26 var stat unix.Stat_t 27 if err := unix.Stat(name, &stat); err == nil && stat.Size > 0 { 28 return int(stat.Size) 29 } 30 31 f, err := os.Open(name) 32 if err != nil { 33 log.G(context.TODO()).WithError(err).Error("Error listing file descriptors") 34 return -1 35 } 36 defer f.Close() 37 38 var fdCount int 39 for { 40 names, err := f.Readdirnames(100) 41 fdCount += len(names) 42 if err == io.EOF { 43 break 44 } else if err != nil { 45 log.G(context.TODO()).WithError(err).Error("Error listing file descriptors") 46 return -1 47 } 48 } 49 // Note that the slow path has 1 more file-descriptor, due to the open 50 // file-handle for /proc/<pid>/fd during the calculation. 51 return fdCount 52 }