SCST Downloads
-The latest stable released version of SCST core is 1.0.1.1. It requires Linux kernel 2.6.16 or higher. +
The latest stable released version of SCST core is 2.0.0. It requires Linux kernel 2.6.18 or higher. More detail information you could find in its README file.
-But at the moment it is recommended to use instead version 2.0-rc3, which you can find in the 2.0.0.x - branch in the SCST SVN. - It has a lot of new features and generally should be more stable. Final 2.0 should be released in the next few weeks.
-You can also download prebuilt SCST modules for Scientific Linux CERN 5 (RHEL5-based), Ubuntu and diff --git a/www/handler_fileio_tgt.html b/www/handler_fileio_tgt.html index 804015e30..d72074081 100644 --- a/www/handler_fileio_tgt.html +++ b/www/handler_fileio_tgt.html @@ -67,7 +67,7 @@ All the words about BLOCKIO mode from SCST's README file apply to O_DIRECT mode as well.
-The latest stable version is 1.0.1.1. Requires SCST version 1.0.1.1 or higher.
+The latest stable version is 2.0.0. Requires SCST version 2.0.0 or higher.
You can find the latest development version of this handler in the SCST SVN. See the download page how to setup access to it.
diff --git a/www/iscsi-scst/index.html b/www/iscsi-scst/index.html index 773e4c05b..80d59f9e1 100644 --- a/www/iscsi-scst/index.html +++ b/www/iscsi-scst/index.html @@ -112,7 +112,7 @@ the SCST core. You can also use a migration tool developed by Scalable Informatics Inc., which will convert your IET machine to an iSCSI-SCST machine. See README for more details.
-The latest stable version is 1.0.1.1. Requires Linux kernel version 2.6.16.x or higher and SCST version 1.0.1.1 or higher. +
The latest stable version is 2.0.0. Requires Linux kernel version 2.6.18.x or higher and SCST version 2.0.0 or higher. Tested mostly on i386 and x86_64, but should work on any other supported by Linux platform.
You can find the latest development version of this driver in the SCST SVN. See the download page how to setup access to it.
diff --git a/www/scst_admin.html b/www/scst_admin.html index 752e080be..1553d2ccc 100644 --- a/www/scst_admin.html +++ b/www/scst_admin.html @@ -66,7 +66,7 @@ scst.conf, then you edit this file, e.g. add new devices, then scstadmin will figure out that you added those devices and add them to SCST. -The latest stable version is 1.0.6.
+The latest stable version is 2.0.0.
Download diff --git a/www/sgv_big_order_alloc-r2.diff b/www/sgv_big_order_alloc-r2.diff deleted file mode 100644 index 1e7ea0409..000000000 --- a/www/sgv_big_order_alloc-r2.diff +++ /dev/null @@ -1,785 +0,0 @@ -Index: scst/include/scst_sgv.h -=================================================================== ---- scst/include/scst_sgv.h (revision 821) -+++ scst/include/scst_sgv.h (working copy) -@@ -58,12 +58,17 @@ void sgv_pool_destroy(struct sgv_pool *p - void sgv_pool_flush(struct sgv_pool *pool); - - void sgv_pool_set_allocator(struct sgv_pool *pool, -- struct page *(*alloc_pages_fn)(struct scatterlist *, gfp_t, void *), -- void (*free_pages_fn)(struct scatterlist *, int, void *)); -+ struct page *(*alloc_pages_fn)(struct scatterlist *sg, -+ gfp_t gfp_mask, int alloc_order, void *priv), -+ void (*free_pages_fn)(struct scatterlist *sg, int sg_count, -+ int alloc_order, void *priv)); -+ -+void sgv_pool_set_max_alloc_order(struct sgv_pool *pool, int max_alloc_order); - - struct scatterlist *sgv_pool_alloc(struct sgv_pool *pool, unsigned int size, - gfp_t gfp_mask, int flags, int *count, -- struct sgv_pool_obj **sgv, struct scst_mem_lim *mem_lim, void *priv); -+ struct sgv_pool_obj **sgv, struct scst_mem_lim *mem_lim, void *priv, -+ int max_sg_count); - void sgv_pool_free(struct sgv_pool_obj *sgv, struct scst_mem_lim *mem_lim); - - void *sgv_get_priv(struct sgv_pool_obj *sgv); -Index: scst/src/scst_mem.h -=================================================================== ---- scst/src/scst_mem.h (revision 821) -+++ scst/src/scst_mem.h (working copy) -@@ -44,6 +44,7 @@ struct sgv_pool_obj { - } recycle_entry; - - struct sgv_pool *owner_pool; -+ int alloc_order; - int orig_sg; - int orig_length; - int sg_count; -@@ -67,14 +68,21 @@ struct sgv_pool_cache_acc { - - struct sgv_pool_alloc_fns { - struct page *(*alloc_pages_fn)(struct scatterlist *sg, gfp_t gfp_mask, -- void *priv); -+ int alloc_order, void *priv); - void (*free_pages_fn)(struct scatterlist *sg, int sg_count, -- void *priv); -+ int alloc_order, void *priv); - }; - - struct sgv_pool { - enum sgv_clustering_types clustering_type; -+ -+ int max_alloc_order; -+ -+#define SGV_POOL_MAX_SG_MISSED 1 -+ unsigned long sgv_pool_flags; -+ - struct sgv_pool_alloc_fns alloc_fns; -+ - /* 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048 */ - struct kmem_cache *caches[SGV_POOL_ELEMENTS]; - -@@ -87,6 +95,7 @@ struct sgv_pool { - /* SCST_MAX_NAME + few more bytes to match scst_user expectations */ - char cache_names[SGV_POOL_ELEMENTS][SCST_MAX_NAME + 10]; - char name[SCST_MAX_NAME + 10]; -+ - struct list_head sgv_pool_list_entry; - }; - -Index: scst/src/scst_lib.c -=================================================================== ---- scst/src/scst_lib.c (revision 821) -+++ scst/src/scst_lib.c (working copy) -@@ -2262,7 +2262,6 @@ int scst_alloc_space(struct scst_cmd *cm - int atomic = scst_cmd_atomic(cmd); - int flags; - struct scst_tgt_dev *tgt_dev = cmd->tgt_dev; -- static int ll; - - TRACE_ENTRY(); - -@@ -2273,40 +2272,25 @@ int scst_alloc_space(struct scst_cmd *cm - flags |= SCST_POOL_ALLOC_NO_CACHED; - - cmd->sg = sgv_pool_alloc(tgt_dev->pool, cmd->bufflen, gfp_mask, flags, -- &cmd->sg_cnt, &cmd->sgv, &cmd->dev->dev_mem_lim, NULL); -+ &cmd->sg_cnt, &cmd->sgv, -+ &cmd->dev->dev_mem_lim, NULL, -+ tgt_dev->max_sg_cnt); - if (cmd->sg == NULL) - goto out; - -- if (unlikely(cmd->sg_cnt > tgt_dev->max_sg_cnt)) { -- if (ll < 10) { -- PRINT_INFO("Unable to complete command due to " -- "SG IO count limitation (requested %d, " -- "available %d, tgt lim %d)", cmd->sg_cnt, -- tgt_dev->max_sg_cnt, cmd->tgt->sg_tablesize); -- ll++; -- } -- goto out_sg_free; -- } -+ EXTRACHECKS_BUG_ON(cmd->sg_cnt > tgt_dev->max_sg_cnt); - - if (cmd->data_direction != SCST_DATA_BIDI) - goto success; - - cmd->in_sg = sgv_pool_alloc(tgt_dev->pool, cmd->in_bufflen, gfp_mask, -- flags, &cmd->in_sg_cnt, &cmd->in_sgv, -- &cmd->dev->dev_mem_lim, NULL); -+ flags, &cmd->in_sg_cnt, &cmd->in_sgv, -+ &cmd->dev->dev_mem_lim, NULL, -+ tgt_dev->max_sg_cnt); - if (cmd->in_sg == NULL) - goto out_sg_free; - -- if (unlikely(cmd->in_sg_cnt > tgt_dev->max_sg_cnt)) { -- if (ll < 10) { -- PRINT_INFO("Unable to complete command due to " -- "SG IO count limitation (IN buffer, requested " -- "%d, available %d, tgt lim %d)", cmd->in_sg_cnt, -- tgt_dev->max_sg_cnt, cmd->tgt->sg_tablesize); -- ll++; -- } -- goto out_in_sg_free; -- } -+ EXTRACHECKS_BUG_ON(cmd->in_sg_cnt > tgt_dev->max_sg_cnt); - - success: - res = 0; -@@ -2315,12 +2299,6 @@ out: - TRACE_EXIT(); - return res; - --out_in_sg_free: -- sgv_pool_free(cmd->in_sgv, &cmd->dev->dev_mem_lim); -- cmd->in_sgv = NULL; -- cmd->in_sg = NULL; -- cmd->in_sg_cnt = 0; -- - out_sg_free: - sgv_pool_free(cmd->sgv, &cmd->dev->dev_mem_lim); - cmd->sgv = NULL; -Index: scst/src/scst_targ.c -=================================================================== ---- scst/src/scst_targ.c (revision 821) -+++ scst/src/scst_targ.c (working copy) -@@ -2066,7 +2066,7 @@ static int scst_do_real_exec(struct scst - res = SCST_EXEC_NEED_THREAD; - goto out_restore; - } else { -- PRINT_ERROR("scst_exec_req() failed: %d", res); -+ PRINT_ERROR("scst_exec_req() failed: %d", rc); - goto out_error; - } - } -Index: scst/src/scst_mem.c -=================================================================== ---- scst/src/scst_mem.c (revision 821) -+++ scst/src/scst_mem.c (working copy) -@@ -168,52 +168,39 @@ out: - } - - static void scst_free_sys_sg_entries(struct scatterlist *sg, int sg_count, -- void *priv) -+ int alloc_order, void *priv) - { - int i; -+ const int num_pages = 1 << alloc_order; - -- TRACE_MEM("sg=%p, sg_count=%d", sg, sg_count); -+ TRACE_MEM("sg=%p, sg_count=%d, alloc_order=%d", sg, sg_count, alloc_order); - - for (i = 0; i < sg_count; i++) { - struct page *p = sg_page(&sg[i]); - int len = sg[i].length; -- int pages = -- (len >> PAGE_SHIFT) + ((len & ~PAGE_MASK) != 0); -+ int pages = (len >> PAGE_SHIFT) + ((len & ~PAGE_MASK) != 0); - - TRACE_MEM("page %lx, len %d, pages %d", - (unsigned long)p, len, pages); - - while (pages > 0) { -- int order = 0; -- --/* -- * __free_pages() doesn't like freeing pages with not that order with -- * which they were allocated, so disable this small optimization. -- */ --#if 0 -- if (len > 0) { -- while (((1 << order) << PAGE_SHIFT) < len) -- order++; -- len = 0; -- } --#endif - TRACE_MEM("free_pages(): order %d, page %lx", -- order, (unsigned long)p); -+ alloc_order, (unsigned long)p); - -- __free_pages(p, order); -+ __free_pages(p, alloc_order); - -- pages -= 1 << order; -- p += 1 << order; -+ pages -= num_pages; -+ p += num_pages; - } - } - } - - static struct page *scst_alloc_sys_pages(struct scatterlist *sg, -- gfp_t gfp_mask, void *priv) -+ gfp_t gfp_mask, int alloc_order, void *priv) - { -- struct page *page = alloc_pages(gfp_mask, 0); -+ struct page *page = alloc_pages(gfp_mask, alloc_order); - -- sg_set_page(sg, page, PAGE_SIZE, 0); -+ sg_set_page(sg, page, PAGE_SIZE << alloc_order, 0); - TRACE_MEM("page=%p, sg=%p, priv=%p", page, sg, priv); - if (page == NULL) { - TRACE(TRACE_OUT_OF_MEM, "%s", "Allocation of " -@@ -225,13 +212,15 @@ static struct page *scst_alloc_sys_pages - static int scst_alloc_sg_entries(struct scatterlist *sg, int pages, - gfp_t gfp_mask, enum sgv_clustering_types clustering_type, - struct trans_tbl_ent *trans_tbl, -- const struct sgv_pool_alloc_fns *alloc_fns, void *priv) -+ const struct sgv_pool_alloc_fns *alloc_fns, int alloc_order, -+ void *priv) - { - int sg_count = 0; - int pg, i, j; - int merged = -1; - -- TRACE_MEM("pages=%d, clustering_type=%d", pages, clustering_type); -+ TRACE_MEM("pages=%d, clustering_type=%d, alloc_order=%d", pages, -+ clustering_type, alloc_order); - - #if 0 - gfp_mask |= __GFP_COLD; -@@ -240,7 +229,7 @@ static int scst_alloc_sg_entries(struct - gfp_mask |= __GFP_ZERO; - #endif - -- for (pg = 0; pg < pages; pg++) { -+ for (pg = 0; pg < pages; pg += 1 << alloc_order) { - void *rc; - #ifdef CONFIG_SCST_DEBUG_OOM - if (((gfp_mask & __GFP_NOFAIL) != __GFP_NOFAIL) && -@@ -249,7 +238,7 @@ static int scst_alloc_sg_entries(struct - else - #endif - rc = alloc_fns->alloc_pages_fn(&sg[sg_count], gfp_mask, -- priv); -+ alloc_order, priv); - if (rc == NULL) - goto out_no_mem; - -@@ -263,8 +252,8 @@ static int scst_alloc_sg_entries(struct - if (merged == -1) - sg_count++; - -- TRACE_MEM("pg=%d, merged=%d, sg_count=%d", pg, merged, -- sg_count); -+ TRACE_MEM("pg=%d, merged=%d, sg_count=%d", -+ pg, merged, sg_count); - } - - if ((clustering_type != sgv_no_clustering) && (trans_tbl != NULL)) { -@@ -285,7 +274,7 @@ out: - return sg_count; - - out_no_mem: -- alloc_fns->free_pages_fn(sg, sg_count, priv); -+ alloc_fns->free_pages_fn(sg, sg_count, alloc_order, priv); - sg_count = 0; - goto out; - } -@@ -346,9 +335,11 @@ out_free: - - static void sgv_dtor_and_free(struct sgv_pool_obj *obj) - { -+ TRACE_MEM("Destroing obj %p", obj); -+ - if (obj->sg_count != 0) { - obj->owner_pool->alloc_fns.free_pages_fn(obj->sg_entries, -- obj->sg_count, obj->allocator_priv); -+ obj->sg_count, obj->alloc_order, obj->allocator_priv); - } - if (obj->sg_entries != obj->sg_entries_data) { - if (obj->trans_tbl != -@@ -364,53 +355,59 @@ static void sgv_dtor_and_free(struct sgv - return; - } - --static struct sgv_pool_obj *sgv_pool_cached_get(struct sgv_pool *pool, -- int order, gfp_t gfp_mask) -+static struct sgv_pool_obj *sgv_cached_obj_get(struct sgv_pool *pool, -+ int order, gfp_t gfp_mask, int max_sg_count) - { - struct sgv_pool_obj *obj; - int pages = 1 << order; - - spin_lock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); -- if (likely(!list_empty(&pool->recycling_lists[order]))) { -- obj = list_entry(pool->recycling_lists[order].next, -- struct sgv_pool_obj, -- recycle_entry.recycling_list_entry); - -- list_del(&obj->recycle_entry.sorted_recycling_list_entry); -- list_del(&obj->recycle_entry.recycling_list_entry); -+ if (!list_empty(&pool->recycling_lists[order])) { -+ list_for_each_entry(obj, &pool->recycling_lists[order], -+ recycle_entry.recycling_list_entry) { - -- sgv_pools_mgr.mgr.throttle.inactive_pages_total -= pages; -- sgv_pools_mgr.mgr.throttle.active_pages_total += pages; -+ TRACE_MEM("obj %p, sg_count %d (max %d)", obj, -+ obj->sg_count, max_sg_count); - -- spin_unlock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); -+ if (unlikely(obj->sg_count > max_sg_count)) -+ continue; - -- EXTRACHECKS_BUG_ON(obj->order_or_pages != order); -- goto out; -- } -+ list_del(&obj->recycle_entry.sorted_recycling_list_entry); -+ list_del(&obj->recycle_entry.recycling_list_entry); - -- pool->acc.cached_entries++; -- pool->acc.cached_pages += pages; -+ sgv_pools_mgr.mgr.throttle.inactive_pages_total -= pages; -+ sgv_pools_mgr.mgr.throttle.active_pages_total += pages; - -- spin_unlock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); -+ spin_unlock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); - -- obj = kmem_cache_alloc(pool->caches[order], -- gfp_mask & ~(__GFP_HIGHMEM|GFP_DMA)); -- if (likely(obj)) { -- memset(obj, 0, sizeof(*obj)); -- obj->order_or_pages = order; -- obj->owner_pool = pool; -+ EXTRACHECKS_BUG_ON(obj->order_or_pages != order); -+ break; -+ } - } else { -- spin_lock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); -- pool->acc.cached_entries--; -- pool->acc.cached_pages -= pages; -+ pool->acc.cached_entries++; -+ pool->acc.cached_pages += pages; -+ - spin_unlock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); -+ -+ obj = kmem_cache_alloc(pool->caches[order], -+ gfp_mask & ~(__GFP_HIGHMEM|GFP_DMA)); -+ if (likely(obj != NULL)) { -+ memset(obj, 0, sizeof(*obj)); -+ obj->order_or_pages = order; -+ obj->owner_pool = pool; -+ } else { -+ spin_lock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); -+ pool->acc.cached_entries--; -+ pool->acc.cached_pages -= pages; -+ spin_unlock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); -+ } - } - --out: - return obj; - } - --static void sgv_pool_cached_put(struct sgv_pool_obj *sgv) -+static void sgv_cached_obj_put(struct sgv_pool_obj *sgv) - { - struct sgv_pool *owner = sgv->owner_pool; - struct list_head *entry; -@@ -464,7 +461,7 @@ static void sgv_pool_cached_put(struct s - } - - /* Must be called under pool_mgr_lock held */ --static void __sgv_pool_cached_purge(struct sgv_pool_obj *e) -+static void __sgv_cached_purge_obj(struct sgv_pool_obj *e) - { - int pages = 1 << e->order_or_pages; - -@@ -478,13 +475,13 @@ static void __sgv_pool_cached_purge(stru - } - - /* Must be called under pool_mgr_lock held */ --static int sgv_pool_cached_purge(struct sgv_pool_obj *e, int t, -+static int sgv_cached_purge_obj(struct sgv_pool_obj *e, int t, - unsigned long rt) - { - EXTRACHECKS_BUG_ON(t == 0); - - if (time_after(rt, (e->recycle_entry.time_stamp + t))) { -- __sgv_pool_cached_purge(e); -+ __sgv_cached_purge_obj(e); - return 0; - } - return 1; -@@ -507,7 +504,7 @@ static int sgv_pool_oom_free_objs(int pg - struct sgv_pool_obj, - recycle_entry.sorted_recycling_list_entry); - -- __sgv_pool_cached_purge(e); -+ __sgv_cached_purge_obj(e); - pgs -= 1 << e->order_or_pages; - - spin_unlock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); -@@ -602,12 +599,13 @@ static void scst_uncheck_allowed_mem(str - - struct scatterlist *sgv_pool_alloc(struct sgv_pool *pool, unsigned int size, - gfp_t gfp_mask, int flags, int *count, -- struct sgv_pool_obj **sgv, struct scst_mem_lim *mem_lim, void *priv) -+ struct sgv_pool_obj **sgv, struct scst_mem_lim *mem_lim, void *priv, -+ int max_sg_count) - { - struct sgv_pool_obj *obj; - int order, pages, cnt; - struct scatterlist *res = NULL; -- int pages_to_alloc; -+ int pages_to_alloc, alloc_order; - struct kmem_cache *cache; - int no_cached = flags & SCST_POOL_ALLOC_NO_CACHED; - bool allowed_mem_checked = false, hiwmk_checked = false; -@@ -643,7 +641,10 @@ struct scatterlist *sgv_pool_alloc(struc - if (unlikely(sgv_pool_hiwmk_check(pages_to_alloc) != 0)) - goto out_fail_free_sg_entries; - hiwmk_checked = true; -- } else if ((order < SGV_POOL_ELEMENTS) && !no_cached) { -+ goto alloc; -+ } -+ -+ if ((order < SGV_POOL_ELEMENTS) && !no_cached) { - pages_to_alloc = (1 << order); - cache = pool->caches[order]; - -@@ -651,7 +652,7 @@ struct scatterlist *sgv_pool_alloc(struc - goto out_fail; - allowed_mem_checked = true; - -- obj = sgv_pool_cached_get(pool, order, gfp_mask); -+ obj = sgv_cached_obj_get(pool, order, gfp_mask, max_sg_count); - if (unlikely(obj == NULL)) { - TRACE(TRACE_OUT_OF_MEM, "Allocation of " - "sgv_pool_obj failed (size %d)", size); -@@ -659,7 +660,8 @@ struct scatterlist *sgv_pool_alloc(struc - } - - if (obj->sg_count != 0) { -- TRACE_MEM("Cached sgv_obj %p", obj); -+ TRACE_MEM("Cached sgv_obj %p (order_or_pages %d, " -+ "order %d)", obj, obj->order_or_pages, order); - EXTRACHECKS_BUG_ON(obj->order_or_pages != order); - atomic_inc(&pool->cache_acc[order].hit_alloc); - goto success; -@@ -738,15 +740,73 @@ struct scatterlist *sgv_pool_alloc(struc - TRACE_MEM("Big or no_cached sgv_obj %p (size %d)", obj, sz); - } - -- obj->sg_count = scst_alloc_sg_entries(obj->sg_entries, -- pages_to_alloc, gfp_mask, pool->clustering_type, -- obj->trans_tbl, &pool->alloc_fns, priv); -- if (unlikely(obj->sg_count <= 0)) { -- obj->sg_count = 0; -- if ((flags & SCST_POOL_RETURN_OBJ_ON_ALLOC_FAIL) && cache) -- goto out_return1; -- else -+alloc: -+ /* -+ * Allocate the scatter gather entries. Since the memory we -+ * request may fit in too many entries, we try to start with -+ * an order big enough. That will save some useless -+ * allocations. -+ */ -+ alloc_order = 0; -+ if (pages_to_alloc > max_sg_count) { -+ if (test_bit(SGV_POOL_MAX_SG_MISSED, &pool->sgv_pool_flags)) { -+ int tmp = pages_to_alloc; -+ do { -+ tmp >>= 1; -+ alloc_order++; -+ } while (tmp > max_sg_count); -+ -+ /* Let's hope for clustering */ -+ if ((cache != NULL) && -+ (pool->clustering_type != sgv_no_clustering)) -+ alloc_order--; -+ -+ if (alloc_order > pool->max_alloc_order) -+ alloc_order = pool->max_alloc_order; -+ } -+ } -+ -+ TRACE_MEM("Starting alloc order %d", alloc_order); -+ -+ while (1) { -+ obj->sg_count = scst_alloc_sg_entries(obj->sg_entries, -+ pages_to_alloc, gfp_mask, pool->clustering_type, -+ obj->trans_tbl, &pool->alloc_fns, alloc_order, priv); -+ if (unlikely(obj->sg_count <= 0)) { -+ obj->sg_count = 0; -+ if ((cache != NULL) && -+ (flags & SCST_POOL_RETURN_OBJ_ON_ALLOC_FAIL)) -+ goto out_return1; -+ else -+ goto out_fail_free_sg_entries; -+ } -+ -+ obj->alloc_order = alloc_order; -+ -+ if (likely(obj->sg_count <= max_sg_count)) -+ break; -+ -+ set_bit(SGV_POOL_MAX_SG_MISSED, &pool->sgv_pool_flags); -+ -+ obj->owner_pool->alloc_fns.free_pages_fn(obj->sg_entries, -+ obj->sg_count, obj->alloc_order, obj->allocator_priv); -+ alloc_order++; -+ -+ TRACE_MEM("Too many sg_count %d (max %d), trying next order %d " -+ "(max order %d)", obj->sg_count, max_sg_count, -+ alloc_order, pool->max_alloc_order); -+ -+ if (alloc_order > pool->max_alloc_order) { -+ static int ll; -+ if (ll < 20) { -+ PRINT_INFO("Unable to make %d segments " -+ "allocation, max order %d exceeded " -+ "(size %d)", max_sg_count, -+ alloc_order-1, size); -+ ll++; -+ } - goto out_fail_free_sg_entries; -+ } - } - - if (cache) { -@@ -773,7 +833,7 @@ success: - if (sgv_pool_clustered(pool)) - cnt = obj->trans_tbl[pages-1].sg_num; - else -- cnt = pages; -+ cnt = obj->sg_count; - sg = cnt-1; - obj->orig_sg = sg; - obj->orig_length = obj->sg_entries[sg].length; -@@ -831,9 +891,13 @@ out_fail_free_sg_entries: - } - - out_fail_free: -- if (cache) -- sgv_pool_cached_put(obj); -- else -+ if (cache) { -+ spin_lock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); -+ pool->acc.cached_entries--; -+ pool->acc.cached_pages -= pages_to_alloc; -+ spin_unlock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); -+ kmem_cache_free(pool->caches[obj->order_or_pages], obj); -+ } else - kfree(obj); - - out_fail: -@@ -868,10 +932,10 @@ void sgv_pool_free(struct sgv_pool_obj * - if (sgv->order_or_pages >= 0) { - sgv->sg_entries[sgv->orig_sg].length = sgv->orig_length; - pages = (sgv->sg_count != 0) ? 1 << sgv->order_or_pages : 0; -- sgv_pool_cached_put(sgv); -+ sgv_cached_obj_put(sgv); - } else { - sgv->owner_pool->alloc_fns.free_pages_fn(sgv->sg_entries, -- sgv->sg_count, sgv->allocator_priv); -+ sgv->sg_count, sgv->alloc_order, sgv->allocator_priv); - pages = (sgv->sg_count != 0) ? -sgv->order_or_pages : 0; - kfree(sgv); - sgv_pool_hiwmk_uncheck(pages); -@@ -924,7 +988,7 @@ struct scatterlist *scst_alloc(int size, - * So, always don't use clustering. - */ - *count = scst_alloc_sg_entries(res, pages, gfp_mask, sgv_no_clustering, -- NULL, &sys_alloc_fns, NULL); -+ NULL, &sys_alloc_fns, 0, NULL); - if (*count <= 0) - goto out_free; - -@@ -951,7 +1015,7 @@ void scst_free(struct scatterlist *sg, i - - sgv_pool_hiwmk_uncheck(count); - -- scst_free_sys_sg_entries(sg, count, NULL); -+ scst_free_sys_sg_entries(sg, count, 0, NULL); - kfree(sg); - return; - } -@@ -983,6 +1047,14 @@ int sgv_pool_init(struct sgv_pool *pool, - atomic_set(&pool->acc.big_merged, 0); - - pool->clustering_type = clustering_type; -+ if (clustering_type == sgv_no_clustering) { -+ /* -+ * No clustering means always single page entries. For -+ * instance, iSCSI-SCST requires that. -+ */ -+ pool->max_alloc_order = 0; -+ } else -+ pool->max_alloc_order = 0x0FFF; /* infinity */ - pool->alloc_fns.alloc_pages_fn = scst_alloc_sys_pages; - pool->alloc_fns.free_pages_fn = scst_free_sys_sg_entries; - -@@ -1102,7 +1174,7 @@ void sgv_pool_flush(struct sgv_pool *poo - struct sgv_pool_obj, - recycle_entry.recycling_list_entry); - -- __sgv_pool_cached_purge(e); -+ __sgv_cached_purge_obj(e); - spin_unlock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); - - EXTRACHECKS_BUG_ON(e->owner_pool != pool); -@@ -1141,8 +1213,10 @@ void sgv_pool_deinit(struct sgv_pool *po - } - - void sgv_pool_set_allocator(struct sgv_pool *pool, -- struct page *(*alloc_pages_fn)(struct scatterlist *, gfp_t, void *), -- void (*free_pages_fn)(struct scatterlist *, int, void *)) -+ struct page *(*alloc_pages_fn)(struct scatterlist *sg, -+ gfp_t gfp_mask, int alloc_order, void *priv), -+ void (*free_pages_fn)(struct scatterlist *sg, int sg_count, -+ int alloc_order, void *priv)) - { - pool->alloc_fns.alloc_pages_fn = alloc_pages_fn; - pool->alloc_fns.free_pages_fn = free_pages_fn; -@@ -1150,6 +1224,12 @@ void sgv_pool_set_allocator(struct sgv_p - } - EXPORT_SYMBOL(sgv_pool_set_allocator); - -+void sgv_pool_set_max_alloc_order(struct sgv_pool *pool, int max_alloc_order) -+{ -+ pool->max_alloc_order = max_alloc_order; -+} -+EXPORT_SYMBOL(sgv_pool_set_max_alloc_order); -+ - struct sgv_pool *sgv_pool_create(const char *name, - enum sgv_clustering_types clustering_type) - { -@@ -1206,7 +1286,7 @@ static int sgv_pool_cached_shrinker(int - struct sgv_pool_obj, - recycle_entry.sorted_recycling_list_entry); - -- if (sgv_pool_cached_purge(e, SHRINK_TIME_AFTER, rt) == 0) { -+ if (sgv_cached_purge_obj(e, SHRINK_TIME_AFTER, rt) == 0) { - nr -= 1 << e->order_or_pages; - spin_unlock_bh( - &sgv_pools_mgr.mgr.pool_mgr_lock); -@@ -1228,7 +1308,7 @@ static int sgv_pool_cached_shrinker(int - return nr; - } - --static void sgv_pool_cached_pitbool(void *p) -+static void sgv_purge_work(void *p) - { - u32 total_pages; - struct sgv_pool_obj *e; -@@ -1245,7 +1325,7 @@ static void sgv_pool_cached_pitbool(void - struct sgv_pool_obj, - recycle_entry.sorted_recycling_list_entry); - -- if (sgv_pool_cached_purge(e, PURGE_TIME_AFTER, rt) == 0) { -+ if (sgv_cached_purge_obj(e, PURGE_TIME_AFTER, rt) == 0) { - spin_unlock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); - sgv_dtor_and_free(e); - spin_lock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock); -@@ -1304,9 +1384,9 @@ int scst_sgv_pools_init(unsigned long me - - #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)) - INIT_DELAYED_WORK(&pools->mgr.apit_pool, -- (void (*)(struct work_struct *))sgv_pool_cached_pitbool); -+ (void (*)(struct work_struct *))sgv_purge_work); - #else -- INIT_WORK(&pools->mgr.apit_pool, sgv_pool_cached_pitbool, NULL); -+ INIT_WORK(&pools->mgr.apit_pool, sgv_purge_work, NULL); - #endif - - #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23)) -Index: scst/src/dev_handlers/scst_user.c -=================================================================== ---- scst/src/dev_handlers/scst_user.c (revision 821) -+++ scst/src/dev_handlers/scst_user.c (working copy) -@@ -169,9 +169,9 @@ static int dev_user_disk_done(struct scs - static int dev_user_tape_done(struct scst_cmd *cmd); - - static struct page *dev_user_alloc_pages(struct scatterlist *sg, -- gfp_t gfp_mask, void *priv); -+ gfp_t gfp_mask, int alloc_order, void *priv); - static void dev_user_free_sg_entries(struct scatterlist *sg, int sg_count, -- void *priv); -+ int alloc_order, void *priv); - - static void dev_user_add_to_ready(struct scst_user_cmd *ucmd); - -@@ -366,7 +366,7 @@ static void dev_user_free_ucmd(struct sc - } - - static struct page *dev_user_alloc_pages(struct scatterlist *sg, -- gfp_t gfp_mask, void *priv) -+ gfp_t gfp_mask, int alloc_order, void *priv) - { - struct scst_user_cmd *ucmd = (struct scst_user_cmd *)priv; - int offset = 0; -@@ -375,8 +375,10 @@ static struct page *dev_user_alloc_pages - - /* *sg supposed to be zeroed */ - -- TRACE_MEM("ucmd %p, ubuff %lx, ucmd->cur_data_page %d", ucmd, -- ucmd->ubuff, ucmd->cur_data_page); -+ TRACE_MEM("ucmd %p, ubuff %lx, ucmd->cur_data_page %d, alloc_order %d", -+ ucmd, ucmd->ubuff, ucmd->cur_data_page, alloc_order); -+ -+ EXTRACHECKS_BUG_ON(alloc_order != 0); - - if (ucmd->cur_data_page == 0) { - TRACE_MEM("ucmd->first_page_offset %d", -@@ -469,7 +471,7 @@ static void __dev_user_free_sg_entries(s - } - - static void dev_user_free_sg_entries(struct scatterlist *sg, int sg_count, -- void *priv) -+ int alloc_order, void *priv) - { - struct scst_user_cmd *ucmd = (struct scst_user_cmd *)priv; - -@@ -558,7 +560,8 @@ static int dev_user_alloc_sg(struct scst - ucmd->buff_cached = cached_buff; - - cmd->sg = sgv_pool_alloc(pool, bufflen, gfp_mask, flags, &cmd->sg_cnt, -- &ucmd->sgv, &dev->udev_mem_lim, ucmd); -+ &ucmd->sgv, &dev->udev_mem_lim, ucmd, -+ cmd->tgt_dev->max_sg_cnt); - if (cmd->sg != NULL) { - struct scst_user_cmd *buf_ucmd = - (struct scst_user_cmd *)sgv_get_priv(ucmd->sgv); -@@ -589,21 +592,6 @@ static int dev_user_alloc_sg(struct scst - TRACE_MEM("cmd %p, in_sg %p, in_sg_cnt %d, sg_cnt %d", - cmd, cmd->in_sg, cmd->in_sg_cnt, cmd->sg_cnt); - } -- -- if (unlikely(cmd->sg_cnt > cmd->tgt_dev->max_sg_cnt)) { -- static int ll; -- if (ll < 10) { -- PRINT_INFO("Unable to complete command due to " -- "SG IO count limitation (requested %d, " -- "available %d, tgt lim %d)", -- cmd->sg_cnt, cmd->tgt_dev->max_sg_cnt, -- cmd->tgt->sg_tablesize); -- ll++; -- } -- cmd->sg = NULL; -- /* sgv will be freed in dev_user_free_sgv() */ -- res = -1; -- } - } else { - TRACE_MEM("Buf not alloced (ucmd %p, h %d, buff_cached, %d, " - "sg_cnt %d, ubuff %lx, sgv %p", ucmd, ucmd->h, -@@ -2713,6 +2701,7 @@ static int dev_user_register_dev(struct - goto out_free_dev; - sgv_pool_set_allocator(dev->pool, dev_user_alloc_pages, - dev_user_free_sg_entries); -+ sgv_pool_set_max_alloc_order(dev->pool, 0); - - scnprintf(dev->devtype.name, sizeof(dev->devtype.name), "%s-clust", - dev->name); -@@ -2722,6 +2711,7 @@ static int dev_user_register_dev(struct - goto out_free0; - sgv_pool_set_allocator(dev->pool_clust, dev_user_alloc_pages, - dev_user_free_sg_entries); -+ sgv_pool_set_max_alloc_order(dev->pool_clust, 0); - - scnprintf(dev->devtype.name, sizeof(dev->devtype.name), "dh-%s", - dev->name); diff --git a/www/sgv_big_order_alloc-sfw4.diff b/www/sgv_big_order_alloc-sfw5-rc3.diff similarity index 56% rename from www/sgv_big_order_alloc-sfw4.diff rename to www/sgv_big_order_alloc-sfw5-rc3.diff index a7c6160de..132d2dde4 100644 --- a/www/sgv_big_order_alloc-sfw4.diff +++ b/www/sgv_big_order_alloc-sfw5-rc3.diff @@ -1,54 +1,55 @@ Index: scst/include/scst_sgv.h =================================================================== ---- scst/include/scst_sgv.h (revision 896) +--- scst/include/scst_sgv.h (revision 3134) +++ scst/include/scst_sgv.h (working copy) -@@ -57,12 +57,13 @@ +@@ -82,12 +82,14 @@ void sgv_pool_put(struct sgv_pool *pool) void sgv_pool_flush(struct sgv_pool *pool); void sgv_pool_set_allocator(struct sgv_pool *pool, - struct page *(*alloc_pages_fn)(struct scatterlist *, gfp_t, void *), - void (*free_pages_fn)(struct scatterlist *, int, void *)); -+ struct page *(*alloc_pages_fn)(struct scatterlist *, gfp_t, int, void *), -+ void (*free_pages_fn)(struct scatterlist *, int, int, void *)); ++ struct page *(*alloc_pages_fn)(struct scatterlist *, ++ gfp_t, int, void *), ++ void (*free_pages_fn)(struct scatterlist *, int, int, void *)); struct scatterlist *sgv_pool_alloc(struct sgv_pool *pool, unsigned int size, gfp_t gfp_mask, int flags, int *count, - struct sgv_pool_obj **sgv, struct scst_mem_lim *mem_lim, void *priv); -+ struct sgv_pool_obj **sgv, struct scst_mem_lim *mem_lim, void *priv, -+ int max_sg_count); ++ struct sgv_pool_obj **sgv, struct scst_mem_lim *mem_lim, void *priv, ++ int max_sg_count); void sgv_pool_free(struct sgv_pool_obj *sgv, struct scst_mem_lim *mem_lim); void *sgv_get_priv(struct sgv_pool_obj *sgv); Index: scst/src/scst_mem.h =================================================================== ---- scst/src/scst_mem.h (revision 896) +--- scst/src/scst_mem.h (revision 3134) +++ scst/src/scst_mem.h (working copy) -@@ -35,6 +35,8 @@ - /* if <0 - pages, >0 - order */ - int order_or_pages; +@@ -37,6 +37,8 @@ struct sgv_pool_obj { + int cache_num; + int pages; + int alloc_order; + /* jiffies, protected by sgv_pool_lock */ unsigned long time_stamp; -@@ -58,9 +60,9 @@ - +@@ -66,9 +68,9 @@ struct sgv_pool_cache_acc { + */ struct sgv_pool_alloc_fns { struct page *(*alloc_pages_fn)(struct scatterlist *sg, gfp_t gfp_mask, - void *priv); -+ int alloc_order, void *priv); ++ int alloc_order, void *priv); void (*free_pages_fn)(struct scatterlist *sg, int sg_count, - void *priv); -+ int alloc_order, void *priv); ++ int alloc_order, void *priv); }; - struct sgv_pool { + /* Index: scst/src/scst_lib.c =================================================================== ---- scst/src/scst_lib.c (revision 896) +--- scst/src/scst_lib.c (revision 3134) +++ scst/src/scst_lib.c (working copy) -@@ -2265,7 +2265,6 @@ +@@ -4454,7 +4454,6 @@ int scst_alloc_space(struct scst_cmd *cm int atomic = scst_cmd_atomic(cmd); int flags; struct scst_tgt_dev *tgt_dev = cmd->tgt_dev; @@ -56,19 +57,18 @@ Index: scst/src/scst_lib.c TRACE_ENTRY(); -@@ -2276,40 +2275,25 @@ - flags |= SCST_POOL_ALLOC_NO_CACHED; +@@ -4465,40 +4464,23 @@ int scst_alloc_space(struct scst_cmd *cm + flags |= SGV_POOL_ALLOC_NO_CACHED; cmd->sg = sgv_pool_alloc(tgt_dev->pool, cmd->bufflen, gfp_mask, flags, - &cmd->sg_cnt, &cmd->sgv, &cmd->dev->dev_mem_lim, NULL); -+ &cmd->sg_cnt, &cmd->sgv, -+ &cmd->dev->dev_mem_lim, NULL, -+ tgt_dev->max_sg_cnt); ++ &cmd->sg_cnt, &cmd->sgv, &cmd->dev->dev_mem_lim, NULL, ++ tgt_dev->max_sg_cnt); if (cmd->sg == NULL) goto out; - if (unlikely(cmd->sg_cnt > tgt_dev->max_sg_cnt)) { -- if (ll < 10) { +- if ((ll < 10) || TRACING_MINOR()) { - PRINT_INFO("Unable to complete command due to " - "SG IO count limitation (requested %d, " - "available %d, tgt lim %d)", cmd->sg_cnt, @@ -82,98 +82,77 @@ Index: scst/src/scst_lib.c if (cmd->data_direction != SCST_DATA_BIDI) goto success; - cmd->in_sg = sgv_pool_alloc(tgt_dev->pool, cmd->in_bufflen, gfp_mask, - flags, &cmd->in_sg_cnt, &cmd->in_sgv, + cmd->out_sg = sgv_pool_alloc(tgt_dev->pool, cmd->out_bufflen, gfp_mask, + flags, &cmd->out_sg_cnt, &cmd->out_sgv, - &cmd->dev->dev_mem_lim, NULL); -+ &cmd->dev->dev_mem_lim, NULL, -+ tgt_dev->max_sg_cnt); - if (cmd->in_sg == NULL) ++ &cmd->dev->dev_mem_lim, NULL, tgt_dev->max_sg_cnt); + if (cmd->out_sg == NULL) goto out_sg_free; -- if (unlikely(cmd->in_sg_cnt > tgt_dev->max_sg_cnt)) { -- if (ll < 10) { +- if (unlikely(cmd->out_sg_cnt > tgt_dev->max_sg_cnt)) { +- if ((ll < 10) || TRACING_MINOR()) { - PRINT_INFO("Unable to complete command due to " -- "SG IO count limitation (IN buffer, requested " -- "%d, available %d, tgt lim %d)", cmd->in_sg_cnt, +- "SG IO count limitation (OUT buffer, requested " +- "%d, available %d, tgt lim %d)", cmd->out_sg_cnt, - tgt_dev->max_sg_cnt, cmd->tgt->sg_tablesize); - ll++; - } -- goto out_in_sg_free; +- goto out_out_sg_free; - } -+ EXTRACHECKS_BUG_ON(cmd->in_sg_cnt > tgt_dev->max_sg_cnt); ++ EXTRACHECKS_BUG_ON(cmd->out_sg_cnt > tgt_dev->max_sg_cnt); success: res = 0; -@@ -2318,12 +2302,6 @@ +@@ -4507,12 +4489,6 @@ out: TRACE_EXIT(); return res; --out_in_sg_free: -- sgv_pool_free(cmd->in_sgv, &cmd->dev->dev_mem_lim); -- cmd->in_sgv = NULL; -- cmd->in_sg = NULL; -- cmd->in_sg_cnt = 0; +-out_out_sg_free: +- sgv_pool_free(cmd->out_sgv, &cmd->dev->dev_mem_lim); +- cmd->out_sgv = NULL; +- cmd->out_sg = NULL; +- cmd->out_sg_cnt = 0; - out_sg_free: sgv_pool_free(cmd->sgv, &cmd->dev->dev_mem_lim); cmd->sgv = NULL; Index: scst/src/scst_mem.c =================================================================== ---- scst/src/scst_mem.c (revision 896) +--- scst/src/scst_mem.c (revision 3134) +++ scst/src/scst_mem.c (working copy) -@@ -111,7 +111,7 @@ +@@ -110,8 +110,8 @@ static void sgv_dtor_and_free(struct sgv + TRACE_MEM("Destroying sgv obj %p", obj); if (obj->sg_count != 0) { - pool->alloc_fns.free_pages_fn(obj->sg_entries, +- pool->alloc_fns.free_pages_fn(obj->sg_entries, - obj->sg_count, obj->allocator_priv); -+ obj->sg_count, obj->alloc_order, obj->allocator_priv); ++ pool->alloc_fns.free_pages_fn(obj->sg_entries, obj->sg_count, ++ obj->alloc_order, obj->allocator_priv); } if (obj->sg_entries != obj->sg_entries_data) { if (obj->trans_tbl != -@@ -134,8 +134,6 @@ - - TRACE_MEM("Deleting sgv pool %p from the active list", pool); - -- spin_lock_bh(&sgv_pools_lock); -- - next = pool->sgv_active_pools_list_entry.next; - list_del(&pool->sgv_active_pools_list_entry); - -@@ -156,7 +154,6 @@ - } - } - -- spin_unlock_bh(&sgv_pools_lock); - return; - } - -@@ -510,12 +507,13 @@ +@@ -522,11 +522,13 @@ out: } static void sgv_free_sys_sg_entries(struct scatterlist *sg, int sg_count, - void *priv) -+ int alloc_order, void *priv) ++ int alloc_order, void *priv) { int i; + const int num_pages = 1 << alloc_order; -+ -+ TRACE_MEM("sg=%p, sg_count=%d, alloc_order=%d", sg, sg_count, alloc_order); - TRACE_MEM("sg=%p, sg_count=%d", sg, sg_count); -- ++ TRACE_MEM("sg=%p, sg_count=%d, alloc_order=%d", ++ sg, sg_count, alloc_order); + for (i = 0; i < sg_count; i++) { struct page *p = sg_page(&sg[i]); - int len = sg[i].length; -@@ -525,37 +523,24 @@ - TRACE_MEM("page %lx, len %d, pages %d", +@@ -538,36 +540,23 @@ static void sgv_free_sys_sg_entries(stru (unsigned long)p, len, pages); -- while (pages > 0) { + while (pages > 0) { - int order = 0; -+ while (pages > 0) { -+ TRACE_MEM("free_pages(): order %d, page %lx", -+ alloc_order, (unsigned long)p); - +- -/* - * __free_pages() doesn't like freeing pages with not that order with - * which they were allocated, so disable this small optimization. @@ -185,24 +164,25 @@ Index: scst/src/scst_mem.c - len = 0; - } -#endif -- TRACE_MEM("free_pages(): order %d, page %lx", + TRACE_MEM("free_pages(): order %d, page %lx", - order, (unsigned long)p); -- ++ alloc_order, (unsigned long)p); + - __free_pages(p, order); -- ++ __free_pages(p, alloc_order); + - pages -= 1 << order; - p += 1 << order; -+ __free_pages(p, alloc_order); -+ + pages -= num_pages; + p += num_pages; } } } - static struct page *sgv_alloc_sys_pages(struct scatterlist *sg, +-static struct page *sgv_alloc_sys_pages(struct scatterlist *sg, - gfp_t gfp_mask, void *priv) -+ gfp_t gfp_mask, int alloc_order, void *priv) ++static struct page *sgv_alloc_sys_pages(struct scatterlist *sg, gfp_t gfp_mask, ++ int alloc_order, void *priv) { - struct page *page = alloc_pages(gfp_mask, 0); + struct page *page = alloc_pages(gfp_mask, alloc_order); @@ -212,7 +192,7 @@ Index: scst/src/scst_mem.c TRACE_MEM("page=%p, sg=%p, priv=%p", page, sg, priv); if (page == NULL) { TRACE(TRACE_OUT_OF_MEM, "%s", "Allocation of " -@@ -567,7 +552,7 @@ +@@ -579,7 +568,7 @@ static struct page *sgv_alloc_sys_pages( static int sgv_alloc_sg_entries(struct scatterlist *sg, int pages, gfp_t gfp_mask, enum sgv_clustering_types clustering_type, struct trans_tbl_ent *trans_tbl, @@ -221,7 +201,7 @@ Index: scst/src/scst_mem.c { int sg_count = 0; int pg, i, j; -@@ -582,7 +567,7 @@ +@@ -594,7 +583,7 @@ static int sgv_alloc_sg_entries(struct s gfp_mask |= __GFP_ZERO; #endif @@ -230,27 +210,27 @@ Index: scst/src/scst_mem.c void *rc; #ifdef CONFIG_SCST_DEBUG_OOM if (((gfp_mask & __GFP_NOFAIL) != __GFP_NOFAIL) && -@@ -591,7 +576,7 @@ +@@ -603,7 +592,7 @@ static int sgv_alloc_sg_entries(struct s else #endif rc = alloc_fns->alloc_pages_fn(&sg[sg_count], gfp_mask, - priv); -+ alloc_order, priv); ++ alloc_order, priv); if (rc == NULL) goto out_no_mem; -@@ -611,8 +596,8 @@ +@@ -623,8 +612,8 @@ static int sgv_alloc_sg_entries(struct s if (merged == -1) sg_count++; - TRACE_MEM("pg=%d, merged=%d, sg_count=%d", pg, merged, - sg_count); -+ TRACE_MEM("pg=%d, merged=%d, sg_count=%d", -+ pg, merged, sg_count); ++ TRACE_MEM("pg=%d, merged=%d, sg_count=%d", ++ pg, merged, sg_count); } if ((clustering_type != sgv_no_clustering) && (trans_tbl != NULL)) { -@@ -633,7 +618,7 @@ +@@ -645,7 +634,7 @@ out: return sg_count; out_no_mem: @@ -259,106 +239,105 @@ Index: scst/src/scst_mem.c sg_count = 0; goto out; } -@@ -692,33 +677,20 @@ +@@ -704,32 +693,16 @@ out_free: goto out; } --static struct sgv_pool_obj *sgv_get_obj(struct sgv_pool *pool, int order, -- gfp_t gfp_mask) +-static struct sgv_pool_obj *sgv_get_obj(struct sgv_pool *pool, int cache_num, +- int pages, gfp_t gfp_mask, bool get_new) +static struct sgv_pool_obj *sgv_create_obj(struct sgv_pool *pool, -+ int order, gfp_t gfp_mask, bool locked) ++ int cache_num, ++ int pages, gfp_t gfp_mask, ++ int locked) { struct sgv_pool_obj *obj; - int pages = 1 << order; - spin_lock_bh(&pool->sgv_pool_lock); -- if (likely(!list_empty(&pool->recycling_lists[order]))) { -- obj = list_entry(pool->recycling_lists[order].next, +- +- if (unlikely(get_new)) { +- /* Used only for buffers preallocation */ +- goto get_new; +- } +- +- if (likely(!list_empty(&pool->recycling_lists[cache_num]))) { +- obj = list_entry(pool->recycling_lists[cache_num].next, - struct sgv_pool_obj, recycling_list_entry); -+ if (!locked) -+ spin_lock_bh(&pool->sgv_pool_lock); - +- - list_del(&obj->sorted_recycling_list_entry); - list_del(&obj->recycling_list_entry); - - pool->inactive_cached_pages -= pages; - - spin_unlock_bh(&pool->sgv_pool_lock); -- -- EXTRACHECKS_BUG_ON(obj->order_or_pages != order); - goto out; - } -- ++ if (!locked) ++ spin_lock_bh(&pool->sgv_pool_lock); + +-get_new: if (pool->cached_entries == 0) { TRACE_MEM("Adding pool %p to the active list", pool); spin_lock_bh(&sgv_pools_lock); - list_add_tail(&pool->sgv_active_pools_list_entry, -- &sgv_active_pools_list); -+ &sgv_active_pools_list); - spin_unlock_bh(&sgv_pools_lock); - } - -@@ -728,10 +700,10 @@ - spin_unlock_bh(&pool->sgv_pool_lock); - - TRACE_MEM("New cached entries %d (pool %p)", pool->cached_entries, -- pool); -+ pool); - - obj = kmem_cache_alloc(pool->caches[order], -- gfp_mask & ~(__GFP_HIGHMEM|GFP_DMA)); -+ gfp_mask & ~(__GFP_HIGHMEM|GFP_DMA)); - if (likely(obj)) { - memset(obj, 0, sizeof(*obj)); - obj->order_or_pages = order; -@@ -742,6 +714,45 @@ +@@ -759,6 +732,57 @@ get_new: spin_unlock_bh(&pool->sgv_pool_lock); } + return obj; +} + -+static struct sgv_pool_obj *sgv_get_obj(struct sgv_pool *pool, int order, -+ gfp_t gfp_mask, int max_sg_count) ++/* FZ Notes: cache_num == order, and we should have pages = 1 << cache_num. */ ++static struct sgv_pool_obj *sgv_get_obj(struct sgv_pool *pool, int cache_num, ++ int pages, gfp_t gfp_mask, ++ int max_sg_count, bool get_new) +{ + struct sgv_pool_obj *obj; -+ int pages = 1 << order; + + spin_lock_bh(&pool->sgv_pool_lock); + -+ /* Note: this test seems superflous and doesn't buy us anything. */ -+ if (likely(!list_empty(&pool->recycling_lists[order]))) { -+ list_for_each_entry(obj, &pool->recycling_lists[order], -+ recycling_list_entry) { ++ if (unlikely(get_new)) { ++ /* Used only for buffers preallocation */ ++ /* TODO: caller of that should now call ++ * sgv_create_obj, and this will go away. */ ++ goto get_new; ++ } + -+ TRACE_MEM("obj %p, sg_count %d (max %d)", obj, -+ obj->sg_count, max_sg_count); ++ if (likely(!list_empty(&pool->recycling_lists[cache_num]))) { ++ list_for_each_entry(obj, &pool->recycling_lists[cache_num], ++ recycling_list_entry) { + -+ if (unlikely(obj->sg_count > max_sg_count)) -+ continue; ++ TRACE_MEM("obj %p, sg_count %d (max %d)", obj, ++ obj->sg_count, max_sg_count); ++ ++ if (unlikely(obj->sg_count > max_sg_count)) ++ continue; ++ ++ obj = list_entry(pool->recycling_lists[cache_num].next, ++ struct sgv_pool_obj, ++ recycling_list_entry); + -+ obj = list_entry(pool->recycling_lists[order].next, -+ struct sgv_pool_obj, recycling_list_entry); -+ + list_del(&obj->sorted_recycling_list_entry); + list_del(&obj->recycling_list_entry); -+ ++ + pool->inactive_cached_pages -= pages; + + spin_unlock_bh(&pool->sgv_pool_lock); + -+ EXTRACHECKS_BUG_ON(obj->order_or_pages != order); ++ /* FZ: note entirely sure of that check. Need ++ * to investigate. */ ++ /*EXTRACHECKS_BUG_ON(obj->alloc_order <= cache_num);*/ ++ + goto out; + } + } + -+ obj = sgv_create_obj(pool, order, gfp_mask, true); ++get_new: ++ obj = sgv_create_obj(pool, cache_num, pages, gfp_mask, true); + out: return obj; } -@@ -877,15 +888,17 @@ - +@@ -908,14 +932,17 @@ static void sgv_uncheck_allowed_mem(stru + */ struct scatterlist *sgv_pool_alloc(struct sgv_pool *pool, unsigned int size, gfp_t gfp_mask, int flags, int *count, - struct sgv_pool_obj **sgv, struct scst_mem_lim *mem_lim, void *priv) @@ -366,59 +345,59 @@ Index: scst/src/scst_mem.c + int max_sg_count) { struct sgv_pool_obj *obj; - int order, pages, cnt; + int cache_num, pages, cnt; struct scatterlist *res = NULL; -- int pages_to_alloc; -+ int pages_to_alloc, alloc_order; - struct kmem_cache *cache; - int no_cached = flags & SCST_POOL_ALLOC_NO_CACHED; + int pages_to_alloc; ++ int alloc_order; + int no_cached = flags & SGV_POOL_ALLOC_NO_CACHED; bool allowed_mem_checked = false, hiwmk_checked = false; + int tmp; TRACE_ENTRY(); -@@ -926,7 +939,7 @@ - goto out_fail; +@@ -958,7 +985,7 @@ struct scatterlist *sgv_pool_alloc(struc allowed_mem_checked = true; -- obj = sgv_get_obj(pool, order, gfp_mask); -+ obj = sgv_get_obj(pool, order, gfp_mask, max_sg_count); + obj = sgv_get_obj(pool, cache_num, pages_to_alloc, gfp_mask, +- flags & SGV_POOL_ALLOC_GET_NEW); ++ max_sg_count, flags & SGV_POOL_ALLOC_GET_NEW); if (unlikely(obj == NULL)) { TRACE(TRACE_OUT_OF_MEM, "Allocation of " "sgv_pool_obj failed (size %d)", size); -@@ -936,7 +949,29 @@ +@@ -967,7 +994,30 @@ struct scatterlist *sgv_pool_alloc(struc + if (obj->sg_count != 0) { TRACE_MEM("Cached obj %p", obj); - EXTRACHECKS_BUG_ON(obj->order_or_pages != order); -- atomic_inc(&pool->cache_acc[order].hit_alloc); +- atomic_inc(&pool->cache_acc[cache_num].hit_alloc); + + if (unlikely(max_sg_count < obj->sg_count)) { + TRACE_MEM("Too many SG entries %d (max %d)", -+ obj->sg_count, max_sg_count); ++ obj->sg_count, max_sg_count); + + sgv_put_obj(obj); + -+ obj = sgv_create_obj(pool, order, -+ gfp_mask, false); -+ -+ if (obj && unlikely(max_sg_count < obj->sg_count)) { ++ obj = sgv_create_obj(pool, cache_num, ++ pages_to_alloc, gfp_mask, ++ false); ++ if (obj && ++ unlikely(max_sg_count < obj->sg_count)) { + sgv_put_obj(obj); + obj = NULL; + } + + if (obj == NULL) { + TRACE(TRACE_OUT_OF_MEM, "Allocation of " -+ "sgv_pool_obj failed (size %d)", -+ size); ++ "sgv_pool_obj failed (size %d)", ++ size); + goto out_fail; + } + } else -+ atomic_inc(&pool->cache_acc[order].hit_alloc); ++ atomic_inc(&pool->cache_acc[cache_num].hit_alloc); goto success; } -@@ -1013,15 +1048,37 @@ - TRACE_MEM("Big or no_cached obj %p (size %d)", obj, sz); +@@ -1045,16 +1095,44 @@ struct scatterlist *sgv_pool_alloc(struc + TRACE_MEM("Big or no_cached obj %p (size %d)", obj, sz); } - obj->sg_count = sgv_alloc_sg_entries(obj->sg_entries, @@ -426,63 +405,71 @@ Index: scst/src/scst_mem.c - obj->trans_tbl, &pool->alloc_fns, priv); - if (unlikely(obj->sg_count <= 0)) { - obj->sg_count = 0; -- if ((flags & SCST_POOL_RETURN_OBJ_ON_ALLOC_FAIL) && cache) +- if ((flags & SGV_POOL_RETURN_OBJ_ON_ALLOC_FAIL) && +- (cache_num >= 0)) - goto out_return1; - else - goto out_fail_free_sg_entries; + /* Allocate the scatter gather entries. Since the memory we -+ * request may fit in too many entries, we try to start with -+ * an order big enough. That will save some useless ++ * request may fit in too many entries, we try to start with ++ * an order big enough. That will save some useless + * allocations. */ + alloc_order = 0; + tmp = pages_to_alloc; -+ while(tmp > max_sg_count) { ++ while (tmp > max_sg_count) { + tmp >>= 1; + alloc_order++; -+ } ++ } + -+ while (1) { ++ while (1) { + obj->sg_count = sgv_alloc_sg_entries(obj->sg_entries, -+ pages_to_alloc, gfp_mask, pool->clustering_type, -+ obj->trans_tbl, &pool->alloc_fns, alloc_order, priv); ++ pages_to_alloc, ++ gfp_mask, ++ pool->clustering_type, ++ obj->trans_tbl, ++ &pool->alloc_fns, ++ alloc_order, priv); + if (unlikely(obj->sg_count <= 0)) { + obj->sg_count = 0; -+ if ((flags & SCST_POOL_RETURN_OBJ_ON_ALLOC_FAIL) && cache) ++ if ((flags & SGV_POOL_RETURN_OBJ_ON_ALLOC_FAIL) && ++ (cache_num >= 0)) + goto out_return1; + else + goto out_fail_free_sg_entries; + } + -+ obj->alloc_order = alloc_order; ++ obj->alloc_order = alloc_order; + -+ if (likely(obj->sg_count <= max_sg_count)) -+ break; ++ if (likely(obj->sg_count <= max_sg_count)) ++ break; + -+ obj->owner_pool->alloc_fns.free_pages_fn(obj->sg_entries, -+ obj->sg_count, obj->alloc_order, obj->allocator_priv); -+ alloc_order++; ++ obj->owner_pool->alloc_fns.free_pages_fn(obj->sg_entries, ++ obj->sg_count, ++ obj->alloc_order, ++ obj->allocator_priv); ++ alloc_order++; } - if (cache) { -@@ -1150,7 +1207,7 @@ + if (cache_num >= 0) { +@@ -1230,7 +1308,7 @@ void sgv_pool_free(struct sgv_pool_obj * sgv_put_obj(obj); } else { obj->owner_pool->alloc_fns.free_pages_fn(obj->sg_entries, - obj->sg_count, obj->allocator_priv); -+ obj->sg_count, obj->alloc_order, obj->allocator_priv); - pages = (obj->sg_count != 0) ? -obj->order_or_pages : 0; ++ obj->sg_count, obj->alloc_order, obj->allocator_priv); kfree(obj); sgv_hiwmk_uncheck(pages); -@@ -1203,7 +1260,7 @@ - * So, always don't use clustering. + } +@@ -1289,7 +1367,7 @@ struct scatterlist *scst_alloc(int size, + * So, let's always don't use clustering. */ - *count = sgv_alloc_sg_entries(res, pages, gfp_mask, sgv_no_clustering, + cnt = sgv_alloc_sg_entries(res, pages, gfp_mask, sgv_no_clustering, - NULL, &sys_alloc_fns, NULL); -+ NULL, &sys_alloc_fns, 0, NULL); - if (*count <= 0) ++ NULL, &sys_alloc_fns, 0, NULL); + if (cnt <= 0) goto out_free; -@@ -1230,7 +1287,7 @@ +@@ -1326,7 +1404,7 @@ void scst_free(struct scatterlist *sg, i sgv_hiwmk_uncheck(count); @@ -491,43 +478,44 @@ Index: scst/src/scst_mem.c kfree(sg); return; } -@@ -1431,8 +1488,8 @@ - } - +@@ -1580,8 +1658,9 @@ static void sgv_pool_destroy(struct sgv_ + * See the SGV pool documentation for more details. + */ void sgv_pool_set_allocator(struct sgv_pool *pool, - struct page *(*alloc_pages_fn)(struct scatterlist *, gfp_t, void *), - void (*free_pages_fn)(struct scatterlist *, int, void *)) -+ struct page *(*alloc_pages_fn)(struct scatterlist *, gfp_t, int, void *), -+ void (*free_pages_fn)(struct scatterlist *, int, int, void *)) ++ struct page *(*alloc_pages_fn)(struct scatterlist *, gfp_t, ++ int, void *), ++ void (*free_pages_fn)(struct scatterlist *, int, int, void *)) { pool->alloc_fns.alloc_pages_fn = alloc_pages_fn; pool->alloc_fns.free_pages_fn = free_pages_fn; Index: scst/src/dev_handlers/scst_user.c =================================================================== ---- scst/src/dev_handlers/scst_user.c (revision 896) +--- scst/src/dev_handlers/scst_user.c (revision 3134) +++ scst/src/dev_handlers/scst_user.c (working copy) -@@ -169,9 +169,9 @@ +@@ -163,9 +163,9 @@ static int dev_user_disk_done(struct scs static int dev_user_tape_done(struct scst_cmd *cmd); static struct page *dev_user_alloc_pages(struct scatterlist *sg, - gfp_t gfp_mask, void *priv); -+ gfp_t gfp_mask, int alloc_order, void *priv); ++ gfp_t gfp_mask, int alloc_order, void *priv); static void dev_user_free_sg_entries(struct scatterlist *sg, int sg_count, - void *priv); -+ int alloc_order, void *priv); ++ int alloc_order, void *priv); static void dev_user_add_to_ready(struct scst_user_cmd *ucmd); -@@ -366,7 +366,7 @@ +@@ -392,7 +392,7 @@ static void dev_user_free_ucmd(struct sc } static struct page *dev_user_alloc_pages(struct scatterlist *sg, - gfp_t gfp_mask, void *priv) -+ gfp_t gfp_mask, int alloc_order, void *priv) ++ gfp_t gfp_mask, int alloc_order, void *priv) { struct scst_user_cmd *ucmd = (struct scst_user_cmd *)priv; int offset = 0; -@@ -375,9 +375,12 @@ +@@ -401,8 +401,11 @@ static struct page *dev_user_alloc_pages /* *sg supposed to be zeroed */ @@ -535,39 +523,38 @@ Index: scst/src/dev_handlers/scst_user.c - ucmd->ubuff, ucmd->cur_data_page); + TRACE_MEM("ucmd %p, ubuff %lx, ucmd->cur_data_page %d, alloc_order %d", + ucmd, ucmd->ubuff, ucmd->cur_data_page, alloc_order); - ++ + if (unlikely(alloc_order != 0)) + goto out; -+ + if (ucmd->cur_data_page == 0) { TRACE_MEM("ucmd->first_page_offset %d", - ucmd->first_page_offset); -@@ -469,7 +472,7 @@ +@@ -495,7 +498,7 @@ static void __dev_user_free_sg_entries(s } static void dev_user_free_sg_entries(struct scatterlist *sg, int sg_count, - void *priv) -+ int alloc_order, void *priv) ++ int alloc_order, void *priv) { struct scst_user_cmd *ucmd = (struct scst_user_cmd *)priv; -@@ -558,7 +561,8 @@ +@@ -582,7 +585,8 @@ static int dev_user_alloc_sg(struct scst ucmd->buff_cached = cached_buff; cmd->sg = sgv_pool_alloc(pool, bufflen, gfp_mask, flags, &cmd->sg_cnt, - &ucmd->sgv, &dev->udev_mem_lim, ucmd); -+ &ucmd->sgv, &dev->udev_mem_lim, ucmd, -+ cmd->tgt_dev->max_sg_cnt); ++ &ucmd->sgv, &dev->udev_mem_lim, ucmd, ++ cmd->tgt_dev->max_sg_cnt); if (cmd->sg != NULL) { struct scst_user_cmd *buf_ucmd = (struct scst_user_cmd *)sgv_get_priv(ucmd->sgv); -@@ -590,20 +594,8 @@ - cmd, cmd->in_sg, cmd->in_sg_cnt, cmd->sg_cnt); +@@ -614,20 +618,7 @@ static int dev_user_alloc_sg(struct scst + cmd, cmd->out_sg, cmd->out_sg_cnt, cmd->sg_cnt); } - if (unlikely(cmd->sg_cnt > cmd->tgt_dev->max_sg_cnt)) { - static int ll; -- if (ll < 10) { +- if ((ll < 10) || TRACING_MINOR()) { - PRINT_INFO("Unable to complete command due to " - "SG IO count limitation (requested %d, " - "available %d, tgt lim %d)", @@ -580,7 +567,30 @@ Index: scst/src/dev_handlers/scst_user.c - res = -1; - } + EXTRACHECKS_BUG_ON(cmd->sg_cnt > cmd->tgt_dev->max_sg_cnt); -+ } else { TRACE_MEM("Buf not alloced (ucmd %p, h %d, buff_cached, %d, " "sg_cnt %d, ubuff %lx, sgv %p", ucmd, ucmd->h, +@@ -3137,6 +3128,14 @@ static int dev_user_prealloc_buffer(stru + + TRACE_ENTRY(); + ++ { ++ /* The SGV patch cannot support that feature because ++ * we don't know either the target or the number of SG ++ * buffer of the target. */ ++ res = -EINVAL; ++ goto out; ++ } ++ + mutex_lock(&dev_priv_mutex); + dev = (struct scst_user_dev *)file->private_data; + res = dev_user_check_reg(dev); +@@ -3188,7 +3187,7 @@ static int dev_user_prealloc_buffer(stru + pool = dev->pool; + + sg = sgv_pool_alloc(pool, bufflen, GFP_KERNEL, SGV_POOL_ALLOC_GET_NEW, +- &sg_cnt, &ucmd->sgv, &dev->udev_mem_lim, ucmd); ++ &sg_cnt, &ucmd->sgv, &dev->udev_mem_lim, ucmd, 0); + if (sg != NULL) { + struct scst_user_cmd *buf_ucmd = + (struct scst_user_cmd *)sgv_get_priv(ucmd->sgv); diff --git a/www/target_emulex.html b/www/target_emulex.html index 66a2c9e8a..a90aab5ce 100644 --- a/www/target_emulex.html +++ b/www/target_emulex.html @@ -68,7 +68,12 @@
The lpfc SCST driver kit is part of the lpfcxxxx SourceForge project located at Emulex Linux Drivers page.
-+
You can find version which can compile on RHEL5 platforms + here. Thanks to Chris Worley who supplied it.
+ +This driver compatible only with SCST 1.x. Update for SCST 2.x is welcome!
+ +README HOWTO diff --git a/www/target_local.html b/www/target_local.html index 786e7f89b..d40cde691 100644 --- a/www/target_local.html +++ b/www/target_local.html @@ -64,9 +64,12 @@ any device handlers that you load in SCST will be visible, including tapes and so forth.
+Additionally, this driver allows creation of fully functional target drivers in user space. + See README for more details.
+This driver was made by Richard Sharpe.
-It is on the beta stage. The latest released version is 0.9. You can download +
It is on the beta stage. The latest stabe version is 1.0.0. You can download the latest development version from the SCST SVN repository. See the download page how to setup access to it.
diff --git a/www/target_qla2x00t.html b/www/target_qla2x00t.html index 774045510..0e3b4ac66 100644 --- a/www/target_qla2x00t.html +++ b/www/target_qla2x00t.html @@ -57,16 +57,10 @@
Target driver qla2x00t for QLogic FC adapters
- This is target driver for QLogic qla2xxx (qla22xx/qla23xx) Fibre Channel adapters. It is stable and well tested.
The latest stable version is 1.0.1.1. Requires Linux kernel version 2.6.16.x or higher and - SCST version 1.0.1.1 or higher.
- -The latest development version is 2.0.0. It additionally has support for 24xx/25xx (4/8 Gbps) adapters - as well as several other important improvements, thanks to ID7. - Requires Linux kernel version 2.6.26.x or higher and SCST version 1.0.2 or higher. - You can download it from the SCST SVN repository. See the download page how to setup - access to it.
+The latest stable version is 2.0.0. Requires Linux kernel version 2.6.26.x or higher and + SCST version 2.0.0 or higher.
This driver is mainline Linux kernel ready and after cosmetic cleanups going to be pushed to it together with other SCST patches.
diff --git a/www/target_qla_isp.html b/www/target_qla_isp.html index 30a097d33..424b8c7a7 100644 --- a/www/target_qla_isp.html +++ b/www/target_qla_isp.html @@ -68,7 +68,7 @@ From other side, qla2x00t is simpler, smaller and much better tested on 22xx and 23xx, hence perform more reliable and, thus, is recommended for these adapters. -Since support of 24xx (4Gbps) and 25xx (8Gbps) series of QLogic adapters was added in version 2.0.0 +
Since support of 24xx (4Gbps) and 25xx (8Gbps) series of QLogic adapters was added in version 2.0.0 of qla2x00t, users are encouraged to switch from this driver to qla2x00t.
The latest release is 1.0.2. It supports kernel versions between 2.6.16 and 2.6.32.
diff --git a/www/target_srp.html b/www/target_srp.html index d91ceb93c..ffdd9c9c0 100644 --- a/www/target_srp.html +++ b/www/target_srp.html @@ -58,13 +58,14 @@Infiniband SCSI RDMA protocol (SRP) target driver
SCSI RDMA Protocol (SRP) target driver has been developed by Vu Pham. Since March
- 2008 the main development place of the SRP target driver is SCST SVN repository.
The latest stable version is 1.0.0.
-You can find instructions how to download and install the development version of the driver on its wiki page. + 2008 the main development place of the SRP target driver is SCST SVN repository. + It is maintained by Bart Van Assche.
+This driver is mainline Linux kernel ready and going to be pushed to it + together with other SCST patches.
+The latest stable version is 2.0.0.
Download - RDMA Wiki SCST SVN Repository