diff options
author | Yan, Zheng <zyan@redhat.com> | 2014-09-16 05:50:45 -0400 |
---|---|---|
committer | Sage Weil <sage@redhat.com> | 2014-10-14 15:56:48 -0400 |
commit | e4339d28f640a7c0d92903bcf389a2dfa281270d (patch) | |
tree | 428c172af1081d29613732cdcf7801f958be358f | |
parent | 0abb43dcacb52145aa265f82c914375d59dfe2da (diff) |
libceph: reference counting pagelist
this allow pagelist to present data that may be sent multiple times.
Signed-off-by: Yan, Zheng <zyan@redhat.com>
Reviewed-by: Sage Weil <sage@redhat.com>
-rw-r--r-- | fs/ceph/mds_client.c | 1 | ||||
-rw-r--r-- | include/linux/ceph/pagelist.h | 5 | ||||
-rw-r--r-- | net/ceph/messenger.c | 4 | ||||
-rw-r--r-- | net/ceph/pagelist.c | 7 |
4 files changed, 10 insertions, 7 deletions
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 5474feb77743..b4430ce1b3f6 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c | |||
@@ -2865,7 +2865,6 @@ fail: | |||
2865 | mutex_unlock(&session->s_mutex); | 2865 | mutex_unlock(&session->s_mutex); |
2866 | fail_nomsg: | 2866 | fail_nomsg: |
2867 | ceph_pagelist_release(pagelist); | 2867 | ceph_pagelist_release(pagelist); |
2868 | kfree(pagelist); | ||
2869 | fail_nopagelist: | 2868 | fail_nopagelist: |
2870 | pr_err("error %d preparing reconnect for mds%d\n", err, mds); | 2869 | pr_err("error %d preparing reconnect for mds%d\n", err, mds); |
2871 | return; | 2870 | return; |
diff --git a/include/linux/ceph/pagelist.h b/include/linux/ceph/pagelist.h index 9660d6b0a35d..5f871d84ddce 100644 --- a/include/linux/ceph/pagelist.h +++ b/include/linux/ceph/pagelist.h | |||
@@ -2,6 +2,7 @@ | |||
2 | #define __FS_CEPH_PAGELIST_H | 2 | #define __FS_CEPH_PAGELIST_H |
3 | 3 | ||
4 | #include <linux/list.h> | 4 | #include <linux/list.h> |
5 | #include <linux/atomic.h> | ||
5 | 6 | ||
6 | struct ceph_pagelist { | 7 | struct ceph_pagelist { |
7 | struct list_head head; | 8 | struct list_head head; |
@@ -10,6 +11,7 @@ struct ceph_pagelist { | |||
10 | size_t room; | 11 | size_t room; |
11 | struct list_head free_list; | 12 | struct list_head free_list; |
12 | size_t num_pages_free; | 13 | size_t num_pages_free; |
14 | atomic_t refcnt; | ||
13 | }; | 15 | }; |
14 | 16 | ||
15 | struct ceph_pagelist_cursor { | 17 | struct ceph_pagelist_cursor { |
@@ -26,9 +28,10 @@ static inline void ceph_pagelist_init(struct ceph_pagelist *pl) | |||
26 | pl->room = 0; | 28 | pl->room = 0; |
27 | INIT_LIST_HEAD(&pl->free_list); | 29 | INIT_LIST_HEAD(&pl->free_list); |
28 | pl->num_pages_free = 0; | 30 | pl->num_pages_free = 0; |
31 | atomic_set(&pl->refcnt, 1); | ||
29 | } | 32 | } |
30 | 33 | ||
31 | extern int ceph_pagelist_release(struct ceph_pagelist *pl); | 34 | extern void ceph_pagelist_release(struct ceph_pagelist *pl); |
32 | 35 | ||
33 | extern int ceph_pagelist_append(struct ceph_pagelist *pl, const void *d, size_t l); | 36 | extern int ceph_pagelist_append(struct ceph_pagelist *pl, const void *d, size_t l); |
34 | 37 | ||
diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index e7d94113f2d6..9764c771cfb1 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c | |||
@@ -3071,10 +3071,8 @@ static void ceph_msg_data_destroy(struct ceph_msg_data *data) | |||
3071 | return; | 3071 | return; |
3072 | 3072 | ||
3073 | WARN_ON(!list_empty(&data->links)); | 3073 | WARN_ON(!list_empty(&data->links)); |
3074 | if (data->type == CEPH_MSG_DATA_PAGELIST) { | 3074 | if (data->type == CEPH_MSG_DATA_PAGELIST) |
3075 | ceph_pagelist_release(data->pagelist); | 3075 | ceph_pagelist_release(data->pagelist); |
3076 | kfree(data->pagelist); | ||
3077 | } | ||
3078 | kmem_cache_free(ceph_msg_data_cache, data); | 3076 | kmem_cache_free(ceph_msg_data_cache, data); |
3079 | } | 3077 | } |
3080 | 3078 | ||
diff --git a/net/ceph/pagelist.c b/net/ceph/pagelist.c index 92866bebb65f..c7c220a736e5 100644 --- a/net/ceph/pagelist.c +++ b/net/ceph/pagelist.c | |||
@@ -1,5 +1,6 @@ | |||
1 | #include <linux/module.h> | 1 | #include <linux/module.h> |
2 | #include <linux/gfp.h> | 2 | #include <linux/gfp.h> |
3 | #include <linux/slab.h> | ||
3 | #include <linux/pagemap.h> | 4 | #include <linux/pagemap.h> |
4 | #include <linux/highmem.h> | 5 | #include <linux/highmem.h> |
5 | #include <linux/ceph/pagelist.h> | 6 | #include <linux/ceph/pagelist.h> |
@@ -13,8 +14,10 @@ static void ceph_pagelist_unmap_tail(struct ceph_pagelist *pl) | |||
13 | } | 14 | } |
14 | } | 15 | } |
15 | 16 | ||
16 | int ceph_pagelist_release(struct ceph_pagelist *pl) | 17 | void ceph_pagelist_release(struct ceph_pagelist *pl) |
17 | { | 18 | { |
19 | if (!atomic_dec_and_test(&pl->refcnt)) | ||
20 | return; | ||
18 | ceph_pagelist_unmap_tail(pl); | 21 | ceph_pagelist_unmap_tail(pl); |
19 | while (!list_empty(&pl->head)) { | 22 | while (!list_empty(&pl->head)) { |
20 | struct page *page = list_first_entry(&pl->head, struct page, | 23 | struct page *page = list_first_entry(&pl->head, struct page, |
@@ -23,7 +26,7 @@ int ceph_pagelist_release(struct ceph_pagelist *pl) | |||
23 | __free_page(page); | 26 | __free_page(page); |
24 | } | 27 | } |
25 | ceph_pagelist_free_reserve(pl); | 28 | ceph_pagelist_free_reserve(pl); |
26 | return 0; | 29 | kfree(pl); |
27 | } | 30 | } |
28 | EXPORT_SYMBOL(ceph_pagelist_release); | 31 | EXPORT_SYMBOL(ceph_pagelist_release); |
29 | 32 | ||