[gvfs] gdu: Use DriveDetach() method to power down hard disk enclosures



commit 27b14622b7fcc228ddd617ebd723751ccd8dadaa
Author: David Zeuthen <davidz redhat com>
Date:   Mon Jun 8 20:19:02 2009 -0400

    gdu: Use DriveDetach() method to power down hard disk enclosures
    
    See this commit
    
    http://cgit.freedesktop.org/DeviceKit/DeviceKit-disks/commit/?id=5b7350df8b63cf4178a2fe69ee740b5222130421
    
    for details about DriveDetach(). In a nutshell it allows us to offer
    an Eject() option on USB enclosures. Currently we don't do this since
    such devices don't have removable media.
    
    With this change, we'll set can_eject to TRUE if the device is
    detachable. If the device is both detachable and removable, we prefer
    Eject over Detach() when doing the deed (e.g. consider a USB optical
    drive; it is both detachable and removable).
    
    To sum up, the net result of this change is that users of Nautilus
    will get an Eject option and the eject icon in Nautilus' sidebar. Upon
    the user pressing Eject in the UI we'll unmount all partitions as
    usual. Then if the device is not removable, we'll invoke
    DriveDetach(). That will make DeviceKit-disks send these two SCSI
    commands
    
     SYNCHRONIZE CACHE
     STOP
    
    and then we'll unbind e.g. the usb-storage driver from the USB
    interface of the USB device. The net result is that the device appears
    to be disconnected (ie. we get remove uevents for e.g. /dev/sdb[0..N]
    and /dev/sdb) and also that the device powers down.
    
    Right now DeviceKit-disks only supports DriveDetach() for USB devices
    but should it gain support for doing the same thing for Firewire,
    eSATA, whatever then we'll get that support for free too.
---
 monitor/gdu/ggdudrive.c |   44 +++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 39 insertions(+), 5 deletions(-)

diff --git a/monitor/gdu/ggdudrive.c b/monitor/gdu/ggdudrive.c
index c2c8b76..8e04104 100644
--- a/monitor/gdu/ggdudrive.c
+++ b/monitor/gdu/ggdudrive.c
@@ -169,7 +169,7 @@ update_drive (GGduDrive *drive)
        *
        * See http://bugzilla.gnome.org/show_bug.cgi?id=576587 for why we want this.
        */
-      drive->can_eject = gdu_device_drive_get_is_media_ejectable (device) || gdu_device_drive_get_requires_eject (device) || gdu_device_is_removable (device);
+      drive->can_eject = gdu_device_drive_get_is_media_ejectable (device) || gdu_device_drive_get_requires_eject (device) || gdu_device_is_removable (device) || gdu_device_drive_get_can_detach (device);
       drive->is_media_check_automatic = gdu_device_is_media_change_detected (device);
       drive->can_poll_for_media = TRUE;
     }
@@ -352,6 +352,23 @@ g_gdu_drive_can_poll_for_media (GDrive *_drive)
 }
 
 static void
+detach_cb (GduDevice *device,
+           GError    *error,
+           gpointer   user_data)
+{
+  GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data);
+
+  if (error != NULL)
+    {
+      g_simple_async_result_set_from_error (simple, error);
+      g_error_free (error);
+    }
+
+  g_simple_async_result_complete (simple);
+  g_object_unref (simple);
+}
+
+static void
 eject_cb (GduDevice *device,
           GError    *error,
           gpointer   user_data)
@@ -360,9 +377,6 @@ eject_cb (GduDevice *device,
 
   if (error != NULL)
     {
-      /* We could handle PolicyKit integration here but this action is allowed by default
-       * and this won't be needed when porting to PolicyKit 1.0 anyway
-       */
       g_simple_async_result_set_from_error (simple, error);
       g_error_free (error);
     }
@@ -401,7 +415,27 @@ g_gdu_drive_eject_do (GDrive              *_drive,
                                           user_data,
                                           NULL);
 
-      gdu_device_op_drive_eject (device, eject_cb, simple);
+      /* Note that we also offer the Eject option for non-removable
+       * devices (see update_drive() above) that are detachable so the
+       * device may actually not be removable when we get here...
+       *
+       * However, keep in mind that a device may be both removable and
+       * detachable (e.g. a usb optical drive)..
+       *
+       * Now, consider what would happen if we detached a USB optical
+       * drive? The device would power down without actually ejecting
+       * the media... and it would require a power-cycle or a replug
+       * to use it for other media. Therefore, never detach devices
+       * with removable media, only eject them.
+       */
+      if (gdu_device_drive_get_can_detach (device) && !gdu_device_is_removable (device))
+        {
+          gdu_device_op_drive_detach (device, detach_cb, simple);
+        }
+      else
+        {
+          gdu_device_op_drive_eject (device, eject_cb, simple);
+        }
       g_object_unref (device);
     }
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]