lock_driver_lockd.c 23.3 KB
Newer Older
1 2 3
/*
 * lock_driver_lockd.c: A lock driver which locks nothing
 *
4
 * Copyright (C) 2010-2011, 2014 Red Hat, Inc.
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library;  If not, see
 * <http://www.gnu.org/licenses/>.
 *
 */

#include <config.h>

#include "lock_driver.h"
25
#include "virconf.h"
26
#include "viralloc.h"
27
#include "vircrypto.h"
28
#include "virlog.h"
29
#include "viruuid.h"
30
#include "virfile.h"
31
#include "virerror.h"
32 33 34
#include "rpc/virnetclient.h"
#include "lock_protocol.h"
#include "configmake.h"
35
#include "virstring.h"
36

37 38
#include "lock_driver_lockd.h"

39 40
#define VIR_FROM_THIS VIR_FROM_LOCKING

41 42
VIR_LOG_INIT("locking.lock_driver_lockd");

43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
typedef struct _virLockManagerLockDaemonPrivate virLockManagerLockDaemonPrivate;
typedef virLockManagerLockDaemonPrivate *virLockManagerLockDaemonPrivatePtr;

typedef struct _virLockManagerLockDaemonResource virLockManagerLockDaemonResource;
typedef virLockManagerLockDaemonResource *virLockManagerLockDaemonResourcePtr;

typedef struct _virLockManagerLockDaemonDriver virLockManagerLockDaemonDriver;
typedef virLockManagerLockDaemonDriver *virLockManagerLockDaemonDriverPtr;

struct _virLockManagerLockDaemonResource {
    char *lockspace;
    char *name;
    unsigned int flags;
};

struct _virLockManagerLockDaemonPrivate {
59 60 61 62
    unsigned char uuid[VIR_UUID_BUFLEN];
    char *name;
    int id;
    pid_t pid;
63 64 65

    size_t nresources;
    virLockManagerLockDaemonResourcePtr resources;
66 67

    bool hasRWDisks;
68 69 70 71 72 73
};


struct _virLockManagerLockDaemonDriver {
    bool autoDiskLease;
    bool requireLeaseForDisks;
74 75

    char *fileLockSpaceDir;
76
    char *lvmLockSpaceDir;
77
    char *scsiLockSpaceDir;
78 79
};

80
static virLockManagerLockDaemonDriverPtr driver;
81 82 83

static int virLockManagerLockDaemonLoadConfig(const char *configFile)
{
84
    VIR_AUTOPTR(virConf) conf = NULL;
85 86 87 88 89 90 91 92 93 94 95 96 97 98

    if (access(configFile, R_OK) == -1) {
        if (errno != ENOENT) {
            virReportSystemError(errno,
                                 _("Unable to access config file %s"),
                                 configFile);
            return -1;
        }
        return 0;
    }

    if (!(conf = virConfReadFile(configFile, 0)))
        return -1;

99
    if (virConfGetValueBool(conf, "auto_disk_leases", &driver->autoDiskLease) < 0)
100
        return -1;
101

102
    if (virConfGetValueString(conf, "file_lockspace_dir", &driver->fileLockSpaceDir) < 0)
103
        return -1;
104

105
    if (virConfGetValueString(conf, "lvm_lockspace_dir", &driver->lvmLockSpaceDir) < 0)
106
        return -1;
107

108
    if (virConfGetValueString(conf, "scsi_lockspace_dir", &driver->scsiLockSpaceDir) < 0)
109
        return -1;
110

111 112
    driver->requireLeaseForDisks = !driver->autoDiskLease;
    if (virConfGetValueBool(conf, "require_lease_for_disks", &driver->requireLeaseForDisks) < 0)
113
        return -1;
114

115
    return 0;
116 117 118 119 120 121 122
}


static char *virLockManagerLockDaemonPath(bool privileged)
{
    char *path;
    if (privileged) {
123
        if (VIR_STRDUP(path, RUNSTATEDIR "/libvirt/virtlockd-sock") < 0)
124 125 126 127 128 129 130 131 132 133 134 135
            return NULL;
    } else {
        char *rundir = NULL;

        if (!(rundir = virGetUserRuntimeDirectory()))
            return NULL;

        if (virAsprintf(&path, "%s/virtlockd-sock", rundir) < 0) {
            VIR_FREE(rundir);
            return NULL;
        }

136
        VIR_FREE(rundir);
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
    }
    return path;
}


static int
virLockManagerLockDaemonConnectionRegister(virLockManagerPtr lock,
                                           virNetClientPtr client,
                                           virNetClientProgramPtr program,
                                           int *counter)
{
    virLockManagerLockDaemonPrivatePtr priv = lock->privateData;
    virLockSpaceProtocolRegisterArgs args;
    int rv = -1;

    memset(&args, 0, sizeof(args));

    args.flags = 0;
155 156 157 158
    memcpy(args.owner.uuid, priv->uuid, VIR_UUID_BUFLEN);
    args.owner.name = priv->name;
    args.owner.id = priv->id;
    args.owner.pid = priv->pid;
159 160 161 162 163 164 165 166 167 168 169 170

    if (virNetClientProgramCall(program,
                                client,
                                (*counter)++,
                                VIR_LOCK_SPACE_PROTOCOL_PROC_REGISTER,
                                0, NULL, NULL, NULL,
                                (xdrproc_t)xdr_virLockSpaceProtocolRegisterArgs, (char*)&args,
                                (xdrproc_t)xdr_void, NULL) < 0)
        goto cleanup;

    rv = 0;

171
 cleanup:
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
    return rv;
}


static int
virLockManagerLockDaemonConnectionRestrict(virLockManagerPtr lock ATTRIBUTE_UNUSED,
                                           virNetClientPtr client,
                                           virNetClientProgramPtr program,
                                           int *counter)
{
    virLockSpaceProtocolRestrictArgs args;
    int rv = -1;

    memset(&args, 0, sizeof(args));

    args.flags = 0;

    if (virNetClientProgramCall(program,
                                client,
                                (*counter)++,
                                VIR_LOCK_SPACE_PROTOCOL_PROC_RESTRICT,
                                0, NULL, NULL, NULL,
                                (xdrproc_t)xdr_virLockSpaceProtocolRestrictArgs, (char*)&args,
                                (xdrproc_t)xdr_void, NULL) < 0)
        goto cleanup;

    rv = 0;

200
 cleanup:
201 202 203 204 205 206 207 208 209
    return rv;
}


static virNetClientPtr virLockManagerLockDaemonConnectionNew(bool privileged,
                                                             virNetClientProgramPtr *prog)
{
    virNetClientPtr client = NULL;
    char *lockdpath;
M
Michal Privoznik 已提交
210
    char *daemonPath = NULL;
211 212 213 214 215 216

    *prog = NULL;

    if (!(lockdpath = virLockManagerLockDaemonPath(privileged)))
        goto error;

217 218 219
    if (!privileged &&
        !(daemonPath = virFileFindResourceFull("virtlockd",
                                               NULL, NULL,
220
                                               abs_top_builddir "/src",
221 222 223
                                               SBINDIR,
                                               "VIRTLOCKD_PATH")))
        goto error;
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239

    if (!(client = virNetClientNewUNIX(lockdpath,
                                       daemonPath != NULL,
                                       daemonPath)))
        goto error;

    if (!(*prog = virNetClientProgramNew(VIR_LOCK_SPACE_PROTOCOL_PROGRAM,
                                         VIR_LOCK_SPACE_PROTOCOL_PROGRAM_VERSION,
                                         NULL,
                                         0,
                                         NULL)))
        goto error;

    if (virNetClientAddProgram(client, *prog) < 0)
        goto error;

240
    VIR_FREE(daemonPath);
241 242 243 244
    VIR_FREE(lockdpath);

    return client;

245
 error:
246
    VIR_FREE(daemonPath);
247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
    VIR_FREE(lockdpath);
    virNetClientClose(client);
    virObjectUnref(client);
    virObjectUnref(*prog);
    return NULL;
}


static virNetClientPtr
virLockManagerLockDaemonConnect(virLockManagerPtr lock,
                                virNetClientProgramPtr *program,
                                int *counter)
{
    virNetClientPtr client;

262
    if (!(client = virLockManagerLockDaemonConnectionNew(geteuid() == 0, program)))
263 264 265 266 267 268 269 270 271 272
        return NULL;

    if (virLockManagerLockDaemonConnectionRegister(lock,
                                                   client,
                                                   *program,
                                                   counter) < 0)
        goto error;

    return client;

273
 error:
274 275 276 277 278 279
    virNetClientClose(client);
    virObjectUnref(client);
    return NULL;
}


280 281 282 283 284 285 286 287 288 289 290
static int virLockManagerLockDaemonSetupLockspace(const char *path)
{
    virNetClientPtr client;
    virNetClientProgramPtr program = NULL;
    virLockSpaceProtocolCreateLockSpaceArgs args;
    int rv = -1;
    int counter = 0;

    memset(&args, 0, sizeof(args));
    args.path = (char*)path;

291
    if (!(client = virLockManagerLockDaemonConnectionNew(geteuid() == 0, &program)))
292 293 294 295 296 297 298 299 300
        return -1;

    if (virNetClientProgramCall(program,
                                client,
                                counter++,
                                VIR_LOCK_SPACE_PROTOCOL_PROC_CREATE_LOCKSPACE,
                                0, NULL, NULL, NULL,
                                (xdrproc_t)xdr_virLockSpaceProtocolCreateLockSpaceArgs, (char*)&args,
                                (xdrproc_t)xdr_void, NULL) < 0) {
301
        if (virGetLastErrorCode() == VIR_ERR_OPERATION_INVALID) {
302 303 304 305 306 307 308 309 310 311
            /* The lockspace already exists */
            virResetLastError();
            rv = 0;
        } else {
            goto cleanup;
        }
    }

    rv = 0;

312
 cleanup:
313 314 315 316 317 318 319
    virObjectUnref(program);
    virNetClientClose(client);
    virObjectUnref(client);
    return rv;
}


320 321 322 323 324 325
static int virLockManagerLockDaemonDeinit(void);

static int virLockManagerLockDaemonInit(unsigned int version,
                                        const char *configFile,
                                        unsigned int flags)
{
326
    VIR_DEBUG("version=%u configFile=%s flags=0x%x", version, NULLSTR(configFile), flags);
327 328 329 330 331 332

    virCheckFlags(0, -1);

    if (driver)
        return 0;

333
    if (VIR_ALLOC(driver) < 0)
334 335 336 337 338
        return -1;

    driver->requireLeaseForDisks = true;
    driver->autoDiskLease = true;

339
    if (virLockManagerLockDaemonLoadConfig(configFile) < 0)
340 341
        goto error;

342 343 344 345 346
    if (driver->autoDiskLease) {
        if (driver->fileLockSpaceDir &&
            virLockManagerLockDaemonSetupLockspace(driver->fileLockSpaceDir) < 0)
            goto error;

347 348 349
        if (driver->lvmLockSpaceDir &&
            virLockManagerLockDaemonSetupLockspace(driver->lvmLockSpaceDir) < 0)
            goto error;
350 351 352 353

        if (driver->scsiLockSpaceDir &&
            virLockManagerLockDaemonSetupLockspace(driver->scsiLockSpaceDir) < 0)
            goto error;
354
    }
355

356 357
    return 0;

358
 error:
359 360 361 362 363 364 365 366 367
    virLockManagerLockDaemonDeinit();
    return -1;
}

static int virLockManagerLockDaemonDeinit(void)
{
    if (!driver)
        return 0;

368 369
    VIR_FREE(driver->scsiLockSpaceDir);
    VIR_FREE(driver->lvmLockSpaceDir);
370
    VIR_FREE(driver->fileLockSpaceDir);
371 372 373 374 375
    VIR_FREE(driver);

    return 0;
}

376 377
static void
virLockManagerLockDaemonPrivateFree(virLockManagerLockDaemonPrivatePtr priv)
378 379 380 381 382 383
{
    size_t i;

    if (!priv)
        return;

384
    for (i = 0; i < priv->nresources; i++) {
385 386 387 388 389
        VIR_FREE(priv->resources[i].lockspace);
        VIR_FREE(priv->resources[i].name);
    }
    VIR_FREE(priv->resources);

390
    VIR_FREE(priv->name);
391 392 393
    VIR_FREE(priv);
}

394 395 396 397 398 399 400 401 402
static void virLockManagerLockDaemonFree(virLockManagerPtr lock)
{
    if (!lock)
        return;

    virLockManagerLockDaemonPrivateFree(lock->privateData);
    lock->privateData = NULL;
}

403 404 405 406 407 408 409

static int virLockManagerLockDaemonNew(virLockManagerPtr lock,
                                       unsigned int type,
                                       size_t nparams,
                                       virLockManagerParamPtr params,
                                       unsigned int flags)
{
410
    virLockManagerLockDaemonPrivatePtr priv = NULL;
411
    size_t i;
412
    int ret = -1;
413

414
    virCheckFlags(VIR_LOCK_MANAGER_NEW_STARTED, -1);
415

416
    if (VIR_ALLOC(priv) < 0)
417 418
        return -1;

419
    switch (type) {
420
    case VIR_LOCK_MANAGER_OBJECT_TYPE_DOMAIN:
421
        for (i = 0; i < nparams; i++) {
422
            if (STREQ(params[i].key, "uuid")) {
423
                memcpy(priv->uuid, params[i].value.uuid, VIR_UUID_BUFLEN);
424
            } else if (STREQ(params[i].key, "name")) {
425
                if (VIR_STRDUP(priv->name, params[i].value.str) < 0)
426
                    goto cleanup;
427
            } else if (STREQ(params[i].key, "id")) {
428
                priv->id = params[i].value.iv;
429
            } else if (STREQ(params[i].key, "pid")) {
430
                priv->pid = params[i].value.iv;
431 432
            } else if (STREQ(params[i].key, "uri")) {
                /* ignored */
433 434
            } else {
                virReportError(VIR_ERR_INTERNAL_ERROR,
435
                               _("Unexpected parameter %s for object"),
436
                               params[i].key);
437
                goto cleanup;
438 439
            }
        }
440
        if (priv->id == 0) {
441 442
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("Missing ID parameter for domain object"));
443
            goto cleanup;
444
        }
445
        if (priv->pid == 0)
J
Jim Fehlig 已提交
446
            VIR_DEBUG("Missing PID parameter for domain object");
447
        if (!priv->name) {
448 449
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("Missing name parameter for domain object"));
450
            goto cleanup;
451
        }
452
        if (!virUUIDIsValid(priv->uuid)) {
453 454
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("Missing UUID parameter for domain object"));
455
            goto cleanup;
456 457 458 459 460 461 462
        }
        break;

    default:
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Unknown lock manager object type %d"),
                       type);
463
        goto cleanup;
464 465
    }

466 467 468 469 470
    VIR_STEAL_PTR(lock->privateData, priv);
    ret = 0;
 cleanup:
    virLockManagerLockDaemonPrivateFree(priv);
    return ret;
471 472 473 474 475 476 477 478 479 480 481
}


static int virLockManagerLockDaemonAddResource(virLockManagerPtr lock,
                                               unsigned int type,
                                               const char *name,
                                               size_t nparams,
                                               virLockManagerParamPtr params,
                                               unsigned int flags)
{
    virLockManagerLockDaemonPrivatePtr priv = lock->privateData;
482
    char *newName = NULL;
483
    char *newLockspace = NULL;
484
    bool autoCreate = false;
485
    int ret = -1;
486 487 488 489 490 491 492

    virCheckFlags(VIR_LOCK_MANAGER_RESOURCE_READONLY |
                  VIR_LOCK_MANAGER_RESOURCE_SHARED, -1);

    if (flags & VIR_LOCK_MANAGER_RESOURCE_READONLY)
        return 0;

493 494 495 496 497 498 499 500 501 502 503 504 505
    switch (type) {
    case VIR_LOCK_MANAGER_RESOURCE_TYPE_DISK:
        if (params || nparams) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("Unexpected parameters for disk resource"));
            goto cleanup;
        }
        if (!driver->autoDiskLease) {
            if (!(flags & (VIR_LOCK_MANAGER_RESOURCE_SHARED |
                           VIR_LOCK_MANAGER_RESOURCE_READONLY)))
                priv->hasRWDisks = true;
            return 0;
        }
506

507 508 509 510 511 512 513
        /* XXX we should somehow pass in TYPE=BLOCK info
         * from the domain_lock code, instead of assuming /dev
         */
        if (STRPREFIX(name, "/dev") &&
            driver->lvmLockSpaceDir) {
            VIR_DEBUG("Trying to find an LVM UUID for %s", name);
            if (virStorageFileGetLVMKey(name, &newName) < 0)
514
                goto cleanup;
515

516 517 518
            if (newName) {
                VIR_DEBUG("Got an LVM UUID %s for %s", newName, name);
                if (VIR_STRDUP(newLockspace, driver->lvmLockSpaceDir) < 0)
519
                    goto cleanup;
520 521
                autoCreate = true;
                break;
522
            }
523 524 525
            virResetLastError();
            /* Fallback to generic non-block code */
        }
526

527 528 529
        if (STRPREFIX(name, "/dev") &&
            driver->scsiLockSpaceDir) {
            VIR_DEBUG("Trying to find an SCSI ID for %s", name);
530
            if (virStorageFileGetSCSIKey(name, &newName, false) < 0)
531
                goto cleanup;
532

533 534 535
            if (newName) {
                VIR_DEBUG("Got an SCSI ID %s for %s", newName, name);
                if (VIR_STRDUP(newLockspace, driver->scsiLockSpaceDir) < 0)
536
                    goto cleanup;
537
                autoCreate = true;
538
                break;
539
            }
540 541 542
            virResetLastError();
            /* Fallback to generic non-block code */
        }
543

544 545
        if (driver->fileLockSpaceDir) {
            if (VIR_STRDUP(newLockspace, driver->fileLockSpaceDir) < 0)
546
                goto cleanup;
547 548 549 550 551 552
            if (virCryptoHashString(VIR_CRYPTO_HASH_SHA256, name, &newName) < 0)
                goto cleanup;
            autoCreate = true;
            VIR_DEBUG("Using indirect lease %s for %s", newName, name);
        } else {
            if (VIR_STRDUP(newLockspace, "") < 0)
553
                goto cleanup;
554
            if (VIR_STRDUP(newName, name) < 0)
555
                goto cleanup;
556 557
            VIR_DEBUG("Using direct lease for %s", name);
        }
558

559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584
        break;
    case VIR_LOCK_MANAGER_RESOURCE_TYPE_LEASE: {
        size_t i;
        char *path = NULL;
        char *lockspace = NULL;
        for (i = 0; i < nparams; i++) {
            if (STREQ(params[i].key, "offset")) {
                if (params[i].value.ul != 0) {
                    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                   _("Offset must be zero for this lock manager"));
                    goto cleanup;
                }
            } else if (STREQ(params[i].key, "lockspace")) {
                lockspace = params[i].value.str;
            } else if (STREQ(params[i].key, "path")) {
                path = params[i].value.str;
            } else {
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("Unexpected parameter %s for lease resource"),
                               params[i].key);
                goto cleanup;
            }
        }
        if (!path || !lockspace) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("Missing path or lockspace for lease resource"));
585
            goto cleanup;
586
        }
587 588 589 590 591
        if (virAsprintf(&newLockspace, "%s/%s",
                        path, lockspace) < 0)
            goto cleanup;
        if (VIR_STRDUP(newName, name) < 0)
            goto cleanup;
592

593
    }   break;
594 595 596 597
    default:
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Unknown lock manager object type %d"),
                       type);
598
        goto cleanup;
599 600 601
    }

    if (VIR_EXPAND_N(priv->resources, priv->nresources, 1) < 0)
602
        goto cleanup;
603

604 605
    VIR_STEAL_PTR(priv->resources[priv->nresources-1].lockspace, newLockspace);
    VIR_STEAL_PTR(priv->resources[priv->nresources-1].name, newName);
606 607 608 609 610 611 612 613

    if (flags & VIR_LOCK_MANAGER_RESOURCE_SHARED)
        priv->resources[priv->nresources-1].flags |=
            VIR_LOCK_SPACE_PROTOCOL_ACQUIRE_RESOURCE_SHARED;

    if (autoCreate)
        priv->resources[priv->nresources-1].flags |=
            VIR_LOCK_SPACE_PROTOCOL_ACQUIRE_RESOURCE_AUTOCREATE;
614

615 616
    ret = 0;
 cleanup:
617
    VIR_FREE(newLockspace);
618
    VIR_FREE(newName);
619
    return ret;
620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635
}


static int virLockManagerLockDaemonAcquire(virLockManagerPtr lock,
                                           const char *state ATTRIBUTE_UNUSED,
                                           unsigned int flags,
                                           virDomainLockFailureAction action ATTRIBUTE_UNUSED,
                                           int *fd)
{
    virNetClientPtr client = NULL;
    virNetClientProgramPtr program = NULL;
    int counter = 0;
    int rv = -1;
    virLockManagerLockDaemonPrivatePtr priv = lock->privateData;

    virCheckFlags(VIR_LOCK_MANAGER_ACQUIRE_REGISTER_ONLY |
636
                  VIR_LOCK_MANAGER_ACQUIRE_RESTRICT, -1);
637

638
    if (priv->nresources == 0 &&
639
        priv->hasRWDisks &&
640 641 642 643 644 645 646 647 648 649 650 651 652 653
        driver->requireLeaseForDisks) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("Read/write, exclusive access, disks were present, but no leases specified"));
        return -1;
    }

    if (!(client = virLockManagerLockDaemonConnect(lock, &program, &counter)))
        goto cleanup;

    if (fd &&
        (*fd = virNetClientDupFD(client, false)) < 0)
        goto cleanup;

    if (!(flags & VIR_LOCK_MANAGER_ACQUIRE_REGISTER_ONLY)) {
654
        size_t i;
655
        for (i = 0; i < priv->nresources; i++) {
656 657 658 659
            virLockSpaceProtocolAcquireResourceArgs args;

            memset(&args, 0, sizeof(args));

660
            args.path = priv->resources[i].lockspace;
661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680
            args.name = priv->resources[i].name;
            args.flags = priv->resources[i].flags;

            if (virNetClientProgramCall(program,
                                        client,
                                        counter++,
                                        VIR_LOCK_SPACE_PROTOCOL_PROC_ACQUIRE_RESOURCE,
                                        0, NULL, NULL, NULL,
                                        (xdrproc_t)xdr_virLockSpaceProtocolAcquireResourceArgs, &args,
                                        (xdrproc_t)xdr_void, NULL) < 0)
                goto cleanup;
        }
    }

    if ((flags & VIR_LOCK_MANAGER_ACQUIRE_RESTRICT) &&
        virLockManagerLockDaemonConnectionRestrict(lock, client, program, &counter) < 0)
        goto cleanup;

    rv = 0;

681
 cleanup:
682 683
    if (rv != 0 && fd)
        VIR_FORCE_CLOSE(*fd);
684 685 686 687 688 689 690 691 692 693 694 695 696 697 698
    virNetClientClose(client);
    virObjectUnref(client);
    virObjectUnref(program);

    return rv;
}

static int virLockManagerLockDaemonRelease(virLockManagerPtr lock,
                                           char **state,
                                           unsigned int flags)
{
    virNetClientPtr client = NULL;
    virNetClientProgramPtr program = NULL;
    int counter = 0;
    int rv = -1;
699 700
    size_t i;
    virLockManagerLockDaemonPrivatePtr priv = lock->privateData;
701

702
    virCheckFlags(0, -1);
703 704 705 706 707 708 709

    if (state)
        *state = NULL;

    if (!(client = virLockManagerLockDaemonConnect(lock, &program, &counter)))
        goto cleanup;

710
    for (i = 0; i < priv->nresources; i++) {
711 712 713
        virLockSpaceProtocolReleaseResourceArgs args;

        memset(&args, 0, sizeof(args));
714

715 716 717 718 719 720 721
        if (priv->resources[i].lockspace)
            args.path = priv->resources[i].lockspace;
        args.name = priv->resources[i].name;
        args.flags = priv->resources[i].flags;

        args.flags &=
            ~(VIR_LOCK_SPACE_PROTOCOL_ACQUIRE_RESOURCE_SHARED |
722
              VIR_LOCK_SPACE_PROTOCOL_ACQUIRE_RESOURCE_AUTOCREATE);
723 724 725 726 727 728 729 730

        if (virNetClientProgramCall(program,
                                    client,
                                    counter++,
                                    VIR_LOCK_SPACE_PROTOCOL_PROC_RELEASE_RESOURCE,
                                    0, NULL, NULL, NULL,
                                    (xdrproc_t)xdr_virLockSpaceProtocolReleaseResourceArgs, &args,
                                    (xdrproc_t)xdr_void, NULL) < 0)
731 732
            goto cleanup;
    }
733 734 735

    rv = 0;

736
 cleanup:
737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774
    virNetClientClose(client);
    virObjectUnref(client);
    virObjectUnref(program);

    return rv;
}


static int virLockManagerLockDaemonInquire(virLockManagerPtr lock ATTRIBUTE_UNUSED,
                                           char **state,
                                           unsigned int flags)
{
    virCheckFlags(0, -1);

    if (state)
        *state = NULL;

    return 0;
}

virLockDriver virLockDriverImpl =
{
    .version = VIR_LOCK_MANAGER_VERSION,
    .flags = 0,

    .drvInit = virLockManagerLockDaemonInit,
    .drvDeinit = virLockManagerLockDaemonDeinit,

    .drvNew = virLockManagerLockDaemonNew,
    .drvFree = virLockManagerLockDaemonFree,

    .drvAddResource = virLockManagerLockDaemonAddResource,

    .drvAcquire = virLockManagerLockDaemonAcquire,
    .drvRelease = virLockManagerLockDaemonRelease,

    .drvInquire = virLockManagerLockDaemonInquire,
};