commit 470d538d28ab3c257fb4230933a9306cb4031a19
parent 1231b1592ccba8c2606599e8b26b180fe049e09c
Author: Matsuda Kenji <info@mtkn.jp>
Date:   Mon, 21 Oct 2024 08:30:16 +0900
delete qid when a file is removed
Diffstat:
4 files changed, 23 insertions(+), 15 deletions(-)
diff --git a/diskfs/fs.go b/diskfs/fs.go
@@ -114,7 +114,6 @@ func (fsys *FS) Create(name string, uid string, omode lib9p.OpenMode, perm lib9p
 				Err:  fmt.Errorf("mkdir: %v", err),
 			}
 		}
-		fmt.Fprintf(os.Stderr, "mkdir(%s, %s)\n", ospath, perm)
 		osfile, err = os.OpenFile(ospath, flag, 0)
 		if err != nil {
 			return nil, &fs.PathError{
@@ -123,8 +122,6 @@ func (fsys *FS) Create(name string, uid string, omode lib9p.OpenMode, perm lib9p
 				Err:  err,
 			}
 		}
-		qid, _ := fsys.qidPool.lookup(&File{fs: fsys, path: name, file: osfile})
-		fmt.Fprintf(os.Stderr, "qid: %v\n", qid)
 	} else {
 		flag |= os.O_CREATE
 		osfile, err = os.OpenFile(ospath, flag, perm)
@@ -143,6 +140,8 @@ func (fsys *FS) Create(name string, uid string, omode lib9p.OpenMode, perm lib9p
 	}, nil
 }
 
+// Remove removes the file specified by name.
+// It also removes the corresponding qid record from fsys.
 func (fsys *FS) Remove(name string) error {
 	ospath := path.Join(fsys.rootPath, name)
 	fi, err := os.Stat(ospath)
@@ -154,6 +153,18 @@ func (fsys *FS) Remove(name string) error {
 	return os.Remove(ospath)
 }
 
+// ShowQidPool returns the string representing the content of
+// fsys.qidPool for debugging.
+func (fsys *FS) ShowQidPool() string {
+	var s string
+	fsys.qidPool.Lock()
+	defer fsys.qidPool.Unlock()
+	for id, qr := range fsys.qidPool.m {
+		s += fmt.Sprintf("%v: %v\n", qr.qid, id)
+	}
+	return s
+}
+
 func (fsys *FS) IsGroupLeader(group, uid string) bool {
 	return isGroupLeader(group, uid)
 }
diff --git a/diskfs/qid_unix.go b/diskfs/qid_unix.go
@@ -21,6 +21,10 @@ type fileID struct {
 	inode  uint64
 }
 
+func (id fileID) String() string {
+	return fmt.Sprintf("(device %d, inode %d)", id.device, id.inode)
+}
+
 // qidReq is used to update the Qid.Vers by checking the file's
 // modified time.
 type qidRec struct {
diff --git a/diskfs/stat_unix.go b/diskfs/stat_unix.go
@@ -3,7 +3,6 @@
 package diskfs
 
 import (
-	"errors"
 	"fmt"
 	"io/fs"
 	"os"
@@ -64,7 +63,6 @@ func init() {
 
 // Stat is real implementation of File.Stat.
 func (f *File) stat() (*lib9p.FileInfo, error) {
-	fmt.Fprintf(os.Stderr, "stat: nextQid: %d ", f.fs.qidPool.nextQid)
 	ospath := filepath.Join(f.fs.rootPath, f.path)
 	fsfi, err := os.Stat(ospath)
 	if err != nil {
@@ -78,14 +76,12 @@ func (f *File) stat() (*lib9p.FileInfo, error) {
 	if err != nil {
 		return nil, fmt.Errorf("fiStat: %v", err)
 	}
-	fmt.Fprintf(os.Stderr, "-> %d\n", f.fs.qidPool.nextQid)
 	return &lib9p.FileInfo{Stat: *stat}, nil
 }
 
 // wstat is the real implementation of File.WStat.
 // TODO: when error occurs, file stat should be restored.
 func (f *File) wstat(s *lib9p.Stat) error {
-	fmt.Fprintf(os.Stderr, "stat: nextQid: %d ", f.fs.qidPool.nextQid)
 	var file *os.File
 	fi, err := f.Stat()
 	if err != nil {
@@ -166,15 +162,16 @@ func (f *File) wstat(s *lib9p.Stat) error {
 		// TODO: check neither Name contains "/"
 		oldpath := path.Join(f.fs.rootPath, path.Dir(f.path), oldStat.Name)
 		newpath := path.Join(f.fs.rootPath, path.Dir(f.path), s.Name)
-		if _, err := os.Stat(newpath); errors.Is(err, fs.ErrExist) {
-			if err := f.fs.Remove(newpath); err != nil {
-				return fmt.Errorf("remove old file: %v", err)
+		if fi, err := os.Stat(newpath); err == nil {
+			id := idFromInfo(newpath, fi)
+			f.fs.qidPool.deleteID(id)
+			if err := os.Remove(newpath); err != nil {
+				return fmt.Errorf("remove old file %s: %v", s.Name, err)
 			}
 		}
 		if err := os.Rename(oldpath, newpath); err != nil {
 			return fmt.Errorf("rename: %v", err)
 		}
 	}
-	fmt.Fprintf(os.Stderr, "-> %d\n", f.fs.qidPool.nextQid)
 	return nil
 }
diff --git a/server.go b/server.go
@@ -672,8 +672,6 @@ func sCreate(ctx context.Context, c *conn, rc <-chan *request) {
 				perm &= ^FileMode(0777) | (dirperm & FileMode(0777))
 			}
 			cpath = path.Join(r.fid.path, ifcall.Name)
-			fmt.Fprintf(os.Stderr, "Create(%s, %s, %v, %v)\n", cpath, r.fid.uid,
-				ifcall.Mode, perm)
 			r.fid.file, err = cfs.Create(cpath, r.fid.uid, ifcall.Mode, perm)
 			if err != nil {
 				r.err = fmt.Errorf("create: %v", err)
@@ -686,8 +684,6 @@ func sCreate(ctx context.Context, c *conn, rc <-chan *request) {
 				r.err = fmt.Errorf("stat: %v", err)
 				goto resp
 			}
-			fmt.Fprintf(os.Stderr, "qid: %v\n", fi.Sys().(*Stat).Qid)
-			fmt.Fprintf(os.Stderr, "filename: %s\n", fi.Sys().(*Stat).Name)
 			r.fid.qidpath = fi.Sys().(*Stat).Qid.Path
 			r.ofcall = &RCreate{
 				Qid:    fi.Sys().(*Stat).Qid,