aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGerhard Heift <gerhard@heift.name>2014-01-30 10:24:01 -0500
committerChris Mason <clm@fb.com>2014-06-12 21:21:56 -0400
commit550ac1d85ef99f3390a6ea87c70b7683647f6110 (patch)
treea3753a08098118a0dda00aff8fcf4dc20e3a480a
parent9b6e817d022fd44fe99db92f00d4b18ac2d8f429 (diff)
btrfs: new function read_extent_buffer_to_user
This new function reads the content of an extent directly to user memory. Signed-off-by: Gerhard Heift <Gerhard@Heift.Name> Signed-off-by: Chris Mason <clm@fb.com> Acked-by: David Sterba <dsterba@suse.cz>
-rw-r--r--fs/btrfs/extent_io.c37
-rw-r--r--fs/btrfs/extent_io.h3
2 files changed, 40 insertions, 0 deletions
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 0b5fa91d9a88..930f23dfaa2b 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -5067,6 +5067,43 @@ void read_extent_buffer(struct extent_buffer *eb, void *dstv,
5067 } 5067 }
5068} 5068}
5069 5069
5070int read_extent_buffer_to_user(struct extent_buffer *eb, void __user *dstv,
5071 unsigned long start,
5072 unsigned long len)
5073{
5074 size_t cur;
5075 size_t offset;
5076 struct page *page;
5077 char *kaddr;
5078 char __user *dst = (char __user *)dstv;
5079 size_t start_offset = eb->start & ((u64)PAGE_CACHE_SIZE - 1);
5080 unsigned long i = (start_offset + start) >> PAGE_CACHE_SHIFT;
5081 int ret = 0;
5082
5083 WARN_ON(start > eb->len);
5084 WARN_ON(start + len > eb->start + eb->len);
5085
5086 offset = (start_offset + start) & (PAGE_CACHE_SIZE - 1);
5087
5088 while (len > 0) {
5089 page = extent_buffer_page(eb, i);
5090
5091 cur = min(len, (PAGE_CACHE_SIZE - offset));
5092 kaddr = page_address(page);
5093 if (copy_to_user(dst, kaddr + offset, cur)) {
5094 ret = -EFAULT;
5095 break;
5096 }
5097
5098 dst += cur;
5099 len -= cur;
5100 offset = 0;
5101 i++;
5102 }
5103
5104 return ret;
5105}
5106
5070int map_private_extent_buffer(struct extent_buffer *eb, unsigned long start, 5107int map_private_extent_buffer(struct extent_buffer *eb, unsigned long start,
5071 unsigned long min_len, char **map, 5108 unsigned long min_len, char **map,
5072 unsigned long *map_start, 5109 unsigned long *map_start,
diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h
index 8b63f2d46518..15ce5f2a2b62 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,
304void read_extent_buffer(struct extent_buffer *eb, void *dst, 304void read_extent_buffer(struct extent_buffer *eb, void *dst,
305 unsigned long start, 305 unsigned long start,
306 unsigned long len); 306 unsigned long len);
307int read_extent_buffer_to_user(struct extent_buffer *eb, void __user *dst,
308 unsigned long start,
309 unsigned long len);
307void write_extent_buffer(struct extent_buffer *eb, const void *src, 310void write_extent_buffer(struct extent_buffer *eb, const void *src,
308 unsigned long start, unsigned long len); 311 unsigned long start, unsigned long len);
309void copy_extent_buffer(struct extent_buffer *dst, struct extent_buffer *src, 312void copy_extent_buffer(struct extent_buffer *dst, struct extent_buffer *src,