scoutfs: add trigger to drop lock cache

We have a corruption that can happen when a lock is reclaimed but it's
cache is still dirty. Detect this corruption by placing a trigger in
statfs which fires off lock reclaim. Statfs is nice because for scoutfs
it's lockless, which means there should not be any references on locks
when the trigger is fired.

Signed-off-by: Mark Fasheh <mfasheh@versity.com>
This commit is contained in:
Mark Fasheh
2018-01-14 10:58:05 -08:00
committed by Zach Brown
parent 5cc05d663e
commit 3661f06bec
5 changed files with 27 additions and 10 deletions
+15 -10
View File
@@ -29,6 +29,7 @@
#include "trans.h"
#include "counters.h"
#include "endian_swap.h"
#include "triggers.h"
#define LN_FMT "%u.%u.%u.%llu.%llu"
#define LN_ARG(name) \
@@ -592,19 +593,12 @@ static void scoutfs_lock_reclaim(struct work_struct *work)
put_scoutfs_lock(linfo->sb, lock);
}
static int shrink_lock_tree(struct shrinker *shrink, struct shrink_control *sc)
void scoutfs_free_unused_locks(struct super_block *sb, unsigned long nr)
{
struct lock_info *linfo = container_of(shrink, struct lock_info,
shrinker);
struct lock_info *linfo = SCOUTFS_SB(sb)->lock_info;
struct scoutfs_lock *lock;
struct scoutfs_lock *tmp;
unsigned long flags;
unsigned long nr;
int ret;
nr = sc->nr_to_scan;
if (!nr)
goto out;
spin_lock_irqsave(&linfo->lock, flags);
list_for_each_entry_safe(lock, tmp, &linfo->lru_list, lru_entry) {
@@ -622,8 +616,19 @@ static int shrink_lock_tree(struct shrinker *shrink, struct shrink_control *sc)
queue_work(linfo->lock_reclaim_wq, &lock->reclaim_work);
}
spin_unlock_irqrestore(&linfo->lock, flags);
}
static int shrink_lock_tree(struct shrinker *shrink, struct shrink_control *sc)
{
struct lock_info *linfo = container_of(shrink, struct lock_info,
shrinker);
unsigned long nr;
int ret;
nr = sc->nr_to_scan;
if (nr)
scoutfs_free_unused_locks(linfo->sb, nr);
out:
ret = min_t(unsigned long, linfo->lru_nr, INT_MAX);
trace_scoutfs_lock_shrink_exit(linfo->sb, sc->nr_to_scan, ret);
return ret;
+2
View File
@@ -60,6 +60,8 @@ void scoutfs_unlock(struct super_block *sb, struct scoutfs_lock *lock,
void scoutfs_unlock_flags(struct super_block *sb, struct scoutfs_lock *lock,
int level, int flags);
void scoutfs_free_unused_locks(struct super_block *sb, unsigned long nr);
int scoutfs_lock_setup(struct super_block *sb);
void scoutfs_lock_destroy(struct super_block *sb);
+8
View File
@@ -88,6 +88,14 @@ static int scoutfs_statfs(struct dentry *dentry, struct kstatfs *kst)
kst->f_frsize = SCOUTFS_BLOCK_SIZE;
/* the vfs fills f_flags */
/*
* We don't take cluster locks in statfs which makes it a very
* convenient place to trigger lock reclaim for debugging. We
* try to free as many locks as possible.
*/
if (scoutfs_trigger(sb, STATFS_LOCK_PURGE))
scoutfs_free_unused_locks(sb, -1UL);
return 0;
}
+1
View File
@@ -41,6 +41,7 @@ static char *names[] = {
[SCOUTFS_TRIGGER_BTREE_STALE_READ] = "btree_stale_read",
[SCOUTFS_TRIGGER_HARD_STALE_ERROR] = "hard_stale_error",
[SCOUTFS_TRIGGER_SEG_STALE_READ] = "seg_stale_read",
[SCOUTFS_TRIGGER_STATFS_LOCK_PURGE] = "statfs_lock_purge",
};
bool scoutfs_trigger_test_and_clear(struct super_block *sb, unsigned int t)
+1
View File
@@ -5,6 +5,7 @@ enum {
SCOUTFS_TRIGGER_BTREE_STALE_READ,
SCOUTFS_TRIGGER_HARD_STALE_ERROR,
SCOUTFS_TRIGGER_SEG_STALE_READ,
SCOUTFS_TRIGGER_STATFS_LOCK_PURGE,
SCOUTFS_TRIGGER_NR,
};