1 /*
2  * The LFS user-level library will be used when writing cleaners and
3  * checkers for LFS file systems.  It will have facilities
4  * for finding and parsing LFS segments.
5  */
6 
7 #define DUMP_SUM_HEADER		0x0001
8 #define DUMP_INODE_ADDRS	0x0002
9 #define DUMP_FINFOS		0x0004
10 #define	DUMP_ALL		0xFFFF
11 
12 #define IFILE_NAME "ifile"
13 
14 #ifndef TRUE
15 #define TRUE	(1)
16 #define FALSE	(0)
17 #endif
18 
19 /*
20  * Cleaner parameters
21  *	BUSY_LIM: lower bound of the number of segments currently available
22  *		as a percentage of the total number of free segments possibly
23  *		available.
24  *	IDLE_LIM: Same as BUSY_LIM but used when the system is idle.
25  *	MIN_SEGS: Minimum number of segments you should always have.
26  *		I have no idea what this should be, but it should probably
27  *		be a function of lfsp.
28  *	NUM_TO_CLEAN: Number of segments to clean at once.  Again, this
29  *		should probably be based on the file system size and how
30  *		full or empty the segments being cleaned are.
31  */
32 
33 #define	BUSY_LIM	0.50
34 #define	IDLE_LIM	0.90
35 #define	MIN_SEGS(lfsp)	(3)
36 #define	NUM_TO_CLEAN(fsp)	(5)
37 
38 #define MAXLOADS	3
39 #define	ONE_MIN	0
40 #define	FIVE_MIN 1
41 #define	FIFTEEN_MIN 2
42 
43 typedef struct fs_info {
44 	struct	statfs	*fi_statfsp;	/* fsstat info from getfsstat */
45 	struct	lfs	fi_lfs;		/* superblock */
46 	CLEANERINFO	*fi_cip;	/* Cleaner info from ifile */
47 	SEGUSE	*fi_segusep;		/* segment usage table (from ifile) */
48 	IFILE	*fi_ifilep;		/* ifile table (from ifile) */
49 	u_long	fi_daddr_shift;		/* shift to get byte offset of daddr */
50 	u_long	fi_ifile_count;		/* # entries in the ifile table */
51 	off_t	fi_ifile_length;	/* length of the ifile */
52 } FS_INFO;
53 
54 /*
55  * XXX: size (in bytes) of a segment
56  *	should lfs_bsize be fsbtodb(fs,1), blksize(fs), or lfs_dsize?
57  */
58 #define seg_size(fs) ((fs)->lfs_ssize << (fs)->lfs_bshift)
59 
60 /* daddr -> byte offset */
61 #define datobyte(fs, da) ((da) << (fs)->fi_daddr_shift)
62 #define bytetoda(fs, byte) ((byte) >> (fs)->fi_daddr_shift)
63 
64 #define CLEANSIZE(fsp)	(fsp->fi_lfs.lfs_cleansz << fsp->fi_lfs.lfs_bshift)
65 #define SEGTABSIZE(fsp)	(fsp->fi_lfs.lfs_segtabsz << fsp->fi_lfs.lfs_bshift)
66 
67 #define IFILE_ENTRY(fs, if, i) \
68 	((IFILE *)((caddr_t)(if) + ((i) / (fs)->lfs_ifpb << (fs)->lfs_bshift)) \
69 	+ (i) % (fs)->lfs_ifpb)
70 
71 #define SEGUSE_ENTRY(fs, su, i) \
72 	((SEGUSE *)((caddr_t)(su) + (fs)->lfs_bsize * ((i) / (fs)->lfs_sepb)) +\
73 	(i) % (fs)->lfs_sepb)
74 
75 __BEGIN_DECLS
76 int	 dump_summary __P((struct lfs *, SEGSUM *, u_long, daddr_t **));
77 void	 err __P((const int, const char *, ...));
78 int	 fs_getmntinfo __P((struct statfs **, int));
79 int	 get __P((int, off_t, void *, size_t));
80 FS_INFO	*get_fs_info __P((struct statfs *, int));
81 int 	 lfs_segmapv __P((FS_INFO *, int, caddr_t, BLOCK_INFO **, int *,
82 	     INODE_INFO **, int *));
83 int	 mmap_segment __P((FS_INFO *, int, caddr_t *));
84 void	 munmap_segment __P((FS_INFO *, caddr_t));
85 void	 reread_fs_info __P((FS_INFO *, int));
86 void	 toss __P((void *, int *, size_t,
87 	      int (*)(const void *, const void *, const void *), void *));
88 
89 /*
90  * USEFUL DEBUGGING FUNCTIONS:
91  */
92 #ifdef VERBOSE
93 #define PRINT_FINFO(fp, ip) { \
94 	(void)printf("    %s %s%d version %d nblocks %d\n", \
95 	    (ip)->if_version > (fp)->fi_version ? "TOSSING" : "KEEPING", \
96 	    "FINFO for inode: ", (fp)->fi_ino, \
97 	    (fp)->fi_version, (fp)->fi_nblocks); \
98 	fflush(stdout); \
99 }
100 
101 #define PRINT_IINFO(b, iip) { \
102 	(void) printf("\t%s inode: %d daddr: 0x%lx create: %s\n", \
103 	    b ? "KEEPING" : "TOSSING", (iip)->ii_inode, (iip)->ii_daddr, \
104 	    ctime((time_t *)&(iip)->ii_segcreate)); \
105 	fflush(stdout); \
106 }
107 
108 #define PRINT_BINFO(bip) { \
109 	(void)printf("\tinode: %d lbn: %d daddr: 0x%lx create: %s\n", \
110 	    (bip)->bi_inode, (bip)->bi_lbn, (bip)->bi_daddr, \
111 	    ctime((time_t *)&(bip)->bi_segcreate)); \
112 	fflush(stdout); \
113 }
114 
115 #define PRINT_SEGUSE(sup, n) { \
116 	(void)printf("Segment %d nbytes=%lu\tflags=%c%c%c ninos=%d nsums=%d lastmod: %s\n", \
117 			n, (sup)->su_nbytes, \
118 			(sup)->su_flags & SEGUSE_DIRTY ? 'D' : 'C', \
119 			(sup)->su_flags & SEGUSE_ACTIVE ? 'A' : ' ', \
120 			(sup)->su_flags & SEGUSE_SUPERBLOCK ? 'S' : ' ', \
121 			(sup)->su_ninos, (sup)->su_nsums, \
122 			ctime((time_t *)&(sup)->su_lastmod)); \
123 	fflush(stdout); \
124 }
125 
126 void	 dump_super __P((struct lfs *));
127 void	 dump_cleaner_info __P((void *));
128 void	 print_SEGSUM __P(( struct lfs *, SEGSUM *));
129 void	 print_CLEANERINFO __P((CLEANERINFO *));
130 #else
131 #define	PRINT_FINFO(fp, ip)
132 #define	PRINT_IINFO(b, iip)
133 #define PRINT_BINFO(bip)
134 #define	PRINT_SEGUSE(sup, n)
135 #define	dump_cleaner_info(cip)
136 #define	dump_super(lfsp)
137 #endif
138 
139 __END_DECLS
140