Merge pull request #32907 from yuwata/image-fix

several fixes for os image handling
This commit is contained in:
Luca Boccassi
2024-05-19 21:10:40 +02:00
committed by GitHub
4 changed files with 104 additions and 44 deletions

View File

@@ -127,9 +127,17 @@ int bus_image_method_rename(
if (r == 0)
return 1; /* Will call us back */
/* The image is cached with its name, hence it is necessary to remove from the cache before renaming. */
assert_se(hashmap_remove_value(m->image_cache, image->name, image));
r = image_rename(image, new_name);
if (r < 0)
if (r < 0) {
image_unref(image);
return r;
}
/* Then save the object again in the cache. */
assert_se(hashmap_put(m->image_cache, image->name, image) > 0);
return sd_bus_reply_method_return(message, NULL);
}
@@ -378,30 +386,17 @@ static int image_flush_cache(sd_event_source *s, void *userdata) {
return 0;
}
static int image_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
_cleanup_free_ char *e = NULL;
Manager *m = userdata;
Image *image = NULL;
const char *p;
int manager_acquire_image(Manager *m, const char *name, Image **ret) {
int r;
assert(bus);
assert(path);
assert(interface);
assert(found);
assert(m);
assert(name);
p = startswith(path, "/org/freedesktop/machine1/image/");
if (!p)
Image *existing = hashmap_get(m->image_cache, name);
if (existing) {
if (ret)
*ret = existing;
return 0;
e = bus_label_unescape(p);
if (!e)
return -ENOMEM;
image = hashmap_get(m->image_cache, e);
if (image) {
*found = image;
return 1;
}
if (!m->image_cache_defer_event) {
@@ -418,19 +413,49 @@ static int image_object_find(sd_bus *bus, const char *path, const char *interfac
if (r < 0)
return r;
r = image_find(IMAGE_MACHINE, e, NULL, &image);
if (r == -ENOENT)
return 0;
_cleanup_(image_unrefp) Image *image = NULL;
r = image_find(IMAGE_MACHINE, name, NULL, &image);
if (r < 0)
return r;
image->userdata = m;
r = hashmap_ensure_put(&m->image_cache, &image_hash_ops, image->name, image);
if (r < 0) {
image_unref(image);
if (r < 0)
return r;
if (ret)
*ret = image;
TAKE_PTR(image);
return 0;
}
static int image_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
_cleanup_free_ char *e = NULL;
Manager *m = userdata;
Image *image;
const char *p;
int r;
assert(bus);
assert(path);
assert(interface);
assert(found);
p = startswith(path, "/org/freedesktop/machine1/image/");
if (!p)
return 0;
e = bus_label_unescape(p);
if (!e)
return -ENOMEM;
r = manager_acquire_image(m, e, &image);
if (r == -ENOENT)
return 0;
if (r < 0)
return r;
}
*found = image;
return 1;

View File

@@ -2,10 +2,12 @@
#pragma once
#include "bus-object.h"
#include "discover-image.h"
#include "machined.h"
extern const BusObjectImplementation image_object;
int manager_acquire_image(Manager *m, const char *name, Image **ret);
char *image_bus_path(const char *name);
int bus_image_method_remove(sd_bus_message *message, void *userdata, sd_bus_error *error);

View File

@@ -550,8 +550,8 @@ static int method_get_machine_uid_shift(sd_bus_message *message, void *userdata,
}
static int redirect_method_to_image(sd_bus_message *message, Manager *m, sd_bus_error *error, sd_bus_message_handler_t method) {
_cleanup_(image_unrefp) Image* i = NULL;
const char *name;
Image *i;
int r;
assert(message);
@@ -565,13 +565,12 @@ static int redirect_method_to_image(sd_bus_message *message, Manager *m, sd_bus_
if (!image_name_is_valid(name))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", name);
r = image_find(IMAGE_MACHINE, name, NULL, &i);
r = manager_acquire_image(m, name, &i);
if (r == -ENOENT)
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name);
if (r < 0)
return r;
i->userdata = m;
return method(message, i, error);
}

View File

@@ -282,6 +282,44 @@ static int extract_image_basename(
return 0;
}
static int image_update_quota(Image *i, int fd) {
_cleanup_close_ int fd_close = -EBADF;
int r;
assert(i);
if (IMAGE_IS_VENDOR(i) || IMAGE_IS_HOST(i))
return -EROFS;
if (i->type != IMAGE_SUBVOLUME)
return -EOPNOTSUPP;
if (fd < 0) {
fd_close = open(i->path, O_CLOEXEC|O_NOCTTY|O_DIRECTORY);
if (fd_close < 0)
return -errno;
fd = fd_close;
}
r = btrfs_quota_scan_ongoing(fd);
if (r < 0)
return r;
if (r > 0)
return 0;
BtrfsQuotaInfo quota;
r = btrfs_subvol_get_subtree_quota_fd(fd, 0, &quota);
if (r < 0)
return r;
i->usage = quota.referenced;
i->usage_exclusive = quota.exclusive;
i->limit = quota.referenced_max;
i->limit_exclusive = quota.exclusive_max;
return 1;
}
static int image_make(
ImageClass c,
const char *pretty,
@@ -375,19 +413,7 @@ static int image_make(
if (r < 0)
return r;
if (btrfs_quota_scan_ongoing(fd) == 0) {
BtrfsQuotaInfo quota;
r = btrfs_subvol_get_subtree_quota_fd(fd, 0, &quota);
if (r >= 0) {
(*ret)->usage = quota.referenced;
(*ret)->usage_exclusive = quota.exclusive;
(*ret)->limit = quota.referenced_max;
(*ret)->limit_exclusive = quota.exclusive_max;
}
}
(void) image_update_quota(*ret, fd);
return 0;
}
}
@@ -1287,6 +1313,7 @@ int image_read_only(Image *i, bool b) {
return -EOPNOTSUPP;
}
i->read_only = b;
return 0;
}
@@ -1395,6 +1422,8 @@ int image_path_lock(
}
int image_set_limit(Image *i, uint64_t referenced_max) {
int r;
assert(i);
if (IMAGE_IS_VENDOR(i) || IMAGE_IS_HOST(i))
@@ -1410,7 +1439,12 @@ int image_set_limit(Image *i, uint64_t referenced_max) {
(void) btrfs_qgroup_set_limit(i->path, 0, referenced_max);
(void) btrfs_subvol_auto_qgroup(i->path, 0, true);
return btrfs_subvol_set_subtree_quota_limit(i->path, 0, referenced_max);
r = btrfs_subvol_set_subtree_quota_limit(i->path, 0, referenced_max);
if (r < 0)
return r;
(void) image_update_quota(i, -EBADF);
return 0;
}
int image_read_metadata(Image *i, const ImagePolicy *image_policy) {