view src/objstore/objstore_impl.h @ 852:8ccfc441cff6

objstore: add alloc_only argument to obj_by_oid This bool will allow obj_by_oid to be used to look up both existing objects (e.g., during open) and not-yet-created objects (e.g., during create). Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
date Sat, 17 Dec 2022 14:03:31 -0500
parents 5427f4e9dcb6
children a2e7e70338eb
line wrap: on
line source

/*
 * Copyright (c) 2015-2020,2022 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#ifndef __OBJSTORE_IMPL_H
#define __OBJSTORE_IMPL_H

#include <jeffpc/mem.h>
#include <jeffpc/list.h>

#include <nomad/objstore.h>
#include <nomad/objstore_backend.h>

/* backend support */
struct backend {
	struct list_node node;
	const struct objstore_vdev_def *def;
	void *module;
};

enum pg_find_flags {
	PG_ALLOC = 0x01,
	PG_FILL = 0x02,
};

struct page {
	union {
		struct rb_node node;	/* in-use: objver pages tree */
		struct list pages;	/* free: internal page list */
	};
	struct objver *objver;
	uint64_t pgno;
	uint8_t *ptr;
	bool inuse:1; /* used by an object version */
	bool filled:1; /* contains data */
	bool dirty:1; /* must be written back */
};

/* internal backend management */
extern struct backend *backend_lookup(const char *name);

/* internal volume management */
extern int vol_init(void);
extern void vol_fini(void);
extern int vol_import(struct objstore_clone *clone);

/* internal vdev management */
extern int vdev_init(void);
extern void vdev_fini(void);

/* internal object management */
extern struct mem_cache *obj_cache;
extern struct mem_cache *objver_cache;
extern struct mem_cache *open_obj_cache;
extern void obj_free(struct obj *obj);

/* internal object version management */
extern struct objver *objver_alloc(void);
extern void objver_free(struct objver *ver);

extern struct obj *obj_by_oid(struct objstore_clone *clone,
			      const struct noid *oid, bool alloc_only);
extern struct objver *objver_by_clock(struct objstore_clone *clone,
				      const struct noid *oid,
				      const struct nvclock *clock);

/* add various transaction ops to the transaction */
extern struct objver *obj_cow(struct txn *txn,
			      struct objstore_open_obj_info *open);
extern int obj_create(struct txn *txn, const struct nattr *attrs,
		      struct noid *oid, const struct noid *parent);
extern ssize_t obj_read(struct objver *ver, void *buf, size_t len,
			uint64_t offset);
extern void obj_setattr(struct txn *txn, struct objver *ver,
			const struct nattr *attrs, unsigned valid);
extern ssize_t obj_write(struct txn *txn, struct objver *ver, const void *buf,
			 size_t len, uint64_t offset);

/* read/manipulate a directory */
extern int dir_lookup_one(struct objver *dirver, const char *name,
			  const struct noid *desired, struct noid *child,
			  uint8_t *type);
extern ssize_t dir_lookup_all(struct objver *dirver, const char *name,
			      struct noid **child, uint8_t **type);
extern int dir_getdent(struct objver *dirver, const uint64_t offset,
		       struct ndirent *child);
extern int dir_create(struct txn *txn, struct objver *dirver, const char *name,
		      uint32_t owner, uint32_t group, uint16_t mode,
		      struct noid *child);
extern int dir_unlink(struct txn *txn, struct objver *dirver, const char *name,
		      const struct noid *desired);

/*
 * Each transaction starts with a begin call and ends with a commit or abort
 * call.  If commit fails, it aborts the transaction internally.
 *
 * While a transaction is open, calls to txn_alloc_entry allocate space for
 * an operation to be performed by the transaction.  This call does not
 * fail.
 *
 * If an error is encountered during a transaction, make sure to leave each
 * entry as either fully initialized or as a no-op (OP_NOP).  Then, call
 * abort which will rollback up any non-nop entries.
 */
extern int txn_begin(struct txn *txn, struct objstore_clone *clone);
extern int txn_commit(struct txn *txn);
extern void txn_abort(struct txn *txn);
extern struct txn_entry *txn_alloc_entry(struct txn *txn);
extern void txn_log_entry(struct txn *txn, struct txn_entry *entry);

static inline int txn_commitabort(struct txn *txn, int err)
{
	if (!err)
		return txn_commit(txn);

	txn_abort(txn);
	return err;
}

static inline void txn_attach_objver(struct txn *txn, struct objver *ver)
{
	if (ver->txn.txn == txn) {
		ver->txn.refcnt++;
		return; /* already attached */
	}

	ASSERT3P(ver->txn.txn, ==, NULL);
	ASSERT3S(ver->txn.refcnt, ==, 0);

	ver->txn.txn = txn;
	ver->txn.refcnt = 1;
	ver->txn.prev_ver = NULL;
	ver->txn.min_data_size = ver->attrs.size;
}

static inline void txn_detach_objver(struct txn *txn, struct objver *ver)
{
	ASSERT3P(ver->txn.txn, ==, txn);
	ASSERT3S(ver->txn.refcnt, >, 0);

	ver->txn.refcnt--;
	if (ver->txn.refcnt)
		return;

	ver->txn.txn = NULL;
	ver->txn.refcnt = 0;
	ver->txn.prev_ver = NULL;
	ver->txn.min_data_size = 0;
}

/*
 * page-based cache
 */
extern int page_cache_init(size_t max_size);
extern void page_cache_free(void);
extern void page_cache_init_objver(struct objver *ver);
extern void page_cache_deinit_objver(struct objver *ver);

extern struct page *page_lookup(struct objver *ver, uint64_t pgno, int flags);
extern void page_inval_range(struct objver *ver, uint64_t pgno, size_t pgcnt);

/* for now, we rely on the obj lock */
#define page_lock(page)		do { } while (0)
#define page_unlock(page)	do { } while (0)

REFCNT_INLINE_FXNS(struct obj, obj, refcnt, obj_free, NULL);

#endif