Loading...
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 | #ifndef _LINUX_PAGEMAP_H
#define _LINUX_PAGEMAP_H
#include <asm/system.h>
/*
* Page-mapping primitive inline functions
*
* Copyright 1995 Linus Torvalds
*/
#include <linux/mm.h>
#include <linux/fs.h>
static inline unsigned long page_address(struct page * page)
{
return PAGE_OFFSET + PAGE_SIZE * page->map_nr;
}
#define PAGE_HASH_BITS 11
#define PAGE_HASH_SIZE (1 << PAGE_HASH_BITS)
#define PAGE_AGE_VALUE 16
extern unsigned long page_cache_size; /* # of pages currently in the hash table */
extern struct page * page_hash_table[PAGE_HASH_SIZE];
/*
* We use a power-of-two hash table to avoid a modulus,
* and get a reasonable hash by knowing roughly how the
* inode pointer and offsets are distributed (ie, we
* roughly know which bits are "significant")
*/
static inline unsigned long _page_hashfn(struct inode * inode, unsigned long offset)
{
#define i (((unsigned long) inode)/(sizeof(struct inode) & ~ (sizeof(struct inode) - 1)))
#define o (offset >> PAGE_SHIFT)
#define s(x) ((x)+((x)>>PAGE_HASH_BITS))
return s(i+o) & (PAGE_HASH_SIZE-1);
#undef i
#undef o
#undef s
}
#define page_hash(inode,offset) (page_hash_table+_page_hashfn(inode,offset))
static inline struct page * __find_page(struct inode * inode, unsigned long offset, struct page *page)
{
goto inside;
for (;;) {
page = page->next_hash;
inside:
if (!page)
goto not_found;
if (page->inode != inode)
continue;
if (page->offset == offset)
break;
}
/* Found the page. */
atomic_inc(&page->count);
set_bit(PG_referenced, &page->flags);
not_found:
return page;
}
static inline struct page *find_page(struct inode * inode, unsigned long offset)
{
return __find_page(inode, offset, *page_hash(inode, offset));
}
static inline void remove_page_from_hash_queue(struct page * page)
{
if(page->pprev_hash) {
if(page->next_hash)
page->next_hash->pprev_hash = page->pprev_hash;
*page->pprev_hash = page->next_hash;
page->pprev_hash = NULL;
}
page_cache_size--;
}
static inline void __add_page_to_hash_queue(struct page * page, struct page **p)
{
page_cache_size++;
set_bit(PG_referenced, &page->flags);
page->age = PAGE_AGE_VALUE;
if((page->next_hash = *p) != NULL)
(*p)->pprev_hash = &page->next_hash;
*p = page;
page->pprev_hash = p;
}
static inline void add_page_to_hash_queue(struct page * page, struct inode * inode, unsigned long offset)
{
__add_page_to_hash_queue(page, page_hash(inode,offset));
}
static inline void remove_page_from_inode_queue(struct page * page)
{
struct inode * inode = page->inode;
page->inode = NULL;
inode->i_nrpages--;
if (inode->i_pages == page)
inode->i_pages = page->next;
if (page->next)
page->next->prev = page->prev;
if (page->prev)
page->prev->next = page->next;
page->next = NULL;
page->prev = NULL;
}
static inline void add_page_to_inode_queue(struct inode * inode, struct page * page)
{
struct page **p = &inode->i_pages;
inode->i_nrpages++;
page->inode = inode;
page->prev = NULL;
if ((page->next = *p) != NULL)
page->next->prev = page;
*p = page;
}
extern void __wait_on_page(struct page *);
static inline void wait_on_page(struct page * page)
{
if (PageLocked(page))
__wait_on_page(page);
}
extern void update_vm_cache(struct inode *, unsigned long, const char *, int);
#endif
|