|
30 | 30 | static unsigned nfs_delegation_watermark = NFS_DEFAULT_DELEGATION_WATERMARK; |
31 | 31 | module_param_named(delegation_watermark, nfs_delegation_watermark, uint, 0644); |
32 | 32 |
|
| 33 | +static struct hlist_head *nfs_delegation_hash(struct nfs_server *server, |
| 34 | + const struct nfs_fh *fhandle) |
| 35 | +{ |
| 36 | + return server->delegation_hash_table + |
| 37 | + (nfs_fhandle_hash(fhandle) & server->delegation_hash_mask); |
| 38 | +} |
| 39 | + |
33 | 40 | static void __nfs_free_delegation(struct nfs_delegation *delegation) |
34 | 41 | { |
35 | 42 | put_cred(delegation->cred); |
@@ -367,6 +374,7 @@ nfs_detach_delegation_locked(struct nfs_inode *nfsi, |
367 | 374 | spin_unlock(&delegation->lock); |
368 | 375 | return NULL; |
369 | 376 | } |
| 377 | + hlist_del_init_rcu(&delegation->hash); |
370 | 378 | list_del_rcu(&delegation->super_list); |
371 | 379 | delegation->inode = NULL; |
372 | 380 | rcu_assign_pointer(nfsi->delegation, NULL); |
@@ -529,6 +537,8 @@ int nfs_inode_set_delegation(struct inode *inode, const struct cred *cred, |
529 | 537 | spin_unlock(&inode->i_lock); |
530 | 538 |
|
531 | 539 | list_add_tail_rcu(&delegation->super_list, &server->delegations); |
| 540 | + hlist_add_head_rcu(&delegation->hash, |
| 541 | + nfs_delegation_hash(server, &NFS_I(inode)->fh)); |
532 | 542 | rcu_assign_pointer(nfsi->delegation, delegation); |
533 | 543 | delegation = NULL; |
534 | 544 |
|
@@ -1166,11 +1176,12 @@ static struct inode * |
1166 | 1176 | nfs_delegation_find_inode_server(struct nfs_server *server, |
1167 | 1177 | const struct nfs_fh *fhandle) |
1168 | 1178 | { |
| 1179 | + struct hlist_head *head = nfs_delegation_hash(server, fhandle); |
1169 | 1180 | struct nfs_delegation *delegation; |
1170 | 1181 | struct super_block *freeme = NULL; |
1171 | 1182 | struct inode *res = NULL; |
1172 | 1183 |
|
1173 | | - list_for_each_entry_rcu(delegation, &server->delegations, super_list) { |
| 1184 | + hlist_for_each_entry_rcu(delegation, head, hash) { |
1174 | 1185 | spin_lock(&delegation->lock); |
1175 | 1186 | if (delegation->inode != NULL && |
1176 | 1187 | !test_bit(NFS_DELEGATION_REVOKED, &delegation->flags) && |
@@ -1577,3 +1588,18 @@ bool nfs4_delegation_flush_on_close(const struct inode *inode) |
1577 | 1588 | rcu_read_unlock(); |
1578 | 1589 | return ret; |
1579 | 1590 | } |
| 1591 | + |
| 1592 | +int nfs4_delegation_hash_alloc(struct nfs_server *server) |
| 1593 | +{ |
| 1594 | + int delegation_buckets, i; |
| 1595 | + |
| 1596 | + delegation_buckets = roundup_pow_of_two(nfs_delegation_watermark / 16); |
| 1597 | + server->delegation_hash_mask = delegation_buckets - 1; |
| 1598 | + server->delegation_hash_table = kmalloc_array(delegation_buckets, |
| 1599 | + sizeof(*server->delegation_hash_table), GFP_KERNEL); |
| 1600 | + if (!server->delegation_hash_table) |
| 1601 | + return -ENOMEM; |
| 1602 | + for (i = 0; i < delegation_buckets; i++) |
| 1603 | + INIT_HLIST_HEAD(&server->delegation_hash_table[i]); |
| 1604 | + return 0; |
| 1605 | +} |
0 commit comments