diff options
| author | Manuel Bentele | 2020-09-09 17:32:57 +0200 |
|---|---|---|
| committer | Manuel Bentele | 2020-09-16 07:37:56 +0200 |
| commit | 55d94d412d4269d93e9c71a2ce59d1b9631b8957 (patch) | |
| tree | 27ef4827a02635d2c9dd84b2949079b424a3a90d /kernel/loop_file_fmt_qcow_cache.c | |
| parent | Added CMake files to build xloop kernel modules and xlosetup utility (diff) | |
| download | xloop-55d94d412d4269d93e9c71a2ce59d1b9631b8957.tar.gz xloop-55d94d412d4269d93e9c71a2ce59d1b9631b8957.tar.xz xloop-55d94d412d4269d93e9c71a2ce59d1b9631b8957.zip | |
Renamed files from loop to xloop and generate package only in Release mode
Diffstat (limited to 'kernel/loop_file_fmt_qcow_cache.c')
| -rw-r--r-- | kernel/loop_file_fmt_qcow_cache.c | 218 |
1 files changed, 0 insertions, 218 deletions
diff --git a/kernel/loop_file_fmt_qcow_cache.c b/kernel/loop_file_fmt_qcow_cache.c deleted file mode 100644 index 4ef772a..0000000 --- a/kernel/loop_file_fmt_qcow_cache.c +++ /dev/null @@ -1,218 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * loop_file_fmt_qcow_cache.c - * - * QCOW file format driver for the xloop device module. - * - * Ported QCOW2 implementation of the QEMU project (GPL-2.0): - * L2/refcount table cache for the QCOW2 format. - * - * The copyright (C) 2010 of the original code is owned by - * Kevin Wolf <kwolf@redhat.com> - * - * Copyright (C) 2019 Manuel Bentele <development@manuel-bentele.de> - */ - -#include <linux/kernel.h> -#include <linux/log2.h> -#include <linux/types.h> -#include <linux/limits.h> -#include <linux/fs.h> -#include <linux/vmalloc.h> - -#include "loop_file_fmt_qcow_main.h" -#include "loop_file_fmt_qcow_cache.h" - -static inline void *__xloop_file_fmt_qcow_cache_get_table_addr( - struct xloop_file_fmt_qcow_cache *c, int table) -{ - return (u8 *) c->table_array + (size_t) table * c->table_size; -} - -static inline int __xloop_file_fmt_qcow_cache_get_table_idx( - struct xloop_file_fmt_qcow_cache *c, void *table) -{ - ptrdiff_t table_offset = (u8 *) table - (u8 *) c->table_array; - int idx = table_offset / c->table_size; - ASSERT(idx >= 0 && idx < c->size && table_offset % c->table_size == 0); - return idx; -} - -static inline const char *__xloop_file_fmt_qcow_cache_get_name( - struct xloop_file_fmt *xlo_fmt, struct xloop_file_fmt_qcow_cache *c) -{ - struct xloop_file_fmt_qcow_data *qcow_data = xlo_fmt->private_data; - - if (c == qcow_data->refcount_block_cache) { - return "refcount block"; - } else if (c == qcow_data->l2_table_cache) { - return "L2 table"; - } else { - /* do not abort, because this is not critical */ - return "unknown"; - } -} - -struct xloop_file_fmt_qcow_cache *xloop_file_fmt_qcow_cache_create( - struct xloop_file_fmt *xlo_fmt, int num_tables, unsigned table_size) -{ -#ifdef CONFIG_DEBUG_DRIVER - struct xloop_file_fmt_qcow_data *qcow_data = xlo_fmt->private_data; -#endif - struct xloop_file_fmt_qcow_cache *c; - - ASSERT(num_tables > 0); - ASSERT(is_power_of_2(table_size)); - ASSERT(table_size >= (1 << QCOW_MIN_CLUSTER_BITS)); - ASSERT(table_size <= qcow_data->cluster_size); - - c = kzalloc(sizeof(*c), GFP_KERNEL); - if (!c) { - return NULL; - } - - c->size = num_tables; - c->table_size = table_size; - c->entries = vzalloc(sizeof(struct xloop_file_fmt_qcow_cache_table) * - num_tables); - c->table_array = vzalloc(num_tables * c->table_size); - - if (!c->entries || !c->table_array) { - vfree(c->table_array); - vfree(c->entries); - kfree(c); - c = NULL; - } - - return c; -} - -void xloop_file_fmt_qcow_cache_destroy(struct xloop_file_fmt *xlo_fmt) -{ - struct xloop_file_fmt_qcow_data *qcow_data = xlo_fmt->private_data; - struct xloop_file_fmt_qcow_cache *c = qcow_data->l2_table_cache; - int i; - - for (i = 0; i < c->size; i++) { - ASSERT(c->entries[i].ref == 0); - } - - vfree(c->table_array); - vfree(c->entries); - kfree(c); -} - -static int __xloop_file_fmt_qcow_cache_entry_flush( - struct xloop_file_fmt_qcow_cache *c, int i) -{ - if (!c->entries[i].dirty || !c->entries[i].offset) { - return 0; - } else { - printk(KERN_ERR "xloop_file_fmt_qcow: Flush dirty cache tables " - "is not supported yet\n"); - return -ENOSYS; - } -} - -static int __xloop_file_fmt_qcow_cache_do_get(struct xloop_file_fmt *xlo_fmt, - struct xloop_file_fmt_qcow_cache *c, u64 offset, void **table, - bool read_from_disk) -{ - struct xloop_device *xlo = xloop_file_fmt_get_xlo(xlo_fmt); - int i; - int ret; - int lookup_index; - u64 min_lru_counter = U64_MAX; - int min_lru_index = -1; - u64 read_offset; - size_t len; - - ASSERT(offset != 0); - - if (!IS_ALIGNED(offset, c->table_size)) { - printk_ratelimited(KERN_ERR "xloop_file_fmt_qcow: Cannot get " - "entry from %s cache: offset %llx is unaligned\n", - __xloop_file_fmt_qcow_cache_get_name(xlo_fmt, c), - offset); - return -EIO; - } - - /* Check if the table is already cached */ - i = lookup_index = (offset / c->table_size * 4) % c->size; - do { - const struct xloop_file_fmt_qcow_cache_table *t = - &c->entries[i]; - if (t->offset == offset) { - goto found; - } - if (t->ref == 0 && t->lru_counter < min_lru_counter) { - min_lru_counter = t->lru_counter; - min_lru_index = i; - } - if (++i == c->size) { - i = 0; - } - } while (i != lookup_index); - - if (min_lru_index == -1) { - BUG(); - panic("Oops: This can't happen in current synchronous code, " - "but leave the check here as a reminder for whoever " - "starts using AIO with the QCOW cache"); - } - - /* Cache miss: write a table back and replace it */ - i = min_lru_index; - - ret = __xloop_file_fmt_qcow_cache_entry_flush(c, i); - if (ret < 0) { - return ret; - } - - c->entries[i].offset = 0; - if (read_from_disk) { - read_offset = offset; - len = kernel_read(xlo->xlo_backing_file, - __xloop_file_fmt_qcow_cache_get_table_addr(c, i), - c->table_size, &read_offset); - if (len < 0) { - len = ret; - return ret; - } - } - - c->entries[i].offset = offset; - - /* And return the right table */ -found: - c->entries[i].ref++; - *table = __xloop_file_fmt_qcow_cache_get_table_addr(c, i); - - return 0; -} - -int xloop_file_fmt_qcow_cache_get(struct xloop_file_fmt *xlo_fmt, u64 offset, - void **table) -{ - struct xloop_file_fmt_qcow_data *qcow_data = xlo_fmt->private_data; - struct xloop_file_fmt_qcow_cache *c = qcow_data->l2_table_cache; - - return __xloop_file_fmt_qcow_cache_do_get(xlo_fmt, c, offset, table, - true); -} - -void xloop_file_fmt_qcow_cache_put(struct xloop_file_fmt *xlo_fmt, void **table) -{ - struct xloop_file_fmt_qcow_data *qcow_data = xlo_fmt->private_data; - struct xloop_file_fmt_qcow_cache *c = qcow_data->l2_table_cache; - int i = __xloop_file_fmt_qcow_cache_get_table_idx(c, *table); - - c->entries[i].ref--; - *table = NULL; - - if (c->entries[i].ref == 0) { - c->entries[i].lru_counter = ++c->lru_counter; - } - - ASSERT(c->entries[i].ref >= 0); -} |
