diff options
-rw-r--r-- | include/linux/ceph/messenger.h | 5 | ||||
-rw-r--r-- | net/ceph/messenger.c | 48 |
2 files changed, 36 insertions, 17 deletions
diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h index 318da0170a1e..de1d2e1ecce2 100644 --- a/include/linux/ceph/messenger.h +++ b/include/linux/ceph/messenger.h | |||
@@ -108,7 +108,10 @@ struct ceph_msg_data { | |||
108 | }; | 108 | }; |
109 | 109 | ||
110 | struct ceph_msg_data_cursor { | 110 | struct ceph_msg_data_cursor { |
111 | struct ceph_msg_data *data; /* data item this describes */ | 111 | size_t total_resid; /* across all data items */ |
112 | struct list_head *data_head; /* = &ceph_msg->data */ | ||
113 | |||
114 | struct ceph_msg_data *data; /* current data item */ | ||
112 | size_t resid; /* bytes not yet consumed */ | 115 | size_t resid; /* bytes not yet consumed */ |
113 | bool last_piece; /* current is last piece */ | 116 | bool last_piece; /* current is last piece */ |
114 | bool need_crc; /* crc update needed */ | 117 | bool need_crc; /* crc update needed */ |
diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 8bfe7d34bc85..84703e550c26 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c | |||
@@ -734,7 +734,7 @@ static void ceph_msg_data_bio_cursor_init(struct ceph_msg_data_cursor *cursor, | |||
734 | BUG_ON(!bio); | 734 | BUG_ON(!bio); |
735 | BUG_ON(!bio->bi_vcnt); | 735 | BUG_ON(!bio->bi_vcnt); |
736 | 736 | ||
737 | cursor->resid = length; | 737 | cursor->resid = min(length, data->bio_length); |
738 | cursor->bio = bio; | 738 | cursor->bio = bio; |
739 | cursor->vector_index = 0; | 739 | cursor->vector_index = 0; |
740 | cursor->vector_offset = 0; | 740 | cursor->vector_offset = 0; |
@@ -833,9 +833,8 @@ static void ceph_msg_data_pages_cursor_init(struct ceph_msg_data_cursor *cursor, | |||
833 | 833 | ||
834 | BUG_ON(!data->pages); | 834 | BUG_ON(!data->pages); |
835 | BUG_ON(!data->length); | 835 | BUG_ON(!data->length); |
836 | BUG_ON(length > data->length); /* short reads are OK */ | ||
837 | 836 | ||
838 | cursor->resid = length; | 837 | cursor->resid = min(length, data->length); |
839 | page_count = calc_pages_for(data->alignment, (u64)data->length); | 838 | page_count = calc_pages_for(data->alignment, (u64)data->length); |
840 | cursor->page_offset = data->alignment & ~PAGE_MASK; | 839 | cursor->page_offset = data->alignment & ~PAGE_MASK; |
841 | cursor->page_index = 0; | 840 | cursor->page_index = 0; |
@@ -904,7 +903,6 @@ ceph_msg_data_pagelist_cursor_init(struct ceph_msg_data_cursor *cursor, | |||
904 | 903 | ||
905 | pagelist = data->pagelist; | 904 | pagelist = data->pagelist; |
906 | BUG_ON(!pagelist); | 905 | BUG_ON(!pagelist); |
907 | BUG_ON(length > pagelist->length); /* short reads are OK */ | ||
908 | 906 | ||
909 | if (!length) | 907 | if (!length) |
910 | return; /* pagelist can be assigned but empty */ | 908 | return; /* pagelist can be assigned but empty */ |
@@ -912,7 +910,7 @@ ceph_msg_data_pagelist_cursor_init(struct ceph_msg_data_cursor *cursor, | |||
912 | BUG_ON(list_empty(&pagelist->head)); | 910 | BUG_ON(list_empty(&pagelist->head)); |
913 | page = list_first_entry(&pagelist->head, struct page, lru); | 911 | page = list_first_entry(&pagelist->head, struct page, lru); |
914 | 912 | ||
915 | cursor->resid = length; | 913 | cursor->resid = min(length, pagelist->length); |
916 | cursor->page = page; | 914 | cursor->page = page; |
917 | cursor->offset = 0; | 915 | cursor->offset = 0; |
918 | cursor->last_piece = length <= PAGE_SIZE; | 916 | cursor->last_piece = length <= PAGE_SIZE; |
@@ -982,13 +980,10 @@ static bool ceph_msg_data_pagelist_advance(struct ceph_msg_data_cursor *cursor, | |||
982 | * be processed in that piece. It also tracks whether the current | 980 | * be processed in that piece. It also tracks whether the current |
983 | * piece is the last one in the data item. | 981 | * piece is the last one in the data item. |
984 | */ | 982 | */ |
985 | static void ceph_msg_data_cursor_init(struct ceph_msg *msg, size_t length) | 983 | static void __ceph_msg_data_cursor_init(struct ceph_msg_data_cursor *cursor) |
986 | { | 984 | { |
987 | struct ceph_msg_data_cursor *cursor = &msg->cursor; | 985 | size_t length = cursor->total_resid; |
988 | struct ceph_msg_data *data; | ||
989 | 986 | ||
990 | data = list_first_entry(&msg->data, struct ceph_msg_data, links); | ||
991 | cursor->data = data; | ||
992 | switch (cursor->data->type) { | 987 | switch (cursor->data->type) { |
993 | case CEPH_MSG_DATA_PAGELIST: | 988 | case CEPH_MSG_DATA_PAGELIST: |
994 | ceph_msg_data_pagelist_cursor_init(cursor, length); | 989 | ceph_msg_data_pagelist_cursor_init(cursor, length); |
@@ -1009,6 +1004,25 @@ static void ceph_msg_data_cursor_init(struct ceph_msg *msg, size_t length) | |||
1009 | cursor->need_crc = true; | 1004 | cursor->need_crc = true; |
1010 | } | 1005 | } |
1011 | 1006 | ||
1007 | static void ceph_msg_data_cursor_init(struct ceph_msg *msg, size_t length) | ||
1008 | { | ||
1009 | struct ceph_msg_data_cursor *cursor = &msg->cursor; | ||
1010 | struct ceph_msg_data *data; | ||
1011 | |||
1012 | BUG_ON(!length); | ||
1013 | BUG_ON(length > msg->data_length); | ||
1014 | BUG_ON(list_empty(&msg->data)); | ||
1015 | |||
1016 | data = list_first_entry(&msg->data, struct ceph_msg_data, links); | ||
1017 | |||
1018 | cursor->data_head = &msg->data; | ||
1019 | cursor->total_resid = length; | ||
1020 | data = list_first_entry(&msg->data, struct ceph_msg_data, links); | ||
1021 | cursor->data = data; | ||
1022 | |||
1023 | __ceph_msg_data_cursor_init(cursor); | ||
1024 | } | ||
1025 | |||
1012 | /* | 1026 | /* |
1013 | * Return the page containing the next piece to process for a given | 1027 | * Return the page containing the next piece to process for a given |
1014 | * data item, and supply the page offset and length of that piece. | 1028 | * data item, and supply the page offset and length of that piece. |
@@ -1073,8 +1087,16 @@ static bool ceph_msg_data_advance(struct ceph_msg_data_cursor *cursor, | |||
1073 | BUG(); | 1087 | BUG(); |
1074 | break; | 1088 | break; |
1075 | } | 1089 | } |
1090 | cursor->total_resid -= bytes; | ||
1076 | cursor->need_crc = new_piece; | 1091 | cursor->need_crc = new_piece; |
1077 | 1092 | ||
1093 | if (!cursor->resid && cursor->total_resid) { | ||
1094 | WARN_ON(!cursor->last_piece); | ||
1095 | BUG_ON(list_is_last(&cursor->data->links, cursor->data_head)); | ||
1096 | cursor->data = list_entry_next(cursor->data, links); | ||
1097 | __ceph_msg_data_cursor_init(cursor); | ||
1098 | } | ||
1099 | |||
1078 | return new_piece; | 1100 | return new_piece; |
1079 | } | 1101 | } |
1080 | 1102 | ||
@@ -2990,8 +3012,6 @@ void ceph_msg_data_set_pages(struct ceph_msg *msg, struct page **pages, | |||
2990 | 3012 | ||
2991 | BUG_ON(!pages); | 3013 | BUG_ON(!pages); |
2992 | BUG_ON(!length); | 3014 | BUG_ON(!length); |
2993 | BUG_ON(msg->data_length); | ||
2994 | BUG_ON(!list_empty(&msg->data)); | ||
2995 | 3015 | ||
2996 | data = ceph_msg_data_create(CEPH_MSG_DATA_PAGES); | 3016 | data = ceph_msg_data_create(CEPH_MSG_DATA_PAGES); |
2997 | BUG_ON(!data); | 3017 | BUG_ON(!data); |
@@ -3012,8 +3032,6 @@ void ceph_msg_data_set_pagelist(struct ceph_msg *msg, | |||
3012 | 3032 | ||
3013 | BUG_ON(!pagelist); | 3033 | BUG_ON(!pagelist); |
3014 | BUG_ON(!pagelist->length); | 3034 | BUG_ON(!pagelist->length); |
3015 | BUG_ON(msg->data_length); | ||
3016 | BUG_ON(!list_empty(&msg->data)); | ||
3017 | 3035 | ||
3018 | data = ceph_msg_data_create(CEPH_MSG_DATA_PAGELIST); | 3036 | data = ceph_msg_data_create(CEPH_MSG_DATA_PAGELIST); |
3019 | BUG_ON(!data); | 3037 | BUG_ON(!data); |
@@ -3031,8 +3049,6 @@ void ceph_msg_data_set_bio(struct ceph_msg *msg, struct bio *bio, | |||
3031 | struct ceph_msg_data *data; | 3049 | struct ceph_msg_data *data; |
3032 | 3050 | ||
3033 | BUG_ON(!bio); | 3051 | BUG_ON(!bio); |
3034 | BUG_ON(msg->data_length); | ||
3035 | BUG_ON(!list_empty(&msg->data)); | ||
3036 | 3052 | ||
3037 | data = ceph_msg_data_create(CEPH_MSG_DATA_BIO); | 3053 | data = ceph_msg_data_create(CEPH_MSG_DATA_BIO); |
3038 | BUG_ON(!data); | 3054 | BUG_ON(!data); |