diff options
author | Trond Myklebust <trond.myklebust@primarydata.com> | 2014-07-29 21:34:36 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2014-07-31 14:20:26 -0400 |
commit | d4f0489f38512027fdf5190d5d1d8007e155e88f (patch) | |
tree | d54d60e2dd6e37b3d2963e4402f790affebf19bf /fs/nfsd | |
parent | c58c6610ec248134b0b0ede2ac80859bf1cefa29 (diff) |
nfsd: Move the open owner hash table into struct nfs4_client
Preparation for removing the client_mutex.
Convert the open owner hash table into a per-client table and protect it
using the nfs4_client->cl_lock spin lock.
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd')
-rw-r--r-- | fs/nfsd/netns.h | 1 | ||||
-rw-r--r-- | fs/nfsd/nfs4state.c | 187 | ||||
-rw-r--r-- | fs/nfsd/state.h | 1 |
3 files changed, 86 insertions, 103 deletions
diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h index a71d14413d39..e1f479c162b5 100644 --- a/fs/nfsd/netns.h +++ b/fs/nfsd/netns.h | |||
@@ -63,7 +63,6 @@ struct nfsd_net { | |||
63 | struct rb_root conf_name_tree; | 63 | struct rb_root conf_name_tree; |
64 | struct list_head *unconf_id_hashtbl; | 64 | struct list_head *unconf_id_hashtbl; |
65 | struct rb_root unconf_name_tree; | 65 | struct rb_root unconf_name_tree; |
66 | struct list_head *ownerstr_hashtbl; | ||
67 | struct list_head *sessionid_hashtbl; | 66 | struct list_head *sessionid_hashtbl; |
68 | /* | 67 | /* |
69 | * client_lru holds client queue ordered by nfs4_client.cl_time | 68 | * client_lru holds client queue ordered by nfs4_client.cl_time |
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 7c15918d20f0..4af4e5eff491 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -240,35 +240,27 @@ static void nfsd4_put_session(struct nfsd4_session *ses) | |||
240 | } | 240 | } |
241 | 241 | ||
242 | static int | 242 | static int |
243 | same_owner_str(struct nfs4_stateowner *sop, struct xdr_netobj *owner, | 243 | same_owner_str(struct nfs4_stateowner *sop, struct xdr_netobj *owner) |
244 | clientid_t *clid) | ||
245 | { | 244 | { |
246 | return (sop->so_owner.len == owner->len) && | 245 | return (sop->so_owner.len == owner->len) && |
247 | 0 == memcmp(sop->so_owner.data, owner->data, owner->len) && | 246 | 0 == memcmp(sop->so_owner.data, owner->data, owner->len); |
248 | (sop->so_client->cl_clientid.cl_id == clid->cl_id); | ||
249 | } | 247 | } |
250 | 248 | ||
251 | static struct nfs4_openowner * | 249 | static struct nfs4_openowner * |
252 | find_openstateowner_str_locked(unsigned int hashval, struct nfsd4_open *open, | 250 | find_openstateowner_str_locked(unsigned int hashval, struct nfsd4_open *open, |
253 | bool sessions, struct nfsd_net *nn) | 251 | struct nfs4_client *clp) |
254 | { | 252 | { |
255 | struct nfs4_stateowner *so; | 253 | struct nfs4_stateowner *so; |
256 | struct nfs4_openowner *oo; | ||
257 | struct nfs4_client *clp; | ||
258 | 254 | ||
259 | lockdep_assert_held(&nn->client_lock); | 255 | lockdep_assert_held(&clp->cl_lock); |
260 | 256 | ||
261 | list_for_each_entry(so, &nn->ownerstr_hashtbl[hashval], so_strhash) { | 257 | list_for_each_entry(so, &clp->cl_ownerstr_hashtbl[hashval], |
258 | so_strhash) { | ||
262 | if (!so->so_is_open_owner) | 259 | if (!so->so_is_open_owner) |
263 | continue; | 260 | continue; |
264 | if (same_owner_str(so, &open->op_owner, &open->op_clientid)) { | 261 | if (same_owner_str(so, &open->op_owner)) { |
265 | oo = openowner(so); | ||
266 | clp = oo->oo_owner.so_client; | ||
267 | if ((bool)clp->cl_minorversion != sessions) | ||
268 | break; | ||
269 | renew_client_locked(clp); | ||
270 | atomic_inc(&so->so_count); | 262 | atomic_inc(&so->so_count); |
271 | return oo; | 263 | return openowner(so); |
272 | } | 264 | } |
273 | } | 265 | } |
274 | return NULL; | 266 | return NULL; |
@@ -276,17 +268,16 @@ find_openstateowner_str_locked(unsigned int hashval, struct nfsd4_open *open, | |||
276 | 268 | ||
277 | static struct nfs4_openowner * | 269 | static struct nfs4_openowner * |
278 | find_openstateowner_str(unsigned int hashval, struct nfsd4_open *open, | 270 | find_openstateowner_str(unsigned int hashval, struct nfsd4_open *open, |
279 | bool sessions, struct nfsd_net *nn) | 271 | struct nfs4_client *clp) |
280 | { | 272 | { |
281 | struct nfs4_openowner *oo; | 273 | struct nfs4_openowner *oo; |
282 | 274 | ||
283 | spin_lock(&nn->client_lock); | 275 | spin_lock(&clp->cl_lock); |
284 | oo = find_openstateowner_str_locked(hashval, open, sessions, nn); | 276 | oo = find_openstateowner_str_locked(hashval, open, clp); |
285 | spin_unlock(&nn->client_lock); | 277 | spin_unlock(&clp->cl_lock); |
286 | return oo; | 278 | return oo; |
287 | } | 279 | } |
288 | 280 | ||
289 | |||
290 | static inline u32 | 281 | static inline u32 |
291 | opaque_hashval(const void *ptr, int nbytes) | 282 | opaque_hashval(const void *ptr, int nbytes) |
292 | { | 283 | { |
@@ -408,12 +399,11 @@ unsigned long max_delegations; | |||
408 | #define OWNER_HASH_SIZE (1 << OWNER_HASH_BITS) | 399 | #define OWNER_HASH_SIZE (1 << OWNER_HASH_BITS) |
409 | #define OWNER_HASH_MASK (OWNER_HASH_SIZE - 1) | 400 | #define OWNER_HASH_MASK (OWNER_HASH_SIZE - 1) |
410 | 401 | ||
411 | static unsigned int ownerstr_hashval(u32 clientid, struct xdr_netobj *ownername) | 402 | static unsigned int ownerstr_hashval(struct xdr_netobj *ownername) |
412 | { | 403 | { |
413 | unsigned int ret; | 404 | unsigned int ret; |
414 | 405 | ||
415 | ret = opaque_hashval(ownername->data, ownername->len); | 406 | ret = opaque_hashval(ownername->data, ownername->len); |
416 | ret += clientid; | ||
417 | return ret & OWNER_HASH_MASK; | 407 | return ret & OWNER_HASH_MASK; |
418 | } | 408 | } |
419 | 409 | ||
@@ -1002,40 +992,37 @@ static void release_lock_stateid(struct nfs4_ol_stateid *stp) | |||
1002 | 992 | ||
1003 | static void unhash_lockowner_locked(struct nfs4_lockowner *lo) | 993 | static void unhash_lockowner_locked(struct nfs4_lockowner *lo) |
1004 | { | 994 | { |
1005 | struct nfsd_net *nn = net_generic(lo->lo_owner.so_client->net, | 995 | struct nfs4_client *clp = lo->lo_owner.so_client; |
1006 | nfsd_net_id); | ||
1007 | 996 | ||
1008 | lockdep_assert_held(&nn->client_lock); | 997 | lockdep_assert_held(&clp->cl_lock); |
1009 | 998 | ||
1010 | list_del_init(&lo->lo_owner.so_strhash); | 999 | list_del_init(&lo->lo_owner.so_strhash); |
1011 | } | 1000 | } |
1012 | 1001 | ||
1013 | static void release_lockowner_stateids(struct nfs4_lockowner *lo) | 1002 | static void release_lockowner_stateids(struct nfs4_lockowner *lo) |
1014 | { | 1003 | { |
1015 | struct nfsd_net *nn = net_generic(lo->lo_owner.so_client->net, | 1004 | struct nfs4_client *clp = lo->lo_owner.so_client; |
1016 | nfsd_net_id); | ||
1017 | struct nfs4_ol_stateid *stp; | 1005 | struct nfs4_ol_stateid *stp; |
1018 | 1006 | ||
1019 | lockdep_assert_held(&nn->client_lock); | 1007 | lockdep_assert_held(&clp->cl_lock); |
1020 | 1008 | ||
1021 | while (!list_empty(&lo->lo_owner.so_stateids)) { | 1009 | while (!list_empty(&lo->lo_owner.so_stateids)) { |
1022 | stp = list_first_entry(&lo->lo_owner.so_stateids, | 1010 | stp = list_first_entry(&lo->lo_owner.so_stateids, |
1023 | struct nfs4_ol_stateid, st_perstateowner); | 1011 | struct nfs4_ol_stateid, st_perstateowner); |
1024 | spin_unlock(&nn->client_lock); | 1012 | spin_unlock(&clp->cl_lock); |
1025 | release_lock_stateid(stp); | 1013 | release_lock_stateid(stp); |
1026 | spin_lock(&nn->client_lock); | 1014 | spin_lock(&clp->cl_lock); |
1027 | } | 1015 | } |
1028 | } | 1016 | } |
1029 | 1017 | ||
1030 | static void release_lockowner(struct nfs4_lockowner *lo) | 1018 | static void release_lockowner(struct nfs4_lockowner *lo) |
1031 | { | 1019 | { |
1032 | struct nfsd_net *nn = net_generic(lo->lo_owner.so_client->net, | 1020 | struct nfs4_client *clp = lo->lo_owner.so_client; |
1033 | nfsd_net_id); | ||
1034 | 1021 | ||
1035 | spin_lock(&nn->client_lock); | 1022 | spin_lock(&clp->cl_lock); |
1036 | unhash_lockowner_locked(lo); | 1023 | unhash_lockowner_locked(lo); |
1037 | release_lockowner_stateids(lo); | 1024 | release_lockowner_stateids(lo); |
1038 | spin_unlock(&nn->client_lock); | 1025 | spin_unlock(&clp->cl_lock); |
1039 | nfs4_put_stateowner(&lo->lo_owner); | 1026 | nfs4_put_stateowner(&lo->lo_owner); |
1040 | } | 1027 | } |
1041 | 1028 | ||
@@ -1070,10 +1057,9 @@ static void release_open_stateid(struct nfs4_ol_stateid *stp) | |||
1070 | 1057 | ||
1071 | static void unhash_openowner_locked(struct nfs4_openowner *oo) | 1058 | static void unhash_openowner_locked(struct nfs4_openowner *oo) |
1072 | { | 1059 | { |
1073 | struct nfsd_net *nn = net_generic(oo->oo_owner.so_client->net, | 1060 | struct nfs4_client *clp = oo->oo_owner.so_client; |
1074 | nfsd_net_id); | ||
1075 | 1061 | ||
1076 | lockdep_assert_held(&nn->client_lock); | 1062 | lockdep_assert_held(&clp->cl_lock); |
1077 | 1063 | ||
1078 | list_del_init(&oo->oo_owner.so_strhash); | 1064 | list_del_init(&oo->oo_owner.so_strhash); |
1079 | list_del_init(&oo->oo_perclient); | 1065 | list_del_init(&oo->oo_perclient); |
@@ -1093,29 +1079,27 @@ static void release_last_closed_stateid(struct nfs4_openowner *oo) | |||
1093 | static void release_openowner_stateids(struct nfs4_openowner *oo) | 1079 | static void release_openowner_stateids(struct nfs4_openowner *oo) |
1094 | { | 1080 | { |
1095 | struct nfs4_ol_stateid *stp; | 1081 | struct nfs4_ol_stateid *stp; |
1096 | struct nfsd_net *nn = net_generic(oo->oo_owner.so_client->net, | 1082 | struct nfs4_client *clp = oo->oo_owner.so_client; |
1097 | nfsd_net_id); | ||
1098 | 1083 | ||
1099 | lockdep_assert_held(&nn->client_lock); | 1084 | lockdep_assert_held(&clp->cl_lock); |
1100 | 1085 | ||
1101 | while (!list_empty(&oo->oo_owner.so_stateids)) { | 1086 | while (!list_empty(&oo->oo_owner.so_stateids)) { |
1102 | stp = list_first_entry(&oo->oo_owner.so_stateids, | 1087 | stp = list_first_entry(&oo->oo_owner.so_stateids, |
1103 | struct nfs4_ol_stateid, st_perstateowner); | 1088 | struct nfs4_ol_stateid, st_perstateowner); |
1104 | spin_unlock(&nn->client_lock); | 1089 | spin_unlock(&clp->cl_lock); |
1105 | release_open_stateid(stp); | 1090 | release_open_stateid(stp); |
1106 | spin_lock(&nn->client_lock); | 1091 | spin_lock(&clp->cl_lock); |
1107 | } | 1092 | } |
1108 | } | 1093 | } |
1109 | 1094 | ||
1110 | static void release_openowner(struct nfs4_openowner *oo) | 1095 | static void release_openowner(struct nfs4_openowner *oo) |
1111 | { | 1096 | { |
1112 | struct nfsd_net *nn = net_generic(oo->oo_owner.so_client->net, | 1097 | struct nfs4_client *clp = oo->oo_owner.so_client; |
1113 | nfsd_net_id); | ||
1114 | 1098 | ||
1115 | spin_lock(&nn->client_lock); | 1099 | spin_lock(&clp->cl_lock); |
1116 | unhash_openowner_locked(oo); | 1100 | unhash_openowner_locked(oo); |
1117 | release_openowner_stateids(oo); | 1101 | release_openowner_stateids(oo); |
1118 | spin_unlock(&nn->client_lock); | 1102 | spin_unlock(&clp->cl_lock); |
1119 | release_last_closed_stateid(oo); | 1103 | release_last_closed_stateid(oo); |
1120 | nfs4_put_stateowner(&oo->oo_owner); | 1104 | nfs4_put_stateowner(&oo->oo_owner); |
1121 | } | 1105 | } |
@@ -1497,15 +1481,20 @@ STALE_CLIENTID(clientid_t *clid, struct nfsd_net *nn) | |||
1497 | static struct nfs4_client *alloc_client(struct xdr_netobj name) | 1481 | static struct nfs4_client *alloc_client(struct xdr_netobj name) |
1498 | { | 1482 | { |
1499 | struct nfs4_client *clp; | 1483 | struct nfs4_client *clp; |
1484 | int i; | ||
1500 | 1485 | ||
1501 | clp = kzalloc(sizeof(struct nfs4_client), GFP_KERNEL); | 1486 | clp = kzalloc(sizeof(struct nfs4_client), GFP_KERNEL); |
1502 | if (clp == NULL) | 1487 | if (clp == NULL) |
1503 | return NULL; | 1488 | return NULL; |
1504 | clp->cl_name.data = kmemdup(name.data, name.len, GFP_KERNEL); | 1489 | clp->cl_name.data = kmemdup(name.data, name.len, GFP_KERNEL); |
1505 | if (clp->cl_name.data == NULL) { | 1490 | if (clp->cl_name.data == NULL) |
1506 | kfree(clp); | 1491 | goto err_no_name; |
1507 | return NULL; | 1492 | clp->cl_ownerstr_hashtbl = kmalloc(sizeof(struct list_head) * |
1508 | } | 1493 | OWNER_HASH_SIZE, GFP_KERNEL); |
1494 | if (!clp->cl_ownerstr_hashtbl) | ||
1495 | goto err_no_hashtbl; | ||
1496 | for (i = 0; i < OWNER_HASH_SIZE; i++) | ||
1497 | INIT_LIST_HEAD(&clp->cl_ownerstr_hashtbl[i]); | ||
1509 | clp->cl_name.len = name.len; | 1498 | clp->cl_name.len = name.len; |
1510 | INIT_LIST_HEAD(&clp->cl_sessions); | 1499 | INIT_LIST_HEAD(&clp->cl_sessions); |
1511 | idr_init(&clp->cl_stateids); | 1500 | idr_init(&clp->cl_stateids); |
@@ -1520,6 +1509,11 @@ static struct nfs4_client *alloc_client(struct xdr_netobj name) | |||
1520 | spin_lock_init(&clp->cl_lock); | 1509 | spin_lock_init(&clp->cl_lock); |
1521 | rpc_init_wait_queue(&clp->cl_cb_waitq, "Backchannel slot table"); | 1510 | rpc_init_wait_queue(&clp->cl_cb_waitq, "Backchannel slot table"); |
1522 | return clp; | 1511 | return clp; |
1512 | err_no_hashtbl: | ||
1513 | kfree(clp->cl_name.data); | ||
1514 | err_no_name: | ||
1515 | kfree(clp); | ||
1516 | return NULL; | ||
1523 | } | 1517 | } |
1524 | 1518 | ||
1525 | static void | 1519 | static void |
@@ -1538,6 +1532,7 @@ free_client(struct nfs4_client *clp) | |||
1538 | } | 1532 | } |
1539 | rpc_destroy_wait_queue(&clp->cl_cb_waitq); | 1533 | rpc_destroy_wait_queue(&clp->cl_cb_waitq); |
1540 | free_svc_cred(&clp->cl_cred); | 1534 | free_svc_cred(&clp->cl_cred); |
1535 | kfree(clp->cl_ownerstr_hashtbl); | ||
1541 | kfree(clp->cl_name.data); | 1536 | kfree(clp->cl_name.data); |
1542 | idr_destroy(&clp->cl_stateids); | 1537 | idr_destroy(&clp->cl_stateids); |
1543 | kfree(clp); | 1538 | kfree(clp); |
@@ -3074,20 +3069,20 @@ static inline void *alloc_stateowner(struct kmem_cache *slab, struct xdr_netobj | |||
3074 | 3069 | ||
3075 | static void hash_openowner(struct nfs4_openowner *oo, struct nfs4_client *clp, unsigned int strhashval) | 3070 | static void hash_openowner(struct nfs4_openowner *oo, struct nfs4_client *clp, unsigned int strhashval) |
3076 | { | 3071 | { |
3077 | struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); | 3072 | lockdep_assert_held(&clp->cl_lock); |
3078 | 3073 | ||
3079 | list_add(&oo->oo_owner.so_strhash, &nn->ownerstr_hashtbl[strhashval]); | 3074 | list_add(&oo->oo_owner.so_strhash, |
3075 | &clp->cl_ownerstr_hashtbl[strhashval]); | ||
3080 | list_add(&oo->oo_perclient, &clp->cl_openowners); | 3076 | list_add(&oo->oo_perclient, &clp->cl_openowners); |
3081 | } | 3077 | } |
3082 | 3078 | ||
3083 | static void nfs4_unhash_openowner(struct nfs4_stateowner *so) | 3079 | static void nfs4_unhash_openowner(struct nfs4_stateowner *so) |
3084 | { | 3080 | { |
3085 | struct nfs4_openowner *oo = openowner(so); | 3081 | struct nfs4_client *clp = so->so_client; |
3086 | struct nfsd_net *nn = net_generic(so->so_client->net, nfsd_net_id); | ||
3087 | 3082 | ||
3088 | spin_lock(&nn->client_lock); | 3083 | spin_lock(&clp->cl_lock); |
3089 | unhash_openowner_locked(oo); | 3084 | unhash_openowner_locked(openowner(so)); |
3090 | spin_unlock(&nn->client_lock); | 3085 | spin_unlock(&clp->cl_lock); |
3091 | } | 3086 | } |
3092 | 3087 | ||
3093 | static void nfs4_free_openowner(struct nfs4_stateowner *so) | 3088 | static void nfs4_free_openowner(struct nfs4_stateowner *so) |
@@ -3107,7 +3102,6 @@ alloc_init_open_stateowner(unsigned int strhashval, struct nfsd4_open *open, | |||
3107 | struct nfsd4_compound_state *cstate) | 3102 | struct nfsd4_compound_state *cstate) |
3108 | { | 3103 | { |
3109 | struct nfs4_client *clp = cstate->clp; | 3104 | struct nfs4_client *clp = cstate->clp; |
3110 | struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); | ||
3111 | struct nfs4_openowner *oo, *ret; | 3105 | struct nfs4_openowner *oo, *ret; |
3112 | 3106 | ||
3113 | oo = alloc_stateowner(openowner_slab, &open->op_owner, clp); | 3107 | oo = alloc_stateowner(openowner_slab, &open->op_owner, clp); |
@@ -3122,15 +3116,14 @@ alloc_init_open_stateowner(unsigned int strhashval, struct nfsd4_open *open, | |||
3122 | oo->oo_time = 0; | 3116 | oo->oo_time = 0; |
3123 | oo->oo_last_closed_stid = NULL; | 3117 | oo->oo_last_closed_stid = NULL; |
3124 | INIT_LIST_HEAD(&oo->oo_close_lru); | 3118 | INIT_LIST_HEAD(&oo->oo_close_lru); |
3125 | spin_lock(&nn->client_lock); | 3119 | spin_lock(&clp->cl_lock); |
3126 | ret = find_openstateowner_str_locked(strhashval, | 3120 | ret = find_openstateowner_str_locked(strhashval, open, clp); |
3127 | open, clp->cl_minorversion, nn); | ||
3128 | if (ret == NULL) { | 3121 | if (ret == NULL) { |
3129 | hash_openowner(oo, clp, strhashval); | 3122 | hash_openowner(oo, clp, strhashval); |
3130 | ret = oo; | 3123 | ret = oo; |
3131 | } else | 3124 | } else |
3132 | nfs4_free_openowner(&oo->oo_owner); | 3125 | nfs4_free_openowner(&oo->oo_owner); |
3133 | spin_unlock(&nn->client_lock); | 3126 | spin_unlock(&clp->cl_lock); |
3134 | return oo; | 3127 | return oo; |
3135 | } | 3128 | } |
3136 | 3129 | ||
@@ -3412,8 +3405,8 @@ nfsd4_process_open1(struct nfsd4_compound_state *cstate, | |||
3412 | return status; | 3405 | return status; |
3413 | clp = cstate->clp; | 3406 | clp = cstate->clp; |
3414 | 3407 | ||
3415 | strhashval = ownerstr_hashval(clientid->cl_id, &open->op_owner); | 3408 | strhashval = ownerstr_hashval(&open->op_owner); |
3416 | oo = find_openstateowner_str(strhashval, open, cstate->minorversion, nn); | 3409 | oo = find_openstateowner_str(strhashval, open, clp); |
3417 | open->op_openowner = oo; | 3410 | open->op_openowner = oo; |
3418 | if (!oo) { | 3411 | if (!oo) { |
3419 | goto new_owner; | 3412 | goto new_owner; |
@@ -4818,15 +4811,16 @@ nevermind: | |||
4818 | 4811 | ||
4819 | static struct nfs4_lockowner * | 4812 | static struct nfs4_lockowner * |
4820 | find_lockowner_str_locked(clientid_t *clid, struct xdr_netobj *owner, | 4813 | find_lockowner_str_locked(clientid_t *clid, struct xdr_netobj *owner, |
4821 | struct nfsd_net *nn) | 4814 | struct nfs4_client *clp) |
4822 | { | 4815 | { |
4823 | unsigned int strhashval = ownerstr_hashval(clid->cl_id, owner); | 4816 | unsigned int strhashval = ownerstr_hashval(owner); |
4824 | struct nfs4_stateowner *so; | 4817 | struct nfs4_stateowner *so; |
4825 | 4818 | ||
4826 | list_for_each_entry(so, &nn->ownerstr_hashtbl[strhashval], so_strhash) { | 4819 | list_for_each_entry(so, &clp->cl_ownerstr_hashtbl[strhashval], |
4820 | so_strhash) { | ||
4827 | if (so->so_is_open_owner) | 4821 | if (so->so_is_open_owner) |
4828 | continue; | 4822 | continue; |
4829 | if (!same_owner_str(so, owner, clid)) | 4823 | if (!same_owner_str(so, owner)) |
4830 | continue; | 4824 | continue; |
4831 | atomic_inc(&so->so_count); | 4825 | atomic_inc(&so->so_count); |
4832 | return lockowner(so); | 4826 | return lockowner(so); |
@@ -4836,23 +4830,23 @@ find_lockowner_str_locked(clientid_t *clid, struct xdr_netobj *owner, | |||
4836 | 4830 | ||
4837 | static struct nfs4_lockowner * | 4831 | static struct nfs4_lockowner * |
4838 | find_lockowner_str(clientid_t *clid, struct xdr_netobj *owner, | 4832 | find_lockowner_str(clientid_t *clid, struct xdr_netobj *owner, |
4839 | struct nfsd_net *nn) | 4833 | struct nfs4_client *clp) |
4840 | { | 4834 | { |
4841 | struct nfs4_lockowner *lo; | 4835 | struct nfs4_lockowner *lo; |
4842 | 4836 | ||
4843 | spin_lock(&nn->client_lock); | 4837 | spin_lock(&clp->cl_lock); |
4844 | lo = find_lockowner_str_locked(clid, owner, nn); | 4838 | lo = find_lockowner_str_locked(clid, owner, clp); |
4845 | spin_unlock(&nn->client_lock); | 4839 | spin_unlock(&clp->cl_lock); |
4846 | return lo; | 4840 | return lo; |
4847 | } | 4841 | } |
4848 | 4842 | ||
4849 | static void nfs4_unhash_lockowner(struct nfs4_stateowner *sop) | 4843 | static void nfs4_unhash_lockowner(struct nfs4_stateowner *sop) |
4850 | { | 4844 | { |
4851 | struct nfsd_net *nn = net_generic(sop->so_client->net, nfsd_net_id); | 4845 | struct nfs4_client *clp = sop->so_client; |
4852 | 4846 | ||
4853 | spin_lock(&nn->client_lock); | 4847 | spin_lock(&clp->cl_lock); |
4854 | unhash_lockowner_locked(lockowner(sop)); | 4848 | unhash_lockowner_locked(lockowner(sop)); |
4855 | spin_unlock(&nn->client_lock); | 4849 | spin_unlock(&clp->cl_lock); |
4856 | } | 4850 | } |
4857 | 4851 | ||
4858 | static void nfs4_free_lockowner(struct nfs4_stateowner *sop) | 4852 | static void nfs4_free_lockowner(struct nfs4_stateowner *sop) |
@@ -4879,7 +4873,6 @@ alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp, | |||
4879 | struct nfs4_ol_stateid *open_stp, | 4873 | struct nfs4_ol_stateid *open_stp, |
4880 | struct nfsd4_lock *lock) | 4874 | struct nfsd4_lock *lock) |
4881 | { | 4875 | { |
4882 | struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); | ||
4883 | struct nfs4_lockowner *lo, *ret; | 4876 | struct nfs4_lockowner *lo, *ret; |
4884 | 4877 | ||
4885 | lo = alloc_stateowner(lockowner_slab, &lock->lk_new_owner, clp); | 4878 | lo = alloc_stateowner(lockowner_slab, &lock->lk_new_owner, clp); |
@@ -4889,16 +4882,16 @@ alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp, | |||
4889 | lo->lo_owner.so_is_open_owner = 0; | 4882 | lo->lo_owner.so_is_open_owner = 0; |
4890 | lo->lo_owner.so_seqid = lock->lk_new_lock_seqid; | 4883 | lo->lo_owner.so_seqid = lock->lk_new_lock_seqid; |
4891 | lo->lo_owner.so_ops = &lockowner_ops; | 4884 | lo->lo_owner.so_ops = &lockowner_ops; |
4892 | spin_lock(&nn->client_lock); | 4885 | spin_lock(&clp->cl_lock); |
4893 | ret = find_lockowner_str_locked(&clp->cl_clientid, | 4886 | ret = find_lockowner_str_locked(&clp->cl_clientid, |
4894 | &lock->lk_new_owner, nn); | 4887 | &lock->lk_new_owner, clp); |
4895 | if (ret == NULL) { | 4888 | if (ret == NULL) { |
4896 | list_add(&lo->lo_owner.so_strhash, | 4889 | list_add(&lo->lo_owner.so_strhash, |
4897 | &nn->ownerstr_hashtbl[strhashval]); | 4890 | &clp->cl_ownerstr_hashtbl[strhashval]); |
4898 | ret = lo; | 4891 | ret = lo; |
4899 | } else | 4892 | } else |
4900 | nfs4_free_lockowner(&lo->lo_owner); | 4893 | nfs4_free_lockowner(&lo->lo_owner); |
4901 | spin_unlock(&nn->client_lock); | 4894 | spin_unlock(&clp->cl_lock); |
4902 | return lo; | 4895 | return lo; |
4903 | } | 4896 | } |
4904 | 4897 | ||
@@ -5010,12 +5003,10 @@ lookup_or_create_lock_state(struct nfsd4_compound_state *cstate, | |||
5010 | struct inode *inode = cstate->current_fh.fh_dentry->d_inode; | 5003 | struct inode *inode = cstate->current_fh.fh_dentry->d_inode; |
5011 | struct nfs4_lockowner *lo; | 5004 | struct nfs4_lockowner *lo; |
5012 | unsigned int strhashval; | 5005 | unsigned int strhashval; |
5013 | struct nfsd_net *nn = net_generic(cl->net, nfsd_net_id); | ||
5014 | 5006 | ||
5015 | lo = find_lockowner_str(&cl->cl_clientid, &lock->v.new.owner, nn); | 5007 | lo = find_lockowner_str(&cl->cl_clientid, &lock->v.new.owner, cl); |
5016 | if (!lo) { | 5008 | if (!lo) { |
5017 | strhashval = ownerstr_hashval(cl->cl_clientid.cl_id, | 5009 | strhashval = ownerstr_hashval(&lock->v.new.owner); |
5018 | &lock->v.new.owner); | ||
5019 | lo = alloc_init_lock_stateowner(strhashval, cl, ost, lock); | 5010 | lo = alloc_init_lock_stateowner(strhashval, cl, ost, lock); |
5020 | if (lo == NULL) | 5011 | if (lo == NULL) |
5021 | return nfserr_jukebox; | 5012 | return nfserr_jukebox; |
@@ -5293,7 +5284,8 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
5293 | goto out; | 5284 | goto out; |
5294 | } | 5285 | } |
5295 | 5286 | ||
5296 | lo = find_lockowner_str(&lockt->lt_clientid, &lockt->lt_owner, nn); | 5287 | lo = find_lockowner_str(&lockt->lt_clientid, &lockt->lt_owner, |
5288 | cstate->clp); | ||
5297 | if (lo) | 5289 | if (lo) |
5298 | file_lock->fl_owner = (fl_owner_t)lo; | 5290 | file_lock->fl_owner = (fl_owner_t)lo; |
5299 | file_lock->fl_pid = current->tgid; | 5291 | file_lock->fl_pid = current->tgid; |
@@ -5436,7 +5428,7 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp, | |||
5436 | struct nfs4_lockowner *lo; | 5428 | struct nfs4_lockowner *lo; |
5437 | struct nfs4_ol_stateid *stp; | 5429 | struct nfs4_ol_stateid *stp; |
5438 | struct xdr_netobj *owner = &rlockowner->rl_owner; | 5430 | struct xdr_netobj *owner = &rlockowner->rl_owner; |
5439 | unsigned int hashval = ownerstr_hashval(clid->cl_id, owner); | 5431 | unsigned int hashval = ownerstr_hashval(owner); |
5440 | __be32 status; | 5432 | __be32 status; |
5441 | struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); | 5433 | struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); |
5442 | struct nfs4_client *clp; | 5434 | struct nfs4_client *clp; |
@@ -5452,29 +5444,29 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp, | |||
5452 | 5444 | ||
5453 | status = nfserr_locks_held; | 5445 | status = nfserr_locks_held; |
5454 | 5446 | ||
5447 | clp = cstate->clp; | ||
5455 | /* Find the matching lock stateowner */ | 5448 | /* Find the matching lock stateowner */ |
5456 | spin_lock(&nn->client_lock); | 5449 | spin_lock(&clp->cl_lock); |
5457 | list_for_each_entry(tmp, &nn->ownerstr_hashtbl[hashval], so_strhash) { | 5450 | list_for_each_entry(tmp, &clp->cl_ownerstr_hashtbl[hashval], |
5451 | so_strhash) { | ||
5458 | if (tmp->so_is_open_owner) | 5452 | if (tmp->so_is_open_owner) |
5459 | continue; | 5453 | continue; |
5460 | if (same_owner_str(tmp, owner, clid)) { | 5454 | if (same_owner_str(tmp, owner)) { |
5461 | sop = tmp; | 5455 | sop = tmp; |
5462 | atomic_inc(&sop->so_count); | 5456 | atomic_inc(&sop->so_count); |
5463 | break; | 5457 | break; |
5464 | } | 5458 | } |
5465 | } | 5459 | } |
5466 | spin_unlock(&nn->client_lock); | ||
5467 | 5460 | ||
5468 | /* No matching owner found, maybe a replay? Just declare victory... */ | 5461 | /* No matching owner found, maybe a replay? Just declare victory... */ |
5469 | if (!sop) { | 5462 | if (!sop) { |
5463 | spin_unlock(&clp->cl_lock); | ||
5470 | status = nfs_ok; | 5464 | status = nfs_ok; |
5471 | goto out; | 5465 | goto out; |
5472 | } | 5466 | } |
5473 | 5467 | ||
5474 | lo = lockowner(sop); | 5468 | lo = lockowner(sop); |
5475 | /* see if there are still any locks associated with it */ | 5469 | /* see if there are still any locks associated with it */ |
5476 | clp = cstate->clp; | ||
5477 | spin_lock(&clp->cl_lock); | ||
5478 | list_for_each_entry(stp, &sop->so_stateids, st_perstateowner) { | 5470 | list_for_each_entry(stp, &sop->so_stateids, st_perstateowner) { |
5479 | if (check_for_locks(stp->st_stid.sc_file, lo)) { | 5471 | if (check_for_locks(stp->st_stid.sc_file, lo)) { |
5480 | spin_unlock(&clp->cl_lock); | 5472 | spin_unlock(&clp->cl_lock); |
@@ -5829,10 +5821,6 @@ static int nfs4_state_create_net(struct net *net) | |||
5829 | CLIENT_HASH_SIZE, GFP_KERNEL); | 5821 | CLIENT_HASH_SIZE, GFP_KERNEL); |
5830 | if (!nn->unconf_id_hashtbl) | 5822 | if (!nn->unconf_id_hashtbl) |
5831 | goto err_unconf_id; | 5823 | goto err_unconf_id; |
5832 | nn->ownerstr_hashtbl = kmalloc(sizeof(struct list_head) * | ||
5833 | OWNER_HASH_SIZE, GFP_KERNEL); | ||
5834 | if (!nn->ownerstr_hashtbl) | ||
5835 | goto err_ownerstr; | ||
5836 | nn->sessionid_hashtbl = kmalloc(sizeof(struct list_head) * | 5824 | nn->sessionid_hashtbl = kmalloc(sizeof(struct list_head) * |
5837 | SESSION_HASH_SIZE, GFP_KERNEL); | 5825 | SESSION_HASH_SIZE, GFP_KERNEL); |
5838 | if (!nn->sessionid_hashtbl) | 5826 | if (!nn->sessionid_hashtbl) |
@@ -5842,8 +5830,6 @@ static int nfs4_state_create_net(struct net *net) | |||
5842 | INIT_LIST_HEAD(&nn->conf_id_hashtbl[i]); | 5830 | INIT_LIST_HEAD(&nn->conf_id_hashtbl[i]); |
5843 | INIT_LIST_HEAD(&nn->unconf_id_hashtbl[i]); | 5831 | INIT_LIST_HEAD(&nn->unconf_id_hashtbl[i]); |
5844 | } | 5832 | } |
5845 | for (i = 0; i < OWNER_HASH_SIZE; i++) | ||
5846 | INIT_LIST_HEAD(&nn->ownerstr_hashtbl[i]); | ||
5847 | for (i = 0; i < SESSION_HASH_SIZE; i++) | 5833 | for (i = 0; i < SESSION_HASH_SIZE; i++) |
5848 | INIT_LIST_HEAD(&nn->sessionid_hashtbl[i]); | 5834 | INIT_LIST_HEAD(&nn->sessionid_hashtbl[i]); |
5849 | nn->conf_name_tree = RB_ROOT; | 5835 | nn->conf_name_tree = RB_ROOT; |
@@ -5859,8 +5845,6 @@ static int nfs4_state_create_net(struct net *net) | |||
5859 | return 0; | 5845 | return 0; |
5860 | 5846 | ||
5861 | err_sessionid: | 5847 | err_sessionid: |
5862 | kfree(nn->ownerstr_hashtbl); | ||
5863 | err_ownerstr: | ||
5864 | kfree(nn->unconf_id_hashtbl); | 5848 | kfree(nn->unconf_id_hashtbl); |
5865 | err_unconf_id: | 5849 | err_unconf_id: |
5866 | kfree(nn->conf_id_hashtbl); | 5850 | kfree(nn->conf_id_hashtbl); |
@@ -5890,7 +5874,6 @@ nfs4_state_destroy_net(struct net *net) | |||
5890 | } | 5874 | } |
5891 | 5875 | ||
5892 | kfree(nn->sessionid_hashtbl); | 5876 | kfree(nn->sessionid_hashtbl); |
5893 | kfree(nn->ownerstr_hashtbl); | ||
5894 | kfree(nn->unconf_id_hashtbl); | 5877 | kfree(nn->unconf_id_hashtbl); |
5895 | kfree(nn->conf_id_hashtbl); | 5878 | kfree(nn->conf_id_hashtbl); |
5896 | put_net(net); | 5879 | put_net(net); |
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index e073c86f389c..73a209dc352b 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h | |||
@@ -235,6 +235,7 @@ struct nfsd4_sessionid { | |||
235 | struct nfs4_client { | 235 | struct nfs4_client { |
236 | struct list_head cl_idhash; /* hash by cl_clientid.id */ | 236 | struct list_head cl_idhash; /* hash by cl_clientid.id */ |
237 | struct rb_node cl_namenode; /* link into by-name trees */ | 237 | struct rb_node cl_namenode; /* link into by-name trees */ |
238 | struct list_head *cl_ownerstr_hashtbl; | ||
238 | struct list_head cl_openowners; | 239 | struct list_head cl_openowners; |
239 | struct idr cl_stateids; /* stateid lookup */ | 240 | struct idr cl_stateids; /* stateid lookup */ |
240 | struct list_head cl_delegations; | 241 | struct list_head cl_delegations; |