| From 5f740d7e1531099b888410e6bab13f68da9b1a4d Mon Sep 17 00:00:00 2001 |
| From: Ilya Dryomov <ilya.dryomov@inktank.com> |
| Date: Fri, 8 Aug 2014 12:43:39 +0400 |
| Subject: libceph: set last_piece in ceph_msg_data_pages_cursor_init() |
| correctly |
| |
| From: Ilya Dryomov <ilya.dryomov@inktank.com> |
| |
| commit 5f740d7e1531099b888410e6bab13f68da9b1a4d upstream. |
| |
| Determining ->last_piece based on the value of ->page_offset + length |
| is incorrect because length here is the length of the entire message. |
| ->last_piece set to false even if page array data item length is <= |
| PAGE_SIZE, which results in invalid length passed to |
| ceph_tcp_{send,recv}page() and causes various asserts to fire. |
| |
| # cat pages-cursor-init.sh |
| #!/bin/bash |
| rbd create --size 10 --image-format 2 foo |
| FOO_DEV=$(rbd map foo) |
| dd if=/dev/urandom of=$FOO_DEV bs=1M &>/dev/null |
| rbd snap create foo@snap |
| rbd snap protect foo@snap |
| rbd clone foo@snap bar |
| # rbd_resize calls librbd rbd_resize(), size is in bytes |
| ./rbd_resize bar $(((4 << 20) + 512)) |
| rbd resize --size 10 bar |
| BAR_DEV=$(rbd map bar) |
| # trigger a 512-byte copyup -- 512-byte page array data item |
| dd if=/dev/urandom of=$BAR_DEV bs=1M count=1 seek=5 |
| |
| The problem exists only in ceph_msg_data_pages_cursor_init(), |
| ceph_msg_data_pages_advance() does the right thing. The size_t cast is |
| unnecessary. |
| |
| Signed-off-by: Ilya Dryomov <ilya.dryomov@inktank.com> |
| Reviewed-by: Sage Weil <sage@redhat.com> |
| Reviewed-by: Alex Elder <elder@linaro.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| net/ceph/messenger.c | 2 +- |
| 1 file changed, 1 insertion(+), 1 deletion(-) |
| |
| --- a/net/ceph/messenger.c |
| +++ b/net/ceph/messenger.c |
| @@ -904,7 +904,7 @@ static void ceph_msg_data_pages_cursor_i |
| BUG_ON(page_count > (int)USHRT_MAX); |
| cursor->page_count = (unsigned short)page_count; |
| BUG_ON(length > SIZE_MAX - cursor->page_offset); |
| - cursor->last_piece = (size_t)cursor->page_offset + length <= PAGE_SIZE; |
| + cursor->last_piece = cursor->page_offset + cursor->resid <= PAGE_SIZE; |
| } |
| |
| static struct page * |