Add p9.OpenTruncate.

This is required to implement O_TRUNC correctly on filesystems backed by
gofers.

9P2000.L: "lopen prepares fid for file I/O. flags contains Linux open(2) flags
bits, e.g. O_RDONLY, O_RDWR, O_WRONLY."

open(2): "The argument flags must include one of the following access modes:
O_RDONLY, O_WRONLY, or O_RDWR. ... In addition, zero or more file creation
flags and file status flags can be bitwise-or'd in flags."

The reference 9P2000.L implementation also appears to expect arbitrary flags,
not just access modes, in Tlopen.flags:
https://github.com/chaos/diod/blob/master/diod/ops.c#L703

PiperOrigin-RevId: 278972683
This commit is contained in:
Jamie Liu
2019-11-06 17:11:58 -08:00
committed by gVisor bot
parent e63db5e7bb
commit f8ffadddb3
3 changed files with 32 additions and 20 deletions
+1 -1
View File
@@ -116,7 +116,7 @@ type File interface {
// N.B. The server must resolve any lazy paths when open is called.
// After this point, read and write may be called on files with no
// deletion check, so resolving in the data path is not viable.
Open(mode OpenFlags) (*fd.FD, QID, uint32, error)
Open(flags OpenFlags) (*fd.FD, QID, uint32, error)
// Read reads from this file. Open must be called first.
//
+24 -13
View File
@@ -32,18 +32,22 @@ import (
type OpenFlags uint32
const (
// ReadOnly is a Topen and Tcreate flag indicating read-only mode.
// ReadOnly is a Tlopen and Tlcreate flag indicating read-only mode.
ReadOnly OpenFlags = 0
// WriteOnly is a Topen and Tcreate flag indicating write-only mode.
// WriteOnly is a Tlopen and Tlcreate flag indicating write-only mode.
WriteOnly OpenFlags = 1
// ReadWrite is a Topen flag indicates read-write mode.
// ReadWrite is a Tlopen flag indicates read-write mode.
ReadWrite OpenFlags = 2
// OpenFlagsModeMask is a mask of valid OpenFlags mode bits.
OpenFlagsModeMask OpenFlags = 3
// OpenTruncate is a Tlopen flag indicating that the opened file should be
// truncated.
OpenTruncate OpenFlags = 01000
// OpenFlagsIgnoreMask is a list of OpenFlags mode bits that are ignored for Tlopen.
// Note that syscall.O_LARGEFILE is set to zero, use value from Linux fcntl.h.
OpenFlagsIgnoreMask OpenFlags = syscall.O_DIRECTORY | syscall.O_NOATIME | 0100000
@@ -71,25 +75,32 @@ const (
// OSFlags converts a p9.OpenFlags to an int compatible with open(2).
func (o OpenFlags) OSFlags() int {
return int(o & OpenFlagsModeMask)
// "flags contains Linux open(2) flags bits" - 9P2000.L
return int(o)
}
// String implements fmt.Stringer.
func (o OpenFlags) String() string {
switch o {
var buf strings.Builder
switch mode := o & OpenFlagsModeMask; mode {
case ReadOnly:
return "ReadOnly"
buf.WriteString("ReadOnly")
case WriteOnly:
return "WriteOnly"
buf.WriteString("WriteOnly")
case ReadWrite:
return "ReadWrite"
case OpenFlagsModeMask:
return "OpenFlagsModeMask"
case OpenFlagsIgnoreMask:
return "OpenFlagsIgnoreMask"
buf.WriteString("ReadWrite")
default:
return "UNDEFINED"
fmt.Fprintf(&buf, "%#o", mode)
}
otherFlags := o &^ OpenFlagsModeMask
if otherFlags&OpenTruncate != 0 {
buf.WriteString("|OpenTruncate")
otherFlags &^= OpenTruncate
}
if otherFlags != 0 {
fmt.Fprintf(&buf, "|%#o", otherFlags)
}
return buf.String()
}
// Tag is a message tag.
+7 -6
View File
@@ -366,23 +366,24 @@ func fchown(fd int, uid p9.UID, gid p9.GID) error {
}
// Open implements p9.File.
func (l *localFile) Open(mode p9.OpenFlags) (*fd.FD, p9.QID, uint32, error) {
func (l *localFile) Open(flags p9.OpenFlags) (*fd.FD, p9.QID, uint32, error) {
if l.isOpen() {
panic(fmt.Sprintf("attempting to open already opened file: %q", l.hostPath))
}
// Check if control file can be used or if a new open must be created.
var newFile *fd.FD
if mode == p9.ReadOnly {
log.Debugf("Open reusing control file, mode: %v, %q", mode, l.hostPath)
if flags == p9.ReadOnly {
log.Debugf("Open reusing control file, flags: %v, %q", flags, l.hostPath)
newFile = l.file
} else {
// Ideally reopen would call name_to_handle_at (with empty name) and
// open_by_handle_at to reopen the file without using 'hostPath'. However,
// name_to_handle_at and open_by_handle_at aren't supported by overlay2.
log.Debugf("Open reopening file, mode: %v, %q", mode, l.hostPath)
log.Debugf("Open reopening file, flags: %v, %q", flags, l.hostPath)
var err error
newFile, err = reopenProcFd(l.file, openFlags|mode.OSFlags())
// Constrain open flags to the open mode and O_TRUNC.
newFile, err = reopenProcFd(l.file, openFlags|(flags.OSFlags()&(syscall.O_ACCMODE|syscall.O_TRUNC)))
if err != nil {
return nil, p9.QID{}, 0, extractErrno(err)
}
@@ -409,7 +410,7 @@ func (l *localFile) Open(mode p9.OpenFlags) (*fd.FD, p9.QID, uint32, error) {
}
l.file = newFile
}
l.mode = mode
l.mode = flags & p9.OpenFlagsModeMask
return fd, l.attachPoint.makeQID(stat), 0, nil
}