Skip to content

Commit

Permalink
btrfs: new function read_extent_buffer_to_user
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Gerhard Heift authored and Chris Mason committed Jun 13, 2014
1 parent 9b6e817 commit 550ac1d
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 0 deletions.
37 changes: 37 additions & 0 deletions fs/btrfs/extent_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
unsigned long min_len, char **map,
unsigned long *map_start,
Expand Down
3 changes: 3 additions & 0 deletions fs/btrfs/extent_io.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down

0 comments on commit 550ac1d

Please sign in to comment.