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 */
|