Repository: juicedata/juicefs
Pull request #2711 (2022-09-09 07:33:15)

meta: move GetPaths to baseMeta

sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!&nbsp; &nbsp; [![Quality Gate passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonarcloud.io/dashboard?id=juicedata_juicefs&pullRequest=2711)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=juicedata_juicefs&pullRequest=2711&resolved=false&types=BUG) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=juicedata_juicefs&pullRequest=2711&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=juicedata_juicefs&pullRequest=2711&resolved=false&types=BUG)  
[![Vulnerability](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability-16px.png 'Vulnerability')](https://sonarcloud.io/project/issues?id=juicedata_juicefs&pullRequest=2711&resolved=false&types=VULNERABILITY) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=juicedata_juicefs&pullRequest=2711&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=juicedata_juicefs&pullRequest=2711&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot-16px.png 'Security Hotspot')](https://sonarcloud.io/project/security_hotspots?id=juicedata_juicefs&pullRequest=2711&resolved=false&types=SECURITY_HOTSPOT) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/security_hotspots?id=juicedata_juicefs&pullRequest=2711&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=juicedata_juicefs&pullRequest=2711&resolved=false&types=SECURITY_HOTSPOT)  
[![Code Smell](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell-16px.png 'Code Smell')](https://sonarcloud.io/project/issues?id=juicedata_juicefs&pullRequest=2711&resolved=false&types=CODE_SMELL) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=juicedata_juicefs&pullRequest=2711&resolved=false&types=CODE_SMELL) [1 Code Smell](https://sonarcloud.io/project/issues?id=juicedata_juicefs&pullRequest=2711&resolved=false&types=CODE_SMELL)

[![No Coverage information](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/NoCoverageInfo-16px.png 'No Coverage information')](https://sonarcloud.io/component_measures?id=juicedata_juicefs&pullRequest=2711) No Coverage information  
[![0.0%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/3-16px.png '0.0%')](https://sonarcloud.io/component_measures?id=juicedata_juicefs&pullRequest=2711&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonarcloud.io/component_measures?id=juicedata_juicefs&pullRequest=2711&metric=new_duplicated_lines_density&view=list)


codecov-commenter: # [Codecov](https://codecov.io/gh/juicedata/juicefs/pull/2711?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=juicedata) Report
> Merging [#2711](https://codecov.io/gh/juicedata/juicefs/pull/2711?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=juicedata) (9de8730) into [main](https://codecov.io/gh/juicedata/juicefs/commit/cdccfe8dbe6128209f9f3917059e7da07509455c?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=juicedata) (cdccfe8) will **decrease** coverage by `0.12%`.
> The diff coverage is `68.71%`.

```diff
@@            Coverage Diff             @@
##             main    #2711      +/-   ##
==========================================
- Coverage   59.58%   59.46%   -0.13%     
==========================================
  Files         138      138              
  Lines       23626    23725      +99     
==========================================
+ Hits        14077    14107      +30     
- Misses       7716     7779      +63     
- Partials     1833     1839       +6     
```


| [Impacted Files](https://codecov.io/gh/juicedata/juicefs/pull/2711?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=juicedata) | Coverage Δ | |
|---|---|---|
| [cmd/fsck.go](https://codecov.io/gh/juicedata/juicefs/pull/2711/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=juicedata#diff-Y21kL2ZzY2suZ28=) | `66.07% <0.00%> (ø)` | |
| [pkg/meta/interface.go](https://codecov.io/gh/juicedata/juicefs/pull/2711/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=juicedata#diff-cGtnL21ldGEvaW50ZXJmYWNlLmdv) | `45.45% <ø> (+0.06%)` | :arrow_up: |
| [pkg/meta/base.go](https://codecov.io/gh/juicedata/juicefs/pull/2711/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=juicedata#diff-cGtnL21ldGEvYmFzZS5nbw==) | `65.37% <49.05%> (-1.59%)` | :arrow_down: |
| [pkg/chunk/cached\_store.go](https://codecov.io/gh/juicedata/juicefs/pull/2711/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=juicedata#diff-cGtnL2NodW5rL2NhY2hlZF9zdG9yZS5nbw==) | `73.80% <50.00%> (-0.42%)` | :arrow_down: |
| [pkg/utils/logger.go](https://codecov.io/gh/juicedata/juicefs/pull/2711/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=juicedata#diff-cGtnL3V0aWxzL2xvZ2dlci5nbw==) | `63.93% <66.66%> (+1.67%)` | :arrow_up: |
| [pkg/chunk/disk\_cache.go](https://codecov.io/gh/juicedata/juicefs/pull/2711/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=juicedata#diff-cGtnL2NodW5rL2Rpc2tfY2FjaGUuZ28=) | `73.99% <79.76%> (-4.22%)` | :arrow_down: |
| [cmd/flags.go](https://codecov.io/gh/juicedata/juicefs/pull/2711/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=juicedata#diff-Y21kL2ZsYWdzLmdv) | `93.96% <100.00%> (+0.15%)` | :arrow_up: |
| [cmd/mount.go](https://codecov.io/gh/juicedata/juicefs/pull/2711/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=juicedata#diff-Y21kL21vdW50Lmdv) | `60.49% <100.00%> (+0.12%)` | :arrow_up: |
| [pkg/utils/logger\_syslog.go](https://codecov.io/gh/juicedata/juicefs/pull/2711/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=juicedata#diff-cGtnL3V0aWxzL2xvZ2dlcl9zeXNsb2cuZ28=) | `42.30% <100.00%> (ø)` | |
| [pkg/vfs/backup.go](https://codecov.io/gh/juicedata/juicefs/pull/2711/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=juicedata#diff-cGtnL3Zmcy9iYWNrdXAuZ28=) | `60.67% <100.00%> (-0.44%)` | :arrow_down: |
| ... and [9 more](https://codecov.io/gh/juicedata/juicefs/pull/2711/diff?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=juicedata) | |

Help us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=juicedata). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=juicedata)


Patch:
diff --git a/cmd/fsck.go b/cmd/fsck.go
index 9fe3d8fe..64e32289 100644
--- a/cmd/fsck.go
+++ b/cmd/fsck.go
@@ -159,7 +159,7 @@ func fsck(ctx *cli.Context) error {
 					}
 					if _, err := blob.Head(objKey); err != nil {
 						if _, ok := brokens[inode]; !ok {
-							if ps := meta.GetPaths(m, meta.Background, inode); len(ps) > 0 {
+							if ps := m.GetPaths(meta.Background, inode); len(ps) > 0 {
 								brokens[inode] = ps[0]
 							} else {
 								brokens[inode] = fmt.Sprintf("inode:%d", inode)
diff --git a/pkg/meta/base.go b/pkg/meta/base.go
index 2e3b55fd..5e22b68e 100644
--- a/pkg/meta/base.go
+++ b/pkg/meta/base.go
@@ -961,6 +961,90 @@ func (m *baseMeta) GetParents(ctx Context, inode Ino) map[Ino]int {
 	}
 }
 
+func (m *baseMeta) GetPaths(ctx Context, inode Ino) []string {
+	if inode == RootInode {
+		return []string{"/"}
+	}
+
+	if inode == TrashInode {
+		return []string{"/.trash"}
+	}
+
+	outside := "path not shown because it's outside of the mounted root"
+	getDirPath := func(ino Ino) (string, error) {
+		var names []string
+		var attr Attr
+		for ino != RootInode && ino != m.root {
+			if st := m.en.doGetAttr(ctx, ino, &attr); st != 0 {
+				return "", fmt.Errorf("getattr inode %d: %s", ino, st)
+			}
+			if attr.Typ != TypeDirectory {
+				return "", fmt.Errorf("inode %d is not a directory", ino)
+			}
+			var entries []*Entry
+			if st := m.en.doReaddir(ctx, attr.Parent, 0, &entries, -1); st != 0 {
+				return "", fmt.Errorf("readdir inode %d: %s", ino, st)
+			}
+			var name string
+			for _, e := range entries {
+				if e.Inode == ino {
+					name = string(e.Name)
+					break
+				}
+			}
+			if attr.Parent == RootInode && ino == TrashInode {
+				name = TrashName
+			}
+			if name == "" {
+				return "", fmt.Errorf("entry %d/%d not found", attr.Parent, ino)
+			}
+			names = append(names, name)
+			ino = attr.Parent
+		}
+		if m.root != RootInode && ino == RootInode {
+			return outside, nil
+		}
+		names = append(names, "/") // add root
+
+		for i, j := 0, len(names)-1; i < j; i, j = i+1, j-1 { // reverse
+			names[i], names[j] = names[j], names[i]
+		}
+		return path.Join(names...), nil
+	}
+
+	var paths []string
+	// inode != RootInode, parent is the real parent inode
+	for parent, count := range m.GetParents(ctx, inode) {
+		if count <= 0 {
+			continue
+		}
+		dir, err := getDirPath(parent)
+		if err != nil {
+			logger.Warnf("Get directory path of %d: %s", parent, err)
+			continue
+		} else if dir == outside {
+			paths = append(paths, outside)
+			continue
+		}
+		var entries []*Entry
+		if st := m.en.doReaddir(ctx, parent, 0, &entries, -1); st != 0 {
+			logger.Warnf("Readdir inode %d: %s", parent, st)
+			continue
+		}
+		var c int
+		for _, e := range entries {
+			if e.Inode == inode {
+				c++
+				paths = append(paths, path.Join(dir, string(e.Name)))
+			}
+		}
+		if c != count {
+			logger.Warnf("Expect to find %d entries under parent %d, but got %d", count, parent, c)
+		}
+	}
+	return paths
+}
+
 func (m *baseMeta) Check(ctx Context, fpath string, repair bool) (st syscall.Errno) {
 	var attr Attr
 	var inode Ino
diff --git a/pkg/meta/interface.go b/pkg/meta/interface.go
index 2f504708..c077179f 100644
--- a/pkg/meta/interface.go
+++ b/pkg/meta/interface.go
@@ -21,7 +21,6 @@ import (
 	"io"
 	"net/url"
 	"os"
-	"path"
 	"strings"
 	"syscall"
 	"time"
@@ -349,6 +348,8 @@ type Meta interface {
 	ListSlices(ctx Context, slices map[Ino][]Slice, delete bool, showProgress func()) syscall.Errno
 	// Remove all files and directories recursively.
 	Remove(ctx Context, parent Ino, name string, count *uint64) syscall.Errno
+	// GetPaths returns all paths of an inode
+	GetPaths(ctx Context, inode Ino) []string
 	// Check integrity of an absolute path and repair it if asked
 	Check(ctx Context, fpath string, repair bool) syscall.Errno
 
@@ -427,89 +428,3 @@ func newSessionInfo() *SessionInfo {
 	}
 	return &SessionInfo{Version: version.Version(), HostName: host, ProcessID: os.Getpid()}
 }
-
-// Get all paths of an inode
-func GetPaths(m Meta, ctx Context, inode Ino) []string {
-	if inode == RootInode {
-		return []string{"/"}
-	}
-
-	if inode == TrashInode {
-		return []string{"/.trash"}
-	}
-
-	base := m.getBase()
-	outside := "path not shown because it's outside of the mounted root"
-	getDirPath := func(ino Ino) (string, error) {
-		var names []string
-		var attr Attr
-		for ino != RootInode && ino != base.root {
-			if st := base.en.doGetAttr(ctx, ino, &attr); st != 0 {
-				return "", fmt.Errorf("getattr inode %d: %s", ino, st)
-			}
-			if attr.Typ != TypeDirectory {
-				return "", fmt.Errorf("inode %d is not a directory", ino)
-			}
-			var entries []*Entry
-			if st := base.en.doReaddir(ctx, attr.Parent, 0, &entries, -1); st != 0 {
-				return "", fmt.Errorf("readdir inode %d: %s", ino, st)
-			}
-			var name string
-			for _, e := range entries {
-				if e.Inode == ino {
-					name = string(e.Name)
-					break
-				}
-			}
-			if attr.Parent == RootInode && ino == TrashInode {
-				name = TrashName
-			}
-			if name == "" {
-				return "", fmt.Errorf("entry %d/%d not found", attr.Parent, ino)
-			}
-			names = append(names, name)
-			ino = attr.Parent
-		}
-		if base.root != RootInode && ino == RootInode {
-			return outside, nil
-		}
-		names = append(names, "/") // add root
-
-		for i, j := 0, len(names)-1; i < j; i, j = i+1, j-1 { // reverse
-			names[i], names[j] = names[j], names[i]
-		}
-		return path.Join(names...), nil
-	}
-
-	var paths []string
-	// inode != RootInode, parent is the real parent inode
-	for parent, count := range m.GetParents(ctx, inode) {
-		if count <= 0 {
-			continue
-		}
-		dir, err := getDirPath(parent)
-		if err != nil {
-			logger.Warnf("Get directory path of %d: %s", parent, err)
-			continue
-		} else if dir == outside {
-			paths = append(paths, outside)
-			continue
-		}
-		var entries []*Entry
-		if st := base.en.doReaddir(ctx, parent, 0, &entries, -1); st != 0 {
-			logger.Warnf("Readdir inode %d: %s", parent, st)
-			continue
-		}
-		var c int
-		for _, e := range entries {
-			if e.Inode == inode {
-				c++
-				paths = append(paths, path.Join(dir, string(e.Name)))
-			}
-		}
-		if c != count {
-			logger.Warnf("Expect to find %d entries under parent %d, but got %d", count, parent, c)
-		}
-	}
-	return paths
-}
diff --git a/pkg/vfs/internal.go b/pkg/vfs/internal.go
index 81d14fa5..b738654d 100644
--- a/pkg/vfs/internal.go
+++ b/pkg/vfs/internal.go
@@ -290,7 +290,7 @@ func (v *VFS) handleInternalMsg(ctx meta.Context, cmd uint32, r *utils.Buffer, d
 		fmt.Fprintf(w, "   dirs: %d\n", summary.Dirs)
 		fmt.Fprintf(w, " length: %s\n", utils.FormatBytes(summary.Length))
 		fmt.Fprintf(w, "   size: %s\n", utils.FormatBytes(summary.Size))
-		ps := meta.GetPaths(v.Meta, ctx, inode)
+		ps := v.Meta.GetPaths(ctx, inode)
 		switch len(ps) {
 		case 0:
 			fmt.Fprintf(w, "   path: %s\n", "unknown")


Test patch:
diff --git a/pkg/meta/base_test.go b/pkg/meta/base_test.go
index 0c4055b1..557eaee9 100644
--- a/pkg/meta/base_test.go
+++ b/pkg/meta/base_test.go
@@ -735,10 +735,10 @@ func testRemove(t *testing.T, m Meta) {
 	if st := m.Create(ctx, parent, "f", 0644, 0, 0, &inode, attr); st != 0 {
 		t.Fatalf("create d/f: %s", st)
 	}
-	if ps := GetPaths(m, ctx, parent); len(ps) == 0 || ps[0] != "/d" {
+	if ps := m.GetPaths(ctx, parent); len(ps) == 0 || ps[0] != "/d" {
 		t.Fatalf("get path /d: %v", ps)
 	}
-	if ps := GetPaths(m, ctx, inode); len(ps) == 0 || ps[0] != "/d/f" {
+	if ps := m.GetPaths(ctx, inode); len(ps) == 0 || ps[0] != "/d/f" {
 		t.Fatalf("get path /d/f: %v", ps)
 	}
 	for i := 0; i < 4096; i++ {