commit 5944c1fe580363b2e373e7ab4fbe420c59e48a02
parent 54b8547e46c57f6a208bf3efd5a40e9cca9df833
Author: Matsuda Kenji <info@mtkn.jp>
Date: Sat, 16 Dec 2023 09:11:14 +0900
cache gid
assuming that gids are not changed by other program
Diffstat:
1 file changed, 26 insertions(+), 9 deletions(-)
diff --git a/diskfs/stat_unix.go b/diskfs/stat_unix.go
@@ -52,6 +52,12 @@ func fiStat(pool *QidPool, id fileID, info fs.FileInfo) *lib9p.Stat {
}
}
+var gidCache map[fileID]string
+
+func init() {
+ gidCache = make(map[fileID]string)
+}
+
// Stat is real implementation of File.Stat.
func (f *File) stat() (*lib9p.FileInfo, error) {
ospath := filepath.Join(f.fs.rootPath, f.path)
@@ -69,26 +75,30 @@ func (f *File) stat() (*lib9p.FileInfo, error) {
panic(fmt.Errorf("alloc qid: %v", err))
}
}
+ stat_t := fsfi.Sys().(*syscall.Stat_t)
stat.Qid = qid
stat.Length = fsfi.Size()
stat.Mode = fsfi.Mode()
stat.Name = fsfi.Name()
- // TODO: Unix specific.
- stat.Atime = uint32(fsfi.Sys().(*syscall.Stat_t).Atim.Sec)
- stat.Mtime = uint32(fsfi.Sys().(*syscall.Stat_t).Mtim.Sec)
- uid := fsfi.Sys().(*syscall.Stat_t).Uid
+ stat.Atime = uint32(stat_t.Atim.Sec)
+ stat.Mtime = uint32(stat_t.Mtim.Sec)
+ uid := stat_t.Uid
usr, err := user.LookupId(strconv.Itoa(int(uid)))
if err != nil {
return nil, fmt.Errorf("LookupId(%d): %v", uid, err)
}
stat.Uid = usr.Username
- gid := fsfi.Sys().(*syscall.Stat_t).Gid
+ gid := stat_t.Gid
// TODO: this call is time consuming.
- group, err := user.LookupGroupId(strconv.Itoa(int(gid)))
- if err != nil {
- return nil, fmt.Errorf("LookupGroupId(%d): %v", gid, err)
+ fileid := fileID{device: stat_t.Dev, inode: stat_t.Ino}
+ if _, ok := gidCache[fileid]; !ok {
+ group, err := user.LookupGroupId(strconv.Itoa(int(gid)))
+ if err != nil {
+ return nil, fmt.Errorf("LookupGroupId(%d): %v", gid, err)
+ }
+ gidCache[fileid] = group.Name
}
- stat.Gid = group.Name
+ stat.Gid = gidCache[fileid]
stat.Muid = ""
return &lib9p.FileInfo{stat}, nil
}
@@ -163,6 +173,13 @@ func (f *File) wstat(s *lib9p.Stat) error {
if err := file.Chown(u, g); err != nil {
return fmt.Errorf("chown: %v", err)
}
+ st, err := file.Stat()
+ if err != nil {
+ return fmt.Errorf("stat: %v", err)
+ }
+ stat_t := st.Sys().(*syscall.Stat_t)
+ fileid := fileID{device: stat_t.Dev, inode: stat_t.Ino}
+ gidCache[fileid] = s.Gid
}
if s.Name != oldStat.Name {
// TODO: check neither Names contains "/"