summaryrefslogtreecommitdiff
path: root/internal/fusefrontend/write_lock.go
diff options
context:
space:
mode:
authorJakob Unterwurzacher2016-02-06 19:27:59 +0100
committerJakob Unterwurzacher2016-02-06 19:27:59 +0100
commit9078a77850dd680bfa938d9ed7c83600a60c0e7b (patch)
tree03ee83879c398307d450002e1f07e928cb743672 /internal/fusefrontend/write_lock.go
parent2b8cbd944149afe51fadddbd67ee4499d1d86250 (diff)
Move pathfs_frontend to internal/fusefrontend
"git status" for reference: renamed: pathfs_frontend/args.go -> internal/fusefrontend/args.go renamed: pathfs_frontend/compat_darwin.go -> internal/fusefrontend/compat_darwin.go renamed: pathfs_frontend/compat_linux.go -> internal/fusefrontend/compat_linux.go renamed: pathfs_frontend/file.go -> internal/fusefrontend/file.go renamed: pathfs_frontend/file_holes.go -> internal/fusefrontend/file_holes.go renamed: pathfs_frontend/fs.go -> internal/fusefrontend/fs.go renamed: pathfs_frontend/fs_dir.go -> internal/fusefrontend/fs_dir.go renamed: pathfs_frontend/names.go -> internal/fusefrontend/names.go renamed: pathfs_frontend/write_lock.go -> internal/fusefrontend/write_lock.go modified: main.go
Diffstat (limited to 'internal/fusefrontend/write_lock.go')
-rw-r--r--internal/fusefrontend/write_lock.go66
1 files changed, 66 insertions, 0 deletions
diff --git a/internal/fusefrontend/write_lock.go b/internal/fusefrontend/write_lock.go
new file mode 100644
index 0000000..a8ec6b6
--- /dev/null
+++ b/internal/fusefrontend/write_lock.go
@@ -0,0 +1,66 @@
+package fusefrontend
+
+import (
+ "sync"
+)
+
+func init() {
+ wlock.m = make(map[uint64]*refCntMutex)
+}
+
+// wlock - serializes write accesses to each file (identified by inode number)
+// Writing partial blocks means we have to do read-modify-write cycles. We
+// really don't want concurrent writes there.
+// Concurrent full-block writes could actually be allowed, but are not to
+// keep the locking simple.
+var wlock wlockMap
+
+// wlockMap - usage:
+// 1) register
+// 2) lock ... unlock ...
+// 3) unregister
+type wlockMap struct {
+ mapMutex sync.RWMutex
+ m map[uint64]*refCntMutex
+}
+
+func (w *wlockMap) register(ino uint64) {
+ w.mapMutex.Lock()
+ r := w.m[ino]
+ if r == nil {
+ r = &refCntMutex{}
+ w.m[ino] = r
+ }
+ r.refCnt++ // this must happen inside the mapMutex lock
+ w.mapMutex.Unlock()
+}
+
+func (w *wlockMap) unregister(ino uint64) {
+ w.mapMutex.Lock()
+ r := w.m[ino]
+ r.refCnt--
+ if r.refCnt == 0 {
+ delete(w.m, ino)
+ }
+ w.mapMutex.Unlock()
+}
+
+func (w *wlockMap) lock(ino uint64) {
+ w.mapMutex.RLock()
+ r := w.m[ino]
+ w.mapMutex.RUnlock()
+ r.Lock() // this can take a long time - execute outside the mapMutex lock
+}
+
+func (w *wlockMap) unlock(ino uint64) {
+ w.mapMutex.RLock()
+ r := w.m[ino]
+ w.mapMutex.RUnlock()
+ r.Unlock()
+}
+
+// refCntMutex - mutex with reference count
+type refCntMutex struct {
+ sync.Mutex
+ refCnt int
+}