Skip to content

Commit

Permalink
lock MFS root in node
Browse files Browse the repository at this point in the history
  • Loading branch information
schomatis committed Nov 27, 2021
1 parent c00065c commit 3939682
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 4 deletions.
12 changes: 10 additions & 2 deletions core/commands/files.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
gopath "path"
"sort"
"strings"
"time"

humanize "github.com/dustin/go-humanize"
"github.com/ipfs/go-ipfs/core"
Expand Down Expand Up @@ -768,6 +769,8 @@ stat' on the file or any of its ancestors.
cmds.BoolOption(filesTruncateOptionName, "t", "Truncate the file to size zero before writing."),
cmds.Int64Option(filesCountOptionName, "n", "Maximum number of bytes to read."),
cmds.BoolOption(filesRawLeavesOptionName, "Use raw blocks for newly created leaf nodes. (experimental)"),
// FIXME: Fake lock for manual testing. Remove.
cmds.IntOption("lock-time", "lt", "[TESTING] timeout to hold the MFS lock while copying").WithDefault(0),
cidVersionOption,
hashOption,
},
Expand All @@ -792,20 +795,25 @@ stat' on the file or any of its ancestors.
if err != nil {
return err
}
filesRoot := nd.LockedFilesRoot.LockRoot()
defer nd.LockedFilesRoot.UnlockRoot()
// Keep the hold for a fake, arbitrary amount of time to test it manually.
timeout, _ := req.Options["lock-time"].(int)
defer time.Sleep(time.Duration(timeout) * time.Second)

offset, _ := req.Options[filesOffsetOptionName].(int64)
if offset < 0 {
return fmt.Errorf("cannot have negative write offset")
}

if mkParents {
err := ensureContainingDirectoryExists(nd.FilesRoot, path, prefix)
err := ensureContainingDirectoryExists(filesRoot, path, prefix)
if err != nil {
return err
}
}

fi, err := getFileHandle(nd.FilesRoot, path, create, prefix)
fi, err := getFileHandle(filesRoot, path, create, prefix)
if err != nil {
return err
}
Expand Down
1 change: 1 addition & 0 deletions core/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ type IpfsNode struct {
Reporter *metrics.BandwidthCounter `optional:"true"`
Discovery mdns.Service `optional:"true"`
FilesRoot *mfs.Root
LockedFilesRoot *node.LockedFilesRoot
RecordValidator record.Validator

// Online
Expand Down
8 changes: 6 additions & 2 deletions core/corerepo/gc.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,9 @@ func BestEffortRoots(filesRoot *mfs.Root) ([]cid.Cid, error) {
}

func GarbageCollect(n *core.IpfsNode, ctx context.Context) error {
roots, err := BestEffortRoots(n.FilesRoot)
filesRoot := n.LockedFilesRoot.LockRoot()
defer n.LockedFilesRoot.UnlockRoot()
roots, err := BestEffortRoots(filesRoot)
if err != nil {
return err
}
Expand Down Expand Up @@ -148,7 +150,9 @@ func (e *MultiError) Error() string {
}

func GarbageCollectAsync(n *core.IpfsNode, ctx context.Context) <-chan gc.Result {
roots, err := BestEffortRoots(n.FilesRoot)
filesRoot := n.LockedFilesRoot.LockRoot()
defer n.LockedFilesRoot.UnlockRoot()
roots, err := BestEffortRoots(filesRoot)
if err != nil {
out := make(chan gc.Result)
out <- gc.Result{Error: err}
Expand Down
22 changes: 22 additions & 0 deletions core/node/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package node
import (
"context"
"fmt"
"sync"

"github.com/ipfs/go-blockservice"
"github.com/ipfs/go-cid"
Expand Down Expand Up @@ -168,3 +169,24 @@ func Files(mctx helpers.MetricsCtx, lc fx.Lifecycle, repo repo.Repo, dag format.

return root, err
}

func LockedFiles(mctx helpers.MetricsCtx, lc fx.Lifecycle, root *mfs.Root) (*LockedFilesRoot, error) {
return &LockedFilesRoot{
root: root,
lock: &sync.Mutex{},
}, nil
}

type LockedFilesRoot struct {
root *mfs.Root
lock *sync.Mutex
}

func (lfr *LockedFilesRoot) LockRoot() *mfs.Root {
lfr.lock.Lock()
return lfr.root
}

func (lfr *LockedFilesRoot) UnlockRoot() {
lfr.lock.Unlock()
}
1 change: 1 addition & 0 deletions core/node/groups.go
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,7 @@ var Core = fx.Options(
fx.Provide(FetcherConfig),
fx.Provide(Pinning),
fx.Provide(Files),
fx.Provide(LockedFiles),
)

func Networked(bcfg *BuildCfg, cfg *config.Config) fx.Option {
Expand Down
13 changes: 13 additions & 0 deletions test-mfs-lock.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
set -x
set -v

# The daemon needs to be running, otherwise the commands will compete on their
# lock of the entire repo (not the MFS root) and fail.
ipfs swarm addrs > /dev/null || (echo "daemon not running" && exit 1)

ipfs --version
ipfs files mkdir /test-lock/
ipfs files rm /test-lock/ -r
((echo "content" | ./cmd/ipfs/ipfs files write --create --parents --truncate --lock-time 3 /test-lock/file) && echo "ipfs write lock released" &)
ipfs repo gc
# FIXME: This is a flaky test just to manually check the lock in ipfs write is blocking the GC.

0 comments on commit 3939682

Please sign in to comment.