1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
23d14c5d2SYehuda Sadeh
33d14c5d2SYehuda Sadeh #include <linux/ceph/ceph_debug.h>
43d14c5d2SYehuda Sadeh
53d14c5d2SYehuda Sadeh #include <linux/module.h>
63d14c5d2SYehuda Sadeh #include <linux/slab.h>
73d14c5d2SYehuda Sadeh
83d14c5d2SYehuda Sadeh #include <linux/ceph/buffer.h>
93d14c5d2SYehuda Sadeh #include <linux/ceph/decode.h>
10*a421ef30SMichal Hocko #include <linux/ceph/libceph.h> /* for kvmalloc */
113d14c5d2SYehuda Sadeh
ceph_buffer_new(size_t len,gfp_t gfp)123d14c5d2SYehuda Sadeh struct ceph_buffer *ceph_buffer_new(size_t len, gfp_t gfp)
133d14c5d2SYehuda Sadeh {
143d14c5d2SYehuda Sadeh struct ceph_buffer *b;
153d14c5d2SYehuda Sadeh
163d14c5d2SYehuda Sadeh b = kmalloc(sizeof(*b), gfp);
173d14c5d2SYehuda Sadeh if (!b)
183d14c5d2SYehuda Sadeh return NULL;
193d14c5d2SYehuda Sadeh
20*a421ef30SMichal Hocko b->vec.iov_base = kvmalloc(len, gfp);
213d14c5d2SYehuda Sadeh if (!b->vec.iov_base) {
223d14c5d2SYehuda Sadeh kfree(b);
233d14c5d2SYehuda Sadeh return NULL;
243d14c5d2SYehuda Sadeh }
253d14c5d2SYehuda Sadeh
263d14c5d2SYehuda Sadeh kref_init(&b->kref);
273d14c5d2SYehuda Sadeh b->alloc_len = len;
283d14c5d2SYehuda Sadeh b->vec.iov_len = len;
293d14c5d2SYehuda Sadeh dout("buffer_new %p\n", b);
303d14c5d2SYehuda Sadeh return b;
313d14c5d2SYehuda Sadeh }
323d14c5d2SYehuda Sadeh EXPORT_SYMBOL(ceph_buffer_new);
333d14c5d2SYehuda Sadeh
ceph_buffer_release(struct kref * kref)343d14c5d2SYehuda Sadeh void ceph_buffer_release(struct kref *kref)
353d14c5d2SYehuda Sadeh {
363d14c5d2SYehuda Sadeh struct ceph_buffer *b = container_of(kref, struct ceph_buffer, kref);
373d14c5d2SYehuda Sadeh
383d14c5d2SYehuda Sadeh dout("buffer_release %p\n", b);
394965fc38SIlya Dryomov kvfree(b->vec.iov_base);
403d14c5d2SYehuda Sadeh kfree(b);
413d14c5d2SYehuda Sadeh }
423d14c5d2SYehuda Sadeh EXPORT_SYMBOL(ceph_buffer_release);
433d14c5d2SYehuda Sadeh
ceph_decode_buffer(struct ceph_buffer ** b,void ** p,void * end)443d14c5d2SYehuda Sadeh int ceph_decode_buffer(struct ceph_buffer **b, void **p, void *end)
453d14c5d2SYehuda Sadeh {
463d14c5d2SYehuda Sadeh size_t len;
473d14c5d2SYehuda Sadeh
483d14c5d2SYehuda Sadeh ceph_decode_need(p, end, sizeof(u32), bad);
493d14c5d2SYehuda Sadeh len = ceph_decode_32(p);
503d14c5d2SYehuda Sadeh dout("decode_buffer len %d\n", (int)len);
513d14c5d2SYehuda Sadeh ceph_decode_need(p, end, len, bad);
523d14c5d2SYehuda Sadeh *b = ceph_buffer_new(len, GFP_NOFS);
533d14c5d2SYehuda Sadeh if (!*b)
543d14c5d2SYehuda Sadeh return -ENOMEM;
553d14c5d2SYehuda Sadeh ceph_decode_copy(p, (*b)->vec.iov_base, len);
563d14c5d2SYehuda Sadeh return 0;
573d14c5d2SYehuda Sadeh bad:
583d14c5d2SYehuda Sadeh return -EINVAL;
593d14c5d2SYehuda Sadeh }
60