1 |
/* Pager for ext2fs |
/* Pager for ext2fs |
2 |
|
|
3 |
Copyright (C) 1994,95,96,97,98,99,2000 Free Software Foundation, Inc. |
Copyright (C) 1994,95,96,97,98,99,2000,02 Free Software Foundation, Inc. |
4 |
|
|
5 |
Converted for ext2fs by Miles Bader <miles@gnu.org> |
Converted for ext2fs by Miles Bader <miles@gnu.org> |
6 |
|
|
69 |
#define STAT_INC(field) /* nop */0 |
#define STAT_INC(field) /* nop */0 |
70 |
#endif /* STATS */ |
#endif /* STATS */ |
71 |
|
|
72 |
#define MAX_FREE_PAGE_BUFS 32 |
#define FREE_PAGE_BUFS 24 |
|
|
|
|
static spin_lock_t free_page_bufs_lock = SPIN_LOCK_INITIALIZER; |
|
|
static void *free_page_bufs = 0; |
|
|
static int num_free_page_bufs = 0; |
|
73 |
|
|
74 |
/* Returns a single page page-aligned buffer. */ |
/* Returns a single page page-aligned buffer. */ |
75 |
static void * |
static void * |
76 |
get_page_buf () |
get_page_buf () |
77 |
{ |
{ |
78 |
|
static struct mutex free_page_bufs_lock = MUTEX_INITIALIZER; |
79 |
|
static void *free_page_bufs; |
80 |
|
static int num_free_page_bufs; |
81 |
void *buf; |
void *buf; |
82 |
|
|
83 |
spin_lock (&free_page_bufs_lock); |
mutex_lock (&free_page_bufs_lock); |
84 |
|
if (num_free_page_bufs > 0) |
|
buf = free_page_bufs; |
|
|
if (buf == 0) |
|
85 |
{ |
{ |
86 |
spin_unlock (&free_page_bufs_lock); |
buf = free_page_bufs; |
87 |
buf = mmap (0, vm_page_size, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0); |
num_free_page_bufs --; |
88 |
if (buf == (void *) -1) |
if (num_free_page_bufs > 0) |
89 |
buf = 0; |
free_page_bufs += vm_page_size; |
90 |
|
#ifndef NDEBUG |
91 |
|
else |
92 |
|
free_page_bufs = 0; |
93 |
|
#endif /* ! NDEBUG */ |
94 |
} |
} |
95 |
else |
else |
96 |
{ |
{ |
97 |
free_page_bufs = *(void **)buf; |
assert (free_page_bufs == 0); |
98 |
num_free_page_bufs--; |
buf = mmap (0, vm_page_size * FREE_PAGE_BUFS, |
99 |
spin_unlock (&free_page_bufs_lock); |
PROT_READ|PROT_WRITE, MAP_ANON, 0, 0); |
100 |
|
if (buf == MAP_FAILED) |
101 |
|
buf = 0; |
102 |
|
else |
103 |
|
{ |
104 |
|
free_page_bufs = buf + vm_page_size; |
105 |
|
num_free_page_bufs = FREE_PAGE_BUFS - 1; |
106 |
|
} |
107 |
} |
} |
108 |
|
|
109 |
|
mutex_unlock (&free_page_bufs_lock); |
110 |
return buf; |
return buf; |
111 |
} |
} |
112 |
|
|
113 |
/* Frees a block returned by get_page_buf. */ |
/* Frees a block returned by get_page_buf. */ |
114 |
static void |
static inline void |
115 |
free_page_buf (void *buf) |
free_page_buf (void *buf) |
116 |
{ |
{ |
117 |
spin_lock (&free_page_bufs_lock); |
munmap (buf, vm_page_size); |
|
if (num_free_page_bufs < MAX_FREE_PAGE_BUFS) |
|
|
{ |
|
|
*(void **)buf = free_page_bufs; |
|
|
free_page_bufs = buf; |
|
|
num_free_page_bufs++; |
|
|
spin_unlock (&free_page_bufs_lock); |
|
|
} |
|
|
else |
|
|
{ |
|
|
spin_unlock (&free_page_bufs_lock); |
|
|
munmap (buf, vm_page_size); |
|
|
} |
|
118 |
} |
} |
119 |
|
|
120 |
/* Find the location on disk of page OFFSET in NODE. Return the disk block |
/* Find the location on disk of page OFFSET in NODE. Return the disk block |
121 |
in BLOCK (if unallocated, then return 0). If *LOCK is 0, then it a reader |
in BLOCK (if unallocated, then return 0). If *LOCK is 0, then a reader |
122 |
lock is aquired on NODE's ALLOC_LOCK before doing anything, and left |
lock is aquired on NODE's ALLOC_LOCK before doing anything, and left |
123 |
locked after return -- even if an error is returned. 0 on success or an |
locked after the return -- even if an error is returned. 0 is returned |
124 |
error code otherwise is returned. */ |
on success otherwise an error code. */ |
125 |
static error_t |
static error_t |
126 |
find_block (struct node *node, vm_offset_t offset, |
find_block (struct node *node, vm_offset_t offset, |
127 |
block_t *block, struct rwlock **lock) |
block_t *block, struct rwlock **lock) |