vishesh92 opened a new issue, #14695:
URL: https://github.com/apache/cloudstack/issues/14695

   ### problem
   
   When a LUKS-encrypted volume on StorPool primary storage is resized, the
   plugin resizes the StorPool volume to exactly the requested size. At creation
   the plugin adds 2 MiB (2097152 bytes) for the LUKS header, but the resize 
path
   does not.
   
   Effects:
   
   1. Live resize fails inside QEMU. The agent runs `virsh blockresize` with the
      new size; QEMU needs new size + LUKS payload offset on the underlying 
block
      device, which is larger than the device, and returns:
   
      ```
      internal error: unable to execute QEMU command 'block_resize': Cannot 
grow device files
      ```
   
      The failure is not surfaced. `notifyqemu()` in `resizevolume.sh` only logs
      "failed to live resize", the script exits 0, the agent returns success and
      the resizeVolume job succeeds. The guest keeps seeing the old size.
   
   2. Size mismatch. CloudStack records the requested size, but once QEMU
      re-reads the device (VM stop/start, or a manual blockresize) the guest 
sees
      the requested size minus the LUKS header. The same shortfall applies to
      offline resize, without any error (from code reading, not tested).
   
   3. Rollback uses the same unadjusted size (from code reading, not tested).
      If the StorPool API call or the agent command fails, `resizeVolume()` 
calls
      `StorPoolUtil.volumeUpdate(name, oldSize, true, ...)`, i.e. shrinkOk=true
      with the CloudStack size. For an encrypted volume that has never been
      resized the device is oldSize + 2097152, so this requests a 2 MiB shrink 
of
      a LUKS device.
   
   Code references (main at cc30155defc89bce24a253df892a0494ae8bba1e):
   
   - Create adds the allowance:
     
https://github.com/apache/cloudstack/blob/cc30155defc89bce24a253df892a0494ae8bba1e/plugins/storage/volume/storpool/src/main/java/org/apache/cloudstack/storage/datastore/driver/StorPoolPrimaryDataStoreDriver.java#L302
     (also L876 and L879 for volumes created from a template/snapshot)
   - Resize does not (`updateVolumeByStorPoolQoS`, `updateVolumeByOffering`):
     
https://github.com/apache/cloudstack/blob/cc30155defc89bce24a253df892a0494ae8bba1e/plugins/storage/volume/storpool/src/main/java/org/apache/cloudstack/storage/datastore/driver/StorPoolPrimaryDataStoreDriver.java#L495-L512
   - Rollback with oldSize and shrinkOk=true:
     
https://github.com/apache/cloudstack/blob/cc30155defc89bce24a253df892a0494ae8bba1e/plugins/storage/volume/storpool/src/main/java/org/apache/cloudstack/storage/datastore/driver/StorPoolPrimaryDataStoreDriver.java#L420-L436
   - QEMU side: `block_crypto_co_truncate` adds the payload offset, and
     `raw_co_truncate` rejects growth of a block device:
     https://github.com/qemu/qemu/blob/v9.0.0/block/crypto.c#L433-L449
     https://github.com/qemu/qemu/blob/v9.0.0/block/file-posix.c#L2670-L2678
   
   The header allowance was introduced with StorPool encryption support in 
#7539.
   
   ### versions
   
   on all versions
   
   ### The steps to reproduce the bug
   
   1. KVM zone with StorPool primary storage and a host that supports volume
      encryption. Create a custom-size disk offering with encrypt=true, tagged
      to the StorPool pool.
   2. Create a 10 GiB data volume from that offering and attach it to a running
      VM. On the host, `blockdev --getsize64` on the StorPool device shows
      10739515392 (10 GiB + 2097152); the guest sees 10737418240.
   3. Resize the volume while the VM is running:
      cmk resize volume id=<volume-uuid> size=20
   4. Observe:
      - the resizeVolume job succeeds and CloudStack reports 20 GiB
      - `blockdev --getsize64` shows 21474836480 (exactly 20 GiB, no allowance)
      - libvirtd logs the block_resize "Cannot grow device files" error
      - the guest still sees 10 GiB
   
   Expected: the StorPool volume is resized to 20 GiB + 2097152, blockresize
   succeeds, and the guest sees 20 GiB, matching what CloudStack reports.
   
   ### What to do about it?
   
   Apply the same allowance on resize as on create, for encrypted volumes only:
   
   - In `updateVolumeByOffering` and `updateVolumeByStorPoolQoS`, send
     `payload.newSize + 2097152` to the StorPool API when the volume has a
     passphrase (or KMS key on main). `updateVolumeByStorPoolQoS` needs the
     volume passed in.
   - Use the same adjusted size for the rollback in `resizeVolume()`.
   - Keep `payload.newSize` for the agent command and for the size stored in
     the database.
   
   Sketch:
   
   ```java
   private static long getStorPoolVolumeSize(VolumeObject vol, long size) {
       boolean encrypted = vol.getPassphraseId() != null || vol.getKmsKeyId() 
!= null;
       return encrypted ? size + 2097152 : size;
   }
   ```
   
   Volumes already resized under this bug have no allowance; the next resize
   after the fix would correct them.
   
   Separately, it may be worth surfacing the blockresize failure instead of
   returning success, so a failed live resize is visible in the job result.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to