Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Yan, Zheng and committed by
Sage Weil
e4339d28 0abb43dc

+10 -7
-1
fs/ceph/mds_client.c
··· 2865 2865 mutex_unlock(&session->s_mutex); 2866 2866 fail_nomsg: 2867 2867 ceph_pagelist_release(pagelist); 2868 - kfree(pagelist); 2869 2868 fail_nopagelist: 2870 2869 pr_err("error %d preparing reconnect for mds%d\n", err, mds); 2871 2870 return;
+4 -1
include/linux/ceph/pagelist.h
··· 2 2 #define __FS_CEPH_PAGELIST_H 3 3 4 4 #include <linux/list.h> 5 + #include <linux/atomic.h> 5 6 6 7 struct ceph_pagelist { 7 8 struct list_head head; ··· 11 10 size_t room; 12 11 struct list_head free_list; 13 12 size_t num_pages_free; 13 + atomic_t refcnt; 14 14 }; 15 15 16 16 struct ceph_pagelist_cursor { ··· 28 26 pl->room = 0; 29 27 INIT_LIST_HEAD(&pl->free_list); 30 28 pl->num_pages_free = 0; 29 + atomic_set(&pl->refcnt, 1); 31 30 } 32 31 33 - extern int ceph_pagelist_release(struct ceph_pagelist *pl); 32 + extern void ceph_pagelist_release(struct ceph_pagelist *pl); 34 33 35 34 extern int ceph_pagelist_append(struct ceph_pagelist *pl, const void *d, size_t l); 36 35
+1 -3
net/ceph/messenger.c
··· 3071 3071 return; 3072 3072 3073 3073 WARN_ON(!list_empty(&data->links)); 3074 - if (data->type == CEPH_MSG_DATA_PAGELIST) { 3074 + if (data->type == CEPH_MSG_DATA_PAGELIST) 3075 3075 ceph_pagelist_release(data->pagelist); 3076 - kfree(data->pagelist); 3077 - } 3078 3076 kmem_cache_free(ceph_msg_data_cache, data); 3079 3077 } 3080 3078
+5 -2
net/ceph/pagelist.c
··· 1 1 #include <linux/module.h> 2 2 #include <linux/gfp.h> 3 + #include <linux/slab.h> 3 4 #include <linux/pagemap.h> 4 5 #include <linux/highmem.h> 5 6 #include <linux/ceph/pagelist.h> ··· 14 13 } 15 14 } 16 15 17 - int ceph_pagelist_release(struct ceph_pagelist *pl) 16 + void ceph_pagelist_release(struct ceph_pagelist *pl) 18 17 { 18 + if (!atomic_dec_and_test(&pl->refcnt)) 19 + return; 19 20 ceph_pagelist_unmap_tail(pl); 20 21 while (!list_empty(&pl->head)) { 21 22 struct page *page = list_first_entry(&pl->head, struct page, ··· 26 23 __free_page(page); 27 24 } 28 25 ceph_pagelist_free_reserve(pl); 29 - return 0; 26 + kfree(pl); 30 27 } 31 28 EXPORT_SYMBOL(ceph_pagelist_release); 32 29