Skip to content

Commit 570d132

Browse files
committed
Free unused volumes in more cases
Freeing volumes is only done on scheduling ticks, but not every scheduling tick resulted in freeing volumes. This change makes it so that volumes are freed every time a scheduling tick happens, regardless of whether there were any scheduled task changes. Signed-off-by: Drew Erny <derny@mirantis.com>
1 parent c6f9c0d commit 570d132

3 files changed

Lines changed: 37 additions & 20 deletions

File tree

manager/scheduler/scheduler.go

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,18 @@ func (s *Scheduler) tick(ctx context.Context) {
488488
}
489489

490490
func (s *Scheduler) applySchedulingDecisions(ctx context.Context, schedulingDecisions map[string]schedulingDecision) (successful, failed []schedulingDecision) {
491+
// applySchedulingDecisions is the only place where we make store
492+
// transactions in the scheduler. the scheduler is responsible for freeing
493+
// volumes that are no longer in use. this means that volumes should be
494+
// freed in this function. sometimes, there are no scheduling decisions to
495+
// be made, so we return early in the if statement below.
496+
//
497+
// however, in all cases, any activity that results in a tick could result
498+
// in needing volumes to be freed, even if nothing new is scheduled. this
499+
// freeing of volumes should always happen *after* all of the scheduling
500+
// decisions have been committed, hence the defer.
501+
defer s.store.Batch(s.volumes.freeVolumes)
502+
491503
if len(schedulingDecisions) == 0 {
492504
return
493505
}
@@ -619,9 +631,7 @@ func (s *Scheduler) applySchedulingDecisions(ctx context.Context, schedulingDeci
619631
}
620632
// finally, every time we make new scheduling decisions, take the
621633
// opportunity to release volumes.
622-
return batch.Update(func(tx store.Tx) error {
623-
return s.volumes.freeVolumes(tx)
624-
})
634+
return nil
625635
})
626636

627637
if err != nil {

manager/scheduler/volumes.go

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -183,24 +183,33 @@ func (vs *volumeSet) releaseVolume(volumeID, taskID string) {
183183
//
184184
// TODO(dperny): this is messy and has a lot of overhead. it should be reworked
185185
// to something more streamlined.
186-
func (vs *volumeSet) freeVolumes(tx store.Tx) error {
186+
func (vs *volumeSet) freeVolumes(batch *store.Batch) error {
187187
for volumeID, info := range vs.volumes {
188-
v := store.GetVolume(tx, volumeID)
189-
if v == nil {
190-
continue
191-
}
188+
if err := batch.Update(func(tx store.Tx) error {
189+
v := store.GetVolume(tx, volumeID)
190+
if v == nil {
191+
return nil
192+
}
192193

193-
changed := false
194-
for _, status := range v.PublishStatus {
195-
if info.nodes[status.NodeID] == 0 && status.State == api.VolumePublishStatus_PUBLISHED {
196-
status.State = api.VolumePublishStatus_PENDING_NODE_UNPUBLISH
197-
changed = true
194+
// when we are freeing a volume, we may update more than one of the
195+
// volume's PublishStatuses. this means we can't simply put the
196+
// Update call inside of the if statement; we need to know if we've
197+
// changed anything once we've checked *all* of the statuses.
198+
changed := false
199+
for _, status := range v.PublishStatus {
200+
if info.nodes[status.NodeID] == 0 && status.State == api.VolumePublishStatus_PUBLISHED {
201+
status.State = api.VolumePublishStatus_PENDING_NODE_UNPUBLISH
202+
changed = true
203+
}
198204
}
199-
}
200-
if changed {
201-
if err := store.UpdateVolume(tx, v); err != nil {
202-
return err
205+
if changed {
206+
if err := store.UpdateVolume(tx, v); err != nil {
207+
return err
208+
}
203209
}
210+
return nil
211+
}); err != nil {
212+
return err
204213
}
205214
}
206215
return nil

manager/scheduler/volumes_test.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -652,9 +652,7 @@ var _ = Describe("volumeSet", func() {
652652
vs.releaseVolume(volumes[0].ID, tasks[0].ID)
653653
vs.releaseVolume(allVolume.ID, tasks[0].ID)
654654

655-
err := s.Update(func(tx store.Tx) error {
656-
return vs.freeVolumes(tx)
657-
})
655+
err := s.Batch(vs.freeVolumes)
658656
Expect(err).ToNot(HaveOccurred())
659657

660658
var freshVolumes []*api.Volume

0 commit comments

Comments
 (0)