Skip to content

Commit daf4258

Browse files
committed
fix: Fix race conditions
1 parent eb90f17 commit daf4258

File tree

16 files changed

+134
-44
lines changed

16 files changed

+134
-44
lines changed

.github/workflows/cluster_test.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,4 @@ jobs:
2121

2222
- name: Run cluster tests
2323
run: NUM_ITER=100 SAME_PROCESS_MOUNT=1 make run-cluster-test
24-
timeout-minutes: 20
24+
timeout-minutes: 25

.github/workflows/test.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,3 @@ jobs:
1818

1919
- name: Run tests
2020
run: SAME_PROCESS_MOUNT=1 make run-test
21-
timeout-minutes: 12

README.md

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,35 @@ In first release we worked on improving reliability of the code base:
2626

2727
## Prebuilt DEB and RPM packages
2828

29-
* Download package from latest release: [DEB](https://github.com/tigrisdata/tigrisfs/releases/latest/download/tigrisfs-linux-amd64.deb), [RPM](https://github.com/tigrisdata/tigrisfs/releases/latest/download/tigrisfs-linux-amd64.rpm).
30-
* Install it with `dpkg -i tigrisfs-linux-amd64.deb` or `rpm -i tigrisfs-linux-amd64.rpm`.
31-
* TigrisFS can use standard AWS credentials file and environment variables. They will be picked up automatically if you have them configured.
32-
Alternatively, you can configure AWS credentials in `/etc/tigrisfs/defaults
33-
* Now you can mount your S3 bucket with `systemctl --user start tigrisfs@<bucket>`.
34-
* The mount will be available at `$HOME/mnt/tigrisfs/<bucket>`.
35-
29+
* Download the latest release: [DEB](https://github.com/tigrisdata/tigrisfs/releases/latest/download/tigrisfs-linux-amd64.deb), [RPM](https://github.com/tigrisdata/tigrisfs/releases/latest/download/tigrisfs-linux-amd64.rpm).
30+
* Install the package:
31+
* Debian-based systems:
32+
```bash
33+
dpkg -i tigrisfs-linux-amd64.deb
34+
```
35+
* RPM-based systems:
36+
```bash
37+
rpm -i tigrisfs-linux-amd64.rpm
38+
```
39+
* Configure credentials
40+
TigrisFS can use credentials from different sources:
41+
* Standard AWS credentials files `~/.aws/credentials` and `~/.aws/config`. Use `aws configure` to set them up and export
42+
`AWS_PROFILE` environment variable to use a specific profile.
43+
* Environment variables `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`.
44+
* TigrisFS credentials in `/etc/default/tigrisfs` or mount specific credentials in `/etc/default/tigrisfs-<bucket>`.
45+
46+
* Mount the bucket
47+
* as current user
48+
```bash
49+
systemctl --user start tigrisfs@<bucket>
50+
```
51+
The bucket is mounted at `$HOME/mnt/tigrisfs/<bucket>`.
52+
* as root
53+
```bash
54+
systemctl start tigrisfs@<bucket>
55+
```
56+
The bucket is mounted at `/mnt/tigrisfs/<bucket>`.
57+
3658
# License
3759

3860
Licensed under the Apache License, Version 2.0

core/cluster_fs.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -488,10 +488,12 @@ func (fs *ClusterFs) lookUpInode1(parent *Inode, name string) (
488488
return nil, 0, nil, err
489489
}
490490

491+
parent.DowngradeToKeepOwnerLock()
492+
493+
child.KeepOwnerLock()
491494
pbInode := child.pbInode()
492495
inodeId := uint64(child.Id)
493-
494-
parent.DowngradeToKeepOwnerLock()
496+
child.KeepOwnerUnlock()
495497

496498
return pbInode, inodeId, pbAttr, nil
497499
}

core/dir.go

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1864,10 +1864,12 @@ func (parent *Inode) insertSubTree(path string, obj *BlobItemOutput, dirs map[*I
18641864
inode.SetFromBlobItem(obj)
18651865
sealPastDirs(dirs, inode)
18661866
} else {
1867+
inode.mu.Lock()
18671868
now := time.Now()
18681869
if inode.AttrTime.Before(now) {
18691870
inode.SetAttrTime(now)
18701871
}
1872+
inode.mu.Unlock()
18711873
}
18721874

18731875
// mark this dir but don't seal anything else
@@ -1905,9 +1907,29 @@ func (parent *Inode) LookUpCached(name string) (inode *Inode, err error) {
19051907
parent.mu.Lock()
19061908
ok := false
19071909
inode = parent.findChildUnlocked(name)
1910+
if inode == nil {
1911+
ok = false
1912+
if parent.dir.DeletedChildren != nil {
1913+
if _, ok := parent.dir.DeletedChildren[name]; ok {
1914+
// File is deleted locally
1915+
parent.mu.Unlock()
1916+
return nil, syscall.ENOENT
1917+
}
1918+
}
1919+
if !expired(parent.dir.DirTime, parent.fs.flags.StatCacheTTL) {
1920+
// Don't recheck from the server if directory cache is actual
1921+
parent.mu.Unlock()
1922+
return nil, syscall.ENOENT
1923+
}
1924+
}
1925+
1926+
ttl := parent.fs.flags.StatCacheTTL
1927+
parent.mu.Unlock()
1928+
19081929
if inode != nil {
1930+
inode.mu.Lock()
19091931
ok = true
1910-
if expired(inode.AttrTime, parent.fs.flags.StatCacheTTL) {
1932+
if expired(inode.AttrTime, ttl) {
19111933
ok = false
19121934
if atomic.LoadInt32(&inode.CacheState) != ST_CACHED ||
19131935
inode.isDir() && atomic.LoadInt64(&inode.dir.ModifiedChildren) > 0 {
@@ -1921,22 +1943,9 @@ func (parent *Inode) LookUpCached(name string) (inode *Inode, err error) {
19211943
inode.logFuse("lookup expired")
19221944
}
19231945
}
1924-
} else {
1925-
ok = false
1926-
if parent.dir.DeletedChildren != nil {
1927-
if _, ok := parent.dir.DeletedChildren[name]; ok {
1928-
// File is deleted locally
1929-
parent.mu.Unlock()
1930-
return nil, syscall.ENOENT
1931-
}
1932-
}
1933-
if !expired(parent.dir.DirTime, parent.fs.flags.StatCacheTTL) {
1934-
// Don't recheck from the server if directory cache is actual
1935-
parent.mu.Unlock()
1936-
return nil, syscall.ENOENT
1937-
}
1946+
inode.mu.Unlock()
19381947
}
1939-
parent.mu.Unlock()
1948+
19401949
if !ok {
19411950
inode, err = parent.recheckInode(inode, name)
19421951
err = mapAwsError(err)
@@ -1947,6 +1956,7 @@ func (parent *Inode) LookUpCached(name string) (inode *Inode, err error) {
19471956
return nil, syscall.ENOENT
19481957
}
19491958
}
1959+
19501960
return inode, nil
19511961
}
19521962

core/file.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -638,15 +638,17 @@ func (inode *Inode) recordFlushError(err error) {
638638

639639
func (inode *Inode) TryFlush(priority int) bool {
640640
overDeleted := false
641+
inode.mu.Lock()
641642
parent := inode.Parent
642643
if parent != nil {
644+
inode.mu.Unlock()
643645
parent.mu.Lock()
644646
if parent.dir.DeletedChildren != nil {
645647
_, overDeleted = parent.dir.DeletedChildren[inode.Name]
646648
}
647649
parent.mu.Unlock()
650+
inode.mu.Lock()
648651
}
649-
inode.mu.Lock()
650652
defer inode.mu.Unlock()
651653
if inode.Parent != parent {
652654
return false

core/tigris_test.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,17 @@ import (
2929
"github.com/tigrisdata/tigrisfs/core/cfg"
3030
)
3131

32+
var (
33+
triedDetect bool
34+
detected bool
35+
localTigris bool
36+
)
37+
3238
func tigrisDetected(flags *cfg.FlagStorage) (bool, bool) {
39+
if triedDetect {
40+
return detected, localTigris
41+
}
42+
3343
endpoint := flags.Endpoint
3444
if endpoint == "" {
3545
endpoint = os.Getenv("AWS_ENDPOINT_URL")
@@ -42,7 +52,11 @@ func tigrisDetected(flags *cfg.FlagStorage) (bool, bool) {
4252
return false, local
4353
}
4454

45-
return strings.Contains(r.Header.Get("Server"), "Tigris"), local
55+
triedDetect = true
56+
localTigris = local
57+
detected = r.StatusCode == http.StatusOK && strings.Contains(r.Header.Get("Server"), "Tigris")
58+
59+
return detected, local
4660
}
4761

4862
func LocalTigrisDetected(flags *cfg.FlagStorage) bool {

log/logger.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ import (
3232
)
3333

3434
var DefaultLogConfig = &LogConfig{
35-
Level: "info",
35+
Level: "info",
36+
Format: "console",
37+
Color: false,
3638
}
3739

3840
var (

pkg/defaults

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,7 @@
77

88
# Alternatively set name of the profile to read from AWS standard
99
# location ~/.aws/config
10-
#AWS_PROFILE=
10+
#AWS_PROFILE=
11+
12+
# Mount options
13+
#OPTS="-o allow_other,uid=1000,gid=1000,umask=0002"

pkg/[email protected]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ EnvironmentFile=-/etc/default/tigrisfs-%i
88
#Environment=MOUNT_PREFIX=%h
99
Type=oneshot
1010
ExecStartPre=/bin/mkdir -p ${MOUNT_PREFIX}/mnt/tigris/%i
11-
ExecStart=/usr/bin/mount -t fuse.tigrisfs %i ${MOUNT_PREFIX}/mnt/tigris/%i
11+
ExecStart=/usr/bin/mount ${OPTS} -t fuse.tigrisfs %i ${MOUNT_PREFIX}/mnt/tigris/%i
1212
ExecStop=/usr/bin/umount ${MOUNT_PREFIX}/mnt/tigris/%i
1313
RemainAfterExit=yes
1414

0 commit comments

Comments
 (0)