1
2
3
4 package plan9
5
6 import (
7 "context"
8 "fmt"
9 "os"
10 "syscall"
11
12 "github.com/Microsoft/hcsshim/internal/guest/transport"
13 "github.com/Microsoft/hcsshim/internal/oc"
14 "github.com/pkg/errors"
15 "go.opencensus.io/trace"
16 "golang.org/x/sys/unix"
17 )
18
19 const packetPayloadBytes = 65536
20
21
22 var (
23 osMkdirAll = os.MkdirAll
24 osRemoveAll = os.RemoveAll
25 unixMount = unix.Mount
26 )
27
28
29
30
31
32 func Mount(ctx context.Context, vsock transport.Transport, target, share string, port uint32, readonly bool) (err error) {
33 _, span := oc.StartSpan(ctx, "plan9::Mount")
34 defer span.End()
35 defer func() { oc.SetSpanStatus(span, err) }()
36
37 span.AddAttributes(
38 trace.StringAttribute("target", target),
39 trace.StringAttribute("share", share),
40 trace.Int64Attribute("port", int64(port)),
41 trace.BoolAttribute("readonly", readonly))
42
43 if err := osMkdirAll(target, 0700); err != nil {
44 return err
45 }
46 defer func() {
47 if err != nil {
48 _ = osRemoveAll(target)
49 }
50 }()
51 conn, err := vsock.Dial(port)
52 if err != nil {
53 return errors.Wrapf(err, "could not connect to plan9 server for %s", target)
54 }
55 f, err := conn.File()
56 conn.Close()
57 if err != nil {
58 return errors.Wrapf(err, "could not get file for plan9 connection for %s", target)
59 }
60 defer f.Close()
61
62 var mountOptions uintptr
63 data := fmt.Sprintf("trans=fd,rfdno=%d,wfdno=%d,msize=%d", f.Fd(), f.Fd(), packetPayloadBytes)
64 if readonly {
65 mountOptions |= unix.MS_RDONLY
66 data += ",noload"
67 }
68 if share != "" {
69 data += ",aname=" + share
70 }
71
72
73 err = syscall.SetsockoptInt(int(f.Fd()), syscall.SOL_SOCKET, syscall.SO_RCVBUF, packetPayloadBytes)
74 if err != nil {
75 return errors.Wrapf(err, "failed to set sock option syscall.SO_RCVBUF to %v on fd %v", packetPayloadBytes, f.Fd())
76 }
77 err = syscall.SetsockoptInt(int(f.Fd()), syscall.SOL_SOCKET, syscall.SO_SNDBUF, packetPayloadBytes)
78 if err != nil {
79 return errors.Wrapf(err, "failed to set sock option syscall.SO_SNDBUF to %v on fd %v", packetPayloadBytes, f.Fd())
80 }
81 if err := unixMount(target, target, "9p", mountOptions, data); err != nil {
82 return errors.Wrapf(err, "failed to mount directory for mapped directory %s", target)
83 }
84 return nil
85 }
86
View as plain text