...

Source file src/github.com/Microsoft/hcsshim/internal/guest/storage/plan9/plan9.go

Documentation: github.com/Microsoft/hcsshim/internal/guest/storage/plan9

     1  //go:build linux
     2  // +build linux
     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  // Test dependencies.
    22  var (
    23  	osMkdirAll  = os.MkdirAll
    24  	osRemoveAll = os.RemoveAll
    25  	unixMount   = unix.Mount
    26  )
    27  
    28  // Mount dials a connection from `vsock` and mounts a Plan9 share to `target`.
    29  //
    30  // `target` will be created. On mount failure the created `target` will be
    31  // automatically cleaned up.
    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  	// set socket options to maximize bandwidth
    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