Skip to content

Commit

Permalink
minor refactor, support for inherit handle, update access mask
Browse files Browse the repository at this point in the history
Signed-off-by: Maksim An <maksiman@microsoft.com>
  • Loading branch information
anmaxvl committed Aug 13, 2024
1 parent eda0446 commit d56b819
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 97 deletions.
62 changes: 7 additions & 55 deletions internal/computecore/operation.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ import (
"syscall"
"time"

"github.com/Microsoft/hcsshim/internal/jobobject"

hcsschema "github.com/Microsoft/hcsshim/internal/hcs/schema2"
"github.com/Microsoft/hcsshim/internal/log"
"github.com/Microsoft/hcsshim/internal/oc"
Expand Down Expand Up @@ -73,35 +71,7 @@ const (

type HCSOperationOpt func(ctx context.Context, op HCSOperation) error

type CreateOperationOptions struct {
JobResources []HCSJobResource
}

func HcsCreateOperation(ctx context.Context, hcsContext uintptr, callback hcsOperationCompletionUintptr, options *CreateOperationOptions) (op HCSOperation, err error) {
op, err = createOperation(ctx, hcsContext, callback)
if err != nil {
return 0, err
}

if options != nil {
if len(options.JobResources) > 0 {
for _, jr := range options.JobResources {
if err := op.addJobResource(ctx, jr); err != nil {
log.G(ctx).WithError(err).Debug("failed to add job to resource")
return 0, err
}
}
}
}

return op, nil
}

func HcsCreateEmptyOperation(ctx context.Context) (op HCSOperation, err error) {
return HcsCreateOperation(ctx, 0, 0, nil)
}

func createOperation(ctx context.Context, hcsContext uintptr, callback hcsOperationCompletionUintptr) (op HCSOperation, err error) {
func HcsCreateOperation(ctx context.Context, hcsContext uintptr, callback hcsOperationCompletionUintptr) (op HCSOperation, err error) {
_, span := oc.StartSpan(ctx, "computecore::HcsCreateOperation", oc.WithClientSpanKind)
defer func() {
span.AddAttributes(trace.StringAttribute("operation", op.String()))
Expand All @@ -115,6 +85,10 @@ func createOperation(ctx context.Context, hcsContext uintptr, callback hcsOperat
return hcsCreateOperation(hcsContext, callback)
}

func HcsCreateEmptyOperation(ctx context.Context) (op HCSOperation, err error) {
return HcsCreateOperation(ctx, 0, 0)
}

// HRESULT WINAPI
// HcsAddResourceToOperation(
// _In_ HCS_OPERATION Operation,
Expand All @@ -124,28 +98,7 @@ func createOperation(ctx context.Context, hcsContext uintptr, callback hcsOperat
// )
//sys hcsAddResourceToOperation(operation HCSOperation, rtype uint32, uri string, handle syscall.Handle) (hr error) = computecore.HcsAddResourceToOperation?

func (op HCSOperation) addJobResource(ctx context.Context, jr HCSJobResource) (err error) {
jobOpts := jobobject.Options{
Name: jr.Name,
}
log.G(ctx).WithField("jobName", jr.Name).Debug("opening job object")
job, err := jobobject.Open(ctx, &jobOpts)
if err != nil {
return err
}
defer func() {
log.G(ctx).WithField("jobName", jr.Name).Debug("closing job object")
if err := job.Close(); err != nil {
log.G(ctx).WithError(err).Error("failed to close job object")
}
}()

rHandle := job.Handle()

return op.addResource(ctx, ResourceTypeJob, jr.Uri, syscall.Handle(rHandle))
}

func (op HCSOperation) addResource(ctx context.Context, rtype HCSResourceType, uri HCSResourceUri, handle syscall.Handle) (err error) {
func AddResourceToOperation(ctx context.Context, op HCSOperation, rtype HCSResourceType, uri HCSResourceUri, handle windows.Handle) (err error) {
_, span := oc.StartSpan(ctx, "computecore::HcsAddResourceToOperation", oc.WithClientSpanKind)
defer func() {
span.AddAttributes(trace.StringAttribute("operation", op.String()))
Expand All @@ -156,8 +109,7 @@ func (op HCSOperation) addResource(ctx context.Context, rtype HCSResourceType, u
trace.Int64Attribute("rtype", int64(rtype)),
trace.StringAttribute("uri", string(uri)),
)

return hcsAddResourceToOperation(op, uint32(rtype), string(uri), handle)
return hcsAddResourceToOperation(op, uint32(rtype), string(uri), syscall.Handle(handle))
}

// void WINAPI
Expand Down
21 changes: 1 addition & 20 deletions internal/computecore/resource_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,5 @@ type HCSResourceUri string

const (
HCSMemoryJobUri = HCSResourceUri("hcs:/VirtualMachine/VmmemJob")
HCSCpuJobUri = HCSResourceUri("hcs:/VirtualMachine/WorkerJob")
HCSWorkerJobUri = HCSResourceUri("hcs:/VirtualMachine/WorkerJob")
)

type HCSJobResource struct {
Name string
Uri HCSResourceUri
}

func NewMemoryPoolResource(name string) HCSJobResource {
return HCSJobResource{
Name: name,
Uri: HCSMemoryJobUri,
}
}

func NewCPUPoolResource(name string) HCSJobResource {
return HCSJobResource{
Name: name,
Uri: HCSCpuJobUri,
}
}
103 changes: 103 additions & 0 deletions internal/hcs/operation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package hcs

import (
"context"
"fmt"
"github.com/Microsoft/hcsshim/internal/computecore"
"github.com/Microsoft/hcsshim/internal/jobobject"
"github.com/Microsoft/hcsshim/internal/log"
"sync"
)

type Operation struct {
handle computecore.HCSOperation

mutex sync.RWMutex

operationType computecore.HCSOperationType
operationJobs []*jobobject.JobObject
}

type JobResource struct {
Name string
Uri computecore.HCSResourceUri
}
type CreateOperationOptions struct {
JobResources []JobResource
}

func CreateOperation(ctx context.Context) (*Operation, error) {
handle, err := computecore.HcsCreateEmptyOperation(ctx)
if err != nil {
return nil, err
}

op := &Operation{
handle: handle,
}

return op, nil
}

func (op *Operation) AddResource(ctx context.Context, resource JobResource) (err error) {
op.mutex.Lock()
defer op.mutex.Unlock()

jobOpts := jobobject.Options{
Name: resource.Name,
InheritHandle: true,
}

log.G(ctx).WithField("jobName", resource.Name).Debug("opening job object")
job, err := jobobject.Open(ctx, &jobOpts)
if err != nil {
return err
}

jobHandle := job.Handle()
defer func() {
if err != nil {
if cErr := job.Close(); cErr != nil {
log.G(ctx).WithError(cErr).Error("failed to close job object")
}
return
}
op.operationJobs = append(op.operationJobs, job)
}()

return computecore.AddResourceToOperation(ctx, op.handle, computecore.ResourceTypeJob, resource.Uri, jobHandle)
}

func (op *Operation) Close(ctx context.Context) error {
op.mutex.Lock()
defer op.mutex.Unlock()

for _, job := range op.operationJobs {
if err := job.Close(); err != nil {
log.G(ctx).WithError(err).Error("failed to close job object")
}
}
if err := op.handle.Close(); err != nil {
return fmt.Errorf("failed to close operation: %w", err)
}
op.handle = 0
return nil
}

func (op *Operation) Handle() computecore.HCSOperation {
return op.handle
}

func NewMemoryResource(name string) JobResource {
return JobResource{
Name: name,
Uri: computecore.HCSMemoryJobUri,
}
}

func NewCPUResource(name string) JobResource {
return JobResource{
Name: name,
Uri: computecore.HCSWorkerJobUri,
}
}
41 changes: 21 additions & 20 deletions internal/hcs/system.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,37 +83,38 @@ func CreateComputeSystem(ctx context.Context, id string, hcsDocumentInterface in

var (
//identity syscall.Handle
hcsOp computecore.HCSOperation
resultJSON string
createError error
operationOpts computecore.CreateOperationOptions
resultJSON string
createError error
)
hcsOperation, err := CreateOperation(ctx)
if err != nil {
return nil, err
}
defer func() {
if iErr := hcsOperation.Close(ctx); iErr != nil {
log.G(ctx).WithError(iErr).Error("failed to close HCS operation")
}
}()

if rpOptions != nil {
// If resource pool configuration isn't empty, we should be using HCS v2
// APIs for creating the compute system.
if rpOptions.MemoryPoolJobName != "" {
operationOpts.JobResources = append(operationOpts.JobResources,
computecore.NewMemoryPoolResource(rpOptions.MemoryPoolJobName))
if err := hcsOperation.AddResource(ctx, NewMemoryResource(rpOptions.MemoryPoolJobName)); err != nil {
return nil, err
}
}
if rpOptions.CPUPoolJobName != "" {
// FIXME (anmaxvl): Currently HCS is unable to find the CPU pool job for some reason. As a workaround, we
// assigning the worker process job to memory job object.
operationOpts.JobResources = append(operationOpts.JobResources,
computecore.NewCPUPoolResource(rpOptions.MemoryPoolJobName))
// FIXME (anmaxvl): Currently OpenJobObjectW is unable to find the worker job object. As a workarodun
// we pass the memory job instead.
if err := hcsOperation.AddResource(ctx, NewCPUResource(rpOptions.MemoryPoolJobName)); err != nil {
return nil, err
}
}
}
hcsOp, err = computecore.HcsCreateOperation(ctx, 0, 0, &operationOpts)
if err != nil {
return nil, err
}
defer func() {
if iErr := hcsOp.Close(); iErr != nil {
log.G(ctx).WithError(iErr).Error("failed to close HCS operation")
}
}()

//computeSystem.handle, resultJSON, createError = vmcompute.HcsCreateComputeSystem(ctx, id, hcsDocument, identity)
computeSystem.handleV2, resultJSON, createError = computecore.HcsCreateComputeSystem(ctx, id, hcsDocument, hcsOp, nil)
computeSystem.handleV2, resultJSON, createError = computecore.HcsCreateComputeSystem(ctx, id, hcsDocument, hcsOperation.Handle(), nil)
if createError == nil || IsPending(createError) {
computeSystem.handle = vmcompute.HcsSystem(computeSystem.handleV2)
defer func() {
Expand Down
10 changes: 8 additions & 2 deletions internal/jobobject/jobobject.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ type Options struct {
// `IOTracking` enables tracking I/O statistics on the job object. More specifically this
// calls SetInformationJobObject with the JobObjectIoAttribution class.
EnableIOTracking bool

InheritHandle bool
}

// Create creates a job object.
Expand Down Expand Up @@ -178,17 +180,21 @@ func Open(ctx context.Context, options *Options) (_ *JobObject, err error) {

var jobHandle windows.Handle
if options.UseNTVariant {
attributes := 0
if options.InheritHandle {
attributes = windows.OBJ_INHERIT
}
oa := winapi.ObjectAttributes{
Length: unsafe.Sizeof(winapi.ObjectAttributes{}),
ObjectName: unicodeJobName,
Attributes: 0,
Attributes: uintptr(attributes),
}
status := winapi.NtOpenJobObject(&jobHandle, winapi.JOB_OBJECT_ALL_ACCESS, &oa)
if status != 0 {
return nil, winapi.RtlNtStatusToDosError(status)
}
} else {
jobHandle, err = winapi.OpenJobObject(winapi.JOB_OBJECT_ALL_ACCESS, false, unicodeJobName.Buffer)
jobHandle, err = winapi.OpenJobObject(winapi.JOB_OBJECT_ALL_ACCESS, options.InheritHandle, unicodeJobName.Buffer)
if err != nil {
return nil, err
}
Expand Down

0 comments on commit d56b819

Please sign in to comment.