From: Mike Christie <[EMAIL PROTECTED]>
Do not merge this patch. It does not work. It is for example only.
I started thinking about how to preallocate skb/frames. I started with
this patch. A problem is that, mempools are nice when all the
structs are the same size. In this patch I used FC_MAX_PAYLOAD.
I do not think it will be that bad if we only have to reserve
a couple frames for that size for each lport. The problem is that I
am not sure how or if it is safe to modify the skb settings. If
we originally allocated a skb for FC_MAX_PAYLOAD, can I just
do a skb_put for the correct size in __fc_frame_alloc?
I was also not sure about some of the network layer behaviors.
With this current patch would I need to preallocate at least
enough frames to answer one ready to transfer? What is the max
and normal sizes we see for that? Can I partially answer it?
If the target had expected 64K can I only send 8K, because
we only have 8K reserved?
Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
drivers/scsi/libfc/fc_frame.c | 39 ++++++++++++++++++++++++++++++++++++---
drivers/scsi/libfc/fc_lport.c | 13 +++++++++++++
include/scsi/libfc/fc_frame.h | 11 ++++++++---
include/scsi/libfc/libfc.h | 1 +
4 files changed, 58 insertions(+), 6 deletions(-)
diff --git a/drivers/scsi/libfc/fc_frame.c b/drivers/scsi/libfc/fc_frame.c
index 7ba241e..589c62e 100644
--- a/drivers/scsi/libfc/fc_frame.c
+++ b/drivers/scsi/libfc/fc_frame.c
@@ -25,6 +25,7 @@
#include <linux/skbuff.h>
#include <linux/crc32.h>
+#include <scsi/libfc/libfc.h>
#include <scsi/libfc/fc_frame.h>
/*
@@ -51,7 +52,7 @@ EXPORT_SYMBOL(fc_frame_crc_check);
* Allocate a frame intended to be sent via fcoe_xmit.
* Get an sk_buff for the frame and set the length.
*/
-struct fc_frame *__fc_frame_alloc(size_t len)
+static struct fc_frame *frame_alloc(size_t len)
{
struct fc_frame *fp;
struct sk_buff *skb;
@@ -67,8 +68,24 @@ struct fc_frame *__fc_frame_alloc(size_t len)
skb_put(skb, len);
return fp;
}
-EXPORT_SYMBOL(__fc_frame_alloc);
+/*
+ * Free the fc_frame structure and buffer.
+ */
+static void frame_free(struct fc_frame *fp)
+{
+ kfree_skb(fp_skb(fp));
+}
+
+/*
+ * Allocate a frame intended to be sent via fcoe_xmit.
+ * Get an sk_buff for the frame and set the length.
+ */
+struct fc_frame *__fc_frame_alloc(struct fc_lport *lp, size_t len)
+{
+ return mempool_alloc(lp->fr_pool, GFP_ATOMIC);
+}
+EXPORT_SYMBOL(__fc_frame_alloc);
struct fc_frame *fc_frame_alloc_fill(struct fc_lport *lp, size_t payload_len)
{
@@ -78,7 +95,7 @@ struct fc_frame *fc_frame_alloc_fill(struct fc_lport *lp,
size_t payload_len)
fill = payload_len % 4;
if (fill != 0)
fill = 4 - fill;
- fp = __fc_frame_alloc(payload_len + fill);
+ fp = __fc_frame_alloc(lp, payload_len + fill);
if (fp) {
memset((char *) fr_hdr(fp) + payload_len, 0, fill);
/* trim is OK, we just allocated it so there are no fragments */
@@ -86,3 +103,19 @@ struct fc_frame *fc_frame_alloc_fill(struct fc_lport *lp,
size_t payload_len)
}
return fp;
}
+
+void *fc_frame_pool_alloc(gfp_t gfp_mask, void *pool_data)
+{
+ /*
+ * this should be the max space we need for the frame.
+ *
+ * if the len is larger than what we want to send what problems
+ * is this going to make?
+ */
+ return frame_alloc(FC_MAX_PAYLOAD);
+}
+
+void fc_frame_pool_free(void *element, void *pool_data)
+{
+ frame_free(element);
+}
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index c0a3554..d1fed8f 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -908,6 +908,19 @@ EXPORT_SYMBOL(fc_lport_config);
int fc_lport_init(struct fc_lport *lp)
{
+ /*
+ * If the skb is released right after it is sent
+ * then we only need one and could reuse it.
+ *
+ * If the skb is not released until some time afterward
+ * then we may need to allocate enough skbs for an entire
+ * sequence. What is the normal size of this?
+ */
+ lp->fr_pool = mempool_create(2, fc_frame_pool_alloc,
+ fc_frame_pool_free, lp);
+ if (!lp->fr_pool)
+ return -ENOMEM;
+
if (!lp->tt.lport_recv)
lp->tt.lport_recv = fc_lport_recv;
diff --git a/include/scsi/libfc/fc_frame.h b/include/scsi/libfc/fc_frame.h
index c7a52bb..43f2cf9 100644
--- a/include/scsi/libfc/fc_frame.h
+++ b/include/scsi/libfc/fc_frame.h
@@ -22,6 +22,7 @@
#include <linux/scatterlist.h>
#include <linux/skbuff.h>
+#include <linux/mempool.h>
#include <scsi/fc/fc_fs.h>
#include <scsi/fc/fc_encaps.h>
@@ -93,7 +94,7 @@ static inline void fc_frame_init(struct fc_frame *fp)
struct fc_frame *fc_frame_alloc_fill(struct fc_lport *, size_t payload_len);
-struct fc_frame *__fc_frame_alloc(size_t payload_len);
+struct fc_frame *__fc_frame_alloc(struct fc_lport *, size_t payload_len);
/*
* Get frame for sending via port.
@@ -101,7 +102,7 @@ struct fc_frame *__fc_frame_alloc(size_t payload_len);
static inline struct fc_frame *_fc_frame_alloc(struct fc_lport *dev,
size_t payload_len)
{
- return __fc_frame_alloc(payload_len);
+ return __fc_frame_alloc(dev, payload_len);
}
/*
@@ -128,7 +129,7 @@ static inline struct fc_frame *fc_frame_alloc(struct
fc_lport *dev, size_t len)
*/
static inline void fc_frame_free(struct fc_frame *fp)
{
- kfree_skb(fp_skb(fp));
+ mempool_free(fp, NULL);
}
static inline int fc_frame_is_linear(struct fc_frame *fp)
@@ -233,4 +234,8 @@ u32 fc_frame_crc_check(struct fc_frame *);
*/
void fc_frame_leak_check(void);
+/* mempool allocator/destructors */
+void *fc_frame_pool_alloc(gfp_t gfp_mask, void *pool_data);
+void fc_frame_pool_free(void *element, void *pool_data);
+
#endif /* _FC_FRAME_H_ */
diff --git a/include/scsi/libfc/libfc.h b/include/scsi/libfc/libfc.h
index de68c44..06abcca 100644
--- a/include/scsi/libfc/libfc.h
+++ b/include/scsi/libfc/libfc.h
@@ -428,6 +428,7 @@ struct fc_lport {
struct fc_gpn_ft_resp ns_disc_buf; /* partial name buffer */
struct timer_list state_timer; /* timer for state events */
struct delayed_work ns_disc_work;
+ mempool_t *fr_pool; /* pool of frames */
void *drv_priv;
};
--
1.5.4.1
_______________________________________________
devel mailing list
[email protected]
http://www.open-fcoe.org/mailman/listinfo/devel