[openib-general] [PATCH] SDP buffer managment simplification.

Libor Michalek libor at topspin.com
Wed Oct 13 18:28:00 PDT 2004


  This patch is a simpliification to the SDP buffer management code. The
previous code would never return memory once it had grabbed it, and the
way the buffers were allocated made adding that feature difficult. So,
I simplified the code in the process of adding this behaviour.

-Libor


Index: infiniband/ulp/sdp/sdp_proto.h
===================================================================
--- infiniband/ulp/sdp/sdp_proto.h	(revision 988)
+++ infiniband/ulp/sdp/sdp_proto.h	(working copy)
@@ -98,7 +98,10 @@
 			     tSDP_BUFF_TEST_FUNC test_func,
 			     void *usr_arg);
 
-int sdp_buff_pool_init(u32 buff_min, u32 buff_max);
+int sdp_buff_pool_init(int buff_min, 
+		       int buff_max,
+		       int alloc_inc,
+		       int free_mark);
 
 void sdp_buff_pool_destroy(void);
 
@@ -276,8 +279,6 @@
 /* --------------------------------------------------------------------- */
 int sdp_conn_table_init(int proto_family,
 			int conn_size,
-			int buff_min,
-			int buff_max,
 			int recv_post_max,
 			int recv_buff_max,
 			int send_post_max,
Index: infiniband/ulp/sdp/sdp_buff.h
===================================================================
--- infiniband/ulp/sdp/sdp_buff.h	(revision 988)
+++ infiniband/ulp/sdp/sdp_buff.h	(working copy)
@@ -32,37 +32,36 @@
  * structures
  */
 struct sdpc_buff_q {
-	struct sdpc_buff *head;		/* double linked list of buffers */
-	u32 size;		/* current number of buffers allocated to the pool */
+	struct sdpc_buff *head; /* double linked list of buffers */
+	u32 size;               /* number of buffers in the pool */
 #ifdef _TS_SDP_DEBUG_POOL_NAME
-	char *name;		/* pointer to pools name */
+	char *name;             /* pointer to pools name */
 #endif
 }; /* struct sdpc_buff_q */
 
 struct sdpc_buff {
 	struct sdpc_buff *next;
 	struct sdpc_buff *prev;
-	u32 type;		/* element type. (for generic queue) */
-	struct sdpc_buff_q *pool;		/* pool currently holding this buffer. */
-	tSDP_GENERIC_DESTRUCT_FUNC release;	/* release the object */
+	u32 type;                 /* element type. (for generic queue) */
+	struct sdpc_buff_q *pool; /* pool currently holding this buffer. */
+	tSDP_GENERIC_DESTRUCT_FUNC release; /* release the object */
 	/*
 	 * primary generic data pointers
 	 */
-	void *head;		/* first byte of data buffer */
-	void *data;		/* first byte of valid data in buffer */
-	void *tail;		/* last byte of valid data in buffer */
-	void *end;		/* last byte of data buffer */
+	void *head; /* first byte of data buffer */
+	void *data; /* first byte of valid data in buffer */
+	void *tail; /* last byte of valid data in buffer */
+	void *end;  /* last byte of data buffer */
 	/*
 	 * Experimental
 	 */
-	u32 flags;		/* Buffer flags */
-	u32 u_id;		/* unique buffer ID, used for tracking */
+	u32 flags;  /* Buffer flags */
 	/*
 	 * Protocol specific data
 	 */
-	struct msg_hdr_bsdh *bsdh_hdr;	/* SDP header (BSDH) */
-	u32 data_size;	/* size of just data in the buffer */
-	u32 ib_wrid;	/* IB work request ID */
+	struct msg_hdr_bsdh *bsdh_hdr; /* SDP header (BSDH) */
+	u32 data_size;                 /* size of just data in the buffer */
+	u32 ib_wrid;                   /* IB work request ID */
 	/*
 	 * IB specific data (The main buffer pool sets the lkey when 
 	 * it is created)
Index: infiniband/ulp/sdp/sdp_buff_p.h
===================================================================
--- infiniband/ulp/sdp/sdp_buff_p.h	(revision 988)
+++ infiniband/ulp/sdp/sdp_buff_p.h	(working copy)
@@ -38,59 +38,36 @@
  * definitions
  */
 #define TS_SDP_BUFFER_COUNT_MIN 1024
-#define TS_SDP_BUFFER_COUNT_MAX 131072
-#define TS_SDP_BUFFER_COUNT_INC 1024
+#define TS_SDP_BUFFER_COUNT_MAX 1048576
+#define TS_SDP_BUFFER_COUNT_INC 128
+#define TS_SDP_BUFFER_FREE_MARK 1024
 
 #define TS_SDP_POOL_NAME_MAX   16	/* maximum size pool name */
 #define TS_SDP_MAIN_POOL_NAME  "main"
-#define TS_SDP_BUFF_OUT_LEN    33	/* size of buffer output line */
 /*
- * types
- */
-typedef struct tSDP_MAIN_POOL_STRUCT tSDP_MAIN_POOL_STRUCT, *tSDP_MAIN_POOL;
-typedef struct tSDP_MEMORY_SEGMENT_STRUCT tSDP_MEMORY_SEGMENT_STRUCT,
-    *tSDP_MEMORY_SEGMENT;
-typedef struct tSDP_MEM_SEG_HEAD_STRUCT tSDP_MEM_SEG_HEAD_STRUCT,
-    *tSDP_MEM_SEG_HEAD;
-/*
  * structures
  */
-struct tSDP_MAIN_POOL_STRUCT {
+struct sdpc_buff_root {
 	/*
 	 * variant
 	 */
-	struct sdpc_buff_q pool;	/* actual pool of buffers */
-	spinlock_t lock;	/* spin lock for pool access */
+	struct sdpc_buff_q pool;  /* actual pool of buffers */
+	spinlock_t lock;          /* spin lock for pool access */
 	/*
 	 * invariant
 	 */
-	kmem_cache_t *pool_cache;	/* cache of pool objects */
+	kmem_cache_t *pool_cache; /* cache of pool objects */
+	kmem_cache_t *buff_cache; /* cache of buffer descriptor objects */
 
-	u32 buff_min;
-	u32 buff_max;
-	u32 buff_cur;
-	u32 buff_size;	/* size of each buffer in the pool */
+	int buff_min;   /* minimum allocated buffers */
+	int buff_max;   /* maximum allocated buffers */
+	int buff_cur;   /* total allocated buffers */
+	int buff_size;	/* size of each buffer in the pool */
 
-	tSDP_MEMORY_SEGMENT segs;
-}; /* tSDP_MAIN_POOL_STRUCT */
+	int alloc_inc;  /* allocation increment */
+	int free_mark;  /* start freeing unused buffers */
+}; /* struct sdpc_buff_root */
 
-/*
- * Each memory segment is its own page.
- */
-struct tSDP_MEM_SEG_HEAD_STRUCT {
-	tSDP_MEMORY_SEGMENT next;
-	tSDP_MEMORY_SEGMENT prev;
-	u32 size;
-}; /* tSDP_MEM_SEG_HEAD_STRUCT */
-
-#define TS_SDP_BUFF_COUNT ((PAGE_SIZE - sizeof(tSDP_MEM_SEG_HEAD_STRUCT))/ \
-			   sizeof(struct sdpc_buff))
-
-struct tSDP_MEMORY_SEGMENT_STRUCT {
-	tSDP_MEM_SEG_HEAD_STRUCT head;
-	struct sdpc_buff     list[TS_SDP_BUFF_COUNT];
-}; /* tSDP_MEMORY_REGION_STRUCT */
-
 #endif /* _TS_SDP_BUFF_P_H */
 
 
Index: infiniband/ulp/sdp/sdp_conn.c
===================================================================
--- infiniband/ulp/sdp/sdp_conn.c	(revision 988)
+++ infiniband/ulp/sdp/sdp_conn.c	(working copy)
@@ -2061,8 +2061,6 @@
 /*..sdp_conn_table_init -- create a sdp connection table */
 int sdp_conn_table_init(int proto_family,
 			int conn_size,
-			int buff_min,
-			int buff_max,
 			int recv_post_max,
 			int recv_buff_max,
 			int send_post_max,
@@ -2151,17 +2149,7 @@
 			 result);
 		goto error_iocb;
 	}
-	/*
-	 * buffer memory
-	 */
-	result = sdp_buff_pool_init(buff_min, buff_max);
-	if (0 > result) {
 
-		TS_TRACE(MOD_LNX_SDP, T_TERSE, TRACE_FLOW_FATAL,
-			 "INIT: Error <%d> initializing buffer pool.", result);
-		goto error_buff;
-	}
-
 	_dev_root_s.conn_cache = kmem_cache_create("SdpConnCache",
 						   sizeof(struct sdp_opt),
 						   0, SLAB_HWCACHE_ALIGN,
@@ -2203,8 +2191,6 @@
 error_sock:
 	kmem_cache_destroy(_dev_root_s.conn_cache);
 error_conn:
-	(void)sdp_buff_pool_destroy();
-error_buff:
 	(void)sdp_main_iocb_cleanup();
 error_iocb:
 	_dev_root_s.sk_array--;
@@ -2251,10 +2237,6 @@
 	 */
 	(void)sdp_cm_listen_stop(&_dev_root_s);
 	/*
-	 * delete buffer memory
-	 */
-	(void)sdp_buff_pool_destroy();
-	/*
 	 * delete IOCB table
 	 */
 	(void)sdp_main_iocb_cleanup();
Index: infiniband/ulp/sdp/sdp_inet.c
===================================================================
--- infiniband/ulp/sdp/sdp_inet.c	(revision 988)
+++ infiniband/ulp/sdp/sdp_inet.c	(working copy)
@@ -27,10 +27,12 @@
 /*
  * list of connections waiting for an incomming connection
  */
-static int _proto_family = TS_SDP_DEV_PROTO;
-static int _buff_min     = TS_SDP_BUFFER_COUNT_MIN;
-static int _buff_max     = TS_SDP_BUFFER_COUNT_MAX;
-static int _conn_size    = TS_SDP_DEV_SK_LIST_SIZE;
+static int _proto_family    = TS_SDP_DEV_PROTO;
+static int _buff_min        = TS_SDP_BUFFER_COUNT_MIN;
+static int _buff_max        = TS_SDP_BUFFER_COUNT_MAX;
+static int _alloc_inc       = TS_SDP_BUFFER_COUNT_INC;
+static int _free_mark       = TS_SDP_BUFFER_FREE_MARK;
+static int _conn_size       = TS_SDP_DEV_SK_LIST_SIZE;
 
 static int _recv_post_max   = TS_SDP_DEV_RECV_POST_MAX;
 static int _recv_buff_max   = TS_SDP_RECV_BUFFERS_MAX;
@@ -1837,17 +1839,28 @@
 	if (0 > result) {
 
 		TS_TRACE(MOD_LNX_SDP, T_TERSE, TRACE_FLOW_FATAL,
-			 "INIT: Error <%d> initializing SDP advertisments <%d>",
+			 "INIT: Error <%d> initializing advertisments <%d>",
 			 result);
 		goto error_advt;
 	}
 	/*
+	 * buffer memory
+	 */
+	result = sdp_buff_pool_init(_buff_min, 
+				    _buff_max, 
+				    _alloc_inc, 
+				    _free_mark);
+	if (0 > result) {
+
+		TS_TRACE(MOD_LNX_SDP, T_TERSE, TRACE_FLOW_FATAL,
+			 "INIT: Error <%d> initializing buffer pool.", result);
+		goto error_buff;
+	}
+	/*
 	 * connection table
 	 */
 	result = sdp_conn_table_init(_proto_family,
 				     _conn_size, 
-				     _buff_min,
-				     _buff_max,
 				     _recv_post_max,
 				     _recv_buff_max,
 				     _send_post_max,
@@ -1878,6 +1891,8 @@
 error_sock:
 	(void)sdp_conn_table_clear();
 error_conn:
+	(void)sdp_buff_pool_destroy();
+error_buff:
 	(void)sdp_main_advt_cleanup();
 error_advt:
 	(void)sdp_main_desc_cleanup();
@@ -1902,6 +1917,10 @@
 	 */
 	(void)sdp_conn_table_clear();
 	/*
+	 * delete buffer memory
+	 */
+	(void)sdp_buff_pool_destroy();
+	/*
 	 * delete advertisment table
 	 */
 	(void)sdp_main_advt_cleanup();
Index: infiniband/ulp/sdp/sdp_buff.c
===================================================================
--- infiniband/ulp/sdp/sdp_buff.c	(revision 988)
+++ infiniband/ulp/sdp/sdp_buff.c	(working copy)
@@ -24,16 +24,19 @@
 #include "sdp_main.h"
 
 static char _main_pool_name[] = TS_SDP_MAIN_POOL_NAME;
-static tSDP_MAIN_POOL main_pool = NULL;
+static struct sdpc_buff_root *main_pool = NULL;
 /*
  * data buffers managment API
  */
 /* ========================================================================= */
 /*.._sdp_buff_q_get - Get a buffer from a specific pool */
-static __inline__ struct sdpc_buff *_sdp_buff_q_get(struct sdpc_buff_q *pool,
-						 int fifo,
-						 tSDP_BUFF_TEST_FUNC test_func,
-						 void *usr_arg)
+static __inline__ struct sdpc_buff *_sdp_buff_q_get
+(
+	struct sdpc_buff_q *pool,
+	int fifo,
+	tSDP_BUFF_TEST_FUNC test_func,
+	void *usr_arg
+)
 {
 	struct sdpc_buff *buff;
 
@@ -483,11 +486,11 @@
 		if (0 > result) {
 
 			TS_TRACE(MOD_LNX_SDP, T_VERY_VERBOSE, TRACE_FLOW_INOUT,
-				 "BUFF: Error <%d> returning buffer to main. <%d>",
-				 result, pool->size);
+				 "BUFF: Error <%d> returning buffer to main",
+				 result);
 		}
 	}
-
+	
 	return 0;
 } /* sdp_buff_q_clear */
 
@@ -498,190 +501,148 @@
 /* --------------------------------------------------------------------- */
 
 /* ========================================================================= */
-/*.._sdp_buff_pool_seg_release -- release buffers from the segment */
-static int _sdp_buff_pool_seg_release(tSDP_MEMORY_SEGMENT mem_seg)
+/*.._sdp_buff_pool_release -- release allocated buffers from the main pool */
+static int _sdp_buff_pool_release(struct sdpc_buff_root *m_pool,
+				     int count)
 {
-	TS_CHECK_NULL(mem_seg, -EINVAL);
-	/*
-	 * loop through pages.
-	 */
-	while (0 < mem_seg->head.size) {
+	struct sdpc_buff *buff;
 
-		mem_seg->head.size--;
-		free_page((unsigned long)mem_seg->list[mem_seg->head.size].
-			  head);
-	}
-	/*
-	 * free  descriptor page
-	 */
-	free_page((unsigned long)mem_seg);
-
-	return 0;
-} /* _sdp_buff_pool_seg_release */
-
-/* ========================================================================= */
-/*.._sdp_buff_pool_seg_release_all -- release buffers from the segment */
-static int _sdp_buff_pool_seg_release_all(tSDP_MAIN_POOL m_pool)
-{
-	tSDP_MEMORY_SEGMENT mem_seg;
-	int result;
-
 	TS_CHECK_NULL(m_pool, -EINVAL);
 	/*
-	 * loop through pages.
+	 * Release count buffers.
 	 */
-	while (NULL != m_pool->segs) {
-
-		mem_seg = m_pool->segs;
-		m_pool->segs = mem_seg->head.next;
-
-		m_pool->buff_cur -= mem_seg->head.size;
-
-		result = _sdp_buff_pool_seg_release(mem_seg);
-		TS_EXPECT(MOD_LNX_SDP, !(0 > result));
+	while (count--) {
+		
+		buff = sdp_buff_q_get(&m_pool->pool);
+		if (NULL == buff) {
+			
+			break;
+		}
+		/*
+		 * decrement global buffer count, free buffer page, and free
+		 * buffer descriptor.
+		 */
+		m_pool->buff_cur--;
+		free_page((unsigned long)buff->head);
+		kmem_cache_free(m_pool->buff_cache, buff);
 	}
-
+	
 	return 0;
-} /* _sdp_buff_pool_seg_release_all */
+} /* _sdp_buff_pool_release */
 
 /* ========================================================================= */
-/*.._sdp_buff_pool_seg_alloc -- allocate more buffers for the main pool */
-static tSDP_MEMORY_SEGMENT _sdp_buff_pool_seg_alloc(void)
+/*.._sdp_buff_pool_release_check -- check for buffer release from main pool */
+static __inline__ int _sdp_buff_pool_release_check
+(
+	struct sdpc_buff_root *m_pool
+)
 {
-	tSDP_MEMORY_SEGMENT mem_seg;
-        int counter;
-	int result;
+	TS_CHECK_NULL(m_pool, -EINVAL);
 	/*
-	 * get descriptor page
+	 * If there are more then minimum buffers outstanding, free half of
+	 * the available buffers.
 	 */
-	mem_seg = (tSDP_MEMORY_SEGMENT) __get_free_page(GFP_ATOMIC);
-	if (NULL == mem_seg) {
+	if (m_pool->buff_cur > m_pool->buff_min &&
+	    m_pool->pool.size > m_pool->free_mark) {
+		int count;
+		/*
+		 * Always leave at least minimum buffers, otherwise remove
+		 * either half of the pool, which is more then the mark
+		 */
+		count = min((m_pool->buff_cur - m_pool->buff_min),
+			    (m_pool->free_mark/2));
 
-		TS_TRACE(MOD_LNX_SDP, T_TERSE, TRACE_FLOW_FATAL,
-			 "BUFFER: Failed to allocate descriptor page.");
-
-		goto error;
+		return _sdp_buff_pool_release(m_pool, count);
 	}
-	/*
-	 * loop
-	 */
-	for (counter = 0, mem_seg->head.size = 0;
-	     counter < TS_SDP_BUFF_COUNT; counter++, mem_seg->head.size++) {
-
-		mem_seg->list[counter].head =
-		    (void *) __get_free_page(GFP_ATOMIC);
-		if (NULL == mem_seg->list[counter].head) {
-
-			TS_TRACE(MOD_LNX_SDP, T_TERSE, TRACE_FLOW_FATAL,
-				 "BUFFER: Failed to allocate buffer page. <%d>",
-				 counter);
-
-			goto error_free;
-		}
-
-		mem_seg->list[counter].end =
-		    mem_seg->list[counter].head + PAGE_SIZE;
-		mem_seg->list[counter].data = mem_seg->list[counter].head;
-		mem_seg->list[counter].tail = mem_seg->list[counter].head;
-		mem_seg->list[counter].lkey = 0;
-		mem_seg->list[counter].real = 0;
-		mem_seg->list[counter].size = 0;
-		mem_seg->list[counter].u_id = 0;
-		mem_seg->list[counter].pool = NULL;
-		mem_seg->list[counter].type = TS_SDP_GENERIC_TYPE_BUFF;
-		mem_seg->list[counter].release = ((tSDP_GENERIC_DESTRUCT_FUNC)
-						  sdp_buff_pool_put);
+	else {
+		
+		return 0;
 	}
-	/*
-	 * return segment
-	 */
-	return mem_seg;
-error_free:
-	result = _sdp_buff_pool_seg_release(mem_seg);
-	TS_EXPECT(MOD_LNX_SDP, !(0 > result));
-error:
-	return NULL;
-} /* _sdp_buff_pool_seg_alloc */
+} /* _sdp_buff_pool_release_check */
 
 /* ========================================================================= */
 /*.._sdp_buff_pool_alloc -- allocate more buffers for the main pool */
-static int _sdp_buff_pool_alloc(tSDP_MAIN_POOL m_pool, u32 size)
+static int _sdp_buff_pool_alloc(struct sdpc_buff_root *m_pool)
 {
-	tSDP_MEMORY_SEGMENT head_seg = NULL;
-	tSDP_MEMORY_SEGMENT mem_seg;
-	u32 counter = 0;
-	u32 total = 0;
+	struct sdpc_buff *buff;
+	int total;
 	int result;
 
 	TS_CHECK_NULL(m_pool, -EINVAL);
 	/*
-	 * check pool limits.
+	 * Calculate the total number of buffers.
 	 */
-	if (m_pool->buff_max < (m_pool->buff_cur + size)) {
+	total = max(m_pool->buff_min, (m_pool->buff_cur + m_pool->alloc_inc));
+	total = min(total, m_pool->buff_max);
 
-		goto error;
-	}
-	/*
-	 * first allocate the requested number of buffers. Once complete
-	 * place them all into the main pool.
-	 */
-	while (total < size) {
+	while (total > m_pool->buff_cur) {
+		/*
+		 * allocate a buffer descriptor, buffer, and then add it to
+		 * the pool.
+		 */
+		buff = kmem_cache_alloc(m_pool->buff_cache, GFP_ATOMIC);
+		if (NULL == buff) {
 
-		mem_seg = _sdp_buff_pool_seg_alloc();
-		if (NULL == mem_seg) {
-
 			TS_TRACE(MOD_LNX_SDP, T_TERSE, TRACE_FLOW_FATAL,
-				 "BUFFER: Failed to allocate segment.");
-
-			goto error;
+				 "BUFFER: Failed to allocate buffer. <%d:%d>",
+				 total, m_pool->buff_cur);
+			break;
 		}
 
-		mem_seg->head.next = head_seg;
-		head_seg = mem_seg;
+		buff->head = (void *)__get_free_page(GFP_ATOMIC);
+		if (NULL == buff->head) {
 
-		total += mem_seg->head.size;
-	}
-	/*
-	 * insert each segment into the list, and insert each buffer into
-	 * the main pool
-	 */
-	while (NULL != head_seg) {
+			TS_TRACE(MOD_LNX_SDP, T_TERSE, TRACE_FLOW_FATAL,
+				 "BUFFER: Failed to allocate page. <%d:%d>",
+				 total, m_pool->buff_cur);
 
-		mem_seg = head_seg;
-		head_seg = mem_seg->head.next;
+			kmem_cache_free(m_pool->buff_cache, buff);
+			break;
+		}
+		
+		buff->end     = buff->head + PAGE_SIZE;
+		buff->data    = buff->head;
+		buff->tail    = buff->head;
+		buff->lkey    = 0;
+		buff->real    = 0;
+		buff->size    = 0;
+		buff->pool    = NULL;
+		buff->type    = TS_SDP_GENERIC_TYPE_BUFF;
+		buff->release = ((tSDP_GENERIC_DESTRUCT_FUNC)sdp_buff_q_put);
 
-		mem_seg->head.next = m_pool->segs;
-		m_pool->segs = mem_seg;
+		result = sdp_buff_q_put(&m_pool->pool, buff);
+		if (0 > result) {
 
-		for (counter = 0; counter < mem_seg->head.size; counter++) {
-
-			mem_seg->list[counter].u_id = m_pool->buff_cur++;
-
-			result =
-			    sdp_buff_q_put(&main_pool->pool,
-					     &mem_seg->list[counter]);
-			TS_EXPECT(MOD_LNX_SDP, !(0 > result));
+			TS_TRACE(MOD_LNX_SDP, T_TERSE, TRACE_FLOW_FATAL,
+				 "BUFFER: Failed to insert buffer. <%d>",
+				 result);
+			
+			free_page((unsigned long)buff->head);
+			kmem_cache_free(m_pool->buff_cache, buff);
+			break;
 		}
+
+		m_pool->buff_cur++;
 	}
 
-	return total;
-error:
+	if (NULL == main_pool->pool.head) {
 
-	while (NULL != head_seg) {
+		TS_TRACE(MOD_LNX_SDP, T_VERBOSE, TRACE_FLOW_FATAL,
+			 "BUFFER: Failed to allocate any buffers. <%d:%d:%d>",
+			 total, m_pool->buff_cur, m_pool->alloc_inc);
 
-		mem_seg = head_seg;
-		head_seg = mem_seg->head.next;
-
-		result = _sdp_buff_pool_seg_release(mem_seg);
-		TS_EXPECT(MOD_LNX_SDP, !(0 > result));
+		return -ENOMEM;
 	}
 
-	return -ENOMEM;
+	return 0;
 } /* _sdp_buff_pool_alloc */
 
 /* ========================================================================= */
 /*..sdp_buff_pool_init - Initialize the main buffer pool of memory */
-int sdp_buff_pool_init(u32 buff_min, u32 buff_max)
+int sdp_buff_pool_init(int buff_min, 
+		       int buff_max,
+		       int alloc_inc,
+		       int free_mark)
 {
 	int result;
 
@@ -692,17 +653,20 @@
 		return -EEXIST;
 	}
 
-	if (!(0 < buff_min) || buff_max < buff_min) {
+	if (!(0 < buff_min) ||
+	    !(0 < alloc_inc) ||
+	    !(0 < free_mark) ||
+	    buff_max < buff_min) {
 
 		TS_TRACE(MOD_LNX_SDP, T_TERSE, TRACE_FLOW_FATAL,
-			 "BUFFER: Pool allocation count error. <%d:%d>",
-			 buff_min, buff_max);
+			 "BUFFER: Pool allocation count error. <%d:%d:%d:%d>",
+			 buff_min, buff_max, alloc_inc, free_mark);
 		return -ERANGE;
 	}
 	/*
 	 * allocate the main pool structures
 	 */
-	main_pool = kmalloc(sizeof(tSDP_MAIN_POOL_STRUCT), GFP_KERNEL);
+	main_pool = kmalloc(sizeof(struct sdpc_buff_root), GFP_KERNEL);
 	if (NULL == main_pool) {
 
 		TS_TRACE(MOD_LNX_SDP, T_TERSE, TRACE_FLOW_FATAL,
@@ -711,18 +675,20 @@
 		goto done;
 	}
 
-	memset(main_pool, 0, sizeof(tSDP_MAIN_POOL_STRUCT));
+	memset(main_pool, 0, sizeof(struct sdpc_buff_root));
 
 	main_pool->buff_size = PAGE_SIZE;
-	main_pool->buff_min = buff_min;
-	main_pool->buff_max = buff_max;
+	main_pool->buff_min  = buff_min;
+	main_pool->buff_max  = buff_max;
+	main_pool->alloc_inc = alloc_inc;
+	main_pool->free_mark = free_mark;
 
 	spin_lock_init(&main_pool->lock);
 
 	result = sdp_buff_q_init(&main_pool->pool, _main_pool_name, 0);
 	TS_EXPECT(MOD_LNX_SDP, !(0 > result));
 
-	main_pool->pool_cache = kmem_cache_create("SdpBuffPool",
+	main_pool->pool_cache = kmem_cache_create("sdp_buff_pool",
 						  sizeof(struct sdpc_buff_q),
 						  0, SLAB_HWCACHE_ALIGN,
 						  NULL, NULL);
@@ -733,10 +699,22 @@
 		result = -ENOMEM;
 		goto error_pool;
 	}
+
+	main_pool->buff_cache = kmem_cache_create("sdp_buff_desc",
+						  sizeof(struct sdpc_buff),
+						  0, SLAB_HWCACHE_ALIGN,
+						  NULL, NULL);
+	if (NULL == main_pool->buff_cache) {
+
+		TS_TRACE(MOD_LNX_SDP, T_TERSE, TRACE_FLOW_FATAL,
+			 "BUFFER: Failed to allocate buffer cache.");
+		result = -ENOMEM;
+		goto error_buff;
+	} /* if */
 	/*
 	 * allocate the minimum number of buffers.
 	 */
-	result = _sdp_buff_pool_alloc(main_pool, buff_min);
+	result = _sdp_buff_pool_alloc(main_pool);
 	if (0 > result) {
 
 		TS_TRACE(MOD_LNX_SDP, T_TERSE, TRACE_FLOW_FATAL,
@@ -753,6 +731,8 @@
 
 	return 0;		/* success */
 error_alloc:
+	kmem_cache_destroy(main_pool->buff_cache);
+error_buff:
 	kmem_cache_destroy(main_pool->pool_cache);
 error_pool:
 	kfree(main_pool);
@@ -772,13 +752,23 @@
 		return;
 	}
 	/*
-	 * Free all the memory regions
+	 * Free all the buffers.
 	 */
-	(void)_sdp_buff_pool_seg_release_all(main_pool);
+	(void)_sdp_buff_pool_release(main_pool, main_pool->buff_cur);
 	/*
+	 * Sanity check that the current number of buffers was released.
+	 */
+	if (main_pool->buff_cur) {
+		
+		TS_TRACE(MOD_LNX_SDP, T_TERSE, TRACE_FLOW_CLEANUP,
+			 "BUFFER: Leaking buffers during cleanup. <%d>", 
+			 main_pool->buff_cur);
+	}
+	/*
 	 * free pool cache
 	 */
 	kmem_cache_destroy(main_pool->pool_cache);
+	kmem_cache_destroy(main_pool->buff_cache);
 	/*
 	 * free main
 	 */
@@ -809,14 +799,13 @@
 
 	if (NULL == main_pool->pool.head) {
 
-		result =
-		    _sdp_buff_pool_alloc(main_pool, TS_SDP_BUFFER_COUNT_INC);
+		result = _sdp_buff_pool_alloc(main_pool);
 		if (0 > result) {
 
 			TS_TRACE(MOD_LNX_SDP, T_TERSE, TRACE_FLOW_FATAL,
 				 "BUFFER: Error <%d> allocating buffers.",
 				 result);
-
+			
 			spin_unlock_irqrestore(&main_pool->lock, flags);
 			return NULL;
 		}
@@ -899,6 +888,8 @@
 
 	main_pool->pool.size++;
 
+	(void)_sdp_buff_pool_release_check(main_pool);
+
 	spin_unlock_irqrestore(&main_pool->lock, flags);
 
 	return 0;
@@ -972,6 +963,8 @@
 
 	main_pool->pool.size += count;
 
+	(void)_sdp_buff_pool_release_check(main_pool);
+
 	spin_unlock_irqrestore(&main_pool->lock, flags);
 
 	return 0;
@@ -1021,11 +1014,8 @@
 			    off_t start_index,
 			    long *end_index)
 {
-	tSDP_MEMORY_SEGMENT mem_seg;
-	int buff_count;
-	int offset = 0;
-	int counter;
 	unsigned long flags;
+	int offset = 0;
 
 	TS_CHECK_NULL(buffer, -EINVAL);
 	/*
@@ -1039,19 +1029,22 @@
 
 	if (0 == start_index) {
 
-		offset += sprintf((buffer + offset), "Totals:\n");
-		offset += sprintf((buffer + offset), "-------\n");
-
 		offset += sprintf((buffer + offset), 
 				  "  buffer size:         %8d\n",
 				  main_pool->buff_size);
-		offset += sprintf((buffer + offset), 
+		offset += sprintf((buffer + offset),
 				  "  buffers maximum:     %8d\n",
 				  main_pool->buff_max);
-		offset += sprintf((buffer + offset), 
+		offset += sprintf((buffer + offset),
 				  "  buffers minimum:     %8d\n",
 				  main_pool->buff_min);
 		offset += sprintf((buffer + offset),
+				  "  buffers increment:   %8d\n",
+				  main_pool->alloc_inc);
+		offset += sprintf((buffer + offset),
+				  "  buffers decrement:   %8d\n",
+				  main_pool->free_mark);
+		offset += sprintf((buffer + offset),
 				  "  buffers allocated:   %8d\n",
 				  main_pool->buff_cur);
 		offset += sprintf((buffer + offset),
@@ -1060,54 +1053,8 @@
 		offset += sprintf((buffer + offset),
 				  "  buffers outstanding: %8d\n",
 				  main_pool->buff_cur - main_pool->pool.size);
-		offset += sprintf((buffer + offset), "\nBuffers:\n");
-		offset += sprintf((buffer + offset), "--------\n");
-		offset += sprintf((buffer + offset),
-				  "     id    size pool name\n");
-		offset += sprintf((buffer + offset),
-				  "  -------- ---- ----------------\n");
 	}
-	/*
-	 * buffers
-	 */
-	if (!(start_index < main_pool->buff_cur)) {
 
-		goto done;
-	}
-
-	for (counter = 0, buff_count = 0, mem_seg = main_pool->segs;
-	     NULL != mem_seg && TS_SDP_BUFF_OUT_LEN < (max_size - offset);
-	     mem_seg = mem_seg->head.next) {
-
-		for (counter = 0;
-		     counter < mem_seg->head.size &&
-			     TS_SDP_BUFF_OUT_LEN < (max_size - offset);
-		     counter++, buff_count++) {
-
-			if (start_index > buff_count) {
-
-				continue;
-			}
-
-			offset += sprintf((buffer + offset),
-					  "  %08x %04x %-16s\n",
-					  mem_seg->list[counter].u_id,
-					  (int)(mem_seg->list[counter].tail -
-						mem_seg->list[counter].data),
-#ifdef _TS_SDP_DEBUG_POOL_NAME
-					  ((NULL != mem_seg->list[counter].
-					    pool) ? 
-					   mem_seg->list[counter].pool->name :
-					   "<none>")
-#else
-					  "<off>"
-#endif
-				);
-		}
-	}
-
-	*end_index = buff_count - start_index;
-done:
 	spin_unlock_irqrestore(&main_pool->lock, flags);
 
 	return offset;



More information about the general mailing list