scoutfs: use radix allocator

Convert metadata block and file data extent allocations to use the radix
allocator.

Most of this is simple transitions between types and calls.  The server
no longer has to initialize blocks because mkfs can write a single
radix parent block with fully set parent refs to initialize a full
radix.  We remove the code and fields that were responsible for adding
uninitialized data and metadata.

The rest of the unused block allocator code is only ifdefed out.  It'll
be removed in a separate patch to reduce noise here.

Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
Zach Brown
2020-02-13 15:52:35 -08:00
committed by Zach Brown
parent 455a547e8e
commit 85142dcadf
13 changed files with 158 additions and 250 deletions
-1
View File
@@ -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 \
+18 -18
View File
@@ -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)
+6 -6
View File
@@ -3,7 +3,7 @@
#include <linux/uio.h>
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);
+42 -46
View File
@@ -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);
}
+4 -2
View File
@@ -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,
+7 -8
View File
@@ -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)
{
+2 -2
View File
@@ -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,
+20 -21
View File
@@ -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;
+3 -3
View File
@@ -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);
+1 -1
View File
@@ -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);
+2
View File
@@ -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,
+47 -137
View File
@@ -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(&ltv, 0, sizeof(ltv));
scoutfs_radix_root_init(sb, &ltv.meta_avail, true);
scoutfs_radix_root_init(sb, &ltv.meta_freed, true);
scoutfs_radix_root_init(sb, &ltv.data_avail, false);
scoutfs_radix_root_init(sb, &ltv.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,
&ltv.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,
&ltv.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,
&ltv.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,
&ltv.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, &ltk, 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(&ltk, 0, sizeof(ltk));
memset(&ltv, 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,
&ltv.data_alloc, &curs, tot);
ret = scoutfs_radix_merge(sb, &server->alloc, &server->wri,
&super->core_data_avail,
&ltv.data_avail, &ltv.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,
&ltv.data_free, &curs, tot);
ret = scoutfs_radix_merge(sb, &server->alloc, &server->wri,
&super->core_data_avail,
&ltv.data_freed, &ltv.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);
+6 -5
View File
@@ -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, &lt);
scoutfs_data_get_btrees(sb, &lt);
@@ -110,7 +110,8 @@ int scoutfs_trans_get_log_trees(struct super_block *sb)
ret = scoutfs_client_get_log_trees(sb, &lt);
if (ret == 0) {
tri->lt = lt;
scoutfs_balloc_init(&tri->alloc, &lt.alloc_root, &lt.free_root);
scoutfs_radix_init_alloc(&tri->alloc, &lt.meta_avail,
&lt.meta_freed);
scoutfs_block_writer_init(sb, &tri->wri);
scoutfs_forest_init_btrees(sb, &tri->alloc, &tri->wri, &lt);