summaryrefslogtreecommitdiffhomepage
path: root/pkg/sentry/fs/inode.go
diff options
context:
space:
mode:
authorAndrei Vagin <avagin@google.com>2019-06-24 17:44:00 -0700
committergVisor bot <gvisor-bot@google.com>2019-06-24 17:45:02 -0700
commite9ea7230f7dc70d3e1bb5ae32b6927209cafb465 (patch)
tree2f8b5aacade58f48ad3f4748c5fe6875f2761f0b /pkg/sentry/fs/inode.go
parent7f5d0afe525af4728ed5ec75193e9e4560d9558c (diff)
fs: synchronize concurrent writes into files with O_APPEND
For files with O_APPEND, a file write operation gets a file size and uses it as offset to call an inode write operation. This means that all other operations which can change a file size should be blocked while the write operation doesn't complete. PiperOrigin-RevId: 254873771
Diffstat (limited to 'pkg/sentry/fs/inode.go')
-rw-r--r--pkg/sentry/fs/inode.go19
1 files changed, 19 insertions, 0 deletions
diff --git a/pkg/sentry/fs/inode.go b/pkg/sentry/fs/inode.go
index a889586aa..e4aae1135 100644
--- a/pkg/sentry/fs/inode.go
+++ b/pkg/sentry/fs/inode.go
@@ -15,6 +15,8 @@
package fs
import (
+ "sync"
+
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/metric"
@@ -55,6 +57,12 @@ type Inode struct {
// overlay is the overlay entry for this Inode.
overlay *overlayEntry
+
+ // appendMu is used to synchronize write operations into files which
+ // have been opened with O_APPEND. Operations which change a file size
+ // have to take this lock for read. Write operations to files with
+ // O_APPEND have to take this lock for write.
+ appendMu sync.RWMutex `state:"nosave"`
}
// LockCtx is an Inode's lock context and contains different personalities of locks; both
@@ -337,6 +345,8 @@ func (i *Inode) Truncate(ctx context.Context, d *Dirent, size int64) error {
if i.overlay != nil {
return overlayTruncate(ctx, i.overlay, d, size)
}
+ i.appendMu.RLock()
+ defer i.appendMu.RUnlock()
return i.InodeOperations.Truncate(ctx, i, size)
}
@@ -438,3 +448,12 @@ func (i *Inode) CheckCapability(ctx context.Context, cp linux.Capability) bool {
}
return creds.HasCapability(cp)
}
+
+func (i *Inode) lockAppendMu(appendMode bool) func() {
+ if appendMode {
+ i.appendMu.Lock()
+ return i.appendMu.Unlock
+ }
+ i.appendMu.RLock()
+ return i.appendMu.RUnlock
+}