diff --git a/internal/rbd/rbd_util.go b/internal/rbd/rbd_util.go index 293997720..7dcf76523 100644 --- a/internal/rbd/rbd_util.go +++ b/internal/rbd/rbd_util.go @@ -333,15 +333,52 @@ func (rv *rbdVolume) allocate(offset uint64) error { return err } - // zeroBlock is the stripe-period: size of the object-size multiplied + // blockSize is the stripe-period: size of the object-size multiplied // by the stripe-count - zeroBlock := make([]byte, sc*(1< blockSize { + writeSize := size + // write a maximum of 1GB per WriteSame() call + if size > helpers.GiB { + writeSize = helpers.GiB + } + + // round down to the size of a zeroBlock + if (writeSize % blockSize) != 0 { + writeSize = (writeSize / blockSize) * blockSize + } + + _, err = image.WriteSame(offset, writeSize, zeroBlock, + rados.OpFlagNone) + if err != nil { + return fmt.Errorf("failed to allocate %d/%d bytes at "+ + "offset %d: %w", writeSize, blockSize, offset, err) + } + + // write succeeded + size -= writeSize + offset += writeSize + } + + // write the last remaining bytes, in case the image size can not be + // written with the optimal blockSize + if size != 0 { + _, err = image.WriteAt(zeroBlock[:size], int64(offset)) + if err != nil { + return fmt.Errorf("failed to allocate %d bytes at "+ + "offset %d: %w", size, offset, err) + } + } + + return nil } // isInUse checks if there is a watcher on the image. It returns true if there