View | Details | Raw Unified | Return to bug 47731
Collapse All | Expand All

(-)a/src/udiskslinuxblock.c (-16 / +82 lines)
Lines 49-54 Link Here
49
#include "udiskslinuxblock.h"
49
#include "udiskslinuxblock.h"
50
#include "udiskslinuxblockobject.h"
50
#include "udiskslinuxblockobject.h"
51
#include "udiskslinuxdriveobject.h"
51
#include "udiskslinuxdriveobject.h"
52
#include "udiskslinuxdrive.h"
52
#include "udisksdaemon.h"
53
#include "udisksdaemon.h"
53
#include "udisksstate.h"
54
#include "udisksstate.h"
54
#include "udisksprivate.h"
55
#include "udisksprivate.h"
Lines 220-239 find_block_device_by_sysfs_path (GDBusObjectManagerServer *object_manager, Link Here
220
221
221
/* ---------------------------------------------------------------------------------------------------- */
222
/* ---------------------------------------------------------------------------------------------------- */
222
223
224
typedef struct
225
{
226
  UDisksDaemon *daemon;
227
  gchar *obj_path;
228
} PingDriveData;
229
230
static void
231
free_ping_drive_data (gpointer user_data)
232
{
233
  PingDriveData *data = user_data;
234
235
  g_free (data->obj_path);
236
  g_free (data);
237
}
238
239
static gboolean
240
ping_drive_idle_cb (gpointer user_data)
241
{
242
  PingDriveData *data = user_data;
243
  UDisksObject *object;
244
  UDisksDrive *drive;
245
246
  object = udisks_daemon_find_object (data->daemon, data->obj_path);
247
  drive = object ? udisks_object_get_drive (object) : NULL;
248
  if (object && drive)
249
    {
250
      udisks_linux_drive_recalculate_nvme_size (UDISKS_LINUX_DRIVE (drive),
251
                                                UDISKS_LINUX_DRIVE_OBJECT (object));
252
    }
253
  g_clear_object (&object);
254
  g_clear_object (&drive);
255
256
  return G_SOURCE_REMOVE;
257
}
258
223
static gchar *
259
static gchar *
224
find_drive (GDBusObjectManagerServer  *object_manager,
260
find_drive (UDisksDaemon  *daemon,
225
            GUdevDevice               *block_device,
261
            GUdevDevice   *block_device,
226
            UDisksDrive              **out_drive)
262
            gboolean       update_size,
263
            UDisksDrive  **out_drive)
227
{
264
{
265
  GDBusObjectManagerServer *object_manager;
228
  GUdevDevice *whole_disk_block_device;
266
  GUdevDevice *whole_disk_block_device;
229
  const gchar *whole_disk_block_device_sysfs_path;
267
  const gchar *whole_disk_block_device_sysfs_path;
230
  gchar **nvme_ctrls = NULL;
268
  gchar **nvme_ctrls = NULL;
231
  gchar *ret;
269
  gchar *ret = NULL;
232
  GList *objects = NULL;
270
  GList *objects = NULL;
233
  GList *l;
271
  GList *l;
234
272
235
  ret = NULL;
236
237
  if (g_strcmp0 (g_udev_device_get_devtype (block_device), "disk") == 0)
273
  if (g_strcmp0 (g_udev_device_get_devtype (block_device), "disk") == 0)
238
    whole_disk_block_device = g_object_ref (block_device);
274
    whole_disk_block_device = g_object_ref (block_device);
239
  else
275
  else
Lines 267-272 find_drive (GDBusObjectManagerServer *object_manager, Link Here
267
      g_clear_object (&parent_device);
303
      g_clear_object (&parent_device);
268
    }
304
    }
269
305
306
  object_manager = udisks_daemon_get_object_manager (daemon);
270
  objects = g_dbus_object_manager_get_objects (G_DBUS_OBJECT_MANAGER (object_manager));
307
  objects = g_dbus_object_manager_get_objects (G_DBUS_OBJECT_MANAGER (object_manager));
271
  for (l = objects; l != NULL; l = l->next)
308
  for (l = objects; l != NULL; l = l->next)
272
    {
309
    {
Lines 283-301 find_drive (GDBusObjectManagerServer *object_manager, Link Here
283
          UDisksLinuxDevice *drive_device = UDISKS_LINUX_DEVICE (j->data);
320
          UDisksLinuxDevice *drive_device = UDISKS_LINUX_DEVICE (j->data);
284
          const gchar *drive_sysfs_path;
321
          const gchar *drive_sysfs_path;
285
322
323
          /* See if the drive object encloses our block device.
324
           * For NVMe, see if the drive object representing a NVMe controller
325
           * provides our namespace.
326
           */
286
          drive_sysfs_path = g_udev_device_get_sysfs_path (drive_device->udev_device);
327
          drive_sysfs_path = g_udev_device_get_sysfs_path (drive_device->udev_device);
287
          if (g_strcmp0 (whole_disk_block_device_sysfs_path, drive_sysfs_path) == 0 ||
328
          if (g_strcmp0 (whole_disk_block_device_sysfs_path, drive_sysfs_path) == 0 ||
288
              (nvme_ctrls && g_strv_contains ((const gchar * const *) nvme_ctrls, drive_sysfs_path)))
329
              (nvme_ctrls && g_strv_contains ((const gchar * const *) nvme_ctrls, drive_sysfs_path)))
289
            {
330
            {
290
              if (out_drive != NULL)
331
              const gchar *obj_path;
291
                *out_drive = udisks_object_get_drive (UDISKS_OBJECT (object));
332
292
              ret = g_strdup (g_dbus_object_get_object_path (G_DBUS_OBJECT (object)));
333
              /* FIXME: An NVMe namespace may be provided by multiple controllers within
293
              g_list_free_full (drive_devices, g_object_unref);
334
               *        an NVMe subsystem, however the org.freedesktop.UDisks2.Block.Drive
294
              /* FIXME: NVMe namespace may be provided by multiple controllers within
335
               *        property may only contain a single object path.
295
               *  a NVMe subsystem, however the org.freedesktop.UDisks2.Block.Drive
296
               *  property may only contain single object path.
297
               */
336
               */
298
              goto out;
337
              if (out_drive != NULL && *out_drive == NULL)
338
                *out_drive = udisks_object_get_drive (UDISKS_OBJECT (object));
339
              obj_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (object));
340
              if (! ret)
341
                ret = g_strdup (obj_path);
342
              if (!nvme_ctrls || !update_size)
343
                {
344
                  g_list_free_full (drive_devices, g_object_unref);
345
                  goto out;
346
                }
347
              else
348
                {
349
                  if (!udisks_linux_device_nvme_tnvmcap_supported (drive_device))
350
                    {
351
                      PingDriveData *data;
352
353
                      /* ping the drive object to recalculate controller size
354
                       * from all attached namespaces
355
                       */
356
                      data = g_new0 (PingDriveData, 1);
357
                      data->daemon = daemon;
358
                      data->obj_path = g_strdup (obj_path);
359
                      g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
360
                                       ping_drive_idle_cb,
361
                                       data,
362
                                       free_ping_drive_data);
363
                    }
364
                }
299
            }
365
            }
300
        }
366
        }
301
      g_list_free_full (drive_devices, g_object_unref);
367
      g_list_free_full (drive_devices, g_object_unref);
Lines 1135-1141 udisks_linux_block_update (UDisksLinuxBlock *block, Link Here
1135
   * TODO: if this is slow we could have a cache or ensure that we
1201
   * TODO: if this is slow we could have a cache or ensure that we
1136
   * only do this once or something else
1202
   * only do this once or something else
1137
   */
1203
   */
1138
  drive_object_path = find_drive (object_manager, device->udev_device, &drive);
1204
  drive_object_path = find_drive (daemon, device->udev_device, TRUE, &drive);
1139
  if (drive_object_path != NULL)
1205
  if (drive_object_path != NULL)
1140
    {
1206
    {
1141
      udisks_block_set_drive (iface, drive_object_path);
1207
      udisks_block_set_drive (iface, drive_object_path);
Lines 1991-1997 update_block_fstab (UDisksDaemon *daemon, Link Here
1991
2057
1992
  /* hints take fstab records in the calculation */
2058
  /* hints take fstab records in the calculation */
1993
  device = udisks_linux_block_object_get_device (object);
2059
  device = udisks_linux_block_object_get_device (object);
1994
  drive_object_path = find_drive (udisks_daemon_get_object_manager (daemon), device->udev_device, &drive);
2060
  drive_object_path = find_drive (daemon, device->udev_device, FALSE, &drive);
1995
  update_hints (daemon, block, device, drive);
2061
  update_hints (daemon, block, device, drive);
1996
  g_free (drive_object_path);
2062
  g_free (drive_object_path);
1997
  g_clear_object (&device);
2063
  g_clear_object (&device);
(-)a/src/udiskslinuxdevice.c (+21 lines)
Lines 543-545 udisks_linux_device_is_mpath_device_path (UDisksLinuxDevice *device) Link Here
543
{
543
{
544
  return g_udev_device_get_property_as_int (device->udev_device, "DM_MULTIPATH_DEVICE_PATH") == 1;
544
  return g_udev_device_get_property_as_int (device->udev_device, "DM_MULTIPATH_DEVICE_PATH") == 1;
545
}
545
}
546
547
/**
548
 * udisks_linux_device_nvme_tnvmcap_supported:
549
 * @device: A #UDisksLinuxDevice.
550
 *
551
 * Determines whether @device supports Capacity information
552
 * in the Identify Controller data structure.
553
 *
554
 * Returns: %TRUE if capacity reporting is supported, %FALSE otherwise.
555
 */
556
gboolean
557
udisks_linux_device_nvme_tnvmcap_supported (UDisksLinuxDevice *device)
558
{
559
  if (device->nvme_ctrl_info == NULL)
560
    return FALSE;
561
562
  /* FIXME: find a more reliable way to detect controller
563
   *        capacity reporting capability.
564
   */
565
  return device->nvme_ctrl_info->size_total > 0;
566
}
(-)a/src/udiskslinuxdevice.h (+1 lines)
Lines 79-84 gboolean udisks_linux_device_nvme_is_fabrics (UDisksLinuxDev Link Here
79
79
80
gboolean           udisks_linux_device_is_dm_multipath           (UDisksLinuxDevice  *device);
80
gboolean           udisks_linux_device_is_dm_multipath           (UDisksLinuxDevice  *device);
81
gboolean           udisks_linux_device_is_mpath_device_path      (UDisksLinuxDevice  *device);
81
gboolean           udisks_linux_device_is_mpath_device_path      (UDisksLinuxDevice  *device);
82
gboolean           udisks_linux_device_nvme_tnvmcap_supported    (UDisksLinuxDevice  *device);
82
83
83
G_END_DECLS
84
G_END_DECLS
84
85
(-)a/src/udiskslinuxdrive.c (+61 lines)
Lines 1055-1060 udisks_linux_drive_update (UDisksLinuxDrive *drive, Link Here
1055
1055
1056
/* ---------------------------------------------------------------------------------------------------- */
1056
/* ---------------------------------------------------------------------------------------------------- */
1057
1057
1058
/**
1059
 * udisks_linux_drive_recalculate_nvme_size:
1060
 * @drive: A #UDisksLinuxDrive.
1061
 * @object: The enclosing #UDisksLinuxDriveObject instance.
1062
 *
1063
 * Find all block objects pointing to this drive, calculate
1064
 * NVMe namespace capacity numbers and update this interface.
1065
 */
1066
void
1067
udisks_linux_drive_recalculate_nvme_size (UDisksLinuxDrive       *drive,
1068
                                          UDisksLinuxDriveObject *object)
1069
{
1070
  UDisksDaemon *daemon;
1071
  GDBusObjectManagerServer *object_manager;
1072
  GList *objects = NULL;
1073
  GList *l;
1074
  const gchar *obj_path;
1075
  guint64 size_total = 0;
1076
1077
  daemon = udisks_linux_drive_object_get_daemon (object);
1078
  object_manager = udisks_daemon_get_object_manager (daemon);
1079
  obj_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (object));
1080
1081
  objects = g_dbus_object_manager_get_objects (G_DBUS_OBJECT_MANAGER (object_manager));
1082
  for (l = objects; l != NULL; l = l->next)
1083
    {
1084
      UDisksObject *o = l->data;
1085
      UDisksBlock *block;
1086
      UDisksLinuxDevice *device;
1087
1088
      if (!UDISKS_IS_LINUX_BLOCK_OBJECT (o))
1089
        continue;
1090
1091
      block = udisks_object_get_block (o);
1092
      if (!block)
1093
          continue;
1094
1095
      if (g_strcmp0 (udisks_block_get_drive (block), obj_path) != 0)
1096
        {
1097
          g_object_unref (block);
1098
          continue;
1099
        }
1100
1101
      device = udisks_linux_block_object_get_device (UDISKS_LINUX_BLOCK_OBJECT (o));
1102
      if (device && device->nvme_ns_info &&
1103
          device->nvme_ns_info->current_lba_format.data_size > 0)
1104
        {
1105
          /* Namespace Size >= Namespace Capacity >= Namespace Utilization */
1106
          size_total += (guint64) device->nvme_ns_info->nsize *
1107
                        (guint64) device->nvme_ns_info->current_lba_format.data_size;
1108
        }
1109
      g_clear_object (&device);
1110
      g_object_unref (block);
1111
    }
1112
  g_list_free_full (objects, g_object_unref);
1113
1114
  udisks_drive_set_size (UDISKS_DRIVE (drive), size_total);
1115
}
1116
1117
/* ---------------------------------------------------------------------------------------------------- */
1118
1058
static gboolean
1119
static gboolean
1059
handle_eject (UDisksDrive           *_drive,
1120
handle_eject (UDisksDrive           *_drive,
1060
              GDBusMethodInvocation *invocation,
1121
              GDBusMethodInvocation *invocation,
(-)a/src/udiskslinuxdrive.h (+3 lines)
Lines 34-39 UDisksDrive *udisks_linux_drive_new (void); Link Here
34
gboolean     udisks_linux_drive_update   (UDisksLinuxDrive       *drive,
34
gboolean     udisks_linux_drive_update   (UDisksLinuxDrive       *drive,
35
                                          UDisksLinuxDriveObject *object);
35
                                          UDisksLinuxDriveObject *object);
36
36
37
void         udisks_linux_drive_recalculate_nvme_size (UDisksLinuxDrive       *drive,
38
                                                       UDisksLinuxDriveObject *object);
39
37
G_END_DECLS
40
G_END_DECLS
38
41
39
#endif /* __UDISKS_LINUX_DRIVE_H__ */
42
#endif /* __UDISKS_LINUX_DRIVE_H__ */

Return to bug 47731