diff options
author | Ilya Dryomov <idryomov@gmail.com> | 2019-03-22 17:14:19 -0400 |
---|---|---|
committer | Ilya Dryomov <idryomov@gmail.com> | 2019-03-25 17:28:07 -0400 |
commit | 187df76325af5d9e12ae9daec1510307797e54f0 (patch) | |
tree | bd3b2b26f3dfaed772ca6a63a632c731abb30979 | |
parent | 8c2ffd9174779014c3fe1f96d9dc3641d9175f00 (diff) |
libceph: fix breakage caused by multipage bvecs
A bvec can now consist of multiple physically contiguous pages.
This means that bvec_iter_advance() can move to a different page while
staying in the same bvec (i.e. ->bi_bvec_done != 0).
The messenger works in terms of segments which can now be defined as
the smaller of a bvec and a page. The "more bytes to process in this
segment" condition holds only if bvec_iter_advance() leaves us in the
same bvec _and_ in the same page. On next bvec (possibly in the same
page) and on next page (possibly in the same bvec) we may need to set
->last_piece.
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
-rw-r--r-- | net/ceph/messenger.c | 8 |
1 files changed, 6 insertions, 2 deletions
diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 7e71b0df1fbc..3083988ce729 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c | |||
@@ -840,6 +840,7 @@ static bool ceph_msg_data_bio_advance(struct ceph_msg_data_cursor *cursor, | |||
840 | size_t bytes) | 840 | size_t bytes) |
841 | { | 841 | { |
842 | struct ceph_bio_iter *it = &cursor->bio_iter; | 842 | struct ceph_bio_iter *it = &cursor->bio_iter; |
843 | struct page *page = bio_iter_page(it->bio, it->iter); | ||
843 | 844 | ||
844 | BUG_ON(bytes > cursor->resid); | 845 | BUG_ON(bytes > cursor->resid); |
845 | BUG_ON(bytes > bio_iter_len(it->bio, it->iter)); | 846 | BUG_ON(bytes > bio_iter_len(it->bio, it->iter)); |
@@ -851,7 +852,8 @@ static bool ceph_msg_data_bio_advance(struct ceph_msg_data_cursor *cursor, | |||
851 | return false; /* no more data */ | 852 | return false; /* no more data */ |
852 | } | 853 | } |
853 | 854 | ||
854 | if (!bytes || (it->iter.bi_size && it->iter.bi_bvec_done)) | 855 | if (!bytes || (it->iter.bi_size && it->iter.bi_bvec_done && |
856 | page == bio_iter_page(it->bio, it->iter))) | ||
855 | return false; /* more bytes to process in this segment */ | 857 | return false; /* more bytes to process in this segment */ |
856 | 858 | ||
857 | if (!it->iter.bi_size) { | 859 | if (!it->iter.bi_size) { |
@@ -899,6 +901,7 @@ static bool ceph_msg_data_bvecs_advance(struct ceph_msg_data_cursor *cursor, | |||
899 | size_t bytes) | 901 | size_t bytes) |
900 | { | 902 | { |
901 | struct bio_vec *bvecs = cursor->data->bvec_pos.bvecs; | 903 | struct bio_vec *bvecs = cursor->data->bvec_pos.bvecs; |
904 | struct page *page = bvec_iter_page(bvecs, cursor->bvec_iter); | ||
902 | 905 | ||
903 | BUG_ON(bytes > cursor->resid); | 906 | BUG_ON(bytes > cursor->resid); |
904 | BUG_ON(bytes > bvec_iter_len(bvecs, cursor->bvec_iter)); | 907 | BUG_ON(bytes > bvec_iter_len(bvecs, cursor->bvec_iter)); |
@@ -910,7 +913,8 @@ static bool ceph_msg_data_bvecs_advance(struct ceph_msg_data_cursor *cursor, | |||
910 | return false; /* no more data */ | 913 | return false; /* no more data */ |
911 | } | 914 | } |
912 | 915 | ||
913 | if (!bytes || cursor->bvec_iter.bi_bvec_done) | 916 | if (!bytes || (cursor->bvec_iter.bi_bvec_done && |
917 | page == bvec_iter_page(bvecs, cursor->bvec_iter))) | ||
914 | return false; /* more bytes to process in this segment */ | 918 | return false; /* more bytes to process in this segment */ |
915 | 919 | ||
916 | BUG_ON(cursor->last_piece); | 920 | BUG_ON(cursor->last_piece); |