This new function reads the content of an extent directly to user memory.

Signed-off-by: Gerhard Heift <gerh...@heift.name>
---
 fs/btrfs/extent_io.c | 37 +++++++++++++++++++++++++++++++++++++
 fs/btrfs/extent_io.h |  3 +++
 2 files changed, 40 insertions(+)

diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index fbe501d..d1e9dd8 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -4956,6 +4956,43 @@ void read_extent_buffer(struct extent_buffer *eb, void 
*dstv,
        }
 }
 
+int read_extent_buffer_to_user(struct extent_buffer *eb, void __user *dstv,
+                       unsigned long start,
+                       unsigned long len)
+{
+       size_t cur;
+       size_t offset;
+       struct page *page;
+       char *kaddr;
+       char __user *dst = (char __user *)dstv;
+       size_t start_offset = eb->start & ((u64)PAGE_CACHE_SIZE - 1);
+       unsigned long i = (start_offset + start) >> PAGE_CACHE_SHIFT;
+       int ret = 0;
+
+       WARN_ON(start > eb->len);
+       WARN_ON(start + len > eb->start + eb->len);
+
+       offset = (start_offset + start) & (PAGE_CACHE_SIZE - 1);
+
+       while (len > 0) {
+               page = extent_buffer_page(eb, i);
+
+               cur = min(len, (PAGE_CACHE_SIZE - offset));
+               kaddr = page_address(page);
+               if (copy_to_user(dst, kaddr + offset, cur)) {
+                       ret = -EFAULT;
+                       break;
+               }
+
+               dst += cur;
+               len -= cur;
+               offset = 0;
+               i++;
+       }
+
+       return ret;
+}
+
 int map_private_extent_buffer(struct extent_buffer *eb, unsigned long start,
                               unsigned long min_len, char **map,
                               unsigned long *map_start,
diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h
index 58b27e5..d0b1541 100644
--- a/fs/btrfs/extent_io.h
+++ b/fs/btrfs/extent_io.h
@@ -304,6 +304,9 @@ int memcmp_extent_buffer(struct extent_buffer *eb, const 
void *ptrv,
 void read_extent_buffer(struct extent_buffer *eb, void *dst,
                        unsigned long start,
                        unsigned long len);
+int read_extent_buffer_to_user(struct extent_buffer *eb, void __user *dst,
+                              unsigned long start,
+                              unsigned long len);
 void write_extent_buffer(struct extent_buffer *eb, const void *src,
                         unsigned long start, unsigned long len);
 void copy_extent_buffer(struct extent_buffer *dst, struct extent_buffer *src,
-- 
1.8.5.3

--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to