cachefs_fs.h revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _SYS_FS_CACHEFS_FS_H
#define _SYS_FS_CACHEFS_FS_H
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/inttypes.h>
#include <sys/time_impl.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifdef CFSDEBUG
#define CFSDEBUG_ALL 0xffffffff
#define CFSDEBUG_NONE 0x0
#define CFSDEBUG_GENERAL 0x1
#define CFSDEBUG_SUBR 0x2
#define CFSDEBUG_CNODE 0x4
#define CFSDEBUG_DIR 0x8
#define CFSDEBUG_STRICT 0x10
#define CFSDEBUG_VOPS 0x20
#define CFSDEBUG_VFSOP 0x40
#define CFSDEBUG_RESOURCE 0x80
#define CFSDEBUG_CHEAT 0x100
#define CFSDEBUG_INVALIDATE 0x200
#define CFSDEBUG_DLOG 0x400
#define CFSDEBUG_FILEGRP 0x800
#define CFSDEBUG_IOCTL 0x1000
#define CFSDEBUG_FRONT 0x2000
#define CFSDEBUG_BACK 0x4000
#define CFSDEBUG_ALLOCMAP 0x8000
#define CFSDEBUG_ASYNCPOP 0x10000
#define CFSDEBUG_VOPS_NFSV4 0x20000
#define CFSCLEANFLAG
extern int cachefsdebug;
#define CFS_DEBUG(N) if (cachefsdebug & (N))
#endif /* DEBUG */
#if 0
#ifdef CFSDEBUG
/*
* Testing usage of cd_access and friends.
* Note we steal an unused bit in t_flag.
* This will certainly bite us later.
*/
#define CFS_CD_DEBUG
#define T_CD_HELD 0x01000
#endif
#endif
/*
* Note: in an RL debugging kernel, CFSVERSION is augmented by 100
*
* Version History:
*
* Beginning -- Solaris 2.3 and 2.4: 1
*
* In Solaris 2.5 alpha, the size of fid_t changed: 2
*
* added which RL list to attrcache header: 4
*
* Large Files support made version to 6.
*
* Sequence numbers made version to 7.
*
* 64-bit on-disk cache will make version 8. Not yet supported.
*/
#if 0
#define CFSRLDEBUG
#endif
#ifdef CFSRLDEBUG
#define CFSVERSION 110
#else /* CFSRLDEBUG */
#define CFSVERSION 7
#endif /* CFSRLDEBUG */
/* Some default values */
#define DEF_FILEGRP_SIZE 256
#define CACHELABEL_NAME ".cfs_label"
#define RESOURCE_NAME ".cfs_resource"
#define CACHEFS_FSINFO ".cfs_fsinfo"
#define ATTRCACHE_NAME ".cfs_attrcache"
#define CACHEFS_LOSTFOUND_NAME "lost+found"
#define BACKMNT_NAME ".cfs_mnt_points"
#define CACHEFS_LOCK_FILE ".cfs_lock"
#define CACHEFS_DLOG_FILE ".cfs_dlog"
#define CACHEFS_DMAP_FILE ".cfs_dmap"
#define CACHEFS_MNT_FILE ".cfs_mnt"
#define CACHEFS_UNMNT_FILE ".cfs_unmnt"
#define LOG_STATUS_NAME ".cfs_logging"
#define NOBACKUP_NAME ".nsr"
#define CACHEFS_PREFIX ".cfs_"
#define CACHEFS_PREFIX_LEN 5
#define ROOTLINK_NAME "root"
#define CFS_FRONTFILE_NAME_SIZE 18
#define CFS_MAXFREECNODES 20
#define CACHEFSTAB "/etc/cachefstab"
#define CACHEFS_ROOTRUN "/var/run"
/*
* The options structure is passed in as part of the mount arguments.
* It is stored in the .options file and kept track of in the fscache
* structure.
*/
struct cachefsoptions {
int opt_popsize; /* cache population size */
int opt_fgsize; /* filegrp size, default 256 */
};
typedef struct cachefscache cachefscache_t;
/*
* all the stuff needed to manage a queue of requests to be processed
* by async threads.
*/
struct cachefs_workq {
int wq_length; /* # of requests on q */
int wq_thread_count; /* # of threads */
int wq_max_len; /* longest queue */
int wq_halt_request; /* halt requested */
};
/*
* cfs_cid is stored on disk, so it needs to be the same 32-bit vs. 64-bit.
*/
#pragma pack(4)
#endif
/* identifies a file in the cache */
struct cfs_cid {
int cid_flags; /* flags */
};
#pragma pack()
#endif
/*
* XX64 - for now redefine all time_t fields that are used by both kernel
* and user space apps as a 32-bit quantity,
*/
#if (defined(_SYSCALL32) && defined(_LP64))
/*
* The cfs_* types are used to represent on-disk data, since its size is
* independent of the kernel memory model (in the LP64 case)
*/
typedef time32_t cfs_time_t;
typedef timestruc32_t cfs_timestruc_t;
typedef vattr32_t cfs_vattr_t;
#define cfs_timespec timespec32
/*
* CACHEFS_DEV_COPY copies between two dev_t's. It expands or compresses
* them based on type changes (if needed).
*/
#define TIME_OVERFLOW(tval) \
/* Set the referred to time value. Set error if overflow */
if (TIME_OVERFLOW(in_tval)) \
/* Set the cfs_timestruc_t with values from input timestruc_t */
/* CACHEFS_FID_COPY copies between two fids */
(out_vattrp)->va_seq = 0
(out_vattrp)->va_fsid); \
&(out_vattrp)->va_atime); \
&(out_vattrp)->va_mtime); \
&(out_vattrp)->va_ctime); \
(out_vattrp)->va_rdev); \
(out_vattrp)->va_seq = 0
#else /* not _SYSCALL32 && _LP64 */
/*
* The cfs_* types are used to represent on-disk data, since its size is
* independent of the kernel memory model (in the LP64 case)
*/
typedef time_t cfs_time_t;
typedef timestruc_t cfs_timestruc_t;
typedef vattr_t cfs_vattr_t;
#define cfs_timespec timespec
*(out_vattrp) = *(in_vattrp); \
(out_vattrp)->va_seq = 0
*(out_vattrp) = *(in_vattrp); \
(out_vattrp)->va_seq = 0
#endif /* _SYSCALL32 && _LP64 */
/*
* The "cfs_*" structs below refer to the on-disk structures. Presently
* they are 32-bit based. When they change to 64-bit, we'd have to modify the
* macros below accordingly.
*/
/*
* One cache_label structure per cache. Contains mainly user defined or
* default values for cache resource management. Contents is static.
* The value cl_maxfiles is not used any where in cachefs code. If and when
* this is really used the cl_maxfiles should be declared as a 64bit value
* for large file support.
* The maxblks, blkhiwat, blklowat, blocktresh, blockmin, may need to be
* 64bit values when we actually start supporting file systems of size
* greater than 1 terabyte.
*/
struct cache_label {
int cl_cfsversion; /* cfs version number */
int cl_maxblks; /* max blocks to be used by cache */
int cl_blkhiwat; /* high water-mark for block usage */
int cl_blklowat; /* low water-mark for block usage */
int cl_maxinodes; /* max inodes to be used by cache */
int cl_filehiwat; /* high water-mark for inode usage */
int cl_filelowat; /* low water-mark for indoe usage */
int cl_blocktresh; /* block max usage treshold */
int cl_blockmin; /* block min usage treshold */
int cl_filetresh; /* inode max usage treshold */
int cl_filemin; /* inode min usage treshold */
int cl_maxfiles; /* max cache file size */
};
/*
* One cache_usage structure per cache. Keeps track of cache usage figures.
* Contents gets updated frequently.
*/
struct cache_usage {
int cu_blksused; /* actual number of blocks used */
int cu_filesused; /* actual number of files used */
};
/*
* RL list identifiers.
*/
enum cachefs_rl_type {
CACHEFS_RL_NONE = 0x101,
};
#define CACHEFS_RL_START CACHEFS_RL_NONE
#define CACHEFS_RL_END CACHEFS_RL_MF
#define CACHEFS_RL_INDEX(X) (X - CACHEFS_RL_START)
struct cachefs_rl_listhead {
int rli_blkcnt; /* number of 8k blocks */
int rli_itemcnt; /* number of items on list */
};
typedef struct cachefs_rl_listhead cachefs_rl_listhead_t;
/*
* Resource List information. One per cache.
*/
struct cachefs_rl_info {
/* heads of the various lists */
};
typedef struct cachefs_rl_info cachefs_rl_info_t;
/*
* rl_debug and rl_entry are stored on disk, so they need to be
* the same 32-bit vs. 64-bit.
*/
#pragma pack(4)
#endif
#ifdef CFSRLDEBUG
/*
* RL debugging thingy
*/
#define CACHEFS_RLDB_STACKSIZE 16
#define CACHEFS_RLDB_DEF_MAXCOUNT 5
typedef struct rl_debug {
enum cachefs_rl_type db_current;
int db_stackheight;
} rl_debug_t;
extern time_t cachefs_dbvalid;
extern struct kmem_cache *cachefs_rl_debug_cache;
extern kmutex_t cachefs_rl_debug_mutex;
#endif /* CFSRLDEBUG */
/*
* RL Entry type.
*/
typedef struct rl_entry {
#ifdef CFSRLDEBUG
#endif /* CFSRLDEBUG */
enum cachefs_rl_type rl_current;
} rl_entry_t;
#pragma pack()
#endif
/*
* rl entries per MAXBSIZE chunk. rl_entry_t's size need not divide
* MAXBSIZE, as long as this constant is an integer (through integer
* division) (see cachefs_rl_entry_get()).
*/
/*
* struct cache contains cache-wide information, and provides access
* to lower level info. There is one cache structure per cache.
*/
struct cachefscache {
int c_refcnt; /* active fs ref count */
struct cachefs_log_cookie
*c_log; /* in-core logging stuff */
struct cachefs_log_control
*c_log_ctl; /* on-disk logging stuff */
};
extern struct kmem_cache *cachefs_cache_kmcache;
/*
* Various cache structure flags.
*/
#define CACHE_DIRTY 0x80
/*
* Values for the mount options flag, opt_flags.
*/
/*
* Mount options
*/
#define MAXCOOKIE_SIZE 36
#define C_BACK_CHECK 0x2
/*
* Macro to determine if this is a snr error where we should do a
* state transition.
*/
/*
* Macros to assert that cachefs fscache and cnode are in
* sync with NFSv4. Note that NFSv4 always passes-through
* the vnode calls directly to the backfilesystem. For
* this to work:
* (1) cachefs is always setup for connected operation,
* (2) cachefs options (example disconnectable (snr), nonshared, etc)
* are disabled, and
* (3) the back filesystem vnode pointer always exists
* (except after a remove operation)
* (4) the front filesystem vnode pointer is always NULL.
*/
#ifdef DEBUG
#define CFS_BACKFS_NFSV4_ASSERT_FSCACHE(fscp) \
if (CFS_ISFS_BACKFS_NFSV4(fscp)) { \
}
#define CFS_BACKFS_NFSV4_ASSERT_CNODE(cp) \
if (CFS_ISFS_BACKFS_NFSV4(fscp)) { \
} else { \
} \
}
#else
#define CFS_BACKFS_NFSV4_ASSERT_FSCACHE(fscp)
#define CFS_BACKFS_NFSV4_ASSERT_CNODE(cp)
#endif /* DEBUG */
#ifdef CFSDEBUG
#define CFS_DPRINT_BACKFS_NFSV4(fscp, x) \
if (CFS_ISFS_BACKFS_NFSV4(fscp)) { \
printf x; \
}
#else
#define CFS_DPRINT_BACKFS_NFSV4(fscp, x)
#endif /* CFSDEBUG */
/*
* cachefs_allocmap and cfs_cachefs_metadata are stored on disk,
* so they need to be the same 32-bit vs. 64-bit.
*/
#pragma pack(4)
#endif
/*
* Large file support. The start offset of the cached file can be
* greater than 2GB and by coelescing the different chunks we may
* end up having a chunk of siz3 > 2GB.
*/
struct cachefs_allocmap {
};
#define C_MAX_ALLOCINFO_SLOTS 32
/*
* CFS fastsymlinks. For symlink of size < C_FSL_SIZE, the symlink
* is stored in the cnode allocmap array.
*/
#define C_FSL_SIZE (sizeof (struct cachefs_allocmap) * \
/*
* Structure representing a cached object in memory.
*/
struct cachefs_metadata {
int md_flags; /* various flags */
int md_consttype; /* type of consistency */
int md_allocents; /* nbr of entries in allocmap */
};
typedef struct cachefs_metadata cachefs_metadata_t;
#if (defined(_SYSCALL32) && defined(_LP64))
/*
* fid_t is long aligned, so user fid could be only 4 byte aligned.
*/
/* on-disk metadata structure - fid aligned to int, time is 32-bit */
struct cfs_cachefs_metadata {
int md_flags; /* various flags */
int md_consttype; /* type of consistency */
int md_allocents; /* nbr of entries in allocmap */
};
typedef struct cfs_cachefs_metadata cfs_cachefs_metadata_t;
#else /* not _SYSCALL32 && _LP64 */
typedef cachefs_metadata_t cfs_cachefs_metadata_t;
#define cfs_cachefs_metadata cachefs_metadata
#endif /* _SYSCALL32 && _LP64 */
#pragma pack()
#endif
/*
* Various flags to be stored in md_flags field of the metadata.
*/
#define C_MAX_MOUNT_FSCDIRNAME 128
/*
* cachefs mount structure and related data
*/
struct cachefs_mountargs {
char *cfs_fsid; /* CFS ID fpr file system */
/* CFS fscdir name */
char *cfs_cachedir; /* path for this cache dir */
char *cfs_backfs; /* back filesystem dir */
char *cfs_hostname; /* server name */
char *cfs_backfsname; /* back filesystem name */
};
#ifdef _SYSCALL32
struct cachefs_mountargs32 {
/* CFS fscdir name */
};
#endif /* _SYSCALL32 */
/*
* struct cachefsops - consistency modules.
*/
struct cachefsops {
int (*co_init_cobject)();
int (*co_check_cobject)();
void (*co_modify_cobject)();
void (*co_invalidate_cobject)();
void (*co_convert_cobject)();
};
/*
* The attrcache file consists of a attrcache_header structure and an
* array of attrcache_slot structures (one per front file).
*/
/*
* Attrcache file format
*
* Header
* Offset array (# of entries = file group size)
* alloc list (1 bit per entry, 0 = free) Note that the
* file will be extended as needed
* attrcache entries
*
*/
struct attrcache_header {
int ach_nffs; /* number of front files */
int ach_nblks; /* number of allocated blocks */
};
/*
* We assume that the seek offset to metadata will never be > 2GB.
* The filegrp size is 256 and the current calculations of the sizes
* of the data structures show that the ach_offset value here will not
* be > 2GB.
*/
struct attrcache_index {
};
/*
* cnode structure, one per file.
*/
/*
* LOCKS: c_rwlock Read / Write serialization
* c_statelock Protects most other fields in the cnode
* c_popcv Condvar used to prevent routines from nuking
* a cnode which is currently being populated.
* Threads blocked on it will be woken when the
* populate completes.
* c_iocv broadcast, but never waited on - unused?
* c_iomutex c_nio and c_ioflags
*
* Fields protected by other locks:
*
* c_next fg_cnodelock in the filegrp struct
* c_idleback fs_idlelock in fscache struct
* c_idlefront fs_idlelock in fscache struct
*
* Large File support: c_size goes to u_offset_t and the apopoff type
* goes to offset_t.
*/
struct cnode {
int c_flags; /* see below */
int c_invals; /* # of recent dir invals */
int c_usage; /* Usefulness of cache */
int c_error;
char *c_unlname; /* name to unlink */
int c_nio; /* Number of io's pending */
int c_ipending; /* 1 if inactive is pending */
int c_mapcnt; /* number of mapped blocks */
int c_rdcnt; /* # of read opens for backvp */
int c_wrcnt; /* # of write opens for backvp */
};
extern struct kmem_cache *cachefs_cnode_cache;
/*
* Directory caching parameters - First cut...
*/
#define CFS_DIRCACHE_COST 3
#define CFS_DIRCACHE_INVAL 3
/*
* Conversion macros
*/
/*
* Various flags stored in the flags field of the cnode structure.
*/
#define CDIRTY 0x80
/*
* io flags (in c_ioflag)
*/
#define CFS_MAX_THREADS 5
enum cachefs_cmd {
};
struct cachefs_fs_sync_req {
struct cachefscache *cf_cachep;
};
struct cachefs_idle_req {
};
/*
* Large File support the offset in the vnode for putpage request
* can now be greater than 2GB.
*/
struct cachefs_putpage_req {
int cp_len;
int cp_flags;
};
/*
* Large File support the offset in the vnode for populate request
* can now be greater than 2GB.
*/
struct cachefs_populate_req {
};
struct cachefs_req {
struct cachefs_req *cfs_next;
union {
struct cachefs_fs_sync_req cu_fs_sync;
struct cachefs_idle_req cu_idle;
struct cachefs_putpage_req cu_putpage;
struct cachefs_populate_req cu_populate;
} cfs_req_u;
};
extern struct kmem_cache *cachefs_req_cache;
/*
* Large file support: We allow cachefs to understand the 64 bit inode type.
*/
struct cachefs_fid {
};
/*
*
* cachefs kstat stuff. each time you mount a cachefs filesystem, it
* gets a unique number. it'll get that number again if you remount
* the same thing. the number is unique until reboot, but it doesn't
* survive reboots.
*
* each cachefs kstat uses this per-filesystem identifier. to get the
* valid identifiers, the `cachefs.0.key' kstat has a mapping of all
* the available filesystems. its structure, cachefs_kstat_key, is
* below.
*
*/
typedef struct cachefs_kstat_key {
int ks_id;
int ks_mounted;
extern cachefs_kstat_key_t *cachefs_kstat_key;
extern int cachefs_kstat_key_n;
/*
* cachefs debugging aid. cachefs_debug_info_t is a cookie that we
* can keep around to see what was happening at a certain time.
*
* for example, if we have a deadlock on the cnode's statelock
* (i.e. someone is not letting go of it), we can add a
* cachefs_debug_info_t * to the cnode structure, and call
* cachefs_debug_save() whenever we grab the lock. then, when we're
* deadlocked, we can see what was going on when we grabbed the lock
* in the first place, and (hopefully) why we didn't release it.
*/
#define CACHEFS_DEBUG_DEPTH (16)
typedef struct cachefs_debug_info {
char *cdb_message; /* arbitrary message */
int cdb_int; /* arbitrary int */
void *cdb_pointer; /* arbitrary pointer */
int cdb_depth; /* depth of saved stack */
/*
* cachefs function prototypes
*/
cachefscache_t *cachefs_cache_create(void);
void cachefs_do_req(struct cachefs_req *);
/* cachefs_cnode.c */
void cachefs_cnode_cleanfreelist();
void cachefs_enable_caching(struct fscache *);
/* cachefs_fscache.c */
void fscache_destroy(fscache_t *);
/* cachefs_ioctl.h */
/* cachefs_subr.c */
int cachefs_sync_metadata(cnode_t *);
int cachefs_cnode_cnt(int);
int cachefs_getfrontfile(cnode_t *);
void cachefs_nocache(cnode_t *);
void cachefs_inval_object(cnode_t *);
int cachefs_async_halt(struct cachefs_workq *, int);
int cachefs_async_okay(void);
/*
* void cachefs_cluster_allocmap(struct cnode *, u_offset_t, u_offset_t *,
* size_t *, size_t);
*/
struct cnode *);
u_offset_t, cred_t *);
int cachefs_stats_kstat_snapshot(kstat_t *, void *, int);
struct cnode *);
void cachefs_debug_show(cachefs_debug_info_t *);
int cachefs_req_create(void *, void *, int);
void cachefs_req_destroy(void *, void *);
int cachefs_stop_cache(cnode_t *);
/* cachefs_resource.c */
size_t);
void cachefs_freefile(cachefscache_t *);
int cachefs_allocfile(cachefscache_t *);
int cachefs_rl_attrc(struct cachefscache *, int, int);
void cachefs_rl_cleanup(cachefscache_t *);
#ifdef CFSRLDEBUG
void cachefs_rl_debug_save(rl_entry_t *);
void cachefs_rl_debug_show(rl_entry_t *);
void cachefs_rl_debug_destroy(rl_entry_t *);
#endif /* CFSRLDEBUG */
/* cachefs_log.c */
int cachefs_log_kstat_snapshot(kstat_t *, void *, int);
void cachefs_log_process_queue(cachefscache_t *, int);
int cachefs_log_logfile_open(cachefscache_t *, char *);
struct cachefs_log_cookie
*cachefs_log_create_cookie(struct cachefs_log_control *);
void cachefs_log_error(cachefscache_t *, int, int);
void cachefs_log_destroy_cookie(struct cachefs_log_cookie *);
uid_t, u_offset_t, int);
uid_t);
uid_t);
uid_t, u_offset_t);
uid_t);
uid_t);
int, uid_t);
uid_t, int);
u_offset_t, size_t);
int);
uint_t);
uid_t);
u_offset_t, size_t);
u_offset_t, size_t);
/* cachefs_vnops.c */
struct vnodeops *cachefs_getvnodeops(void);
void cachefs_purgeacl(cnode_t *);
int cachefs_vtype_aclok(vnode_t *);
/* cachefs_vfsops.c */
int cachefs_init_vfsops(int);
int cachefs_init_vnops(char *);
void cachefs_kstat_mount(struct fscache *, char *, char *, char *, char *);
void cachefs_kstat_umount(int);
int cachefs_kstat_key_update(kstat_t *, int);
int cachefs_kstat_key_snapshot(kstat_t *, void *, int);
extern void cachefs_workq_init(struct cachefs_workq *);
extern void *cachefs_kmem_alloc(size_t, int);
extern void *cachefs_kmem_zalloc(size_t, int);
extern void cachefs_kmem_free(void *, size_t);
extern char *cachefs_strdup(char *);
#endif /* defined (_KERNEL) && defined (__STDC__) */
/*
* ioctls.
*/
#ifdef __cplusplus
}
#endif
#endif /* _SYS_FS_CACHEFS_FS_H */