diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-14 20:48:43 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-14 20:48:43 -0400 |
commit | 16d52ef7c026f925893a1c0fc46516349928f319 (patch) | |
tree | 1cb9bf5406e22bb3f4fb37d9e6d4e926304dfe04 /fs/btrfs/extent_io.c | |
parent | a311c480384c5aa9aaae195b89c3ec89c3b66379 (diff) | |
parent | 47a306a74842248dcd537b85f9a36c7b156c59a9 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs
Pull more btrfs updates from Chris Mason:
"This has a few fixes since our last pull and a new ioctl for doing
btree searches from userland. It's very similar to the existing
ioctl, but lets us return larger items back down to the app"
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs:
btrfs: fix error handling in create_pending_snapshot
btrfs: fix use of uninit "ret" in end_extent_writepage()
btrfs: free ulist in qgroup_shared_accounting() error path
Btrfs: fix qgroups sanity test crash or hang
btrfs: prevent RCU warning when dereferencing radix tree slot
Btrfs: fix unfinished readahead thread for raid5/6 degraded mounting
btrfs: new ioctl TREE_SEARCH_V2
btrfs: tree_search, search_ioctl: direct copy to userspace
btrfs: new function read_extent_buffer_to_user
btrfs: tree_search, copy_to_sk: return needed size on EOVERFLOW
btrfs: tree_search, copy_to_sk: return EOVERFLOW for too small buffer
btrfs: tree_search, search_ioctl: accept varying buffer
btrfs: tree_search: eliminate redundant nr_items check
Diffstat (limited to 'fs/btrfs/extent_io.c')
-rw-r--r-- | fs/btrfs/extent_io.c | 39 |
1 files changed, 38 insertions, 1 deletions
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index f25a9092b946..a389820d158b 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
@@ -2354,7 +2354,7 @@ int end_extent_writepage(struct page *page, int err, u64 start, u64 end) | |||
2354 | { | 2354 | { |
2355 | int uptodate = (err == 0); | 2355 | int uptodate = (err == 0); |
2356 | struct extent_io_tree *tree; | 2356 | struct extent_io_tree *tree; |
2357 | int ret; | 2357 | int ret = 0; |
2358 | 2358 | ||
2359 | tree = &BTRFS_I(page->mapping->host)->io_tree; | 2359 | tree = &BTRFS_I(page->mapping->host)->io_tree; |
2360 | 2360 | ||
@@ -5068,6 +5068,43 @@ void read_extent_buffer(struct extent_buffer *eb, void *dstv, | |||
5068 | } | 5068 | } |
5069 | } | 5069 | } |
5070 | 5070 | ||
5071 | int read_extent_buffer_to_user(struct extent_buffer *eb, void __user *dstv, | ||
5072 | unsigned long start, | ||
5073 | unsigned long len) | ||
5074 | { | ||
5075 | size_t cur; | ||
5076 | size_t offset; | ||
5077 | struct page *page; | ||
5078 | char *kaddr; | ||
5079 | char __user *dst = (char __user *)dstv; | ||
5080 | size_t start_offset = eb->start & ((u64)PAGE_CACHE_SIZE - 1); | ||
5081 | unsigned long i = (start_offset + start) >> PAGE_CACHE_SHIFT; | ||
5082 | int ret = 0; | ||
5083 | |||
5084 | WARN_ON(start > eb->len); | ||
5085 | WARN_ON(start + len > eb->start + eb->len); | ||
5086 | |||
5087 | offset = (start_offset + start) & (PAGE_CACHE_SIZE - 1); | ||
5088 | |||
5089 | while (len > 0) { | ||
5090 | page = extent_buffer_page(eb, i); | ||
5091 | |||
5092 | cur = min(len, (PAGE_CACHE_SIZE - offset)); | ||
5093 | kaddr = page_address(page); | ||
5094 | if (copy_to_user(dst, kaddr + offset, cur)) { | ||
5095 | ret = -EFAULT; | ||
5096 | break; | ||
5097 | } | ||
5098 | |||
5099 | dst += cur; | ||
5100 | len -= cur; | ||
5101 | offset = 0; | ||
5102 | i++; | ||
5103 | } | ||
5104 | |||
5105 | return ret; | ||
5106 | } | ||
5107 | |||
5071 | int map_private_extent_buffer(struct extent_buffer *eb, unsigned long start, | 5108 | int map_private_extent_buffer(struct extent_buffer *eb, unsigned long start, |
5072 | unsigned long min_len, char **map, | 5109 | unsigned long min_len, char **map, |
5073 | unsigned long *map_start, | 5110 | unsigned long *map_start, |