summaryrefslogtreecommitdiffstats
path: root/common/state/backend_storage.c
Commit message (Collapse)AuthorAgeFilesLines
* state: backend: direct: open backend in read-only mode if possibleAhmad Fatoum2023-01-161-1/+1
| | | | | | | | | | | | | | | | | We unconditionally open the device backing a direct bucket in read-write mode. We already populate struct state_backend_storage::readonly though, which we could consult at device open time. Do so. This could possibly be done for MTD as well, but until that's tested, for now, we do it only for the direct backend meant for use with block devices. This has no functional change for barebox, which calls state_new_from_node in the DT driver and in the EFI initcall always with readonly=false, but we can benefit from this in barebox_state to open a device in read-only mode when possible (e.g. when called to --dump). Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de> Link: https://lore.barebox.org/20230116125443.713033-1-a.fatoum@pengutronix.de Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
* state: make first boot with uninitialized legacy state less verboseAhmad Fatoum2022-01-101-2/+5
| | | | | | | | | | With non-legacy state, barebox checks a header for a specific magic signature. This can be all zero on an uninitialized state, so in that particular case, bump down the log message severity. Signed-off-by: Ahmad Fatoum <ahmad@a3f.at> Link: https://lore.barebox.org/20211129072235.2016324-1-ahmad@a3f.at Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
* state: make first boot less verboseAhmad Fatoum2021-12-071-3/+9
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | First boot with uninitialized state is needlessly verbose: state: New state registered 'state' state: Detected old on-storage format ERROR: state: Error, invalid header crc in raw format, calculated 0x7bd5c66f, found 0x00000000 state: Ignoring broken bucket 0@0x00000000... state: Detected old on-storage format ERROR: state: Error, invalid header crc in raw format, calculated 0x7bd5c66f, found 0x00000000 state: Ignoring broken bucket 1@0x00040000... state: Detected old on-storage format ERROR: state: Error, invalid header crc in raw format, calculated 0x7bd5c66f, found 0x00000000 state: Ignoring broken bucket 2@0x00080000... ERROR: state: Failed to find any valid state copy in any bucket ERROR: state: Failed to read state with format raw, -2 This has confused barebox-state novices more than once. Let's handle the zeroed state case specially and reduce output in that case, so it now looks like this: state: New state registered 'state' state: Detected old on-storage format state: Detected old on-storage format state: Detected old on-storage format state state.of: Fresh state detected, continuing with defaults This is only the output when CRC is zero (hinting at zeroed state partition). If crc != zero, then output is a little more verbose than before: state: New state registered 'state' state: Detected old on-storage format ERROR: state: init error: Invalid argument: header crc in raw format, calculated 0x7bd5c66f, found 0x00000000 state: Ignoring broken bucket 0@0x00000000... state: Detected old on-storage format ERROR: state: init error: Invalid argument: header crc in raw format, calculated 0x7bd5c66f, found 0x00000000 state: Ignoring broken bucket 1@0x00040000... state: Detected old on-storage format ERROR: state: init error: Invalid argument: header crc in raw format, calculated 0x7bd5c66f, found 0x00000000 state: Ignoring broken bucket 2@0x00080000... ERROR: state: init error: No such file or directory: no valid state copy in any bucket ERROR: state: init error: No such file or directory: format raw read failed WARNING: state state.of: Failed to load persistent state, continuing with defaults, -2 Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de> Link: https://lore.barebox.org/20211125161042.3829996-3-a.fatoum@pengutronix.de Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
* state: mark state init errors speciallyAhmad Fatoum2021-12-071-5/+2
| | | | | | | | | | First boot with uninitialized state is needlessly verbose. As preparation for making boot less noisy on fresh state, mark all the error messages with newly introduced dev_err_state_init(). Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de> Link: https://lore.barebox.org/20211125161042.3829996-2-a.fatoum@pengutronix.de Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
* include: add dedicated header for printf/printkAhmad Fatoum2021-11-011-1/+1
| | | | | | | | | | | | Including <stdio.h> for printf is a bit problematic, because it pulls in other headers for <console.h>, which includes quite a few more headers as well. To make it easier to share code between barebox and host tools make <printk.h> the new minimal header for printf and move the extra logging stuff into <linux/printk.h>. Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de> Link: https://lore.barebox.org/20211030141739.2207431-3-a.fatoum@pengutronix.de Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
* state: backend_storage: deal gracefully with runtime bucket corruptionAhmad Fatoum2020-03-091-0/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Corrupting an already selected bucket and then reading it again will crash barebox when it attempts the refresh: barebox$ state -l barebox$ mw -d /dev/eeprom0.state 0 0x42 barebox$ state -l ERROR: state: No meta data header found state: Using bucket 1@0x00000040 unable to handle NULL pointer dereference at address 0x00000000 pc : [<4fe4f1ea>] lr : [<4fe0bcb1>] sp : 4ffefd5c ip : 00000000 fp : 2ff68f04 r10: 4ffefdc8 r9 : 4b434d63 r8 : 30155f50 r7 : 00000024 r6 : 2ff68b60 r5 : 2ff68e90 r4 : 00000000 r3 : 00000024 r2 : 00000024 r1 : 30155f50 r0 : 00000000 Flags: Nzcv IRQs off FIQs off Mode SVC_32 WARNING: [<4fe4f1ea>] (memcmp+0x14/0x1a) from [<4fe0bcb1>] (bucket_refresh.isra.0+0x4d/0x78) WARNING: [<4fe0bcb1>] (bucket_refresh.isra.0+0x4d/0x78) from [<4fe0be1d>] (state_storage_read+0xd1/0x104) WARNING: [<4fe0be1d>] (state_storage_read+0xd1/0x104) from [<4fe0a5bd>] (state_do_load+0x1d/0x78) WARNING: [<4fe0a5bd>] (state_do_load+0x1d/0x78) from [<4fe04137>] (execute_command+0x23/0x4c) The memcmp called here is an optimization to skip I/O if the used bucket and the one to be refreshed compare equal. Unfortunately, if the now corrupt bucket was previously the used one, bucket->len will hold the old value and we'll run into a NULL pointer dereference. While this is quite inconvenient, it appears it doesn't affect correctness: after the reset, the corrupt bucket will be refreshed as expected. Improve upon this by setting the length to zero when we are NULLing the buffer. The zero length of the corrupted bucket will then compare unequal to used_bucket->len in bucket_refresh() and ensure we will always refresh the buffer if it becomes corrupted without an intermittent reset. Fixes: 238008b4bd8f ("state: Drop cache bucket") Cc: Enrico Jörns <ejo@pengutronix.de> Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
* common: state: harmonize code with dt-utilsUlrich Ölmann2019-02-111-1/+1
| | | | | | | | | | | | | | Linux userspace with recent glibc versions lets barebox-state suffer from linux/stat.h redefining 'struct statx' and because of that switched to the inclusion of sys/stat.h instead, see dt-utils commit 1c80e31872ae ("src: fix compilation for glibc version 2.27.9000-36.fc29 and newer"). We can follow this switch in barebox without any problems, too, as in barebox sys/stat.h includes linux/stat.h (and adds some more definitions on top that don't hurt us here). Signed-off-by: Ulrich Ölmann <u.oelmann@pengutronix.de> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
* common: state: fix formatting of "off_t" variablesUlrich Ölmann2019-02-111-10/+10
| | | | | | | | | | | | | | | | | | | | To harmonize the common codebase this ports the following dt-utils commit: | commit 89d033284cb69f834c1f2195c9e99a3d7f585cf1 | Author: Ulrich Ölmann <u.oelmann@pengutronix.de> | Date: Sun Feb 3 22:48:06 2019 +0100 | | state: fix formatting of "off_t" variables | | Explicitely casting an "off_t" variable to "long long" and formatting it via | "%lld" or "%llx" respectively makes 32- as well as 64-bit compilers | happy (tested with gcc-8.2.1 and clang-7.0.1). | | Signed-off-by: Ulrich Ölmann <u.oelmann@pengutronix.de> | Signed-off-by: Roland Hieber <rhi@pengutronix.de> Signed-off-by: Ulrich Ölmann <u.oelmann@pengutronix.de> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
* state: don't use uninitialized variableJuergen Borleis2017-09-061-1/+1
| | | | | | | Printing 'ret' makes no sense. Signed-off-by: Juergen Borleis <jbe@pengutronix.de> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
* state: use the given backend storage type nameJuergen Borleis2017-09-061-4/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | Change 119f92b27e131a0cb506fe8d8bffe8010fb14a3d already tried to fix it, but forgets the 'direct' usecase. The 'backend-storage-type' node is optional. Its default depends on the capability of the used backend memory, which means "circular" or NULL. The latter defaults to 'direct' in the routines. If it is NULL, the devicetree fixup routine skips exporting a 'backend-storage-type' node to the kernel's devicetree. But currently if the 'backend-storage-type' node is explicitly given as 'direct', it will be skipped silently and set to NULL instead. In this case the user of the 'barebox-state' tool then ends up with the warning: "No backend-storage-type found, using default" which is annoying, because it was given. Storing the given value will still use a NULL if the 'backend-storage-type' node isn't defined, but stores everything else if it is defined. Then the 'backend-storage-type' node is present in the kernel's devicetree as well. Signed-off-by: Juergen Borleis <jbe@pengutronix.de> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
* state: add debugging helpJuergen Borleis2017-09-061-1/+6
| | | | | | | | | While working on the state documentation it turns out to be helpful to have more debug messages while a developer implements a 'state' variable set and tries to configure it correctly. Signed-off-by: Juergen Borleis <jbe@pengutronix.de> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
* Merge branch 'for-next/state'Lucas Stach2017-07-311-2/+0
|\
| * state: backend_storage: remove unreachable error messagePhilipp Zabel2017-07-201-2/+0
| | | | | | | | | | | | | | This looks like a leftover. Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de> Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
* | state: fix compile warnings for dev_err expansionSteffen Trumtrar2017-07-101-1/+1
|/ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Fix the following warnings: CC common/state/backend_format_dtb.o In file included from include/common.h:33:0, from common/state/backend_format_dtb.c:18: common/state/backend_format_dtb.c: In function ‘state_backend_format_dtb_verify’: include/printk.h:52:52: warning: format ‘%d’ expects argument of type ‘int’, but argument 4 has type ‘size_t {aka long unsigned int}’ [-Wformat=] (level) <= LOGLEVEL ? dev_printf((level), (dev), (format), ##args) : 0; \ ^ include/printk.h:63:2: note: in expansion of macro ‘__dev_printf’ __dev_printf(3, (dev) , format , ## arg) ^~~~~~~~~~~~ common/state/backend_format_dtb.c:52:3: note: in expansion of macro ‘dev_err’ dev_err(fdtb->dev, "Error, stored DTB length (%d) longer than read buffer (%d)\n", ^~~~~~~ include/printk.h:52:52: warning: format ‘%d’ expects argument of type ‘int’, but argument 5 has type ‘size_t {aka long unsigned int}’ [-Wformat=] (level) <= LOGLEVEL ? dev_printf((level), (dev), (format), ##args) : 0; \ ^ include/printk.h:63:2: note: in expansion of macro ‘__dev_printf’ __dev_printf(3, (dev) , format , ## arg) ^~~~~~~~~~~~ common/state/backend_format_dtb.c:52:3: note: in expansion of macro ‘dev_err’ dev_err(fdtb->dev, "Error, stored DTB length (%d) longer than read buffer (%d)\n", ^~~~~~~ CC common/state/backend_format_raw.o In file included from include/common.h:33:0, from common/state/backend_format_raw.c:18: common/state/backend_format_raw.c: In function ‘backend_format_raw_verify’: include/printk.h:52:52: warning: format ‘%d’ expects argument of type ‘int’, but argument 4 has type ‘ssize_t {aka long int}’ [-Wformat=] (level) <= LOGLEVEL ? dev_printf((level), (dev), (format), ##args) : 0; \ ^ include/printk.h:63:2: note: in expansion of macro ‘__dev_printf’ __dev_printf(3, (dev) , format , ## arg) ^~~~~~~~~~~~ common/state/backend_format_raw.c:111:3: note: in expansion of macro ‘dev_err’ dev_err(backend_raw->dev, "Error, buffer length (%d) is shorter than the minimum required header length\n", ^~~~~~~ CC common/state/backend_storage.o In file included from common/state/backend_storage.c:24:0: common/state/backend_storage.c: In function ‘state_storage_mtd_buckets_init’: include/printk.h:52:52: warning: format ‘%zu’ expects argument of type ‘size_t’, but argument 5 has type ‘uint32_t {aka unsigned int}’ [-Wformat=] (level) <= LOGLEVEL ? dev_printf((level), (dev), (format), ##args) : 0; \ ^ include/printk.h:63:2: note: in expansion of macro ‘__dev_printf’ __dev_printf(3, (dev) , format , ## arg) ^~~~~~~~~~~~ common/state/backend_storage.c:250:3: note: in expansion of macro ‘dev_err’ dev_err(storage->dev, "Offset within the device is not aligned to eraseblocks. Offset is %ld, erasesize %zu\n", ^~~~~~~ Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de> Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
* state: backend: always pass backend type to Linux dtbSascha Hauer2017-06-231-1/+2
| | | | | | | | | | When the "backend-storage-type" property is unset in the barebox dtb then barebox will use the default. Instead of leaving the property unset in the Linux dtb, set it to the value we used as default. By making the default explicit to Linux we force Linux to the same backend type, even when the defaults may differ. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
* state: backend_storage: Set needs_refresh back to 0 after refreshingSascha Hauer2017-04-191-2/+4
| | | | | | | | | | Set needs_refresh back to 0 after refreshing so that we do not refresh it again without need. This would only happen when we read the state from the storage multiple times, which normally is not the case. However, it's more consistent like this. Reported-by: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
* state: Allow to load without authentificationSascha Hauer2017-03-311-2/+4
| | | | | | | Sometimes it's useful to be able to load a state even when it can't be authentificated. Add an option for this. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
* state: backend_storage: rename more variablesSascha Hauer2017-03-311-6/+6
| | | | | | Use "buckets" rather than "copies" in variable names. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
* state: backend_storage: make locally used variable staticSascha Hauer2017-03-311-1/+1
| | | | Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
* state: backend_storage: rewrite function docSascha Hauer2017-03-311-2/+2
| | | | | | | The function documentation for state_storage_file_buckets_init() is not very accurate. Rewrite it. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
* state: backend_storage: Rename variable desired_copies to desired_bucketsSascha Hauer2017-03-311-9/+9
| | | | | | | | | We defined what a bucket is, so rename the variable that holds the number of desired buckets from desired_copies to desired_buckets. While at it, make locally used variable static. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
* state: backend_storage: Rename variable nr_copies to n_bucketsSascha Hauer2017-03-311-12/+12
| | | | | | | We defined what a bucket is, so use n_buckets when counting buckets, and not nr_copies. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
* state: backend_circular: rewrite function docSascha Hauer2017-03-311-5/+3
| | | | | | | The commment talks about copies where buckets are meant and also claims we start at offset 0, which may not be true. Rewrite comment. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
* state: backend_circular: default to circular storageSascha Hauer2017-03-311-6/+8
| | | | | | | | Default to the new circular storage format which saves erase cycles. The old format can still be selected with backend-storage-type = "noncircular". Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
* state: backend: Add some documentationSascha Hauer2017-03-311-0/+22
| | | | | | Write some sentences to make the concepts clearer. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
* state: backend_circular: remove unnecessary warningSascha Hauer2017-03-311-4/+1
| | | | | | | It's expected that NAND flashes contain bad blocks, do not warn about them. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
* state: backend: Add more fields to struct state_backend_storageSascha Hauer2017-03-311-28/+20
| | | | | | To save a few function arguments. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
* state: bucket: Make output more informativeSascha Hauer2017-03-311-10/+15
| | | | | | | | | | | Print offset and number of the bucket along with the bucket specific messages to give a hint which bucket a message is for. Also it's pretty much expected that buckets sometimes have no data or need cleanup, so instead of complaining loudly, only write which bucket is used and which buckets are cleaned up. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
* state: Drop cache bucketSascha Hauer2017-03-311-45/+67
| | | | | | | | | | | | | | The cache bucket sits between the storage functions and the backend storage. We only read from the storage once, so there is no need to cache anything. The real purpose of the cache bucket is to keep the -EUCLEAN information when a NAND block needs to be rewritten and to keep the read buffers as long as the backend iterates over all buckets trying to find the one we want to use. This can be coded easier and more obvious in the backend code, so drop the cache bucket. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
* state: Convert all bufs to void *Sascha Hauer2017-03-311-3/+3
| | | | | | | | A void * is a much better type for a buffer than a u8 * as it can be casted to any other type implicitly. Convert all buffers used by the state framework to void *. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
* state: replace len_hint logicSascha Hauer2017-03-311-3/+6
| | | | | | | | The len_hint mechanism is rather hard to understand as it's not clear from where to where the hint is passed and also it's not clear what happens if the hint is empty or wrong. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
* state: simplify direct backendSascha Hauer2017-03-311-131/+14
| | | | | | | | | - drop support for regular files. This, if at all, is only useful for debugging. For the debugging case still a file of sufficient size can be created manually. - make stridesize mandatory. Makes the code simpler. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
* state: drop lazy_initSascha Hauer2017-03-311-33/+1
| | | | | | | | | lazy_init is an optimization that makes it possible to read only up to the first valid bucket when starting. However, when restoring consistency, immediately afterwards we have we have to initialize all buckets anyway, so being lazy doesn't give us any gain. Remove it to simplify the code. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
* state: storage: initialize variable once outside loopSascha Hauer2017-03-311-4/+6
| | | | | | | writesize is initialized with the same value in each loop iteration, Instead, initialize it once outside the loop. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
* state: pass struct state * to storage functionsSascha Hauer2017-03-311-4/+3
| | | | | | | We can get a state_backend_storage * and the device * from struct state, so pass this to the storage functions rather than the two pointers. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
* state: backend: remove len_hint argument from state_storage_readSascha Hauer2017-03-311-3/+2
| | | | | | The argument is 0 in the only caller, so remove the argument. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
* state: Use positive logicSascha Hauer2017-03-311-7/+7
| | | | | | | bools with "non" in the names are rather confusing. Switch to positive logic. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
* state: only build circular backend if MTD is enabledLucas Stach2016-07-251-2/+4
| | | | | | | | The circular backend depends on MTD symbols and is only useful if MTD is present. Exclude it from the build if MTD is not enabled. Signed-off-by: Lucas Stach <l.stach@pengutronix.de> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
* state: also append backend storage stridesizeMichael Grzeschik2016-07-081-0/+1
| | | | | Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
* state: Refactor state frameworkMarkus Pargmann2016-07-081-0/+524
The state framework grew organically over the time. Unfortunately the architecture and abstractions disappeared during this period. This patch refactors the framework to recreate the abstractions. The main focus was the backend with its storage. The main use-case was to offer better NAND support with less erase cycles and interchangeable data formats (dtb,raw). The general architecture now has a backend which consists of a data format and storage. The storage consists of multiple storage buckets each holding exactly one copy of the state data. A data format describes a data serialization for the state framework. This can be either dtb or raw. A storage bucket is a storage location which is used to store any data. There is a (new) circular type which writes changes behind the last written data and therefore reduces the number of erases. The other type is a direct bucket which writes directly to a storage offset for all non-erase storage. Furthermore this patch splits up all classes into different files in a subdirectory. This is currently all in one patch as I can't see a good way to split the changes up without having a non-working state framework in between. The following diagram shows the new architecture roughly: .----------. | state | '----------' | | v .----------------------------. | state_backend | |----------------------------| | + state_load(*state); | | + state_save(*state); | | + state_backend_init(...); | | | | | '----------------------------' | | The format describes | | how the state data | '-------------> is serialized | .--------------------------------------------. | | state_backend_format <INTERFACE> | | |--------------------------------------------| | | + verify(*format, magic, *buf, len); | | | + pack(*format, *state, **buf, len); | | | + unpack(*format, *state, *buf, len); | | | + get_packed_len(*format, *state); | | | + free(*format); | | '--------------------------------------------' | ^ ^ | * * | * * | .--------------------. .--------------------. | | backend_format_dtb | | backend_format_raw | | '--------------------' '--------------------' | | | v .----------------------------------------------------------. | state_backend_storage | |----------------------------------------------------------| | + init(...); | | + free(*storage); | | + read(*storage, *format, magic, **buf, *len, len_hint); | | + write(*storage, *buf, len); | | + restore_consistency(*storage, *buf, len); | '----------------------------------------------------------' | The backend storage is responsible to manage multiple data copies and distribute them onto several buckets. Read data is verified against the given format to ensure that the read data is correct. | | | | | v .------------------------------------------. | state_backend_storage_bucket <INTERFACE> | |------------------------------------------| | + init(*bucket); | | + write(*bucket, *buf, len); | | + read(*bucket, **buf, len_hint); | | + free(*bucket); | '------------------------------------------' ^ ^ ^ * * * * * * A storage bucket represents*exactly one data copy at one data location. A circular b*cket writes any new data to the end of the bucket (for *educed erases on NAND). A direct bucket directly writ*s at one location. * * * * * * * * * .-----------------------. * .-------------------------. | backend_bucket_direct | * | backend_bucket_circular | '-----------------------' * '-------------------------' ^ * ^ | * | | * | | * | | .-----------------------. | '--| backend_bucket_cached |---' '-----------------------' A backend_bucket_cached is a transparent bucket that directly uses another bucket as backend device and caches all accesses. Signed-off-by: Markus Pargmann <mpa@pengutronix.de> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>