summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/sys/fs/hsfs_node.h
blob: 52524c79bc39a5cb1b2038f2c90ed634624b653e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (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
 * or http://www.opensolaris.org/os/licensing.
 * 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
 */
/*
 * High Sierra filesystem structure definitions
 */
/*
 * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_SYS_FS_HSFS_NODE_H
#define	_SYS_FS_HSFS_NODE_H

#pragma ident	"%Z%%M%	%I%	%E% SMI"

#ifdef	__cplusplus
extern "C" {
#endif

#include <sys/taskq.h>

struct	hs_direntry {
	uint_t		ext_lbn;	/* LBN of start of extent */
	uint_t		ext_size;    	/* no. of data bytes in extent */
	struct timeval	cdate;		/* creation date */
	struct timeval	mdate;		/* last modification date */
	struct timeval	adate;		/* last access date */
	enum vtype	type;		/* file type */
	mode_t		mode;		/* mode and type of file (UNIX) */
	uint_t		nlink;		/* no. of links to file */
	uid_t		uid;		/* owner's user id */
	gid_t		gid;		/* owner's group id */
	ino64_t		inode;		/* inode number from rrip data */
	dev_t		r_dev;		/* major/minor device numbers */
	uint_t		xar_prot :1;	/* 1 if protection in XAR */
	uchar_t		xar_len;	/* no. of Logical blocks in XAR */
	uchar_t		intlf_sz;	/* intleaving size */
	uchar_t		intlf_sk;	/* intleaving skip factor */
	ushort_t	sym_link_flag;	/* flags for sym link */
	char		*sym_link; 	/* path of sym link for readlink() */
};

struct	ptable {
	uchar_t	filler[7];		/* filler */
	uchar_t	dname_len;		/* length of directory name */
	uchar_t	dname[HS_DIR_NAMELEN+1];	/* directory name */
};

struct ptable_idx {
	struct ptable_idx *idx_pptbl_idx; /* parent's path table index entry */
	struct ptable	*idx_mptbl;	/* path table entry for myself */
	ushort_t idx_nochild;		/* no. of children */
	ushort_t idx_childid;		/* directory no of first child */
};

/*
 * hsnode structure:
 *
 * hs_offset, hs_ptbl_idx, base  apply to VDIR type only
 *
 * nodeid uniquely identifies an hsnode, ISO9660 means
 * nodeid can be very big.
 * For directories it is the disk address of
 * the data extent of the dir (the directory itself,
 * ".", and ".." all point to same data extent).
 * For non-directories, it is the disk address of the
 * directory entry for the file; note that this does
 * not permit hard links, as it assumes a single dir
 * entry per file.
 */

struct  hsnode {
	struct hsnode	*hs_hash;	/* next hsnode in hash list */
	struct hsnode	*hs_freef;	/* next hsnode in free list */
	struct hsnode	*hs_freeb;	/* previous hsnode in free list */
	struct vnode	*hs_vnode;	/* the real vnode for the file */
	struct hs_direntry hs_dirent;	/* the directory entry for this file */
	ino64_t		hs_nodeid;	/* "inode" number for hsnode */
	uint_t		hs_dir_lbn;	/* LBN of directory entry */
	uint_t		hs_dir_off;	/* offset in LBN of directory entry */
	struct ptable_idx	*hs_ptbl_idx;	/* path table index */
	uint_t		hs_offset;	/* start offset in dir for searching */
	long		hs_mapcnt;	/* mappings to file pages */
	uint_t		hs_seq;		/* sequence number */
	uint_t		hs_flags;	/* (see below) */
	u_offset_t	hs_prev_offset; /* Last read end offset (readahead) */
	int		hs_num_contig;  /* Count of contiguous reads */
	int		hs_ra_bytes;    /* Bytes to readahead */
	kmutex_t	hs_contents_lock;	/* protects hsnode contents */
						/* 	except hs_offset */
};

/* hs_flags */
#define	HREF	1			/* hsnode is referenced */

/* hs_modes */

#define	HFDIR	0040000			/* directory */
#define	HFREG	0100000			/* regular file */

struct  hsfid {
	ushort_t	hf_len;		/* length of fid */
	ushort_t	hf_dir_off;	/* offset in LBN of directory entry */
	uint_t		hf_dir_lbn;	/* LBN of directory */
	uint32_t	hf_ino;		/* The inode number or HS_DUMMY_INO */
};


/*
 * All of the fields in the hs_volume are read-only once they have been
 * initialized.
 */
struct	hs_volume {
	ulong_t		vol_size; 	/* no. of Logical blocks in Volume */
	uint_t		lbn_size;	/* no. of bytes in a block */
	uint_t		lbn_shift;	/* shift to convert lbn to bytes */
	uint_t		lbn_secshift;	/* shift to convert lbn to sec */
	uint_t		lbn_maxoffset;	/* max lbn-relative offset and mask */
	uchar_t		file_struct_ver; /* version of directory structure */
	uid_t		vol_uid;	/* uid of volume */
	gid_t		vol_gid;	/* gid of volume */
	uint_t		vol_prot;	/* protection (mode) of volume */
	struct timeval	cre_date;	/* volume creation time */
	struct timeval	mod_date;	/* volume modification time */
	struct	hs_direntry root_dir;	/* dir entry for Root Directory */
	ushort_t	ptbl_len;	/* number of bytes in Path Table */
	uint_t		ptbl_lbn;	/* logical block no of Path Table */
	ushort_t	vol_set_size;	/* number of CD in this vol set */
	ushort_t	vol_set_seq;	/* the sequence number of this CD */
	char		vol_id[32];		/* volume id in PVD */
};

/*
 * The hsnode table is no longer fixed in size but grows
 * and shrinks dynamically. However a cache of nodes is still maintained
 * for efficiency. This cache size (nhsnode) is a tunable which
 * is either specified in /etc/system or calculated as the number
 * that will fit into the number of bytes defined by HS_HSNODESPACE (below).
 */
#define	HS_HASHSIZE	32		/* hsnode hash table size */
#define	HS_HSNODESPACE	16384		/* approx. space used for hsnodes */

/*
 * We usually use the starting extent LBA for the inode numbers of files and
 * directories. As this will not work for zero sized files, we assign a dummy
 * inode number to all zero sized files. We use the number 16 as this is the
 * LBA for the PVD, this number cannot be a valid starting extent LBA for a
 * file. In case that the node number is the HS_DUMMY_INO, we use the LBA and
 * offset of the directory entry of this file (which is what we used before
 * we started to support correct hard links).
 */
#define	HS_DUMMY_INO	16	/* dummy inode number for empty files */

/*
 * Hsfs I/O Scheduling parameters and data structures.
 * Deadline for reads is set at 5000 usec.
 */
#define	HSFS_READ_DEADLINE 5000
#define	HSFS_NORMAL 0x0

/*
 * This structure holds information for a read request that is enqueued
 * for processing by the scheduling function. An AVL tree is used to
 * access the read requests in a sorted manner.
 */
struct hio {
	struct buf	*bp;		/* The buf for this read */
	struct hio	*contig_chain;  /* Next adjacent read if any */
	offset_t	io_lblkno;	/* Starting disk block of io */
	u_offset_t	nblocks;	/* # disk blocks */
	uint64_t	io_timestamp;	/* usec timestamp for deadline */
	ksema_t		*sema;		/* Completion flag */
	avl_node_t	io_offset_node; /* Avl tree requirements */
	avl_node_t	io_deadline_node;
};

/*
 * This structure holds information about all the read requests issued
 * during a read-ahead invocation. This is then enqueued on a task-queue
 * for processing by a background thread that takes this read-ahead to
 * completion and cleans up.
 */
struct hio_info {
	struct buf	*bufs;	/* array of bufs issued for this R/A */
	caddr_t		*vas;	/* The kmem_alloced chunk for the bufs */
	ksema_t		*sema;	/* Semaphores used in the bufs */
	uint_t		bufsused; /* # of bufs actually used */
	uint_t		bufcnt;   /* Tot bufs allocated. */
	struct page	*pp;	  /* The list of I/O locked pages */
	struct hsfs	*fsp; /* The filesystem structure */
};

/*
 * This is per-filesystem structure that stores toplevel data structures for
 * the I/O scheduler.
 */
struct hsfs_queue {
	/*
	 * A dummy hio holding the LBN of the last read processed. Easy
	 * to use in AVL_NEXT for Circular Look behavior.
	 */
	struct hio	*next;

	/*
	 * A pre-allocated buf for issuing coalesced reads. The scheduling
	 * function is mostly single threaded by necessity.
	 */
	struct buf	*nbuf;
	kmutex_t	hsfs_queue_lock; /* Protects the AVL trees */

	/*
	 * Makes most of the scheduling function Single-threaded.
	 */
	kmutex_t	strategy_lock;
	avl_tree_t	read_tree;	 /* Reads ordered by LBN */
	avl_tree_t	deadline_tree;	 /* Reads ordered by timestamp */
	taskq_t		*ra_task;	 /* Read-ahead Q */
	int		max_ra_bytes;	 /* Max read-ahead quantum */

	/* Device Max Transfer size in DEV_BSIZE */
	uint_t		dev_maxtransfer;
};

/*
 * High Sierra filesystem structure.
 * There is one of these for each mounted High Sierra filesystem.
 */
enum hs_vol_type {
	HS_VOL_TYPE_HS = 0, HS_VOL_TYPE_ISO = 1, HS_VOL_TYPE_ISO_V2 = 2,
	HS_VOL_TYPE_JOLIET = 3
};
#define	HSFS_MAGIC 0x03095500
struct hsfs {
	struct hsfs	*hsfs_next;	/* ptr to next entry in linked list */
	long		hsfs_magic;	/* should be HSFS_MAGIC */
	struct vfs	*hsfs_vfs;	/* vfs for this fs */
	struct vnode	*hsfs_rootvp;	/* vnode for root of filesystem */
	struct vnode	*hsfs_devvp;	/* device mounted on */
	enum hs_vol_type hsfs_vol_type; /* see above */
	struct hs_volume hsfs_vol;	/* File Structure Volume Descriptor */
	struct ptable	*hsfs_ptbl;	/* pointer to incore Path Table */
	int		hsfs_ptbl_size;	/* size of incore path table */
	struct ptable_idx *hsfs_ptbl_idx; /* pointer to path table index */
	int		hsfs_ptbl_idx_size;	/* no. of path table index */
	ulong_t		hsfs_ext_impl;	/* ext. information bits */
	ushort_t	hsfs_sua_off;	/* the SUA offset */
	ushort_t	hsfs_namemax;	/* maximum file name length */
	ushort_t	hsfs_namelen;	/* "official" max. file name length */
	ulong_t		hsfs_err_flags;	/* ways in which fs is non-conformant */
	char		*hsfs_fsmnt;	/* name mounted on */
	ulong_t		hsfs_flags;	/* hsfs-specific mount flags */
	krwlock_t	hsfs_hash_lock;	/* protect hash table & hst_nohsnode */
	struct hsnode	*hsfs_hash[HS_HASHSIZE]; /* head of hash lists */
	uint32_t	hsfs_nohsnode;	/* no. of allocated hsnodes */
	kmutex_t	hsfs_free_lock;	/* protects free list */
	struct hsnode	*hsfs_free_f;	/* first entry of free list */
	struct hsnode	*hsfs_free_b;	/* last entry of free list */

	/*
	 * Counters exported through kstats.
	 */
	uint64_t	physical_read_bytes;
	uint64_t	cache_read_pages;
	uint64_t	readahead_bytes;
	uint64_t	coalesced_bytes;
	uint64_t	total_pages_requested;
	kstat_t		*hsfs_kstats;

	struct hsfs_queue *hqueue;	/* I/O Scheduling parameters */
};

/*
 * Error types: bit offsets into hsfs_err_flags.
 * Also serves as index into hsfs_error[], so must be
 * kept in sync with that data structure.
 */
#define	HSFS_ERR_TRAILING_JUNK		0
#define	HSFS_ERR_LOWER_CASE_NM		1
#define	HSFS_ERR_BAD_ROOT_DIR		2
#define	HSFS_ERR_UNSUP_TYPE		3
#define	HSFS_ERR_BAD_FILE_LEN		4
#define	HSFS_ERR_BAD_JOLIET_FILE_LEN	5
#define	HSFS_ERR_TRUNC_JOLIET_FILE_LEN	6
#define	HSFS_ERR_BAD_DIR_ENTRY		7
#define	HSFS_ERR_NEG_SUA_LEN		8
#define	HSFS_ERR_BAD_SUA_LEN		9

#define	HSFS_HAVE_LOWER_CASE(fsp) \
	((fsp)->hsfs_err_flags & (1 << HSFS_ERR_LOWER_CASE_NM))


/*
 * File system parameter macros
 */
#define	hs_blksize(HSFS, HSP, OFF)	/* file system block size */ \
	((HSP)->hs_vn.v_flag & VROOT ? \
	    ((OFF) >= \
		((HSFS)->hsfs_rdirsec & ~((HSFS)->hsfs_spcl - 1))*HS_SECSIZE ?\
		((HSFS)->hsfs_rdirsec & ((HSFS)->hsfs_spcl - 1))*HS_SECSIZE :\
		(HSFS)->hsfs_clsize): \
	    (HSFS)->hsfs_clsize)
#define	hs_blkoff(OFF)		/* offset within block */ \
	((OFF) & (HS_SECSIZE - 1))

/*
 * Conversion macros
 */
#define	VFS_TO_HSFS(VFSP)	((struct hsfs *)(VFSP)->vfs_data)
#define	HSFS_TO_VFS(FSP)	((FSP)->hsfs_vfs)

#define	VTOH(VP)		((struct hsnode *)(VP)->v_data)
#define	HTOV(HP)		(((HP)->hs_vnode))

/*
 * Convert between Logical Block Number and Sector Number.
 */
#define	LBN_TO_SEC(lbn, vfsp)	((lbn)>>((struct hsfs *)((vfsp)->vfs_data))->  \
				hsfs_vol.lbn_secshift)

#define	SEC_TO_LBN(sec, vfsp)	((sec)<<((struct hsfs *)((vfsp)->vfs_data))->  \
				hsfs_vol.lbn_secshift)

#define	LBN_TO_BYTE(lbn, vfsp)	((lbn)<<((struct hsfs *)((vfsp)->vfs_data))->  \
				hsfs_vol.lbn_shift)
#define	BYTE_TO_LBN(boff, vfsp)	((boff)>>((struct hsfs *)((vfsp)->vfs_data))-> \
				hsfs_vol.lbn_shift)

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_FS_HSFS_NODE_H */