diff options
author | Sage Weil <sage@newdream.net> | 2009-10-06 11:31:07 -0700 |
---|---|---|
committer | Sage Weil <sage@newdream.net> | 2009-10-06 11:31:07 -0700 |
commit | c30dbb9cc7fc75ab1d0ee6fb084ba4684f7a665d (patch) | |
tree | 7e702615046c0c866bb0229c731f86916c526115 /fs/ceph/buffer.c | |
parent | de57606c23afded22202825b3db8a5d61859f198 (diff) |
ceph: ref counted buffer
struct ceph_buffer is a simple ref-counted buffer. We transparently
choose between kmalloc for small buffers and vmalloc for large ones.
This is currently used only for allocating memory for xattr data.
Signed-off-by: Sage Weil <sage@newdream.net>
Diffstat (limited to 'fs/ceph/buffer.c')
-rw-r--r-- | fs/ceph/buffer.c | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/fs/ceph/buffer.c b/fs/ceph/buffer.c new file mode 100644 index 00000000000..cf9aaccef22 --- /dev/null +++ b/fs/ceph/buffer.c @@ -0,0 +1,34 @@ + +#include "ceph_debug.h" +#include "buffer.h" + +struct ceph_buffer *ceph_buffer_new(gfp_t gfp) +{ + struct ceph_buffer *b; + + b = kmalloc(sizeof(*b), gfp); + if (!b) + return NULL; + atomic_set(&b->nref, 1); + b->vec.iov_base = NULL; + b->vec.iov_len = 0; + b->alloc_len = 0; + return b; +} + +int ceph_buffer_alloc(struct ceph_buffer *b, int len, gfp_t gfp) +{ + b->vec.iov_base = kmalloc(len, gfp | __GFP_NOWARN); + if (b->vec.iov_base) { + b->is_vmalloc = false; + } else { + b->vec.iov_base = __vmalloc(len, gfp, PAGE_KERNEL); + b->is_vmalloc = true; + } + if (!b->vec.iov_base) + return -ENOMEM; + b->alloc_len = len; + b->vec.iov_len = len; + return 0; +} + |