aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYan, Zheng <zyan@redhat.com>2014-09-16 05:50:45 -0400
committerSage Weil <sage@redhat.com>2014-10-14 15:56:48 -0400
commite4339d28f640a7c0d92903bcf389a2dfa281270d (patch)
tree428c172af1081d29613732cdcf7801f958be358f
parent0abb43dcacb52145aa265f82c914375d59dfe2da (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.c1
-rw-r--r--include/linux/ceph/pagelist.h5
-rw-r--r--net/ceph/messenger.c4
-rw-r--r--net/ceph/pagelist.c7
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);
2866fail_nomsg: 2866fail_nomsg:
2867 ceph_pagelist_release(pagelist); 2867 ceph_pagelist_release(pagelist);
2868 kfree(pagelist);
2869fail_nopagelist: 2868fail_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
6struct ceph_pagelist { 7struct 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
15struct ceph_pagelist_cursor { 17struct 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
31extern int ceph_pagelist_release(struct ceph_pagelist *pl); 34extern void ceph_pagelist_release(struct ceph_pagelist *pl);
32 35
33extern int ceph_pagelist_append(struct ceph_pagelist *pl, const void *d, size_t l); 36extern 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
16int ceph_pagelist_release(struct ceph_pagelist *pl) 17void 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}
28EXPORT_SYMBOL(ceph_pagelist_release); 31EXPORT_SYMBOL(ceph_pagelist_release);
29 32