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>
This commit is contained in:
parent
9b6e817d02
commit
550ac1d85e
|
@ -5067,6 +5067,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,
|
int map_private_extent_buffer(struct extent_buffer *eb, unsigned long start,
|
||||||
unsigned long min_len, char **map,
|
unsigned long min_len, char **map,
|
||||||
unsigned long *map_start,
|
unsigned long *map_start,
|
||||||
|
|
|
@ -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,
|
void read_extent_buffer(struct extent_buffer *eb, void *dst,
|
||||||
unsigned long start,
|
unsigned long start,
|
||||||
unsigned long len);
|
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,
|
void write_extent_buffer(struct extent_buffer *eb, const void *src,
|
||||||
unsigned long start, unsigned long len);
|
unsigned long start, unsigned long len);
|
||||||
void copy_extent_buffer(struct extent_buffer *dst, struct extent_buffer *src,
|
void copy_extent_buffer(struct extent_buffer *dst, struct extent_buffer *src,
|
||||||
|
|
Loading…
Reference in New Issue