[BACK]Return to xfs_inode.h CVS log [TXT][DIR] Up to [Development] / xfs-linux

File: [Development] / xfs-linux / xfs_inode.h (download)

Revision 1.114, Thu Aug 28 22:55:01 1997 UTC (20 years, 1 month ago) by kayuri
Branch: MAIN
Changes since 1.113: +11 -5 lines

Added inode readahead lock to the incore inode structure. Rearranged
some inode readahead state fields in the incore inode and added locks around
the readahead clear state macro (bug 516806).

#ifndef	_XFS_INODE_H
#define	_XFS_INODE_H

#ident "$Revision: 1.113 $"

struct bhv_desc;
struct buf;
struct cred;
struct grio_ticket;
struct ktrace;
struct vnode;
struct xfs_bmbt_block;
struct xfs_ext_attr;
struct xfs_gap;
struct xfs_inode;
struct xfs_inode_log_item;
struct xfs_mount;
struct xfs_trans;
struct zone;
struct xfs_dquot;

/*
 * This is the type used in the xfs inode hash table.
 * An array of these is allocated for each mounted
 * file system to hash the inodes for that file system.
 */
typedef struct xfs_ihash {
	struct xfs_inode	*ih_next;	
	mutex_t			ih_lock;
	uint			ih_version;
} xfs_ihash_t;

#ifdef NOTYET
/*
 * The range structure is used to describe a locked range
 * within a file.  It is used in conjunction with the
 * xfs_range_lock_t defined below.
 */
typedef struct xfs_range {
	struct xfs_range	*r_forw;	/* range list pointer */
	struct xfs_range	*r_back;	/* range list pointer */
	xfs_fileoff_t		r_off;		/* start of range */
	xfs_fileoff_t		r_len;		/* length of range */
	int			r_sleepers;	/* count of sleepers */
} xfs_range_t;

/*
 * This is a structure embedded in the incore inode for
 * tracking range locks over the file.  The semaphore is
 * dynamically allocated to reduce our memory consumption.
 * XXX Semaphores are now only 32-bits -- should allocate in-line. --yohn
 */
typedef struct xfs_range_lock {
	mutex_t		r_spinlock;	/* lock to make sleeps atomic */
	sema_t		*r_sleep;	/* semaphore for sleeping on */
	xfs_range_t	*r_range_list;	/* list of locked ranges */
} xfs_range_lock_t;
#endif /* NOTYET */

/*
 * File incore extent information, present for each of data & attr forks.
 */
#define	XFS_INLINE_EXTS	2
#define	XFS_INLINE_DATA	32
typedef struct xfs_ifork {
	int			if_bytes; 	/* bytes in if_u1 */
	int			if_real_bytes;	/* bytes allocated in if_u1 */
	xfs_bmbt_block_t	*if_broot;	/* file's incore btree root */
	short			if_broot_bytes;	/* bytes allocated for root */
	unsigned char		if_flags;	/* per-fork flags */
	unsigned char		if_ext_max;	/* max # of extent records */
	xfs_extnum_t		if_lastex;	/* last if_extents used */
	union {
		xfs_bmbt_rec_t	*if_extents;	/* linear map file exts */
		char		*if_data;	/* inline file data */
	} if_u1;
	union {
		xfs_bmbt_rec_t	if_inline_ext[XFS_INLINE_EXTS];
						/* very small file extents */
		char		if_inline_data[XFS_INLINE_DATA];
						/* very small file data */
		dev_t		if_rdev;	/* dev number if special */
		uuid_t		if_uuid;	/* mount point value */
	} if_u2;
} xfs_ifork_t;

/*
 * This is the xfs in-core inode structure.
 * Most of the on-disk inode is embedded in the i_d field.
 *
 * The extent pointers/inline file space, however, are managed
 * separately.  The memory for this information is pointed to by
 * the if_u1 unions depending on the type of the data.
 * This is used to linearize the array of extents for fast in-core
 * access.  This is used until the file's number of extents
 * surpasses XFS_MAX_INCORE_EXTENTS, at which point all extent pointers
 * are accessed through the buffer cache.
 *
 * Other state kept in the in-core inode is used for identification,
 * locking, transactional updating, etc of the inode.
 *
 * Generally, we do not want to hold the i_rlock while holding the 
 * i_ilock. Hierarchy is i_iolock followed by i_rlock. 
 */
typedef struct xfs_inode {
	/* Inode linking and identification information. */
	struct xfs_ihash	*i_hash;	/* pointer to hash header */
	struct xfs_inode	*i_next;	/* inode hash link forw */
	struct xfs_inode	**i_prevp;	/* ptr to prev i_next */
	struct xfs_mount	*i_mount;	/* fs mount struct ptr */
	struct xfs_inode	*i_mnext;	/* next inode in mount list */
	struct xfs_inode	*i_mprev;	/* ptr to prev inode */
	struct bhv_desc		i_bhv_desc;	/* inode behavior descriptor*/
	struct xfs_dquot	*i_udquot;	/* user dquot */
	struct xfs_dquot	*i_pdquot;	/* project dquot */

	/* Inode location stuff */
	xfs_ino_t		i_ino;		/* inode number (agno/agino)*/
	daddr_t			i_blkno;	/* blkno of inode buffer */
	dev_t			i_dev;		/* dev for this inode */
	short			i_len;		/* len of inode buffer */
	short			i_boffset;	/* off of inode in buffer */

	/* Extent information. */
	xfs_ifork_t		*i_afp;		/* attribute fork pointer */
	xfs_ifork_t		i_df;		/* data fork */

	/* Transaction and locking information. */
	struct xfs_trans	*i_transp;	/* ptr to owning transaction*/
	struct xfs_inode_log_item *i_itemp;	/* logging information */
	mrlock_t		i_lock;		/* inode lock */
	mrlock_t		i_iolock;	/* inode IO lock */
	sema_t			i_flock;	/* inode flush lock */
	unsigned int		i_pincount;	/* inode pin count */
	sv_t			i_pinsema;	/* inode pin sema */
	lock_t			i_ipinlock;	/* inode pinning mutex */
	mutex_t			i_rlock;	/* inode readahead mutex */
#ifdef NOTYET
	xfs_range_lock_t	i_range_lock;	/* range lock base */
#endif /* NOTYET */
	struct xfs_inode	**i_refcache;	/* ptr to entry in ref cache */
	struct xfs_inode	*i_release;	/* inode to unref */

	/* I/O state */
	off_t			i_io_offset;	/* last buf offset */
	off_t			i_next_offset;	/* seq read detector */
	unsigned int		i_last_req_sz;	/* last read size */
	unsigned int		i_io_size;	/* file io buffer len */
	xfs_fsize_t		i_new_size;	/* sz when write completes */
	off_t			i_write_offset;	/* start off of curr write */
	xfs_fileoff_t		i_reada_blkno;	/* next blk to start ra */
	struct xfs_gap		*i_gap_list;	/* hole list in write range */
	unsigned int		i_readio_blocks;	/* read buffer size */
	unsigned int		i_writeio_blocks;	/* write buffer size */
	uchar_t			i_readio_log;	/* log2 of read buffer size */
	uchar_t			i_writeio_log;	/* log2 of write buffer size */
	uchar_t			i_max_io_log;	/* max r/w io value */

	/* Miscellaneous state. */
	unsigned short		i_flags;	/* see defined flags below */
	unsigned short		i_update_core;	/* timestamps/size is dirty */
	unsigned short		i_update_size;	/* di_size field is dirty */
	int			i_queued_bufs;	/* count of xfsd queued bufs*/
	unsigned int		i_gen;		/* generation count */
	unsigned int		i_delayed_blks;	/* count of delay alloc blks */
	struct xfs_ext_attr	*i_ext_attr;	/* Critical ext attributes */

	xfs_dinode_core_t	i_d;		/* most of ondisk inode */

#ifdef DEBUG
	/* Trace buffers per inode. */
	struct ktrace		*i_xtrace;	/* inode extent list trace */
	struct ktrace		*i_btrace;	/* inode bmap btree trace */
	struct ktrace		*i_rwtrace;	/* inode read/write trace */
	struct ktrace		*i_strat_trace;	/* inode strat_write trace */
	struct ktrace		*i_lock_trace;	/* inode lock/unlock trace */
#endif /* DEBUG */
} xfs_inode_t;

/*
 * Fork handling.
 */
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_IFORK_PTR)
xfs_ifork_t *xfs_ifork_ptr(xfs_inode_t *ip, int w);
#define	XFS_IFORK_PTR(ip,w)   		xfs_ifork_ptr(ip,w)
#else
#define	XFS_IFORK_PTR(ip,w)   ((w) == XFS_DATA_FORK ? &(ip)->i_df : (ip)->i_afp)
#endif
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_IFORK_Q)
int xfs_ifork_q(xfs_inode_t *ip);
#define	XFS_IFORK_Q(ip)			xfs_ifork_q(ip)
#else
#define	XFS_IFORK_Q(ip)			XFS_CFORK_Q(&(ip)->i_d)
#endif
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_IFORK_DSIZE)
int xfs_ifork_dsize(xfs_inode_t *ip);
#define	XFS_IFORK_DSIZE(ip)		xfs_ifork_dsize(ip)
#else
#define	XFS_IFORK_DSIZE(ip)		XFS_CFORK_DSIZE(&ip->i_d, ip->i_mount)
#endif
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_IFORK_ASIZE)
int xfs_ifork_asize(xfs_inode_t *ip);
#define	XFS_IFORK_ASIZE(ip)		xfs_ifork_asize(ip)
#else
#define	XFS_IFORK_ASIZE(ip)		XFS_CFORK_ASIZE(&ip->i_d, ip->i_mount)
#endif
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_IFORK_SIZE)
int xfs_ifork_size(xfs_inode_t *ip, int w);
#define	XFS_IFORK_SIZE(ip,w)		xfs_ifork_size(ip,w)
#else
#define	XFS_IFORK_SIZE(ip,w)		XFS_CFORK_SIZE(&ip->i_d, ip->i_mount, w)
#endif
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_IFORK_FORMAT)
int xfs_ifork_format(xfs_inode_t *ip, int w);
#define	XFS_IFORK_FORMAT(ip,w)		xfs_ifork_format(ip,w)
#else
#define	XFS_IFORK_FORMAT(ip,w)		XFS_CFORK_FORMAT(&ip->i_d, w)
#endif
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_IFORK_FMT_SET)
void xfs_ifork_fmt_set(xfs_inode_t *ip, int w, int n);
#define	XFS_IFORK_FMT_SET(ip,w,n)	xfs_ifork_fmt_set(ip,w,n)
#else
#define	XFS_IFORK_FMT_SET(ip,w,n)	XFS_CFORK_FMT_SET(&ip->i_d, w, n)
#endif
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_IFORK_NEXTENTS)
int xfs_ifork_nextents(xfs_inode_t *ip, int w);
#define	XFS_IFORK_NEXTENTS(ip,w)	xfs_ifork_nextents(ip,w)
#else
#define	XFS_IFORK_NEXTENTS(ip,w)	XFS_CFORK_NEXTENTS(&ip->i_d, w)
#endif
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_IFORK_NEXT_SET)
void xfs_ifork_next_set(xfs_inode_t *ip, int w, int n);
#define	XFS_IFORK_NEXT_SET(ip,w,n)	xfs_ifork_next_set(ip,w,n)
#else
#define	XFS_IFORK_NEXT_SET(ip,w,n)	XFS_CFORK_NEXT_SET(&ip->i_d, w, n)
#endif

/*
 * In-core inode flags.
 */
#define XFS_IGRIO	0x0001  /* inode will be used for guaranteed rate i/o */
#define XFS_IUIOSZ	0x0002  /* inode i/o sizes have been explicitly set */

/*
 * Per-fork incore inode flags.
 */
#define	XFS_IFINLINE	0x0001	/* Inline data is read in */
#define	XFS_IFEXTENTS	0x0002	/* All extent pointers are read in */
#define	XFS_IFBROOT	0x0004	/* i_broot points to the bmap b-tree root */

/*
 * Flags for inode locking.
 */
#define	XFS_IOLOCK_EXCL		0x01
#define	XFS_IOLOCK_SHARED	0x02
#define	XFS_ILOCK_EXCL		0x04
#define	XFS_ILOCK_SHARED	0x08
#define	XFS_IUNLOCK_NONOTIFY	0x10

/*
 * Flags for xfs_iflush()
 */
#define	XFS_IFLUSH_DELWRI_ELSE_SYNC	1
#define	XFS_IFLUSH_DELWRI_ELSE_ASYNC	2
#define	XFS_IFLUSH_SYNC			3
#define	XFS_IFLUSH_ASYNC		4
#define	XFS_IFLUSH_DELWRI		5

/*
 * Flags for xfs_iflush_all.
 */
#define	XFS_FLUSH_ALL		0x1

/*
 * Flags for xfs_itruncate_start().
 */
#define	XFS_ITRUNC_DEFINITE	0x1
#define	XFS_ITRUNC_MAYBE	0x2

/*
 * Flags for xfs_ichgtime().
 */
#define	XFS_ICHGTIME_MOD	0x1	/* data fork modification timestamp */
#define	XFS_ICHGTIME_ACC	0x2	/* data fork access timestamp */
#define	XFS_ICHGTIME_CHG	0x4	/* inode field change timestamp */

/*
 * Flags for xfs_imap() and xfs_dilocate().
 */
#define	XFS_IMAP_LOOKUP		0x1

/*
 * Maximum number of extent pointers in if_u1.if_extents.
 */
#define	XFS_MAX_INCORE_EXTENTS	32768

/*
 * Maximum file size.
 * if XFS_BIG_FILES 2^63 - 1 (largest positive value of xfs_fsize_t)
 * else 2^40 - 1 (40=31+9) (might be an int holding a block #)
 * Note, we allow seeks to this offset, although you can't read or write.
 * For the not XFS_BIG_FILES case, the value could be 1 higher but we don't
 * do that, for symmetry.
 */
#if XFS_BIG_FILES
#define XFS_MAX_FILE_OFFSET	((long long)((1ULL<<63)-1ULL))
#else
#define	XFS_MAX_FILE_OFFSET	((1LL<<40)-1LL)
#endif

#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_ITOV)
struct vnode *xfs_itov(xfs_inode_t *ip);
#define	XFS_ITOV(ip)		xfs_itov(ip)
#else
#define	XFS_ITOV(ip)		BHV_TO_VNODE(XFS_ITOBHV(ip))
#endif
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_ITOBHV)
struct bhv_desc *xfs_itobhv(xfs_inode_t *ip);
#define	XFS_ITOBHV(ip)		xfs_itobhv(ip)
#else
#define	XFS_ITOBHV(ip)		((struct bhv_desc *)(&((ip)->i_bhv_desc)))
#endif
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_BHVTOI)
xfs_inode_t *xfs_bhvtoi(struct bhv_desc *bhvp);
#define	XFS_BHVTOI(bhvp)	xfs_bhvtoi(bhvp)
#else
#define	XFS_BHVTOI(bhvp)	\
	((xfs_inode_t *)((char *)(bhvp) - \
			 (char *)&(((xfs_inode_t *)0)->i_bhv_desc)))
#endif

/*
 * Clear out the read-ahead state in the in-core inode.
 * We actually only need to clear i_next_offset and
 * i_last_req_sz to get the effect of making all the
 * read ahead state unusable.
 */
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_INODE_CLEAR_READ_AHEAD)
void xfs_inode_clear_read_ahead(xfs_inode_t *ip);
#define	XFS_INODE_CLEAR_READ_AHEAD(ip)		xfs_inode_clear_read_ahead(ip)
#else
#define	XFS_INODE_CLEAR_READ_AHEAD(ip)	{	\
		mutex_lock(&((ip)->i_rlock), PINOD);	\
		ip->i_next_offset = 0;		\
		ip->i_last_req_sz = 0; 		\
		mutex_unlock(&((ip)->i_rlock)); }
#endif

/*
 * XFS file identifiers.  The xfs_fid_ino_t type is because NFS 2 won't
 * take more than 10 bytes of stuff past fid_len.  xfs_fid2_t is solely
 * to get a full 64 bit inode number.
 */
typedef __uint32_t	xfs_fid_ino_t;
typedef struct xfs_fid {
	u_short		fid_len;       /* length of remainder */
        u_short		fid_pad;       /* padding, must be zero */
	__uint32_t	fid_gen;       /* generation number */
        xfs_fid_ino_t	fid_ino;       /* inode number */
} xfs_fid_t;

typedef struct xfs_fid2 {
	u_short		fid_len;	/* length of remainder */
	u_short		fid_pad;	/* padding, must be zero */
	__uint32_t	fid_gen;	/* generation number */
	xfs_ino_t	fid_ino;	/* inode number */
} xfs_fid2_t;

/*
 * xfs_iget.c prototypes.
 */
void		xfs_ihash_init(struct xfs_mount *);
void		xfs_ihash_free(struct xfs_mount *);
xfs_inode_t	*xfs_inode_incore(struct xfs_mount *, xfs_ino_t,
				  struct xfs_trans *);
int		xfs_iget(struct xfs_mount *, struct xfs_trans *, xfs_ino_t,
			 uint, xfs_inode_t **, daddr_t);
void		xfs_iput(xfs_inode_t *, uint);
void		xfs_ilock(xfs_inode_t *, uint);
int		xfs_ilock_nowait(xfs_inode_t *, uint);
void		xfs_iunlock(xfs_inode_t *, uint);
void		xfs_iflock(xfs_inode_t *);
int		xfs_iflock_nowait(xfs_inode_t *);
uint		xfs_ilock_map_shared(xfs_inode_t *);
void		xfs_iunlock_map_shared(xfs_inode_t *, uint);
void		xfs_ifunlock(xfs_inode_t *);
void		xfs_ireclaim(xfs_inode_t *);

/*
 * xfs_inode.c prototypes.
 */
int		xfs_inotobp(struct xfs_mount *, struct xfs_trans *, xfs_ino_t,
			    xfs_dinode_t **, struct buf **);
int		xfs_itobp(struct xfs_mount *, struct xfs_trans *,
			  xfs_inode_t *, xfs_dinode_t **, struct buf **,
			  daddr_t);
int		xfs_iread(struct xfs_mount *, struct xfs_trans *, xfs_ino_t,
			  xfs_inode_t **, daddr_t);
int		xfs_iread_extents(struct xfs_trans *, xfs_inode_t *, int);
int		xfs_ialloc(struct xfs_trans *, xfs_inode_t *, mode_t, nlink_t,
		           dev_t, struct cred *, xfs_prid_t, int,
			   struct buf **, boolean_t *, xfs_inode_t **);
#ifndef SIM
int		xfs_ifree(struct xfs_trans *, xfs_inode_t *);
int		xfs_atruncate_start(xfs_inode_t *);
void		xfs_itruncate_start(xfs_inode_t *, uint, xfs_fsize_t);
int		xfs_itruncate_finish(struct xfs_trans **, xfs_inode_t *,
				     xfs_fsize_t, int, int);
int		xfs_iunlink(struct xfs_trans *, xfs_inode_t *);
#endif	/* !SIM */
int		xfs_igrow_start(xfs_inode_t *, xfs_fsize_t, struct cred *);
void		xfs_igrow_finish(struct xfs_trans *, xfs_inode_t *,
				 xfs_fsize_t);

void		xfs_idestroy_fork(xfs_inode_t *, int);
void		xfs_idestroy(xfs_inode_t *);
void		xfs_idata_realloc(xfs_inode_t *, int, int);
void		xfs_iext_realloc(xfs_inode_t *, int, int);
void		xfs_iroot_realloc(xfs_inode_t *, int, int);
void		xfs_ipin(xfs_inode_t *);
void		xfs_iunpin(xfs_inode_t *);
unsigned int	xfs_ipincount(xfs_inode_t *);
int		xfs_iextents_copy(xfs_inode_t *, xfs_bmbt_rec_32_t *, int);
int		xfs_iflush(xfs_inode_t *, uint);
int		xfs_iflush_all(struct xfs_mount *, int);
#ifdef SIM
void		xfs_iprint(xfs_inode_t *);
#endif
int		xfs_iaccess(xfs_inode_t *, mode_t, struct cred *);
uint		xfs_iroundup(uint);
void		xfs_ichgtime(xfs_inode_t *, int);
xfs_fsize_t	xfs_file_last_byte(xfs_inode_t *);

#ifdef DEBUG
void		xfs_isize_check(struct xfs_mount *, xfs_inode_t *, xfs_fsize_t);
#else	/* DEBUG */
#define xfs_isize_check(mp, ip, isize)
#endif	/* DEBUG */

#if defined(DEBUG) && !defined(XFS_REPAIR_SIM)
void		xfs_inobp_check(struct xfs_mount *, struct buf *);
#else
#define	xfs_inobp_check(mp, bp)
#endif /* DEBUG && !XFS_REPAIR_SIM */

/*
 * xfs_vnodeops.c prototypes.
 */
int		xfs_fast_fid(struct bhv_desc *, xfs_fid_t *);

extern struct zone	*xfs_ifork_zone;
extern struct zone	*xfs_inode_zone;
extern struct zone	*xfs_ili_zone;
extern struct vnodeops	xfs_vnodeops;

#ifdef XFS_ILOCK_TRACE
#define XFS_ILOCK_KTRACE_SIZE	256
void	xfs_ilock_trace(xfs_inode_t *ip, int lock, unsigned int lockflags, 
			inst_t *ra);
#endif

#endif	/* _XFS_INODE_H */