From e240b4ae86adb022e3266220ce9807dad8b51beb Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Wed, 30 Mar 2022 17:40:25 -0400 Subject: [PATCH] Update bcachefs sources to f638850417 bcachefs: bch2_trans_log_msg() --- .bcachefs_revision | 2 +- ccan/darray/LICENSE | 17 -- ccan/darray/_info | 57 ----- ccan/darray/darray.h | 355 ---------------------------- cmd_debug.c | 6 +- cmd_format.c | 30 +-- cmd_fs.c | 15 +- cmd_migrate.c | 6 +- include/linux/slab.h | 63 +++++ include/linux/types.h | 1 + include/linux/vmalloc.h | 53 ----- include/trace/events/bcachefs.h | 27 ++- libbcachefs.c | 2 +- libbcachefs.h | 2 +- libbcachefs/alloc_background.c | 5 +- libbcachefs/alloc_foreground.c | 110 ++++++--- libbcachefs/bcachefs.h | 2 +- libbcachefs/btree_iter.c | 13 +- libbcachefs/btree_types.h | 4 +- libbcachefs/btree_update.h | 2 + libbcachefs/btree_update_interior.c | 29 ++- libbcachefs/btree_update_leaf.c | 44 +++- libbcachefs/darray.h | 76 ++++++ libbcachefs/fs.c | 2 +- libbcachefs/fs.h | 4 +- libbcachefs/fsck.c | 153 +++++------- libbcachefs/move.c | 8 +- libbcachefs/subvolume.c | 41 +--- libbcachefs/subvolume.h | 38 +-- libbcachefs/subvolume_types.h | 8 +- qcow2.c | 2 +- tools-util.c | 17 +- tools-util.h | 12 +- 33 files changed, 448 insertions(+), 758 deletions(-) delete mode 100644 ccan/darray/LICENSE delete mode 100644 ccan/darray/_info delete mode 100644 ccan/darray/darray.h create mode 100644 libbcachefs/darray.h diff --git a/.bcachefs_revision b/.bcachefs_revision index 4a20b81..09f07f6 100644 --- a/.bcachefs_revision +++ b/.bcachefs_revision @@ -1 +1 @@ -7786034caa4ee7d10d25202284220513c0944ce2 +f638850417c9042dab40511e3c3ed0b1be355301 diff --git a/ccan/darray/LICENSE b/ccan/darray/LICENSE deleted file mode 100644 index 89de354..0000000 --- a/ccan/darray/LICENSE +++ /dev/null @@ -1,17 +0,0 @@ -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/ccan/darray/_info b/ccan/darray/_info deleted file mode 100644 index b6d5e4b..0000000 --- a/ccan/darray/_info +++ /dev/null @@ -1,57 +0,0 @@ -#include "config.h" -#include -#include - -#include "ccan/darray/darray.h" - -/** - * darray - Generic resizable arrays - * - * darray is a set of macros for managing dynamically-allocated arrays. - * It removes the tedium of managing realloc'd arrays with pointer, size, and - * allocated size. - * - * Example: - * #include - * #include - * - * int main(void) { - * darray(int) numbers = darray_new(); - * char buffer[32]; - * - * for (;;) { - * int *i; - * darray_foreach(i, numbers) - * printf("%d ", *i); - * if (darray_size(numbers) > 0) - * puts(""); - * - * printf("darray> "); - * fgets(buffer, sizeof(buffer), stdin); - * if (*buffer == '\0' || *buffer == '\n') - * break; - * - * darray_append(numbers, atoi(buffer)); - * } - * - * darray_free(numbers); - * - * return 0; - * } - * - * Author: Joey Adams - * License: MIT - * Version: 0.2 - */ -int main(int argc, char *argv[]) -{ - if (argc != 2) - return 1; - - if (strcmp(argv[1], "depends") == 0) { - /* Nothing. */ - return 0; - } - - return 1; -} diff --git a/ccan/darray/darray.h b/ccan/darray/darray.h deleted file mode 100644 index 7511241..0000000 --- a/ccan/darray/darray.h +++ /dev/null @@ -1,355 +0,0 @@ -/* - * Copyright (C) 2011 Joseph Adams - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef CCAN_DARRAY_H -#define CCAN_DARRAY_H - -#include -#include -#include "config.h" - -/* - * SYNOPSIS - * - * Life cycle of a darray (dynamically-allocated array): - * - * darray(int) a = darray_new(); - * darray_free(a); - * - * struct {darray(int) a;} foo; - * darray_init(foo.a); - * darray_free(foo.a); - * - * Typedefs for darrays of common types: - * - * darray_char, darray_schar, darray_uchar - * darray_short, darray_int, darray_long - * darray_ushort, darray_uint, darray_ulong - * - * Access: - * - * T darray_item(darray(T) arr, size_t index); - * size_t darray_size(darray(T) arr); - * size_t darray_alloc(darray(T) arr); - * bool darray_empty(darray(T) arr); - * - * Insertion (single item): - * - * void darray_append(darray(T) arr, T item); - * void darray_prepend(darray(T) arr, T item); - * void darray_push(darray(T) arr, T item); // same as darray_append - * - * Insertion (multiple items): - * - * void darray_append_items(darray(T) arr, T *items, size_t count); - * void darray_prepend_items(darray(T) arr, T *items, size_t count); - * - * void darray_appends(darray(T) arr, [T item, [...]]); - * void darray_prepends(darray(T) arr, [T item, [...]]); - * - * // Same functionality as above, but does not require typeof. - * void darray_appends_t(darray(T) arr, #T, [T item, [...]]); - * void darray_prepends_t(darray(T) arr, #T, [T item, [...]]); - * - * Removal: - * - * T darray_pop(darray(T) arr | darray_size(arr) != 0); - * T* darray_pop_check(darray(T*) arr); - * void darray_remove(darray(T) arr, size_t index); - * - * Replacement: - * - * void darray_from_items(darray(T) arr, T *items, size_t count); - * void darray_from_c(darray(T) arr, T c_array[N]); - * - * String buffer: - * - * void darray_append_string(darray(char) arr, const char *str); - * void darray_append_lit(darray(char) arr, char stringLiteral[N+1]); - * - * void darray_prepend_string(darray(char) arr, const char *str); - * void darray_prepend_lit(darray(char) arr, char stringLiteral[N+1]); - * - * void darray_from_string(darray(T) arr, const char *str); - * void darray_from_lit(darray(char) arr, char stringLiteral[N+1]); - * - * Size management: - * - * void darray_resize(darray(T) arr, size_t newSize); - * void darray_resize0(darray(T) arr, size_t newSize); - * - * void darray_realloc(darray(T) arr, size_t newAlloc); - * void darray_growalloc(darray(T) arr, size_t newAlloc); - * - * void darray_make_room(darray(T) arr, size_t room); - * - * Traversal: - * - * darray_foreach(T *&i, darray(T) arr) {...} - * darray_foreach_reverse(T *&i, darray(T) arr) {...} - * - * Except for darray_foreach, darray_foreach_reverse, and darray_remove, - * all macros evaluate their non-darray arguments only once. - */ - -/*** Life cycle ***/ - -#define darray(type) struct {type *item; size_t size; size_t alloc;} - -#define darray_new() {0,0,0} -#define darray_init(arr) do {(arr).item=0; (arr).size=0; (arr).alloc=0;} while(0) -#define darray_free(arr) do {free((arr).item);} while(0) - - -/* - * Typedefs for darrays of common types. These are useful - * when you want to pass a pointer to an darray(T) around. - * - * The following will produce an incompatible pointer warning: - * - * void foo(darray(int) *arr); - * darray(int) arr = darray_new(); - * foo(&arr); - * - * The workaround: - * - * void foo(darray_int *arr); - * darray_int arr = darray_new(); - * foo(&arr); - */ - -typedef darray(char) darray_char; -typedef darray(signed char) darray_schar; -typedef darray(unsigned char) darray_uchar; - -typedef darray(short) darray_short; -typedef darray(int) darray_int; -typedef darray(long) darray_long; - -typedef darray(unsigned short) darray_ushort; -typedef darray(unsigned int) darray_uint; -typedef darray(unsigned long) darray_ulong; - - -/*** Access ***/ - -#define darray_item(arr, i) ((arr).item[i]) -#define darray_size(arr) ((arr).size) -#define darray_alloc(arr) ((arr).alloc) -#define darray_empty(arr) ((arr).size == 0) - - -/*** Insertion (single item) ***/ - -#define darray_append(arr, ...) do { \ - darray_resize(arr, (arr).size+1); \ - (arr).item[(arr).size-1] = (__VA_ARGS__); \ - } while(0) -#define darray_prepend(arr, ...) do { \ - darray_resize(arr, (arr).size+1); \ - memmove((arr).item+1, (arr).item, ((arr).size-1)*sizeof(*(arr).item)); \ - (arr).item[0] = (__VA_ARGS__); \ - } while(0) -#define darray_push(arr, ...) darray_append(arr, __VA_ARGS__) - - -/*** Insertion (multiple items) ***/ - -#define darray_append_items(arr, items, count) do { \ - size_t __count = (count), __oldSize = (arr).size; \ - darray_resize(arr, __oldSize + __count); \ - memcpy((arr).item + __oldSize, items, __count * sizeof(*(arr).item)); \ - } while(0) - -#define darray_prepend_items(arr, items, count) do { \ - size_t __count = (count), __oldSize = (arr).size; \ - darray_resize(arr, __count + __oldSize); \ - memmove((arr).item + __count, (arr).item, __oldSize * sizeof(*(arr).item)); \ - memcpy((arr).item, items, __count * sizeof(*(arr).item)); \ - } while(0) - -#define darray_append_items_nullterminate(arr, items, count) do { \ - size_t __count = (count), __oldSize = (arr).size; \ - darray_resize(arr, __oldSize + __count + 1); \ - memcpy((arr).item + __oldSize, items, __count * sizeof(*(arr).item)); \ - (arr).item[--(arr).size] = 0; \ - } while(0) - -#define darray_prepend_items_nullterminate(arr, items, count) do { \ - size_t __count = (count), __oldSize = (arr).size; \ - darray_resize(arr, __count + __oldSize + 1); \ - memmove((arr).item + __count, (arr).item, __oldSize * sizeof(*(arr).item)); \ - memcpy((arr).item, items, __count * sizeof(*(arr).item)); \ - (arr).item[--(arr).size] = 0; \ - } while(0) - -#if HAVE_TYPEOF -#define darray_appends(arr, ...) darray_appends_t(arr, typeof((*(arr).item)), __VA_ARGS__) -#define darray_prepends(arr, ...) darray_prepends_t(arr, typeof((*(arr).item)), __VA_ARGS__) -#endif - -#define darray_appends_t(arr, type, ...) do { \ - type __src[] = {__VA_ARGS__}; \ - darray_append_items(arr, __src, sizeof(__src)/sizeof(*__src)); \ - } while(0) -#define darray_prepends_t(arr, type, ...) do { \ - type __src[] = {__VA_ARGS__}; \ - darray_prepend_items(arr, __src, sizeof(__src)/sizeof(*__src)); \ - } while(0) - - -/*** Removal ***/ - -/* Warning: Do not call darray_pop on an empty darray. */ -#define darray_pop(arr) ((arr).item[--(arr).size]) -#define darray_pop_check(arr) ((arr).size ? darray_pop(arr) : NULL) -/* Warning, slow: Requires copying all elements after removed item. */ -#define darray_remove(arr, index) do { \ - if (index < arr.size-1) \ - memmove(&(arr).item[index], &(arr).item[index+1], ((arr).size-1-i)*sizeof(*(arr).item)); \ - (arr).size--; \ - } while(0) - - -/*** Replacement ***/ - -#define darray_from_items(arr, items, count) do {size_t __count = (count); darray_resize(arr, __count); memcpy((arr).item, items, __count*sizeof(*(arr).item));} while(0) -#define darray_from_c(arr, c_array) darray_from_items(arr, c_array, sizeof(c_array)/sizeof(*(c_array))) - - -/*** String buffer ***/ - -#define darray_append_string(arr, str) do {const char *__str = (str); darray_append_items(arr, __str, strlen(__str)+1); (arr).size--;} while(0) -#define darray_append_lit(arr, stringLiteral) do {darray_append_items(arr, stringLiteral, sizeof(stringLiteral)); (arr).size--;} while(0) - -#define darray_prepend_string(arr, str) do { \ - const char *__str = (str); \ - darray_prepend_items_nullterminate(arr, __str, strlen(__str)); \ - } while(0) -#define darray_prepend_lit(arr, stringLiteral) \ - darray_prepend_items_nullterminate(arr, stringLiteral, sizeof(stringLiteral) - 1) - -#define darray_from_string(arr, str) do {const char *__str = (str); darray_from_items(arr, __str, strlen(__str)+1); (arr).size--;} while(0) -#define darray_from_lit(arr, stringLiteral) do {darray_from_items(arr, stringLiteral, sizeof(stringLiteral)); (arr).size--;} while(0) - - -/*** Size management ***/ - -#define darray_resize(arr, newSize) darray_growalloc(arr, (arr).size = (newSize)) -#define darray_resize0(arr, newSize) do { \ - size_t __oldSize = (arr).size, __newSize = (newSize); \ - (arr).size = __newSize; \ - if (__newSize > __oldSize) { \ - darray_growalloc(arr, __newSize); \ - memset(&(arr).item[__oldSize], 0, (__newSize - __oldSize) * sizeof(*(arr).item)); \ - } \ - } while(0) - -#define darray_realloc(arr, newAlloc) do { \ - (arr).item = realloc((arr).item, ((arr).alloc = (newAlloc)) * sizeof(*(arr).item)); \ - } while(0) -#define darray_growalloc(arr, need) do { \ - size_t __need = (need); \ - if (__need > (arr).alloc) \ - darray_realloc(arr, darray_next_alloc((arr).alloc, __need)); \ - } while(0) - -#if HAVE_STATEMENT_EXPR==1 -#define darray_make_room(arr, room) ({size_t newAlloc = (arr).size+(room); if ((arr).alloc &(arr).item[0]; ) - - -#endif /* CCAN_DARRAY_H */ - -/* - -darray_growalloc(arr, newAlloc) sees if the darray can currently hold newAlloc items; - if not, it increases the alloc to satisfy this requirement, allocating slack - space to avoid having to reallocate for every size increment. - -darray_from_string(arr, str) copies a string to an darray_char. - -darray_push(arr, item) pushes an item to the end of the darray. -darray_pop(arr) pops it back out. Be sure there is at least one item in the darray before calling. -darray_pop_check(arr) does the same as darray_pop, but returns NULL if there are no more items left in the darray. - -darray_make_room(arr, room) ensures there's 'room' elements of space after the end of the darray, and it returns a pointer to this space. -Currently requires HAVE_STATEMENT_EXPR, but I plan to remove this dependency by creating an inline function. - -The following require HAVE_TYPEOF==1 : - -darray_appends(arr, item0, item1...) appends a collection of comma-delimited items to the darray. -darray_prepends(arr, item0, item1...) prepends a collection of comma-delimited items to the darray.\ - - -Examples: - - darray(int) arr; - int *i; - - darray_appends(arr, 0,1,2,3,4); - darray_appends(arr, -5,-4,-3,-2,-1); - darray_foreach(i, arr) - printf("%d ", *i); - printf("\n"); - - darray_free(arr); - - - typedef struct {int n,d;} Fraction; - darray(Fraction) fractions; - Fraction *i; - - darray_appends(fractions, {3,4}, {3,5}, {2,1}); - darray_foreach(i, fractions) - printf("%d/%d\n", i->n, i->d); - - darray_free(fractions); -*/ diff --git a/cmd_debug.c b/cmd_debug.c index 04afea1..159835b 100644 --- a/cmd_debug.c +++ b/cmd_debug.c @@ -38,12 +38,10 @@ static void dump_one_device(struct bch_fs *c, struct bch_dev *ca, int fd, bool entire_journal) { struct bch_sb *sb = ca->disk_sb.sb; - ranges data; + ranges data = { 0 }; unsigned i; int ret; - darray_init(data); - /* Superblock: */ range_add(&data, BCH_SB_LAYOUT_SECTOR << 9, sizeof(struct bch_sb_layout)); @@ -110,7 +108,7 @@ static void dump_one_device(struct bch_fs *c, struct bch_dev *ca, int fd, qcow2_write_image(ca->disk_sb.bdev->bd_fd, fd, &data, max_t(unsigned, btree_bytes(c) / 8, block_bytes(c))); - darray_free(data); + darray_exit(data); } int cmd_dump(int argc, char *argv[]) diff --git a/cmd_format.c b/cmd_format.c index d25163a..c3debe0 100644 --- a/cmd_format.c +++ b/cmd_format.c @@ -20,11 +20,10 @@ #include -#include "ccan/darray/darray.h" - #include "cmds.h" #include "libbcachefs.h" #include "crypto.h" +#include "libbcachefs/darray.h" #include "libbcachefs/opts.h" #include "libbcachefs/super-io.h" #include "libbcachefs/util.h" @@ -114,17 +113,14 @@ u64 read_flag_list_or_die(char *opt, const char * const list[], int cmd_format(int argc, char *argv[]) { - darray(struct dev_opts) devices; - darray(char *) device_paths; + DARRAY(struct dev_opts) devices = { 0 }; + DARRAY(char *) device_paths = { 0 }; struct format_opts opts = format_opts_default(); struct dev_opts dev_opts = dev_opts_default(), *dev; bool force = false, no_passphrase = false, quiet = false, initialize = true, verbose = false; unsigned v; int opt; - darray_init(devices); - darray_init(device_paths); - struct bch_opt_strs fs_opt_strs = bch2_cmdline_opts_get(&argc, argv, OPT_FORMAT); struct bch_opts fs_opts = bch2_parse_opts(fs_opt_strs); @@ -201,9 +197,9 @@ int cmd_format(int argc, char *argv[]) initialize = false; break; case O_no_opt: - darray_append(device_paths, optarg); + darray_push(device_paths, optarg); dev_opts.path = optarg; - darray_append(devices, dev_opts); + darray_push(devices, dev_opts); dev_opts.size = 0; break; case O_quiet: @@ -222,7 +218,7 @@ int cmd_format(int argc, char *argv[]) break; } - if (darray_empty(devices)) + if (!devices.nr) die("Please supply a device"); if (opts.encrypted && !no_passphrase) { @@ -230,14 +226,14 @@ int cmd_format(int argc, char *argv[]) initialize = false; } - darray_foreach(dev, devices) + darray_for_each(devices, dev) dev->fd = open_for_format(dev->path, force); struct bch_sb *sb = bch2_format(fs_opt_strs, fs_opts, opts, - devices.item, darray_size(devices)); + devices.data, devices.nr); bch2_opt_strs_free(&fs_opt_strs); if (!quiet) { @@ -257,7 +253,7 @@ int cmd_format(int argc, char *argv[]) free(opts.passphrase); } - darray_free(devices); + darray_exit(devices); if (initialize) { struct bch_opts mount_opts = bch2_opts_empty(); @@ -269,17 +265,17 @@ int cmd_format(int argc, char *argv[]) * Start the filesystem once, to allocate the journal and create * the root directory: */ - struct bch_fs *c = bch2_fs_open(device_paths.item, - darray_size(device_paths), + struct bch_fs *c = bch2_fs_open(device_paths.data, + device_paths.nr, mount_opts); if (IS_ERR(c)) - die("error opening %s: %s", device_paths.item[0], + die("error opening %s: %s", device_paths.data[0], strerror(-PTR_ERR(c))); bch2_fs_stop(c); } - darray_free(device_paths); + darray_exit(device_paths); return 0; } diff --git a/cmd_fs.c b/cmd_fs.c index 6bf00c0..3121e5b 100644 --- a/cmd_fs.c +++ b/cmd_fs.c @@ -4,11 +4,10 @@ #include -#include "ccan/darray/darray.h" - #include "linux/sort.h" #include "libbcachefs/bcachefs_ioctl.h" +#include "libbcachefs/darray.h" #include "libbcachefs/opts.h" #include "cmds.h" @@ -115,7 +114,7 @@ static struct dev_name *dev_idx_to_name(dev_names *dev_names, unsigned idx) { struct dev_name *dev; - darray_foreach(dev, *dev_names) + darray_for_each(*dev_names, dev) if (dev->idx == idx) return dev; @@ -256,22 +255,22 @@ static void fs_usage_to_text(struct printbuf *out, const char *path) free(u); - sort(&darray_item(dev_names, 0), darray_size(dev_names), - sizeof(darray_item(dev_names, 0)), dev_by_label_cmp, NULL); + sort(dev_names.data, dev_names.nr, + sizeof(dev_names.data[0]), dev_by_label_cmp, NULL); out->tabstops[0] = 16; out->tabstops[1] = 36; out->tabstops[2] = 52; out->tabstops[3] = 68; - darray_foreach(dev, dev_names) + darray_for_each(dev_names, dev) dev_usage_to_text(out, fs, dev); - darray_foreach(dev, dev_names) { + darray_for_each(dev_names, dev) { free(dev->dev); free(dev->label); } - darray_free(dev_names); + darray_exit(dev_names); bcache_fs_close(fs); } diff --git a/cmd_migrate.c b/cmd_migrate.c index 4da3ab1..08ec7de 100644 --- a/cmd_migrate.c +++ b/cmd_migrate.c @@ -530,7 +530,7 @@ static ranges reserve_new_fs_space(const char *file_path, unsigned block_size, struct fiemap_iter iter; struct fiemap_extent e; - ranges extents = { NULL }; + ranges extents = { 0 }; fiemap_for_each(fd, iter, e) { if (e.fe_flags & (FIEMAP_EXTENT_UNKNOWN| @@ -603,7 +603,7 @@ static void copy_fs(struct bch_fs *c, int src_fd, const char *src_path, update_inode(c, &root_inode); - darray_free(s.extents); + darray_exit(s.extents); genradix_free(&s.hardlinks); } @@ -613,7 +613,7 @@ static void find_superblock_space(ranges extents, { struct range *i; - darray_foreach(i, extents) { + darray_for_each(extents, i) { u64 start = round_up(max(256ULL << 10, i->start), dev->bucket_size << 9); u64 end = round_down(i->end, diff --git a/include/linux/slab.h b/include/linux/slab.h index 557c041..17fe235 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -7,10 +7,14 @@ #include #include +#include #include #include #include +#include +#include + #define ARCH_KMALLOC_MINALIGN 16 #define KMALLOC_MAX_SIZE SIZE_MAX @@ -58,6 +62,16 @@ static inline void *krealloc(void *old, size_t size, gfp_t flags) return new; } +static inline void *krealloc_array(void *p, size_t new_n, size_t new_size, gfp_t flags) +{ + size_t bytes; + + if (unlikely(check_mul_overflow(new_n, new_size, &bytes))) + return NULL; + + return krealloc(p, bytes, flags); +} + #define kzalloc(size, flags) kmalloc(size, flags|__GFP_ZERO) #define kmalloc_array(n, size, flags) \ ((size) != 0 && (n) > SIZE_MAX / (size) \ @@ -174,4 +188,53 @@ static inline struct kmem_cache *kmem_cache_create(size_t obj_size) #define KMEM_CACHE(_struct, _flags) kmem_cache_create(sizeof(struct _struct)) +#define PAGE_KERNEL 0 +#define PAGE_KERNEL_EXEC 1 + +#define vfree(p) free(p) + +static inline void *__vmalloc(unsigned long size, gfp_t gfp_mask) +{ + unsigned i = 0; + void *p; + + size = round_up(size, PAGE_SIZE); + + do { + run_shrinkers(gfp_mask, i != 0); + + p = aligned_alloc(PAGE_SIZE, size); + if (p && gfp_mask & __GFP_ZERO) + memset(p, 0, size); + } while (!p && i++ < 10); + + return p; +} + +static inline void *vmalloc_exec(unsigned long size, gfp_t gfp_mask) +{ + void *p; + + p = __vmalloc(size, gfp_mask); + if (!p) + return NULL; + + if (mprotect(p, size, PROT_READ|PROT_WRITE|PROT_EXEC)) { + vfree(p); + return NULL; + } + + return p; +} + +static inline void *vmalloc(unsigned long size) +{ + return __vmalloc(size, GFP_KERNEL); +} + +static inline void *vzalloc(unsigned long size) +{ + return __vmalloc(size, GFP_KERNEL|__GFP_ZERO); +} + #endif /* __TOOLS_LINUX_SLAB_H */ diff --git a/include/linux/types.h b/include/linux/types.h index 77f9673..7eb2222 100644 --- a/include/linux/types.h +++ b/include/linux/types.h @@ -6,6 +6,7 @@ #include #include +#include #include #define __SANE_USERSPACE_TYPES__ /* For PPC64, to get LL64 types */ diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h index 965e341..55fffb5 100644 --- a/include/linux/vmalloc.h +++ b/include/linux/vmalloc.h @@ -1,59 +1,6 @@ #ifndef __TOOLS_LINUX_VMALLOC_H #define __TOOLS_LINUX_VMALLOC_H -#include -#include - #include "linux/slab.h" -#include "tools-util.h" - -#define PAGE_KERNEL 0 -#define PAGE_KERNEL_EXEC 1 - -#define vfree(p) free(p) - -static inline void *__vmalloc(unsigned long size, gfp_t gfp_mask) -{ - unsigned i = 0; - void *p; - - size = round_up(size, PAGE_SIZE); - - do { - run_shrinkers(gfp_mask, i != 0); - - p = aligned_alloc(PAGE_SIZE, size); - if (p && gfp_mask & __GFP_ZERO) - memset(p, 0, size); - } while (!p && i++ < 10); - - return p; -} - -static inline void *vmalloc_exec(unsigned long size, gfp_t gfp_mask) -{ - void *p; - - p = __vmalloc(size, gfp_mask); - if (!p) - return NULL; - - if (mprotect(p, size, PROT_READ|PROT_WRITE|PROT_EXEC)) { - vfree(p); - return NULL; - } - - return p; -} - -static inline void *vmalloc(unsigned long size) -{ - return __vmalloc(size, GFP_KERNEL); -} - -static inline void *vzalloc(unsigned long size) -{ - return __vmalloc(size, GFP_KERNEL|__GFP_ZERO); -} #endif /* __TOOLS_LINUX_VMALLOC_H */ diff --git a/include/trace/events/bcachefs.h b/include/trace/events/bcachefs.h index 08de7e6..ac2aecd 100644 --- a/include/trace/events/bcachefs.h +++ b/include/trace/events/bcachefs.h @@ -493,32 +493,49 @@ DEFINE_EVENT(bucket_alloc, bucket_alloc, TRACE_EVENT(bucket_alloc_fail, TP_PROTO(struct bch_dev *ca, const char *alloc_reserve, - u64 avail, u64 need_journal_commit, - bool nonblocking), - TP_ARGS(ca, alloc_reserve, avail, need_journal_commit, nonblocking), + u64 avail, + u64 seen, + u64 open, + u64 need_journal_commit, + u64 nouse, + bool nonblocking, + int ret), + TP_ARGS(ca, alloc_reserve, avail, seen, open, need_journal_commit, nouse, nonblocking, ret), TP_STRUCT__entry( __field(dev_t, dev ) __array(char, reserve, 16 ) __field(u64, avail ) + __field(u64, seen ) + __field(u64, open ) __field(u64, need_journal_commit ) + __field(u64, nouse ) __field(bool, nonblocking ) + __field(int, ret ) ), TP_fast_assign( __entry->dev = ca->dev; strlcpy(__entry->reserve, alloc_reserve, sizeof(__entry->reserve)); __entry->avail = avail; + __entry->seen = seen; + __entry->open = open; __entry->need_journal_commit = need_journal_commit; + __entry->nouse = nouse; __entry->nonblocking = nonblocking; + __entry->ret = ret; ), - TP_printk("%d,%d reserve %s avail %llu need_journal_commit %llu nonblocking %u", + TP_printk("%d,%d reserve %s avail %llu seen %llu open %llu need_journal_commit %llu nouse %llu nonblocking %u ret %i", MAJOR(__entry->dev), MINOR(__entry->dev), __entry->reserve, __entry->avail, + __entry->seen, + __entry->open, __entry->need_journal_commit, - __entry->nonblocking) + __entry->nouse, + __entry->nonblocking, + __entry->ret) ); DEFINE_EVENT(bucket_alloc, open_bucket_alloc_fail, diff --git a/libbcachefs.c b/libbcachefs.c index ceca428..8ba0194 100644 --- a/libbcachefs.c +++ b/libbcachefs.c @@ -713,7 +713,7 @@ dev_names bchu_fs_get_devices(struct bchfs_handle fs) n.label = read_file_str(fs.sysfs_fd, label_attr); free(label_attr); - darray_append(devs, n); + darray_push(devs, n); } closedir(dir); diff --git a/libbcachefs.h b/libbcachefs.h index 3a83e16..17e8eef 100644 --- a/libbcachefs.h +++ b/libbcachefs.h @@ -237,7 +237,7 @@ struct dev_name { char *label; uuid_le uuid; }; -typedef darray(struct dev_name) dev_names; +typedef DARRAY(struct dev_name) dev_names; dev_names bchu_fs_get_devices(struct bchfs_handle); diff --git a/libbcachefs/alloc_background.c b/libbcachefs/alloc_background.c index 81cbfeb..07a7699 100644 --- a/libbcachefs/alloc_background.c +++ b/libbcachefs/alloc_background.c @@ -862,7 +862,9 @@ static void bch2_do_discards_work(struct work_struct *work) bch2_bucket_is_open_safe(c, k.k->p.inode, k.k->p.offset)) continue; - ret = __bch2_trans_do(&trans, NULL, NULL, 0, + ret = __bch2_trans_do(&trans, NULL, NULL, + BTREE_INSERT_USE_RESERVE| + BTREE_INSERT_NOFAIL, bch2_clear_need_discard(&trans, k.k->p, ca, &discard_done)); if (ret) break; @@ -954,6 +956,7 @@ static void bch2_do_invalidates_work(struct work_struct *work) for_each_member_device(ca, c, i) while (!ret && should_invalidate_buckets(ca)) ret = __bch2_trans_do(&trans, NULL, NULL, + BTREE_INSERT_USE_RESERVE| BTREE_INSERT_NOFAIL, invalidate_one_bucket(&trans, ca)); diff --git a/libbcachefs/alloc_foreground.c b/libbcachefs/alloc_foreground.c index 5b11493..538b597 100644 --- a/libbcachefs/alloc_foreground.c +++ b/libbcachefs/alloc_foreground.c @@ -192,20 +192,26 @@ static inline unsigned open_buckets_reserved(enum alloc_reserve reserve) static struct open_bucket *__try_alloc_bucket(struct bch_fs *c, struct bch_dev *ca, enum alloc_reserve reserve, struct bkey_alloc_unpacked a, - size_t *need_journal_commit, + u64 *skipped_open, + u64 *skipped_need_journal_commit, + u64 *skipped_nouse, struct closure *cl) { struct open_bucket *ob; - if (unlikely(ca->buckets_nouse && test_bit(a.bucket, ca->buckets_nouse))) + if (unlikely(ca->buckets_nouse && test_bit(a.bucket, ca->buckets_nouse))) { + (*skipped_nouse)++; return NULL; + } - if (bch2_bucket_is_open(c, ca->dev_idx, a.bucket)) + if (bch2_bucket_is_open(c, ca->dev_idx, a.bucket)) { + (*skipped_open)++; return NULL; + } if (bch2_bucket_needs_journal_commit(&c->buckets_waiting_for_journal, c->journal.flushed_seq_ondisk, ca->dev_idx, a.bucket)) { - (*need_journal_commit)++; + (*skipped_need_journal_commit)++; return NULL; } @@ -227,6 +233,7 @@ static struct open_bucket *__try_alloc_bucket(struct bch_fs *c, struct bch_dev * /* Recheck under lock: */ if (bch2_bucket_is_open(c, ca->dev_idx, a.bucket)) { spin_unlock(&c->freelist_lock); + (*skipped_open)++; return NULL; } @@ -267,7 +274,9 @@ static struct open_bucket *__try_alloc_bucket(struct bch_fs *c, struct bch_dev * static struct open_bucket *try_alloc_bucket(struct btree_trans *trans, struct bch_dev *ca, enum alloc_reserve reserve, u64 free_entry, - size_t *need_journal_commit, + u64 *skipped_open, + u64 *skipped_need_journal_commit, + u64 *skipped_nouse, struct closure *cl) { struct bch_fs *c = trans->c; @@ -317,7 +326,11 @@ static struct open_bucket *try_alloc_bucket(struct btree_trans *trans, struct bc goto err; } - ob = __try_alloc_bucket(c, ca, reserve, a, need_journal_commit, cl); + ob = __try_alloc_bucket(c, ca, reserve, a, + skipped_open, + skipped_need_journal_commit, + skipped_nouse, + cl); err: bch2_trans_iter_exit(trans, &iter); printbuf_exit(&buf); @@ -360,8 +373,11 @@ static noinline struct open_bucket * bch2_bucket_alloc_trans_early(struct btree_trans *trans, struct bch_dev *ca, enum alloc_reserve reserve, - u64 *b, - size_t *need_journal_commit, + u64 *cur_bucket, + u64 *buckets_seen, + u64 *skipped_open, + u64 *skipped_need_journal_commit, + u64 *skipped_nouse, struct closure *cl) { struct btree_iter iter; @@ -369,10 +385,10 @@ bch2_bucket_alloc_trans_early(struct btree_trans *trans, struct open_bucket *ob = NULL; int ret; - *b = max_t(u64, *b, ca->mi.first_bucket); - *b = max_t(u64, *b, ca->new_fs_bucket_idx); + *cur_bucket = max_t(u64, *cur_bucket, ca->mi.first_bucket); + *cur_bucket = max_t(u64, *cur_bucket, ca->new_fs_bucket_idx); - for_each_btree_key(trans, iter, BTREE_ID_alloc, POS(ca->dev_idx, *b), + for_each_btree_key(trans, iter, BTREE_ID_alloc, POS(ca->dev_idx, *cur_bucket), BTREE_ITER_SLOTS, k, ret) { struct bkey_alloc_unpacked a; @@ -388,14 +404,19 @@ bch2_bucket_alloc_trans_early(struct btree_trans *trans, if (bucket_state(a) != BUCKET_free) continue; + (*buckets_seen)++; + ob = __try_alloc_bucket(trans->c, ca, reserve, a, - need_journal_commit, cl); + skipped_open, + skipped_need_journal_commit, + skipped_nouse, + cl); if (ob) break; } bch2_trans_iter_exit(trans, &iter); - *b = iter.pos.offset; + *cur_bucket = iter.pos.offset; return ob ?: ERR_PTR(ret ?: -FREELIST_EMPTY); } @@ -403,8 +424,11 @@ bch2_bucket_alloc_trans_early(struct btree_trans *trans, static struct open_bucket *bch2_bucket_alloc_trans(struct btree_trans *trans, struct bch_dev *ca, enum alloc_reserve reserve, - u64 *b, - size_t *need_journal_commit, + u64 *cur_bucket, + u64 *buckets_seen, + u64 *skipped_open, + u64 *skipped_need_journal_commit, + u64 *skipped_nouse, struct closure *cl) { struct btree_iter iter; @@ -413,26 +437,37 @@ static struct open_bucket *bch2_bucket_alloc_trans(struct btree_trans *trans, int ret; if (unlikely(!ca->mi.freespace_initialized)) - return bch2_bucket_alloc_trans_early(trans, ca, reserve, b, - need_journal_commit, cl); + return bch2_bucket_alloc_trans_early(trans, ca, reserve, + cur_bucket, + buckets_seen, + skipped_open, + skipped_need_journal_commit, + skipped_nouse, + cl); BUG_ON(ca->new_fs_bucket_idx); for_each_btree_key(trans, iter, BTREE_ID_freespace, - POS(ca->dev_idx, *b), 0, k, ret) { + POS(ca->dev_idx, *cur_bucket), 0, k, ret) { if (k.k->p.inode != ca->dev_idx) break; - for (*b = max(*b, bkey_start_offset(k.k)); - *b != k.k->p.offset && !ob; - (*b)++) { + for (*cur_bucket = max(*cur_bucket, bkey_start_offset(k.k)); + *cur_bucket != k.k->p.offset && !ob; + (*cur_bucket)++) { if (btree_trans_too_many_iters(trans)) { ob = ERR_PTR(-EINTR); break; } - ob = try_alloc_bucket(trans, ca, reserve, *b, - need_journal_commit, cl); + (*buckets_seen)++; + + ob = try_alloc_bucket(trans, ca, reserve, + *cur_bucket, + skipped_open, + skipped_need_journal_commit, + skipped_nouse, + cl); } if (ob) break; @@ -453,9 +488,12 @@ struct open_bucket *bch2_bucket_alloc(struct bch_fs *c, struct bch_dev *ca, struct closure *cl) { struct open_bucket *ob = NULL; - size_t need_journal_commit = 0; u64 avail = dev_buckets_available(ca, reserve); - u64 b = 0; + u64 cur_bucket = 0; + u64 buckets_seen = 0; + u64 skipped_open = 0; + u64 skipped_need_journal_commit = 0; + u64 skipped_nouse = 0; int ret; if (may_alloc_partial) { @@ -483,19 +521,27 @@ again: } ret = bch2_trans_do(c, NULL, NULL, 0, - PTR_ERR_OR_ZERO(ob = bch2_bucket_alloc_trans(&trans, - ca, reserve, &b, - &need_journal_commit, cl))); - - if (need_journal_commit * 2 > avail) + PTR_ERR_OR_ZERO(ob = bch2_bucket_alloc_trans(&trans, ca, reserve, + &cur_bucket, + &buckets_seen, + &skipped_open, + &skipped_need_journal_commit, + &skipped_nouse, + cl))); + + if (skipped_need_journal_commit * 2 > avail) bch2_journal_flush_async(&c->journal, NULL); err: if (!ob) ob = ERR_PTR(ret ?: -FREELIST_EMPTY); - if (ob == ERR_PTR(-FREELIST_EMPTY)) { + if (IS_ERR(ob)) { trace_bucket_alloc_fail(ca, bch2_alloc_reserves[reserve], avail, - need_journal_commit, cl == NULL); + buckets_seen, + skipped_open, + skipped_need_journal_commit, + skipped_nouse, + cl == NULL, PTR_ERR(ob)); atomic_long_inc(&c->bucket_alloc_fail); } diff --git a/libbcachefs/bcachefs.h b/libbcachefs/bcachefs.h index a4ef9aa..9877037 100644 --- a/libbcachefs/bcachefs.h +++ b/libbcachefs/bcachefs.h @@ -649,7 +649,7 @@ struct bch_fs { struct mutex snapshot_table_lock; struct work_struct snapshot_delete_work; struct work_struct snapshot_wait_for_pagecache_and_delete_work; - struct snapshot_id_list snapshots_unlinked; + snapshot_id_list snapshots_unlinked; struct mutex snapshots_unlinked_lock; /* BTREE CACHE */ diff --git a/libbcachefs/btree_iter.c b/libbcachefs/btree_iter.c index 56c493c..25d254e 100644 --- a/libbcachefs/btree_iter.c +++ b/libbcachefs/btree_iter.c @@ -1686,6 +1686,7 @@ bch2_btree_path_make_mut(struct btree_trans *trans, btree_trans_verify_sorted(trans); } + path->should_be_locked = false; return path; } @@ -1705,8 +1706,7 @@ bch2_btree_path_set_pos(struct btree_trans *trans, path = bch2_btree_path_make_mut(trans, path, intent, ip); - path->pos = new_pos; - path->should_be_locked = false; + path->pos = new_pos; bch2_btree_path_check_sort(trans, path, cmp); @@ -1720,6 +1720,7 @@ bch2_btree_path_set_pos(struct btree_trans *trans, l = btree_path_up_until_good_node(trans, path, cmp); if (btree_path_node(path, l)) { + BUG_ON(!btree_node_locked(path, l)); /* * We might have to skip over many keys, or just a few: try * advancing the node iterator, and if we have to skip over too @@ -1923,6 +1924,7 @@ struct btree_path *bch2_path_get(struct btree_trans *trans, BUG_ON(trans->restarted); btree_trans_verify_sorted(trans); + bch2_trans_verify_locks(trans); trans_for_each_path_inorder(trans, path, i) { if (__btree_path_cmp(path, @@ -2114,6 +2116,7 @@ struct btree *bch2_btree_iter_next_node(struct btree_iter *iter) btree_node_unlock(path, path->level); path->l[path->level].b = BTREE_ITER_NO_NODE_UP; path->level++; + btree_path_set_dirty(path, BTREE_ITER_NEED_TRAVERSE); return NULL; } @@ -2121,6 +2124,7 @@ struct btree *bch2_btree_iter_next_node(struct btree_iter *iter) __bch2_btree_path_unlock(path); path->l[path->level].b = BTREE_ITER_NO_NODE_GET_LOCKS; path->l[path->level + 1].b = BTREE_ITER_NO_NODE_GET_LOCKS; + btree_path_set_dirty(path, BTREE_ITER_NEED_TRAVERSE); trace_trans_restart_relock_next_node(trans->fn, _THIS_IP_, path->btree_id, &path->pos); btree_trans_restart(trans); @@ -3055,8 +3059,7 @@ void bch2_trans_begin(struct btree_trans *trans) trans->mem_top = 0; trans->hooks = NULL; - trans->extra_journal_entries = NULL; - trans->extra_journal_entry_u64s = 0; + trans->extra_journal_entries.nr = 0; if (trans->fs_usage_deltas) { trans->fs_usage_deltas->used = 0; @@ -3189,6 +3192,8 @@ void bch2_trans_exit(struct btree_trans *trans) bch2_journal_preres_put(&c->journal, &trans->journal_preres); + kfree(trans->extra_journal_entries.data); + if (trans->fs_usage_deltas) { if (trans->fs_usage_deltas->size + sizeof(trans->fs_usage_deltas) == REPLICAS_DELTA_LIST_MAX) diff --git a/libbcachefs/btree_types.h b/libbcachefs/btree_types.h index 993f04f..b86a721 100644 --- a/libbcachefs/btree_types.h +++ b/libbcachefs/btree_types.h @@ -8,6 +8,7 @@ #include "bkey_methods.h" #include "buckets_types.h" +#include "darray.h" #include "journal_types.h" struct open_bucket; @@ -417,8 +418,7 @@ struct btree_trans { /* update path: */ struct btree_trans_commit_hook *hooks; - struct jset_entry *extra_journal_entries; - unsigned extra_journal_entry_u64s; + DARRAY(u64) extra_journal_entries; struct journal_entry_pin *journal_pin; struct journal_res journal_res; diff --git a/libbcachefs/btree_update.h b/libbcachefs/btree_update.h index ca142f9..ad13b07 100644 --- a/libbcachefs/btree_update.h +++ b/libbcachefs/btree_update.h @@ -80,6 +80,8 @@ void bch2_trans_commit_hook(struct btree_trans *, struct btree_trans_commit_hook *); int __bch2_trans_commit(struct btree_trans *); +int bch2_trans_log_msg(struct btree_trans *, const char *); + /** * bch2_trans_commit - insert keys at given iterator positions * diff --git a/libbcachefs/btree_update_interior.c b/libbcachefs/btree_update_interior.c index c2232f8..42ae3b0 100644 --- a/libbcachefs/btree_update_interior.c +++ b/libbcachefs/btree_update_interior.c @@ -532,8 +532,15 @@ static int btree_update_nodes_written_trans(struct btree_trans *trans, struct bkey_i *k; int ret; - trans->extra_journal_entries = (void *) &as->journal_entries[0]; - trans->extra_journal_entry_u64s = as->journal_u64s; + ret = darray_make_room(trans->extra_journal_entries, as->journal_u64s); + if (ret) + return ret; + + memcpy(&darray_top(trans->extra_journal_entries), + as->journal_entries, + as->journal_u64s * sizeof(u64)); + trans->extra_journal_entries.nr += as->journal_u64s; + trans->journal_pin = &as->journal; for_each_keylist_key(&as->new_keys, k) { @@ -1899,7 +1906,6 @@ static int __bch2_btree_node_update_key(struct btree_trans *trans, struct bch_fs *c = trans->c; struct btree_iter iter2 = { NULL }; struct btree *parent; - u64 journal_entries[BKEY_BTREE_PTR_U64s_MAX]; int ret; if (!skip_triggers) { @@ -1933,6 +1939,7 @@ static int __bch2_btree_node_update_key(struct btree_trans *trans, btree_node_unlock(iter2.path, iter2.path->level); path_l(iter2.path)->b = BTREE_ITER_NO_NODE_UP; iter2.path->level++; + btree_path_set_dirty(iter2.path, BTREE_ITER_NEED_TRAVERSE); bch2_btree_path_check_sort(trans, iter2.path, 0); @@ -1943,12 +1950,16 @@ static int __bch2_btree_node_update_key(struct btree_trans *trans, } else { BUG_ON(btree_node_root(c, b) != b); - trans->extra_journal_entries = (void *) &journal_entries[0]; - trans->extra_journal_entry_u64s = - journal_entry_set((void *) &journal_entries[0], - BCH_JSET_ENTRY_btree_root, - b->c.btree_id, b->c.level, - new_key, new_key->k.u64s); + ret = darray_make_room(trans->extra_journal_entries, + jset_u64s(new_key->k.u64s)); + if (ret) + return ret; + + journal_entry_set((void *) &darray_top(trans->extra_journal_entries), + BCH_JSET_ENTRY_btree_root, + b->c.btree_id, b->c.level, + new_key, new_key->k.u64s); + trans->extra_journal_entries.nr += jset_u64s(new_key->k.u64s); } ret = bch2_trans_commit(trans, NULL, NULL, diff --git a/libbcachefs/btree_update_leaf.c b/libbcachefs/btree_update_leaf.c index 8d185c7..6f4ee55 100644 --- a/libbcachefs/btree_update_leaf.c +++ b/libbcachefs/btree_update_leaf.c @@ -700,13 +700,13 @@ bch2_trans_commit_write_locked(struct btree_trans *trans, trans->journal_res.seq = c->journal.replay_journal_seq; } - if (unlikely(trans->extra_journal_entry_u64s)) { + if (unlikely(trans->extra_journal_entries.nr)) { memcpy_u64s_small(journal_res_entry(&c->journal, &trans->journal_res), - trans->extra_journal_entries, - trans->extra_journal_entry_u64s); + trans->extra_journal_entries.data, + trans->extra_journal_entries.nr); - trans->journal_res.offset += trans->extra_journal_entry_u64s; - trans->journal_res.u64s -= trans->extra_journal_entry_u64s; + trans->journal_res.offset += trans->extra_journal_entries.nr; + trans->journal_res.u64s -= trans->extra_journal_entries.nr; } /* @@ -1088,7 +1088,7 @@ int __bch2_trans_commit(struct btree_trans *trans) int ret = 0; if (!trans->nr_updates && - !trans->extra_journal_entry_u64s) + !trans->extra_journal_entries.nr) goto out_reset; if (trans->flags & BTREE_INSERT_GC_LOCK_HELD) @@ -1112,7 +1112,7 @@ int __bch2_trans_commit(struct btree_trans *trans) memset(&trans->journal_preres, 0, sizeof(trans->journal_preres)); - trans->journal_u64s = trans->extra_journal_entry_u64s; + trans->journal_u64s = trans->extra_journal_entries.nr; trans->journal_preres_u64s = 0; trans->journal_transaction_names = READ_ONCE(c->opts.journal_transaction_names); @@ -1170,8 +1170,7 @@ out_reset: trans->extra_journal_res = 0; trans->nr_updates = 0; trans->hooks = NULL; - trans->extra_journal_entries = NULL; - trans->extra_journal_entry_u64s = 0; + trans->extra_journal_entries.nr = 0; if (trans->fs_usage_deltas) { trans->fs_usage_deltas->used = 0; @@ -1739,3 +1738,30 @@ int bch2_btree_delete_range(struct bch_fs *c, enum btree_id id, bch2_btree_delete_range_trans(&trans, id, start, end, update_flags, journal_seq)); } + +int bch2_trans_log_msg(struct btree_trans *trans, const char *msg) +{ + unsigned len = strlen(msg); + unsigned u64s = DIV_ROUND_UP(len, sizeof(u64)); + struct jset_entry_log *l; + int ret; + + ret = darray_make_room(trans->extra_journal_entries, jset_u64s(u64s)); + if (ret) + return ret; + + l = (void *) &darray_top(trans->extra_journal_entries); + l->entry.u64s = cpu_to_le16(u64s); + l->entry.btree_id = 0; + l->entry.level = 1; + l->entry.type = BCH_JSET_ENTRY_log; + l->entry.pad[0] = 0; + l->entry.pad[1] = 0; + l->entry.pad[2] = 0; + memcpy(l->d, msg, len); + while (len & 7) + l->d[len++] = '\0'; + + trans->extra_journal_entries.nr += jset_u64s(u64s); + return 0; +} diff --git a/libbcachefs/darray.h b/libbcachefs/darray.h new file mode 100644 index 0000000..745b1cd --- /dev/null +++ b/libbcachefs/darray.h @@ -0,0 +1,76 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _BCACHEFS_DARRAY_H +#define _BCACHEFS_DARRAY_H + +/* + * Dynamic arrays: + * + * Inspired by CCAN's darray + */ + +#include "util.h" +#include + +#define DARRAY(type) \ +struct { \ + size_t nr, size; \ + type *data; \ +} + +typedef DARRAY(void) darray_void; + +static inline int __darray_make_room(darray_void *d, size_t t_size, size_t more) +{ + if (d->nr + more > d->size) { + size_t new_size = roundup_pow_of_two(d->nr + more); + void *data = krealloc_array(d->data, new_size, t_size, GFP_KERNEL); + + if (!data) + return -ENOMEM; + + d->data = data; + d->size = new_size; + } + + return 0; +} + +#define darray_make_room(_d, _more) \ + __darray_make_room((darray_void *) &(_d), sizeof((_d).data[0]), (_more)) + +#define darray_top(_d) ((_d).data[(_d).nr]) + +#define darray_push(_d, _item) \ +({ \ + int _ret = darray_make_room((_d), 1); \ + \ + if (!_ret) \ + (_d).data[(_d).nr++] = (_item); \ + _ret; \ +}) + +#define darray_insert_item(_d, _pos, _item) \ +({ \ + int _ret = darray_make_room((_d), 1); \ + \ + if (!_ret) \ + array_insert_item((_d).data, (_d).nr, (_pos), (_item)); \ + _ret; \ +}) + +#define darray_for_each(_d, _i) \ + for (_i = (_d).data; _i < (_d).data + (_d).nr; _i++) + +#define darray_init(_d) \ +do { \ + (_d).data = NULL; \ + (_d).nr = (_d).size = 0; \ +} while (0) + +#define darray_exit(_d) \ +do { \ + kfree((_d).data); \ + darray_init(_d); \ +} while (0) + +#endif /* _BCACHEFS_DARRAY_H */ diff --git a/libbcachefs/fs.c b/libbcachefs/fs.c index 9fc6c39..d462c06 100644 --- a/libbcachefs/fs.c +++ b/libbcachefs/fs.c @@ -1477,7 +1477,7 @@ static void bch2_evict_inode(struct inode *vinode) } void bch2_evict_subvolume_inodes(struct bch_fs *c, - struct snapshot_id_list *s) + snapshot_id_list *s) { struct super_block *sb = c->vfs_sb; struct inode *inode; diff --git a/libbcachefs/fs.h b/libbcachefs/fs.h index b2211ec..9f4b57e 100644 --- a/libbcachefs/fs.h +++ b/libbcachefs/fs.h @@ -191,7 +191,7 @@ int bch2_setattr_nonsize(struct user_namespace *, struct iattr *); int __bch2_unlink(struct inode *, struct dentry *, bool); -void bch2_evict_subvolume_inodes(struct bch_fs *, struct snapshot_id_list *); +void bch2_evict_subvolume_inodes(struct bch_fs *, snapshot_id_list *); void bch2_vfs_exit(void); int bch2_vfs_init(void); @@ -199,7 +199,7 @@ int bch2_vfs_init(void); #else static inline void bch2_evict_subvolume_inodes(struct bch_fs *c, - struct snapshot_id_list *s) {} + snapshot_id_list *s) {} static inline void bch2_vfs_exit(void) {} static inline int bch2_vfs_init(void) { return 0; } diff --git a/libbcachefs/fsck.c b/libbcachefs/fsck.c index 8783b95..2582ddf 100644 --- a/libbcachefs/fsck.c +++ b/libbcachefs/fsck.c @@ -3,6 +3,7 @@ #include "bcachefs.h" #include "bkey_buf.h" #include "btree_update.h" +#include "darray.h" #include "dirent.h" #include "error.h" #include "fs-common.h" @@ -471,11 +472,11 @@ static int snapshots_seen_update(struct bch_fs *c, struct snapshots_seen *s, str pos.snapshot = snapshot_t(c, pos.snapshot)->equiv; if (bkey_cmp(s->pos, pos)) - s->nr = 0; + s->ids.nr = 0; s->pos = pos; /* Might get called multiple times due to lock restarts */ - if (s->nr && s->d[s->nr - 1] == pos.snapshot) + if (s->ids.nr && s->ids.data[s->ids.nr - 1] == pos.snapshot) return 0; return snapshots_seen_add(c, s, pos.snapshot); @@ -498,7 +499,7 @@ static bool key_visible_in_snapshot(struct bch_fs *c, struct snapshots_seen *see ancestor = snapshot_t(c, ancestor)->equiv; /* @ancestor should be the snapshot most recently added to @seen */ - BUG_ON(!seen->nr || seen->d[seen->nr - 1] != ancestor); + BUG_ON(!seen->ids.nr || seen->ids.data[seen->ids.nr - 1] != ancestor); BUG_ON(seen->pos.snapshot != ancestor); if (id == ancestor) @@ -507,11 +508,11 @@ static bool key_visible_in_snapshot(struct bch_fs *c, struct snapshots_seen *see if (!bch2_snapshot_is_ancestor(c, id, ancestor)) return false; - for (i = seen->nr - 2; - i >= 0 && seen->d[i] >= id; + for (i = seen->ids.nr - 2; + i >= 0 && seen->ids.data[i] >= id; --i) - if (bch2_snapshot_is_ancestor(c, id, seen->d[i]) && - bch2_snapshot_is_ancestor(c, seen->d[i], ancestor)) + if (bch2_snapshot_is_ancestor(c, id, seen->ids.data[i]) && + bch2_snapshot_is_ancestor(c, seen->ids.data[i], ancestor)) return false; return true; @@ -537,26 +538,25 @@ static int ref_visible(struct bch_fs *c, struct snapshots_seen *s, } #define for_each_visible_inode(_c, _s, _w, _snapshot, _i) \ - for (_i = (_w)->d; _i < (_w)->d + (_w)->nr && (_i)->snapshot <= (_snapshot); _i++)\ + for (_i = (_w)->inodes.data; _i < (_w)->inodes.data + (_w)->inodes.nr && (_i)->snapshot <= (_snapshot); _i++)\ if (key_visible_in_snapshot(_c, _s, _i->snapshot, _snapshot)) +struct inode_walker_entry { + struct bch_inode_unpacked inode; + u32 snapshot; + u64 count; +}; + struct inode_walker { bool first_this_inode; u64 cur_inum; - size_t nr; - size_t size; - struct inode_walker_entry { - struct bch_inode_unpacked inode; - u32 snapshot; - u64 count; - } *d; + DARRAY(struct inode_walker_entry) inodes; }; static void inode_walker_exit(struct inode_walker *w) { - kfree(w->d); - w->d = NULL; + darray_exit(w->inodes); } static struct inode_walker inode_walker_init(void) @@ -564,43 +564,17 @@ static struct inode_walker inode_walker_init(void) return (struct inode_walker) { 0, }; } -static int inode_walker_realloc(struct bch_fs *c, struct inode_walker *w) -{ - if (w->nr == w->size) { - size_t new_size = max_t(size_t, 8UL, w->size * 2); - void *d = krealloc(w->d, new_size * sizeof(w->d[0]), - GFP_KERNEL); - if (!d) { - bch_err(c, "fsck: error allocating memory for inode_walker, size %zu", - new_size); - return -ENOMEM; - } - - w->d = d; - w->size = new_size; - } - - return 0; -} - static int add_inode(struct bch_fs *c, struct inode_walker *w, struct bkey_s_c inode) { struct bch_inode_unpacked u; - int ret; - - ret = inode_walker_realloc(c, w); - if (ret) - return ret; BUG_ON(bch2_inode_unpack(inode, &u)); - w->d[w->nr++] = (struct inode_walker_entry) { + return darray_push(w->inodes, ((struct inode_walker_entry) { .inode = u, .snapshot = snapshot_t(c, inode.k->p.snapshot)->equiv, - }; - - return 0; + })); } static int __walk_inode(struct btree_trans *trans, @@ -619,7 +593,7 @@ static int __walk_inode(struct btree_trans *trans, goto lookup_snapshot; } - w->nr = 0; + w->inodes.nr = 0; for_each_btree_key(trans, iter, BTREE_ID_inodes, POS(0, pos.inode), BTREE_ITER_ALL_SNAPSHOTS, k, ret) { @@ -637,26 +611,25 @@ static int __walk_inode(struct btree_trans *trans, w->cur_inum = pos.inode; w->first_this_inode = true; lookup_snapshot: - for (i = 0; i < w->nr; i++) - if (bch2_snapshot_is_ancestor(c, pos.snapshot, w->d[i].snapshot)) + for (i = 0; i < w->inodes.nr; i++) + if (bch2_snapshot_is_ancestor(c, pos.snapshot, w->inodes.data[i].snapshot)) goto found; return INT_MAX; found: - BUG_ON(pos.snapshot > w->d[i].snapshot); + BUG_ON(pos.snapshot > w->inodes.data[i].snapshot); - if (pos.snapshot != w->d[i].snapshot) { + if (pos.snapshot != w->inodes.data[i].snapshot) { ancestor_pos = i; - while (i && w->d[i - 1].snapshot > pos.snapshot) + while (i && w->inodes.data[i - 1].snapshot > pos.snapshot) --i; - ret = inode_walker_realloc(c, w); + ret = darray_insert_item(w->inodes, i, w->inodes.data[ancestor_pos]); if (ret) return ret; - array_insert_item(w->d, w->nr, i, w->d[ancestor_pos]); - w->d[i].snapshot = pos.snapshot; - w->d[i].count = 0; + w->inodes.data[i].snapshot = pos.snapshot; + w->inodes.data[i].count = 0; } return i; @@ -672,7 +645,7 @@ static int __get_visible_inodes(struct btree_trans *trans, struct bkey_s_c k; int ret; - w->nr = 0; + w->inodes.nr = 0; for_each_btree_key(trans, iter, BTREE_ID_inodes, POS(0, inum), BTREE_ITER_ALL_SNAPSHOTS, k, ret) { @@ -1133,7 +1106,7 @@ static int check_i_sectors(struct btree_trans *trans, struct inode_walker *w) int ret = 0, ret2 = 0; s64 count2; - for (i = w->d; i < w->d + w->nr; i++) { + darray_for_each(w->inodes, i) { if (i->inode.bi_sectors == i->count) continue; @@ -1232,7 +1205,7 @@ static int check_extent(struct btree_trans *trans, struct btree_iter *iter, goto out; } - i = inode->d + ret; + i = inode->inodes.data + ret; ret = 0; if (fsck_err_on(!S_ISREG(i->inode.bi_mode) && @@ -1333,7 +1306,7 @@ static int check_subdir_count(struct btree_trans *trans, struct inode_walker *w) int ret = 0, ret2 = 0; s64 count2; - for (i = w->d; i < w->d + w->nr; i++) { + darray_for_each(w->inodes, i) { if (i->inode.bi_nlink == i->count) continue; @@ -1537,7 +1510,7 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter, goto out; } - i = dir->d + ret; + i = dir->inodes.data + ret; ret = 0; if (fsck_err_on(!S_ISDIR(i->inode.bi_mode), c, @@ -1550,7 +1523,7 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter, } if (dir->first_this_inode) - *hash_info = bch2_hash_info_init(c, &dir->d[0].inode); + *hash_info = bch2_hash_info_init(c, &dir->inodes.data[0].inode); ret = hash_check_key(trans, bch2_dirent_hash_desc, hash_info, iter, k); @@ -1618,7 +1591,7 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter, if (ret) goto err; - if (fsck_err_on(!target->nr, c, + if (fsck_err_on(!target->inodes.nr, c, "dirent points to missing inode:\n%s", (printbuf_reset(&buf), bch2_bkey_val_to_text(&buf, c, k), @@ -1628,7 +1601,7 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter, goto err; } - for (i = target->d; i < target->d + target->nr; i++) { + darray_for_each(target->inodes, i) { ret = check_dirent_target(trans, iter, d, &i->inode, i->snapshot); if (ret) @@ -1726,7 +1699,7 @@ static int check_xattr(struct btree_trans *trans, struct btree_iter *iter, ret = 0; if (inode->first_this_inode) - *hash_info = bch2_hash_info_init(c, &inode->d[0].inode); + *hash_info = bch2_hash_info_init(c, &inode->inodes.data[0].inode); ret = hash_check_key(trans, bch2_xattr_hash_desc, hash_info, iter, k); fsck_err: @@ -1836,21 +1809,18 @@ static int check_root(struct bch_fs *c) check_root_trans(&trans)); } -struct pathbuf { - size_t nr; - size_t size; - - struct pathbuf_entry { - u64 inum; - u32 snapshot; - } *entries; +struct pathbuf_entry { + u64 inum; + u32 snapshot; }; -static bool path_is_dup(struct pathbuf *p, u64 inum, u32 snapshot) +typedef DARRAY(struct pathbuf_entry) pathbuf; + +static bool path_is_dup(pathbuf *p, u64 inum, u32 snapshot) { struct pathbuf_entry *i; - for (i = p->entries; i < p->entries + p->nr; i++) + darray_for_each(*p, i) if (i->inum == inum && i->snapshot == snapshot) return true; @@ -1858,29 +1828,18 @@ static bool path_is_dup(struct pathbuf *p, u64 inum, u32 snapshot) return false; } -static int path_down(struct bch_fs *c, struct pathbuf *p, +static int path_down(struct bch_fs *c, pathbuf *p, u64 inum, u32 snapshot) { - if (p->nr == p->size) { - size_t new_size = max_t(size_t, 256UL, p->size * 2); - void *n = krealloc(p->entries, - new_size * sizeof(p->entries[0]), - GFP_KERNEL); - if (!n) { - bch_err(c, "fsck: error allocating memory for pathbuf, size %zu", - new_size); - return -ENOMEM; - } - - p->entries = n; - p->size = new_size; - }; - - p->entries[p->nr++] = (struct pathbuf_entry) { + int ret = darray_push(*p, ((struct pathbuf_entry) { .inum = inum, .snapshot = snapshot, - }; - return 0; + })); + + if (ret) + bch_err(c, "fsck: error allocating memory for pathbuf, size %zu", + p->size); + return ret; } /* @@ -1889,7 +1848,7 @@ static int path_down(struct bch_fs *c, struct pathbuf *p, * XXX: we should also be verifying that inodes are in the right subvolumes */ static int check_path(struct btree_trans *trans, - struct pathbuf *p, + pathbuf *p, struct bch_inode_unpacked *inode, u32 snapshot) { @@ -1963,7 +1922,7 @@ static int check_path(struct btree_trans *trans, /* XXX print path */ bch_err(c, "directory structure loop"); - for (i = p->entries; i < p->entries + p->nr; i++) + darray_for_each(*p, i) pr_err("%llu:%u", i->inum, i->snapshot); pr_err("%llu:%u", inode->bi_inum, snapshot); @@ -2000,7 +1959,7 @@ static int check_directory_structure(struct bch_fs *c) struct btree_iter iter; struct bkey_s_c k; struct bch_inode_unpacked u; - struct pathbuf path = { 0, 0, NULL }; + pathbuf path = { 0, }; int ret; bch2_trans_init(&trans, c, BTREE_ITER_MAX, 0); @@ -2030,7 +1989,7 @@ static int check_directory_structure(struct bch_fs *c) BUG_ON(ret == -EINTR); - kfree(path.entries); + darray_exit(path); bch2_trans_exit(&trans); return ret; diff --git a/libbcachefs/move.c b/libbcachefs/move.c index 8eb4938..1de2135 100644 --- a/libbcachefs/move.c +++ b/libbcachefs/move.c @@ -92,10 +92,10 @@ next: if (bch2_snapshot_is_ancestor(c, k.k->p.snapshot, old_pos.snapshot)) { struct bkey_i *update; - size_t i; + u32 *i; - for (i = 0; i < s.nr; i++) - if (bch2_snapshot_is_ancestor(c, k.k->p.snapshot, s.d[i])) + darray_for_each(s.ids, i) + if (bch2_snapshot_is_ancestor(c, k.k->p.snapshot, *i)) goto next; update = bch2_trans_kmalloc(trans, sizeof(struct bkey_i)); @@ -125,7 +125,7 @@ next: } } bch2_trans_iter_exit(trans, &iter); - kfree(s.d); + darray_exit(s.ids); return ret; } diff --git a/libbcachefs/subvolume.c b/libbcachefs/subvolume.c index 666f1c8..cdb89ba 100644 --- a/libbcachefs/subvolume.c +++ b/libbcachefs/subvolume.c @@ -545,36 +545,21 @@ err: return ret; } -static int snapshot_id_add(struct snapshot_id_list *s, u32 id) +static int snapshot_id_add(snapshot_id_list *s, u32 id) { BUG_ON(snapshot_list_has_id(s, id)); - if (s->nr == s->size) { - size_t new_size = max(8U, s->size * 2); - void *n = krealloc(s->d, - new_size * sizeof(s->d[0]), - GFP_KERNEL); - if (!n) { - pr_err("error allocating snapshot ID list"); - return -ENOMEM; - } - - s->d = n; - s->size = new_size; - }; - - s->d[s->nr++] = id; - return 0; + return darray_push(*s, id); } static int bch2_snapshot_delete_keys_btree(struct btree_trans *trans, - struct snapshot_id_list *deleted, + snapshot_id_list *deleted, enum btree_id btree_id) { struct bch_fs *c = trans->c; struct btree_iter iter; struct bkey_s_c k; - struct snapshot_id_list equiv_seen = { 0 }; + snapshot_id_list equiv_seen = { 0 }; struct bpos last_pos = POS_MIN; int ret = 0; @@ -621,7 +606,7 @@ static int bch2_snapshot_delete_keys_btree(struct btree_trans *trans, } bch2_trans_iter_exit(trans, &iter); - kfree(equiv_seen.d); + darray_exit(equiv_seen); return ret; } @@ -633,7 +618,7 @@ static void bch2_delete_dead_snapshots_work(struct work_struct *work) struct btree_iter iter; struct bkey_s_c k; struct bkey_s_c_snapshot snap; - struct snapshot_id_list deleted = { 0 }; + snapshot_id_list deleted = { 0 }; u32 i, id, children[2]; int ret = 0; @@ -713,15 +698,15 @@ static void bch2_delete_dead_snapshots_work(struct work_struct *work) for (i = 0; i < deleted.nr; i++) { ret = __bch2_trans_do(&trans, NULL, NULL, 0, - bch2_snapshot_node_delete(&trans, deleted.d[i])); + bch2_snapshot_node_delete(&trans, deleted.data[i])); if (ret) { bch_err(c, "error deleting snapshot %u: %i", - deleted.d[i], ret); + deleted.data[i], ret); goto err; } } err: - kfree(deleted.d); + darray_exit(deleted); bch2_trans_exit(&trans); percpu_ref_put(&c->writes); } @@ -876,14 +861,14 @@ void bch2_subvolume_wait_for_pagecache_and_delete(struct work_struct *work) { struct bch_fs *c = container_of(work, struct bch_fs, snapshot_wait_for_pagecache_and_delete_work); - struct snapshot_id_list s; + snapshot_id_list s; u32 *id; int ret = 0; while (!ret) { mutex_lock(&c->snapshots_unlinked_lock); s = c->snapshots_unlinked; - memset(&c->snapshots_unlinked, 0, sizeof(c->snapshots_unlinked)); + darray_init(c->snapshots_unlinked); mutex_unlock(&c->snapshots_unlinked_lock); if (!s.nr) @@ -891,7 +876,7 @@ void bch2_subvolume_wait_for_pagecache_and_delete(struct work_struct *work) bch2_evict_subvolume_inodes(c, &s); - for (id = s.d; id < s.d + s.nr; id++) { + for (id = s.data; id < s.data + s.nr; id++) { ret = bch2_trans_do(c, NULL, NULL, BTREE_INSERT_NOFAIL, bch2_subvolume_delete(&trans, *id)); if (ret) { @@ -900,7 +885,7 @@ void bch2_subvolume_wait_for_pagecache_and_delete(struct work_struct *work) } } - kfree(s.d); + darray_exit(s); } percpu_ref_put(&c->writes); diff --git a/libbcachefs/subvolume.h b/libbcachefs/subvolume.h index 4abe53d..f609291 100644 --- a/libbcachefs/subvolume.h +++ b/libbcachefs/subvolume.h @@ -2,6 +2,7 @@ #ifndef _BCACHEFS_SUBVOLUME_H #define _BCACHEFS_SUBVOLUME_H +#include "darray.h" #include "subvolume_types.h" void bch2_snapshot_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c); @@ -58,15 +59,13 @@ static inline bool bch2_snapshot_is_ancestor(struct bch_fs *c, u32 id, u32 ances struct snapshots_seen { struct bpos pos; - size_t nr; - size_t size; - u32 *d; + DARRAY(u32) ids; }; static inline void snapshots_seen_exit(struct snapshots_seen *s) { - kfree(s->d); - s->d = NULL; + kfree(s->ids.data); + s->ids.data = NULL; } static inline void snapshots_seen_init(struct snapshots_seen *s) @@ -76,30 +75,19 @@ static inline void snapshots_seen_init(struct snapshots_seen *s) static inline int snapshots_seen_add(struct bch_fs *c, struct snapshots_seen *s, u32 id) { - if (s->nr == s->size) { - size_t new_size = max(s->size, (size_t) 128) * 2; - u32 *d = krealloc(s->d, new_size * sizeof(s->d[0]), GFP_KERNEL); - - if (!d) { - bch_err(c, "error reallocating snapshots_seen table (new size %zu)", - new_size); - return -ENOMEM; - } - - s->size = new_size; - s->d = d; - } - - s->d[s->nr++] = id; - return 0; + int ret = darray_push(s->ids, id); + if (ret) + bch_err(c, "error reallocating snapshots_seen table (size %zu)", + s->ids.size); + return ret; } -static inline bool snapshot_list_has_id(struct snapshot_id_list *s, u32 id) +static inline bool snapshot_list_has_id(snapshot_id_list *s, u32 id) { - unsigned i; + u32 *i; - for (i = 0; i < s->nr; i++) - if (id == s->d[i]) + darray_for_each(*s, i) + if (*i == id) return true; return false; } diff --git a/libbcachefs/subvolume_types.h b/libbcachefs/subvolume_types.h index 9410b95..f7562b5 100644 --- a/libbcachefs/subvolume_types.h +++ b/libbcachefs/subvolume_types.h @@ -2,10 +2,8 @@ #ifndef _BCACHEFS_SUBVOLUME_TYPES_H #define _BCACHEFS_SUBVOLUME_TYPES_H -struct snapshot_id_list { - u32 nr; - u32 size; - u32 *d; -}; +#include "darray.h" + +typedef DARRAY(u32) snapshot_id_list; #endif /* _BCACHEFS_SUBVOLUME_TYPES_H */ diff --git a/qcow2.c b/qcow2.c index 7cf4992..d01fa94 100644 --- a/qcow2.c +++ b/qcow2.c @@ -94,7 +94,7 @@ void qcow2_write_image(int infd, int outfd, ranges *data, ranges_sort_merge(data); /* Write data: */ - darray_foreach(r, *data) + darray_for_each(*data, r) for (src_offset = r->start; src_offset < r->end; src_offset += block_size) { diff --git a/tools-util.c b/tools-util.c index 621ab42..e338152 100644 --- a/tools-util.c +++ b/tools-util.c @@ -295,22 +295,21 @@ static int range_cmp(const void *_l, const void *_r) void ranges_sort_merge(ranges *r) { struct range *t, *i; - ranges tmp = { NULL }; + ranges tmp = { 0 }; - sort(&darray_item(*r, 0), darray_size(*r), - sizeof(darray_item(*r, 0)), range_cmp, NULL); + sort(r->data, r->nr, sizeof(r->data[0]), range_cmp, NULL); /* Merge contiguous ranges: */ - darray_foreach(i, *r) { - t = tmp.size ? &tmp.item[tmp.size - 1] : NULL; + darray_for_each(*r, i) { + t = tmp.nr ? &tmp.data[tmp.nr - 1] : NULL; if (t && t->end >= i->start) t->end = max(t->end, i->end); else - darray_append(tmp, *i); + darray_push(tmp, *i); } - darray_free(*r); + darray_exit(*r); *r = tmp; } @@ -318,7 +317,7 @@ void ranges_roundup(ranges *r, unsigned block_size) { struct range *i; - darray_foreach(i, *r) { + darray_for_each(*r, i) { i->start = round_down(i->start, block_size); i->end = round_up(i->end, block_size); } @@ -328,7 +327,7 @@ void ranges_rounddown(ranges *r, unsigned block_size) { struct range *i; - darray_foreach(i, *r) { + darray_for_each(*r, i) { i->start = round_up(i->start, block_size); i->end = round_down(i->end, block_size); i->end = max(i->end, i->start); diff --git a/tools-util.h b/tools-util.h index 78827b8..a0e20eb 100644 --- a/tools-util.h +++ b/tools-util.h @@ -18,7 +18,7 @@ #include #include #include -#include "ccan/darray/darray.h" +#include "libbcachefs/darray.h" #define noreturn __attribute__((noreturn)) @@ -72,14 +72,14 @@ struct range { u64 end; }; -typedef darray(struct range) ranges; +typedef DARRAY(struct range) ranges; static inline void range_add(ranges *data, u64 offset, u64 size) { - darray_append(*data, (struct range) { + darray_push(*data, ((struct range) { .start = offset, .end = offset + size - }); + })); } void ranges_sort_merge(ranges *); @@ -95,9 +95,9 @@ struct hole_iter { static inline struct range hole_iter_next(struct hole_iter *iter) { struct range r = { - .start = iter->idx ? iter->r.item[iter->idx - 1].end : 0, + .start = iter->idx ? iter->r.data[iter->idx - 1].end : 0, .end = iter->idx < iter->r.size - ? iter->r.item[iter->idx].start : iter->end, + ? iter->r.data[iter->idx].start : iter->end, }; BUG_ON(r.start > r.end); -- 2.39.2