diff --git a/kmod/src/counters.h b/kmod/src/counters.h index 22bf8645..ef808252 100644 --- a/kmod/src/counters.h +++ b/kmod/src/counters.h @@ -100,7 +100,7 @@ EXPAND_COUNTER(lock_grace_wait) \ EXPAND_COUNTER(lock_grant_request) \ EXPAND_COUNTER(lock_grant_response) \ - EXPAND_COUNTER(lock_invalidate_clean_item) \ + EXPAND_COUNTER(lock_invalidate_commit) \ EXPAND_COUNTER(lock_invalidate_coverage) \ EXPAND_COUNTER(lock_invalidate_inode) \ EXPAND_COUNTER(lock_invalidate_request) \ @@ -113,7 +113,6 @@ EXPAND_COUNTER(lock_shrink_request_aborted) \ EXPAND_COUNTER(lock_unlock) \ EXPAND_COUNTER(lock_wait) \ - EXPAND_COUNTER(lock_write_dirty_item) \ EXPAND_COUNTER(manifest_compact_migrate) \ EXPAND_COUNTER(manifest_hard_stale_error) \ EXPAND_COUNTER(manifest_read_excluded_key) \ @@ -157,8 +156,6 @@ EXPAND_COUNTER(trans_commit_item_flush) \ EXPAND_COUNTER(trans_commit_sync_fs) \ EXPAND_COUNTER(trans_commit_timer) \ - EXPAND_COUNTER(trans_level0_seg_write_bytes) \ - EXPAND_COUNTER(trans_level0_seg_writes) \ EXPAND_COUNTER(trans_write_item) \ EXPAND_COUNTER(trans_write_deletion_item) diff --git a/kmod/src/lock.c b/kmod/src/lock.c index aa3d6b04..6397d573 100644 --- a/kmod/src/lock.c +++ b/kmod/src/lock.c @@ -21,7 +21,7 @@ #include "super.h" #include "lock.h" -#include "item.h" +#include "forest.h" #include "scoutfs_trace.h" #include "msg.h" #include "cmp.h" @@ -145,12 +145,10 @@ static void invalidate_inode(struct super_block *sb, u64 ino) static int lock_invalidate(struct super_block *sb, struct scoutfs_lock *lock, int prev, int mode) { - struct scoutfs_key *start = &lock->start; - struct scoutfs_key *end = &lock->end; struct scoutfs_lock_coverage *cov; struct scoutfs_lock_coverage *tmp; u64 ino, last; - int ret; + int ret = 0; trace_scoutfs_lock_invalidate(sb, lock); @@ -159,12 +157,12 @@ static int lock_invalidate(struct super_block *sb, struct scoutfs_lock *lock, mode != SCOUTFS_LOCK_NULL); /* any transition from a mode allowed to dirty items has to write */ - if (lock_mode_can_write(prev)) { - ret = scoutfs_item_writeback(sb, start, end); + if (lock_mode_can_write(prev) && scoutfs_forest_has_dirty(sb)) { + ret = scoutfs_trans_sync(sb, 1); if (ret < 0) return ret; if (ret > 0) { - scoutfs_add_counter(sb, lock_write_dirty_item, ret); + scoutfs_add_counter(sb, lock_invalidate_commit, ret); ret = 0; } } @@ -195,13 +193,6 @@ retry: ino++; } } - - ret = scoutfs_item_invalidate(sb, start, end); - if (ret > 0) { - scoutfs_add_counter(sb, lock_invalidate_clean_item, - ret); - ret = 0; - } } return ret; @@ -548,49 +539,6 @@ static void extend_grace(struct super_block *sb, struct scoutfs_lock *lock) lock->grace_deadline = ktime_add(now, GRACE_PERIOD_KT); } -/* - * The given lock is processing a received a grant response. Trigger a - * bug if the cache is inconsistent. - * - * We only have two modes that can create dirty items. We can't have - * dirty items when transitioning from write_only to write because the - * writer can't trust the cached items in the cache for reading. And we - * don't currently transition directly from write to write_only, we - * first go through null. So if we have dirty items as we're granted a - * mode it's always incorrect. - * - * And we can't have cached items that we're going to use for reading if - * the previous mode didn't allow reading. - * - * Inconsistencies have come from all sorts of bugs: invalidation missed - * items, the cache was populated outside of locking coverage, lock - * holders performed the wrong item operations under their lock, - * overlapping locks, out of order granting or invalidating, etc. - */ -static void bug_on_inconsistent_grant_cache(struct super_block *sb, - struct scoutfs_lock *lock, - int old_mode, int new_mode) -{ - bool cached = scoutfs_item_range_cached(sb, &lock->start, &lock->end, - false); - bool dirty = scoutfs_item_range_cached(sb, &lock->start, &lock->end, - true); - - if (dirty || - (cached && (!lock_mode_can_read(old_mode) || !lock_mode_can_read(new_mode)))) { - scoutfs_err(sb, "granted lock item cache inconsistency, cached %u dirty %u old_mode %d new_mode %d: start "SK_FMT" end "SK_FMT" refresh_gen %llu mode %u waiters: rd %u wr %u wo %u users: rd %u wr %u wo %u", - cached, dirty, old_mode, new_mode, SK_ARG(&lock->start), - SK_ARG(&lock->end), lock->refresh_gen, lock->mode, - lock->waiters[SCOUTFS_LOCK_READ], - lock->waiters[SCOUTFS_LOCK_WRITE], - lock->waiters[SCOUTFS_LOCK_WRITE_ONLY], - lock->users[SCOUTFS_LOCK_READ], - lock->users[SCOUTFS_LOCK_WRITE], - lock->users[SCOUTFS_LOCK_WRITE_ONLY]); - BUG(); - } -} - /* * The client is receiving a lock response message from the server. * This can be reordered with incoming invlidation requests from the @@ -631,8 +579,6 @@ int scoutfs_lock_grant_response(struct super_block *sb, spin_lock(&linfo->lock); } - bug_on_inconsistent_grant_cache(sb, lock, nl->old_mode, nl->new_mode); - if (!lock_mode_can_read(nl->old_mode) && lock_mode_can_read(nl->new_mode)) { lock->refresh_gen = diff --git a/kmod/src/scoutfs_trace.h b/kmod/src/scoutfs_trace.h index 4c2f9a4d..bcdfaf5c 100644 --- a/kmod/src/scoutfs_trace.h +++ b/kmod/src/scoutfs_trace.h @@ -570,13 +570,13 @@ TRACE_EVENT(scoutfs_sync_fs, ); TRACE_EVENT(scoutfs_trans_write_func, - TP_PROTO(struct super_block *sb, int dirty), + TP_PROTO(struct super_block *sb, unsigned long dirty), TP_ARGS(sb, dirty), TP_STRUCT__entry( SCSB_TRACE_FIELDS - __field(int, dirty) + __field(unsigned long, dirty) ), TP_fast_assign( @@ -584,7 +584,7 @@ TRACE_EVENT(scoutfs_trans_write_func, __entry->dirty = dirty; ), - TP_printk(SCSBF" dirty %d", SCSB_TRACE_ARGS, __entry->dirty) + TP_printk(SCSBF" dirty %lu", SCSB_TRACE_ARGS, __entry->dirty) ); TRACE_EVENT(scoutfs_release_trans, diff --git a/kmod/src/super.c b/kmod/src/super.c index b3b5370d..34f9f8df 100644 --- a/kmod/src/super.c +++ b/kmod/src/super.c @@ -435,7 +435,8 @@ static int scoutfs_fill_super(struct super_block *sb, void *data, int silent) scoutfs_server_setup(sb) ?: scoutfs_client_setup(sb) ?: scoutfs_lock_rid(sb, SCOUTFS_LOCK_WRITE, 0, sbi->rid, - &sbi->rid_lock); + &sbi->rid_lock) ?: + scoutfs_forest_get_log_trees(sb); if (ret) goto out; diff --git a/kmod/src/trans.c b/kmod/src/trans.c index 710fa6cd..aa7930d6 100644 --- a/kmod/src/trans.c +++ b/kmod/src/trans.c @@ -23,6 +23,7 @@ #include "data.h" #include "bio.h" #include "item.h" +#include "forest.h" #include "manifest.h" #include "seg.h" #include "counters.h" @@ -110,44 +111,27 @@ void scoutfs_trans_write_func(struct work_struct *work) trans_write_work.work); struct super_block *sb = sbi->sb; DECLARE_TRANS_INFO(sb, tri); - struct scoutfs_bio_completion comp; - struct scoutfs_segment *seg = NULL; - u64 segno; int ret = 0; - scoutfs_bio_init_comp(&comp); sbi->trans_task = current; wait_event(sbi->trans_hold_wq, drained_holders(tri)); - trace_scoutfs_trans_write_func(sb, scoutfs_item_has_dirty(sb)); + trace_scoutfs_trans_write_func(sb, scoutfs_forest_dirty_bytes(sb)); - - if (scoutfs_item_has_dirty(sb)) { + if (scoutfs_forest_has_dirty(sb)) { if (sbi->trans_deadline_expired) scoutfs_inc_counter(sb, trans_commit_timer); - /* - * XXX only straight pass through, we're not worrying - * about leaking segnos nor duplicate manifest entries - * on crashes between us and the server. - */ + ret = scoutfs_inode_walk_writeback(sb, true) ?: - scoutfs_client_alloc_segno(sb, &segno) ?: - scoutfs_seg_alloc(sb, segno, &seg) ?: - scoutfs_item_dirty_seg(sb, seg) ?: - scoutfs_seg_submit_write(sb, seg, &comp) ?: + scoutfs_forest_write(sb) ?: scoutfs_inode_walk_writeback(sb, false) ?: - scoutfs_bio_wait_comp(sb, &comp) ?: - scoutfs_client_record_segment(sb, seg, 0) ?: - scoutfs_client_advance_seq(sb, &sbi->trans_seq); - scoutfs_seg_put(seg); + scoutfs_forest_commit(sb) ?: + scoutfs_client_advance_seq(sb, &sbi->trans_seq) ?: + scoutfs_forest_get_log_trees(sb); if (ret) goto out; - scoutfs_inc_counter(sb, trans_level0_seg_writes); - scoutfs_add_counter(sb, trans_level0_seg_write_bytes, - scoutfs_seg_total_bytes(seg)); - } else if (sbi->trans_deadline_expired) { /* * If we're not writing data then we only advance the @@ -295,7 +279,6 @@ static bool acquired_hold(struct super_block *sb, bool acquired = false; unsigned items; unsigned vals; - bool fits; spin_lock(&tri->lock); @@ -316,8 +299,9 @@ static bool acquired_hold(struct super_block *sb, /* see if we can reserve space for our item count */ items = tri->reserved_items + cnt->items; vals = tri->reserved_vals + cnt->vals; - fits = scoutfs_item_dirty_fits_single(sb, items, vals); - if (!fits) { + + /* XXX just limit to 256K transactions */ + if (scoutfs_forest_dirty_bytes(sb) >= (256 * 1024)) { scoutfs_inc_counter(sb, trans_commit_full); queue_trans_work(sbi); goto out; @@ -352,8 +336,7 @@ int scoutfs_hold_trans(struct super_block *sb, * Caller shouldn't provide garbage counts, nor counts that * can't fit in segments by themselves. */ - if (WARN_ON_ONCE(cnt.items <= 0 || cnt.vals < 0) || - WARN_ON_ONCE(!scoutfs_seg_fits_single(cnt.items, cnt.vals))) + if (WARN_ON_ONCE(cnt.items <= 0 || cnt.vals < 0)) return -EINVAL; if (current == sbi->trans_task)