nodemap_destroy might sleep, but cfs_hash_for_each iterators aren't
allowed to sleep. This patch changes nodemap_cleanup_all to avoid
destroying nodemaps in its cfs_hash_for_each iterator. Instead, the
iterator creats a list of nodemaps, and then all the nodemaps in the
list are destroyed.
Signed-off-by: Kit Westneat <kit.westneat@gmail.com>
Change-Id: I1d16f61ba7739af0494944f6515508b3f0d19ba1
Reviewed-on: http://review.whamcloud.com/14275
Tested-by: Jenkins
Reviewed-by: James Simmons <uja.ornl@yahoo.com>
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Reviewed-by: Andrew Perepechko <andrew.perepechko@seagate.com>
Reviewed-by: John L. Hammond <john.hammond@intel.com>
struct cfs_hash *nm_member_hash;
/* access by nodemap name */
struct hlist_node nm_hash;
struct cfs_hash *nm_member_hash;
/* access by nodemap name */
struct hlist_node nm_hash;
+
+ /* used when unloading nodemaps */
+ struct list_head nm_list;
};
void nodemap_activate(const bool value);
};
void nodemap_activate(const bool value);
/* end of cfs_hash functions */
/**
/* end of cfs_hash functions */
/**
- * Helper iterator to clean up nodemap on module exit.
+ * Helper iterator to convert nodemap hash to list.
- * \param hs hash structure
- * \param bd bucket descriptor
- * \param hnode hash node
- * \param data not used here
+ * \param hs hash structure
+ * \param bd bucket descriptor
+ * \param hnode hash node
+ * \param nodemap_list_head list head for list of nodemaps in hash
*/
static int nodemap_cleanup_iter_cb(struct cfs_hash *hs, struct cfs_hash_bd *bd,
*/
static int nodemap_cleanup_iter_cb(struct cfs_hash *hs, struct cfs_hash_bd *bd,
- struct hlist_node *hnode, void *data)
+ struct hlist_node *hnode,
+ void *nodemap_list_head)
- struct lu_nodemap *nodemap;
+ struct lu_nodemap *nodemap;
nodemap = hlist_entry(hnode, struct lu_nodemap, nm_hash);
nodemap = hlist_entry(hnode, struct lu_nodemap, nm_hash);
- nodemap_putref(nodemap);
+ list_add(&nodemap->nm_list, (struct list_head *)nodemap_list_head);
*/
void nodemap_cleanup_all(void)
{
*/
void nodemap_cleanup_all(void)
{
- cfs_hash_for_each_safe(nodemap_hash, nodemap_cleanup_iter_cb, NULL);
+ struct lu_nodemap *nodemap = NULL;
+ struct list_head *pos, *next;
+ struct list_head nodemap_list_head = LIST_HEAD_INIT(nodemap_list_head);
+
+ cfs_hash_for_each_safe(nodemap_hash, nodemap_cleanup_iter_cb,
+ &nodemap_list_head);
cfs_hash_putref(nodemap_hash);
cfs_hash_putref(nodemap_hash);
+
+ /* Because nodemap_destroy might sleep, we can't destroy them
+ * in cfs_hash_for_each. Instead we build a list and destroy here
+ */
+ list_for_each_safe(pos, next, &nodemap_list_head) {
+ nodemap = list_entry(pos, struct lu_nodemap, nm_list);
+ nodemap_putref(nodemap);
+ }
}
INIT_LIST_HEAD(&nodemap->nm_ranges);
}
INIT_LIST_HEAD(&nodemap->nm_ranges);
+ INIT_LIST_HEAD(&nodemap->nm_list);
rwlock_init(&nodemap->nm_idmap_lock);
nodemap->nm_fs_to_client_uidmap = RB_ROOT;
rwlock_init(&nodemap->nm_idmap_lock);
nodemap->nm_fs_to_client_uidmap = RB_ROOT;