mirror of
https://github.com/versity/scoutfs.git
synced 2026-01-07 20:45:18 +00:00
@@ -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
|
||||
|
||||
@@ -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) ?:
|
||||
|
||||
@@ -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
118
kmod/src/triggers.c
Normal 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
17
kmod/src/triggers.h
Normal 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
|
||||
Reference in New Issue
Block a user