162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * snapshot.c    Ceph snapshot context utility routines (part of libceph)
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2013 Inktank Storage, Inc.
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <linux/types.h>
962306a36Sopenharmony_ci#include <linux/export.h>
1062306a36Sopenharmony_ci#include <linux/ceph/libceph.h>
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci/*
1362306a36Sopenharmony_ci * Ceph snapshot contexts are reference counted objects, and the
1462306a36Sopenharmony_ci * returned structure holds a single reference.  Acquire additional
1562306a36Sopenharmony_ci * references with ceph_get_snap_context(), and release them with
1662306a36Sopenharmony_ci * ceph_put_snap_context().  When the reference count reaches zero
1762306a36Sopenharmony_ci * the entire structure is freed.
1862306a36Sopenharmony_ci */
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci/*
2162306a36Sopenharmony_ci * Create a new ceph snapshot context large enough to hold the
2262306a36Sopenharmony_ci * indicated number of snapshot ids (which can be 0).  Caller has
2362306a36Sopenharmony_ci * to fill in snapc->seq and snapc->snaps[0..snap_count-1].
2462306a36Sopenharmony_ci *
2562306a36Sopenharmony_ci * Returns a null pointer if an error occurs.
2662306a36Sopenharmony_ci */
2762306a36Sopenharmony_cistruct ceph_snap_context *ceph_create_snap_context(u32 snap_count,
2862306a36Sopenharmony_ci						gfp_t gfp_flags)
2962306a36Sopenharmony_ci{
3062306a36Sopenharmony_ci	struct ceph_snap_context *snapc;
3162306a36Sopenharmony_ci	size_t size;
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci	size = sizeof (struct ceph_snap_context);
3462306a36Sopenharmony_ci	size += snap_count * sizeof (snapc->snaps[0]);
3562306a36Sopenharmony_ci	snapc = kzalloc(size, gfp_flags);
3662306a36Sopenharmony_ci	if (!snapc)
3762306a36Sopenharmony_ci		return NULL;
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci	refcount_set(&snapc->nref, 1);
4062306a36Sopenharmony_ci	snapc->num_snaps = snap_count;
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci	return snapc;
4362306a36Sopenharmony_ci}
4462306a36Sopenharmony_ciEXPORT_SYMBOL(ceph_create_snap_context);
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_cistruct ceph_snap_context *ceph_get_snap_context(struct ceph_snap_context *sc)
4762306a36Sopenharmony_ci{
4862306a36Sopenharmony_ci	if (sc)
4962306a36Sopenharmony_ci		refcount_inc(&sc->nref);
5062306a36Sopenharmony_ci	return sc;
5162306a36Sopenharmony_ci}
5262306a36Sopenharmony_ciEXPORT_SYMBOL(ceph_get_snap_context);
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_civoid ceph_put_snap_context(struct ceph_snap_context *sc)
5562306a36Sopenharmony_ci{
5662306a36Sopenharmony_ci	if (!sc)
5762306a36Sopenharmony_ci		return;
5862306a36Sopenharmony_ci	if (refcount_dec_and_test(&sc->nref)) {
5962306a36Sopenharmony_ci		/*printk(" deleting snap_context %p\n", sc);*/
6062306a36Sopenharmony_ci		kfree(sc);
6162306a36Sopenharmony_ci	}
6262306a36Sopenharmony_ci}
6362306a36Sopenharmony_ciEXPORT_SYMBOL(ceph_put_snap_context);
64