Commit e4339d28 authored by Yan, Zheng's avatar Yan, Zheng Committed by Sage Weil

libceph: reference counting pagelist

this allow pagelist to present data that may be sent multiple times.
Signed-off-by: default avatarYan, Zheng <zyan@redhat.com>
Reviewed-by: default avatarSage Weil <sage@redhat.com>
parent 0abb43dc
...@@ -2865,7 +2865,6 @@ static void send_mds_reconnect(struct ceph_mds_client *mdsc, ...@@ -2865,7 +2865,6 @@ static void send_mds_reconnect(struct ceph_mds_client *mdsc,
mutex_unlock(&session->s_mutex); mutex_unlock(&session->s_mutex);
fail_nomsg: fail_nomsg:
ceph_pagelist_release(pagelist); ceph_pagelist_release(pagelist);
kfree(pagelist);
fail_nopagelist: fail_nopagelist:
pr_err("error %d preparing reconnect for mds%d\n", err, mds); pr_err("error %d preparing reconnect for mds%d\n", err, mds);
return; return;
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#define __FS_CEPH_PAGELIST_H #define __FS_CEPH_PAGELIST_H
#include <linux/list.h> #include <linux/list.h>
#include <linux/atomic.h>
struct ceph_pagelist { struct ceph_pagelist {
struct list_head head; struct list_head head;
...@@ -10,6 +11,7 @@ struct ceph_pagelist { ...@@ -10,6 +11,7 @@ struct ceph_pagelist {
size_t room; size_t room;
struct list_head free_list; struct list_head free_list;
size_t num_pages_free; size_t num_pages_free;
atomic_t refcnt;
}; };
struct ceph_pagelist_cursor { struct ceph_pagelist_cursor {
...@@ -26,9 +28,10 @@ static inline void ceph_pagelist_init(struct ceph_pagelist *pl) ...@@ -26,9 +28,10 @@ static inline void ceph_pagelist_init(struct ceph_pagelist *pl)
pl->room = 0; pl->room = 0;
INIT_LIST_HEAD(&pl->free_list); INIT_LIST_HEAD(&pl->free_list);
pl->num_pages_free = 0; pl->num_pages_free = 0;
atomic_set(&pl->refcnt, 1);
} }
extern int ceph_pagelist_release(struct ceph_pagelist *pl); extern void ceph_pagelist_release(struct ceph_pagelist *pl);
extern int ceph_pagelist_append(struct ceph_pagelist *pl, const void *d, size_t l); extern int ceph_pagelist_append(struct ceph_pagelist *pl, const void *d, size_t l);
......
...@@ -3071,10 +3071,8 @@ static void ceph_msg_data_destroy(struct ceph_msg_data *data) ...@@ -3071,10 +3071,8 @@ static void ceph_msg_data_destroy(struct ceph_msg_data *data)
return; return;
WARN_ON(!list_empty(&data->links)); WARN_ON(!list_empty(&data->links));
if (data->type == CEPH_MSG_DATA_PAGELIST) { if (data->type == CEPH_MSG_DATA_PAGELIST)
ceph_pagelist_release(data->pagelist); ceph_pagelist_release(data->pagelist);
kfree(data->pagelist);
}
kmem_cache_free(ceph_msg_data_cache, data); kmem_cache_free(ceph_msg_data_cache, data);
} }
......
#include <linux/module.h> #include <linux/module.h>
#include <linux/gfp.h> #include <linux/gfp.h>
#include <linux/slab.h>
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include <linux/highmem.h> #include <linux/highmem.h>
#include <linux/ceph/pagelist.h> #include <linux/ceph/pagelist.h>
...@@ -13,8 +14,10 @@ static void ceph_pagelist_unmap_tail(struct ceph_pagelist *pl) ...@@ -13,8 +14,10 @@ static void ceph_pagelist_unmap_tail(struct ceph_pagelist *pl)
} }
} }
int ceph_pagelist_release(struct ceph_pagelist *pl) void ceph_pagelist_release(struct ceph_pagelist *pl)
{ {
if (!atomic_dec_and_test(&pl->refcnt))
return;
ceph_pagelist_unmap_tail(pl); ceph_pagelist_unmap_tail(pl);
while (!list_empty(&pl->head)) { while (!list_empty(&pl->head)) {
struct page *page = list_first_entry(&pl->head, struct page, struct page *page = list_first_entry(&pl->head, struct page,
...@@ -23,7 +26,7 @@ int ceph_pagelist_release(struct ceph_pagelist *pl) ...@@ -23,7 +26,7 @@ int ceph_pagelist_release(struct ceph_pagelist *pl)
__free_page(page); __free_page(page);
} }
ceph_pagelist_free_reserve(pl); ceph_pagelist_free_reserve(pl);
return 0; kfree(pl);
} }
EXPORT_SYMBOL(ceph_pagelist_release); EXPORT_SYMBOL(ceph_pagelist_release);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment