diff options
| author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-01-17 22:04:25 -0500 |
|---|---|---|
| committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-01-31 18:20:28 -0500 |
| commit | d2d7ce28a2f8ec6ca2a49145e643d2e3c7d21ba3 (patch) | |
| tree | 4c73f071c2282185402a4da7d20b30749530c89f | |
| parent | 9157c31dd610a127bc6f01bc1953cf8b80382040 (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.c | 2 | ||||
| -rw-r--r-- | fs/nfs/nfs4_fs.h | 7 | ||||
| -rw-r--r-- | fs/nfs/nfs4proc.c | 6 | ||||
| -rw-r--r-- | fs/nfs/nfs4state.c | 74 | ||||
| -rw-r--r-- | include/linux/nfs_fs_sb.h | 2 |
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 | ||
| 84 | struct 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 | ||
| 320 | static 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; | ||
| 336 | retry: | ||
| 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; | ||
| 354 | id_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 | |||
| 371 | static void nfs_free_unique_id(struct rb_root *root, struct nfs_unique_id *id) | ||
| 372 | { | ||
| 373 | rb_erase(&id->rb_node, root); | ||
| 374 | } | ||
| 375 | |||
| 376 | static struct nfs4_state_owner * | 320 | static struct nfs4_state_owner * |
| 377 | nfs4_find_state_owner_locked(struct nfs_server *server, struct rpc_cred *cred) | 321 | nfs4_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; |
| 773 | out_free: | ||
| 774 | kfree(lsp); | ||
| 775 | return NULL; | ||
| 831 | } | 776 | } |
| 832 | 777 | ||
| 833 | static void nfs4_free_lock_state(struct nfs4_lock_state *lsp) | 778 | static 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; |
