diff options
Diffstat (limited to 'pkg/p9')
-rw-r--r-- | pkg/p9/client.go | 23 | ||||
-rw-r--r-- | pkg/p9/file.go | 2 | ||||
-rw-r--r-- | pkg/p9/p9.go | 39 | ||||
-rw-r--r-- | pkg/p9/server.go | 8 | ||||
-rw-r--r-- | pkg/p9/transport_flipcall.go | 24 |
5 files changed, 54 insertions, 42 deletions
diff --git a/pkg/p9/client.go b/pkg/p9/client.go index 2412aa5e1..221516c6c 100644 --- a/pkg/p9/client.go +++ b/pkg/p9/client.go @@ -505,12 +505,27 @@ func (c *Client) sendRecvChannel(t message, r message) error { ch.active = false c.channelsMu.Unlock() c.channelsWg.Done() - return err + // Map all transport errors to EIO, but ensure that the real error + // is logged. + log.Warningf("p9.Client.sendRecvChannel: flipcall.Endpoint.Connect: %v", err) + return syscall.EIO } } - // Send the message. - err := ch.sendRecv(c, t, r) + // Send the request and receive the server's response. + rsz, err := ch.send(t) + if err != nil { + // See above. + c.channelsMu.Lock() + ch.active = false + c.channelsMu.Unlock() + c.channelsWg.Done() + log.Warningf("p9.Client.sendRecvChannel: p9.channel.send: %v", err) + return syscall.EIO + } + + // Parse the server's response. + _, retErr := ch.recv(r, rsz) // Release the channel. c.channelsMu.Lock() @@ -523,7 +538,7 @@ func (c *Client) sendRecvChannel(t message, r message) error { c.channelsMu.Unlock() c.channelsWg.Done() - return err + return retErr } // Version returns the negotiated 9P2000.L.Google version number. diff --git a/pkg/p9/file.go b/pkg/p9/file.go index 907445e15..96d1f2a8e 100644 --- a/pkg/p9/file.go +++ b/pkg/p9/file.go @@ -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. // diff --git a/pkg/p9/p9.go b/pkg/p9/p9.go index 25530adca..415200d60 100644 --- a/pkg/p9/p9.go +++ b/pkg/p9/p9.go @@ -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. @@ -814,7 +825,7 @@ func StatToAttr(s *syscall.Stat_t, req AttrMask) (Attr, AttrMask) { attr.Mode = FileMode(s.Mode) } if req.NLink { - attr.NLink = s.Nlink + attr.NLink = uint64(s.Nlink) } if req.UID { attr.UID = UID(s.Uid) diff --git a/pkg/p9/server.go b/pkg/p9/server.go index 69c886a5d..40b8fa023 100644 --- a/pkg/p9/server.go +++ b/pkg/p9/server.go @@ -452,7 +452,13 @@ func (cs *connState) initializeChannels() (err error) { cs.channelWg.Add(1) go func() { // S/R-SAFE: Server side. defer cs.channelWg.Done() - res.service(cs) + if err := res.service(cs); err != nil { + // Don't log flipcall.ShutdownErrors, which we expect to be + // returned during server shutdown. + if _, ok := err.(flipcall.ShutdownError); !ok { + log.Warningf("p9.channel.service: %v", err) + } + } }() } diff --git a/pkg/p9/transport_flipcall.go b/pkg/p9/transport_flipcall.go index 7cdf4ecc3..233f825e3 100644 --- a/pkg/p9/transport_flipcall.go +++ b/pkg/p9/transport_flipcall.go @@ -132,7 +132,7 @@ func (ch *channel) send(m message) (uint32, error) { if filer, ok := m.(filer); ok { if f := filer.FilePayload(); f != nil { if err := ch.fds.SendFD(f.FD()); err != nil { - return 0, syscall.EIO // Map everything to EIO. + return 0, err } f.Close() // Per sendRecvLegacy. sentFD = true // To mark below. @@ -162,15 +162,7 @@ func (ch *channel) send(m message) (uint32, error) { } // Perform the one-shot communication. - n, err := ch.data.SendRecv(ssz) - if err != nil { - if n > 0 { - return n, nil - } - return 0, syscall.EIO // See above. - } - - return n, nil + return ch.data.SendRecv(ssz) } // recv decodes a message that exists on the channel. @@ -249,15 +241,3 @@ func (ch *channel) recv(r message, rsz uint32) (message, error) { return r, nil } - -// sendRecv sends the given message over the channel. -// -// This is used by the client. -func (ch *channel) sendRecv(c *Client, m, r message) error { - rsz, err := ch.send(m) - if err != nil { - return err - } - _, err = ch.recv(r, rsz) - return err -} |