Difference between volume and drive

Hi, ALL,

Can someone please explain what is the difference between the volume and the drive?

There are 2 APIs:

  1. g_volume_monitor_get_volumes()
  2. g_volume_monitor_get_connected_drives().

What is the difference? When to use one over the other?

Unfortunately the documentation does not say anything in this regards…

Thank you.

2 Likes

@ebassi ,
I saw you placing a reply but I don’t see it anymore.

Did you remove it later?

Thank you.

A drive is a piece of hardware which may contain volumes. For example, a DVD drive (regardless of whether it contains a DVD at the moment) or a USB stick.

A volume is a file system (which doesn’t have to be mounted). For example, a DVD in the DVD drive, or a partition on the USB stick.

A mount is a mounted file system (i.e. a mounted volume). This roughly corresponds to a UNIX mount, although it actually also allows for GVFS (user space) mounts too, so it’s not a perfect correspondence with /proc/self/mounts.

1 Like

@pwithnall ,
So if I understand correctly, get_drves() will return /dev/sda, ./dev/sdv and /dev/sdc, while get_volumes() will give /dev/sda1, /dev/sda2 and /dev/sda3.

Is it correct?

Thank you.

Also for some unknown reason I didn’t get an E-mail notification about your reply…

Thank you.

I’m not sure what function you’re referring to with get_drives(). There is no such method on any object in GIO as far as I can see.

You can see what drives and volumes are abstracted by GIO on your system by running gio mount --list --detail.

@pwithnall ,
I’m referring to the 2 API I referenced in the OP…

Thank you.

I thought maybe a simple script could help show the differences but I can’t get g_volume_monitor_get_volumes() or g_volume_monitor_get_mounts() to return anything other than an empty list?

Same with the command gio mount --list --detail. It only shows drives, no volumes or mounts.

Anyway, the script:

#!/usr/bin/python3

import gi
from gi.repository import Gio

volume_monitor = Gio.VolumeMonitor.get()

print(f'Number of drives: {len(volume_monitor.get_connected_drives())}')
for drive in volume_monitor.get_connected_drives():
	identifier = drive.get_identifier(Gio.DRIVE_IDENTIFIER_KIND_UNIX_DEVICE)
	name = drive.get_name()
	print(f'  {identifier}: {name}')

print(f'Number of volumes: {len(volume_monitor.get_volumes())}')

print(f'Number of mounts: {len(volume_monitor.get_mounts())}')

For the last 2 that always prints:

Number of volumes: 0
Number of mounts: 0

As I understood it drives are the storage devices, volumes are the available filesystems on them and mounts are the mounted filesystems.

1 Like

Your code example works fine here:

Number of drives: 9
  /dev/nvme0n1: Samsung SSD 970 EVO Plus 1TB
  /dev/sda: Seagate Expansion HDD
  /dev/sdb: ST1000LM025 HN-M101ABB
  /dev/sdc: WDC WD40NDZW-11BCSS0
  /dev/sdd: WDC WD50NDZW-11BCSS0
  /dev/sde: WDC WD40NDZW-11BHVS1
  /dev/sdf: WDC WD20SDRW-11VUUS0
  /dev/sdg: Generic- USB3.0 CRW   -SD
  /dev/sdh: Generic- USB3.0 CRW   -SD
Number of volumes: 7
Number of mounts: 6

Huh. My gio mount --list command also only shows drives, it doesn’t show volumes or mounts.

I’m using Arch Linux with glib 2.80.4. Any idea how I could try to figure out why my system’s GIO is not seeing volumes or mounts?

Hi,
I am actually looking for something like “C”, “D” and “E” on Windows.

Which means I will probably need to use second API from the OP, right?

Thank you

Hi, guys,

It unfortunately doesn’t work here as well:

16	    auto monitor = g_volume_monitor_get();
(gdb) 
17	    GList *volumelist = g_volume_monitor_get_volumes( monitor ), *volumes;
(gdb) p monitor
$1 = 0x555555ee6a20
(gdb) n
18	    for( volumes = volumelist; volumes != NULL; volumes = volumes->next )
(gdb) p volumelist
$2 = 0x0
(gdb)

I’m under Gentoo with X and GTK-3.24.21.

I’ll try to talk to Gentoo people and see what could be wrong…

Thank you.

@ebassi ,

What OS/GTK version/Backend did you run it under?

However, the command from @jakedane works fine:

igor@WaylandGnome ~/dbhandler $ gio mount --list --detail
Drive(0): HGST HTS721010A9E630
  Type: GProxyDrive (GProxyVolumeMonitorUDisks2)
  ids:
   unix-device: '/dev/sda'
  themed icons:  [drive-harddisk]  [drive]  [drive-harddisk-symbolic]  [drive-symbolic]
  symbolic themed icons:  [drive-harddisk-symbolic]  [drive-symbolic]  [drive-harddisk]  [drive]
  is_removable=0
  is_media_removable=0
  has_media=1
  is_media_check_automatic=1
  can_poll_for_media=0
  can_eject=0
  can_start=0
  can_stop=0
  start_stop_type=shutdown
  sort_key=00coldplug/00fixed/sd____a

Hi, guys,
Could someone please explain following:

igor@WaylandGnome ~/wxFork/buildGTK/tests $ python
Python 3.11.8 (main, Mar 24 2024, 02:40:39) [GCC 10.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import gi
>>> from gi.repository import Gio
>>> volume_monitor = Gio.VolumeMonitor.get()
>>> print(f'Number of drives: {len(volume_monitor.get_connected_drives())}')
Number of drives: 1
>>> print(f'Number of drives: {len(volume_monitor.get_volumes())}')
Number of drives: 0
>>> print(f'Number of drives: {len(volume_monitor.get_mounts())}')
Number of drives: 0
>>>

Thank you.

What are you expecting to see? We can’t really explain what you’re printing unless we know what the ground truth is, i.e. what hardware and partitions your computer has.

@pwithnall ,
OK.

I have a laptop with 1 hard drive so the first print is correct.

However the second print is incorrect as I have 1 volume/drive, as drive is basically a physical volume. Unless I’m wrong.

Now on this drive I have 3 partitions. And if I do “mount” I will get:

igor@WaylandGnome ~/wxFork/buildGTK/tests $ mount
/dev/sda3 on / type ext4 (rw,noatime)
devtmpfs on /dev type devtmpfs (rw,nosuid,noexec,relatime,size=10240k,nr_inodes=950063,mode=755)
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
tmpfs on /run type tmpfs (rw,nosuid,nodev,size=1520712k,nr_inodes=819200,mode=755)
sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime)
debugfs on /sys/kernel/debug type debugfs (rw,nosuid,nodev,noexec,relatime)
efivarfs on /sys/firmware/efi/efivars type efivarfs (rw,nosuid,nodev,noexec,relatime)
none on /sys/fs/cgroup type cgroup2 (rw,nosuid,nodev,noexec,relatime,nsdelegate)
mqueue on /dev/mqueue type mqueue (rw,nosuid,nodev,noexec,relatime)
devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000)
shm on /dev/shm type tmpfs (rw,nosuid,nodev,noexec,relatime)
binfmt_misc on /proc/sys/fs/binfmt_misc type binfmt_misc (rw,nosuid,nodev,noexec,relatime)
tmpfs on /run/user/1000 type tmpfs (rw,nosuid,nodev,relatime,size=760356k,nr_inodes=190089,mode=700,uid=1000,gid=1000)
igor@WaylandGnome ~/wxFork/buildGTK/tests $

So the last print should give at least 1 (for /dev/sda3).

Am I wrong?

Thank you.

No idea. You could run your program under gdb and set a breakpoint on update_volumes (it’s in gunixvolumemonitor.c), then step through the code and see what volumes are being listed by the code in gunixmounts.c and whether they are making their way through to the volume monitor.

@pwithnall ,
Yes, I should.
I’m setting up the environment to do some debugging…

And then I’ll rebuild glib in order to debug gio…

But I actually wonder if my assessment is correct…

Thank you,

Hi,
How can I get in touch with glib/gio developers?

I tried to debug it but the code has a lot of macros and I’m completely lost there…

Thank you.

This is what my session looks like:

19	        volumelist = g_volume_monitor_get_mounts( monitor );
(gdb) s
g_volume_monitor_get_mounts (volume_monitor=0x555555e47240 [GUnionVolumeMonitor])
    at ../glib-2.78.3/gio/gvolumemonitor.c:344
344	  g_return_val_if_fail (G_IS_VOLUME_MONITOR (volume_monitor), NULL);
(gdb) s
0x00007ffff2c38670 in g_volume_monitor_get_type () at ../glib-2.78.3/gio/gvolumemonitor.c:53
53	G_DEFINE_TYPE (GVolumeMonitor, g_volume_monitor, G_TYPE_OBJECT)
(gdb) s
g_type_check_instance_is_a (type_instance=type_instance@entry=0x555555e47240 [GUnionVolumeMonitor], 
    iface_type=0x555555d1c5c0 [GVolumeMonitor]) at ../glib-2.78.3/gobject/gtype.c:4164
4164	  if (!type_instance || !type_instance->g_class)
(gdb) n
4167	  iface = lookup_type_node_I (iface_type);
(gdb) 
4168	  if (iface && iface->is_final)
(gdb) 
4171	  node = lookup_type_node_I (type_instance->g_class->g_type);
(gdb) 
4172	  check = node && node->is_instantiatable && iface && type_node_conforms_to_U (node, iface, TRUE, FALSE);
(gdb) p node
$1 = (TypeNode *) 0x555555e5d480
(gdb) n
3632	  return type_node_check_conformities_UorL (node, iface_node, support_interfaces, support_prerequisites, FALSE);
(gdb) 
4172	  check = node && node->is_instantiatable && iface && type_node_conforms_to_U (node, iface, TRUE, FALSE);
(gdb) 
g_volume_monitor_get_mounts (volume_monitor=0x555555e47240 [GUnionVolumeMonitor])
    at ../glib-2.78.3/gio/gvolumemonitor.c:348
348	  return class->get_mounts (volume_monitor);
(gdb) s
get_mounts (volume_monitor=0x555555e47240 [GUnionVolumeMonitor])
    at ../glib-2.78.3/gio/gunionvolumemonitor.c:109
109	  monitor = G_UNION_VOLUME_MONITOR (volume_monitor);
(gdb) n
113	  g_rec_mutex_lock (&the_volume_monitor_mutex);
(gdb) p monitor
$2 = 0x555555e47240 [GUnionVolumeMonitor]
(gdb) n
115	  for (l = monitor->monitors; l != NULL; l = l->next)
(gdb) p monitor+>monitors
A syntax error in expression, near `>monitors'.
(gdb) p monitor->monitors
$3 = 0x7fffd4005c90 = {0x555555ee3060, 0x555555e45cb0, 0x555555e45d80}
(gdb) n
119	      res = g_list_concat (res, g_volume_monitor_get_mounts (child_monitor));
(gdb) s
g_volume_monitor_get_mounts (volume_monitor=0x555555ee3060 [GDaemonVolumeMonitor])
    at ../glib-2.78.3/gio/gvolumemonitor.c:344
344	  g_return_val_if_fail (G_IS_VOLUME_MONITOR (volume_monitor), NULL);
(gdb) s
0x00007ffff2c38670 in g_volume_monitor_get_type () at ../glib-2.78.3/gio/gvolumemonitor.c:53
53	G_DEFINE_TYPE (GVolumeMonitor, g_volume_monitor, G_TYPE_OBJECT)
(gdb) n
g_volume_monitor_get_mounts (volume_monitor=0x555555ee3060 [GDaemonVolumeMonitor])
    at ../glib-2.78.3/gio/gvolumemonitor.c:348
348	  return class->get_mounts (volume_monitor);
(gdb) s
0x00007fffea919200 in get_mounts () from /usr/lib64/gio/modules/libgvfsdbus.so
(gdb) n
Single stepping until exit from function get_mounts,
which has no line number information.
get_mounts (volume_monitor=<optimized out>) at ../glib-2.78.3/gio/gunionvolumemonitor.c:115
115	  for (l = monitor->monitors; l != NULL; l = l->next)
(gdb) 
119	      res = g_list_concat (res, g_volume_monitor_get_mounts (child_monitor));
(gdb) p monitor
$4 = <optimized out>
(gdb) p monitor->monitors
value has been optimized out
(gdb) p l
$5 = 0x7fffd4002790 = {0x555555e45cb0, 0x555555e45d80}
(gdb) n
115	  for (l = monitor->monitors; l != NULL; l = l->next)
(gdb) 
119	      res = g_list_concat (res, g_volume_monitor_get_mounts (child_monitor));
(gdb) 
115	  for (l = monitor->monitors; l != NULL; l = l->next)
(gdb) p res
$6 = 0x0
(gdb) n
122	  g_rec_mutex_unlock (&the_volume_monitor_mutex);
(gdb) 
124	  return res;
(gdb) p res
$7 = <optimized out>
(gdb) n

Philip Withnall is the core maintainer of GLib.

I think you could rather build GLib and use debug statements if you’re comfortable building packages on Gentoo.

@Sid ,
He maybe a glib core-dev, but not gio… :wink:

Anyway, that will probably be the next step…

However, what worries me is the fact that jakedane and ebassi results differ. It would be nice to know what OS/glib version they use and find out what is resulting in the diff.

After all Emmanuele is core maintainer of the GTK…

Thank you.