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)
{
J
Ján Tomko 已提交
84
    g_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
    return rv;
}


static int
J
Ján Tomko 已提交
177
virLockManagerLockDaemonConnectionRestrict(virLockManagerPtr lock G_GNUC_UNUSED,
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
                                           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
    lock->privateData = g_steal_pointer(&priv);
467 468 469 470
    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
    priv->resources[priv->nresources-1].lockspace = g_steal_pointer(&newLockspace);
    priv->resources[priv->nresources-1].name = g_steal_pointer(&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
}


static int virLockManagerLockDaemonAcquire(virLockManagerPtr lock,
J
Ján Tomko 已提交
624
                                           const char *state G_GNUC_UNUSED,
625
                                           unsigned int flags,
J
Ján Tomko 已提交
626
                                           virDomainLockFailureAction action G_GNUC_UNUSED,
627 628 629 630 631 632 633 634 635
                                           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
    virNetClientClose(client);
    virObjectUnref(client);
    virObjectUnref(program);

    return rv;
}


J
Ján Tomko 已提交
745
static int virLockManagerLockDaemonInquire(virLockManagerPtr lock G_GNUC_UNUSED,
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
                                           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,
};