aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2012-01-17 22:04:25 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-01-31 18:20:28 -0500
commitd2d7ce28a2f8ec6ca2a49145e643d2e3c7d21ba3 (patch)
tree4c73f071c2282185402a4da7d20b30749530c89f
parent9157c31dd610a127bc6f01bc1953cf8b80382040 (diff)
NFSv4: Replace lock_owner->ld_id with an ida based allocator
Again, We're unlikely to ever need more than 2^31 simultaneous lock owners, so let's replace the custom allocator. Now that there are no more users, we can also get rid of the custom allocator code. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/client.c2
-rw-r--r--fs/nfs/nfs4_fs.h7
-rw-r--r--fs/nfs/nfs4proc.c6
-rw-r--r--fs/nfs/nfs4state.c74
-rw-r--r--include/linux/nfs_fs_sb.h2
5 files changed, 15 insertions, 76 deletions
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 8d1739d3424d..df60d9971b95 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -1093,6 +1093,7 @@ static struct nfs_server *nfs_alloc_server(void)
1093 } 1093 }
1094 1094
1095 ida_init(&server->openowner_id); 1095 ida_init(&server->openowner_id);
1096 ida_init(&server->lockowner_id);
1096 pnfs_init_server(server); 1097 pnfs_init_server(server);
1097 1098
1098 return server; 1099 return server;
@@ -1118,6 +1119,7 @@ void nfs_free_server(struct nfs_server *server)
1118 1119
1119 nfs_put_client(server->nfs_client); 1120 nfs_put_client(server->nfs_client);
1120 1121
1122 ida_destroy(&server->lockowner_id);
1121 ida_destroy(&server->openowner_id); 1123 ida_destroy(&server->openowner_id);
1122 nfs_free_iostats(server->io_stats); 1124 nfs_free_iostats(server->io_stats);
1123 bdi_destroy(&server->backing_dev_info); 1125 bdi_destroy(&server->backing_dev_info);
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 091b679747ed..b23cb0cda632 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -81,11 +81,6 @@ static inline void nfs_confirm_seqid(struct nfs_seqid_counter *seqid, int status
81 seqid->flags |= NFS_SEQID_CONFIRMED; 81 seqid->flags |= NFS_SEQID_CONFIRMED;
82} 82}
83 83
84struct nfs_unique_id {
85 struct rb_node rb_node;
86 __u64 id;
87};
88
89/* 84/*
90 * NFS4 state_owners and lock_owners are simply labels for ordered 85 * NFS4 state_owners and lock_owners are simply labels for ordered
91 * sequences of RPC calls. Their sole purpose is to provide once-only 86 * sequences of RPC calls. Their sole purpose is to provide once-only
@@ -145,9 +140,9 @@ struct nfs4_lock_state {
145 struct nfs4_state * ls_state; /* Pointer to open state */ 140 struct nfs4_state * ls_state; /* Pointer to open state */
146#define NFS_LOCK_INITIALIZED 1 141#define NFS_LOCK_INITIALIZED 1
147 int ls_flags; 142 int ls_flags;
143 int ls_id;
148 struct nfs_seqid_counter ls_seqid; 144 struct nfs_seqid_counter ls_seqid;
149 struct rpc_sequence ls_sequence; 145 struct rpc_sequence ls_sequence;
150 struct nfs_unique_id ls_id;
151 nfs4_stateid ls_stateid; 146 nfs4_stateid ls_stateid;
152 atomic_t ls_count; 147 atomic_t ls_count;
153 struct nfs4_lock_owner ls_owner; 148 struct nfs4_lock_owner ls_owner;
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 1dd2e407a901..9c77af900960 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -4017,7 +4017,7 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock
4017 if (status != 0) 4017 if (status != 0)
4018 goto out; 4018 goto out;
4019 lsp = request->fl_u.nfs4_fl.owner; 4019 lsp = request->fl_u.nfs4_fl.owner;
4020 arg.lock_owner.id = lsp->ls_id.id; 4020 arg.lock_owner.id = lsp->ls_id;
4021 arg.lock_owner.s_dev = server->s_dev; 4021 arg.lock_owner.s_dev = server->s_dev;
4022 status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); 4022 status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1);
4023 switch (status) { 4023 switch (status) {
@@ -4262,7 +4262,7 @@ static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl,
4262 goto out_free_seqid; 4262 goto out_free_seqid;
4263 p->arg.lock_stateid = &lsp->ls_stateid; 4263 p->arg.lock_stateid = &lsp->ls_stateid;
4264 p->arg.lock_owner.clientid = server->nfs_client->cl_clientid; 4264 p->arg.lock_owner.clientid = server->nfs_client->cl_clientid;
4265 p->arg.lock_owner.id = lsp->ls_id.id; 4265 p->arg.lock_owner.id = lsp->ls_id;
4266 p->arg.lock_owner.s_dev = server->s_dev; 4266 p->arg.lock_owner.s_dev = server->s_dev;
4267 p->res.lock_seqid = p->arg.lock_seqid; 4267 p->res.lock_seqid = p->arg.lock_seqid;
4268 p->lsp = lsp; 4268 p->lsp = lsp;
@@ -4679,7 +4679,7 @@ void nfs4_release_lockowner(const struct nfs4_lock_state *lsp)
4679 if (!args) 4679 if (!args)
4680 return; 4680 return;
4681 args->lock_owner.clientid = server->nfs_client->cl_clientid; 4681 args->lock_owner.clientid = server->nfs_client->cl_clientid;
4682 args->lock_owner.id = lsp->ls_id.id; 4682 args->lock_owner.id = lsp->ls_id;
4683 args->lock_owner.s_dev = server->s_dev; 4683 args->lock_owner.s_dev = server->s_dev;
4684 msg.rpc_argp = args; 4684 msg.rpc_argp = args;
4685 rpc_call_async(server->client, &msg, 0, &nfs4_release_lockowner_ops, args); 4685 rpc_call_async(server->client, &msg, 0, &nfs4_release_lockowner_ops, args);
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 8472707286f9..5abf23615bc5 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -317,62 +317,6 @@ out:
317 return cred; 317 return cred;
318} 318}
319 319
320static void nfs_alloc_unique_id_locked(struct rb_root *root,
321 struct nfs_unique_id *new,
322 __u64 minval, int maxbits)
323{
324 struct rb_node **p, *parent;
325 struct nfs_unique_id *pos;
326 __u64 mask = ~0ULL;
327
328 if (maxbits < 64)
329 mask = (1ULL << maxbits) - 1ULL;
330
331 /* Ensure distribution is more or less flat */
332 get_random_bytes(&new->id, sizeof(new->id));
333 new->id &= mask;
334 if (new->id < minval)
335 new->id += minval;
336retry:
337 p = &root->rb_node;
338 parent = NULL;
339
340 while (*p != NULL) {
341 parent = *p;
342 pos = rb_entry(parent, struct nfs_unique_id, rb_node);
343
344 if (new->id < pos->id)
345 p = &(*p)->rb_left;
346 else if (new->id > pos->id)
347 p = &(*p)->rb_right;
348 else
349 goto id_exists;
350 }
351 rb_link_node(&new->rb_node, parent, p);
352 rb_insert_color(&new->rb_node, root);
353 return;
354id_exists:
355 for (;;) {
356 new->id++;
357 if (new->id < minval || (new->id & mask) != new->id) {
358 new->id = minval;
359 break;
360 }
361 parent = rb_next(parent);
362 if (parent == NULL)
363 break;
364 pos = rb_entry(parent, struct nfs_unique_id, rb_node);
365 if (new->id < pos->id)
366 break;
367 }
368 goto retry;
369}
370
371static void nfs_free_unique_id(struct rb_root *root, struct nfs_unique_id *id)
372{
373 rb_erase(&id->rb_node, root);
374}
375
376static struct nfs4_state_owner * 320static struct nfs4_state_owner *
377nfs4_find_state_owner_locked(struct nfs_server *server, struct rpc_cred *cred) 321nfs4_find_state_owner_locked(struct nfs_server *server, struct rpc_cred *cred)
378{ 322{
@@ -800,7 +744,6 @@ static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, f
800{ 744{
801 struct nfs4_lock_state *lsp; 745 struct nfs4_lock_state *lsp;
802 struct nfs_server *server = state->owner->so_server; 746 struct nfs_server *server = state->owner->so_server;
803 struct nfs_client *clp = server->nfs_client;
804 747
805 lsp = kzalloc(sizeof(*lsp), GFP_NOFS); 748 lsp = kzalloc(sizeof(*lsp), GFP_NOFS);
806 if (lsp == NULL) 749 if (lsp == NULL)
@@ -820,24 +763,23 @@ static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, f
820 lsp->ls_owner.lo_u.posix_owner = fl_owner; 763 lsp->ls_owner.lo_u.posix_owner = fl_owner;
821 break; 764 break;
822 default: 765 default:
823 kfree(lsp); 766 goto out_free;
824 return NULL;
825 } 767 }
826 spin_lock(&clp->cl_lock); 768 lsp->ls_id = ida_simple_get(&server->lockowner_id, 0, 0, GFP_NOFS);
827 nfs_alloc_unique_id_locked(&server->lockowner_id, &lsp->ls_id, 1, 64); 769 if (lsp->ls_id < 0)
828 spin_unlock(&clp->cl_lock); 770 goto out_free;
829 INIT_LIST_HEAD(&lsp->ls_locks); 771 INIT_LIST_HEAD(&lsp->ls_locks);
830 return lsp; 772 return lsp;
773out_free:
774 kfree(lsp);
775 return NULL;
831} 776}
832 777
833static void nfs4_free_lock_state(struct nfs4_lock_state *lsp) 778static void nfs4_free_lock_state(struct nfs4_lock_state *lsp)
834{ 779{
835 struct nfs_server *server = lsp->ls_state->owner->so_server; 780 struct nfs_server *server = lsp->ls_state->owner->so_server;
836 struct nfs_client *clp = server->nfs_client;
837 781
838 spin_lock(&clp->cl_lock); 782 ida_simple_remove(&server->lockowner_id, lsp->ls_id);
839 nfs_free_unique_id(&server->lockowner_id, &lsp->ls_id);
840 spin_unlock(&clp->cl_lock);
841 rpc_destroy_wait_queue(&lsp->ls_sequence.wait); 783 rpc_destroy_wait_queue(&lsp->ls_sequence.wait);
842 kfree(lsp); 784 kfree(lsp);
843} 785}
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index 645537e18bd0..c23469308b8e 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -152,9 +152,9 @@ struct nfs_server {
152 152
153 /* the following fields are protected by nfs_client->cl_lock */ 153 /* the following fields are protected by nfs_client->cl_lock */
154 struct rb_root state_owners; 154 struct rb_root state_owners;
155 struct rb_root lockowner_id;
156#endif 155#endif
157 struct ida openowner_id; 156 struct ida openowner_id;
157 struct ida lockowner_id;
158 struct list_head state_owners_lru; 158 struct list_head state_owners_lru;
159 struct list_head layouts; 159 struct list_head layouts;
160 struct list_head delegations; 160 struct list_head delegations;