diff options
author | Colin Walters <walters@verbum.org> | 2015-05-04 18:35:52 -0400 |
---|---|---|
committer | Colin Walters <walters@verbum.org> | 2015-05-05 08:52:44 -0400 |
commit | 9ef98fd05a335834b3ecb005d820be19784764d8 (patch) | |
tree | 2ea2810444e05a64d29dd8b919d50a93a63c3334 /src/libostree | |
parent | 33b06675976e5a353cff29bbf5622f7fd7565c27 (diff) | |
download | ostree-9ef98fd05a335834b3ecb005d820be19784764d8.tar.gz |
sysroot: Add an API to lock
If a system administrator happens to type `ostree admin upgrade`
multiple times, currently that will lead to a potentially corrupted
system.
I originally attempted to do locking *internally* in `libostree`, but
that didn't work out because currently a number of the commands
perform multi-step operations that all need to be serialized. All of
the current code in `ostree admin deploy` is an example.
Therefore, allow callers to perform locking, as most of the higher
level logic is presently implemented there.
At some point, we can revisit having internal locking, but it will be
difficult. A more likely approach would be similar to Java's approach
with concurrency on iterators - a "fail fast" method.
Diffstat (limited to 'src/libostree')
-rw-r--r-- | src/libostree/ostree-sysroot-private.h | 5 | ||||
-rw-r--r-- | src/libostree/ostree-sysroot.c | 44 | ||||
-rw-r--r-- | src/libostree/ostree-sysroot.h | 3 |
3 files changed, 52 insertions, 0 deletions
diff --git a/src/libostree/ostree-sysroot-private.h b/src/libostree/ostree-sysroot-private.h index 69310c3f..fa7b0866 100644 --- a/src/libostree/ostree-sysroot-private.h +++ b/src/libostree/ostree-sysroot-private.h @@ -20,6 +20,7 @@ #pragma once +#include "libglnx.h" #include "ostree.h" #include "ostree-kernel-args.h" #include "ostree-bootloader.h" @@ -31,6 +32,7 @@ struct OstreeSysroot { GFile *path; int sysroot_fd; + GLnxLockFile lock; gboolean loaded; @@ -43,8 +45,11 @@ struct OstreeSysroot { /* Only access through ostree_sysroot_get_repo() */ OstreeRepo *repo; + }; +#define OSTREE_SYSROOT_LOCKFILE "ostree/lock" + gboolean _ostree_sysroot_read_boot_loader_configs (OstreeSysroot *self, int bootversion, diff --git a/src/libostree/ostree-sysroot.c b/src/libostree/ostree-sysroot.c index 62558037..8f2b2496 100644 --- a/src/libostree/ostree-sysroot.c +++ b/src/libostree/ostree-sysroot.c @@ -44,6 +44,10 @@ find_booted_deployment (OstreeSysroot *self, * which in particular should contain a toplevel /ostree directory. * Inside this directory is an #OstreeRepo in /ostree/repo, plus a set * of deployments in /ostree/deploy. + * + * This class is not by default safe against concurrent use by threads + * or external processes. You can use ostree_sysroot_lock() to + * perform locking externally. */ typedef struct { GObjectClass parent_class; @@ -66,6 +70,8 @@ ostree_sysroot_finalize (GObject *object) g_clear_object (&self->sepolicy); g_clear_object (&self->repo); + glnx_release_lock_file (&self->lock); + if (self->sysroot_fd != -1) (void) close (self->sysroot_fd); @@ -148,6 +154,7 @@ static void ostree_sysroot_init (OstreeSysroot *self) { self->sysroot_fd = -1; + self->lock = (GLnxLockFile)GLNX_LOCK_FILE_INIT; } /** @@ -1143,6 +1150,43 @@ ostree_sysroot_origin_new_from_refspec (OstreeSysroot *sysroot, } /** + * ostree_sysroot_lock: + * @self: Self + * @error: Error + * + * Acquire an exclusive multi-process write lock for @self. This call + * blocks until the lock has been acquired. The lock is not + * reentrant. + * + * Release the lock with ostree_sysroot_unlock(). The lock will also + * be released if @self is deallocated. + */ +gboolean +ostree_sysroot_lock (OstreeSysroot *self, + GError **error) +{ + if (!ensure_sysroot_fd (self, error)) + return FALSE; + return glnx_make_lock_file (self->sysroot_fd, OSTREE_SYSROOT_LOCKFILE, + LOCK_EX, &self->lock, error); +} + +/** + * ostree_sysroot_unlock: + * @self: Self + * @error: Error + * + * Clear the lock previously acquired with ostree_sysroot_lock(). It + * is safe to call this function if the lock has not been previously + * acquired. + */ +void +ostree_sysroot_unlock (OstreeSysroot *self) +{ + glnx_release_lock_file (&self->lock); +} + +/** * ostree_sysroot_simple_write_deployment: * @sysroot: Sysroot * @osname: (allow-none): OS name diff --git a/src/libostree/ostree-sysroot.h b/src/libostree/ostree-sysroot.h index fe6441fb..e7f6e482 100644 --- a/src/libostree/ostree-sysroot.h +++ b/src/libostree/ostree-sysroot.h @@ -62,6 +62,9 @@ char *ostree_sysroot_get_deployment_dirpath (OstreeSysroot *self, GFile * ostree_sysroot_get_deployment_origin_path (GFile *deployment_path); +gboolean ostree_sysroot_lock (OstreeSysroot *self, GError **error); +void ostree_sysroot_unlock (OstreeSysroot *self); + gboolean ostree_sysroot_cleanup (OstreeSysroot *self, GCancellable *cancellable, GError **error); |