diff options
Diffstat (limited to 'net/ceph')
-rw-r--r-- | net/ceph/messenger.c | 46 |
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, | |||
985 | static void ceph_msg_data_cursor_init(struct ceph_msg *msg, size_t length) | 985 | static 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 | } |
3001 | EXPORT_SYMBOL(ceph_msg_data_set_pages); | 3006 | EXPORT_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 | } |
3020 | EXPORT_SYMBOL(ceph_msg_data_set_pagelist); | 3025 | EXPORT_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 | } |
3040 | EXPORT_SYMBOL(ceph_msg_data_set_bio); | 3045 | EXPORT_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) | |||
3204 | void ceph_msg_last_put(struct kref *kref) | 3210 | void 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); | |||
3227 | void ceph_msg_dump(struct ceph_msg *msg) | 3243 | void 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); |