Skip to content

Commit 0659e3b

Browse files
giggsofferiknordmark
authored andcommitted
Move check for size into doUpdateVol and add retry
We expect error "Remaining disk space ... volume needs ..." in case of no space for new volume, but I see this error for several seconds. Seems it was silently hidden by "Error creating zfs zvol at ..., error=exit status 1, output=cannot create '...': out of space" which is not expected. Seems we should move check for space into our volume state handler function (doUpdateVol). Also this commit adds simple retry in case of delete of another volume. Signed-off-by: Petr Fedchenkov <giggsoff@gmail.com>
1 parent 5995553 commit 0659e3b

File tree

4 files changed

+74
-28
lines changed

4 files changed

+74
-28
lines changed

pkg/pillar/cmd/volumemgr/handlevolume.go

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ func handleVolumeDelete(ctxArg interface{}, key string,
9090
}
9191
updateVolumeStatusRefCount(ctx, status)
9292
maybeDeleteVolume(ctx, status)
93+
maybeSpaceAvailable(ctx)
9394
}
9495
log.Functionf("handleVolumeDelete(%s) Done", key)
9596
}
@@ -190,31 +191,6 @@ func handleDeferredVolumeCreate(ctx *volumemgrContext, key string, config *types
190191
return
191192
}
192193
publishVolumeStatus(ctx, status)
193-
if !ctx.globalConfig.GlobalValueBool(types.IgnoreDiskCheckForApps) {
194-
// Check disk usage
195-
remaining, err := getRemainingDiskSpace(ctx)
196-
if err != nil {
197-
errStr := fmt.Sprintf("getRemainingDiskSpace failed: %s\n",
198-
err)
199-
status.SetError(errStr, time.Now())
200-
publishVolumeStatus(ctx, status)
201-
updateVolumeRefStatus(ctx, status)
202-
if err := createOrUpdateAppDiskMetrics(ctx, status); err != nil {
203-
log.Errorf("handleDeferredVolumeCreate(%s): exception while publishing diskmetric. %s", key, err.Error())
204-
}
205-
return
206-
} else if remaining < status.MaxVolSize {
207-
errStr := fmt.Sprintf("Remaining disk space %d volume needs %d\n",
208-
remaining, status.MaxVolSize)
209-
status.SetError(errStr, time.Now())
210-
publishVolumeStatus(ctx, status)
211-
updateVolumeRefStatus(ctx, status)
212-
if err := createOrUpdateAppDiskMetrics(ctx, status); err != nil {
213-
log.Errorf("handleDeferredVolumeCreate(%s): exception while publishing diskmetric. %s", key, err.Error())
214-
}
215-
return
216-
}
217-
}
218194
changed, _ := doUpdateVol(ctx, status)
219195
if changed {
220196
publishVolumeStatus(ctx, status)
@@ -351,6 +327,27 @@ func maybeDeleteVolume(ctx *volumemgrContext, status *types.VolumeStatus) {
351327
log.Functionf("maybeDeleteVolume for %v Done", status.Key())
352328
}
353329

330+
// maybeSpaceAvailable iterates over VolumeStatus and call doUpdateVol if state is less than CREATING_VOLUME
331+
func maybeSpaceAvailable(ctx *volumemgrContext) {
332+
for _, s := range ctx.pubVolumeStatus.GetAll() {
333+
status := s.(types.VolumeStatus)
334+
if status.State >= types.CREATING_VOLUME {
335+
continue
336+
}
337+
if vc := lookupVolumeConfig(ctx, status.Key()); vc == nil {
338+
continue
339+
}
340+
changed, _ := doUpdateVol(ctx, &status)
341+
if changed {
342+
publishVolumeStatus(ctx, &status)
343+
updateVolumeRefStatus(ctx, &status)
344+
if err := createOrUpdateAppDiskMetrics(ctx, &status); err != nil {
345+
log.Errorf("maybeSpaceAvailable(%s): exception while publishing diskmetric. %s", status.Key(), err.Error())
346+
}
347+
}
348+
}
349+
}
350+
354351
// updateVolumeStatusRefCount updates the refcount in volume status
355352
// Refcount in volume status is sum of refount in volume config and volume ref config
356353
func updateVolumeStatusRefCount(ctx *volumemgrContext, vs *types.VolumeStatus) {

pkg/pillar/cmd/volumemgr/handlevolumeref.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ func handleVolumeRefCreate(ctxArg interface{}, key string,
6262
if changed {
6363
publishVolumeStatus(ctx, vs)
6464
updateVolumeRefStatus(ctx, vs)
65+
if err := createOrUpdateAppDiskMetrics(ctx, vs); err != nil {
66+
log.Errorf("handleVolumeRefCreate(%s): exception while publishing diskmetric. %s",
67+
status.Key(), err.Error())
68+
}
6569
}
6670
}
6771
log.Functionf("handleVolumeRefCreate(%s) Done", key)
@@ -91,6 +95,10 @@ func handleVolumeRefModify(ctxArg interface{}, key string,
9195
}
9296
updateVolumeStatusRefCount(ctx, vs)
9397
publishVolumeStatus(ctx, vs)
98+
if err := createOrUpdateAppDiskMetrics(ctx, vs); err != nil {
99+
log.Errorf("handleVolumeRefModify(%s): exception while publishing diskmetric. %s",
100+
status.Key(), err.Error())
101+
}
94102
}
95103
log.Functionf("handleVolumeRefModify(%s) Done", key)
96104
}
@@ -107,6 +115,7 @@ func handleVolumeRefDelete(ctxArg interface{}, key string,
107115
updateVolumeStatusRefCount(ctx, vs)
108116
publishVolumeStatus(ctx, vs)
109117
maybeDeleteVolume(ctx, vs)
118+
maybeSpaceAvailable(ctx)
110119
}
111120
log.Functionf("handleVolumeRefDelete(%s) Done", key)
112121
}

pkg/pillar/cmd/volumemgr/sizemgmt.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,9 @@ func getRemainingDiskSpace(ctxPtr *volumemgrContext) (uint64, error) {
3838
itemsVolume := pubVolume.GetAll()
3939
for _, iterVolumeStatusJSON := range itemsVolume {
4040
iterVolumeStatus := iterVolumeStatusJSON.(types.VolumeStatus)
41-
if iterVolumeStatus.State < types.CREATED_VOLUME {
42-
log.Tracef("Volume %s State %d < CREATED_VOLUME",
41+
// we start consume space when moving into CREATING_VOLUME state
42+
if iterVolumeStatus.State < types.CREATING_VOLUME {
43+
log.Tracef("Volume %s State %d < CREATING_VOLUME",
4344
iterVolumeStatus.Key(), iterVolumeStatus.State)
4445
continue
4546
}
@@ -50,6 +51,11 @@ func getRemainingDiskSpace(ctxPtr *volumemgrContext) (uint64, error) {
5051
log.Noticef("getRemainingDiskSpace: Volume %s not found in VolumeConfigs, ignore",
5152
iterVolumeStatus.Key())
5253
continue
54+
}
55+
if vault.ReadPersistType() == types.PersistZFS {
56+
log.Noticef("getRemainingDiskSpace: Volume %s is zvol, use MaxVolSize",
57+
iterVolumeStatus.Key())
58+
sizeToUseInCalculation = iterVolumeStatus.MaxVolSize
5359
} else if cfg.ReadOnly {
5460
// it is ReadOnly and will not grow
5561
log.Noticef("getRemainingDiskSpace: Volume %s is ReadOnly, use CurrentSize",

pkg/pillar/cmd/volumemgr/updatestatus.go

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,8 @@ func doUpdateContentTree(ctx *volumemgrContext, status *types.ContentTreeStatus)
427427
// XXX remove "done" boolean return?
428428
func doUpdateVol(ctx *volumemgrContext, status *types.VolumeStatus) (bool, bool) {
429429

430+
var changed bool
431+
430432
log.Functionf("doUpdateVol(%s) name %s", status.Key(), status.DisplayName)
431433

432434
// Anything to do?
@@ -436,6 +438,39 @@ func doUpdateVol(ctx *volumemgrContext, status *types.VolumeStatus) (bool, bool)
436438
return false, true
437439
}
438440

441+
// do not go into CREATING_VOLUME state if no space available
442+
if status.State < types.CREATING_VOLUME && !ctx.globalConfig.GlobalValueBool(types.IgnoreDiskCheckForApps) {
443+
// Check disk usage
444+
remaining, err := getRemainingDiskSpace(ctx)
445+
if err != nil {
446+
description := types.ErrorDescription{}
447+
description.Error = fmt.Sprintf("getRemainingDiskSpace failed: %s\n", err)
448+
// do not touch time of the error with the same content
449+
if status.Error != description.Error {
450+
status.SetErrorWithSourceAndDescription(description, types.DiskMetric{})
451+
changed = true
452+
}
453+
return changed, false
454+
} else if remaining < status.MaxVolSize {
455+
description := types.ErrorDescription{}
456+
description.Error = fmt.Sprintf("Remaining disk space %d volume needs %d\n",
457+
remaining, status.MaxVolSize)
458+
description.ErrorRetryCondition = "Will retry when more space will be available"
459+
// do not touch time of the error with the same content
460+
if status.Error != description.Error {
461+
status.SetErrorWithSourceAndDescription(description, types.DiskMetric{})
462+
changed = true
463+
}
464+
return changed, false
465+
}
466+
}
467+
468+
if status.IsErrorSource(types.DiskMetric{}) {
469+
log.Functionf("doUpdateVol: Clearing DiskMetric error %s", status.Error)
470+
status.ClearErrorWithSource()
471+
changed = true
472+
}
473+
439474
verifyOnly := false
440475
vrc := lookupVolumeRefConfig(ctx, status.Key())
441476
if vrc != nil {
@@ -450,7 +485,6 @@ func doUpdateVol(ctx *volumemgrContext, status *types.VolumeStatus) (bool, bool)
450485
}
451486
}
452487

453-
changed := false
454488
switch status.VolumeContentOriginType {
455489
case zconfig.VolumeContentOriginType_VCOT_BLANK:
456490
if status.MaxVolSize == 0 {

0 commit comments

Comments
 (0)