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>
This commit is contained in:
Yan, Zheng 2014-09-16 17:50:45 +08:00 committed by Sage Weil
parent 0abb43dcac
commit e4339d28f6
4 changed files with 10 additions and 7 deletions

View file

@ -2865,7 +2865,6 @@ fail:
mutex_unlock(&session->s_mutex);
fail_nomsg:
ceph_pagelist_release(pagelist);
kfree(pagelist);
fail_nopagelist:
pr_err("error %d preparing reconnect for mds%d\n", err, mds);
return;

View file

@ -2,6 +2,7 @@
#define __FS_CEPH_PAGELIST_H
#include <linux/list.h>
#include <linux/atomic.h>
struct ceph_pagelist {
struct list_head head;
@ -10,6 +11,7 @@ struct ceph_pagelist {
size_t room;
struct list_head free_list;
size_t num_pages_free;
atomic_t refcnt;
};
struct ceph_pagelist_cursor {
@ -26,9 +28,10 @@ static inline void ceph_pagelist_init(struct ceph_pagelist *pl)
pl->room = 0;
INIT_LIST_HEAD(&pl->free_list);
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);

View file

@ -3071,10 +3071,8 @@ static void ceph_msg_data_destroy(struct ceph_msg_data *data)
return;
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);
kfree(data->pagelist);
}
kmem_cache_free(ceph_msg_data_cache, data);
}

View file

@ -1,5 +1,6 @@
#include <linux/module.h>
#include <linux/gfp.h>
#include <linux/slab.h>
#include <linux/pagemap.h>
#include <linux/highmem.h>
#include <linux/ceph/pagelist.h>
@ -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);
while (!list_empty(&pl->head)) {
struct page *page = list_first_entry(&pl->head, struct page,
@ -23,7 +26,7 @@ int ceph_pagelist_release(struct ceph_pagelist *pl)
__free_page(page);
}
ceph_pagelist_free_reserve(pl);
return 0;
kfree(pl);
}
EXPORT_SYMBOL(ceph_pagelist_release);