| #ifndef __FS_CEPH_BUFFER_H |
| #define __FS_CEPH_BUFFER_H |
| |
| #include <linux/mm.h> |
| #include <linux/vmalloc.h> |
| #include <linux/types.h> |
| #include <linux/uio.h> |
| |
| /* |
| * a simple reference counted buffer. |
| * |
| * use kmalloc for small sizes (<= one page), vmalloc for larger |
| * sizes. |
| */ |
| struct ceph_buffer { |
| atomic_t nref; |
| struct kvec vec; |
| size_t alloc_len; |
| bool is_vmalloc; |
| }; |
| |
| struct ceph_buffer *ceph_buffer_new(gfp_t gfp); |
| int ceph_buffer_alloc(struct ceph_buffer *b, int len, gfp_t gfp); |
| |
| static inline struct ceph_buffer *ceph_buffer_get(struct ceph_buffer *b) |
| { |
| atomic_inc(&b->nref); |
| return b; |
| } |
| |
| static inline void ceph_buffer_put(struct ceph_buffer *b) |
| { |
| if (b && atomic_dec_and_test(&b->nref)) { |
| if (b->vec.iov_base) { |
| if (b->is_vmalloc) |
| vfree(b->vec.iov_base); |
| else |
| kfree(b->vec.iov_base); |
| } |
| kfree(b); |
| } |
| } |
| |
| static inline struct ceph_buffer *ceph_buffer_new_alloc(int len, gfp_t gfp) |
| { |
| struct ceph_buffer *b = ceph_buffer_new(gfp); |
| |
| if (b && ceph_buffer_alloc(b, len, gfp) < 0) { |
| ceph_buffer_put(b); |
| b = NULL; |
| } |
| return b; |
| } |
| |
| #endif |