Blame view

include/linux/pagemap.h 7.19 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
  #ifndef _LINUX_PAGEMAP_H
  #define _LINUX_PAGEMAP_H
  
  /*
   * Copyright 1995 Linus Torvalds
   */
  #include <linux/mm.h>
  #include <linux/fs.h>
  #include <linux/list.h>
  #include <linux/highmem.h>
  #include <linux/compiler.h>
  #include <asm/uaccess.h>
  #include <linux/gfp.h>
3e9f45bd1   Guillaume Chazarain   Factor outstandin...
14
  #include <linux/bitops.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
15
16
17
18
19
20
21
  
  /*
   * Bits in mapping->flags.  The lower __GFP_BITS_SHIFT bits are the page
   * allocation mode flags.
   */
  #define	AS_EIO		(__GFP_BITS_SHIFT + 0)	/* IO error on async write */
  #define AS_ENOSPC	(__GFP_BITS_SHIFT + 1)	/* ENOSPC on async write */
3e9f45bd1   Guillaume Chazarain   Factor outstandin...
22
23
24
25
26
27
28
29
30
  static inline void mapping_set_error(struct address_space *mapping, int error)
  {
  	if (error) {
  		if (error == -ENOSPC)
  			set_bit(AS_ENOSPC, &mapping->flags);
  		else
  			set_bit(AS_EIO, &mapping->flags);
  	}
  }
dd0fc66fb   Al Viro   [PATCH] gfp flags...
31
  static inline gfp_t mapping_gfp_mask(struct address_space * mapping)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32
  {
260b23674   Al Viro   [PATCH] gfp_t: th...
33
  	return (__force gfp_t)mapping->flags & __GFP_BITS_MASK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
35
36
37
38
39
  }
  
  /*
   * This is non-atomic.  Only to be used before the mapping is activated.
   * Probably needs a barrier...
   */
260b23674   Al Viro   [PATCH] gfp_t: th...
40
  static inline void mapping_set_gfp_mask(struct address_space *m, gfp_t mask)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
  {
260b23674   Al Viro   [PATCH] gfp_t: th...
42
43
  	m->flags = (m->flags & ~(__force unsigned long)__GFP_BITS_MASK) |
  				(__force unsigned long)mask;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
  }
  
  /*
   * The page cache can done in larger chunks than
   * one page, because it allows for more efficient
   * throughput (it can then be mapped into user
   * space in smaller chunks for same flexibility).
   *
   * Or rather, it _will_ be done in larger chunks.
   */
  #define PAGE_CACHE_SHIFT	PAGE_SHIFT
  #define PAGE_CACHE_SIZE		PAGE_SIZE
  #define PAGE_CACHE_MASK		PAGE_MASK
  #define PAGE_CACHE_ALIGN(addr)	(((addr)+PAGE_CACHE_SIZE-1)&PAGE_CACHE_MASK)
  
  #define page_cache_get(page)		get_page(page)
  #define page_cache_release(page)	put_page(page)
  void release_pages(struct page **pages, int nr, int cold);
44110fe38   Paul Jackson   [PATCH] cpuset me...
62
  #ifdef CONFIG_NUMA
2ae88149a   Nick Piggin   [PATCH] mm: clean...
63
  extern struct page *__page_cache_alloc(gfp_t gfp);
44110fe38   Paul Jackson   [PATCH] cpuset me...
64
  #else
2ae88149a   Nick Piggin   [PATCH] mm: clean...
65
66
67
68
69
  static inline struct page *__page_cache_alloc(gfp_t gfp)
  {
  	return alloc_pages(gfp, 0);
  }
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70
71
  static inline struct page *page_cache_alloc(struct address_space *x)
  {
2ae88149a   Nick Piggin   [PATCH] mm: clean...
72
  	return __page_cache_alloc(mapping_gfp_mask(x));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
73
74
75
76
  }
  
  static inline struct page *page_cache_alloc_cold(struct address_space *x)
  {
2ae88149a   Nick Piggin   [PATCH] mm: clean...
77
  	return __page_cache_alloc(mapping_gfp_mask(x)|__GFP_COLD);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78
79
80
81
82
83
84
85
  }
  
  typedef int filler_t(void *, struct page *);
  
  extern struct page * find_get_page(struct address_space *mapping,
  				unsigned long index);
  extern struct page * find_lock_page(struct address_space *mapping,
  				unsigned long index);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86
  extern struct page * find_or_create_page(struct address_space *mapping,
6daa0e286   Al Viro   [PATCH] gfp_t: mm...
87
  				unsigned long index, gfp_t gfp_mask);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
88
89
  unsigned find_get_pages(struct address_space *mapping, pgoff_t start,
  			unsigned int nr_pages, struct page **pages);
ebf43500e   Jens Axboe   [PATCH] Add find_...
90
91
  unsigned find_get_pages_contig(struct address_space *mapping, pgoff_t start,
  			       unsigned int nr_pages, struct page **pages);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
92
93
94
95
96
97
98
99
100
101
102
103
104
  unsigned find_get_pages_tag(struct address_space *mapping, pgoff_t *index,
  			int tag, unsigned int nr_pages, struct page **pages);
  
  /*
   * Returns locked page at given index in given cache, creating it if needed.
   */
  static inline struct page *grab_cache_page(struct address_space *mapping, unsigned long index)
  {
  	return find_or_create_page(mapping, index, mapping_gfp_mask(mapping));
  }
  
  extern struct page * grab_cache_page_nowait(struct address_space *mapping,
  				unsigned long index);
6fe6900e1   Nick Piggin   mm: make read_cac...
105
106
107
  extern struct page * read_cache_page_async(struct address_space *mapping,
  				unsigned long index, filler_t *filler,
  				void *data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
108
109
110
111
112
  extern struct page * read_cache_page(struct address_space *mapping,
  				unsigned long index, filler_t *filler,
  				void *data);
  extern int read_cache_pages(struct address_space *mapping,
  		struct list_head *pages, filler_t *filler, void *data);
6fe6900e1   Nick Piggin   mm: make read_cac...
113
114
115
116
117
118
119
  static inline struct page *read_mapping_page_async(
  						struct address_space *mapping,
  					     unsigned long index, void *data)
  {
  	filler_t *filler = (filler_t *)mapping->a_ops->readpage;
  	return read_cache_page_async(mapping, index, filler, data);
  }
090d2b185   Pekka Enberg   [PATCH] read_mapp...
120
121
122
123
124
125
  static inline struct page *read_mapping_page(struct address_space *mapping,
  					     unsigned long index, void *data)
  {
  	filler_t *filler = (filler_t *)mapping->a_ops->readpage;
  	return read_cache_page(mapping, index, filler, data);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
126
  int add_to_page_cache(struct page *page, struct address_space *mapping,
6daa0e286   Al Viro   [PATCH] gfp_t: mm...
127
  				unsigned long index, gfp_t gfp_mask);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
128
  int add_to_page_cache_lru(struct page *page, struct address_space *mapping,
6daa0e286   Al Viro   [PATCH] gfp_t: mm...
129
  				unsigned long index, gfp_t gfp_mask);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
130
131
  extern void remove_from_page_cache(struct page *page);
  extern void __remove_from_page_cache(struct page *page);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
  /*
   * Return byte-offset into filesystem object for page.
   */
  static inline loff_t page_offset(struct page *page)
  {
  	return ((loff_t)page->index) << PAGE_CACHE_SHIFT;
  }
  
  static inline pgoff_t linear_page_index(struct vm_area_struct *vma,
  					unsigned long address)
  {
  	pgoff_t pgoff = (address - vma->vm_start) >> PAGE_SHIFT;
  	pgoff += vma->vm_pgoff;
  	return pgoff >> (PAGE_CACHE_SHIFT - PAGE_SHIFT);
  }
  
  extern void FASTCALL(__lock_page(struct page *page));
db37648cd   Nick Piggin   [PATCH] mm: non s...
149
  extern void FASTCALL(__lock_page_nosync(struct page *page));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
150
  extern void FASTCALL(unlock_page(struct page *page));
db37648cd   Nick Piggin   [PATCH] mm: non s...
151
152
153
  /*
   * lock_page may only be called if we have the page's inode pinned.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
154
155
156
157
158
159
  static inline void lock_page(struct page *page)
  {
  	might_sleep();
  	if (TestSetPageLocked(page))
  		__lock_page(page);
  }
db37648cd   Nick Piggin   [PATCH] mm: non s...
160
161
162
163
164
165
166
167
168
169
170
  
  /*
   * lock_page_nosync should only be used if we can't pin the page's inode.
   * Doesn't play quite so well with block device plugging.
   */
  static inline void lock_page_nosync(struct page *page)
  {
  	might_sleep();
  	if (TestSetPageLocked(page))
  		__lock_page_nosync(page);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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
  	
  /*
   * This is exported only for wait_on_page_locked/wait_on_page_writeback.
   * Never use this directly!
   */
  extern void FASTCALL(wait_on_page_bit(struct page *page, int bit_nr));
  
  /* 
   * Wait for a page to be unlocked.
   *
   * This must be called with the caller "holding" the page,
   * ie with increased "page->count" so that the page won't
   * go away during the wait..
   */
  static inline void wait_on_page_locked(struct page *page)
  {
  	if (PageLocked(page))
  		wait_on_page_bit(page, PG_locked);
  }
  
  /* 
   * Wait for a page to complete writeback
   */
  static inline void wait_on_page_writeback(struct page *page)
  {
  	if (PageWriteback(page))
  		wait_on_page_bit(page, PG_writeback);
  }
  
  extern void end_page_writeback(struct page *page);
  
  /*
   * Fault a userspace page into pagetables.  Return non-zero on a fault.
   *
   * This assumes that two userspace pages are always sufficient.  That's
   * not true if PAGE_CACHE_SIZE > PAGE_SIZE.
   */
  static inline int fault_in_pages_writeable(char __user *uaddr, int size)
  {
  	int ret;
  
  	/*
  	 * Writing zeroes into userspace here is OK, because we know that if
  	 * the zero gets there, we'll be overwriting it.
  	 */
  	ret = __put_user(0, uaddr);
  	if (ret == 0) {
  		char __user *end = uaddr + size - 1;
  
  		/*
  		 * If the page was already mapped, this will get a cache miss
  		 * for sure, so try to avoid doing it.
  		 */
  		if (((unsigned long)uaddr & PAGE_MASK) !=
  				((unsigned long)end & PAGE_MASK))
  		 	ret = __put_user(0, end);
  	}
  	return ret;
  }
  
  static inline void fault_in_pages_readable(const char __user *uaddr, int size)
  {
  	volatile char c;
  	int ret;
  
  	ret = __get_user(c, uaddr);
  	if (ret == 0) {
  		const char __user *end = uaddr + size - 1;
  
  		if (((unsigned long)uaddr & PAGE_MASK) !=
  				((unsigned long)end & PAGE_MASK))
  		 	__get_user(c, end);
  	}
  }
  
  #endif /* _LINUX_PAGEMAP_H */