code: func (ctrl *PersistentVolumeController) unbindVolume(volume *v1.PersistentVolume) error {
  	klog.V(4).Infof("updating PersistentVolume[%s]: rolling back binding from %q", volume.Name, claimrefToClaimKey(volume.Spec.ClaimRef))
  
  	// Save the PV only when any modification is necessary.
  	volumeClone := volume.DeepCopy()
  
  	if metav1.HasAnnotation(volume.ObjectMeta, annBoundByController) {
  		// The volume was bound by the controller.
  		volumeClone.Spec.ClaimRef = nil
  		delete(volumeClone.Annotations, annBoundByController)
  		if len(volumeClone.Annotations) == 0 {
  			// No annotations look better than empty annotation map (and it's easier
  			// to test).
  			volumeClone.Annotations = nil
  		}
  	} else {
  		// The volume was pre-bound by user. Clear only the binging UID.
  		volumeClone.Spec.ClaimRef.UID = ""
  	}
  
  	newVol, err := ctrl.kubeClient.CoreV1().PersistentVolumes().Update(volumeClone)
  	if err != nil {
  		klog.V(4).Infof("updating PersistentVolume[%s]: rollback failed: %v", volume.Name, err)
  		return err
  	}
  	_, err = ctrl.storeVolumeUpdate(newVol)
  	if err != nil {
  		klog.V(4).Infof("updating PersistentVolume[%s]: cannot update internal cache: %v", volume.Name, err)
  		return err
  	}
  	klog.V(4).Infof("updating PersistentVolume[%s]: rolled back", newVol.Name)
  
  	// Update the status
  	_, err = ctrl.updateVolumePhase(newVol, v1.VolumeAvailable, "")
  	return err
  }
docs: // unbindVolume rolls back previous binding of the volume. This may be necessary
  // when two controllers bound two volumes to single claim - when we detect this,
  // only one binding succeeds and the second one must be rolled back.
  // This method updates both Spec and Status.
  // It returns on first error, it's up to the caller to implement some retry
  // mechanism.