Index: /trunk/include/VBox/settings.h
===================================================================
--- /trunk/include/VBox/settings.h	(revision 38872)
+++ /trunk/include/VBox/settings.h	(revision 38873)
@@ -841,4 +841,7 @@
     bool                fNonRotational;
 
+    // Whether the medium supports discarding unused blocks:
+    bool                fDiscard;
+
     int32_t             lPort;
     int32_t             lDevice;
Index: /trunk/src/VBox/Main/idl/VirtualBox.xidl
===================================================================
--- /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 38872)
+++ /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 38873)
@@ -3627,5 +3627,5 @@
   <interface
     name="IMachine" extends="$unknown"
-    uuid="5eaa9319-62fc-4b0a-843c-0cb1940f8a91"
+    uuid="5a8e9425-aa0d-4703-9f28-2353fc4ee623"
     wsmap="managed"
     >
@@ -4763,4 +4763,43 @@
     </method>
 
+    <method name="discardDevice">
+      <desc>
+        Sets a flag in the device information which indicates that the medium
+        supports discarding unsused blocks (called trimming for SATA or unmap
+        for SCSI devices) .This may or may not be supported by a particular drive,
+        and is silently ignored in the latter case. At the moment only hard disks
+        (which is a misnomer in this context) accept this setting. Changing the
+        setting while the VM is running is forbidden. The device must already
+        exist; see <link to="IMachine::attachDevice"/> for how to attach a new
+        device.
+
+        The @a controllerPort and @a device parameters specify the device slot and
+        have have the same meaning as with <link to="IMachine::attachDevice" />.
+
+        <result name="E_INVALIDARG">
+          SATA device, SATA port, SCSI port out of range.
+        </result>
+        <result name="VBOX_E_INVALID_OBJECT_STATE">
+          Attempt to modify an unregistered virtual machine.
+        </result>
+        <result name="VBOX_E_INVALID_VM_STATE">
+          Invalid machine state.
+        </result>
+
+      </desc>
+      <param name="name" type="wstring" dir="in">
+        <desc>Name of the storage controller.</desc>
+      </param>
+      <param name="controllerPort" type="long" dir="in">
+        <desc>Storage controller port.</desc>
+      </param>
+      <param name="device" type="long" dir="in">
+        <desc>Device slot in the given port.</desc>
+      </param>
+      <param name="discard" type="boolean" dir="in">
+        <desc>New value for the discard device flag.</desc>
+      </param>
+    </method>
+
     <method name="setBandwidthGroupForDevice">
       <desc>
@@ -9793,5 +9832,5 @@
   <interface
     name="IMediumAttachment" extends="$unknown"
-    uuid="b5dfbb8c-7498-48c3-bf10-78fc60f064e1"
+    uuid="5ee464d6-0613-4331-b154-7ce12170ef9f"
     wsmap="struct"
     >
@@ -10017,4 +10056,8 @@
     <attribute name="nonRotational" type="boolean" readonly="yes">
       <desc>Whether the associated medium is non-rotational.</desc>
+    </attribute>
+
+    <attribute name="discard" type="boolean" readonly="yes">
+      <desc>Whether the associated medium supports discarding unused blocks.</desc>
     </attribute>
 
Index: /trunk/src/VBox/Main/include/ConsoleImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/ConsoleImpl.h	(revision 38872)
+++ /trunk/src/VBox/Main/include/ConsoleImpl.h	(revision 38873)
@@ -528,4 +528,5 @@
                      unsigned uMergeTarget,
                      const char *pcszBwGroup,
+                     bool fDiscard,
                      IMedium *pMedium,
                      MachineState_T aMachineState,
Index: /trunk/src/VBox/Main/include/MachineImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/MachineImpl.h	(revision 38872)
+++ /trunk/src/VBox/Main/include/MachineImpl.h	(revision 38873)
@@ -479,4 +479,5 @@
     STDMETHOD(TemporaryEjectDevice)(IN_BSTR aControllerName, LONG aControllerPort, LONG aDevice, BOOL aTempEject);
     STDMETHOD(NonRotationalDevice)(IN_BSTR aControllerName, LONG aControllerPort, LONG aDevice, BOOL aNonRotational);
+    STDMETHOD(DiscardDevice)(IN_BSTR aControllerName, LONG aControllerPort, LONG aDevice, BOOL aDiscard);
     STDMETHOD(SetBandwidthGroupForDevice)(IN_BSTR aControllerName, LONG aControllerPort,
                                           LONG aDevice, IBandwidthGroup *aBandwidthGroup);
Index: /trunk/src/VBox/Main/include/MediumAttachmentImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/MediumAttachmentImpl.h	(revision 38872)
+++ /trunk/src/VBox/Main/include/MediumAttachmentImpl.h	(revision 38873)
@@ -51,4 +51,5 @@
                  bool fTempEject,
                  bool fNonRotational,
+                 bool fDiscard,
                  const Utf8Str &strBandwidthGroup);
     HRESULT initCopy(Machine *aParent, MediumAttachment *aThat);
@@ -68,4 +69,5 @@
     STDMETHOD(COMGETTER(IsEjected))(BOOL *aIsEjected);
     STDMETHOD(COMGETTER(NonRotational))(BOOL *aNonRotational);
+    STDMETHOD(COMGETTER(Discard))(BOOL *aDiscard);
     STDMETHOD(COMGETTER(BandwidthGroup))(IBandwidthGroup **aBwGroup);
 
@@ -87,4 +89,5 @@
     bool getTempEject() const;
     bool getNonRotational() const;
+    bool getDiscard() const;
     const Utf8Str& getBandwidthGroup() const;
 
@@ -102,4 +105,7 @@
     /** Must be called from under this object's write lock. */
     void updateNonRotational(bool aNonRotational);
+
+    /** Must be called from under this object's write lock. */
+    void updateDiscard(bool aDiscard);
 
     /** Must be called from under this object's write lock. */
Index: /trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp	(revision 38872)
+++ /trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp	(revision 38873)
@@ -2877,4 +2877,6 @@
         BOOL fNonRotational;
         hrc = pMediumAtt->COMGETTER(NonRotational)(&fNonRotational);                        H();
+        BOOL fDiscard;
+        hrc = pMediumAtt->COMGETTER(Discard)(&fDiscard);                                    H();
 
         unsigned uLUN;
@@ -3174,4 +3176,5 @@
                           uMergeTarget,
                           strBwGroup.isEmpty() ? NULL : Utf8Str(strBwGroup).c_str(),
+                          fDiscard,
                           pMedium,
                           aMachineState,
@@ -3215,4 +3218,5 @@
                           unsigned uMergeTarget,
                           const char *pcszBwGroup,
+                          bool fDiscard,
                           IMedium *pMedium,
                           MachineState_T aMachineState,
@@ -3403,4 +3407,7 @@
                 if (pcszBwGroup)
                     InsertConfigString(pCfg, "BwGroup", pcszBwGroup);
+
+                if (fDiscard)
+                    InsertConfigInteger(pCfg, "Discard", 1);
 
                 /* Pass all custom parameters. */
Index: /trunk/src/VBox/Main/src-server/MachineImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-server/MachineImpl.cpp	(revision 38872)
+++ /trunk/src/VBox/Main/src-server/MachineImpl.cpp	(revision 38873)
@@ -3807,4 +3807,5 @@
                           false /* fTempEject */,
                           false /* fNonRotational */,
+                          false /* fDiscard */,
                           Utf8Str::Empty);
     if (FAILED(rc)) return rc;
@@ -4045,4 +4046,51 @@
                         aDevice, aControllerPort, aControllerName);
     pAttach->updateNonRotational(!!aNonRotational);
+
+    return S_OK;
+}
+
+STDMETHODIMP Machine::DiscardDevice(IN_BSTR aControllerName, LONG aControllerPort,
+                                    LONG aDevice, BOOL aDiscard)
+{
+    CheckComArgStrNotEmptyOrNull(aControllerName);
+
+    LogFlowThisFunc(("aControllerName=\"%ls\" aControllerPort=%d aDevice=%d aDiscard=%d\n",
+                     aControllerName, aControllerPort, aDevice, aDiscard));
+
+    AutoCaller autoCaller(this);
+    if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    HRESULT rc = checkStateDependency(MutableStateDep);
+    if (FAILED(rc)) return rc;
+
+    AssertReturn(mData->mMachineState != MachineState_Saved, E_FAIL);
+
+    if (Global::IsOnlineOrTransient(mData->mMachineState))
+        return setError(VBOX_E_INVALID_VM_STATE,
+                        tr("Invalid machine state: %s"),
+                        Global::stringifyMachineState(mData->mMachineState));
+
+    MediumAttachment *pAttach = findAttachment(mMediaData->mAttachments,
+                                               aControllerName,
+                                               aControllerPort,
+                                               aDevice);
+    if (!pAttach)
+        return setError(VBOX_E_OBJECT_NOT_FOUND,
+                        tr("No storage device attached to device slot %d on port %d of controller '%ls'"),
+                        aDevice, aControllerPort, aControllerName);
+
+
+    setModified(IsModified_Storage);
+    mMediaData.backup();
+
+    AutoWriteLock attLock(pAttach COMMA_LOCKVAL_SRC_POS);
+
+    if (pAttach->getType() != DeviceType_HardDisk)
+        return setError(E_INVALIDARG,
+                        tr("Setting the discard medium flag rejected as the device attached to device slot %d on port %d of controller '%ls' is not a hard disk"),
+                        aDevice, aControllerPort, aControllerName);
+    pAttach->updateDiscard(!!aDiscard);
 
     return S_OK;
@@ -8184,4 +8232,5 @@
                                dev.fTempEject,
                                dev.fNonRotational,
+                               dev.fDiscard,
                                pBwGroup.isNull() ? Utf8Str::Empty : pBwGroup->getName());
         if (FAILED(rc)) break;
@@ -9131,5 +9180,5 @@
             dev.fPassThrough = pAttach->getPassthrough();
             dev.fTempEject = pAttach->getTempEject();
-            dev.fNonRotational = pAttach->getNonRotational();
+            dev.fDiscard = pAttach->getDiscard();
         }
 
@@ -9475,4 +9524,5 @@
                                   false /* aTempEject */,
                                   pAtt->getNonRotational(),
+                                  pAtt->getDiscard(),
                                   pAtt->getBandwidthGroup());
             if (FAILED(rc)) throw rc;
Index: /trunk/src/VBox/Main/src-server/MediumAttachmentImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-server/MediumAttachmentImpl.cpp	(revision 38872)
+++ /trunk/src/VBox/Main/src-server/MediumAttachmentImpl.cpp	(revision 38873)
@@ -42,4 +42,5 @@
           fTempEject(false),
           fNonRotational(false),
+          fDiscard(false),
           fImplicit(false)
     { }
@@ -60,4 +61,5 @@
     bool                fTempEject;
     bool                fNonRotational;
+    bool                fDiscard;
     bool                fImplicit;
 };
@@ -120,4 +122,5 @@
                                bool aTempEject,
                                bool aNonRotational,
+                               bool aDiscard,
                                const Utf8Str &strBandwidthGroup)
 {
@@ -147,4 +150,5 @@
     m->bd->fTempEject = aTempEject;
     m->bd->fNonRotational = aNonRotational;
+    m->bd->fDiscard = aDiscard;
     m->bd->fImplicit = aImplicit;
 
@@ -370,4 +374,21 @@
 }
 
+STDMETHODIMP MediumAttachment::COMGETTER(Discard)(BOOL *aDiscard)
+{
+    LogFlowThisFuncEnter();
+
+    CheckComArgOutPointerValid(aDiscard);
+
+    AutoCaller autoCaller(this);
+    if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+    AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
+
+    *aDiscard = m->bd->fDiscard;
+
+    LogFlowThisFuncLeave();
+    return S_OK;
+}
+
 STDMETHODIMP MediumAttachment::COMGETTER(BandwidthGroup) (IBandwidthGroup **aBwGroup)
 {
@@ -486,4 +507,10 @@
 }
 
+bool MediumAttachment::getDiscard() const
+{
+    AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
+    return m->bd->fDiscard;
+}
+
 const Utf8Str& MediumAttachment::getBandwidthGroup() const
 {
@@ -547,4 +574,13 @@
 }
 
+/** Must be called from under this object's write lock. */
+void MediumAttachment::updateDiscard(bool aDiscard)
+{
+    Assert(isWriteLockOnCurrentThread());
+
+    m->bd.backup();
+    m->bd->fDiscard = aDiscard;
+}
+
 void MediumAttachment::updateBandwidthGroup(const Utf8Str &aBandwidthGroup)
 {
Index: /trunk/src/VBox/Main/xml/Settings.cpp
===================================================================
--- /trunk/src/VBox/Main/xml/Settings.cpp	(revision 38872)
+++ /trunk/src/VBox/Main/xml/Settings.cpp	(revision 38873)
@@ -1693,4 +1693,5 @@
                   && (fTempEject                == a.fTempEject)
                   && (fNonRotational            == a.fNonRotational)
+                  && (fDiscard                  == a.fDiscard)
                   && (lPort                     == a.lPort)
                   && (lDevice                   == a.lDevice)
@@ -2989,4 +2990,5 @@
                 att.deviceType = DeviceType_HardDisk;
                 pelmAttached->getAttributeValue("nonrotational", att.fNonRotational);
+                pelmAttached->getAttributeValue("discard", att.fDiscard);
             }
             else if (m->sv >= SettingsVersion_v1_9)
@@ -4237,4 +4239,6 @@
                     if (att.fNonRotational)
                         pelmDevice->setAttribute("nonrotational", att.fNonRotational);
+                    if (att.fDiscard)
+                        pelmDevice->setAttribute("discard", att.fDiscard);
                     break;
 
@@ -4603,5 +4607,5 @@
     {
         // VirtualBox 4.0 adds HD audio, CPU priorities, fault tolerance,
-        // per-machine media registries, VRDE, JRockitVE, bandwidth gorups,
+        // per-machine media registries, VRDE, JRockitVE, bandwidth groups,
         // ICH9 chipset
         if (    hardwareMachine.audioAdapter.controllerType == AudioControllerType_HDA
