~behda/+junk/udisks2.original

« back to all changes in this revision

Viewing changes to src/udiskslinuxmdraidobject.c

  • Committer: behda
  • Date: 2014-05-24 15:15:11 UTC
  • Revision ID: pauvitk@gmail.com-20140524151511-3vtr0uubjewx3z2j
Initial commit of source code and Debian packaging.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
 
2
 *
 
3
 * Copyright (C) 2007-2010 David Zeuthen <zeuthen@gmail.com>
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or modify
 
6
 * it under the terms of the GNU General Public License as published by
 
7
 * the Free Software Foundation; either version 2 of the License, or
 
8
 * (at your option) any later version.
 
9
 *
 
10
 * This program is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 * GNU General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU General Public License
 
16
 * along with this program; if not, write to the Free Software
 
17
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
18
 *
 
19
 */
 
20
 
 
21
#include "config.h"
 
22
#include <glib/gi18n-lib.h>
 
23
 
 
24
#include <string.h>
 
25
#include <stdlib.h>
 
26
#include <stdio.h>
 
27
 
 
28
#include "udiskslogging.h"
 
29
#include "udisksdaemon.h"
 
30
#include "udisksdaemonutil.h"
 
31
#include "udiskslinuxprovider.h"
 
32
#include "udiskslinuxmdraidobject.h"
 
33
#include "udiskslinuxmdraid.h"
 
34
#include "udiskslinuxblockobject.h"
 
35
#include "udiskslinuxdevice.h"
 
36
 
 
37
/**
 
38
 * SECTION:udiskslinuxmdraidobject
 
39
 * @title: UDisksLinuxMDRaidObject
 
40
 * @short_description: Object representing a Linux Software RAID array
 
41
 *
 
42
 * Object corresponding to a Linux Software RAID array.
 
43
 */
 
44
 
 
45
typedef struct _UDisksLinuxMDRaidObjectClass   UDisksLinuxMDRaidObjectClass;
 
46
 
 
47
/**
 
48
 * UDisksLinuxMDRaidObject:
 
49
 *
 
50
 * The #UDisksLinuxMDRaidObject structure contains only private data and
 
51
 * should only be accessed using the provided API.
 
52
 */
 
53
struct _UDisksLinuxMDRaidObject
 
54
{
 
55
  UDisksObjectSkeleton parent_instance;
 
56
 
 
57
  UDisksDaemon *daemon;
 
58
 
 
59
  /* The UUID for the object */
 
60
  gchar *uuid;
 
61
 
 
62
  /* The UDisksLinuxDevice for the RAID device (e.g. /dev/md0), if any */
 
63
  UDisksLinuxDevice *raid_device;
 
64
 
 
65
  /* list of UDisksLinuxDevice objects for detected member devices */
 
66
  GList *member_devices;
 
67
 
 
68
  /* interfaces */
 
69
  UDisksMDRaid *iface_mdraid;
 
70
 
 
71
  /* watches for sysfs attr changes */
 
72
  GSource *sync_action_source;
 
73
  GSource *degraded_source;
 
74
};
 
75
 
 
76
struct _UDisksLinuxMDRaidObjectClass
 
77
{
 
78
  UDisksObjectSkeletonClass parent_class;
 
79
};
 
80
 
 
81
enum
 
82
{
 
83
  PROP_0,
 
84
  PROP_UUID,
 
85
  PROP_DAEMON,
 
86
};
 
87
 
 
88
static void
 
89
remove_watches (UDisksLinuxMDRaidObject *object)
 
90
{
 
91
  if (object->sync_action_source != NULL)
 
92
    {
 
93
      g_source_destroy (object->sync_action_source);
 
94
      object->sync_action_source = NULL;
 
95
    }
 
96
  if (object->degraded_source != NULL)
 
97
    {
 
98
      g_source_destroy (object->degraded_source);
 
99
      object->degraded_source = NULL;
 
100
    }
 
101
}
 
102
 
 
103
G_DEFINE_TYPE (UDisksLinuxMDRaidObject, udisks_linux_mdraid_object, UDISKS_TYPE_OBJECT_SKELETON);
 
104
 
 
105
static void
 
106
udisks_linux_mdraid_object_finalize (GObject *_object)
 
107
{
 
108
  UDisksLinuxMDRaidObject *object = UDISKS_LINUX_MDRAID_OBJECT (_object);
 
109
 
 
110
  /* note: we don't hold a ref to object->daemon */
 
111
 
 
112
  remove_watches (object);
 
113
 
 
114
  if (object->iface_mdraid != NULL)
 
115
    g_object_unref (object->iface_mdraid);
 
116
 
 
117
  g_clear_object (&object->raid_device);
 
118
 
 
119
  g_list_foreach (object->member_devices, (GFunc) g_object_unref, NULL);
 
120
  g_list_free (object->member_devices);
 
121
 
 
122
  g_free (object->uuid);
 
123
 
 
124
  if (G_OBJECT_CLASS (udisks_linux_mdraid_object_parent_class)->finalize != NULL)
 
125
    G_OBJECT_CLASS (udisks_linux_mdraid_object_parent_class)->finalize (_object);
 
126
}
 
127
 
 
128
static void
 
129
udisks_linux_mdraid_object_get_property (GObject    *__object,
 
130
                                         guint       prop_id,
 
131
                                         GValue     *value,
 
132
                                         GParamSpec *pspec)
 
133
{
 
134
  UDisksLinuxMDRaidObject *object = UDISKS_LINUX_MDRAID_OBJECT (__object);
 
135
 
 
136
  switch (prop_id)
 
137
    {
 
138
    case PROP_DAEMON:
 
139
      g_value_set_object (value, udisks_linux_mdraid_object_get_daemon (object));
 
140
      break;
 
141
 
 
142
    default:
 
143
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
144
      break;
 
145
    }
 
146
}
 
147
 
 
148
static void
 
149
udisks_linux_mdraid_object_set_property (GObject      *__object,
 
150
                                         guint         prop_id,
 
151
                                         const GValue *value,
 
152
                                         GParamSpec   *pspec)
 
153
{
 
154
  UDisksLinuxMDRaidObject *object = UDISKS_LINUX_MDRAID_OBJECT (__object);
 
155
 
 
156
  switch (prop_id)
 
157
    {
 
158
    case PROP_DAEMON:
 
159
      g_assert (object->daemon == NULL);
 
160
      /* we don't take a reference to the daemon */
 
161
      object->daemon = g_value_get_object (value);
 
162
      break;
 
163
 
 
164
    case PROP_UUID:
 
165
      object->uuid = g_value_dup_string (value);
 
166
      break;
 
167
 
 
168
    default:
 
169
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
170
      break;
 
171
    }
 
172
}
 
173
 
 
174
 
 
175
static void
 
176
udisks_linux_mdraid_object_init (UDisksLinuxMDRaidObject *object)
 
177
{
 
178
}
 
179
 
 
180
static void
 
181
strip_and_replace_with_uscore (gchar *s)
 
182
{
 
183
  guint n;
 
184
 
 
185
  if (s == NULL)
 
186
    goto out;
 
187
 
 
188
  g_strstrip (s);
 
189
 
 
190
  for (n = 0; s != NULL && s[n] != '\0'; n++)
 
191
    {
 
192
      if (s[n] == ' ' || s[n] == '-' || s[n] == ':')
 
193
        s[n] = '_';
 
194
    }
 
195
 
 
196
 out:
 
197
  ;
 
198
}
 
199
 
 
200
static void
 
201
udisks_linux_mdraid_object_constructed (GObject *_object)
 
202
{
 
203
  UDisksLinuxMDRaidObject *object = UDISKS_LINUX_MDRAID_OBJECT (_object);
 
204
  gchar *uuid;
 
205
  gchar *s;
 
206
 
 
207
  /* compute the object path */
 
208
  uuid = g_strdup (object->uuid);
 
209
  strip_and_replace_with_uscore (uuid);
 
210
  s = g_strdup_printf ("/org/freedesktop/UDisks2/mdraid/%s", uuid);
 
211
  g_free (uuid);
 
212
  g_dbus_object_skeleton_set_object_path (G_DBUS_OBJECT_SKELETON (object), s);
 
213
  g_free (s);
 
214
 
 
215
  if (G_OBJECT_CLASS (udisks_linux_mdraid_object_parent_class)->constructed != NULL)
 
216
    G_OBJECT_CLASS (udisks_linux_mdraid_object_parent_class)->constructed (_object);
 
217
}
 
218
 
 
219
static void
 
220
udisks_linux_mdraid_object_class_init (UDisksLinuxMDRaidObjectClass *klass)
 
221
{
 
222
  GObjectClass *gobject_class;
 
223
 
 
224
  gobject_class = G_OBJECT_CLASS (klass);
 
225
  gobject_class->finalize     = udisks_linux_mdraid_object_finalize;
 
226
  gobject_class->constructed  = udisks_linux_mdraid_object_constructed;
 
227
  gobject_class->set_property = udisks_linux_mdraid_object_set_property;
 
228
  gobject_class->get_property = udisks_linux_mdraid_object_get_property;
 
229
 
 
230
  /**
 
231
   * UDisksLinuxMDRaidObject:daemon:
 
232
   *
 
233
   * The #UDisksDaemon the object is for.
 
234
   */
 
235
  g_object_class_install_property (gobject_class,
 
236
                                   PROP_DAEMON,
 
237
                                   g_param_spec_object ("daemon",
 
238
                                                        "Daemon",
 
239
                                                        "The daemon the object is for",
 
240
                                                        UDISKS_TYPE_DAEMON,
 
241
                                                        G_PARAM_READABLE |
 
242
                                                        G_PARAM_WRITABLE |
 
243
                                                        G_PARAM_CONSTRUCT_ONLY |
 
244
                                                        G_PARAM_STATIC_STRINGS));
 
245
 
 
246
  /**
 
247
   * UDisksLinuxMDRaidObject:uuid:
 
248
   *
 
249
   * The UUID for the array.
 
250
   */
 
251
  g_object_class_install_property (gobject_class,
 
252
                                   PROP_UUID,
 
253
                                   g_param_spec_string ("uuid",
 
254
                                                        "UUID",
 
255
                                                        "The UUID for the array",
 
256
                                                        NULL,
 
257
                                                        G_PARAM_WRITABLE |
 
258
                                                        G_PARAM_CONSTRUCT_ONLY |
 
259
                                                        G_PARAM_STATIC_STRINGS));
 
260
}
 
261
 
 
262
/**
 
263
 * udisks_linux_mdraid_object_new:
 
264
 * @daemon: A #UDisksDaemon.
 
265
 * @uuid: The UUID for the array.
 
266
 *
 
267
 * Create a new MDRaid object.
 
268
 *
 
269
 * Returns: A #UDisksLinuxMDRaidObject object. Free with g_object_unref().
 
270
 */
 
271
UDisksLinuxMDRaidObject *
 
272
udisks_linux_mdraid_object_new (UDisksDaemon  *daemon,
 
273
                                const gchar   *uuid)
 
274
{
 
275
  g_return_val_if_fail (UDISKS_IS_DAEMON (daemon), NULL);
 
276
  g_return_val_if_fail (uuid != NULL, NULL);
 
277
  return UDISKS_LINUX_MDRAID_OBJECT (g_object_new (UDISKS_TYPE_LINUX_MDRAID_OBJECT,
 
278
                                                   "daemon", daemon,
 
279
                                                   "uuid", uuid,
 
280
                                                   NULL));
 
281
}
 
282
 
 
283
/**
 
284
 * udisks_linux_mdraid_object_get_daemon:
 
285
 * @object: A #UDisksLinuxMDRaidObject.
 
286
 *
 
287
 * Gets the daemon used by @object.
 
288
 *
 
289
 * Returns: A #UDisksDaemon. Do not free, the object is owned by @object.
 
290
 */
 
291
UDisksDaemon *
 
292
udisks_linux_mdraid_object_get_daemon (UDisksLinuxMDRaidObject *object)
 
293
{
 
294
  g_return_val_if_fail (UDISKS_IS_LINUX_MDRAID_OBJECT (object), NULL);
 
295
  return object->daemon;
 
296
}
 
297
 
 
298
/**
 
299
 * udisks_linux_mdraid_object_get_members:
 
300
 * @object: A #UDisksLinuxMDRaidObject.
 
301
 *
 
302
 * Gets the current #UDisksLinuxDevice objects for the RAID members associated with @object.
 
303
 *
 
304
 * Returns: A list of #UDisksLinuxDevice objects. Free each element with
 
305
 * g_object_unref(), then free the list with g_list_free().
 
306
 */
 
307
GList *
 
308
udisks_linux_mdraid_object_get_members (UDisksLinuxMDRaidObject *object)
 
309
{
 
310
  GList *ret = NULL;
 
311
 
 
312
  g_return_val_if_fail (UDISKS_IS_LINUX_MDRAID_OBJECT (object), NULL);
 
313
 
 
314
  ret = g_list_copy (object->member_devices);
 
315
  g_list_foreach (ret, (GFunc) g_object_ref, NULL);
 
316
 
 
317
  return ret;
 
318
}
 
319
 
 
320
/**
 
321
 * udisks_linux_mdraid_object_get_device:
 
322
 * @object: A #UDisksLinuxMDRaidObject.
 
323
 *
 
324
 * Gets the current #UDisksLinuxDevice object for the RAID device
 
325
 * (e.g. /dev/md0) associated with @object, if any.
 
326
 *
 
327
 * Returns: (transfer full): A #UDisksLinuxDevice or %NULL. Free with g_object_unref().
 
328
 */
 
329
UDisksLinuxDevice *
 
330
udisks_linux_mdraid_object_get_device (UDisksLinuxMDRaidObject   *object)
 
331
{
 
332
  UDisksLinuxDevice *ret = NULL;
 
333
 
 
334
  g_return_val_if_fail (UDISKS_IS_LINUX_MDRAID_OBJECT (object), NULL);
 
335
 
 
336
  ret = object->raid_device != NULL ? g_object_ref (object->raid_device) : NULL;
 
337
 
 
338
  return ret;
 
339
}
 
340
 
 
341
/* ---------------------------------------------------------------------------------------------------- */
 
342
 
 
343
typedef gboolean (*HasInterfaceFunc)    (UDisksLinuxMDRaidObject     *object);
 
344
typedef void     (*ConnectInterfaceFunc) (UDisksLinuxMDRaidObject    *object);
 
345
typedef gboolean (*UpdateInterfaceFunc) (UDisksLinuxMDRaidObject     *object,
 
346
                                         const gchar    *uevent_action,
 
347
                                         GDBusInterface *interface);
 
348
 
 
349
static gboolean
 
350
update_iface (UDisksLinuxMDRaidObject   *object,
 
351
              const gchar              *uevent_action,
 
352
              HasInterfaceFunc          has_func,
 
353
              ConnectInterfaceFunc      connect_func,
 
354
              UpdateInterfaceFunc       update_func,
 
355
              GType                     skeleton_type,
 
356
              gpointer                  _interface_pointer)
 
357
{
 
358
  gboolean ret = FALSE;
 
359
  gboolean has;
 
360
  gboolean add;
 
361
  GDBusInterface **interface_pointer = _interface_pointer;
 
362
 
 
363
  g_return_val_if_fail (object != NULL, FALSE);
 
364
  g_return_val_if_fail (has_func != NULL, FALSE);
 
365
  g_return_val_if_fail (update_func != NULL, FALSE);
 
366
  g_return_val_if_fail (g_type_is_a (skeleton_type, G_TYPE_OBJECT), FALSE);
 
367
  g_return_val_if_fail (g_type_is_a (skeleton_type, G_TYPE_DBUS_INTERFACE), FALSE);
 
368
  g_return_val_if_fail (interface_pointer != NULL, FALSE);
 
369
  g_return_val_if_fail (*interface_pointer == NULL || G_IS_DBUS_INTERFACE (*interface_pointer), FALSE);
 
370
 
 
371
  add = FALSE;
 
372
  has = has_func (object);
 
373
  if (*interface_pointer == NULL)
 
374
    {
 
375
      if (has)
 
376
        {
 
377
          *interface_pointer = g_object_new (skeleton_type, NULL);
 
378
          if (connect_func != NULL)
 
379
            connect_func (object);
 
380
          add = TRUE;
 
381
        }
 
382
    }
 
383
  else
 
384
    {
 
385
      if (!has)
 
386
        {
 
387
          g_dbus_object_skeleton_remove_interface (G_DBUS_OBJECT_SKELETON (object),
 
388
                                                   G_DBUS_INTERFACE_SKELETON (*interface_pointer));
 
389
          g_object_unref (*interface_pointer);
 
390
          *interface_pointer = NULL;
 
391
        }
 
392
    }
 
393
 
 
394
  if (*interface_pointer != NULL)
 
395
    {
 
396
      if (update_func (object, uevent_action, G_DBUS_INTERFACE (*interface_pointer)))
 
397
        ret = TRUE;
 
398
      if (add)
 
399
        g_dbus_object_skeleton_add_interface (G_DBUS_OBJECT_SKELETON (object),
 
400
                                              G_DBUS_INTERFACE_SKELETON (*interface_pointer));
 
401
    }
 
402
 
 
403
  return ret;
 
404
}
 
405
 
 
406
/* ---------------------------------------------------------------------------------------------------- */
 
407
 
 
408
static gboolean
 
409
mdraid_check (UDisksLinuxMDRaidObject *object)
 
410
{
 
411
  return TRUE;
 
412
}
 
413
 
 
414
static void
 
415
mdraid_connect (UDisksLinuxMDRaidObject *object)
 
416
{
 
417
}
 
418
 
 
419
static gboolean
 
420
mdraid_update (UDisksLinuxMDRaidObject  *object,
 
421
               const gchar              *uevent_action,
 
422
               GDBusInterface           *_iface)
 
423
{
 
424
  return udisks_linux_mdraid_update (UDISKS_LINUX_MDRAID (object->iface_mdraid), object);
 
425
}
 
426
 
 
427
/* ---------------------------------------------------------------------------------------------------- */
 
428
 
 
429
static GList *
 
430
find_link_for_sysfs_path_for_member (UDisksLinuxMDRaidObject *object,
 
431
                                     const gchar            *sysfs_path)
 
432
{
 
433
  GList *l;
 
434
  GList *ret;
 
435
  ret = NULL;
 
436
 
 
437
  for (l = object->member_devices; l != NULL; l = l->next)
 
438
    {
 
439
      UDisksLinuxDevice *device = UDISKS_LINUX_DEVICE (l->data);
 
440
      if (g_strcmp0 (g_udev_device_get_sysfs_path (device->udev_device), sysfs_path) == 0)
 
441
        {
 
442
          ret = l;
 
443
          goto out;
 
444
        }
 
445
    }
 
446
 out:
 
447
  return ret;
 
448
}
 
449
 
 
450
/* ---------------------------------------------------------------------------------------------------- */
 
451
 
 
452
static GSource *
 
453
watch_attr (UDisksLinuxDevice *device,
 
454
            const gchar       *attr,
 
455
            GSourceFunc        callback,
 
456
            gpointer           user_data)
 
457
{
 
458
  GError *error = NULL;
 
459
  gchar *path = NULL;
 
460
  GIOChannel *channel = NULL;
 
461
  GSource *ret = NULL;;
 
462
 
 
463
  g_return_val_if_fail (UDISKS_IS_LINUX_DEVICE (device), NULL);
 
464
 
 
465
  path = g_strdup_printf ("%s/%s", g_udev_device_get_sysfs_path (device->udev_device), attr);
 
466
  channel = g_io_channel_new_file (path, "r", &error);
 
467
  if (channel != NULL)
 
468
    {
 
469
      ret = g_io_create_watch (channel, G_IO_ERR);
 
470
      g_source_set_callback (ret, callback, user_data, NULL);
 
471
      g_source_attach (ret, g_main_context_get_thread_default ());
 
472
      g_source_unref (ret);
 
473
      g_io_channel_unref (channel); /* the keeps a reference to this object */
 
474
    }
 
475
  else
 
476
    {
 
477
      udisks_warning ("Error creating watch for file %s: %s (%s, %d)",
 
478
                      path, error->message, g_quark_to_string (error->domain), error->code);
 
479
      g_clear_error (&error);
 
480
    }
 
481
  g_free (path);
 
482
 
 
483
  return ret;
 
484
}
 
485
 
 
486
/* ----------------------------------------------------------------------------------------------------  */
 
487
 
 
488
static gboolean
 
489
attr_changed (GIOChannel   *channel,
 
490
              GIOCondition  cond,
 
491
              gpointer      user_data)
 
492
{
 
493
  UDisksLinuxMDRaidObject *object = UDISKS_LINUX_MDRAID_OBJECT (user_data);
 
494
  gboolean bail = FALSE;
 
495
  GError *error = NULL;
 
496
  gchar *str = NULL;
 
497
  gsize len = 0;
 
498
 
 
499
  if (cond & ~G_IO_ERR)
 
500
    goto out;
 
501
 
 
502
  if (g_io_channel_seek_position (channel, 0, G_SEEK_SET, &error) != G_IO_STATUS_NORMAL)
 
503
    {
 
504
      udisks_debug ("Error seeking in channel (uuid %s): %s (%s, %d)",
 
505
                    object->uuid, error->message, g_quark_to_string (error->domain), error->code);
 
506
      g_clear_error (&error);
 
507
      bail = TRUE;
 
508
      goto out;
 
509
    }
 
510
 
 
511
  if (g_io_channel_read_to_end (channel, &str, &len, &error) != G_IO_STATUS_NORMAL)
 
512
    {
 
513
      udisks_debug ("Error reading (uuid %s): %s (%s, %d)",
 
514
                    object->uuid, error->message, g_quark_to_string (error->domain), error->code);
 
515
      g_clear_error (&error);
 
516
      bail = TRUE;
 
517
      goto out;
 
518
    }
 
519
 
 
520
  g_free (str);
 
521
 
 
522
  /* synthesize uevent */
 
523
  if (object->raid_device != NULL)
 
524
    udisks_linux_mdraid_object_uevent (object, "change", object->raid_device, FALSE);
 
525
 
 
526
 out:
 
527
  if (bail)
 
528
    remove_watches (object);
 
529
  return TRUE; /* keep event source around */
 
530
}
 
531
 
 
532
/* ---------------------------------------------------------------------------------------------------- */
 
533
 
 
534
/* The md(4) driver does not use the usual uevent 'change' mechanism
 
535
 * for notification - instead it excepts user-space to select(2)-ish
 
536
 * on a fd for the sysfs attribute. Annoying. See
 
537
 *
 
538
 *  http://www.kernel.org/doc/Documentation/md.txt
 
539
 *
 
540
 * for more details.
 
541
 */
 
542
 
 
543
static void
 
544
raid_device_added (UDisksLinuxMDRaidObject *object,
 
545
                   UDisksLinuxDevice       *device)
 
546
{
 
547
  g_assert (object->sync_action_source == NULL);
 
548
  g_assert (object->degraded_source == NULL);
 
549
 
 
550
  /* udisks_debug ("start watching %s", g_udev_device_get_sysfs_path (device->udev_device)); */
 
551
  object->sync_action_source = watch_attr (device,
 
552
                                           "md/sync_action",
 
553
                                           (GSourceFunc) attr_changed,
 
554
                                           object);
 
555
  object->degraded_source = watch_attr (device,
 
556
                                        "md/degraded",
 
557
                                        (GSourceFunc) attr_changed,
 
558
                                        object);
 
559
}
 
560
 
 
561
static void
 
562
raid_device_removed (UDisksLinuxMDRaidObject *object,
 
563
                     UDisksLinuxDevice       *device)
 
564
{
 
565
  /* udisks_debug ("stop watching %s", g_udev_device_get_sysfs_path (device->udev_device)); */
 
566
  remove_watches (object);
 
567
}
 
568
 
 
569
/* ---------------------------------------------------------------------------------------------------- */
 
570
 
 
571
/**
 
572
 * udisks_linux_mdraid_object_uevent:
 
573
 * @object: A #UDisksLinuxMDRaidObject.
 
574
 * @action: Uevent action or %NULL
 
575
 * @device: A #UDisksLinuxDevice device object or %NULL if the device hasn't changed.
 
576
 * @is_member: %TRUE if @device is a member, %FALSE if it's the raid device.
 
577
 *
 
578
 * Updates all information on interfaces on @mdraid.
 
579
 */
 
580
void
 
581
udisks_linux_mdraid_object_uevent (UDisksLinuxMDRaidObject *object,
 
582
                                   const gchar             *action,
 
583
                                   UDisksLinuxDevice       *device,
 
584
                                   gboolean                 is_member)
 
585
{
 
586
  gboolean conf_changed = FALSE;
 
587
 
 
588
  g_return_if_fail (UDISKS_IS_LINUX_MDRAID_OBJECT (object));
 
589
  g_return_if_fail (UDISKS_IS_LINUX_DEVICE (device));
 
590
 
 
591
  /* udisks_debug ("is_member=%d for uuid %s and device %s", is_member, object->uuid, g_udev_device_get_device_file (device->udev_device)); */
 
592
 
 
593
  if (is_member)
 
594
    {
 
595
      GList *link = NULL;
 
596
      link = NULL;
 
597
      if (device != NULL)
 
598
        link = find_link_for_sysfs_path_for_member (object, g_udev_device_get_sysfs_path (device->udev_device));
 
599
 
 
600
      if (g_strcmp0 (action, "remove") == 0)
 
601
        {
 
602
          if (link != NULL)
 
603
            {
 
604
              g_object_unref (UDISKS_LINUX_DEVICE (link->data));
 
605
              object->member_devices = g_list_delete_link (object->member_devices, link);
 
606
            }
 
607
          else
 
608
            {
 
609
              udisks_warning ("MDRaid with UUID %s doesn't have member device with sysfs path %s on remove event",
 
610
                              object->uuid,
 
611
                              g_udev_device_get_sysfs_path (device->udev_device));
 
612
            }
 
613
        }
 
614
      else
 
615
        {
 
616
          if (link != NULL)
 
617
            {
 
618
              if (device != link->data)
 
619
                {
 
620
                  g_object_unref (UDISKS_LINUX_DEVICE (link->data));
 
621
                  link->data = g_object_ref (device);
 
622
                }
 
623
            }
 
624
          else
 
625
            {
 
626
              if (device != NULL)
 
627
                {
 
628
                  object->member_devices = g_list_append (object->member_devices, g_object_ref (device));
 
629
                }
 
630
            }
 
631
        }
 
632
    }
 
633
  else
 
634
    {
 
635
      /* Skip partitions of raid devices */
 
636
      if (g_strcmp0 (g_udev_device_get_devtype (device->udev_device), "disk") != 0)
 
637
        goto out;
 
638
 
 
639
      if (g_strcmp0 (action, "remove") == 0)
 
640
        {
 
641
          if (object->raid_device != NULL)
 
642
            if (g_strcmp0 (g_udev_device_get_sysfs_path (object->raid_device->udev_device),
 
643
                           g_udev_device_get_sysfs_path (device->udev_device)) == 0)
 
644
              {
 
645
                g_clear_object (&object->raid_device);
 
646
                raid_device_removed (object, object->raid_device);
 
647
              }
 
648
            else
 
649
              {
 
650
                udisks_warning ("MDRaid with UUID %s doesn't have raid device with sysfs path %s on remove event (it has %s)",
 
651
                                object->uuid,
 
652
                                g_udev_device_get_sysfs_path (device->udev_device),
 
653
                                g_udev_device_get_sysfs_path (object->raid_device->udev_device));
 
654
              }
 
655
          else
 
656
            {
 
657
              udisks_warning ("MDRaid with UUID %s doesn't have raid device with sysfs path %s on remove event",
 
658
                              object->uuid,
 
659
                              g_udev_device_get_sysfs_path (device->udev_device));
 
660
            }
 
661
        }
 
662
      else
 
663
        {
 
664
          if (object->raid_device == NULL)
 
665
            {
 
666
              object->raid_device = g_object_ref (device);
 
667
              raid_device_added (object, object->raid_device);
 
668
            }
 
669
          else
 
670
            {
 
671
              if (device != object->raid_device)
 
672
                {
 
673
                  g_clear_object (&object->raid_device);
 
674
                  object->raid_device = g_object_ref (device);
 
675
                }
 
676
            }
 
677
        }
 
678
    }
 
679
 
 
680
  /* if we don't have any devices, no point in updating (we should get nuked soon anyway) */
 
681
  if (udisks_linux_mdraid_object_have_devices (object))
 
682
    {
 
683
      conf_changed = FALSE;
 
684
      conf_changed |= update_iface (object, action, mdraid_check, mdraid_connect, mdraid_update,
 
685
                                    UDISKS_TYPE_LINUX_MDRAID, &object->iface_mdraid);
 
686
    }
 
687
 out:
 
688
  ;
 
689
}
 
690
 
 
691
/* ---------------------------------------------------------------------------------------------------- */
 
692
 
 
693
/**
 
694
 * udisks_linux_mdraid_object_have_devices:
 
695
 * @object: A #UDisksLinuxMDRaidObject.
 
696
 *
 
697
 * Checks if there are any devices associated with @object at
 
698
 * all. This includes both member devices and the raid device.
 
699
 *
 
700
 * Returns: %TRUE if at least one device is associated with @object, %FALSE otherwise.
 
701
 */
 
702
gboolean
 
703
udisks_linux_mdraid_object_have_devices (UDisksLinuxMDRaidObject   *object)
 
704
{
 
705
  g_return_val_if_fail (UDISKS_IS_LINUX_MDRAID_OBJECT (object), FALSE);
 
706
 
 
707
  return g_list_length (object->member_devices) > 0 || object->raid_device != NULL;
 
708
}
 
709
 
 
710
/**
 
711
 * udisks_linux_mdraid_object_get_uuid:
 
712
 * @object: A #UDisksLinuxMDRaidObject.
 
713
 *
 
714
 * Gets the UUID for @object.
 
715
 *
 
716
 * Returns: (transfer none): The UUID for object. Do not free, the string belongs to @object.
 
717
 */
 
718
const gchar *
 
719
udisks_linux_mdraid_object_get_uuid (UDisksLinuxMDRaidObject *object)
 
720
{
 
721
  g_return_val_if_fail (UDISKS_IS_LINUX_MDRAID_OBJECT (object), NULL);
 
722
  return object->uuid;
 
723
}
 
724
 
 
725