From 2839d4f6f4fe6908cd41976807261ec760490499 Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Tue, 5 Jul 2016 12:37:36 +0200 Subject: Update barebox-state Fixed direct bucket Signed-off-by: Markus Pargmann --- Makefile.am | 2 + src/barebox-state.c | 8 +- src/barebox-state/backend.c | 31 +----- src/barebox-state/backend_bucket_cached.c | 155 ++++++++++++++++++++++++++++ src/barebox-state/backend_bucket_circular.c | 117 +++++---------------- src/barebox-state/backend_format_raw.c | 2 + src/barebox-state/backend_storage.c | 65 +++++++++++- src/barebox-state/state.c | 31 ++++-- src/barebox-state/state.h | 16 ++- src/crc.h | 1 + src/dt/common.h | 16 ++- src/state.h | 2 +- 12 files changed, 305 insertions(+), 141 deletions(-) create mode 100644 src/barebox-state/backend_bucket_cached.c create mode 100644 src/crc.h diff --git a/Makefile.am b/Makefile.am index a8dcd18..62979fa 100644 --- a/Makefile.am +++ b/Makefile.am @@ -53,6 +53,7 @@ barebox_state_SOURCES = \ src/base64.c \ src/barebox-state/backend_bucket_circular.c \ src/barebox-state/backend_bucket_direct.c \ + src/barebox-state/backend_bucket_cached.c \ src/barebox-state/backend.c \ src/barebox-state/backend_format_dtb.c \ src/barebox-state/backend_format_raw.c \ @@ -82,6 +83,7 @@ barebox_state_SOURCES = \ src/libbb.h \ src/fdt.h \ src/of.h \ + src/crc.h \ src/mtd/mtd-peb.h \ src/driver.h barebox_state_CFLAGS = $(LIBDT_CFLAGS) diff --git a/src/barebox-state.c b/src/barebox-state.c index 2bfd85c..36da8fa 100644 --- a/src/barebox-state.c +++ b/src/barebox-state.c @@ -309,7 +309,7 @@ static int state_set_var(struct state *state, const char *var, const char *val) } -struct state *state_get(const char *name) +struct state *state_get(const char *name, bool readonly) { struct device_node *root, *node, *partition_node; char *path; @@ -363,7 +363,7 @@ struct state *state_get(const char *name) return ERR_PTR(ret); } - state = state_new_from_node(node, devpath, offset, size); + state = state_new_from_node(node, devpath, offset, size, readonly); if (IS_ERR(state)) { fprintf(stderr, "unable to initlialize state: %s\n", strerror(PTR_ERR(state))); @@ -421,6 +421,7 @@ int main(int argc, char *argv[]) struct list_head sg_list; char *statename = NULL; int lock_fd; + bool readonly = true; INIT_LIST_HEAD(&sg_list); @@ -443,6 +444,7 @@ int main(int argc, char *argv[]) sg->get = 0; sg->arg = optarg; list_add_tail(&sg->list, &sg_list); + readonly = false; break; case 'd': do_dump = 1; @@ -472,7 +474,7 @@ int main(int argc, char *argv[]) exit(1); } - state = state_get(statename); + state = state_get(statename, readonly); if (IS_ERR(state)) { ret = 1; goto out_unlock; diff --git a/src/barebox-state/backend.c b/src/barebox-state/backend.c index 054f8d6..2f2e6df 100644 --- a/src/barebox-state/backend.c +++ b/src/barebox-state/backend.c @@ -153,8 +153,6 @@ int state_backend_init(struct state_backend *backend, struct device_d *dev, char *of_path, off_t offset, size_t max_size, uint32_t stridesize, const char *storagetype) { - struct state_backend_storage_bucket *bucket; - struct state_backend_storage_bucket *bucket_tmp; int ret; ret = state_format_init(backend, dev, backend_format, node, state_name); @@ -166,34 +164,10 @@ int state_backend_init(struct state_backend *backend, struct device_d *dev, if (ret) goto out_free_format; - list_for_each_entry_safe(bucket, bucket_tmp, &backend->storage.buckets, - bucket_list) { - if (!bucket->init) - continue; - - ret = bucket->init(bucket); - if (ret) { - dev_warn(dev, "Bucket init failed, state degraded, %d\n", - ret); - list_del(&bucket->bucket_list); - bucket->free(bucket); - continue; - } - } - - if (list_empty(&backend->storage.buckets)) { - dev_err(dev, "Failed to initialize any state bucket\n"); - ret = -EIO; - goto out_free_storage; - } - - backend->of_path = of_path; return 0; -out_free_storage: - state_storage_free(&backend->storage); out_free_format: state_format_free(backend->format); backend->format = NULL; @@ -201,6 +175,11 @@ out_free_format: return ret; } +void state_backend_set_readonly(struct state_backend *backend) +{ + state_storage_set_readonly(&backend->storage); +} + void state_backend_free(struct state_backend *backend) { state_storage_free(&backend->storage); diff --git a/src/barebox-state/backend_bucket_cached.c b/src/barebox-state/backend_bucket_cached.c new file mode 100644 index 0000000..781ac2d --- /dev/null +++ b/src/barebox-state/backend_bucket_cached.c @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2016 Pengutronix, Markus Pargmann + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2, as published by the Free Software Foundation. + * + * This program 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 General Public License for more details. + * + */ + +#include +#include "state.h" + +struct state_backend_storage_bucket_cache { + struct state_backend_storage_bucket bucket; + + struct state_backend_storage_bucket *raw; + + u8 *data; + ssize_t data_len; + bool force_write; + + /* For outputs */ + struct device_d *dev; +}; + +static inline struct state_backend_storage_bucket_cache + *get_bucket_cache(struct state_backend_storage_bucket *bucket) +{ + return container_of(bucket, + struct state_backend_storage_bucket_cache, + bucket); +} + +static inline void state_backend_bucket_cache_drop( + struct state_backend_storage_bucket_cache *cache) +{ + if (cache->data) { + free(cache->data); + cache->data = NULL; + cache->data_len = 0; + } +} + +static int state_backend_bucket_cache_fill( + struct state_backend_storage_bucket_cache *cache) +{ + int ret; + + ret = cache->raw->read(cache->raw, &cache->data, &cache->data_len); + if (ret == -EUCLEAN) + cache->force_write = true; + else if (ret) + return ret; + + return 0; +} + +static int state_backend_bucket_cache_read(struct state_backend_storage_bucket *bucket, + uint8_t ** buf_out, + ssize_t * len_hint) +{ + struct state_backend_storage_bucket_cache *cache = + get_bucket_cache(bucket); + int ret; + + if (!cache->data) { + ret = state_backend_bucket_cache_fill(cache); + if (ret) + return ret; + } + + if (cache->data) { + *buf_out = xmemdup(cache->data, cache->data_len); + if (!*buf_out) + return -ENOMEM; + *len_hint = cache->data_len; + } + + return 0; +} + +static int state_backend_bucket_cache_write(struct state_backend_storage_bucket *bucket, + const uint8_t * buf, ssize_t len) +{ + struct state_backend_storage_bucket_cache *cache = + get_bucket_cache(bucket); + int ret; + + if (!cache->force_write) { + if (!cache->data) + ret = state_backend_bucket_cache_fill(cache); + + if (cache->data_len == len && !memcmp(cache->data, buf, len)) + return 0; + } + + state_backend_bucket_cache_drop(cache); + + ret = cache->raw->write(cache->raw, buf, len); + if (ret) + return ret; + + cache->data = xmemdup(buf, len); + cache->data_len = len; + return 0; +} + +static int state_backend_bucket_cache_init( + struct state_backend_storage_bucket *bucket) +{ + struct state_backend_storage_bucket_cache *cache = + get_bucket_cache(bucket); + + if (cache->raw->init) { + return cache->raw->init(cache->raw); + } + + return 0; +} + +static void state_backend_bucket_cache_free( + struct state_backend_storage_bucket *bucket) +{ + struct state_backend_storage_bucket_cache *cache = + get_bucket_cache(bucket); + + state_backend_bucket_cache_drop(cache); + cache->raw->free(cache->raw); + free(cache); +} + +int state_backend_bucket_cached_create(struct device_d *dev, + struct state_backend_storage_bucket *raw, + struct state_backend_storage_bucket **out) +{ + struct state_backend_storage_bucket_cache *cache; + + cache = xzalloc(sizeof(*cache)); + cache->raw = raw; + cache->dev = dev; + + cache->bucket.free = state_backend_bucket_cache_free; + cache->bucket.read = state_backend_bucket_cache_read; + cache->bucket.write = state_backend_bucket_cache_write; + cache->bucket.init = state_backend_bucket_cache_init; + + *out = &cache->bucket; + + return 0; +} diff --git a/src/barebox-state/backend_bucket_circular.c b/src/barebox-state/backend_bucket_circular.c index 64e9be2..72e165e 100644 --- a/src/barebox-state/backend_bucket_circular.c +++ b/src/barebox-state/backend_bucket_circular.c @@ -43,12 +43,6 @@ struct state_backend_storage_bucket_circular { int fd; #endif - /* Cached data of the last read/write */ - u8 *current_data; - ssize_t current_data_len; - - bool force_rewrite; /* In case of degradation, force a rewrite */ - /* For outputs */ struct device_d *dev; }; @@ -92,21 +86,19 @@ static int state_mtd_peb_read(struct state_backend_storage_bucket_circular *circ * behind this area */ memset(buf, 0, len); - circ->force_rewrite = true; + ret = -EUCLEAN; circ->write_area = 0; dev_dbg(circ->dev, "PEB %u has ECC error, forcing rewrite\n", circ->eraseblock); } else if (ret == -EUCLEAN) { - circ->force_rewrite = true; dev_dbg(circ->dev, "PEB %u is unclean, forcing rewrite\n", circ->eraseblock); } else if (ret < 0) { dev_err(circ->dev, "Failed to read PEB %u, %d\n", circ->eraseblock, ret); - return ret; } - return 0; + return ret; } static int state_mtd_peb_write(struct state_backend_storage_bucket_circular *circ, @@ -126,14 +118,13 @@ static int state_mtd_peb_write(struct state_backend_storage_bucket_circular *cir ret); return ret; } - circ->force_rewrite = true; + ret = -EUCLEAN; } else if (ret < 0 && ret != -EUCLEAN) { dev_err(circ->dev, "Failed to write PEB %u, %d\n", circ->eraseblock, ret); - return ret; } - return 0; + return ret; } static int state_mtd_peb_erase(struct state_backend_storage_bucket_circular *circ) @@ -181,16 +172,16 @@ static int state_mtd_peb_read(struct state_backend_storage_bucket_circular *circ return 0; if (stat2.failed - stat1.failed > 0) { - circ->force_rewrite = true; + ret = -EUCLEAN; dev_dbg(circ->dev, "PEB %u has ECC error, forcing rewrite\n", circ->eraseblock); } else if (stat2.corrected - stat1.corrected > 0) { - circ->force_rewrite = true; + ret = -EUCLEAN; dev_dbg(circ->dev, "PEB %u is unclean, forcing rewrite\n", circ->eraseblock); } - return 0; + return ret; } static int state_mtd_peb_write(struct state_backend_storage_bucket_circular *circ, @@ -234,8 +225,9 @@ static int state_mtd_peb_erase(struct state_backend_storage_bucket_circular *cir } #endif -static int state_backend_bucket_circular_fill_cache( - struct state_backend_storage_bucket *bucket) +static int state_backend_bucket_circular_read(struct state_backend_storage_bucket *bucket, + uint8_t ** buf_out, + ssize_t * len_hint) { struct state_backend_storage_bucket_circular *circ = get_bucket_circular(bucket); @@ -282,44 +274,17 @@ static int state_backend_bucket_circular_fill_cache( circ->eraseblock, offset, read_len); ret = state_mtd_peb_read(circ, buf, offset, read_len); - if (ret < 0) { + if (ret < 0 && ret != -EUCLEAN) { dev_err(circ->dev, "Failed to read circular storage len %zd, %d\n", read_len, ret); free(buf); return ret; } - circ->current_data = buf; - circ->current_data_len = read_len; - - return 0; -} - -static int state_backend_bucket_circular_read(struct state_backend_storage_bucket *bucket, - uint8_t ** buf_out, - ssize_t * len_hint) -{ - struct state_backend_storage_bucket_circular *circ = - get_bucket_circular(bucket); - int ret; + *buf_out = buf; + *len_hint = read_len - sizeof(struct state_backend_storage_bucket_circular_meta); - if (!circ->current_data) { - ret = state_backend_bucket_circular_fill_cache(bucket); - if (ret) - return ret; - } - - /* - * We keep the internal copy in the cache and duplicate the data for - * external use - */ - *buf_out = xmemdup(circ->current_data, circ->current_data_len); - if (!*buf_out) - return -ENOMEM; - - *len_hint = circ->current_data_len - sizeof(struct state_backend_storage_bucket_circular_meta); - - return 0; + return ret; } static int state_backend_bucket_circular_write(struct state_backend_storage_bucket *bucket, @@ -354,31 +319,6 @@ static int state_backend_bucket_circular_write(struct state_backend_storage_buck meta->magic = circular_magic; meta->written_length = written_length; - /* Nothing in cache? Then read to see what is on the device currently */ - if (!circ->current_data) { - state_backend_bucket_circular_fill_cache(bucket); - } - - /* - * If we would write the same data that is currently on the device, we - * can return successfully without writing. - * Note that the cache may still be empty if the storage is empty or - * errors occured. - */ - if (circ->current_data) { - dev_dbg(circ->dev, "Comparing cached data, writing %zd bytes, cached %zd bytes\n", - written_length, circ->current_data_len); - if (!circ->force_rewrite && - written_length == circ->current_data_len && - !memcmp(circ->current_data, write_buf, written_length)) { - dev_dbg(circ->dev, "Data already on device, not writing again\n"); - goto out_free; - } else { - free(circ->current_data); - circ->current_data = NULL; - } - } - if (circ->write_area + written_length >= circ->max_size) { circ->write_area = 0; } @@ -408,7 +348,7 @@ static int state_backend_bucket_circular_write(struct state_backend_storage_buck circ->write_area += written_length; ret = state_mtd_peb_write(circ, write_buf, offset, written_length); - if (ret < 0) { + if (ret < 0 && ret != -EUCLEAN) { dev_err(circ->dev, "Failed to write circular to %ld length %zd, %d\n", offset, written_length, ret); goto out_free; @@ -417,17 +357,9 @@ static int state_backend_bucket_circular_write(struct state_backend_storage_buck dev_dbg(circ->dev, "Written state to PEB %u offset %ld length %zd data length %zd\n", circ->eraseblock, offset, written_length, len); - /* Put written data into the cache */ - WARN_ON(circ->current_data); - circ->current_data = write_buf; - circ->current_data_len = written_length; - write_buf = NULL; - circ->force_rewrite = false; - out_free: - if (write_buf) - free(write_buf); - return 0; + free(write_buf); + return ret; } /** @@ -492,8 +424,6 @@ static void state_backend_bucket_circular_free(struct struct state_backend_storage_bucket_circular *circ = get_bucket_circular(bucket); - if (circ->current_data) - free(circ->current_data); free(circ); } @@ -528,7 +458,8 @@ int state_backend_bucket_circular_create(struct device_d *dev, const char *path, struct state_backend_storage_bucket **bucket, unsigned int eraseblock, ssize_t writesize, - struct mtd_info_user *mtd_uinfo) + struct mtd_info_user *mtd_uinfo, + bool lazy_init) { struct state_backend_storage_bucket_circular *circ; int ret; @@ -564,9 +495,13 @@ int state_backend_bucket_circular_create(struct device_d *dev, const char *path, circ->bucket.free = state_backend_bucket_circular_free; *bucket = &circ->bucket; - ret = state_backend_bucket_circular_init(*bucket); - if (ret) - goto out_free; + if (!lazy_init) { + ret = state_backend_bucket_circular_init(*bucket); + if (ret) + goto out_free; + } else { + circ->bucket.init = state_backend_bucket_circular_init; + } return 0; diff --git a/src/barebox-state/backend_format_raw.c b/src/barebox-state/backend_format_raw.c index ad55b9f..4209424 100644 --- a/src/barebox-state/backend_format_raw.c +++ b/src/barebox-state/backend_format_raw.c @@ -21,7 +21,9 @@ #include #include #include +#include #include +#include #include "state.h" diff --git a/src/barebox-state/backend_storage.c b/src/barebox-state/backend_storage.c index 4620eda..6b9d86b 100644 --- a/src/barebox-state/backend_storage.c +++ b/src/barebox-state/backend_storage.c @@ -27,6 +27,23 @@ const unsigned int min_copies_written = 1; +static int bucket_lazy_init(struct state_backend_storage_bucket *bucket) +{ + int ret; + + if (bucket->initialized) + return 0; + + if (bucket->init) { + ret = bucket->init(bucket); + if (ret) + return ret; + } + bucket->initialized = true; + + return 0; +} + /** * state_storage_write - Writes the given data to the storage * @param storage Storage object @@ -48,9 +65,19 @@ int state_storage_write(struct state_backend_storage *storage, int ret; int copies_written = 0; + if (storage->readonly) + return 0; + list_for_each_entry(bucket, &storage->buckets, bucket_list) { - ret = bucket->write(bucket, buf, len); + ret = bucket_lazy_init(bucket); if (ret) { + dev_warn(storage->dev, "Failed to init bucket/write state backend bucket, %d\n", + ret); + continue; + } + + ret = bucket->write(bucket, buf, len); + if (ret < 0) { dev_warn(storage->dev, "Failed to write state backend bucket, %d\n", ret); } else { @@ -78,9 +105,8 @@ int state_storage_write(struct state_backend_storage *storage, * to all buckets. Bucket implementations that need to keep the number of writes * low, can read their own copy first and compare it. */ -int state_storage_restore_consistency(struct state_backend_storage - *storage, const uint8_t * buf, - ssize_t len) +int state_storage_restore_consistency(struct state_backend_storage *storage, + const uint8_t * buf, ssize_t len) { return state_storage_write(storage, buf, len); } @@ -111,6 +137,13 @@ int state_storage_read(struct state_backend_storage *storage, list_for_each_entry(bucket, &storage->buckets, bucket_list) { *len = len_hint; + ret = bucket_lazy_init(bucket); + if (ret) { + dev_warn(storage->dev, "Failed to init bucket/read state backend bucket, %d\n", + ret); + continue; + } + ret = bucket->read(bucket, buf, len); if (ret) { dev_warn(storage->dev, "Failed to read from state backend bucket, trying next, %d\n", @@ -250,6 +283,7 @@ static int state_storage_mtd_buckets_init(struct state_backend_storage *storage, int ret; ssize_t writesize = meminfo->writesize; unsigned int eraseblock = offset / meminfo->erasesize; + bool lazy_init = true; if (non_circular) writesize = meminfo->erasesize; @@ -258,13 +292,21 @@ static int state_storage_mtd_buckets_init(struct state_backend_storage *storage, &bucket, eraseblock, writesize, - meminfo); + meminfo, + lazy_init); if (ret) { dev_warn(storage->dev, "Failed to create bucket at '%s' eraseblock %u\n", path, eraseblock); continue; } + ret = state_backend_bucket_cached_create(storage->dev, bucket, + &bucket); + if (ret) { + dev_warn(storage->dev, "Failed to setup cache bucket, continuing without cache, %d\n", + ret); + } + list_add_tail(&bucket->bucket_list, &storage->buckets); ++nr_copies; if (nr_copies >= desired_copies) @@ -387,6 +429,13 @@ static int state_storage_file_buckets_init(struct state_backend_storage *storage continue; } + ret = state_backend_bucket_cached_create(storage->dev, bucket, + &bucket); + if (ret) { + dev_warn(storage->dev, "Failed to setup cache bucket, continuing without cache, %d\n", + ret); + } + list_add_tail(&bucket->bucket_list, &storage->buckets); ++nr_copies; if (nr_copies >= desired_copies) @@ -428,6 +477,7 @@ int state_storage_init(struct state_backend_storage *storage, INIT_LIST_HEAD(&storage->buckets); storage->dev = dev; storage->name = storagetype; + storage->stridesize = stridesize; ret = mtd_get_meminfo(path, &meminfo); if (!ret && !(meminfo.flags & MTD_NO_ERASE)) { @@ -450,6 +500,11 @@ int state_storage_init(struct state_backend_storage *storage, dev_err(storage->dev, "storage init done\n"); } +void state_storage_set_readonly(struct state_backend_storage *storage) +{ + storage->readonly = true; +} + /** * state_storage_free - Free backend storage * @param storage Storage object diff --git a/src/barebox-state/state.c b/src/barebox-state/state.c index 5e2625e..28cfb83 100644 --- a/src/barebox-state/state.c +++ b/src/barebox-state/state.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -66,10 +67,6 @@ static struct state *state_new(const char *name) return state; } -#ifndef __BAREBOX__ -#define asprintf(fmt, arg...) barebox_asprintf(fmt, ##arg) -#endif - static int state_convert_node_variable(struct state *state, struct device_node *node, struct device_node *parent, @@ -92,8 +89,8 @@ static int state_convert_node_variable(struct state *state, *indexs = 0; /* construct full name */ - name = asprintf("%s%s%s", parent_name, parent_name[0] ? "." : "", - short_name); + name = basprintf("%s%s%s", parent_name, parent_name[0] ? "." : "", + short_name); free(short_name); if ((conv == STATE_CONVERT_TO_NODE) || (conv == STATE_CONVERT_FIXUP)) @@ -380,6 +377,13 @@ static int of_state_fixup(struct device_node *root, void *ctx) } } + if (state->backend.storage.stridesize) { + ret = of_property_write_u32(new_node, "backend-stridesize", + state->backend.storage.stridesize); + if (ret) + goto out; + } + /* address-cells + size-cells */ ret = of_property_write_u32(new_node, "#address-cells", 1); if (ret) @@ -417,9 +421,11 @@ void state_release(struct state *state) * @offset Offset in the device path. May be 0 to start at the beginning. * @max_size Maximum size of the area used. This may be 0 to use the full * size. + * @readonly This is a read-only state. Note that with this option set, + * there are no repairs done. */ struct state *state_new_from_node(struct device_node *node, char *path, - off_t offset, size_t max_size) + off_t offset, size_t max_size, bool readonly) { struct state *state; int ret = 0; @@ -459,7 +465,7 @@ struct state *state_new_from_node(struct device_node *node, char *path, ret = of_find_path_by_node(partition_node, &path, 0); } if (!path) { - pr_err("state failed to parse path to backend\n"); + dev_err(&state->dev, "state failed to parse path to backend\n"); ret = -EINVAL; goto out_release_state; } @@ -479,7 +485,7 @@ struct state *state_new_from_node(struct device_node *node, char *path, &storage_type); if (ret) { storage_type = NULL; - pr_info("No backend-storage-type found, using default.\n"); + dev_info(&state->dev, "No backend-storage-type found, using default.\n"); } ret = state_backend_init(&state->backend, &state->dev, node, @@ -488,6 +494,9 @@ struct state *state_new_from_node(struct device_node *node, char *path, if (ret) goto out_release_state; + if (readonly) + state_backend_set_readonly(&state->backend); + ret = state_from_node(state, node, 1); if (ret) { goto out_release_state; @@ -500,11 +509,11 @@ struct state *state_new_from_node(struct device_node *node, char *path, ret = state_load(state); if (ret) { - pr_warn("Failed to load persistent state, continuing with defaults, %d\n", ret); + dev_warn(&state->dev, "Failed to load persistent state, continuing with defaults, %d\n", ret); state->state_default = 1; } - pr_info("New state registered '%s'\n", alias); + dev_info(&state->dev, "New state registered '%s'\n", alias); return state; diff --git a/src/barebox-state/state.h b/src/barebox-state/state.h index 2226356..48a6785 100644 --- a/src/barebox-state/state.h +++ b/src/barebox-state/state.h @@ -27,6 +27,7 @@ struct state_backend_storage_bucket { uint8_t ** buf, ssize_t * len_hint); void (*free) (struct state_backend_storage_bucket * bucket); + bool initialized; struct list_head bucket_list; }; @@ -70,6 +71,9 @@ struct state_backend_storage { struct device_d *dev; const char *name; + uint32_t stridesize; + + bool readonly; }; /** @@ -200,13 +204,18 @@ int state_storage_init(struct state_backend_storage *storage, struct device_d *dev, const char *path, off_t offset, size_t max_size, uint32_t stridesize, const char *storagetype); +void state_storage_set_readonly(struct state_backend_storage *storage); void state_add_var(struct state *state, struct state_variable *var); struct variable_type *state_find_type_by_name(const char *name); int state_backend_bucket_circular_create(struct device_d *dev, const char *path, - struct state_backend_storage_bucket - **bucket, unsigned int eraseblock, + struct state_backend_storage_bucket **bucket, + unsigned int eraseblock, ssize_t writesize, - struct mtd_info_user *mtd_uinfo); + struct mtd_info_user *mtd_uinfo, + bool lazy_init); +int state_backend_bucket_cached_create(struct device_d *dev, + struct state_backend_storage_bucket *raw, + struct state_backend_storage_bucket **out); struct state_variable *state_find_var(struct state *state, const char *name); struct digest *state_backend_format_raw_get_digest(struct state_backend_format *format); @@ -215,6 +224,7 @@ int state_backend_init(struct state_backend *backend, struct device_d *dev, const char *storage_path, const char *state_name, const char *of_path, off_t offset, size_t max_size, uint32_t stridesize, const char *storagetype); +void state_backend_set_readonly(struct state_backend *backend); void state_backend_free(struct state_backend *backend); void state_storage_free(struct state_backend_storage *storage); int state_backend_bucket_direct_create(struct device_d *dev, const char *path, diff --git a/src/crc.h b/src/crc.h new file mode 100644 index 0000000..40a8c17 --- /dev/null +++ b/src/crc.h @@ -0,0 +1 @@ +/* empty */ diff --git a/src/dt/common.h b/src/dt/common.h index f903176..2c45c11 100644 --- a/src/dt/common.h +++ b/src/dt/common.h @@ -153,6 +153,8 @@ static inline char *barebox_asprintf(const char *fmt, ...) return ret == -1 ? NULL : p; } +#define basprintf(fmt, arg...) barebox_asprintf(fmt, ##arg) + /** * strlcpy - Copy a %NUL terminated string into a sized buffer * @dest: Where to copy the string to @@ -579,7 +581,19 @@ static inline __u32 ror32(__u32 word, unsigned int shift) uint32_t crc32(uint32_t crc, const void *_buf, unsigned int len); uint32_t crc32_no_comp(uint32_t crc, const void *_buf, unsigned int len); -#define flush(fd) fsync(fd) +static inline int flush(int fd) +{ + int ret; + + ret = fsync(fd); + if (!ret) + return 0; + + if (errno == EINVAL) + return 0; + + return -errno; +} static inline int mtd_buf_all_ff(const void *buf, unsigned int len) { diff --git a/src/state.h b/src/state.h index 48c60ea..bc9a574 100644 --- a/src/state.h +++ b/src/state.h @@ -11,7 +11,7 @@ int state_backend_raw_file(struct state *state, const char *of_path, const char *path, off_t offset, size_t size); struct state *state_new_from_node(struct device_node *node, char *path, - off_t offset, size_t max_size); + off_t offset, size_t max_size, bool readonly); void state_release(struct state *state); struct state *state_by_name(const char *name); -- cgit v1.2.3