File: locking.html

package info (click to toggle)
libvirt 5.6.0-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 240,844 kB
  • sloc: ansic: 584,521; xml: 176,725; sh: 9,912; python: 4,731; perl: 4,343; makefile: 3,321; ml: 465
file content (383 lines) | stat: -rw-r--r-- 12,881 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
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
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
  <!--
        This file is autogenerated from internals/locking.html.in
        Do not edit this file. Changes will be lost.
      -->
  <!--
        This page was generated at Tue Jul 30 02:04:28 UTC 2019.
      -->
  <head>
    <meta charset="UTF-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1"/>
    <link rel="stylesheet" type="text/css" href="../main.css"/>
    <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png"/>
    <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png"/>
    <link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png"/>
    <link rel="manifest" href="/manifest.json"/>
    <meta name="theme-color" content="#ffffff"/>
    <title>libvirt: Resource Lock Manager</title>
    <meta name="description" content="libvirt, virtualization, virtualization API"/>
    <script type="text/javascript" src="../js/main.js">
      <!--// forces non-empty element-->
    </script>
  </head>
  <body onload="pageload()">
    <div id="body">
      <div id="content">
        <h1>Resource Lock Manager</h1>
        <ul>
          <li>
            <a href="#goals">Goals</a>
          </li>
          <li>
            <a href="#requirement">Requirements</a>
          </li>
          <li>
            <a href="#design">Design</a>
          </li>
          <li>
            <a href="#impl">Plugin Implementations</a>
          </li>
          <li>
            <a href="#qemuIntegrate">QEMU Driver integration</a>
          </li>
          <li>
            <a href="#usagePatterns">Lock usage patterns</a>
            <ul>
              <li>
                <a href="#usageLockAcquire">Lock acquisition</a>
              </li>
              <li>
                <a href="#usageLockAttach">Lock release</a>
              </li>
            </ul>
          </li>
        </ul>
        <p>
      This page describes the design of the resource lock manager
      that is used for locking disk images, to ensure exclusive
      access to content.
    </p>
        <h2>
          <a id="goals">Goals</a>
          <a class="headerlink" href="#goals" title="Permalink to this headline">¶</a>
        </h2>
        <p>
      The high level goal is to prevent the same disk image being
      used by more than one QEMU instance at a time (unless the
      disk is marked as shareable, or readonly). The scenarios
      to be prevented are thus:
    </p>
        <ol>
          <li>
        Two different guests running configured to point at the
        same disk image.
      </li>
          <li>
        One guest being started more than once on two different
        machines due to admin mistake
      </li>
          <li>
        One guest being started more than once on a single machine
        due to libvirt driver bug on a single machine.
      </li>
        </ol>
        <h2>
          <a id="requirement">Requirements</a>
          <a class="headerlink" href="#requirement" title="Permalink to this headline">¶</a>
        </h2>
        <p>
      The high level goal leads to a set of requirements
      for the lock manager design
    </p>
        <ol>
          <li>
        A lock must be held on a disk whenever a QEMU process
        has the disk open
      </li>
          <li>
        The lock scheme must allow QEMU to be configured with
        readonly, shared write, or exclusive writable disks
      </li>
          <li>
        A lock handover must be performed during the migration
        process where 2 QEMU processes will have the same disk
        open concurrently.
      </li>
          <li>
        The lock manager must be able to identify and kill the
        process accessing the resource if the lock is revoked.
      </li>
          <li>
        Locks can be acquired for arbitrary VM related resources,
        as determined by the management application.
      </li>
        </ol>
        <h2>
          <a id="design">Design</a>
          <a class="headerlink" href="#design" title="Permalink to this headline">¶</a>
        </h2>
        <p>
      Within a lock manager the following series of operations
      will need to be supported.
    </p>
        <ul>
          <li><strong>Register object</strong>
        Register the identity of an object against which
        locks will be acquired
      </li>
          <li><strong>Add resource</strong>
        Associate a resource with an object for future
        lock acquisition / release
      </li>
          <li><strong>Acquire locks</strong>
        Acquire the locks for all resources associated
        with the object
      </li>
          <li><strong>Release locks</strong>
        Release the locks for all resources associated
        with the object
      </li>
          <li><strong>Inquire locks</strong>
        Get a representation of the state of the locks
        for all resources associated with the object
      </li>
        </ul>
        <h2>
          <a id="impl">Plugin Implementations</a>
          <a class="headerlink" href="#impl" title="Permalink to this headline">¶</a>
        </h2>
        <p>
      Lock manager implementations are provided as LGPLv2+
      licensed, dlopen()able library modules. The plugins
      will be loadable from the following location:
    </p>
        <pre>
/usr/{lib,lib64}/libvirt/lock_manager/$NAME.so
</pre>
        <p>
      The lock manager plugin must export a single ELF
      symbol named <code>virLockDriverImpl</code>, which is
      a static instance of the <code>virLockDriver</code>
      struct. The struct is defined in the header file
    </p>
        <pre>
#include &lt;libvirt/plugins/lock_manager.h&gt;
    </pre>
        <p>
      All callbacks in the struct must be initialized
      to non-NULL pointers. The semantics of each
      callback are defined in the API docs embedded
      in the previously mentioned header file
    </p>
        <h2>
          <a id="qemuIntegrate">QEMU Driver integration</a>
          <a class="headerlink" href="#qemuIntegrate" title="Permalink to this headline">¶</a>
        </h2>
        <p>
      With the QEMU driver, the lock plugin will be set
      in the <code>/etc/libvirt/qemu.conf</code> configuration
      file by specifying the lock manager name.
    </p>
        <pre>
lockManager="sanlock"
    </pre>
        <p>
      By default the lock manager will be a 'no op' implementation
      for backwards compatibility
    </p>
        <h2>
          <a id="usagePatterns">Lock usage patterns</a>
          <a class="headerlink" href="#usagePatterns" title="Permalink to this headline">¶</a>
        </h2>
        <p>
      The following pseudo code illustrates the common
      patterns of operations invoked on the lock
      manager plugin callbacks.
    </p>
        <h3>
          <a id="usageLockAcquire">Lock acquisition</a>
          <a class="headerlink" href="#usageLockAcquire" title="Permalink to this headline">¶</a>
        </h3>
        <p>
      Initial lock acquisition will be performed from the
      process that is to own the lock. This is typically
      the QEMU child process, in between the fork+exec
      pairing. When adding further resources on the fly,
      to an existing object holding locks, this will be
      done from the libvirtd process.
    </p>
        <pre>
virLockManagerParam params[] = {
  { .type = VIR_LOCK_MANAGER_PARAM_TYPE_UUID,
    .key = "uuid",
  },
  { .type = VIR_LOCK_MANAGER_PARAM_TYPE_STRING,
    .key = "name",
    .value = { .str = dom-&gt;def-&gt;name },
  },
  { .type = VIR_LOCK_MANAGER_PARAM_TYPE_UINT,
    .key = "id",
    .value = { .i = dom-&gt;def-&gt;id },
  },
  { .type = VIR_LOCK_MANAGER_PARAM_TYPE_UINT,
    .key = "pid",
    .value = { .i = dom-&gt;pid },
  },
  { .type = VIR_LOCK_MANAGER_PARAM_TYPE_CSTRING,
    .key = "uri",
    .value = { .cstr = driver-&gt;uri },
  },
};
mgr = virLockManagerNew(lockPlugin,
                        VIR_LOCK_MANAGER_TYPE_DOMAIN,
                        ARRAY_CARDINALITY(params),
                        params,
                        0)));

foreach (initial disks)
    virLockManagerAddResource(mgr,
                              VIR_LOCK_MANAGER_RESOURCE_TYPE_DISK,
                              $path, 0, NULL, $flags);

if (virLockManagerAcquire(lock, NULL, 0) &lt; 0);
  ...abort...
    </pre>
        <h3>
          <a id="usageLockAttach">Lock release</a>
          <a class="headerlink" href="#usageLockAttach" title="Permalink to this headline">¶</a>
        </h3>
        <p>
      The locks are all implicitly released when the process
      that acquired them exits, however, a process may
      voluntarily give up the lock by running
    </p>
        <pre>
char *state = NULL;
virLockManagerParam params[] = {
  { .type = VIR_LOCK_MANAGER_PARAM_TYPE_UUID,
    .key = "uuid",
  },
  { .type = VIR_LOCK_MANAGER_PARAM_TYPE_STRING,
    .key = "name",
    .value = { .str = dom-&gt;def-&gt;name },
  },
  { .type = VIR_LOCK_MANAGER_PARAM_TYPE_UINT,
    .key = "id",
    .value = { .i = dom-&gt;def-&gt;id },
  },
  { .type = VIR_LOCK_MANAGER_PARAM_TYPE_UINT,
    .key = "pid",
    .value = { .i = dom-&gt;pid },
  },
  { .type = VIR_LOCK_MANAGER_PARAM_TYPE_CSTRING,
    .key = "uri",
    .value = { .cstr = driver-&gt;uri },
  },
};
mgr = virLockManagerNew(lockPlugin,
                        VIR_LOCK_MANAGER_TYPE_DOMAIN,
                        ARRAY_CARDINALITY(params),
                        params,
                        0)));

foreach (initial disks)
    virLockManagerAddResource(mgr,
                              VIR_LOCK_MANAGER_RESOURCE_TYPE_DISK,
                              $path, 0, NULL, $flags);

virLockManagerRelease(mgr, &amp; state, 0);
    </pre>
        <p>
      The returned state string can be passed to the
      <code>virLockManagerAcquire</code> method to
      later re-acquire the exact same locks. This
      state transfer is commonly used when performing
      live migration of virtual machines. By validating
      the state the lock manager can ensure no other
      VM has re-acquire the same locks on a different
      host. The state can also be obtained without
      releasing the locks, by calling the
      <code>virLockManagerInquire</code> method.
    </p>
      </div>
    </div>
    <div id="nav">
      <div id="home">
        <a href="../index.html">Home</a>
      </div>
      <div id="jumplinks">
        <ul>
          <li>
            <a href="../downloads.html">Download</a>
          </li>
          <li>
            <a href="../contribute.html">Contribute</a>
          </li>
          <li>
            <a href="../docs.html">Docs</a>
          </li>
        </ul>
      </div>
      <div id="search">
        <form id="simplesearch" action="https://www.google.com/search" enctype="application/x-www-form-urlencoded" method="get">
          <div>
            <input id="searchsite" name="sitesearch" type="hidden" value="libvirt.org"/>
            <input id="searchq" name="q" type="text" size="12" value=""/>
            <input name="submit" type="submit" value="Go"/>
          </div>
        </form>
        <div id="advancedsearch">
          <span>
            <input type="radio" name="what" id="whatwebsite" checked="checked" value="website"/>
            <label for="whatwebsite">Website</label>
          </span>
          <span>
            <input type="radio" name="what" id="whatwiki" value="wiki"/>
            <label for="whatwiki">Wiki</label>
          </span>
          <span>
            <input type="radio" name="what" id="whatdevs" value="devs"/>
            <label for="whatdevs">Developers list</label>
          </span>
          <span>
            <input type="radio" name="what" id="whatusers" value="users"/>
            <label for="whatusers">Users list</label>
          </span>
        </div>
      </div>
    </div>
    <div id="footer">
      <div id="contact">
        <h3>Contact</h3>
        <ul>
          <li>
            <a href="../contact.html#email">email</a>
          </li>
          <li>
            <a href="../contact.html#irc">irc</a>
          </li>
        </ul>
      </div>
      <div id="community">
        <h3>Community</h3>
        <ul>
          <li>
            <a href="https://twitter.com/hashtag/libvirt">twitter</a>
          </li>
          <li>
            <a href="http://stackoverflow.com/questions/tagged/libvirt">stackoverflow</a>
          </li>
          <li>
            <a href="http://serverfault.com/questions/tagged/libvirt">serverfault</a>
          </li>
        </ul>
      </div>
      <div id="conduct">
            Participants in the libvirt project agree to abide by <a href="../governance.html#codeofconduct">the project code of conduct</a></div>
      <br class="clear"/>
    </div>
  </body>
</html>