Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 550ac1d8 authored by Gerhard Heift's avatar Gerhard Heift Committed by Chris Mason
Browse files

btrfs: new function read_extent_buffer_to_user



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

Signed-off-by: default avatarGerhard Heift <Gerhard@Heift.Name>
Signed-off-by: default avatarChris Mason <clm@fb.com>
Acked-by: default avatarDavid Sterba <dsterba@suse.cz>
parent 9b6e817d
Loading
Loading
Loading
Loading
+37 −0
Original line number Diff line number Diff line
@@ -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,
+3 −0
Original line number Diff line number Diff line
@@ -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,