aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4state.c
diff options
context:
space:
mode:
authorJeff Layton <jlayton@primarydata.com>2014-07-30 08:27:22 -0400
committerJ. Bruce Fields <bfields@redhat.com>2014-08-05 10:55:08 -0400
commit82e05efaec9b5b1528771b30c27d060961576827 (patch)
tree4b644391f9c4d0af4d7723667bed98e8c030be0e /fs/nfsd/nfs4state.c
parent016200c37341b62df14ec642b0b30b4b70bc09af (diff)
nfsd: add more granular locking to forget_openowners fault injector
...instead of relying on the client_mutex. Also, fix up the printk output that is generated when the file is read. It currently says that it's reporting the number of open files, but it's actually reporting the number of openowners. Signed-off-by: Jeff Layton <jlayton@primarydata.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r--fs/nfsd/nfs4state.c122
1 files changed, 114 insertions, 8 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 48ae0a66d512..20bffa8c976c 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -5965,30 +5965,136 @@ nfsd_inject_forget_locks(struct nfsd_fault_inject_op *op, u64 max)
5965 return count; 5965 return count;
5966} 5966}
5967 5967
5968static u64 nfsd_foreach_client_open(struct nfs4_client *clp, u64 max, void (*func)(struct nfs4_openowner *)) 5968static u64
5969nfsd_foreach_client_openowner(struct nfs4_client *clp, u64 max,
5970 struct list_head *collect,
5971 void (*func)(struct nfs4_openowner *))
5969{ 5972{
5970 struct nfs4_openowner *oop, *next; 5973 struct nfs4_openowner *oop, *next;
5974 struct nfsd_net *nn = net_generic(current->nsproxy->net_ns,
5975 nfsd_net_id);
5971 u64 count = 0; 5976 u64 count = 0;
5972 5977
5978 lockdep_assert_held(&nn->client_lock);
5979
5980 spin_lock(&clp->cl_lock);
5973 list_for_each_entry_safe(oop, next, &clp->cl_openowners, oo_perclient) { 5981 list_for_each_entry_safe(oop, next, &clp->cl_openowners, oo_perclient) {
5974 if (func) 5982 if (func) {
5975 func(oop); 5983 func(oop);
5976 if (++count == max) 5984 if (collect) {
5985 atomic_inc(&clp->cl_refcount);
5986 list_add(&oop->oo_perclient, collect);
5987 }
5988 }
5989 ++count;
5990 /*
5991 * Despite the fact that these functions deal with
5992 * 64-bit integers for "count", we must ensure that
5993 * it doesn't blow up the clp->cl_refcount. Throw a
5994 * warning if we start to approach INT_MAX here.
5995 */
5996 WARN_ON_ONCE(count == (INT_MAX / 2));
5997 if (count == max)
5977 break; 5998 break;
5978 } 5999 }
6000 spin_unlock(&clp->cl_lock);
6001
6002 return count;
6003}
5979 6004
6005static u64
6006nfsd_print_client_openowners(struct nfs4_client *clp)
6007{
6008 u64 count = nfsd_foreach_client_openowner(clp, 0, NULL, NULL);
6009
6010 nfsd_print_count(clp, count, "openowners");
5980 return count; 6011 return count;
5981} 6012}
5982 6013
5983u64 nfsd_forget_client_openowners(struct nfs4_client *clp, u64 max) 6014static u64
6015nfsd_collect_client_openowners(struct nfs4_client *clp,
6016 struct list_head *collect, u64 max)
5984{ 6017{
5985 return nfsd_foreach_client_open(clp, max, release_openowner); 6018 return nfsd_foreach_client_openowner(clp, max, collect,
6019 unhash_openowner_locked);
5986} 6020}
5987 6021
5988u64 nfsd_print_client_openowners(struct nfs4_client *clp, u64 max) 6022u64
6023nfsd_inject_print_openowners(struct nfsd_fault_inject_op *op)
5989{ 6024{
5990 u64 count = nfsd_foreach_client_open(clp, max, NULL); 6025 struct nfs4_client *clp;
5991 nfsd_print_count(clp, count, "open files"); 6026 u64 count = 0;
6027 struct nfsd_net *nn = net_generic(current->nsproxy->net_ns,
6028 nfsd_net_id);
6029
6030 if (!nfsd_netns_ready(nn))
6031 return 0;
6032
6033 spin_lock(&nn->client_lock);
6034 list_for_each_entry(clp, &nn->client_lru, cl_lru)
6035 count += nfsd_print_client_openowners(clp);
6036 spin_unlock(&nn->client_lock);
6037
6038 return count;
6039}
6040
6041static void
6042nfsd_reap_openowners(struct list_head *reaplist)
6043{
6044 struct nfs4_client *clp;
6045 struct nfs4_openowner *oop, *next;
6046
6047 list_for_each_entry_safe(oop, next, reaplist, oo_perclient) {
6048 list_del_init(&oop->oo_perclient);
6049 clp = oop->oo_owner.so_client;
6050 release_openowner(oop);
6051 put_client(clp);
6052 }
6053}
6054
6055u64
6056nfsd_inject_forget_client_openowners(struct nfsd_fault_inject_op *op,
6057 struct sockaddr_storage *addr, size_t addr_size)
6058{
6059 unsigned int count = 0;
6060 struct nfs4_client *clp;
6061 struct nfsd_net *nn = net_generic(current->nsproxy->net_ns,
6062 nfsd_net_id);
6063 LIST_HEAD(reaplist);
6064
6065 if (!nfsd_netns_ready(nn))
6066 return count;
6067
6068 spin_lock(&nn->client_lock);
6069 clp = nfsd_find_client(addr, addr_size);
6070 if (clp)
6071 count = nfsd_collect_client_openowners(clp, &reaplist, 0);
6072 spin_unlock(&nn->client_lock);
6073 nfsd_reap_openowners(&reaplist);
6074 return count;
6075}
6076
6077u64
6078nfsd_inject_forget_openowners(struct nfsd_fault_inject_op *op, u64 max)
6079{
6080 u64 count = 0;
6081 struct nfs4_client *clp;
6082 struct nfsd_net *nn = net_generic(current->nsproxy->net_ns,
6083 nfsd_net_id);
6084 LIST_HEAD(reaplist);
6085
6086 if (!nfsd_netns_ready(nn))
6087 return count;
6088
6089 spin_lock(&nn->client_lock);
6090 list_for_each_entry(clp, &nn->client_lru, cl_lru) {
6091 count += nfsd_collect_client_openowners(clp, &reaplist,
6092 max - count);
6093 if (max != 0 && count >= max)
6094 break;
6095 }
6096 spin_unlock(&nn->client_lock);
6097 nfsd_reap_openowners(&reaplist);
5992 return count; 6098 return count;
5993} 6099}
5994 6100