aboutsummaryrefslogtreecommitdiffstats
path: root/net/ceph
diff options
context:
space:
mode:
Diffstat (limited to 'net/ceph')
-rw-r--r--net/ceph/messenger.c46
1 files changed, 31 insertions, 15 deletions
diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c
index 3aa0f30c3c5e..8bfe7d34bc85 100644
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -985,8 +985,10 @@ static bool ceph_msg_data_pagelist_advance(struct ceph_msg_data_cursor *cursor,
985static void ceph_msg_data_cursor_init(struct ceph_msg *msg, size_t length) 985static void ceph_msg_data_cursor_init(struct ceph_msg *msg, size_t length)
986{ 986{
987 struct ceph_msg_data_cursor *cursor = &msg->cursor; 987 struct ceph_msg_data_cursor *cursor = &msg->cursor;
988 struct ceph_msg_data *data;
988 989
989 cursor->data = msg->data; 990 data = list_first_entry(&msg->data, struct ceph_msg_data, links);
991 cursor->data = data;
990 switch (cursor->data->type) { 992 switch (cursor->data->type) {
991 case CEPH_MSG_DATA_PAGELIST: 993 case CEPH_MSG_DATA_PAGELIST:
992 ceph_msg_data_pagelist_cursor_init(cursor, length); 994 ceph_msg_data_pagelist_cursor_init(cursor, length);
@@ -1410,7 +1412,7 @@ static int write_partial_message_data(struct ceph_connection *con)
1410 1412
1411 dout("%s %p msg %p\n", __func__, con, msg); 1413 dout("%s %p msg %p\n", __func__, con, msg);
1412 1414
1413 if (WARN_ON(!msg->data)) 1415 if (list_empty(&msg->data))
1414 return -EINVAL; 1416 return -EINVAL;
1415 1417
1416 /* 1418 /*
@@ -2111,7 +2113,7 @@ static int read_partial_msg_data(struct ceph_connection *con)
2111 int ret; 2113 int ret;
2112 2114
2113 BUG_ON(!msg); 2115 BUG_ON(!msg);
2114 if (!msg->data) 2116 if (list_empty(&msg->data))
2115 return -EIO; 2117 return -EIO;
2116 2118
2117 if (do_datacrc) 2119 if (do_datacrc)
@@ -2963,6 +2965,7 @@ static struct ceph_msg_data *ceph_msg_data_create(enum ceph_msg_data_type type)
2963 data = kzalloc(sizeof (*data), GFP_NOFS); 2965 data = kzalloc(sizeof (*data), GFP_NOFS);
2964 if (data) 2966 if (data)
2965 data->type = type; 2967 data->type = type;
2968 INIT_LIST_HEAD(&data->links);
2966 2969
2967 return data; 2970 return data;
2968} 2971}
@@ -2972,6 +2975,7 @@ static void ceph_msg_data_destroy(struct ceph_msg_data *data)
2972 if (!data) 2975 if (!data)
2973 return; 2976 return;
2974 2977
2978 WARN_ON(!list_empty(&data->links));
2975 if (data->type == CEPH_MSG_DATA_PAGELIST) { 2979 if (data->type == CEPH_MSG_DATA_PAGELIST) {
2976 ceph_pagelist_release(data->pagelist); 2980 ceph_pagelist_release(data->pagelist);
2977 kfree(data->pagelist); 2981 kfree(data->pagelist);
@@ -2987,7 +2991,7 @@ void ceph_msg_data_set_pages(struct ceph_msg *msg, struct page **pages,
2987 BUG_ON(!pages); 2991 BUG_ON(!pages);
2988 BUG_ON(!length); 2992 BUG_ON(!length);
2989 BUG_ON(msg->data_length); 2993 BUG_ON(msg->data_length);
2990 BUG_ON(msg->data != NULL); 2994 BUG_ON(!list_empty(&msg->data));
2991 2995
2992 data = ceph_msg_data_create(CEPH_MSG_DATA_PAGES); 2996 data = ceph_msg_data_create(CEPH_MSG_DATA_PAGES);
2993 BUG_ON(!data); 2997 BUG_ON(!data);
@@ -2995,8 +2999,9 @@ void ceph_msg_data_set_pages(struct ceph_msg *msg, struct page **pages,
2995 data->length = length; 2999 data->length = length;
2996 data->alignment = alignment & ~PAGE_MASK; 3000 data->alignment = alignment & ~PAGE_MASK;
2997 3001
2998 msg->data = data; 3002 BUG_ON(!list_empty(&msg->data));
2999 msg->data_length = length; 3003 list_add_tail(&data->links, &msg->data);
3004 msg->data_length += length;
3000} 3005}
3001EXPORT_SYMBOL(ceph_msg_data_set_pages); 3006EXPORT_SYMBOL(ceph_msg_data_set_pages);
3002 3007
@@ -3008,14 +3013,14 @@ void ceph_msg_data_set_pagelist(struct ceph_msg *msg,
3008 BUG_ON(!pagelist); 3013 BUG_ON(!pagelist);
3009 BUG_ON(!pagelist->length); 3014 BUG_ON(!pagelist->length);
3010 BUG_ON(msg->data_length); 3015 BUG_ON(msg->data_length);
3011 BUG_ON(msg->data != NULL); 3016 BUG_ON(!list_empty(&msg->data));
3012 3017
3013 data = ceph_msg_data_create(CEPH_MSG_DATA_PAGELIST); 3018 data = ceph_msg_data_create(CEPH_MSG_DATA_PAGELIST);
3014 BUG_ON(!data); 3019 BUG_ON(!data);
3015 data->pagelist = pagelist; 3020 data->pagelist = pagelist;
3016 3021
3017 msg->data = data; 3022 list_add_tail(&data->links, &msg->data);
3018 msg->data_length = pagelist->length; 3023 msg->data_length += pagelist->length;
3019} 3024}
3020EXPORT_SYMBOL(ceph_msg_data_set_pagelist); 3025EXPORT_SYMBOL(ceph_msg_data_set_pagelist);
3021 3026
@@ -3027,15 +3032,15 @@ void ceph_msg_data_set_bio(struct ceph_msg *msg, struct bio *bio,
3027 3032
3028 BUG_ON(!bio); 3033 BUG_ON(!bio);
3029 BUG_ON(msg->data_length); 3034 BUG_ON(msg->data_length);
3030 BUG_ON(msg->data != NULL); 3035 BUG_ON(!list_empty(&msg->data));
3031 3036
3032 data = ceph_msg_data_create(CEPH_MSG_DATA_BIO); 3037 data = ceph_msg_data_create(CEPH_MSG_DATA_BIO);
3033 BUG_ON(!data); 3038 BUG_ON(!data);
3034 data->bio = bio; 3039 data->bio = bio;
3035 data->bio_length = length; 3040 data->bio_length = length;
3036 3041
3037 msg->data = data; 3042 list_add_tail(&data->links, &msg->data);
3038 msg->data_length = length; 3043 msg->data_length += length;
3039} 3044}
3040EXPORT_SYMBOL(ceph_msg_data_set_bio); 3045EXPORT_SYMBOL(ceph_msg_data_set_bio);
3041#endif /* CONFIG_BLOCK */ 3046#endif /* CONFIG_BLOCK */
@@ -3059,6 +3064,7 @@ struct ceph_msg *ceph_msg_new(int type, int front_len, gfp_t flags,
3059 3064
3060 INIT_LIST_HEAD(&m->list_head); 3065 INIT_LIST_HEAD(&m->list_head);
3061 kref_init(&m->kref); 3066 kref_init(&m->kref);
3067 INIT_LIST_HEAD(&m->data);
3062 3068
3063 /* front */ 3069 /* front */
3064 m->front_max = front_len; 3070 m->front_max = front_len;
@@ -3204,6 +3210,9 @@ void ceph_msg_kfree(struct ceph_msg *m)
3204void ceph_msg_last_put(struct kref *kref) 3210void ceph_msg_last_put(struct kref *kref)
3205{ 3211{
3206 struct ceph_msg *m = container_of(kref, struct ceph_msg, kref); 3212 struct ceph_msg *m = container_of(kref, struct ceph_msg, kref);
3213 LIST_HEAD(data);
3214 struct list_head *links;
3215 struct list_head *next;
3207 3216
3208 dout("ceph_msg_put last one on %p\n", m); 3217 dout("ceph_msg_put last one on %p\n", m);
3209 WARN_ON(!list_empty(&m->list_head)); 3218 WARN_ON(!list_empty(&m->list_head));
@@ -3213,8 +3222,15 @@ void ceph_msg_last_put(struct kref *kref)
3213 ceph_buffer_put(m->middle); 3222 ceph_buffer_put(m->middle);
3214 m->middle = NULL; 3223 m->middle = NULL;
3215 } 3224 }
3216 ceph_msg_data_destroy(m->data); 3225
3217 m->data = NULL; 3226 list_splice_init(&m->data, &data);
3227 list_for_each_safe(links, next, &data) {
3228 struct ceph_msg_data *data;
3229
3230 data = list_entry(links, struct ceph_msg_data, links);
3231 list_del_init(links);
3232 ceph_msg_data_destroy(data);
3233 }
3218 m->data_length = 0; 3234 m->data_length = 0;
3219 3235
3220 if (m->pool) 3236 if (m->pool)
@@ -3227,7 +3243,7 @@ EXPORT_SYMBOL(ceph_msg_last_put);
3227void ceph_msg_dump(struct ceph_msg *msg) 3243void ceph_msg_dump(struct ceph_msg *msg)
3228{ 3244{
3229 pr_debug("msg_dump %p (front_max %d length %zd)\n", msg, 3245 pr_debug("msg_dump %p (front_max %d length %zd)\n", msg,
3230 msg->front_max, msg->data->length); 3246 msg->front_max, msg->data_length);
3231 print_hex_dump(KERN_DEBUG, "header: ", 3247 print_hex_dump(KERN_DEBUG, "header: ",
3232 DUMP_PREFIX_OFFSET, 16, 1, 3248 DUMP_PREFIX_OFFSET, 16, 1,
3233 &msg->hdr, sizeof(msg->hdr), true); 3249 &msg->hdr, sizeof(msg->hdr), true);