xref: /openbmc/qemu/migration/options.c (revision 77608706459bd197e25ac1ef54591b9f8a0b46f8)
11f0776f1SJuan Quintela /*
21f0776f1SJuan Quintela  * QEMU migration capabilities
31f0776f1SJuan Quintela  *
41f0776f1SJuan Quintela  * Copyright (c) 2012-2023 Red Hat Inc
51f0776f1SJuan Quintela  *
61f0776f1SJuan Quintela  * Authors:
71f0776f1SJuan Quintela  *   Orit Wasserman <owasserm@redhat.com>
81f0776f1SJuan Quintela  *   Juan Quintela <quintela@redhat.com>
91f0776f1SJuan Quintela  *
101f0776f1SJuan Quintela  * This work is licensed under the terms of the GNU GPL, version 2 or later.
111f0776f1SJuan Quintela  * See the COPYING file in the top-level directory.
121f0776f1SJuan Quintela  */
131f0776f1SJuan Quintela 
141f0776f1SJuan Quintela #include "qemu/osdep.h"
15*77608706SJuan Quintela #include "qapi/error.h"
16*77608706SJuan Quintela #include "sysemu/runstate.h"
171f0776f1SJuan Quintela #include "migration.h"
18*77608706SJuan Quintela #include "ram.h"
191f0776f1SJuan Quintela #include "options.h"
201f0776f1SJuan Quintela 
211f0776f1SJuan Quintela bool migrate_auto_converge(void)
221f0776f1SJuan Quintela {
231f0776f1SJuan Quintela     MigrationState *s;
241f0776f1SJuan Quintela 
251f0776f1SJuan Quintela     s = migrate_get_current();
261f0776f1SJuan Quintela 
271f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_AUTO_CONVERGE];
281f0776f1SJuan Quintela }
291f0776f1SJuan Quintela 
301f0776f1SJuan Quintela bool migrate_background_snapshot(void)
311f0776f1SJuan Quintela {
321f0776f1SJuan Quintela     MigrationState *s;
331f0776f1SJuan Quintela 
341f0776f1SJuan Quintela     s = migrate_get_current();
351f0776f1SJuan Quintela 
361f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT];
371f0776f1SJuan Quintela }
381f0776f1SJuan Quintela 
399d4b1e5fSJuan Quintela bool migrate_block(void)
409d4b1e5fSJuan Quintela {
419d4b1e5fSJuan Quintela     MigrationState *s;
429d4b1e5fSJuan Quintela 
439d4b1e5fSJuan Quintela     s = migrate_get_current();
449d4b1e5fSJuan Quintela 
459d4b1e5fSJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_BLOCK];
469d4b1e5fSJuan Quintela }
479d4b1e5fSJuan Quintela 
485e804644SJuan Quintela bool migrate_colo(void)
495e804644SJuan Quintela {
505e804644SJuan Quintela     MigrationState *s = migrate_get_current();
515e804644SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_X_COLO];
525e804644SJuan Quintela }
535e804644SJuan Quintela 
54a7a94d14SJuan Quintela bool migrate_compress(void)
55a7a94d14SJuan Quintela {
56a7a94d14SJuan Quintela     MigrationState *s;
57a7a94d14SJuan Quintela 
58a7a94d14SJuan Quintela     s = migrate_get_current();
59a7a94d14SJuan Quintela 
60a7a94d14SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_COMPRESS];
61a7a94d14SJuan Quintela }
62a7a94d14SJuan Quintela 
631f0776f1SJuan Quintela bool migrate_dirty_bitmaps(void)
641f0776f1SJuan Quintela {
651f0776f1SJuan Quintela     MigrationState *s;
661f0776f1SJuan Quintela 
671f0776f1SJuan Quintela     s = migrate_get_current();
681f0776f1SJuan Quintela 
691f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_DIRTY_BITMAPS];
701f0776f1SJuan Quintela }
711f0776f1SJuan Quintela 
72b890902cSJuan Quintela bool migrate_events(void)
73b890902cSJuan Quintela {
74b890902cSJuan Quintela     MigrationState *s;
75b890902cSJuan Quintela 
76b890902cSJuan Quintela     s = migrate_get_current();
77b890902cSJuan Quintela 
78b890902cSJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_EVENTS];
79b890902cSJuan Quintela }
80b890902cSJuan Quintela 
811f0776f1SJuan Quintela bool migrate_ignore_shared(void)
821f0776f1SJuan Quintela {
831f0776f1SJuan Quintela     MigrationState *s;
841f0776f1SJuan Quintela 
851f0776f1SJuan Quintela     s = migrate_get_current();
861f0776f1SJuan Quintela 
871f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_X_IGNORE_SHARED];
881f0776f1SJuan Quintela }
891f0776f1SJuan Quintela 
901f0776f1SJuan Quintela bool migrate_late_block_activate(void)
911f0776f1SJuan Quintela {
921f0776f1SJuan Quintela     MigrationState *s;
931f0776f1SJuan Quintela 
941f0776f1SJuan Quintela     s = migrate_get_current();
951f0776f1SJuan Quintela 
961f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_LATE_BLOCK_ACTIVATE];
971f0776f1SJuan Quintela }
981f0776f1SJuan Quintela 
9951b07548SJuan Quintela bool migrate_multifd(void)
10051b07548SJuan Quintela {
10151b07548SJuan Quintela     MigrationState *s;
10251b07548SJuan Quintela 
10351b07548SJuan Quintela     s = migrate_get_current();
10451b07548SJuan Quintela 
10551b07548SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_MULTIFD];
10651b07548SJuan Quintela }
10751b07548SJuan Quintela 
1081f0776f1SJuan Quintela bool migrate_pause_before_switchover(void)
1091f0776f1SJuan Quintela {
1101f0776f1SJuan Quintela     MigrationState *s;
1111f0776f1SJuan Quintela 
1121f0776f1SJuan Quintela     s = migrate_get_current();
1131f0776f1SJuan Quintela 
1141f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_PAUSE_BEFORE_SWITCHOVER];
1151f0776f1SJuan Quintela }
1161f0776f1SJuan Quintela 
1171f0776f1SJuan Quintela bool migrate_postcopy_blocktime(void)
1181f0776f1SJuan Quintela {
1191f0776f1SJuan Quintela     MigrationState *s;
1201f0776f1SJuan Quintela 
1211f0776f1SJuan Quintela     s = migrate_get_current();
1221f0776f1SJuan Quintela 
1231f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_BLOCKTIME];
1241f0776f1SJuan Quintela }
1251f0776f1SJuan Quintela 
1261f0776f1SJuan Quintela bool migrate_postcopy_preempt(void)
1271f0776f1SJuan Quintela {
1281f0776f1SJuan Quintela     MigrationState *s;
1291f0776f1SJuan Quintela 
1301f0776f1SJuan Quintela     s = migrate_get_current();
1311f0776f1SJuan Quintela 
1321f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_PREEMPT];
1331f0776f1SJuan Quintela }
1341f0776f1SJuan Quintela 
1351f0776f1SJuan Quintela bool migrate_postcopy_ram(void)
1361f0776f1SJuan Quintela {
1371f0776f1SJuan Quintela     MigrationState *s;
1381f0776f1SJuan Quintela 
1391f0776f1SJuan Quintela     s = migrate_get_current();
1401f0776f1SJuan Quintela 
1411f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_RAM];
1421f0776f1SJuan Quintela }
1431f0776f1SJuan Quintela 
14417cba690SJuan Quintela bool migrate_rdma_pin_all(void)
14517cba690SJuan Quintela {
14617cba690SJuan Quintela     MigrationState *s = migrate_get_current();
14717cba690SJuan Quintela 
14817cba690SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_RDMA_PIN_ALL];
14917cba690SJuan Quintela }
15017cba690SJuan Quintela 
1511f0776f1SJuan Quintela bool migrate_release_ram(void)
1521f0776f1SJuan Quintela {
1531f0776f1SJuan Quintela     MigrationState *s;
1541f0776f1SJuan Quintela 
1551f0776f1SJuan Quintela     s = migrate_get_current();
1561f0776f1SJuan Quintela 
1571f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_RELEASE_RAM];
1581f0776f1SJuan Quintela }
1591f0776f1SJuan Quintela 
16038ad1110SJuan Quintela bool migrate_return_path(void)
16138ad1110SJuan Quintela {
16238ad1110SJuan Quintela     MigrationState *s;
16338ad1110SJuan Quintela 
16438ad1110SJuan Quintela     s = migrate_get_current();
16538ad1110SJuan Quintela 
16638ad1110SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_RETURN_PATH];
16738ad1110SJuan Quintela }
16838ad1110SJuan Quintela 
1691f0776f1SJuan Quintela bool migrate_validate_uuid(void)
1701f0776f1SJuan Quintela {
1711f0776f1SJuan Quintela     MigrationState *s;
1721f0776f1SJuan Quintela 
1731f0776f1SJuan Quintela     s = migrate_get_current();
1741f0776f1SJuan Quintela 
1751f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_VALIDATE_UUID];
1761f0776f1SJuan Quintela }
1771f0776f1SJuan Quintela 
17887dca0c9SJuan Quintela bool migrate_xbzrle(void)
17987dca0c9SJuan Quintela {
18087dca0c9SJuan Quintela     MigrationState *s;
18187dca0c9SJuan Quintela 
18287dca0c9SJuan Quintela     s = migrate_get_current();
18387dca0c9SJuan Quintela 
18487dca0c9SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_XBZRLE];
18587dca0c9SJuan Quintela }
18687dca0c9SJuan Quintela 
1871f0776f1SJuan Quintela bool migrate_zero_blocks(void)
1881f0776f1SJuan Quintela {
1891f0776f1SJuan Quintela     MigrationState *s;
1901f0776f1SJuan Quintela 
1911f0776f1SJuan Quintela     s = migrate_get_current();
1921f0776f1SJuan Quintela 
1931f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_ZERO_BLOCKS];
1941f0776f1SJuan Quintela }
195b4bc342cSJuan Quintela 
196b4bc342cSJuan Quintela bool migrate_zero_copy_send(void)
197b4bc342cSJuan Quintela {
198b4bc342cSJuan Quintela     MigrationState *s;
199b4bc342cSJuan Quintela 
200b4bc342cSJuan Quintela     s = migrate_get_current();
201b4bc342cSJuan Quintela 
202b4bc342cSJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_ZERO_COPY_SEND];
203b4bc342cSJuan Quintela }
204*77608706SJuan Quintela typedef enum WriteTrackingSupport {
205*77608706SJuan Quintela     WT_SUPPORT_UNKNOWN = 0,
206*77608706SJuan Quintela     WT_SUPPORT_ABSENT,
207*77608706SJuan Quintela     WT_SUPPORT_AVAILABLE,
208*77608706SJuan Quintela     WT_SUPPORT_COMPATIBLE
209*77608706SJuan Quintela } WriteTrackingSupport;
210*77608706SJuan Quintela 
211*77608706SJuan Quintela static
212*77608706SJuan Quintela WriteTrackingSupport migrate_query_write_tracking(void)
213*77608706SJuan Quintela {
214*77608706SJuan Quintela     /* Check if kernel supports required UFFD features */
215*77608706SJuan Quintela     if (!ram_write_tracking_available()) {
216*77608706SJuan Quintela         return WT_SUPPORT_ABSENT;
217*77608706SJuan Quintela     }
218*77608706SJuan Quintela     /*
219*77608706SJuan Quintela      * Check if current memory configuration is
220*77608706SJuan Quintela      * compatible with required UFFD features.
221*77608706SJuan Quintela      */
222*77608706SJuan Quintela     if (!ram_write_tracking_compatible()) {
223*77608706SJuan Quintela         return WT_SUPPORT_AVAILABLE;
224*77608706SJuan Quintela     }
225*77608706SJuan Quintela 
226*77608706SJuan Quintela     return WT_SUPPORT_COMPATIBLE;
227*77608706SJuan Quintela }
228*77608706SJuan Quintela 
229*77608706SJuan Quintela /* Migration capabilities set */
230*77608706SJuan Quintela struct MigrateCapsSet {
231*77608706SJuan Quintela     int size;                       /* Capability set size */
232*77608706SJuan Quintela     MigrationCapability caps[];     /* Variadic array of capabilities */
233*77608706SJuan Quintela };
234*77608706SJuan Quintela typedef struct MigrateCapsSet MigrateCapsSet;
235*77608706SJuan Quintela 
236*77608706SJuan Quintela /* Define and initialize MigrateCapsSet */
237*77608706SJuan Quintela #define INITIALIZE_MIGRATE_CAPS_SET(_name, ...)   \
238*77608706SJuan Quintela     MigrateCapsSet _name = {    \
239*77608706SJuan Quintela         .size = sizeof((int []) { __VA_ARGS__ }) / sizeof(int), \
240*77608706SJuan Quintela         .caps = { __VA_ARGS__ } \
241*77608706SJuan Quintela     }
242*77608706SJuan Quintela 
243*77608706SJuan Quintela /* Background-snapshot compatibility check list */
244*77608706SJuan Quintela static const
245*77608706SJuan Quintela INITIALIZE_MIGRATE_CAPS_SET(check_caps_background_snapshot,
246*77608706SJuan Quintela     MIGRATION_CAPABILITY_POSTCOPY_RAM,
247*77608706SJuan Quintela     MIGRATION_CAPABILITY_DIRTY_BITMAPS,
248*77608706SJuan Quintela     MIGRATION_CAPABILITY_POSTCOPY_BLOCKTIME,
249*77608706SJuan Quintela     MIGRATION_CAPABILITY_LATE_BLOCK_ACTIVATE,
250*77608706SJuan Quintela     MIGRATION_CAPABILITY_RETURN_PATH,
251*77608706SJuan Quintela     MIGRATION_CAPABILITY_MULTIFD,
252*77608706SJuan Quintela     MIGRATION_CAPABILITY_PAUSE_BEFORE_SWITCHOVER,
253*77608706SJuan Quintela     MIGRATION_CAPABILITY_AUTO_CONVERGE,
254*77608706SJuan Quintela     MIGRATION_CAPABILITY_RELEASE_RAM,
255*77608706SJuan Quintela     MIGRATION_CAPABILITY_RDMA_PIN_ALL,
256*77608706SJuan Quintela     MIGRATION_CAPABILITY_COMPRESS,
257*77608706SJuan Quintela     MIGRATION_CAPABILITY_XBZRLE,
258*77608706SJuan Quintela     MIGRATION_CAPABILITY_X_COLO,
259*77608706SJuan Quintela     MIGRATION_CAPABILITY_VALIDATE_UUID,
260*77608706SJuan Quintela     MIGRATION_CAPABILITY_ZERO_COPY_SEND);
261*77608706SJuan Quintela 
262*77608706SJuan Quintela /**
263*77608706SJuan Quintela  * @migration_caps_check - check capability compatibility
264*77608706SJuan Quintela  *
265*77608706SJuan Quintela  * @old_caps: old capability list
266*77608706SJuan Quintela  * @new_caps: new capability list
267*77608706SJuan Quintela  * @errp: set *errp if the check failed, with reason
268*77608706SJuan Quintela  *
269*77608706SJuan Quintela  * Returns true if check passed, otherwise false.
270*77608706SJuan Quintela  */
271*77608706SJuan Quintela bool migrate_caps_check(bool *old_caps, bool *new_caps, Error **errp)
272*77608706SJuan Quintela {
273*77608706SJuan Quintela     MigrationIncomingState *mis = migration_incoming_get_current();
274*77608706SJuan Quintela 
275*77608706SJuan Quintela #ifndef CONFIG_LIVE_BLOCK_MIGRATION
276*77608706SJuan Quintela     if (new_caps[MIGRATION_CAPABILITY_BLOCK]) {
277*77608706SJuan Quintela         error_setg(errp, "QEMU compiled without old-style (blk/-b, inc/-i) "
278*77608706SJuan Quintela                    "block migration");
279*77608706SJuan Quintela         error_append_hint(errp, "Use drive_mirror+NBD instead.\n");
280*77608706SJuan Quintela         return false;
281*77608706SJuan Quintela     }
282*77608706SJuan Quintela #endif
283*77608706SJuan Quintela 
284*77608706SJuan Quintela #ifndef CONFIG_REPLICATION
285*77608706SJuan Quintela     if (new_caps[MIGRATION_CAPABILITY_X_COLO]) {
286*77608706SJuan Quintela         error_setg(errp, "QEMU compiled without replication module"
287*77608706SJuan Quintela                    " can't enable COLO");
288*77608706SJuan Quintela         error_append_hint(errp, "Please enable replication before COLO.\n");
289*77608706SJuan Quintela         return false;
290*77608706SJuan Quintela     }
291*77608706SJuan Quintela #endif
292*77608706SJuan Quintela 
293*77608706SJuan Quintela     if (new_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM]) {
294*77608706SJuan Quintela         /* This check is reasonably expensive, so only when it's being
295*77608706SJuan Quintela          * set the first time, also it's only the destination that needs
296*77608706SJuan Quintela          * special support.
297*77608706SJuan Quintela          */
298*77608706SJuan Quintela         if (!old_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM] &&
299*77608706SJuan Quintela             runstate_check(RUN_STATE_INMIGRATE) &&
300*77608706SJuan Quintela             !postcopy_ram_supported_by_host(mis)) {
301*77608706SJuan Quintela             /* postcopy_ram_supported_by_host will have emitted a more
302*77608706SJuan Quintela              * detailed message
303*77608706SJuan Quintela              */
304*77608706SJuan Quintela             error_setg(errp, "Postcopy is not supported");
305*77608706SJuan Quintela             return false;
306*77608706SJuan Quintela         }
307*77608706SJuan Quintela 
308*77608706SJuan Quintela         if (new_caps[MIGRATION_CAPABILITY_X_IGNORE_SHARED]) {
309*77608706SJuan Quintela             error_setg(errp, "Postcopy is not compatible with ignore-shared");
310*77608706SJuan Quintela             return false;
311*77608706SJuan Quintela         }
312*77608706SJuan Quintela     }
313*77608706SJuan Quintela 
314*77608706SJuan Quintela     if (new_caps[MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT]) {
315*77608706SJuan Quintela         WriteTrackingSupport wt_support;
316*77608706SJuan Quintela         int idx;
317*77608706SJuan Quintela         /*
318*77608706SJuan Quintela          * Check if 'background-snapshot' capability is supported by
319*77608706SJuan Quintela          * host kernel and compatible with guest memory configuration.
320*77608706SJuan Quintela          */
321*77608706SJuan Quintela         wt_support = migrate_query_write_tracking();
322*77608706SJuan Quintela         if (wt_support < WT_SUPPORT_AVAILABLE) {
323*77608706SJuan Quintela             error_setg(errp, "Background-snapshot is not supported by host kernel");
324*77608706SJuan Quintela             return false;
325*77608706SJuan Quintela         }
326*77608706SJuan Quintela         if (wt_support < WT_SUPPORT_COMPATIBLE) {
327*77608706SJuan Quintela             error_setg(errp, "Background-snapshot is not compatible "
328*77608706SJuan Quintela                     "with guest memory configuration");
329*77608706SJuan Quintela             return false;
330*77608706SJuan Quintela         }
331*77608706SJuan Quintela 
332*77608706SJuan Quintela         /*
333*77608706SJuan Quintela          * Check if there are any migration capabilities
334*77608706SJuan Quintela          * incompatible with 'background-snapshot'.
335*77608706SJuan Quintela          */
336*77608706SJuan Quintela         for (idx = 0; idx < check_caps_background_snapshot.size; idx++) {
337*77608706SJuan Quintela             int incomp_cap = check_caps_background_snapshot.caps[idx];
338*77608706SJuan Quintela             if (new_caps[incomp_cap]) {
339*77608706SJuan Quintela                 error_setg(errp,
340*77608706SJuan Quintela                         "Background-snapshot is not compatible with %s",
341*77608706SJuan Quintela                         MigrationCapability_str(incomp_cap));
342*77608706SJuan Quintela                 return false;
343*77608706SJuan Quintela             }
344*77608706SJuan Quintela         }
345*77608706SJuan Quintela     }
346*77608706SJuan Quintela 
347*77608706SJuan Quintela #ifdef CONFIG_LINUX
348*77608706SJuan Quintela     if (new_caps[MIGRATION_CAPABILITY_ZERO_COPY_SEND] &&
349*77608706SJuan Quintela         (!new_caps[MIGRATION_CAPABILITY_MULTIFD] ||
350*77608706SJuan Quintela          new_caps[MIGRATION_CAPABILITY_COMPRESS] ||
351*77608706SJuan Quintela          new_caps[MIGRATION_CAPABILITY_XBZRLE] ||
352*77608706SJuan Quintela          migrate_multifd_compression() ||
353*77608706SJuan Quintela          migrate_use_tls())) {
354*77608706SJuan Quintela         error_setg(errp,
355*77608706SJuan Quintela                    "Zero copy only available for non-compressed non-TLS multifd migration");
356*77608706SJuan Quintela         return false;
357*77608706SJuan Quintela     }
358*77608706SJuan Quintela #else
359*77608706SJuan Quintela     if (new_caps[MIGRATION_CAPABILITY_ZERO_COPY_SEND]) {
360*77608706SJuan Quintela         error_setg(errp,
361*77608706SJuan Quintela                    "Zero copy currently only available on Linux");
362*77608706SJuan Quintela         return false;
363*77608706SJuan Quintela     }
364*77608706SJuan Quintela #endif
365*77608706SJuan Quintela 
366*77608706SJuan Quintela     if (new_caps[MIGRATION_CAPABILITY_POSTCOPY_PREEMPT]) {
367*77608706SJuan Quintela         if (!new_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM]) {
368*77608706SJuan Quintela             error_setg(errp, "Postcopy preempt requires postcopy-ram");
369*77608706SJuan Quintela             return false;
370*77608706SJuan Quintela         }
371*77608706SJuan Quintela 
372*77608706SJuan Quintela         /*
373*77608706SJuan Quintela          * Preempt mode requires urgent pages to be sent in separate
374*77608706SJuan Quintela          * channel, OTOH compression logic will disorder all pages into
375*77608706SJuan Quintela          * different compression channels, which is not compatible with the
376*77608706SJuan Quintela          * preempt assumptions on channel assignments.
377*77608706SJuan Quintela          */
378*77608706SJuan Quintela         if (new_caps[MIGRATION_CAPABILITY_COMPRESS]) {
379*77608706SJuan Quintela             error_setg(errp, "Postcopy preempt not compatible with compress");
380*77608706SJuan Quintela             return false;
381*77608706SJuan Quintela         }
382*77608706SJuan Quintela     }
383*77608706SJuan Quintela 
384*77608706SJuan Quintela     if (new_caps[MIGRATION_CAPABILITY_MULTIFD]) {
385*77608706SJuan Quintela         if (new_caps[MIGRATION_CAPABILITY_COMPRESS]) {
386*77608706SJuan Quintela             error_setg(errp, "Multifd is not compatible with compress");
387*77608706SJuan Quintela             return false;
388*77608706SJuan Quintela         }
389*77608706SJuan Quintela     }
390*77608706SJuan Quintela 
391*77608706SJuan Quintela     return true;
392*77608706SJuan Quintela }
393