mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-28 09:20:18 +00:00
Web updates
git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@3169 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -51,7 +51,7 @@
|
||||
mailing list and it will be corrected.
|
||||
</p>
|
||||
|
||||
<p><small>As on September 2010</small></p>
|
||||
<p><small>As on September 2010. Partially updated in December 2010.</small></p>
|
||||
|
||||
<table bgcolor="#F0F0F0" border="1" cellspacing="1" cellpadding="7" style="text-align:center" width="620">
|
||||
|
||||
@@ -80,9 +80,7 @@
|
||||
</sup> </td> <td> - </td> <td> Kernel only </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><b>Stability</b></td> <td> Final testing
|
||||
before release (1.0.1.x
|
||||
- stable)</td> <td> +
|
||||
<td align="left"><b>Stability</b></td> <td> + </td> <td> +
|
||||
<sup><A HREF="#3">3</A>
|
||||
</sup> </td> <td> + </td> <td> Probably (no released packages) </td>
|
||||
</tr>
|
||||
@@ -245,7 +243,8 @@ apply changes in the config file on fly without any restarts</b></td> <td> scsta
|
||||
<td align="left"><b>iSCSI</b></td> <td> + </td> <td> + </td> <td> + </td> <td> + </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><b>QLogic (Fibre Channel)</b></td> <td> + </td> <td> - </td> <td> - </td> <td> - </td>
|
||||
<td align="left"><b>QLogic (Fibre Channel)</b></td> <td> + </td> <td> - </td> <td> - </td> <td> Preliminary
|
||||
(just added) </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><b>Emulex (Fibre Channel and FCoE)</b></td> <td> + </td> <td> - </td> <td> - </td> <td> - </td>
|
||||
@@ -274,7 +273,7 @@ apply changes in the config file on fly without any restarts</b></td> <td> scsta
|
||||
(not completed) </td> <td> - </td> <td> - </td> <td> - </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><b>IBM pSeries Virtual SCSI</b></td> <td> - </td> <td> + </td> <td> - </td> <td> - </td>
|
||||
<td align="left"><b>IBM pSeries Virtual SCSI</b></td> <td> + </td> <td> + </td> <td> - </td> <td> - </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><b>Local access to emulated backstorage devices
|
||||
|
||||
@@ -297,18 +297,10 @@
|
||||
of entries inside the SG IO count limitation. In <a href="sgv_big_order_alloc.diff">sgv_big_order_alloc.diff</a>
|
||||
you can find a possible way to solve this issue.</p>
|
||||
|
||||
<p>There are also 2 more patches you can look at:</p>
|
||||
|
||||
<ul>
|
||||
|
||||
<li><span><a href="sgv_big_order_alloc-r2.diff">sgv_big_order_alloc-r2.diff</a> - this patch
|
||||
has all the required features, but has a memory corruption.</span></li>
|
||||
|
||||
<li><span><a href="sgv_big_order_alloc-sfw4.diff">sgv_big_order_alloc-sfw4.diff</a> - this patch,
|
||||
created by Frank Zago, works for him, but doesn't have all the required features to be merged
|
||||
in SCST.</span></li>
|
||||
|
||||
</ul>
|
||||
<p>You can also look at patch
|
||||
<a href="sgv_big_order_alloc-sfw5-rc3.diff">sgv_big_order_alloc-sfw5-rc3.diff</a>
|
||||
created by Frank Zago for SCST 2.0.0. It was submitted too late to be included in it.
|
||||
Update for SCST trunk is welcome!</p>
|
||||
|
||||
<A NAME="MEM_REG"></A><h3>Memory registration</h3>
|
||||
|
||||
|
||||
@@ -36,13 +36,9 @@
|
||||
<div id="main">
|
||||
<h1>SCST Downloads</h1>
|
||||
|
||||
<p>The latest stable released version of SCST core is 1.0.1.1. It requires Linux kernel 2.6.16 or higher.
|
||||
<p>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.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>You can also download prebuilt SCST modules for
|
||||
<a href="http://linuxsoft.cern.ch/cern/slc5X/x86_64/yum/extras/repoview">Scientific Linux CERN 5</a> (RHEL5-based),
|
||||
<a href="https://launchpad.net/~ast/+archive/scst2">Ubuntu</a> and
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
All the words about BLOCKIO mode from SCST's README file apply to
|
||||
O_DIRECT mode as well.</p>
|
||||
|
||||
<p>The latest stable version is 1.0.1.1. Requires SCST version 1.0.1.1 or higher.</p>
|
||||
<p>The latest stable version is 2.0.0. Requires SCST version 2.0.0 or higher.</p>
|
||||
<p>You can find the latest development version of this handler in the SCST SVN. See the download page how to setup
|
||||
access to it.</p>
|
||||
<p class="post-footer align-right">
|
||||
|
||||
@@ -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.</p>
|
||||
|
||||
<p>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.
|
||||
<p>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.</p>
|
||||
<p>You can find the latest development version of this driver in the SCST SVN. See the download page how to setup
|
||||
access to it.</p>
|
||||
|
||||
@@ -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.</p>
|
||||
|
||||
<p>The latest stable version is 1.0.6.</p>
|
||||
<p>The latest stable version is 2.0.0.</p>
|
||||
|
||||
<p class="post-footer align-right">
|
||||
<a href="downloads.html" class="readmore">Download</a>
|
||||
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -68,7 +68,12 @@
|
||||
<p>The lpfc SCST driver kit is part of the lpfcxxxx SourceForge project located at
|
||||
<a href="https://sourceforge.net/projects/lpfcxxxx" class="readmore">Emulex Linux Drivers</a> page.</p>
|
||||
|
||||
<br><br><br><br>
|
||||
<p>You can find version which can compile on RHEL5 platforms
|
||||
<a href="lpfc_scst1123.tar.bz2" class="readmore">here</a>. Thanks to Chris Worley who supplied it.</p>
|
||||
|
||||
<p>This driver compatible only with SCST 1.x. Update for SCST 2.x is welcome!</p>
|
||||
|
||||
<br><br>
|
||||
<p class="post-footer align-right">
|
||||
<a href="http://lpfcxxxx.sourceforge.net/README" class="readmore">README</a>
|
||||
<a href="http://lpfcxxxx.sourceforge.net/HOWTO.lpfc" class="readmore">HOWTO</a>
|
||||
|
||||
@@ -64,9 +64,12 @@
|
||||
any device handlers that you load in SCST will be visible, including tapes
|
||||
and so forth.</p>
|
||||
|
||||
<p>Additionally, this driver allows creation of fully functional target drivers in user space.
|
||||
See README for more details.</p>
|
||||
|
||||
<p>This driver was made by Richard Sharpe.</p>
|
||||
|
||||
<p>It is on the beta stage. The latest released version is 0.9. You can download
|
||||
<p>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. </p><br><br><br>
|
||||
<p class="post-footer align-right">
|
||||
|
||||
@@ -57,16 +57,10 @@
|
||||
<div id="main">
|
||||
<h1>Target driver qla2x00t for QLogic FC adapters</h1>
|
||||
<p><img src="images/t_qlogic.gif" width="100" height="120" class="float-left" alt="SCST QLogic">
|
||||
This is target driver for QLogic qla2xxx (qla22xx/qla23xx) Fibre Channel adapters. It is stable and well tested.</p>
|
||||
This is target driver for QLogic qla2xxx (22xx/23xx/24xx/25xx) Fibre Channel adapters. It is stable and well tested.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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 <a href="http://www.id-7.com/">ID7</a>.
|
||||
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.</p>
|
||||
<p>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.</p>
|
||||
|
||||
<p>This driver is mainline Linux kernel ready and after cosmetic cleanups going to be pushed to it
|
||||
together with other SCST patches.</p>
|
||||
|
||||
@@ -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.</p>
|
||||
|
||||
<p> Since support of 24xx (4Gbps) and 25xx (8Gbps) series of QLogic adapters was added in version 2.0.0
|
||||
<p> 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.</p>
|
||||
|
||||
<p>The latest release is 1.0.2. It supports kernel versions between 2.6.16 and 2.6.32.</p>
|
||||
|
||||
@@ -58,13 +58,14 @@
|
||||
<h1>Infiniband SCSI RDMA protocol (SRP) target driver</h1>
|
||||
<p><img src="images/t_rdma.gif" width="100" height="120" class="float-left" alt="SCST SRP">
|
||||
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.</p>
|
||||
<p>The latest stable version is 1.0.0.</p>
|
||||
<p>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.</p>
|
||||
<p>This driver is mainline Linux kernel ready and going to be pushed to it
|
||||
together with other SCST patches.</p>
|
||||
<p>The latest stable version is 2.0.0.</p>
|
||||
</p><br><br><br>
|
||||
<p class="post-footer align-right">
|
||||
<a href="downloads.html" class="readmore">Download</a>
|
||||
<a href="https://wiki.openfabrics.org/tiki-index.php?page=SRPT+Installation" class="readmore">RDMA Wiki</a>
|
||||
<a href="http://scst.svn.sourceforge.net/" class="readmore">SCST SVN Repository</a>
|
||||
</p>
|
||||
<table border=0><tr><td height="300px"> </td></tr></table>
|
||||
|
||||
Reference in New Issue
Block a user