UDisksModuleManager

UDisksModuleManager — Manages daemon modules

Functions

Types and Values

Description

UDisks modular approach

UDisks functionality can be extended by modules. It's not a fully pluggable system as we know it, in this case modules are almost integral parts of the source tree. Meaning that modules are free to use whatever internal objects they need as there is no universal module API (or a translation layer).

This fact allows us to stay code-wise simple and transparent. It also means that there's no support for out-of-the-tree modules and care must be taken when changing UDisks internals. As a design decision, for sake of simplicity, once modules are loaded they stay active until the daemon exits (this may be a subject to change in the future).

The primary motivation for this was to keep the daemon low on resource footprint for basic usage (typically desktop environments) and only activating the extended functionality when needed (e.g. enterprise storage applications). As the extra information comes in form of additional D-Bus objects and interfaces, no difference should be observed by legacy clients.

D-Bus interface extensibility

The modular approach is fairly simple, there are basically two primary ways of extending the D-Bus API:

  • by attaching custom interfaces to existing objects (limited to block and drive objects for the moment)

  • by exporting objects of its own type directly in the object manager root

Besides that there are several other ways of extensibility such as attaching custom interfaces on the master /org/freedesktop/UDisks2/Manager object.

Modules activation

The UDisks daemon constructs a UDisksModuleManager singleton acting as a manager. This object tracks module usage and takes care of its activation.

By default, module manager is constructed on daemon startup but module loading is delayed until requested. This can be overriden by the --force-load-modules and --disable-modules commandline switches that makes modules loaded right on startup or never loaded respectively.

Upon successful activation, the "modules-ready" property on the UDisksModuleManager instance is set to TRUE. Any daemon objects watching this property are responsible for performing "coldplug" on their exported objects to assure modules would pick up the devices they're interested in. See e.g. UDisksModuleObjectNewFunc() to see how device binding works for UDisksModuleObject.

Modules are in fact separate shared objects (.so) that are loaded from the "$(libdir)/udisks2/modules" path (usually "/usr/lib/udisks2/modules"). No extra or service files are needed, the directory is enumerated and all files are attempted to be loaded.

Clients are supposed to call the org.freedesktop.UDisks2.Manager.EnableModules() D-Bus method as a "greeter" call. Please note that from asynchronous nature of uevents and the way modules are processing them the extra D-Bus interfaces may not be available right after this method call returns.

Module API

The (strictly internal) module API is simple - only a couple of functions are needed. The following text contains brief description of individual parts of the module API with further links to detailed description within this API reference book.

The UDisksModuleManager first loads all module entry functions, i.e. symbols defined in the public facing header "udisksmoduleiface.h". Only those symbols should be exported from each module. The header file is only meant to be compiled in modules, not the daemon. If any of the symbols is missing in the module library, the whole module is skipped.

Once module symbols are resolved, module manager activates each module by calling udisks_module_init() on it. The returned so-called "state" pointer is stored in the UDisksModuleManager and can be later retrieved by calling the udisks_module_manager_get_module_state_pointer() method. This is typically used further in the module code to retrieve and store module-specific runtime data.

Every one of the "udisksmoduleiface.h" header file symbols has its counterpart defined in the "udisksmoduleifacetypes.h" header file in form of function pointers. Those are used internally for symbol resolving purposes. However, they also carry detailed documentation. For illustration purposes, let's call these symbol pairs the "module setup entry functions". See UDisksModuleIfaceSetupFunc, UDisksModuleObjectNewSetupFunc and UDisksModuleNewManagerIfaceSetupFunc for reference. These however are essentially auxiliary symbols only described for demonstrating the big picture; for the useful part of the module API please read on.

Every module setup entry function (besides the very simple udisks_module_init()) returns an array of setup structures or functions, containing either none (NULL result), one or more elements. The result is then mixed by UDisksModuleManager from all modules and separate lists are created for each kind of UDisks way of extension. Such lists are then used in the daemon code at appropriate places, sequentially calling elements from the lists to obtain data or objects that are then typically exported on D-Bus.

In short, have a look at the UDisksModuleInterfaceInfo, UDisksModuleObjectNewFunc and UDisksModuleNewManagerIfaceFunc definitions to learn more about particular ways of extending UDisks.

Functions

UDisksObjectHasInterfaceFunc ()

gboolean
(*UDisksObjectHasInterfaceFunc) (UDisksObject *object);

Function prototype that is used to determine whether the object is applicable for carrying a particular D-Bus interface (determined by the callback function itself).

Used typically over UDisksLinuxBlockObject and UDisksLinuxDriveObject objects for checking specific feature that leads to exporting extra D-Bus interface on the object.

Parameters

object

A UDisksObject to consider.

 

Returns

TRUE if the object is a valid candidate for the particular D-Bus interface, FALSE otherwise.


UDisksObjectConnectInterfaceFunc ()

void
(*UDisksObjectConnectInterfaceFunc) (UDisksObject *object);

Function prototype that is used once a new D-Bus interface is created (meaning the UDisksObjectHasInterfaceFunc call was successful) to perform optional additional tasks before the interface is exported on the object .

Used typically over UDisksLinuxBlockObject and UDisksLinuxDriveObject objects.

Parameters

object

A UDisksObject to perform connection operation onto.

 

UDisksObjectUpdateInterfaceFunc ()

gboolean
(*UDisksObjectUpdateInterfaceFunc) (UDisksObject *object,
                                    const gchar *uevent_action,
                                    GDBusInterface *interface);

Function prototype that is used on existing interface on the object to process incoming uevents.

Used typically over UDisksLinuxBlockObject and UDisksLinuxDriveObject objects.

Parameters

object

A UDisksObject.

 

uevent_action

An uevent action string.

 

interface

Existing GDBusInterface exported on the object .

 

Returns

TRUE if configuration (properties) on the interface have changed, FALSE otherwise.


UDisksModuleObjectNewFunc ()

GDBusObjectSkeleton *
(*UDisksModuleObjectNewFunc) (UDisksDaemon *daemon,
                              UDisksLinuxDevice *device);

Function prototype that creates new GDBusObjectSkeleton instance that implements the UDisksModuleObject interface.

This is an another way of extending UDisks functionality. Objects in this scope are meant to be of virtual kind and are pretty flexible - not necessarily bound to any block device or perhaps representing a group of resources. For illustration this kind of object may represent e.g. a RAID array comprised of several block devices, all devices of the same kind such as loop devices or any higher level representation of something else.

This function may be called quite often, for nearly any uevent received. It's done this way for broad flexibility and to give a chance to UDisksModuleObjectNewFunc functions to claim any device needed.

Every GDBusObjectSkeleton can claim one or more devices and UDisks automatically manages uevent routing and instance lifecycle. A hierarchy of claimed devices is maintained for the combination of particular module and every UDisksModuleObjectNewFunc - see below. This list lives in UDisksLinuxProvider and is strictly internal. Every module can provide multiple UDisksModuleObjectNewFunc functions for different kind of objects.

Two scenarios are distinguished:

  1. The device is already claimed by existing GDBusObjectSkeleton instance for the current UDisksModuleObjectNewFunc, it is guaranteed that only that instance will receive further uevents for the particular device . This is done by calling the udisks_module_object_process_uevent() method of the UDisksModuleObject interface. Depending on the returning value the device is either kept claimed by the object or removed. When last claimed device has been removed from the instance, it is automatically destroyed. In either case no further processing is done at this cycle to prevent creating new bogus instances for a device that has just given up.

  2. In case the device is not claimed by any existing GDBusObjectSkeleton instance for the current UDisksModuleObjectNewFunc. It now all depends on the return value of the function called. If it returns a new GDBusObjectSkeleton instance, it also indicates to UDisksLinuxProvider that it claims the device. The UDisksLinuxProvider then registers the value with the current function and keeps track of it. If it returns NULL, it inidcates that the current function is not interested in this kind of device.

It's guaranteed that existing GDBusObjectSkeleton instances will receive uevents for devices they took and creating a new instance will take place only if the event was not processed by any of them.

Parameters

daemon

A UDisksDaemon instance.

 

device

A UDisksLinuxDevice device object.

 

Returns

A new GDBusObjectSkeleton or NULL when the module doesn't handle the device specified. Free with g_object_unref().


UDisksModuleNewManagerIfaceFunc ()

GDBusInterfaceSkeleton *
(*UDisksModuleNewManagerIfaceFunc) (UDisksDaemon *daemon);

Function prototype that creates new GDBusInterfaceSkeleton instance carrying an additional D-Bus interface to be exported on the UDisks manager object (on the "/org/freedesktop/UDisks2/Manager" path). It is a fairly simple stateless object not related to any device and serves the purpose of performing general tasks or creating new resources.

Parameters

daemon

A UDisksDaemon instance.

 

Returns

A new GDBusInterfaceSkeleton. Free with g_object_unref().


UDisksModuleInitFunc ()

gpointer
(*UDisksModuleInitFunc) (UDisksDaemon *daemon);

Function prototype that is called upon module initialization. Its purpose is to perform internal initialization and allocate memory that is then used e.g. for saving state. See the udisks_module_manager_get_module_state_pointer() method for how to work with state pointers.

Corresponds with the udisks_module_init() module symbol. Used internally by UDisksModuleManager.

Parameters

daemon

A UDisksDaemon instance.

 

Returns

Pointer to an opaque memory or NULL when module doesn't need to save its state.


UDisksModuleIfaceSetupFunc ()

UDisksModuleInterfaceInfo **
(*UDisksModuleIfaceSetupFunc) (void);

Type declaration of a module setup entry function.

Corresponds with the udisks_module_get_block_object_iface_setup_entries() and udisks_module_get_drive_object_iface_setup_entries() module symbols. Used internally by UDisksModuleManager.

Returns

An array of pointers to the UDisksModuleInterfaceInfo structs. Free with g_free().


UDisksModuleObjectNewSetupFunc ()

UDisksModuleObjectNewFunc *
(*UDisksModuleObjectNewSetupFunc) (void);

Type declaration of a module setup entry function.

Corresponds with the udisks_module_get_object_new_funcs() module symbol. Used internally by UDisksModuleManager.

Returns

An array of pointers to the UDisksModuleObjectNewFunc functions. Free with g_free().


UDisksModuleNewManagerIfaceSetupFunc ()

UDisksModuleNewManagerIfaceFunc *
(*UDisksModuleNewManagerIfaceSetupFunc)
                               (void);

Type declaration of a module setup entry function.

Corresponds with the udisks_module_get_new_manager_iface_funcs() module symbol. Used internally by UDisksModuleManager.

Returns

An array of pointers to the UDisksModuleNewManagerIfaceFunc functions. Free with g_free().


udisks_module_manager_new ()

UDisksModuleManager *
udisks_module_manager_new (UDisksDaemon *daemon);

Creates a new UDisksModuleManager object.

Parameters

daemon

A UDisksDaemon instance.

 

Returns

A UDisksModuleManager. Free with g_object_unref().


udisks_module_manager_get_modules_available ()

gboolean
udisks_module_manager_get_modules_available
                               (UDisksModuleManager *manager);

Indicates whether modules have been loaded.

Parameters

manager

A UDisksModuleManager instance.

 

Returns

TRUE if modules have been loaded, FALSE otherwise.


udisks_module_manager_load_modules ()

void
udisks_module_manager_load_modules (UDisksModuleManager *manager);

Loads all modules at a time and emits the "modules-ready" signal. Does nothing when called multiple times.

Parameters

manager

A UDisksModuleManager instance.

 

udisks_module_manager_get_module_state_pointer ()

gpointer
udisks_module_manager_get_module_state_pointer
                               (UDisksModuleManager *manager,
                                const gchar *module_name);

Retrieves the stored module state pointer for the given module_name .

Parameters

manager

A UDisksModuleManager instance.

 

module_name

A module name.

 

Returns

A stored pointer to the private data or NULL if there is no state pointer for the given module_name .


udisks_module_manager_set_module_state_pointer ()

void
udisks_module_manager_set_module_state_pointer
                               (UDisksModuleManager *manager,
                                const gchar *module_name,
                                gpointer state);

Stores the state pointer for the given module_name .

Parameters

manager

A UDisksModuleManager instance.

 

module_name

A module name.

 

state

Pointer to a private data.

 

udisks_module_manager_get_block_object_iface_infos ()

GList *
udisks_module_manager_get_block_object_iface_infos
                               (UDisksModuleManager *manager);

Returns a list of block object interface info structs that can be plugged in UDisksLinuxBlockObject instances. See UDisksModuleIfaceSetupFunc for details.

Parameters

manager

A UDisksModuleManager instance.

 

Returns

A list of UDisksModuleIfaceSetupFunc structs that belongs to the manager and must not be freed.

[element-type UDisksModuleIfaceSetupFunc][transfer full]


udisks_module_manager_get_drive_object_iface_infos ()

GList *
udisks_module_manager_get_drive_object_iface_infos
                               (UDisksModuleManager *manager);

Returns a list of drive object interface info structs that can be plugged in UDisksLinuxDriveObject instances. See UDisksModuleIfaceSetupFunc for details.

Parameters

manager

A UDisksModuleManager instance.

 

Returns

A list of UDisksModuleIfaceSetupFunc structs that belongs to the manager and must not be freed.

[element-type UDisksModuleIfaceSetupFunc][transfer full]


udisks_module_manager_get_module_object_new_funcs ()

GList *
udisks_module_manager_get_module_object_new_funcs
                               (UDisksModuleManager *manager);

Returns a list of all module object new functions. See UDisksModuleObjectNewFunc for details.

Parameters

manager

A UDisksModuleManager instance.

 

Returns

A list of UDisksModuleObjectNewFunc function pointers that belongs to the manager and must not be freed.

[element-type UDisksModuleObjectNewFunc][transfer full]


udisks_module_manager_get_new_manager_iface_funcs ()

GList *
udisks_module_manager_get_new_manager_iface_funcs
                               (UDisksModuleManager *manager);

Returns a list of all module new manager interface functions. See UDisksModuleNewManagerIfaceFunc for details.

Parameters

manager

A UDisksModuleManager instance.

 

Returns

A list of UDisksModuleNewManagerIfaceFunc function pointers that belongs to the manager and must not be freed.

[element-type UDisksModuleNewManagerIfaceFunc][transfer full]


udisks_module_object_process_uevent ()

gboolean
udisks_module_object_process_uevent (UDisksModuleObject *object,
                                     const gchar *action,
                                     UDisksLinuxDevice *device);

Virtual method that processes the uevent and updates all information on interfaces on object .

See UDisksModuleObjectNewFunc for detailed information on how to work with the events.

Parameters

object

A UDisksModuleObject.

 

action

Uevent action, common values are "add", "changed" and "removed" or NULL

 

device

A UDisksLinuxDevice device object or NULL if the device hasn't changed.

 

Returns

FALSE if the object should be unexported and removed, TRUE if the object has processed the information successfully and should be kept around.


udisks_module_object_housekeeping ()

gboolean
udisks_module_object_housekeeping (UDisksModuleObject *object,
                                   guint secs_since_last,
                                   GCancellable *cancellable,
                                   GError **error);

Virtual method that is called periodically (every ten minutes or so) to perform housekeeping tasks such as refreshing ATA SMART data.

The function runs in a dedicated thread and is allowed to perform blocking I/O.

Long-running tasks should periodically check cancellable to see if they have been cancelled.

Parameters

object

A UDisksModuleObject.

 

secs_since_last

Number of seconds since the last housekeeping or 0 if the first housekeeping ever.

 

cancellable

A GCancellable or NULL.

 

error

Return location for error or NULL.

 

Returns

TRUE if the operation succeeded, FALSE if error is set.

Types and Values

UDisksModuleManager

typedef struct _UDisksModuleManager UDisksModuleManager;

The UDisksModuleManager structure contains only private data and should only be accessed using the provided API.


UDisksModuleInterfaceInfo

typedef struct {
  UDisksObjectHasInterfaceFunc has_func;
  UDisksObjectConnectInterfaceFunc connect_func;
  UDisksObjectUpdateInterfaceFunc update_func;
  GType skeleton_type;
} UDisksModuleInterfaceInfo;

Structure containing interface setup functions used by modules for exporting custom interfaces on existing block and drive objects.

Event processing is solely done by UDisksLinuxBlockObject and UDisksLinuxDriveObject themselves whose call the has_func , connect_func and update_func respectively as needed. Purpose of these member functions is to check whether the particular UDisksModuleInterfaceInfo record is applicable to the current device and construct a new GDBusInterface if so.

See UDisksObjectHasInterfaceFunc, UDisksObjectConnectInterfaceFunc and UDisksObjectUpdateInterfaceFunc for detailed description and return values.

Members

UDisksObjectHasInterfaceFunc has_func;

A UDisksObjectHasInterfaceFunc

 

UDisksObjectConnectInterfaceFunc connect_func;

A UDisksObjectConnectInterfaceFunc

 

UDisksObjectUpdateInterfaceFunc update_func;

A UDisksObjectUpdateInterfaceFunc

 

GType skeleton_type;

A GType of the instance that is created once has_func succeeds.

 

UDisksModuleObject

typedef struct _UDisksModuleObject UDisksModuleObject;

The UDisksModuleObject structure contains only private data and should only be accessed using the provided API.


struct UDisksModuleObjectIface

struct UDisksModuleObjectIface {
  GTypeInterface parent_iface;

  gboolean (*process_uevent) (UDisksModuleObject  *object,
                              const gchar         *action,
                              UDisksLinuxDevice   *device);

  gboolean (*housekeeping) (UDisksModuleObject  *object,
                            guint                secs_since_last,
                            GCancellable        *cancellable,
                            GError             **error);
};