[PATCH 02/20] staging: lustre: convert lov_pool to use rhashtable
The pools hashtable can be implemented using the rhashtable implementation in lib. This has the benefit that lookups are lock-free. We need to use kfree_rcu() to free a pool so that a lookup racing with a deletion will not access freed memory. rhashtable has no combined lookup-and-delete interface, but as the lookup is lockless and the chains are short, this brings little cost. Even if a lookup finds a pool, we must be prepared for the delete to fail to find it, as we might race with another thread doing a delete. We use atomic_inc_not_zero() after finding a pool in the hash table and if that fails, we must have raced with a deletion, so we treat the lookup as a failure. Use hashlen_string() rather than a hand-crafted hash function. Note that the pool_name, and the search key, are guaranteed to be nul terminated. Signed-off-by: NeilBrown--- drivers/staging/lustre/lustre/include/obd.h|4 - .../staging/lustre/lustre/include/obd_support.h|3 drivers/staging/lustre/lustre/lov/lov_internal.h | 11 + drivers/staging/lustre/lustre/lov/lov_obd.c| 12 +- drivers/staging/lustre/lustre/lov/lov_pool.c | 159 5 files changed, 80 insertions(+), 109 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index f1233ca7d337..ad265db48b76 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -46,6 +46,8 @@ #include #include +#include + #define MAX_OBD_DEVICES 8192 struct osc_async_rc { @@ -383,7 +385,7 @@ struct lov_obd { __u32 lov_tgt_size; /* size of tgts array */ int lov_connects; int lov_pool_count; - struct cfs_hash *lov_pools_hash_body; /* used for key access */ + struct rhashtable lov_pools_hash_body; /* used for key access */ struct list_headlov_pool_list; /* used for sequential access */ struct dentry *lov_pool_debugfs_entry; enum lustre_sec_partlov_sp_me; diff --git a/drivers/staging/lustre/lustre/include/obd_support.h b/drivers/staging/lustre/lustre/include/obd_support.h index aebcab191442..730a6ee71565 100644 --- a/drivers/staging/lustre/lustre/include/obd_support.h +++ b/drivers/staging/lustre/lustre/include/obd_support.h @@ -61,9 +61,6 @@ extern atomic_long_t obd_dirty_transit_pages; extern char obd_jobid_var[]; /* Some hash init argument constants */ -#define HASH_POOLS_BKT_BITS 3 -#define HASH_POOLS_CUR_BITS 3 -#define HASH_POOLS_MAX_BITS 7 #define HASH_UUID_BKT_BITS 5 #define HASH_UUID_CUR_BITS 7 #define HASH_UUID_MAX_BITS 12 diff --git a/drivers/staging/lustre/lustre/lov/lov_internal.h b/drivers/staging/lustre/lustre/lov/lov_internal.h index 27f60dd7ab9a..47042f27ca90 100644 --- a/drivers/staging/lustre/lustre/lov/lov_internal.h +++ b/drivers/staging/lustre/lustre/lov/lov_internal.h @@ -149,11 +149,16 @@ struct pool_desc { char pool_name[LOV_MAXPOOLNAME + 1]; struct ost_pool pool_obds; atomic_t pool_refcount; - struct hlist_nodepool_hash; /* access by poolname */ - struct list_head pool_list; /* serial access */ + struct rhash_headpool_hash; /* access by poolname */ + union { + struct list_headpool_list; /* serial access */ + struct rcu_head rcu;/* delayed free */ + }; struct dentry *pool_debugfs_entry;/* file in debugfs */ struct obd_device *pool_lobd; /* owner */ }; +int lov_pool_hash_init(struct rhashtable *tbl); +void lov_pool_hash_destroy(struct rhashtable *tbl); struct lov_request { struct obd_info rq_oi; @@ -241,8 +246,6 @@ void lprocfs_lov_init_vars(struct lprocfs_static_vars *lvars); /* lov_cl.c */ extern struct lu_device_type lov_device_type; -/* pools */ -extern struct cfs_hash_ops pool_hash_operations; /* ost_pool methods */ int lov_ost_pool_init(struct ost_pool *op, unsigned int count); int lov_ost_pool_extend(struct ost_pool *op, unsigned int min_count); diff --git a/drivers/staging/lustre/lustre/lov/lov_obd.c b/drivers/staging/lustre/lustre/lov/lov_obd.c index 355e87ecc62d..94da35e673f7 100644 --- a/drivers/staging/lustre/lustre/lov/lov_obd.c +++ b/drivers/staging/lustre/lustre/lov/lov_obd.c @@ -795,15 +795,11 @@ int lov_setup(struct obd_device *obd, struct lustre_cfg *lcfg) init_rwsem(>lov_notify_lock); - lov->lov_pools_hash_body = cfs_hash_create("POOLS", HASH_POOLS_CUR_BITS, - HASH_POOLS_MAX_BITS, - HASH_POOLS_BKT_BITS, 0, - CFS_HASH_MIN_THETA, -
[PATCH 02/20] staging: lustre: convert lov_pool to use rhashtable
The pools hashtable can be implemented using the rhashtable implementation in lib. This has the benefit that lookups are lock-free. We need to use kfree_rcu() to free a pool so that a lookup racing with a deletion will not access freed memory. rhashtable has no combined lookup-and-delete interface, but as the lookup is lockless and the chains are short, this brings little cost. Even if a lookup finds a pool, we must be prepared for the delete to fail to find it, as we might race with another thread doing a delete. We use atomic_inc_not_zero() after finding a pool in the hash table and if that fails, we must have raced with a deletion, so we treat the lookup as a failure. Use hashlen_string() rather than a hand-crafted hash function. Note that the pool_name, and the search key, are guaranteed to be nul terminated. Signed-off-by: NeilBrown --- drivers/staging/lustre/lustre/include/obd.h|4 - .../staging/lustre/lustre/include/obd_support.h|3 drivers/staging/lustre/lustre/lov/lov_internal.h | 11 + drivers/staging/lustre/lustre/lov/lov_obd.c| 12 +- drivers/staging/lustre/lustre/lov/lov_pool.c | 159 5 files changed, 80 insertions(+), 109 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index f1233ca7d337..ad265db48b76 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -46,6 +46,8 @@ #include #include +#include + #define MAX_OBD_DEVICES 8192 struct osc_async_rc { @@ -383,7 +385,7 @@ struct lov_obd { __u32 lov_tgt_size; /* size of tgts array */ int lov_connects; int lov_pool_count; - struct cfs_hash *lov_pools_hash_body; /* used for key access */ + struct rhashtable lov_pools_hash_body; /* used for key access */ struct list_headlov_pool_list; /* used for sequential access */ struct dentry *lov_pool_debugfs_entry; enum lustre_sec_partlov_sp_me; diff --git a/drivers/staging/lustre/lustre/include/obd_support.h b/drivers/staging/lustre/lustre/include/obd_support.h index aebcab191442..730a6ee71565 100644 --- a/drivers/staging/lustre/lustre/include/obd_support.h +++ b/drivers/staging/lustre/lustre/include/obd_support.h @@ -61,9 +61,6 @@ extern atomic_long_t obd_dirty_transit_pages; extern char obd_jobid_var[]; /* Some hash init argument constants */ -#define HASH_POOLS_BKT_BITS 3 -#define HASH_POOLS_CUR_BITS 3 -#define HASH_POOLS_MAX_BITS 7 #define HASH_UUID_BKT_BITS 5 #define HASH_UUID_CUR_BITS 7 #define HASH_UUID_MAX_BITS 12 diff --git a/drivers/staging/lustre/lustre/lov/lov_internal.h b/drivers/staging/lustre/lustre/lov/lov_internal.h index 27f60dd7ab9a..47042f27ca90 100644 --- a/drivers/staging/lustre/lustre/lov/lov_internal.h +++ b/drivers/staging/lustre/lustre/lov/lov_internal.h @@ -149,11 +149,16 @@ struct pool_desc { char pool_name[LOV_MAXPOOLNAME + 1]; struct ost_pool pool_obds; atomic_t pool_refcount; - struct hlist_nodepool_hash; /* access by poolname */ - struct list_head pool_list; /* serial access */ + struct rhash_headpool_hash; /* access by poolname */ + union { + struct list_headpool_list; /* serial access */ + struct rcu_head rcu;/* delayed free */ + }; struct dentry *pool_debugfs_entry;/* file in debugfs */ struct obd_device *pool_lobd; /* owner */ }; +int lov_pool_hash_init(struct rhashtable *tbl); +void lov_pool_hash_destroy(struct rhashtable *tbl); struct lov_request { struct obd_info rq_oi; @@ -241,8 +246,6 @@ void lprocfs_lov_init_vars(struct lprocfs_static_vars *lvars); /* lov_cl.c */ extern struct lu_device_type lov_device_type; -/* pools */ -extern struct cfs_hash_ops pool_hash_operations; /* ost_pool methods */ int lov_ost_pool_init(struct ost_pool *op, unsigned int count); int lov_ost_pool_extend(struct ost_pool *op, unsigned int min_count); diff --git a/drivers/staging/lustre/lustre/lov/lov_obd.c b/drivers/staging/lustre/lustre/lov/lov_obd.c index 355e87ecc62d..94da35e673f7 100644 --- a/drivers/staging/lustre/lustre/lov/lov_obd.c +++ b/drivers/staging/lustre/lustre/lov/lov_obd.c @@ -795,15 +795,11 @@ int lov_setup(struct obd_device *obd, struct lustre_cfg *lcfg) init_rwsem(>lov_notify_lock); - lov->lov_pools_hash_body = cfs_hash_create("POOLS", HASH_POOLS_CUR_BITS, - HASH_POOLS_MAX_BITS, - HASH_POOLS_BKT_BITS, 0, - CFS_HASH_MIN_THETA, -