diff options
-rw-r--r-- | fs/ceph/buffer.c | 14 | ||||
-rw-r--r-- | fs/ceph/buffer.h | 18 |
2 files changed, 20 insertions, 12 deletions
diff --git a/fs/ceph/buffer.c b/fs/ceph/buffer.c index cf9aaccef22b..847c5da9a0db 100644 --- a/fs/ceph/buffer.c +++ b/fs/ceph/buffer.c | |||
@@ -9,13 +9,25 @@ struct ceph_buffer *ceph_buffer_new(gfp_t gfp) | |||
9 | b = kmalloc(sizeof(*b), gfp); | 9 | b = kmalloc(sizeof(*b), gfp); |
10 | if (!b) | 10 | if (!b) |
11 | return NULL; | 11 | return NULL; |
12 | atomic_set(&b->nref, 1); | 12 | kref_init(&b->kref); |
13 | b->vec.iov_base = NULL; | 13 | b->vec.iov_base = NULL; |
14 | b->vec.iov_len = 0; | 14 | b->vec.iov_len = 0; |
15 | b->alloc_len = 0; | 15 | b->alloc_len = 0; |
16 | return b; | 16 | return b; |
17 | } | 17 | } |
18 | 18 | ||
19 | void ceph_buffer_release(struct kref *kref) | ||
20 | { | ||
21 | struct ceph_buffer *b = container_of(kref, struct ceph_buffer, kref); | ||
22 | if (b->vec.iov_base) { | ||
23 | if (b->is_vmalloc) | ||
24 | vfree(b->vec.iov_base); | ||
25 | else | ||
26 | kfree(b->vec.iov_base); | ||
27 | } | ||
28 | kfree(b); | ||
29 | } | ||
30 | |||
19 | int ceph_buffer_alloc(struct ceph_buffer *b, int len, gfp_t gfp) | 31 | int ceph_buffer_alloc(struct ceph_buffer *b, int len, gfp_t gfp) |
20 | { | 32 | { |
21 | b->vec.iov_base = kmalloc(len, gfp | __GFP_NOWARN); | 33 | b->vec.iov_base = kmalloc(len, gfp | __GFP_NOWARN); |
diff --git a/fs/ceph/buffer.h b/fs/ceph/buffer.h index 16b1930acc45..3f541a13094f 100644 --- a/fs/ceph/buffer.h +++ b/fs/ceph/buffer.h | |||
@@ -1,6 +1,7 @@ | |||
1 | #ifndef __FS_CEPH_BUFFER_H | 1 | #ifndef __FS_CEPH_BUFFER_H |
2 | #define __FS_CEPH_BUFFER_H | 2 | #define __FS_CEPH_BUFFER_H |
3 | 3 | ||
4 | #include <linux/kref.h> | ||
4 | #include <linux/mm.h> | 5 | #include <linux/mm.h> |
5 | #include <linux/vmalloc.h> | 6 | #include <linux/vmalloc.h> |
6 | #include <linux/types.h> | 7 | #include <linux/types.h> |
@@ -13,7 +14,7 @@ | |||
13 | * sizes. | 14 | * sizes. |
14 | */ | 15 | */ |
15 | struct ceph_buffer { | 16 | struct ceph_buffer { |
16 | atomic_t nref; | 17 | struct kref kref; |
17 | struct kvec vec; | 18 | struct kvec vec; |
18 | size_t alloc_len; | 19 | size_t alloc_len; |
19 | bool is_vmalloc; | 20 | bool is_vmalloc; |
@@ -24,21 +25,16 @@ int ceph_buffer_alloc(struct ceph_buffer *b, int len, gfp_t gfp); | |||
24 | 25 | ||
25 | static inline struct ceph_buffer *ceph_buffer_get(struct ceph_buffer *b) | 26 | static inline struct ceph_buffer *ceph_buffer_get(struct ceph_buffer *b) |
26 | { | 27 | { |
27 | atomic_inc(&b->nref); | 28 | kref_get(&b->kref); |
28 | return b; | 29 | return b; |
29 | } | 30 | } |
30 | 31 | ||
32 | void ceph_buffer_release(struct kref *kref); | ||
33 | |||
31 | static inline void ceph_buffer_put(struct ceph_buffer *b) | 34 | static inline void ceph_buffer_put(struct ceph_buffer *b) |
32 | { | 35 | { |
33 | if (b && atomic_dec_and_test(&b->nref)) { | 36 | if (b) |
34 | if (b->vec.iov_base) { | 37 | kref_put(&b->kref, ceph_buffer_release); |
35 | if (b->is_vmalloc) | ||
36 | vfree(b->vec.iov_base); | ||
37 | else | ||
38 | kfree(b->vec.iov_base); | ||
39 | } | ||
40 | kfree(b); | ||
41 | } | ||
42 | } | 38 | } |
43 | 39 | ||
44 | static inline struct ceph_buffer *ceph_buffer_new_alloc(int len, gfp_t gfp) | 40 | static inline struct ceph_buffer *ceph_buffer_new_alloc(int len, gfp_t gfp) |