diff --git a/kmod/src/Makefile b/kmod/src/Makefile index 4492cc52..f0c62bb4 100644 --- a/kmod/src/Makefile +++ b/kmod/src/Makefile @@ -9,7 +9,6 @@ CFLAGS_scoutfs_trace.o = -I$(src) # define_trace.h double include -include $(src)/Makefile.kernelcompat scoutfs-y += \ - balloc.o \ block.o \ btree.o \ client.o \ diff --git a/kmod/src/btree.c b/kmod/src/btree.c index 936de009..f31e44f5 100644 --- a/kmod/src/btree.c +++ b/kmod/src/btree.c @@ -27,7 +27,7 @@ #include "options.h" #include "msg.h" #include "block.h" -#include "balloc.h" +#include "radix.h" #include "scoutfs_trace.h" @@ -387,7 +387,7 @@ static void move_items(struct scoutfs_btree_block *dst, * error. */ static int get_ref_block(struct super_block *sb, - struct scoutfs_balloc_allocator *alloc, + struct scoutfs_radix_allocator *alloc, struct scoutfs_block_writer *wri, int flags, struct scoutfs_btree_ref *ref, struct scoutfs_block **bl_ret) @@ -450,7 +450,7 @@ retry: goto out; } - ret = scoutfs_balloc_alloc(sb, alloc, wri, &blkno); + ret = scoutfs_radix_alloc(sb, alloc, wri, &blkno); if (ret < 0) goto out; @@ -458,7 +458,7 @@ retry: new_bl = scoutfs_block_create(sb, blkno); if (IS_ERR(new_bl)) { - ret = scoutfs_balloc_free(sb, alloc, wri, blkno); + ret = scoutfs_radix_free(sb, alloc, wri, blkno); BUG_ON(ret); /* radix should have been dirty */ ret = PTR_ERR(new_bl); goto out; @@ -546,7 +546,7 @@ static void update_parent_item(struct scoutfs_btree_block *parent, * Returns -errno, 0 if nothing done, or 1 if we split. */ static int try_split(struct super_block *sb, - struct scoutfs_balloc_allocator *alloc, + struct scoutfs_radix_allocator *alloc, struct scoutfs_block_writer *wri, struct scoutfs_btree_root *root, void *key, unsigned key_len, unsigned val_len, @@ -582,8 +582,8 @@ static int try_split(struct super_block *sb, if (!parent) { ret = get_ref_block(sb, alloc, wri, BTW_ALLOC, NULL, &par_bl); if (ret) { - err = scoutfs_balloc_free(sb, alloc, wri, - le64_to_cpu(left->hdr.blkno)); + err = scoutfs_radix_free(sb, alloc, wri, + le64_to_cpu(left->hdr.blkno)); BUG_ON(err); /* radix should have been dirty */ scoutfs_block_put(sb, left_bl); return ret; @@ -622,7 +622,7 @@ static int try_split(struct super_block *sb, * XXX this could more cleverly chose a merge candidate sibling */ static int try_merge(struct super_block *sb, - struct scoutfs_balloc_allocator *alloc, + struct scoutfs_radix_allocator *alloc, struct scoutfs_block_writer *wri, struct scoutfs_btree_root *root, struct scoutfs_btree_block *parent, unsigned pos, @@ -676,8 +676,8 @@ static int try_merge(struct super_block *sb, /* update or delete sibling's parent item */ if (le32_to_cpu(sib->nr_items) == 0) { delete_item(parent, sib_pos); - ret = scoutfs_balloc_free(sb, alloc, wri, - le64_to_cpu(sib->hdr.blkno)); + ret = scoutfs_radix_free(sb, alloc, wri, + le64_to_cpu(sib->hdr.blkno)); BUG_ON(ret); /* could have dirtied alloc to avoid error */ } else if (move_right) { @@ -689,8 +689,8 @@ static int try_merge(struct super_block *sb, root->height--; root->ref.blkno = bt->hdr.blkno; root->ref.seq = bt->hdr.seq; - ret = scoutfs_balloc_free(sb, alloc, wri, - le64_to_cpu(parent->hdr.blkno)); + ret = scoutfs_radix_free(sb, alloc, wri, + le64_to_cpu(parent->hdr.blkno)); BUG_ON(ret); /* could have dirtied alloc to avoid error */ } @@ -803,7 +803,7 @@ static void inc_key(u8 *bytes, unsigned *len) * blocks themselves. */ static int btree_walk(struct super_block *sb, - struct scoutfs_balloc_allocator *alloc, + struct scoutfs_radix_allocator *alloc, struct scoutfs_block_writer *wri, struct scoutfs_btree_root *root, int flags, void *key, unsigned key_len, @@ -1037,7 +1037,7 @@ static bool invalid_item(void *key, unsigned key_len, unsigned val_len) * length value. */ int scoutfs_btree_insert(struct super_block *sb, - struct scoutfs_balloc_allocator *alloc, + struct scoutfs_radix_allocator *alloc, struct scoutfs_block_writer *wri, struct scoutfs_btree_root *root, void *key, unsigned key_len, @@ -1081,7 +1081,7 @@ int scoutfs_btree_insert(struct super_block *sb, * which doesn't fit. */ int scoutfs_btree_update(struct super_block *sb, - struct scoutfs_balloc_allocator *alloc, + struct scoutfs_radix_allocator *alloc, struct scoutfs_block_writer *wri, struct scoutfs_btree_root *root, void *key, unsigned key_len, @@ -1120,7 +1120,7 @@ int scoutfs_btree_update(struct super_block *sb, * which will insert instead of returning -ENOENT. */ int scoutfs_btree_force(struct super_block *sb, - struct scoutfs_balloc_allocator *alloc, + struct scoutfs_radix_allocator *alloc, struct scoutfs_block_writer *wri, struct scoutfs_btree_root *root, void *key, unsigned key_len, @@ -1154,7 +1154,7 @@ int scoutfs_btree_force(struct super_block *sb, * found. */ int scoutfs_btree_delete(struct super_block *sb, - struct scoutfs_balloc_allocator *alloc, + struct scoutfs_radix_allocator *alloc, struct scoutfs_block_writer *wri, struct scoutfs_btree_root *root, void *key, unsigned key_len) @@ -1312,7 +1312,7 @@ int scoutfs_btree_before(struct super_block *sb, struct scoutfs_btree_root *root * <0 is returned on error, including -ENOENT if the key isn't present. */ int scoutfs_btree_dirty(struct super_block *sb, - struct scoutfs_balloc_allocator *alloc, + struct scoutfs_radix_allocator *alloc, struct scoutfs_block_writer *wri, struct scoutfs_btree_root *root, void *key, unsigned key_len) diff --git a/kmod/src/btree.h b/kmod/src/btree.h index 9278cec8..e37ab023 100644 --- a/kmod/src/btree.h +++ b/kmod/src/btree.h @@ -3,7 +3,7 @@ #include -struct scoutfs_balloc_allocator; +struct scoutfs_radix_allocator; struct scoutfs_block_writer; struct scoutfs_block; @@ -24,25 +24,25 @@ int scoutfs_btree_lookup(struct super_block *sb, struct scoutfs_btree_root *root void *key, unsigned key_len, struct scoutfs_btree_item_ref *iref); int scoutfs_btree_insert(struct super_block *sb, - struct scoutfs_balloc_allocator *alloc, + struct scoutfs_radix_allocator *alloc, struct scoutfs_block_writer *wri, struct scoutfs_btree_root *root, void *key, unsigned key_len, void *val, unsigned val_len); int scoutfs_btree_update(struct super_block *sb, - struct scoutfs_balloc_allocator *alloc, + struct scoutfs_radix_allocator *alloc, struct scoutfs_block_writer *wri, struct scoutfs_btree_root *root, void *key, unsigned key_len, void *val, unsigned val_len); int scoutfs_btree_force(struct super_block *sb, - struct scoutfs_balloc_allocator *alloc, + struct scoutfs_radix_allocator *alloc, struct scoutfs_block_writer *wri, struct scoutfs_btree_root *root, void *key, unsigned key_len, void *val, unsigned val_len); int scoutfs_btree_delete(struct super_block *sb, - struct scoutfs_balloc_allocator *alloc, + struct scoutfs_radix_allocator *alloc, struct scoutfs_block_writer *wri, struct scoutfs_btree_root *root, void *key, unsigned key_len); @@ -59,7 +59,7 @@ int scoutfs_btree_before(struct super_block *sb, struct scoutfs_btree_root *root void *key, unsigned key_len, struct scoutfs_btree_item_ref *iref); int scoutfs_btree_dirty(struct super_block *sb, - struct scoutfs_balloc_allocator *alloc, + struct scoutfs_radix_allocator *alloc, struct scoutfs_block_writer *wri, struct scoutfs_btree_root *root, void *key, unsigned key_len); diff --git a/kmod/src/data.c b/kmod/src/data.c index 802e7d47..4eaf701e 100644 --- a/kmod/src/data.c +++ b/kmod/src/data.c @@ -38,6 +38,7 @@ #include "file.h" #include "msg.h" #include "count.h" +#include "radix.h" /* * Logical file blocks are mapped to device blocks with extents stored @@ -53,33 +54,17 @@ * modified they can be packed back into the item. Typically there are * very few extents that cover the region. * - * Free blocks are tracked with bitmaps that are stored in items. Again - * the bitmaps are stored in a packed form and operated on in memory in - * a native form. Only 64bit words with a mix of set and clear bits are - * stored. The bitmaps are translated into long bitmaps in memory so we - * can use the kernel's long bitmap interfaces. - * - * There are two types of bitmap items: little bitmap bits track - * individual blocks and large bitmap bits track full little bitmap - * items. The logical packed extent item and little bitmap item sizes - * are chosen such that a full little bitmap represents a full packed - * extent item so we can allocate maximum size extents from the large - * bitmap bits. - * - * The client is given a tree of free block bitmap items from the server - * at the start of each transaction. The client allocates from items in - * an allocation tree and frees into items in a free tree. The server - * is responsible for filling the alloc tree and reclaiming the free - * tree as transactions are opened and committed. + * The client is given a radix allocator with trees for allocating + * blocks and recording frees at the start of each transaction. */ struct data_info { struct super_block *sb; struct rw_semaphore alloc_rwsem; - struct scoutfs_balloc_allocator *alloc; + struct scoutfs_radix_allocator *alloc; struct scoutfs_block_writer *wri; - struct scoutfs_balloc_root data_alloc; - struct scoutfs_balloc_root data_free; + struct scoutfs_radix_root data_avail; + struct scoutfs_radix_root data_freed; }; #define DECLARE_DATA_INFO(sb, name) \ @@ -140,11 +125,6 @@ static u64 ext_last(struct unpacked_extent *ext) return ext->iblock + ext->count - 1; } -static u64 bitmap_base(u64 blkno) -{ - return blkno >> SCOUTFS_BLOCK_BITMAP_BASE_SHIFT; -} - /* The first possible iblock in an item that contains the given iblock */ static u64 first_iblock(u64 iblock) { @@ -163,8 +143,8 @@ static u64 last_iblock(u64 iblock) * flags. * * We also require that a given extent's allocation be from only one - * bitmap item because the block bitmap clearing functions only operate - * on one item. + * radix bitmap leaf block because the radix freeing functions only + * operate on one leaf block. */ static bool extents_merge(struct unpacked_extent *left, struct unpacked_extent *right) @@ -173,7 +153,8 @@ static bool extents_merge(struct unpacked_extent *left, ((!left->blkno && !right->blkno) || (left->blkno + left->count == right->blkno)) && (left->flags == right->flags) && - (bitmap_base(left->blkno) == bitmap_base(right->blkno)); + (scoutfs_radix_bit_leaf_nr(left->blkno) == + scoutfs_radix_bit_leaf_nr(right->blkno + right->count - 1)); } static struct unpacked_extent *first_extent(struct unpacked_extents *unpe) @@ -708,6 +689,7 @@ static int set_extent(struct super_block *sb, struct inode *inode, return 0; } +#if 0 static bool block_bitmap_fits(u64 blkno, u64 count) { return ((blkno & SCOUTFS_BLOCK_BITMAP_BIT_MASK) + count) <= @@ -1298,6 +1280,7 @@ int scoutfs_data_add_free_blocks(struct super_block *sb, return ret; } +#endif /* * Find and remove or mark offline the block mappings that intersect @@ -1350,7 +1333,10 @@ static s64 truncate_extents(struct super_block *sb, struct inode *inode, if (ext->blkno) { down_write(&datinf->alloc_rwsem); - err = free_blocks(sb, &datinf->data_free, blkno, count); + err = scoutfs_radix_free_data(sb, datinf->alloc, + datinf->wri, + &datinf->data_freed, + blkno, count); up_write(&datinf->alloc_rwsem); if (err < 0) { ret = err; @@ -1482,11 +1468,11 @@ static int alloc_block(struct super_block *sb, struct inode *inode, const u64 ino = scoutfs_ino(inode); struct scoutfs_traced_extent te; u64 blkno = 0; - u64 count; u64 online; u64 offline; u64 last; u8 flags; + int count; int ret; int err; @@ -1517,11 +1503,13 @@ static int alloc_block(struct super_block *sb, struct inode *inode, /* only strictly contiguous extending writes will try to preallocate */ if (iblock > 1 && iblock == online) - count = min(iblock, count); + count = min_t(u64, iblock, count); else count = 1; - ret = alloc_blocks(sb, count, &blkno, &count); + ret = scoutfs_radix_alloc_data(sb, datinf->alloc, datinf->wri, + &datinf->data_avail, count, &blkno, + &count); if (ret < 0) goto out; @@ -1551,7 +1539,9 @@ static int alloc_block(struct super_block *sb, struct inode *inode, out: if (ret < 0 && blkno > 0) { - err = free_blocks(sb, &datinf->data_alloc, blkno, count); + err = scoutfs_radix_free_data(sb, datinf->alloc, datinf->wri, + &datinf->data_freed, + blkno, count); BUG_ON(err); /* leaked free blocks */ } @@ -1946,7 +1936,7 @@ static int fallocate_extents(struct super_block *sb, struct inode *inode, struct unpacked_extent *ext; u8 ext_fl; u64 blkno; - u64 count; + int count; int done; int ret; int err; @@ -1971,7 +1961,8 @@ static int fallocate_extents(struct super_block *sb, struct inode *inode, } else if (ext->iblock <= iblock && ext->blkno) { /* skip portion of allocated extent */ - count = min(count, ext->count - (iblock - ext->iblock)); + count = min_t(u64, count, + ext->count - (iblock - ext->iblock)); iblock += count; done += count; ext = next_extent(ext); @@ -1979,23 +1970,28 @@ static int fallocate_extents(struct super_block *sb, struct inode *inode, } else if (ext->iblock <= iblock && !ext->blkno) { /* alloc portion of unallocated extent */ - count = min(count, ext->count - (iblock - ext->iblock)); + count = min_t(u64, count, + ext->count - (iblock - ext->iblock)); ext_fl = ext->flags; } else if (iblock < ext->iblock) { /* alloc hole until next extent */ - count = min(count, ext->iblock - iblock); + count = min_t(u64, count, ext->iblock - iblock); } down_write(&datinf->alloc_rwsem); - ret = alloc_blocks(sb, count, &blkno, &count); + ret = scoutfs_radix_alloc_data(sb, datinf->alloc, datinf->wri, + &datinf->data_avail, count, + &blkno, &count); if (ret == 0) { ret = set_extent(sb, inode, ino, unpe, iblock, blkno, count, ext_fl | SEF_UNWRITTEN); if (ret < 0) { - err = free_blocks(sb, &datinf->data_alloc, - blkno, count); + err = scoutfs_radix_free_data(sb, datinf->alloc, + datinf->wri, + &datinf->data_avail, + blkno, count); BUG_ON(err); /* inconsistent */ } } @@ -2576,7 +2572,7 @@ const struct file_operations scoutfs_file_fops = { }; void scoutfs_data_init_btrees(struct super_block *sb, - struct scoutfs_balloc_allocator *alloc, + struct scoutfs_radix_allocator *alloc, struct scoutfs_block_writer *wri, struct scoutfs_log_trees *lt) { @@ -2586,8 +2582,8 @@ void scoutfs_data_init_btrees(struct super_block *sb, datinf->alloc = alloc; datinf->wri = wri; - datinf->data_alloc = lt->data_alloc; - datinf->data_free = lt->data_free; + datinf->data_avail = lt->data_avail; + datinf->data_freed = lt->data_freed; up_write(&datinf->alloc_rwsem); } @@ -2599,8 +2595,8 @@ void scoutfs_data_get_btrees(struct super_block *sb, down_read(&datinf->alloc_rwsem); - lt->data_alloc = datinf->data_alloc; - lt->data_free = datinf->data_free; + lt->data_avail = datinf->data_avail; + lt->data_freed = datinf->data_freed; up_read(&datinf->alloc_rwsem); } diff --git a/kmod/src/data.h b/kmod/src/data.h index 912284d9..0da25fa1 100644 --- a/kmod/src/data.h +++ b/kmod/src/data.h @@ -45,7 +45,7 @@ struct scoutfs_traced_extent { extern const struct address_space_operations scoutfs_file_aops; extern const struct file_operations scoutfs_file_fops; -struct scoutfs_balloc_allocator; +struct scoutfs_radix_allocator; struct scoutfs_block_writer; int scoutfs_data_truncate_items(struct super_block *sb, struct inode *inode, @@ -72,6 +72,7 @@ int scoutfs_data_waiting(struct super_block *sb, u64 ino, u64 iblock, struct scoutfs_ioctl_data_waiting_entry *dwe, unsigned int nr); +#if 0 int scoutfs_data_move_alloc_bits(struct super_block *sb, struct scoutfs_balloc_allocator *alloc, struct scoutfs_block_writer *wri, @@ -83,8 +84,9 @@ int scoutfs_data_add_free_blocks(struct super_block *sb, struct scoutfs_block_writer *wri, struct scoutfs_balloc_root *broot, u64 blkno, u64 count); +#endif void scoutfs_data_init_btrees(struct super_block *sb, - struct scoutfs_balloc_allocator *alloc, + struct scoutfs_radix_allocator *alloc, struct scoutfs_block_writer *wri, struct scoutfs_log_trees *lt); void scoutfs_data_get_btrees(struct super_block *sb, diff --git a/kmod/src/forest.c b/kmod/src/forest.c index 64e4a49e..a88d2119 100644 --- a/kmod/src/forest.c +++ b/kmod/src/forest.c @@ -21,7 +21,7 @@ #include "lock.h" #include "btree.h" #include "client.h" -#include "balloc.h" +#include "radix.h" #include "block.h" #include "forest.h" #include "scoutfs_trace.h" @@ -61,7 +61,7 @@ struct forest_info { struct rw_semaphore rwsem; - struct scoutfs_balloc_allocator *alloc; + struct scoutfs_radix_allocator *alloc; struct scoutfs_block_writer *wri; struct scoutfs_log_trees our_log; }; @@ -1158,22 +1158,21 @@ static int set_lock_bloom_bits(struct super_block *sb, if (!ref->blkno || !scoutfs_block_writer_is_dirty(sb, bl)) { - ret = scoutfs_balloc_alloc(sb, finf->alloc, finf->wri, - &blkno); + ret = scoutfs_radix_alloc(sb, finf->alloc, finf->wri, &blkno); if (ret < 0) goto unlock; new_bl = scoutfs_block_create(sb, blkno); if (IS_ERR(new_bl)) { - err = scoutfs_balloc_free(sb, finf->alloc, finf->wri, - blkno); + err = scoutfs_radix_free(sb, finf->alloc, finf->wri, + blkno); BUG_ON(err); /* could have dirtied */ ret = PTR_ERR(new_bl); goto unlock; } if (bl) { - err = scoutfs_balloc_free(sb, finf->alloc, finf->wri, + err = scoutfs_radix_free(sb, finf->alloc, finf->wri, le64_to_cpu(ref->blkno)); BUG_ON(err); /* could have dirtied */ memcpy(new_bl->data, bl->data, SCOUTFS_BLOCK_SIZE); @@ -1455,7 +1454,7 @@ void scoutfs_forest_free_batch(struct super_block *sb, struct list_head *list) * serialized with all writers. */ void scoutfs_forest_init_btrees(struct super_block *sb, - struct scoutfs_balloc_allocator *alloc, + struct scoutfs_radix_allocator *alloc, struct scoutfs_block_writer *wri, struct scoutfs_log_trees *lt) { diff --git a/kmod/src/forest.h b/kmod/src/forest.h index 7757d1f1..c82f1a2b 100644 --- a/kmod/src/forest.h +++ b/kmod/src/forest.h @@ -1,7 +1,7 @@ #ifndef _SCOUTFS_FOREST_H_ #define _SCOUTFS_FOREST_H_ -struct scoutfs_balloc_allocator; +struct scoutfs_radix_allocator; struct scoutfs_block_writer; int scoutfs_forest_lookup(struct super_block *sb, struct scoutfs_key *key, @@ -40,7 +40,7 @@ int scoutfs_forest_restore(struct super_block *sb, struct list_head *list, void scoutfs_forest_free_batch(struct super_block *sb, struct list_head *list); void scoutfs_forest_init_btrees(struct super_block *sb, - struct scoutfs_balloc_allocator *alloc, + struct scoutfs_radix_allocator *alloc, struct scoutfs_block_writer *wri, struct scoutfs_log_trees *lt); void scoutfs_forest_get_btrees(struct super_block *sb, diff --git a/kmod/src/format.h b/kmod/src/format.h index edb429b4..34f55252 100644 --- a/kmod/src/format.h +++ b/kmod/src/format.h @@ -246,6 +246,7 @@ struct scoutfs_btree_block { struct scoutfs_btree_item_header item_hdrs[0]; } __packed; +#if 0 /* * Free metadata blocks are tracked by block allocator items. */ @@ -294,6 +295,7 @@ struct scoutfs_packed_bitmap { __le64 set; __le64 words[0]; }; +#endif /* * The lock server keeps a persistent record of connected clients so that @@ -331,12 +333,12 @@ struct scoutfs_mounted_client_btree_val { * about item logs, it's about clients making changes to trees. */ struct scoutfs_log_trees { - struct scoutfs_balloc_root alloc_root; - struct scoutfs_balloc_root free_root; + struct scoutfs_radix_root meta_avail; + struct scoutfs_radix_root meta_freed; struct scoutfs_btree_root item_root; struct scoutfs_btree_ref bloom_ref; - struct scoutfs_balloc_root data_alloc; - struct scoutfs_balloc_root data_free; + struct scoutfs_radix_root data_avail; + struct scoutfs_radix_root data_freed; __le64 rid; __le64 nr; } __packed; @@ -347,12 +349,12 @@ struct scoutfs_log_trees_key { } __packed; struct scoutfs_log_trees_val { - struct scoutfs_balloc_root alloc_root; - struct scoutfs_balloc_root free_root; + struct scoutfs_radix_root meta_avail; + struct scoutfs_radix_root meta_freed; struct scoutfs_btree_root item_root; struct scoutfs_btree_ref bloom_ref; - struct scoutfs_balloc_root data_alloc; - struct scoutfs_balloc_root data_free; + struct scoutfs_radix_root data_avail; + struct scoutfs_radix_root data_freed; } __packed; struct scoutfs_log_item_value { @@ -527,25 +529,22 @@ struct scoutfs_super_block { __u8 uuid[SCOUTFS_UUID_BYTES]; __le64 next_ino; __le64 next_trans_seq; - __le64 total_blocks; - __le64 next_uninit_meta_blkno; - __le64 last_uninit_meta_blkno; - __le64 next_uninit_data_blkno; - __le64 last_uninit_data_blkno; - __le64 core_balloc_cursor; - __le64 core_data_alloc_cursor; + __le64 total_meta_blocks; /* both static and dynamic */ + __le64 first_meta_blkno; /* first dynamically allocated */ + __le64 last_meta_blkno; + __le64 total_data_blocks; + __le64 first_data_blkno; + __le64 last_data_blkno; __le64 free_blocks; - __le64 first_fs_blkno; - __le64 last_fs_blkno; __le64 quorum_fenced_term; __le64 quorum_server_term; __le64 unmount_barrier; __u8 quorum_count; struct scoutfs_inet_addr server_addr; - struct scoutfs_balloc_root core_balloc_alloc; - struct scoutfs_balloc_root core_balloc_free; - struct scoutfs_balloc_root core_data_alloc; - struct scoutfs_balloc_root core_data_free; + struct scoutfs_radix_root core_meta_avail; + struct scoutfs_radix_root core_meta_freed; + struct scoutfs_radix_root core_data_avail; + struct scoutfs_radix_root core_data_freed; struct scoutfs_btree_root fs_root; struct scoutfs_btree_root logs_root; struct scoutfs_btree_root lock_clients; diff --git a/kmod/src/lock_server.c b/kmod/src/lock_server.c index 2199bb23..f4bf64a0 100644 --- a/kmod/src/lock_server.c +++ b/kmod/src/lock_server.c @@ -20,7 +20,7 @@ #include "tseq.h" #include "spbm.h" #include "block.h" -#include "balloc.h" +#include "radix.h" #include "btree.h" #include "msg.h" #include "scoutfs_trace.h" @@ -87,7 +87,7 @@ struct lock_server_info { struct scoutfs_tseq_tree tseq_tree; struct dentry *tseq_dentry; - struct scoutfs_balloc_allocator *alloc; + struct scoutfs_radix_allocator *alloc; struct scoutfs_block_writer *wri; }; @@ -946,7 +946,7 @@ static void lock_server_tseq_show(struct seq_file *m, * we time them out. */ int scoutfs_lock_server_setup(struct super_block *sb, - struct scoutfs_balloc_allocator *alloc, + struct scoutfs_radix_allocator *alloc, struct scoutfs_block_writer *wri) { struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb); diff --git a/kmod/src/lock_server.h b/kmod/src/lock_server.h index 784b2575..99c82b8d 100644 --- a/kmod/src/lock_server.h +++ b/kmod/src/lock_server.h @@ -12,7 +12,7 @@ int scoutfs_lock_server_response(struct super_block *sb, u64 rid, int scoutfs_lock_server_farewell(struct super_block *sb, u64 rid); int scoutfs_lock_server_setup(struct super_block *sb, - struct scoutfs_balloc_allocator *alloc, + struct scoutfs_radix_allocator *alloc, struct scoutfs_block_writer *wri); void scoutfs_lock_server_destroy(struct super_block *sb); diff --git a/kmod/src/scoutfs_trace.h b/kmod/src/scoutfs_trace.h index e08d15ac..c5b028fc 100644 --- a/kmod/src/scoutfs_trace.h +++ b/kmod/src/scoutfs_trace.h @@ -118,6 +118,7 @@ TRACE_EVENT(scoutfs_complete_truncate, __entry->flags) ); +#if 0 TRACE_EVENT(scoutfs_data_alloc_blocks, TP_PROTO(struct super_block *sb, struct scoutfs_balloc_root *broot, u64 base, u8 type, int bit, u64 blkno, u64 count), @@ -182,6 +183,7 @@ TRACE_EVENT(scoutfs_data_free_blocks, SCSB_TRACE_ARGS, __entry->root_blkno, __entry->root_seq, __entry->root_total_free, __entry->blkno, __entry->count) ); +#endif TRACE_EVENT(scoutfs_data_fallocate, TP_PROTO(struct super_block *sb, u64 ino, int mode, loff_t offset, diff --git a/kmod/src/server.c b/kmod/src/server.c index 54dee331..93c89fa7 100644 --- a/kmod/src/server.c +++ b/kmod/src/server.c @@ -26,7 +26,7 @@ #include "counters.h" #include "inode.h" #include "block.h" -#include "balloc.h" +#include "radix.h" #include "btree.h" #include "scoutfs_trace.h" #include "msg.h" @@ -78,7 +78,7 @@ struct server_info { struct list_head farewell_requests; struct work_struct farewell_work; - struct scoutfs_balloc_allocator alloc; + struct scoutfs_radix_allocator alloc; struct scoutfs_block_writer wri; struct mutex logs_mutex; @@ -144,77 +144,6 @@ static inline int wait_for_commit(struct commit_waiter *cw) return cw->ret; } -/* - * Add newly initialized free metadata block allocator items to the core - * block allocator. This is called as we commit transactions in the - * server. It adds many more free blocks than is ever consumed by a - * transaction so this will stay ahead of the server's block allocation. - * The intent is to have a low constant overhead to initializing block - * allocators over time instead of requiring a large amount of IO during - * mkfs. - */ -static int add_uninit_balloc_items(struct super_block *sb, - struct server_info *server, - struct scoutfs_super_block *super) -{ - u64 next = le64_to_cpu(super->next_uninit_meta_blkno); - u64 last = le64_to_cpu(super->last_uninit_meta_blkno); - u64 nr; - int ret; - - if (next > last) - return 0; - - /* next_uninit should always start a new item */ - if (WARN_ON_ONCE(next & SCOUTFS_BALLOC_ITEM_BIT_MASK)) - return -EIO; - - nr = min_t(u64, last - next + 1, - round_up(512 * 1024 * 1024 / SCOUTFS_BLOCK_SIZE, - SCOUTFS_BALLOC_ITEM_BITS)); - - ret = scoutfs_balloc_add_alloc_bulk(sb, &server->alloc, &server->wri, - next, nr); - if (ret == 0) - le64_add_cpu(&super->next_uninit_meta_blkno, nr); - - return ret; -} - -/* - * Add newly initialized free block bitmap items. - */ -static int add_uninit_data_alloc_items(struct super_block *sb, - struct server_info *server, - struct scoutfs_super_block *super) -{ - int nr = 16; - u64 next; - u64 last; - int ret; - - while (nr-- > 0) { - next = le64_to_cpu(super->next_uninit_data_blkno); - last = le64_to_cpu(super->last_uninit_data_blkno); - if (next > last) { - ret = 0; - break; - } - - ret = scoutfs_data_add_free_blocks(sb, &server->alloc, - &server->wri, - &super->core_data_alloc, - next, last - next + 1); - if (ret <= 0) - break; - - le64_add_cpu(&super->next_uninit_data_blkno, ret); - ret = 0; - } - - return ret; -} - /* * A core function of request processing is to modify the manifest and * allocator. Often the processing needs to make the modifications @@ -249,22 +178,14 @@ static void scoutfs_server_commit_func(struct work_struct *work) down_write(&server->commit_rwsem); - /* XXX not sure what to do about failure here */ - ret = add_uninit_balloc_items(sb, server, super); - BUG_ON(ret); - - /* XXX not sure what to do about failure here */ - ret = add_uninit_data_alloc_items(sb, server, super); - BUG_ON(ret); - ret = scoutfs_block_writer_write(sb, &server->wri); if (ret) { scoutfs_err(sb, "server error writing btree blocks: %d", ret); goto out; } - super->core_balloc_alloc = server->alloc.alloc_root; - super->core_balloc_free = server->alloc.free_root; + super->core_meta_avail = server->alloc.avail; + super->core_meta_freed = server->alloc.freed; ret = scoutfs_write_super(sb, super); if (ret) { @@ -342,10 +263,8 @@ static int server_get_log_trees(struct super_block *sb, struct scoutfs_log_trees_val ltv; struct scoutfs_log_trees lt; struct commit_waiter cw; - u64 next_past; - u64 at_least; + u64 count; u64 target; - u64 from; int ret; if (arg_len != 0) { @@ -385,39 +304,37 @@ static int server_get_log_trees(struct super_block *sb, ltk.rid = cpu_to_be64(rid); ltk.nr = cpu_to_be64(1); memset(<v, 0, sizeof(ltv)); + scoutfs_radix_root_init(sb, <v.meta_avail, true); + scoutfs_radix_root_init(sb, <v.meta_freed, true); + scoutfs_radix_root_init(sb, <v.data_avail, false); + scoutfs_radix_root_init(sb, <v.data_freed, false); } /* ensure client has enough free metadata blocks for a transaction */ target = (64*1024*1024) / SCOUTFS_BLOCK_SIZE; - while (le64_to_cpu(ltv.alloc_root.total_free) < target) { - from = le64_to_cpu(super->core_balloc_cursor); - at_least = target - le64_to_cpu(ltv.alloc_root.total_free); + if (le64_to_cpu(ltv.meta_avail.ref.sm_total) < target) { + count = target - le64_to_cpu(ltv.meta_avail.ref.sm_total); - ret = scoutfs_balloc_move(sb, &server->alloc, &server->wri, - <v.alloc_root, - &server->alloc.alloc_root, - from, at_least, &next_past); - if (ret == -ENOENT && from != 0) { - super->core_balloc_cursor = 0; - continue; - } + ret = scoutfs_radix_merge(sb, &server->alloc, &server->wri, + <v.meta_avail, + &server->alloc.avail, + &server->alloc.avail, count); if (ret < 0) goto unlock; - - super->core_balloc_cursor = cpu_to_le64(next_past); } - /* fill client's data block allocator */ + /* ensure client has enough free data blocks for a transaction */ target = (2ULL*1024*1024*1024) / SCOUTFS_BLOCK_SIZE; - down_write(&server->alloc_rwsem); - ret = scoutfs_data_move_alloc_bits(sb, &server->alloc, &server->wri, - <v.data_alloc, - &super->core_data_alloc, - &super->core_data_alloc_cursor, - target); - up_write(&server->alloc_rwsem); - if (ret < 0) - goto unlock; + if (le64_to_cpu(ltv.data_avail.ref.sm_total) < target) { + count = target - le64_to_cpu(ltv.data_avail.ref.sm_total); + + ret = scoutfs_radix_merge(sb, &server->alloc, &server->wri, + <v.data_avail, + &super->core_data_avail, + &super->core_data_avail, count); + if (ret < 0) + goto unlock; + } /* update client's log tree's item */ ret = scoutfs_btree_force(sb, &server->alloc, &server->wri, @@ -433,12 +350,12 @@ unlock: ret = wait_for_commit(&cw); if (ret == 0) { - lt.alloc_root = ltv.alloc_root; - lt.free_root = ltv.free_root; + lt.meta_avail = ltv.meta_avail; + lt.meta_freed = ltv.meta_freed; lt.item_root = ltv.item_root; lt.bloom_ref = ltv.bloom_ref; - lt.data_alloc = ltv.data_alloc; - lt.data_free = ltv.data_free; + lt.data_avail = ltv.data_avail; + lt.data_freed = ltv.data_freed; lt.rid = be64_to_le64(ltk.rid); lt.nr = be64_to_le64(ltk.nr); } @@ -497,12 +414,12 @@ static int server_commit_log_trees(struct super_block *sb, /* XXX probably want to merge free blocks */ - ltv.alloc_root = lt->alloc_root; - ltv.free_root = lt->free_root; + ltv.meta_avail = lt->meta_avail; + ltv.meta_freed = lt->meta_freed; ltv.item_root = lt->item_root; ltv.bloom_ref = lt->bloom_ref; - ltv.data_alloc = lt->data_alloc; - ltv.data_free = lt->data_free; + ltv.data_avail = lt->data_avail; + ltv.data_freed = lt->data_freed; ret = scoutfs_btree_update(sb, &server->alloc, &server->wri, &super->logs_root, <k, sizeof(ltk), @@ -542,13 +459,8 @@ static int reclaim_log_trees(struct super_block *sb, u64 rid) SCOUTFS_BTREE_ITEM_REF(iref); struct scoutfs_log_trees_key ltk; struct scoutfs_log_trees_val ltv; - __le64 curs; - u64 tot; int ret; - memset(<k, 0, sizeof(ltk)); - memset(<v, 0, sizeof(ltv)); - mutex_lock(&server->logs_mutex); down_write(&server->alloc_rwsem); @@ -575,21 +487,17 @@ static int reclaim_log_trees(struct super_block *sb, u64 rid) goto out; } - tot = le64_to_cpu(super->core_data_alloc.total_free) + - le64_to_cpu(ltv.data_alloc.total_free); - curs = 0; - ret = scoutfs_data_move_alloc_bits(sb, &server->alloc, &server->wri, - &super->core_data_alloc, - <v.data_alloc, &curs, tot); + ret = scoutfs_radix_merge(sb, &server->alloc, &server->wri, + &super->core_data_avail, + <v.data_avail, <v.data_avail, + le64_to_cpu(ltv.data_avail.ref.sm_total)); if (ret < 0) goto out; - tot = le64_to_cpu(super->core_data_alloc.total_free) + - le64_to_cpu(ltv.data_free.total_free); - curs = 0; - ret = scoutfs_data_move_alloc_bits(sb, &server->alloc, &server->wri, - &super->core_data_alloc, - <v.data_free, &curs, tot); + ret = scoutfs_radix_merge(sb, &server->alloc, &server->wri, + &super->core_data_avail, + <v.data_freed, <v.data_freed, + le64_to_cpu(ltv.data_freed.ref.sm_total)); out: up_write(&server->alloc_rwsem); mutex_unlock(&server->logs_mutex); @@ -801,7 +709,9 @@ static int server_statfs(struct super_block *sb, spin_unlock(&sbi->next_ino_lock); down_read(&server->alloc_rwsem); - nstatfs.total_blocks = super->total_blocks; + nstatfs.total_blocks = super->total_meta_blocks; + le64_add_cpu(&nstatfs.total_blocks, + le64_to_cpu(super->total_data_blocks)); nstatfs.bfree = super->free_blocks; up_read(&server->alloc_rwsem); ret = 0; @@ -1408,8 +1318,8 @@ static void scoutfs_server_worker(struct work_struct *work) if (ret < 0) goto shutdown; - scoutfs_balloc_init(&server->alloc, &super->core_balloc_alloc, - &super->core_balloc_free); + scoutfs_radix_init_alloc(&server->alloc, &super->core_meta_avail, + &super->core_meta_freed); scoutfs_block_writer_init(sb, &server->wri); ret = scoutfs_lock_server_setup(sb, &server->alloc, &server->wri); diff --git a/kmod/src/trans.c b/kmod/src/trans.c index 6bd4c218..a5017821 100644 --- a/kmod/src/trans.c +++ b/kmod/src/trans.c @@ -25,7 +25,7 @@ #include "counters.h" #include "client.h" #include "inode.h" -#include "balloc.h" +#include "radix.h" #include "block.h" #include "scoutfs_trace.h" @@ -64,7 +64,7 @@ struct trans_info { bool writing; struct scoutfs_log_trees lt; - struct scoutfs_balloc_allocator alloc; + struct scoutfs_radix_allocator alloc; struct scoutfs_block_writer wri; }; @@ -89,8 +89,8 @@ static int commit_btrees(struct super_block *sb) struct scoutfs_log_trees lt; lt = tri->lt; - lt.alloc_root = tri->alloc.alloc_root; - lt.free_root = tri->alloc.free_root; + lt.meta_avail = tri->alloc.avail; + lt.meta_freed = tri->alloc.freed; scoutfs_forest_get_btrees(sb, <); scoutfs_data_get_btrees(sb, <); @@ -110,7 +110,8 @@ int scoutfs_trans_get_log_trees(struct super_block *sb) ret = scoutfs_client_get_log_trees(sb, <); if (ret == 0) { tri->lt = lt; - scoutfs_balloc_init(&tri->alloc, <.alloc_root, <.free_root); + scoutfs_radix_init_alloc(&tri->alloc, <.meta_avail, + <.meta_freed); scoutfs_block_writer_init(sb, &tri->wri); scoutfs_forest_init_btrees(sb, &tri->alloc, &tri->wri, <);