@@ -58,7 +58,7 @@ type UpdateFn func(context.Context, []*ContainerUpdate) ([]*ContainerUpdate, err
5858
5959// Adaptation is the NRI abstraction for container runtime NRI adaptation/integration.
6060type Adaptation struct {
61- sync. Mutex
61+ locker locker
6262 name string
6363 version string
6464 dropinPath string
@@ -144,6 +144,16 @@ func WithDefaultValidator(cfg *validator.DefaultValidatorConfig) Option {
144144 }
145145}
146146
147+ // WithPodLocking enables the per-Pod locking strategy instead of the default global lock.
148+ // WARNING: This is ONLY safe if the consumer guarantees that no plugin
149+ // will ever request cross-Pod container updates in its responses.
150+ func WithPodLocking () Option {
151+ return func (r * Adaptation ) error {
152+ r .locker = newPodLocker ()
153+ return nil
154+ }
155+ }
156+
147157// New creates a new NRI Runtime.
148158func New (name , version string , syncFn SyncFn , updateFn UpdateFn , opts ... Option ) (* Adaptation , error ) {
149159 var err error
@@ -175,6 +185,7 @@ func New(name, version string, syncFn SyncFn, updateFn UpdateFn, opts ...Option)
175185 }
176186
177187 r := & Adaptation {
188+ locker : newGlobalLocker (),
178189 name : name ,
179190 version : version ,
180191 syncFn : syncFn ,
@@ -192,7 +203,7 @@ func New(name, version string, syncFn SyncFn, updateFn UpdateFn, opts ...Option)
192203 }
193204 }
194205
195- log .Infof (noCtx , "runtime interface created" )
206+ log .Infof (noCtx , "runtime interface created, using locker: %T" , r . locker )
196207
197208 return r , nil
198209}
@@ -201,8 +212,8 @@ func New(name, version string, syncFn SyncFn, updateFn UpdateFn, opts ...Option)
201212func (r * Adaptation ) Start () error {
202213 log .Infof (noCtx , "runtime interface starting up..." )
203214
204- r . Lock ()
205- defer r . Unlock ()
215+ unlock := r . locker . Lock (noCtx )
216+ defer unlock ()
206217
207218 if err := r .startPlugins (); err != nil {
208219 return err
@@ -219,8 +230,8 @@ func (r *Adaptation) Start() error {
219230func (r * Adaptation ) Stop () {
220231 log .Infof (noCtx , "runtime interface shutting down..." )
221232
222- r . Lock ()
223- defer r . Unlock ()
233+ unlock := r . locker . Lock (noCtx )
234+ defer unlock ()
224235
225236 r .stopListener ()
226237 r .stopPlugins ()
@@ -234,8 +245,9 @@ func (r *Adaptation) RunPodSandbox(ctx context.Context, evt *StateChangeEvent) e
234245
235246// UpdatePodSandbox relays the corresponding CRI request to plugins.
236247func (r * Adaptation ) UpdatePodSandbox (ctx context.Context , req * UpdatePodSandboxRequest ) (* UpdatePodSandboxResponse , error ) {
237- r .Lock ()
238- defer r .Unlock ()
248+ podUID := req .GetPod ().GetId ()
249+ unlock := r .locker .LockPod (ctx , podUID )
250+ defer unlock ()
239251 defer r .removeClosedPlugins ()
240252
241253 for _ , plugin := range r .plugins {
@@ -268,8 +280,9 @@ func (r *Adaptation) RemovePodSandbox(ctx context.Context, evt *StateChangeEvent
268280
269281// CreateContainer relays the corresponding CRI request to plugins.
270282func (r * Adaptation ) CreateContainer (ctx context.Context , req * CreateContainerRequest ) (* CreateContainerResponse , error ) {
271- r .Lock ()
272- defer r .Unlock ()
283+ podUID := req .GetPod ().GetId ()
284+ unlock := r .locker .LockPod (ctx , podUID )
285+ defer unlock ()
273286 defer r .removeClosedPlugins ()
274287
275288 var (
@@ -321,8 +334,9 @@ func (r *Adaptation) PostStartContainer(ctx context.Context, evt *StateChangeEve
321334
322335// UpdateContainer relays the corresponding CRI request to plugins.
323336func (r * Adaptation ) UpdateContainer (ctx context.Context , req * UpdateContainerRequest ) (* UpdateContainerResponse , error ) {
324- r .Lock ()
325- defer r .Unlock ()
337+ podUID := req .GetPod ().GetId ()
338+ unlock := r .locker .LockPod (ctx , podUID )
339+ defer unlock ()
326340 defer r .removeClosedPlugins ()
327341
328342 result := collectUpdateContainerResult (req )
@@ -348,8 +362,9 @@ func (r *Adaptation) PostUpdateContainer(ctx context.Context, evt *StateChangeEv
348362
349363// StopContainer relays the corresponding CRI request to plugins.
350364func (r * Adaptation ) StopContainer (ctx context.Context , req * StopContainerRequest ) (* StopContainerResponse , error ) {
351- r .Lock ()
352- defer r .Unlock ()
365+ podUID := req .GetPod ().GetId ()
366+ unlock := r .locker .LockPod (ctx , podUID )
367+ defer unlock ()
353368 defer r .removeClosedPlugins ()
354369
355370 result := collectStopContainerResult ()
@@ -379,24 +394,39 @@ func (r *Adaptation) StateChange(ctx context.Context, evt *StateChangeEvent) err
379394 return errors .New ("invalid (unset) event in state change notification" )
380395 }
381396
382- r .Lock ()
383- defer r .Unlock ()
384- defer r .removeClosedPlugins ()
397+ defer func () {
398+ unlock := r .locker .Lock (ctx )
399+ r .removeClosedPlugins ()
400+ unlock ()
401+ }()
385402
386- for _ , plugin := range r .plugins {
387- err := plugin .StateChange (ctx , evt )
388- if err != nil {
389- return err
403+ podUID := evt .GetPod ().GetId ()
404+ if err := func () error {
405+ unlock := r .locker .LockPod (ctx , podUID )
406+ defer unlock ()
407+ for _ , plugin := range r .plugins {
408+ err := plugin .StateChange (ctx , evt )
409+ if err != nil {
410+ return err
411+ }
390412 }
413+ return nil
414+ }(); err != nil {
415+ return err
416+ }
417+
418+ // Cleanup pod lock resources if this is the removal event
419+ if evt .Event == Event_REMOVE_POD_SANDBOX {
420+ r .locker .CleanupPod (ctx , podUID )
391421 }
392422
393423 return nil
394424}
395425
396426// Perform a set of unsolicited container updates requested by a plugin.
397427func (r * Adaptation ) updateContainers (ctx context.Context , req []* ContainerUpdate ) ([]* ContainerUpdate , error ) {
398- r . Lock ()
399- defer r . Unlock ()
428+ unlock := r . locker . Lock (ctx )
429+ defer unlock ()
400430
401431 return r .updateFn (ctx , req )
402432}
@@ -608,13 +638,13 @@ func (r *Adaptation) acceptPluginConnections(l net.Listener) error {
608638 if err != nil {
609639 log .Infof (ctx , "failed to synchronize plugin: %v" , err )
610640 } else {
611- r . Lock ()
641+ unlock := r . locker . Lock (ctx )
612642 r .plugins = append (r .plugins , p )
613643 if p .isContainerAdjustmentValidator () {
614644 r .validators = append (r .validators , p )
615645 }
616646 r .sortPlugins ()
617- r . Unlock ()
647+ unlock ()
618648 log .Infof (ctx , "plugin %q connected and synchronized" , p .name ())
619649 }
620650
0 commit comments