+static void
+filter_iobuf_hop_exit(cfs_hash_t *hs, cfs_hlist_node_t *hnode)
+{
+ struct filter_iobuf *pool;
+
+ pool = cfs_hlist_entry(hnode, struct filter_iobuf, dr_hlist);
+ filter_free_iobuf(pool);
+}
+
+static struct cfs_hash_ops filter_iobuf_hops = {
+ .hs_hash = filter_iobuf_hop_hash,
+ .hs_key = filter_iobuf_hop_key,
+ .hs_keycmp = filter_iobuf_hop_keycmp,
+ .hs_object = filter_iobuf_hop_object,
+ .hs_get = filter_iobuf_hop_get,
+ .hs_put_locked = filter_iobuf_hop_put_locked,
+ .hs_exit = filter_iobuf_hop_exit
+};
+
+#define FILTER_IOBUF_HASH_BITS 9
+#define FILTER_IOBUF_HBKT_BITS 4
+
+/*
+ * pre-allocate pool of iobuf's to be used by filter_{prep,commit}rw_write().
+ */
+static int filter_iobuf_pool_init(struct filter_obd *filter)
+{
+ filter->fo_iobuf_hash = cfs_hash_create("filter_iobuf",
+ FILTER_IOBUF_HASH_BITS,
+ FILTER_IOBUF_HASH_BITS,
+ FILTER_IOBUF_HBKT_BITS, 0,
+ CFS_HASH_MIN_THETA,
+ CFS_HASH_MAX_THETA,
+ &filter_iobuf_hops,
+ CFS_HASH_RW_BKTLOCK |
+ CFS_HASH_NO_ITEMREF);
+
+ return filter->fo_iobuf_hash != NULL ? 0 : -ENOMEM;
+}
+
+/* Return iobuf allocated for @thread_id.
+ * If we haven't allocated a pool entry for this thread before, do so now and
+ * insert it into fo_iobuf_hash, otherwise we can find it from fo_iobuf_hash */
+void *filter_iobuf_get(struct filter_obd *filter, struct obd_trans_info *oti)
+{
+ struct filter_iobuf *pool = NULL;
+ __u64 key = 0;
+ int thread_id;
+ int rc;
+
+ thread_id = (oti && oti->oti_thread) ? oti->oti_thread->t_id : -1;
+ if (thread_id >= 0) {
+ struct ptlrpc_service_part *svcpt;
+
+ svcpt = oti->oti_thread->t_svcpt;
+ LASSERT(svcpt != NULL);
+
+ key = (__u64)(svcpt->scp_cpt) << 32 | thread_id;
+ pool = cfs_hash_lookup(filter->fo_iobuf_hash, &key);
+ if (pool != NULL)
+ return pool;
+ }
+
+ pool = filter_alloc_iobuf(filter, OBD_BRW_WRITE, PTLRPC_MAX_BRW_PAGES);
+ if (pool == NULL)
+ return NULL;
+
+ if (thread_id >= 0) {
+ pool->dr_hkey = key;
+ rc = cfs_hash_add_unique(filter->fo_iobuf_hash,
+ &key, &pool->dr_hlist);
+ /* ptlrpc service thould guarantee thread ID is unique */
+ LASSERT(rc != -EALREADY);
+ }
+
+ return pool;