All of lore.kernel.org
 help / color / mirror / Atom feed
From: Maxim Levitsky <maximlevitsky@gmail.com>
To: Andrew Morton <akpm@linux-foundation.org>
Cc: James Bottomley <James.Bottomley@HansenPartnership.com>,
	FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>,
	linux-kernel@vger.kernel.org, oakad@yahoo.com,
	Maxim Levitsky <maximlevitsky@gmail.com>
Subject: [PATCH 1/4] scatterlist: new helper functions
Date: Fri,  4 Mar 2011 06:16:50 +0200	[thread overview]
Message-ID: <1299212213-4255-2-git-send-email-maximlevitsky@gmail.com> (raw)
In-Reply-To: <1299212213-4255-1-git-send-email-maximlevitsky@gmail.com>

While developing memstick driver for legacy memsticks
I found the need in few helpers that I think should be
in common scatterlist library

The functions that were added:

* sg_nents/sg_total_len - iterate over scatterlist to figure
out total length of memory it covers / number of entries.

Usefull for small sg lists where there is no prefomance advantage of
storing this info in a special variable.

* sg_copy/sg_truncate - Allow to break scatterlists apart into smaller chunks.
sg_copy creates smaller scatterlist, spanning first 'len' bytes, while
sg_truncate edits the scatterlist in such way that it skips over 'len' bytes.


* sg_compare_to_buffer - another function to hide gory details of access
to sg list by CPU.
Allows to transparently compare contents of the sg list to given linear
buffer.
If needed later, a function that compares two sgs can be added.

All of this code is used by my ms_block.c driver.

Signed-off-by: Maxim Levitsky <maximlevitsky@gmail.com>
---
 include/linux/scatterlist.h |    8 ++
 lib/scatterlist.c           |  152 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 160 insertions(+), 0 deletions(-)

diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h
index 9aaf5bf..88fc7a5 100644
--- a/include/linux/scatterlist.h
+++ b/include/linux/scatterlist.h
@@ -199,6 +199,12 @@ static inline void *sg_virt(struct scatterlist *sg)
 	return page_address(sg_page(sg)) + sg->offset;
 }
 
+struct scatterlist *sg_truncate(struct scatterlist *sg, int consumed);
+int sg_nents(struct scatterlist *sg);
+int sg_total_len(struct scatterlist *sg);
+int sg_copy(struct scatterlist *sg_from, struct scatterlist *sg_to,
+							int to_nents, int len);
+
 struct scatterlist *sg_next(struct scatterlist *);
 struct scatterlist *sg_last(struct scatterlist *s, unsigned int);
 void sg_init_table(struct scatterlist *, unsigned int);
@@ -217,6 +223,8 @@ size_t sg_copy_from_buffer(struct scatterlist *sgl, unsigned int nents,
 			   void *buf, size_t buflen);
 size_t sg_copy_to_buffer(struct scatterlist *sgl, unsigned int nents,
 			 void *buf, size_t buflen);
+bool sg_compare_to_buffer(struct scatterlist *sg, unsigned int nents,
+							u8 *buffer, size_t len);
 
 /*
  * Maximum number of entries that will be allocated in one piece, if
diff --git a/lib/scatterlist.c b/lib/scatterlist.c
index 4ceb05d..941195d 100644
--- a/lib/scatterlist.c
+++ b/lib/scatterlist.c
@@ -39,6 +39,76 @@ struct scatterlist *sg_next(struct scatterlist *sg)
 EXPORT_SYMBOL(sg_next);
 
 /**
+ * sg_truncate - remove 'consumed' bytes from head of a scatterlist
+ * @sg:		The current sg entry
+ * @consumed:	How much bytes to remove
+ */
+struct scatterlist *sg_truncate(struct scatterlist *sg, int consumed)
+{
+	while (consumed >= sg->length) {
+		consumed -= sg->length;
+
+		sg = sg_next(sg);
+		if (!sg)
+			break;
+	}
+
+	WARN_ON(!sg && consumed);
+
+	if (!sg)
+		return NULL;
+
+	sg->offset += consumed;
+	sg->length -= consumed;
+
+	if (sg->offset >= PAGE_SIZE) {
+		struct page *page =
+			nth_page(sg_page(sg), sg->offset / PAGE_SIZE);
+		sg_set_page(sg, page, sg->length, sg->offset % PAGE_SIZE);
+	}
+
+	return sg;
+}
+EXPORT_SYMBOL(sg_truncate);
+
+/**
+ * sg_nents - calculate number of sg entries in sg list
+ * @sg:		The current sg entry
+ *
+ * Allows to calculate dynamically the length of the sg table, based on
+ * assumption that last entry is correctly marked by sg_mark_end
+ */
+int sg_nents(struct scatterlist *sg)
+{
+	int nents = 0;
+	while (sg) {
+		nents++;
+		sg = sg_next(sg);
+	}
+
+	return nents;
+}
+EXPORT_SYMBOL(sg_nents);
+
+/**
+ * sg_total_len - calculate total length of scatterlist
+ * @sg:		The current sg entry
+ *
+ * Dynamically calculate total number of bytes in an scatterlist
+ * based on assumption that last entry is correctly marked by sg_mark_end
+ */
+int sg_total_len(struct scatterlist *sg)
+{
+	int len = 0;
+	while (sg) {
+		len += sg->length;
+		sg = sg_next(sg);
+	}
+	return len;
+}
+EXPORT_SYMBOL(sg_total_len);
+
+/**
  * sg_last - return the last scatterlist entry in a list
  * @sgl:	First entry in the scatterlist
  * @nents:	Number of entries in the scatterlist
@@ -110,6 +180,47 @@ void sg_init_one(struct scatterlist *sg, const void *buf, unsigned int buflen)
 }
 EXPORT_SYMBOL(sg_init_one);
 
+/**
+ * sg_copy - copies sg entries from sg_from to sg_to, such
+ * as sg_to covers first 'len' bytes from sg_from.
+ * @sg_from:	SG list to copy entries from
+ * @sg_to:	SG list to write entries to
+ * @to_nents:	number of usable entries in 'sg_to'
+ * @len:	maximum number of bytes the 'sg_to' will cover
+ *
+ * Returns actual number of bytes covered by sg_to
+ */
+int sg_copy(struct scatterlist *sg_from, struct scatterlist *sg_to,
+							int to_nents, int len)
+{
+	int copied = 0;
+
+	while (len > sg_from->length && to_nents--) {
+
+		len -= sg_from->length;
+		copied += sg_from->length;
+
+		sg_set_page(sg_to, sg_page(sg_from),
+				sg_from->length, sg_from->offset);
+
+		if (sg_is_last(sg_from) || !len) {
+			sg_mark_end(sg_to);
+			return copied;
+		}
+
+		sg_from = sg_next(sg_from);
+		sg_to = sg_next(sg_to);
+	}
+
+	if (to_nents) {
+		sg_set_page(sg_to, sg_page(sg_from), len, sg_from->offset);
+		sg_mark_end(sg_to);
+	}
+
+	return copied;
+}
+EXPORT_SYMBOL(sg_copy);
+
 /*
  * The default behaviour of sg_alloc_table() is to use these kmalloc/kfree
  * helpers.
@@ -517,3 +628,44 @@ size_t sg_copy_to_buffer(struct scatterlist *sgl, unsigned int nents,
 	return sg_copy_buffer(sgl, nents, buf, buflen, 1);
 }
 EXPORT_SYMBOL(sg_copy_to_buffer);
+
+
+/**
+ * sg_compare_to_buffer - compare contents of the data pointed by sg table
+ * to a kernel ram buffer
+ *
+ * @sg:		The current sg entry
+ * @buffer:	Linear kernel buffer to compare with
+ * @len:	Length of that buffer
+ *
+ * Returns 0 if equal and memcmp compliant result otherwise
+ */
+bool sg_compare_to_buffer(struct scatterlist *sg, unsigned int nents,
+							u8 *buffer, size_t len)
+{
+	unsigned long flags;
+	int retval = 0;
+	struct sg_mapping_iter miter;
+
+	local_irq_save(flags);
+	sg_miter_start(&miter, sg, nents, SG_MITER_ATOMIC | SG_MITER_FROM_SG);
+
+	while (sg_miter_next(&miter) && len > 0) {
+
+		int cmplen = min(miter.length, len);
+		retval = memcmp(miter.addr, buffer, cmplen);
+		if (retval)
+			break;
+
+		buffer += cmplen;
+		len -= cmplen;
+	}
+
+	if (!retval && len)
+		retval = -1;
+
+	sg_miter_stop(&miter);
+	local_irq_restore(flags);
+	return retval;
+}
+EXPORT_SYMBOL(sg_compare_to_buffer);
-- 
1.7.1


  reply	other threads:[~2011-03-04  4:17 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-03-04  4:16 [PATH 0/4] Memstick patches for 2.6.39 Maxim Levitsky
2011-03-04  4:16 ` Maxim Levitsky [this message]
2011-03-06  7:29   ` [PATCH 1/4] scatterlist: new helper functions FUJITA Tomonori
2011-03-06 15:14     ` Maxim Levitsky
2011-03-06 21:49       ` FUJITA Tomonori
2011-03-07  2:20         ` Maxim Levitsky
2011-03-09 17:24           ` Maxim Levitsky
2011-03-16  0:44           ` Andrew Morton
2011-03-16  2:35             ` FUJITA Tomonori
2011-03-16  4:18               ` Alex Dubov
2011-03-16  4:55                 ` FUJITA Tomonori
2011-03-17  3:46                   ` Alex Dubov
2011-03-17  3:57                     ` James Bottomley
2011-03-16 22:33                 ` Andrew Morton
2011-03-17  6:41                   ` Alex Dubov
2011-03-17 13:17                     ` Maxim Levitsky
2011-03-18  0:59                     ` FUJITA Tomonori
2011-03-04  4:16 ` [PATCH 2/4] memstick: add support for legacy memorysticks Maxim Levitsky
2011-03-04  4:16 ` [PATCH 3/4] memstick: Add driver for Ricoh R5C592 card reader Maxim Levitsky
2011-03-16  4:25   ` Alex Dubov
2011-03-04  4:16 ` [PATCH 4/4] memstick: add Alex Dubov to MAINTAINERS of the memstick core Maxim Levitsky
2011-03-12 16:23 ` [PATH 0/4] Memstick patches for 2.6.39 Maxim Levitsky
2011-03-15 20:00   ` Maxim Levitsky
2011-03-15 21:04     ` Andrew Morton
2011-03-16  0:25       ` Maxim Levitsky
2011-03-20  3:09       ` Maxim Levitsky
2011-03-20  6:47         ` Andrew Morton
2011-03-20 11:42           ` Maxim Levitsky
2011-03-22 13:01             ` Maxim Levitsky
2011-03-22 23:21             ` Andrew Morton
2011-03-23  0:59               ` Maxim Levitsky
2011-03-23  3:42                 ` Greg KH
2011-03-23 15:30                   ` Maxim Levitsky
2011-03-24  3:27                     ` Alex Dubov
  -- strict thread matches above, loose matches on Subject: below --
2011-01-11 23:36 [PATCH V2 0/4]: MEMSTICK: My 2 drivers for 2.6.38 inclusion Maxim Levitsky
2011-01-11 23:36 ` [PATCH 1/4] scatterlist: new helper functions Maxim Levitsky
2011-01-11 23:51   ` Randy Dunlap
2011-01-11 23:55     ` Andrew Morton
2011-01-11 23:58       ` Randy Dunlap
2011-01-12  2:52         ` Maxim Levitsky
2011-01-12  6:41           ` Randy Dunlap
2011-01-11  2:58 Alex Dubov
2011-01-11  1:50 MEMSTICK: My 2 drivers for 2.6.38 inclusion Maxim Levitsky
2011-01-11  1:50 ` [PATCH 1/4] scatterlist: new helper functions Maxim Levitsky

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1299212213-4255-2-git-send-email-maximlevitsky@gmail.com \
    --to=maximlevitsky@gmail.com \
    --cc=James.Bottomley@HansenPartnership.com \
    --cc=akpm@linux-foundation.org \
    --cc=fujita.tomonori@lab.ntt.co.jp \
    --cc=linux-kernel@vger.kernel.org \
    --cc=oakad@yahoo.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.