18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci
38c2ecf20Sopenharmony_ci#include <linux/ceph/ceph_debug.h>
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci#include <linux/module.h>
68c2ecf20Sopenharmony_ci#include <linux/slab.h>
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include <linux/ceph/buffer.h>
98c2ecf20Sopenharmony_ci#include <linux/ceph/decode.h>
108c2ecf20Sopenharmony_ci#include <linux/ceph/libceph.h> /* for ceph_kvmalloc */
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_cistruct ceph_buffer *ceph_buffer_new(size_t len, gfp_t gfp)
138c2ecf20Sopenharmony_ci{
148c2ecf20Sopenharmony_ci	struct ceph_buffer *b;
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci	b = kmalloc(sizeof(*b), gfp);
178c2ecf20Sopenharmony_ci	if (!b)
188c2ecf20Sopenharmony_ci		return NULL;
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci	b->vec.iov_base = ceph_kvmalloc(len, gfp);
218c2ecf20Sopenharmony_ci	if (!b->vec.iov_base) {
228c2ecf20Sopenharmony_ci		kfree(b);
238c2ecf20Sopenharmony_ci		return NULL;
248c2ecf20Sopenharmony_ci	}
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci	kref_init(&b->kref);
278c2ecf20Sopenharmony_ci	b->alloc_len = len;
288c2ecf20Sopenharmony_ci	b->vec.iov_len = len;
298c2ecf20Sopenharmony_ci	dout("buffer_new %p\n", b);
308c2ecf20Sopenharmony_ci	return b;
318c2ecf20Sopenharmony_ci}
328c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ceph_buffer_new);
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_civoid ceph_buffer_release(struct kref *kref)
358c2ecf20Sopenharmony_ci{
368c2ecf20Sopenharmony_ci	struct ceph_buffer *b = container_of(kref, struct ceph_buffer, kref);
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci	dout("buffer_release %p\n", b);
398c2ecf20Sopenharmony_ci	kvfree(b->vec.iov_base);
408c2ecf20Sopenharmony_ci	kfree(b);
418c2ecf20Sopenharmony_ci}
428c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ceph_buffer_release);
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ciint ceph_decode_buffer(struct ceph_buffer **b, void **p, void *end)
458c2ecf20Sopenharmony_ci{
468c2ecf20Sopenharmony_ci	size_t len;
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci	ceph_decode_need(p, end, sizeof(u32), bad);
498c2ecf20Sopenharmony_ci	len = ceph_decode_32(p);
508c2ecf20Sopenharmony_ci	dout("decode_buffer len %d\n", (int)len);
518c2ecf20Sopenharmony_ci	ceph_decode_need(p, end, len, bad);
528c2ecf20Sopenharmony_ci	*b = ceph_buffer_new(len, GFP_NOFS);
538c2ecf20Sopenharmony_ci	if (!*b)
548c2ecf20Sopenharmony_ci		return -ENOMEM;
558c2ecf20Sopenharmony_ci	ceph_decode_copy(p, (*b)->vec.iov_base, len);
568c2ecf20Sopenharmony_ci	return 0;
578c2ecf20Sopenharmony_cibad:
588c2ecf20Sopenharmony_ci	return -EINVAL;
598c2ecf20Sopenharmony_ci}
60