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
|
/*
* include/linux/pagevec.h
*
* In many places it is efficient to batch an operation up against multiple
* pages. A pagevec is a multipage container which is used for that.
*/
#ifndef _LINUX_PAGEVEC_H
#define _LINUX_PAGEVEC_H
/* 14 pointers + two long's align the pagevec structure to a power of two */
#define PAGEVEC_SIZE 14
struct page;
struct address_space;
struct pagevec {
unsigned long nr;
unsigned long cold;
struct page *pages[PAGEVEC_SIZE];
};
void __pagevec_release(struct pagevec *pvec);
void __pagevec_lru_add(struct pagevec *pvec);
void pagevec_remove_exceptionals(struct pagevec *pvec);
unsigned pagevec_lookup(struct pagevec *pvec, struct address_space *mapping,
pgoff_t start, unsigned nr_pages);
unsigned pagevec_lookup_tag(struct pagevec *pvec,
struct address_space *mapping, pgoff_t *index, int tag,
unsigned nr_pages);
static inline void pagevec_init(struct pagevec *pvec, int cold)
{
pvec->nr = 0;
pvec->cold = cold;
}
static inline void pagevec_reinit(struct pagevec *pvec)
{
pvec->nr = 0;
}
static inline unsigned pagevec_count(struct pagevec *pvec)
{
return pvec->nr;
}
static inline unsigned pagevec_space(struct pagevec *pvec)
{
return PAGEVEC_SIZE - pvec->nr;
}
/*
* Add a page to a pagevec. Returns the number of slots still available.
*/
static inline unsigned pagevec_add(struct pagevec *pvec, struct page *page)
{
pvec->pages[pvec->nr++] = page;
return pagevec_space(pvec);
}
static inline void pagevec_release(struct pagevec *pvec)
{
if (pagevec_count(pvec))
__pagevec_release(pvec);
}
struct pagecache_iter {
unsigned nr;
unsigned idx;
pgoff_t index;
struct page *pages[PAGEVEC_SIZE];
pgoff_t indices[PAGEVEC_SIZE];
};
static inline void pagecache_iter_init(struct pagecache_iter *iter,
pgoff_t start)
{
iter->nr = 0;
iter->idx = 0;
iter->index = start;
}
void __pagecache_iter_release(struct pagecache_iter *iter);
/**
* pagecache_iter_release - release cached pages from pagacache_iter
*
* Must be called if breaking out of for_each_pagecache_page() etc. early - not
* needed if pagecache_iter_next() returned NULL and loop terminated normally
*/
static inline void pagecache_iter_release(struct pagecache_iter *iter)
{
if (iter->nr)
__pagecache_iter_release(iter);
}
struct page *pagecache_iter_next(struct pagecache_iter *iter,
struct address_space *mapping,
pgoff_t end, pgoff_t *index,
unsigned flags);
#define __pagecache_iter_for_each(_iter, _mapping, _start, _end, \
_page, _index, _flags) \
for (pagecache_iter_init((_iter), (_start)); \
((_page) = pagecache_iter_next((_iter), (_mapping), \
(_end), (_index), (_flags)));)
#define for_each_pagecache_page(_iter, _mapping, _start, _end, _page) \
__pagecache_iter_for_each((_iter), (_mapping), (_start), (_end),\
(_page), NULL, 0)
#define for_each_pagecache_page_contig(_iter, _mapping, _start, _end, _page)\
__pagecache_iter_for_each((_iter), (_mapping), (_start), (_end),\
(_page), NULL, RADIX_TREE_ITER_CONTIG)
#define for_each_pagecache_tag(_iter, _mapping, _tag, _start, _end, _page)\
__pagecache_iter_for_each((_iter), (_mapping), (_start), (_end),\
(_page), NULL, RADIX_TREE_ITER_TAGGED|(_tag))
#define for_each_pagecache_entry(_iter, _mapping, _start, _end, _page, _index)\
__pagecache_iter_for_each((_iter), (_mapping), (_start), (_end),\
(_page), &(_index), RADIX_TREE_ITER_EXCEPTIONAL)
#define for_each_pagecache_entry_tag(_iter, _mapping, _tag, \
_start, _end, _page, _index) \
__pagecache_iter_for_each((_iter), (_mapping), (_start), (_end),\
(_page), &(_index), RADIX_TREE_ITER_EXCEPTIONAL|\
RADIX_TREE_ITER_TAGGED|(_tag))
#endif /* _LINUX_PAGEVEC_H */
|