From: Bryan Schumaker <[email protected]>
These patches apply on top of v2 of my fault injection framework
(submitted on may 20). They clean up the injection file creation and
add in a method to allow users to specifiy the maximum number of items
to forget or recall.
- Bryan
From: Bryan Schumaker <[email protected]>
This number represents the maximum number of items to either forget or
recall. Passing 0 means that we should forget or recall all items.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfsd/fault_inject.c | 35 ++++++++++-------
fs/nfsd/nfs4state.c | 96 ++++++++++++++++++++++++++++++++++--------------
fs/nfsd/nfsd.h | 20 +++++-----
3 files changed, 98 insertions(+), 53 deletions(-)
diff --git a/fs/nfsd/fault_inject.c b/fs/nfsd/fault_inject.c
index 7f5ac83..b987d39 100644
--- a/fs/nfsd/fault_inject.c
+++ b/fs/nfsd/fault_inject.c
@@ -9,14 +9,14 @@
#include "state.h"
#include "nfsd.h"
-static void nfsd_forget_everything(void);
+static void nfsd_forget_everything(u64);
struct nfsd_fault_inject_op {
char *action;
char *item;
char *file;
int file_data;
- void (*func)(void);
+ void (*func)(u64);
};
#define INJECTION_OP(op_action, op_item, op_func) \
@@ -28,23 +28,23 @@ struct nfsd_fault_inject_op {
}
static struct nfsd_fault_inject_op inject_ops[] = {
- INJECTION_OP("forget", "clients", nfsd_forget_all_clients),
- INJECTION_OP("forget", "locks", nfsd_forget_all_locks),
- INJECTION_OP("forget", "open_owners", nfsd_forget_all_open_owners),
- INJECTION_OP("forget", "delegations", nfsd_forget_all_delegations),
+ INJECTION_OP("forget", "clients", nfsd_forget_clients),
+ INJECTION_OP("forget", "locks", nfsd_forget_locks),
+ INJECTION_OP("forget", "open_owners", nfsd_forget_open_owners),
+ INJECTION_OP("forget", "delegations", nfsd_forget_delegations),
INJECTION_OP("forget", "everything", nfsd_forget_everything),
- INJECTION_OP("recall", "delegations", nfsd_recall_all_delegations),
+ INJECTION_OP("recall", "delegations", nfsd_recall_delegations),
};
static long int NUM_INJECT_OPS = sizeof(inject_ops) / sizeof(struct nfsd_fault_inject_op);
static struct dentry *debug_dir;
-static void nfsd_forget_everything(void)
+static void nfsd_forget_everything(u64 num)
{
- nfsd_forget_all_clients();
- nfsd_forget_all_locks();
- nfsd_forget_all_open_owners();
- nfsd_forget_all_delegations();
+ nfsd_forget_clients(num);
+ nfsd_forget_locks(num);
+ nfsd_forget_open_owners(num);
+ nfsd_forget_delegations(num);
}
static int nfsd_inject_set(void *data, u64 val)
@@ -54,9 +54,14 @@ static int nfsd_inject_set(void *data, u64 val)
for (i = 0; i < NUM_INJECT_OPS; i++) {
op = &inject_ops[i];
if (&op->file_data == data) {
- printk(KERN_INFO "%s %s Server will %s all %s", __FILE__,
- __func__, op->action, op->item);
- op->func();
+ if (val == 0) {
+ printk(KERN_INFO "%s %s Server %sing all %s",
+ __FILE__, __func__, op->action, op->item);
+ } else {
+ printk(KERN_INFO "%s %s Server %sing at most %llu %s",
+ __FILE__, __func__, op->action, val, op->item);
+ }
+ op->func(val);
}
}
return 0;
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 0b124c8..672d904 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -4439,7 +4439,7 @@ nfs4_check_open_reclaim(clientid_t *clid)
#ifdef CONFIG_NFSD_FAULT_INJECTION
-void nfsd_forget_all_clients(void)
+void nfsd_forget_clients(u64 num)
{
struct nfs4_client *clp;
struct list_head *pos, *next, reaplist;
@@ -4453,7 +4453,8 @@ void nfsd_forget_all_clients(void)
clp = list_entry(pos, struct nfs4_client, cl_lru);
unhash_client_locked(clp);
list_add(&clp->cl_lru, &reaplist);
- count ++;
+ if (++count == num)
+ break;
}
spin_unlock(&client_lock);
list_for_each_safe(pos, next, &reaplist) {
@@ -4466,107 +4467,146 @@ void nfsd_forget_all_clients(void)
printk(KERN_INFO "%s %s Forgot %d clients", __FILE__, __func__, count);
}
-void nfsd_forget_all_locks(void)
+int nfsd_forget_locks_reaplist(struct list_head *reaplist, u64 num)
{
+ int i;
+ int count = 0;
struct nfs4_stateid *stp;
struct nfs4_stateowner *sop;
- struct list_head reaplist;
- int count = 0;
- int i;
- INIT_LIST_HEAD(&reaplist);
- nfs4_lock_state();
+ INIT_LIST_HEAD(reaplist);
+
for (i = 0; i < LOCK_HASH_SIZE; i++) {
list_for_each_entry(sop, &lock_ownerid_hashtbl[i], so_idhash) {
list_for_each_entry(stp, &sop->so_stateids, st_perstateowner) {
- list_add(&sop->so_perclient, &reaplist);
+ list_add(&sop->so_perclient, reaplist);
+ if (++count == num)
+ return count;
}
}
}
+ return count;
+}
+
+void nfsd_forget_locks(u64 num)
+{
+ struct nfs4_stateowner *sop;
+ struct list_head reaplist;
+ int count;
+ nfs4_lock_state();
+ count = nfsd_forget_locks_reaplist(&reaplist, num);
while (!list_empty(&reaplist)) {
sop = list_entry(reaplist.next, struct nfs4_stateowner, so_perclient);
list_del(&sop->so_perclient);
release_lockowner(sop);
- count ++;
}
nfs4_unlock_state();
printk(KERN_INFO "%s %s Forgot %d locks", __FILE__, __func__, count);
}
-void nfsd_forget_all_open_owners(void)
+int nfsd_forget_n_open_owners(u64 num)
{
+ int i, count = 0;
struct nfs4_stateid *stp, *next;
- unsigned int i;
- int count = 0;
- nfs4_lock_state();
for (i = 0; i < STATEID_HASH_SIZE; i++) {
list_for_each_entry_safe(stp, next, &stateid_hashtbl[i], st_hash) {
if (stp->st_openstp == NULL) {
release_openowner(stp->st_stateowner);
- count++;
+ if (++count == num)
+ return count;
}
}
}
+ return count;
+}
+
+void nfsd_forget_open_owners(u64 num)
+{
+ int count;
+ nfs4_lock_state();
+ count = nfsd_forget_n_open_owners(num);
nfs4_unlock_state();
printk(KERN_INFO "%s %s Forgot %d open owners", __FILE__, __func__, count);
}
-void nfsd_forget_all_delegations(void)
+int nfsd_forget_delegations_reaplist(struct list_head *reaplist, u64 num)
{
+ int i, count = 0;
struct nfs4_file *fp;
struct nfs4_delegation *dp;
- struct list_head *pos, *next, reaplist;
- unsigned int i;
- unsigned int count = 0;
+ struct list_head *pos;
- INIT_LIST_HEAD(&reaplist);
+ INIT_LIST_HEAD(reaplist);
- nfs4_lock_state();
spin_lock(&recall_lock);
for (i = 0; i < FILE_HASH_SIZE; i++) {
list_for_each_entry(fp, &file_hashtbl[i], fi_hash) {
list_for_each(pos, &fp->fi_delegations) {
dp = list_entry(pos, struct nfs4_delegation, dl_perfile);
list_del_init(&dp->dl_perclnt);
- list_move(&dp->dl_recall_lru, &reaplist);
+ list_move(&dp->dl_recall_lru, reaplist);
+ if (++count == num)
+ return count;
}
}
}
+ return count;
+}
+
+void nfsd_forget_delegations(u64 num)
+{
+ struct nfs4_delegation *dp;
+ struct list_head *pos, *next, reaplist;
+ unsigned int count;
+
+ nfs4_lock_state();
+ spin_lock(&recall_lock);
+ count = nfsd_forget_delegations_reaplist(&reaplist, num);
spin_unlock(&recall_lock);
+
list_for_each_safe(pos, next, &reaplist) {
dp = list_entry(pos, struct nfs4_delegation, dl_recall_lru);
list_del_init(&dp->dl_recall_lru);
unhash_delegation(dp);
count++;
}
- nfs4_unlock_state();
+ nfs4_unlock_state();
printk(KERN_INFO "%s %s Forgot %d delegations", __FILE__, __func__, count);
}
-void nfsd_recall_all_delegations(void)
+int nfsd_recall_n_delegations(u64 num)
{
struct nfs4_file *fp;
struct nfs4_delegation *dp;
struct list_head *pos;
unsigned int i;
- unsigned int count = 0;
+ int count = 0;
- nfs4_lock_state();
- spin_lock(&recall_lock);
for (i = 0; i < FILE_HASH_SIZE; i++) {
list_for_each_entry(fp, &file_hashtbl[i], fi_hash) {
list_for_each(pos, &fp->fi_delegations) {
dp = list_entry(pos, struct nfs4_delegation, dl_perfile);
nfsd_break_one_deleg(dp);
- count++;
+ if (++count == num)
+ return count;
}
}
}
+
+ return count;
+}
+
+void nfsd_recall_delegations(u64 num)
+{
+ unsigned int count;
+ nfs4_lock_state();
+ spin_lock(&recall_lock);
+ count = nfsd_recall_n_delegations(num);
spin_unlock(&recall_lock);
nfs4_unlock_state();
printk(KERN_INFO "%s %s Recalled %d delegations", __FILE__, __func__, count);
diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h
index 4a6cded..167a824 100644
--- a/fs/nfsd/nfsd.h
+++ b/fs/nfsd/nfsd.h
@@ -86,11 +86,11 @@ int nfs4_state_start(void);
void nfs4_state_shutdown(void);
void nfs4_reset_lease(time_t leasetime);
int nfs4_reset_recoverydir(char *recdir);
-void nfsd_forget_all_clients(void);
-void nfsd_forget_all_locks(void);
-void nfsd_forget_all_open_owners(void);
-void nfsd_forget_all_delegations(void);
-void nfsd_recall_all_delegations(void);
+void nfsd_forget_clients(u64);
+void nfsd_forget_locks(u64);
+void nfsd_forget_open_owners(u64);
+void nfsd_forget_delegations(u64);
+void nfsd_recall_delegations(u64);
#else
static inline int nfs4_state_init(void) { return 0; }
static inline void nfsd4_free_slabs(void) { }
@@ -98,11 +98,11 @@ static inline int nfs4_state_start(void) { return 0; }
static inline void nfs4_state_shutdown(void) { }
static inline void nfs4_reset_lease(time_t leasetime) { }
static inline int nfs4_reset_recoverydir(char *recdir) { return 0; }
-static inline void nfsd_forget_all_clients(void) {};
-static inline void nfsd_forget_all_locks(void) {};
-static inline void nfsd_forget_all_open_owners(void) {};
-static inline void nfsd_forget_all_delegations(void) {};
-static inline void nfsd_recall_all_delegations(void) {};
+static inline void nfsd_forget_clients(u64) {};
+static inline void nfsd_forget_locks(u64) {};
+static inline void nfsd_forget_open_owners(u64) {};
+static inline void nfsd_forget_delegations(u64) {};
+static inline void nfsd_recall_delegations(u64) {};
#endif
/*
--
1.7.6
From: Bryan Schumaker <[email protected]>
I think it is easier to specify an action and an item (such as "forget" and
"clients") once, rather than having to state them multiple times for the same
macro.
Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfsd/fault_inject.c | 39 ++++++++++++++++++++++-----------------
1 files changed, 22 insertions(+), 17 deletions(-)
diff --git a/fs/nfsd/fault_inject.c b/fs/nfsd/fault_inject.c
index 3dd1c32..7f5ac83 100644
--- a/fs/nfsd/fault_inject.c
+++ b/fs/nfsd/fault_inject.c
@@ -12,26 +12,28 @@
static void nfsd_forget_everything(void);
struct nfsd_fault_inject_op {
- char *name;
- char *text;
+ char *action;
+ char *item;
+ char *file;
int file_data;
void (*func)(void);
};
-#define INJECTION_OP(op_name, op_text, op_func) \
-{ \
- .name = op_name, \
- .text = op_text, \
- .func = op_func, \
+#define INJECTION_OP(op_action, op_item, op_func) \
+{ \
+ .action = op_action, \
+ .item = op_item, \
+ .file = op_action"_"op_item, \
+ .func = op_func, \
}
static struct nfsd_fault_inject_op inject_ops[] = {
- INJECTION_OP("forget_clients", "forget all clients", nfsd_forget_all_clients),
- INJECTION_OP("forget_locks", "forget all locks", nfsd_forget_all_locks),
- INJECTION_OP("forget_open_owners", "forget all open owners", nfsd_forget_all_open_owners),
- INJECTION_OP("forget_delegations", "forget all delegations", nfsd_forget_all_delegations),
- INJECTION_OP("forget_everything", "forget everything", nfsd_forget_everything),
- INJECTION_OP("recall_delegations", "recall all delegations", nfsd_recall_all_delegations),
+ INJECTION_OP("forget", "clients", nfsd_forget_all_clients),
+ INJECTION_OP("forget", "locks", nfsd_forget_all_locks),
+ INJECTION_OP("forget", "open_owners", nfsd_forget_all_open_owners),
+ INJECTION_OP("forget", "delegations", nfsd_forget_all_delegations),
+ INJECTION_OP("forget", "everything", nfsd_forget_everything),
+ INJECTION_OP("recall", "delegations", nfsd_recall_all_delegations),
};
static long int NUM_INJECT_OPS = sizeof(inject_ops) / sizeof(struct nfsd_fault_inject_op);
@@ -48,10 +50,13 @@ static void nfsd_forget_everything(void)
static int nfsd_inject_set(void *data, u64 val)
{
int i;
+ struct nfsd_fault_inject_op *op;
for (i = 0; i < NUM_INJECT_OPS; i++) {
- if (&inject_ops[i].file_data == data) {
- printk(KERN_INFO "%s %s Server will %s", __FILE__, __func__, inject_ops[i].text);
- inject_ops[i].func();
+ op = &inject_ops[i];
+ if (&op->file_data == data) {
+ printk(KERN_INFO "%s %s Server will %s all %s", __FILE__,
+ __func__, op->action, op->item);
+ op->func();
}
}
return 0;
@@ -83,7 +88,7 @@ nfsd_fault_inject_init(void)
for (i = 0; i < NUM_INJECT_OPS; i++) {
op = &inject_ops[i];
- debugfs_create_file(op->name, mode, debug_dir, &op->file_data, &fops_nfsd);
+ debugfs_create_file(op->file, mode, debug_dir, &op->file_data, &fops_nfsd);
}
return 0;
fail:
--
1.7.6