/*	$NetBSD: ulfs_inode.h,v 1.25 2024/02/17 09:08:21 mlelstv Exp $	*/
/*  from NetBSD: inode.h,v 1.72 2016/06/03 15:36:03 christos Exp  */

/*
 * Copyright (c) 1982, 1989, 1993
 *	The Regents of the University of California.  All rights reserved.
 * (c) UNIX System Laboratories, Inc.
 * All or some portions of this file are derived from material licensed
 * to the University of California by American Telephone and Telegraph
 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
 * the permission of UNIX System Laboratories, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	@(#)inode.h	8.9 (Berkeley) 5/14/95
 */

#ifndef _UFS_LFS_ULFS_INODE_H_
#define	_UFS_LFS_ULFS_INODE_H_

#include <sys/vnode.h>
#include <ufs/lfs/lfs_inode.h>
#include <ufs/lfs/ulfs_dinode.h>
#include <ufs/lfs/ulfs_quotacommon.h>

/*
 * These macros are used to bracket ULFS directory ops, so that we can
 * identify all the pages touched during directory ops which need to
 * be ordered and flushed atomically, so that they may be recovered.
 *
 * Because we have to mark nodes VU_DIROP in order to prevent
 * the cache from reclaiming them while a dirop is in progress, we must
 * also manage the number of nodes so marked (otherwise we can run out).
 * We do this by setting lfs_dirvcount to the number of marked vnodes; it
 * is decremented during segment write, when VU_DIROP is taken off.
 */
#define	MARK_VNODE(vp)			lfs_mark_vnode(vp)
#define	UNMARK_VNODE(vp)		lfs_unmark_vnode(vp)
int lfs_set_dirop(struct vnode *, struct vnode *);
void lfs_unset_dirop(struct lfs *, struct vnode *, const char *);

/* Misc. definitions */
#define BW_CLEAN	1		/* Flag for lfs_bwrite_ext() */
#define PG_DELWRI	PG_PAGER1	/* Local def for delayed pageout */

/* Resource limits */
#define	LFS_MAX_RESOURCE(x, u)	(((x) >> 2) - 10 * (u))
#define	LFS_WAIT_RESOURCE(x, u)	(((x) >> 1) - ((x) >> 3) - 10 * (u))
#define	LFS_INVERSE_MAX_RESOURCE(x, u)	(((x) + 10 * (u)) << 2)
#define LFS_MAX_BUFS	    lfs_max_bufs()
#define LFS_WAIT_BUFS	    lfs_wait_bufs()
#define LFS_INVERSE_MAX_BUFS(n)	LFS_INVERSE_MAX_RESOURCE(n, 1)
#define LFS_MAX_BYTES	    LFS_MAX_RESOURCE(bufmem_lowater, PAGE_SIZE)
#define LFS_INVERSE_MAX_BYTES(n) LFS_INVERSE_MAX_RESOURCE(n, PAGE_SIZE)
#define LFS_WAIT_BYTES	    LFS_WAIT_RESOURCE(bufmem_lowater, PAGE_SIZE)
#define LFS_MAX_DIROP	    ((desiredvnodes >> 2) + (desiredvnodes >> 3))
#define SIZEOF_DIROP(fs)	(2 * (lfs_sb_getbsize(fs) + DINOSIZE(fs)))
#define LFS_MAX_FSDIROP(fs)						\
	(lfs_sb_getnclean(fs) <= lfs_sb_getresvseg(fs) ? 0 :		\
	 ((lfs_sb_getnclean(fs) - lfs_sb_getresvseg(fs)) * lfs_sb_getssize(fs)) / \
          (2 * SIZEOF_DIROP(fs)))
#define LFS_MAX_PAGES	lfs_max_pages()
#define LFS_WAIT_PAGES	lfs_wait_pages()
#define LFS_BUFWAIT	    2	/* How long to wait if over *_WAIT_* */

#ifdef _KERNEL
extern u_long bufmem_lowater, bufmem_hiwater; /* XXX */

int lfs_wait_pages(void);
int lfs_max_pages(void);
#endif /* _KERNEL */

/* How starved can we be before we start holding back page writes */
#define LFS_STARVED_FOR_SEGS(fs) (lfs_sb_getnclean(fs) < lfs_sb_getresvseg(fs))

/*
 * Reserved blocks for lfs_malloc
 */

/* Structure to keep reserved blocks */
typedef struct lfs_res_blk {
	void *p;
	LIST_ENTRY(lfs_res_blk) res;
	int size;
	char inuse;
} res_t;

/* Types for lfs_newbuf and lfs_malloc */
#define LFS_NB_UNKNOWN -1
#define LFS_NB_SUMMARY	0
#define LFS_NB_SBLOCK	1
#define LFS_NB_IBLOCK	2
#define LFS_NB_CLUSTER	3
#define LFS_NB_CLEAN	4
#define LFS_NB_BLKIOV	5
#define LFS_NB_COUNT	6 /* always last */

/* Number of reserved memory blocks of each type */
#define LFS_N_SUMMARIES 2
#define LFS_N_SBLOCKS	1   /* Always 1, to throttle superblock writes */
#define LFS_N_IBLOCKS	16  /* In theory ssize/bsize; in practice around 2 */
#define LFS_N_CLUSTERS	16  /* In theory ssize/MAXPHYS */
#define LFS_N_CLEAN	0
#define LFS_N_BLKIOV	1

/* Total count of "large" (non-pool) types */
#define LFS_N_TOTAL (LFS_N_SUMMARIES + LFS_N_SBLOCKS + LFS_N_IBLOCKS +	\
		     LFS_N_CLUSTERS + LFS_N_CLEAN + LFS_N_BLKIOV)

/* Counts for pool types */
#define LFS_N_CL	LFS_N_CLUSTERS
#define LFS_N_BPP	2
#define LFS_N_SEG	2

/*
 * "struct buf" associated definitions
 */

/* Determine if a buffer belongs to the ifile */
#define IS_IFILE(bp)	(VTOI(bp->b_vp)->i_number == LFS_IFILE_INUM)

#ifdef _KERNEL
/* This overlays the fid structure (see fstypes.h). */
struct ulfs_ufid {
	uint16_t ufid_len;	/* Length of structure. */
	uint16_t ufid_pad;	/* Force 32-bit alignment. */
	uint32_t ufid_ino;	/* File number (ino). XXX should be 64 */
	int32_t  ufid_gen;	/* Generation number. */
};
/* Filehandle structure for exported LFSes */
struct lfid {
	struct ulfs_ufid lfid_ufid;
#define lfid_len lfid_ufid.ufid_len
#define lfid_ino lfid_ufid.ufid_ino
#define lfid_gen lfid_ufid.ufid_gen
	uint32_t lfid_ident;
};
#endif /* _KERNEL */

/* Address calculations for metadata located in the inode */
#define	S_INDIR(fs)	-ULFS_NDADDR
#define	D_INDIR(fs)	(S_INDIR(fs) - LFS_NINDIR(fs) - 1)
#define	T_INDIR(fs)	(D_INDIR(fs) - LFS_NINDIR(fs) * LFS_NINDIR(fs) - 1)

/*
 * "struct vnode" associated definitions
 */

/* Heuristic emptiness measure */
#define VPISEMPTY(vp)	 (LIST_EMPTY(&(vp)->v_dirtyblkhd) && 		\
			  !(vp->v_type == VREG && (vp)->v_iflag & VI_ONWORKLST) &&\
			  VTOI(vp)->i_lfs_nbtree == 0)

#define WRITEINPROG(vp) ((vp)->v_numoutput > 0 ||			\
	(!LIST_EMPTY(&(vp)->v_dirtyblkhd) &&				\
	 !(VTOI(vp)->i_state & (IN_MODIFIED | IN_ACCESSED | IN_CLEANING))))





#if defined(_KERNEL)

/*
 * The DIP macro is used to access fields in the dinode that are
 * not cached in the inode itself.
 */
#define	DIP(ip, field) \
	(((ip)->i_ump->um_fstype == ULFS1) ? \
	(ip)->i_din->u_32.di_##field : (ip)->i_din->u_64.di_##field)

#define	DIP_ASSIGN(ip, field, value)					\
	do {								\
		if ((ip)->i_ump->um_fstype == ULFS1)			\
			(ip)->i_din->u_32.di_##field = (value);	\
		else							\
			(ip)->i_din->u_64.di_##field = (value);	\
	} while(0)

#define	DIP_ADD(ip, field, value)					\
	do {								\
		if ((ip)->i_ump->um_fstype == ULFS1)			\
			(ip)->i_din->u_32.di_##field += (value);	\
		else							\
			(ip)->i_din->u_64.di_##field += (value);	\
	} while(0)

/* XXX rework this better */
#define	 SHORTLINK(ip) \
	(((ip)->i_ump->um_fstype == ULFS1) ? \
	(void *)(ip)->i_din->u_32.di_db : (void *)(ip)->i_din->u_64.di_db)


/*
 * Structure used to pass around logical block paths generated by
 * ulfs_getlbns and used by truncate and bmap code.
 */
struct indir {
	daddr_t in_lbn;		/* Logical block number. */
	int	in_off;			/* Offset in buffer. */
	int	in_exists;		/* Flag if the block exists. */
};

/* Convert between inode pointers and vnode pointers. */
#define	VTOI(vp)	((struct inode *)(vp)->v_data)
#define	ITOV(ip)	((ip)->i_vnode)

#endif /* _KERNEL */

#endif /* !_UFS_LFS_ULFS_INODE_H_ */
