scoutfs: add triggers

Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
Zach Brown
2017-12-18 11:29:02 -08:00
committed by Mark Fasheh
parent bbcf76e154
commit 9ed34f8892
5 changed files with 141 additions and 1 deletions

View File

@@ -9,7 +9,7 @@ scoutfs-y += alloc.o bio.o btree.o client.o compact.o counters.o data.o dir.o \
dlmglue.o file.o kvec.o inode.o ioctl.o item.o key.o lock.o \
manifest.o msg.o options.o per_task.o seg.o server.o \
scoutfs_trace.o sock.o sort_priv.o stackglue.o super.o trans.o \
xattr.o
triggers.o xattr.o
#
# The raw types aren't available in userspace headers. Make sure all

View File

@@ -28,6 +28,7 @@
#include "xattr.h"
#include "msg.h"
#include "counters.h"
#include "triggers.h"
#include "trans.h"
#include "item.h"
#include "manifest.h"
@@ -125,6 +126,7 @@ static void scoutfs_put_super(struct super_block *sb)
scoutfs_seg_destroy(sb);
scoutfs_lock_destroy(sb);
scoutfs_destroy_triggers(sb);
debugfs_remove(sbi->debug_root);
scoutfs_destroy_counters(sb);
if (sbi->kset)
@@ -324,6 +326,7 @@ static int scoutfs_fill_super(struct super_block *sb, void *data, int silent)
ret = scoutfs_setup_counters(sb) ?:
scoutfs_read_supers(sb, &SCOUTFS_SB(sb)->super) ?:
scoutfs_debugfs_setup(sb) ?:
scoutfs_setup_triggers(sb) ?:
scoutfs_seg_setup(sb) ?:
scoutfs_item_setup(sb) ?:
scoutfs_inode_setup(sb) ?:

View File

@@ -8,6 +8,7 @@
#include "options.h"
struct scoutfs_counters;
struct scoutfs_triggers;
struct item_cache;
struct manifest;
struct segment_cache;
@@ -61,6 +62,7 @@ struct scoutfs_sb_info {
struct kset *kset;
struct scoutfs_counters *counters;
struct scoutfs_triggers *triggers;
struct mount_options opts;

118
kmod/src/triggers.c Normal file
View File

@@ -0,0 +1,118 @@
/*
* Copyright (C) 2017 Versity Software, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License v2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/atomic.h>
#include <linux/debugfs.h>
#include "super.h"
#include "triggers.h"
/*
* We have debugfs files we can write to which arm triggers which
* atomically fire once for testing or debugging.
*/
/*
* The atomic cachelines are kept hot and shared by being read by fast
* paths. They're very rarely modified by debugfs writes which arm them
* and then the next read will atomically clear and return true.
*/
struct scoutfs_triggers {
struct dentry *dir;
atomic_t atomics[SCOUTFS_TRIGGER_NR];
};
#define DECLARE_TRIGGERS(sb, name) \
struct scoutfs_triggers *name = SCOUTFS_SB(sb)->triggers
static char *names[] = {
[SCOUTFS_TRIGGER_SOMETHING] = "something",
};
bool scoutfs_trigger_test_and_clear(struct super_block *sb, unsigned int t)
{
DECLARE_TRIGGERS(sb, triggers);
atomic_t *atom;
int old;
int mem;
BUG_ON(t >= SCOUTFS_TRIGGER_NR);
atom = &triggers->atomics[t];
mem = atomic_read(atom);
if (likely(!mem))
return 0;
do {
old = mem;
mem = atomic_cmpxchg(atom, old, 0);
} while (mem && mem != old);
return !!mem;
}
int scoutfs_setup_triggers(struct super_block *sb)
{
struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb);
struct scoutfs_triggers *triggers;
int ret;
int i;
BUILD_BUG_ON(ARRAY_SIZE(names) != SCOUTFS_TRIGGER_NR);
for (i = 0; i < ARRAY_SIZE(names); i++) {
if (WARN_ON(!names[i]))
return -EINVAL;
}
triggers = kzalloc(sizeof(struct scoutfs_triggers), GFP_KERNEL);
if (!triggers)
return -ENOMEM;
sbi->triggers = triggers;
triggers->dir = debugfs_create_dir("trigger", sbi->debug_root);
if (!triggers->dir) {
ret = -ENOMEM;
goto out;
}
for (i = 0; i < ARRAY_SIZE(triggers->atomics); i++) {
if (!debugfs_create_atomic_t(names[i], 0644, triggers->dir,
&triggers->atomics[i])) {
ret = -ENOMEM;
goto out;
}
}
ret = 0;
out:
if (ret)
scoutfs_destroy_triggers(sb);
return ret;
}
void scoutfs_destroy_triggers(struct super_block *sb)
{
struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb);
struct scoutfs_triggers *triggers = sbi->triggers;
if (triggers) {
if (triggers->dir)
debugfs_remove_recursive(triggers->dir);
kfree(triggers);
sbi->triggers = NULL;
}
}

17
kmod/src/triggers.h Normal file
View File

@@ -0,0 +1,17 @@
#ifndef _SCOUTFS_TRIGGERS_H_
#define _SCOUTFS_TRIGGERS_H_
enum {
SCOUTFS_TRIGGER_SOMETHING,
SCOUTFS_TRIGGER_NR,
};
bool scoutfs_trigger_test_and_clear(struct super_block *sb, unsigned int t);
#define scoutfs_trigger(sb, which) \
scoutfs_trigger_test_and_clear(sb, SCOUTFS_TRIGGER_##which)
int scoutfs_setup_triggers(struct super_block *sb);
void scoutfs_destroy_triggers(struct super_block *sb);
#endif