@@ -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;
@@ -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);
@@ -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
/*