1 |
/* Common definitions for the ext2 filesystem translator |
/* Common definitions for the ext2 filesystem translator |
2 |
|
|
3 |
Copyright (C) 1995, 1996, 1999, 2002, 2004 Free Software Foundation, Inc. |
Copyright (C) 1995,1996,1999,2002,2004,2005 Free Software Foundation, Inc. |
4 |
Written by Miles Bader <miles@gnu.org> |
Written by Miles Bader <miles@gnu.org> |
5 |
|
|
6 |
This program is free software; you can redistribute it and/or |
This program is free software; you can redistribute it and/or |
23 |
#include <hurd/pager.h> |
#include <hurd/pager.h> |
24 |
#include <hurd/fshelp.h> |
#include <hurd/fshelp.h> |
25 |
#include <hurd/iohelp.h> |
#include <hurd/iohelp.h> |
26 |
|
#include <hurd/store.h> |
27 |
#include <hurd/diskfs.h> |
#include <hurd/diskfs.h> |
28 |
|
#include <hurd/ihash.h> |
29 |
#include <assert.h> |
#include <assert.h> |
30 |
#include <rwlock.h> |
#include <rwlock.h> |
31 |
#include <sys/mman.h> |
#include <sys/mman.h> |
188 |
/* ---------------------------------------------------------------- */ |
/* ---------------------------------------------------------------- */ |
189 |
/* pager.c */ |
/* pager.c */ |
190 |
|
|
191 |
|
#define DISK_CACHE_BLOCKS (512 * 1024 * 1024 / 4096) /* 512M */ |
192 |
|
|
193 |
#include <hurd/diskfs-pager.h> |
#include <hurd/diskfs-pager.h> |
194 |
|
|
195 |
/* Set up the disk pager. */ |
/* Set up the disk pager. */ |
213 |
/* What the user specified. */ |
/* What the user specified. */ |
214 |
extern struct store_parsed *store_parsed; |
extern struct store_parsed *store_parsed; |
215 |
|
|
216 |
/* Mapped image of the disk. */ |
/* Mapped image of cached blocks of the disk. */ |
217 |
extern void *disk_image; |
extern void *disk_cache; |
218 |
|
extern store_offset_t disk_cache_size; |
219 |
|
extern int disk_cache_blocks; |
220 |
|
|
221 |
|
#define DC_INCORE 0x01 /* Not in core. */ |
222 |
|
#define DC_UNTOUCHED 0x02 /* Not touched by disk_pager_read_paged |
223 |
|
or buffer_lookup. */ |
224 |
|
#define DC_FIXED 0x04 /* Must not be re-associated. */ |
225 |
|
|
226 |
|
/* Flags that forbid re-association of page. DC_UNTOUCHED is included |
227 |
|
because this flag is used only when page is already to be |
228 |
|
re-associated, so it's not good candidate for another |
229 |
|
remapping. */ |
230 |
|
#define DC_DONT_REUSE (DC_INCORE | DC_UNTOUCHED | DC_FIXED) |
231 |
|
|
232 |
|
#define DC_NO_BLOCK ((block_t) -1L) |
233 |
|
|
234 |
|
#ifndef NDEBUG |
235 |
|
#define DISK_CACHE_LAST_READ_XOR 0xDEADBEEF |
236 |
|
#endif |
237 |
|
|
238 |
/* Our in-core copy of the super-block (pointer into the disk_image). */ |
/* Disk cache blocks' meta info. */ |
239 |
struct ext2_super_block *sblock; |
struct disk_cache_info |
240 |
|
{ |
241 |
|
block_t block; |
242 |
|
uint16_t flags; |
243 |
|
uint16_t ref_count; |
244 |
|
#ifndef NDEBUG |
245 |
|
block_t last_read, last_read_xor; |
246 |
|
#endif |
247 |
|
}; |
248 |
|
|
249 |
|
/* block num --> pointer to in-memory block */ |
250 |
|
extern hurd_ihash_t disk_cache_bptr; |
251 |
|
/* Metadata about cached block. */ |
252 |
|
extern struct disk_cache_info *disk_cache_info; |
253 |
|
/* Lock for these mappings */ |
254 |
|
extern struct mutex disk_cache_lock; |
255 |
|
/* Fired when a re-association is done. */ |
256 |
|
extern struct condition disk_cache_reassociation; |
257 |
|
|
258 |
|
void *buffer_lookup (block_t block); |
259 |
|
void buffer_ref (void *ptr); |
260 |
|
void buffer_put (void *ptr); |
261 |
|
int buffer_is_ref (block_t block); |
262 |
|
|
263 |
|
/* Our in-core copy of the super-block (pointer into the disk_cache). */ |
264 |
|
extern struct ext2_super_block *sblock; |
265 |
/* True if sblock has been modified. */ |
/* True if sblock has been modified. */ |
266 |
int sblock_dirty; |
extern int sblock_dirty; |
267 |
|
|
268 |
/* Where the super-block is located on disk (at min-block 1). */ |
/* Where the super-block is located on disk (at min-block 1). */ |
269 |
#define SBLOCK_BLOCK 1 /* Default location, second 1k block. */ |
#define SBLOCK_BLOCK 1 /* Default location, second 1k block. */ |
290 |
|
|
291 |
/* Get the superblock from the disk, & setup various global info from it. */ |
/* Get the superblock from the disk, & setup various global info from it. */ |
292 |
void get_hypermetadata (); |
void get_hypermetadata (); |
293 |
|
|
294 |
|
/* Map `sblock' and `group_desc_image' pointers to disk cache. */ |
295 |
|
void map_hypermetadata (); |
296 |
|
|
297 |
/* ---------------------------------------------------------------- */ |
/* ---------------------------------------------------------------- */ |
298 |
/* Random stuff calculated from the super block. */ |
/* Random stuff calculated from the super block. */ |
316 |
unsigned long next_generation; |
unsigned long next_generation; |
317 |
|
|
318 |
/* ---------------------------------------------------------------- */ |
/* ---------------------------------------------------------------- */ |
319 |
/* Functions for looking inside disk_image */ |
/* Functions for looking inside disk_cache */ |
320 |
|
|
321 |
#define trunc_block(offs) (((offs) >> log2_block_size) << log2_block_size) |
#define trunc_block(offs) \ |
322 |
|
((off_t) ((offs) >> log2_block_size) << log2_block_size) |
323 |
#define round_block(offs) \ |
#define round_block(offs) \ |
324 |
((((offs) + block_size - 1) >> log2_block_size) << log2_block_size) |
((off_t) (((offs) + block_size - 1) >> log2_block_size) << log2_block_size) |
325 |
|
|
326 |
/* block num --> byte offset on disk */ |
/* block num --> byte offset on disk */ |
327 |
#define boffs(block) ((block) << log2_block_size) |
#define boffs(block) ((off_t) (block) << log2_block_size) |
328 |
/* byte offset on disk --> block num */ |
/* byte offset on disk --> block num */ |
329 |
#define boffs_block(offs) ((offs) >> log2_block_size) |
#define boffs_block(offs) ((offs) >> log2_block_size) |
330 |
|
|
331 |
|
/* pointer to in-memory block -> index in disk_cache_info */ |
332 |
|
#define bptr_index(ptr) (((char *)ptr - (char *)disk_cache) >> log2_block_size) |
333 |
|
|
334 |
/* byte offset on disk --> pointer to in-memory block */ |
/* byte offset on disk --> pointer to in-memory block */ |
335 |
#define boffs_ptr(offs) (((char *)disk_image) + (offs)) |
EXT2FS_EI char * |
336 |
|
boffs_ptr (off_t offset) |
337 |
|
{ |
338 |
|
block_t block = boffs_block (offset); |
339 |
|
mutex_lock (&disk_cache_lock); |
340 |
|
char *ptr = hurd_ihash_find (disk_cache_bptr, block); |
341 |
|
mutex_unlock (&disk_cache_lock); |
342 |
|
assert (ptr); |
343 |
|
ptr += offset % block_size; |
344 |
|
ext2_debug ("(%Ld) = %p", offset, ptr); |
345 |
|
return ptr; |
346 |
|
} |
347 |
|
|
348 |
/* pointer to in-memory block --> byte offset on disk */ |
/* pointer to in-memory block --> byte offset on disk */ |
349 |
#define bptr_offs(ptr) ((char *)(ptr) - ((char *)disk_image)) |
EXT2FS_EI off_t |
350 |
|
bptr_offs (void *ptr) |
351 |
|
{ |
352 |
|
vm_offset_t mem_offset = (char *)ptr - (char *)disk_cache; |
353 |
|
off_t offset; |
354 |
|
assert (mem_offset < disk_cache_size); |
355 |
|
mutex_lock (&disk_cache_lock); |
356 |
|
offset = (off_t) disk_cache_info[boffs_block (mem_offset)].block |
357 |
|
<< log2_block_size; |
358 |
|
assert (offset || mem_offset < block_size); |
359 |
|
offset += mem_offset % block_size; |
360 |
|
mutex_unlock (&disk_cache_lock); |
361 |
|
ext2_debug ("(%p) = %Ld", ptr, offset); |
362 |
|
return offset; |
363 |
|
} |
364 |
|
|
365 |
/* block num --> pointer to in-memory block */ |
/* block num --> pointer to in-memory block */ |
366 |
#define bptr(block) boffs_ptr(boffs(block)) |
#define bptr(block) boffs_ptr(boffs(block)) |
377 |
|
|
378 |
/* Convert an inode number to the dinode on disk. */ |
/* Convert an inode number to the dinode on disk. */ |
379 |
EXT2FS_EI struct ext2_inode * |
EXT2FS_EI struct ext2_inode * |
380 |
dino (ino_t inum) |
dino_lookup (ino_t inum) |
381 |
{ |
{ |
382 |
unsigned long inodes_per_group = sblock->s_inodes_per_group; |
unsigned long inodes_per_group = sblock->s_inodes_per_group; |
383 |
unsigned long bg_num = (inum - 1) / inodes_per_group; |
unsigned long bg_num = (inum - 1) / inodes_per_group; |
384 |
unsigned long group_inum = (inum - 1) % inodes_per_group; |
unsigned long group_inum = (inum - 1) % inodes_per_group; |
385 |
struct ext2_group_desc *bg = group_desc(bg_num); |
struct ext2_group_desc *bg = group_desc (bg_num); |
386 |
block_t block = bg->bg_inode_table + (group_inum / inodes_per_block); |
block_t block = bg->bg_inode_table + (group_inum / inodes_per_block); |
387 |
return ((struct ext2_inode *)bptr(block)) + group_inum % inodes_per_block; |
struct ext2_inode *inode = buffer_lookup (block); |
388 |
|
inode += group_inum % inodes_per_block; |
389 |
|
ext2_debug ("(%qd) = %p", inum, inode); |
390 |
|
return inode; |
391 |
|
} |
392 |
|
|
393 |
|
EXT2FS_EI void |
394 |
|
dino_put (struct ext2_inode *inode) |
395 |
|
{ |
396 |
|
ext2_debug ("(%p)", inode); |
397 |
|
buffer_put (inode); |
398 |
} |
} |
399 |
|
|
400 |
/* ---------------------------------------------------------------- */ |
/* ---------------------------------------------------------------- */ |
447 |
EXT2FS_EI void |
EXT2FS_EI void |
448 |
record_global_poke (void *ptr) |
record_global_poke (void *ptr) |
449 |
{ |
{ |
450 |
int boffs = trunc_block (bptr_offs (ptr)); |
block_t block = boffs_block (bptr_offs (ptr)); |
451 |
global_block_modified (boffs_block (boffs)); |
void *block_ptr = bptr (block); |
452 |
pokel_add (&global_pokel, boffs_ptr(boffs), block_size); |
ext2_debug ("(%p = %p)", ptr, block_ptr); |
453 |
|
assert (buffer_is_ref (block)); |
454 |
|
global_block_modified (block); |
455 |
|
pokel_add (&global_pokel, block_ptr, block_size); |
456 |
} |
} |
457 |
|
|
458 |
/* This syncs a modification to a non-file block. */ |
/* This syncs a modification to a non-file block. */ |
459 |
EXT2FS_EI void |
EXT2FS_EI void |
460 |
sync_global_ptr (void *bptr, int wait) |
sync_global_ptr (void *bptr, int wait) |
461 |
{ |
{ |
462 |
vm_offset_t boffs = trunc_block (bptr_offs (bptr)); |
block_t block = boffs_block (bptr_offs (bptr)); |
463 |
global_block_modified (boffs_block (boffs)); |
void *block_ptr = bptr (block); |
464 |
pager_sync_some (diskfs_disk_pager, trunc_page (boffs), vm_page_size, wait); |
ext2_debug ("(%p -> %u)", bptr, (block_t)block); |
465 |
|
global_block_modified (block); |
466 |
|
buffer_put (block_ptr); |
467 |
|
pager_sync_some (diskfs_disk_pager, |
468 |
|
block_ptr - disk_cache, block_size, wait); |
469 |
|
|
470 |
} |
} |
471 |
|
|
472 |
/* This records a modification to one of a file's indirect blocks. */ |
/* This records a modification to one of a file's indirect blocks. */ |
473 |
EXT2FS_EI void |
EXT2FS_EI void |
474 |
record_indir_poke (struct node *node, void *ptr) |
record_indir_poke (struct node *node, void *ptr) |
475 |
{ |
{ |
476 |
int boffs = trunc_block (bptr_offs (ptr)); |
block_t block = boffs_block (bptr_offs (ptr)); |
477 |
global_block_modified (boffs_block (boffs)); |
void *block_ptr = bptr (block); |
478 |
pokel_add (&node->dn->indir_pokel, boffs_ptr(boffs), block_size); |
ext2_debug ("(%d, %p)", (int)node->cache_id, ptr); |
479 |
|
assert (buffer_is_ref (block)); |
480 |
|
global_block_modified (block); |
481 |
|
pokel_add (&node->dn->indir_pokel, block_ptr, block_size); |
482 |
} |
} |
483 |
|
|
484 |
/* ---------------------------------------------------------------- */ |
/* ---------------------------------------------------------------- */ |
486 |
EXT2FS_EI void |
EXT2FS_EI void |
487 |
sync_global (int wait) |
sync_global (int wait) |
488 |
{ |
{ |
489 |
|
ext2_debug ("%d", wait); |
490 |
pokel_sync (&global_pokel, wait); |
pokel_sync (&global_pokel, wait); |
491 |
} |
} |
492 |
|
|