[GFS2] Add generation number
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / fs / gfs2 / page.c
CommitLineData
b3b94faa
DT
1/*
2 * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
3a8a9a10 3 * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
b3b94faa
DT
4 *
5 * This copyrighted material is made available to anyone wishing to use,
6 * modify, copy, or redistribute it subject to the terms and conditions
7 * of the GNU General Public License v.2.
8 */
9
10#include <linux/sched.h>
11#include <linux/slab.h>
12#include <linux/spinlock.h>
13#include <linux/completion.h>
14#include <linux/buffer_head.h>
15#include <linux/pagemap.h>
16#include <linux/mm.h>
5c676f6d 17#include <linux/gfs2_ondisk.h>
b3b94faa
DT
18
19#include "gfs2.h"
5c676f6d
SW
20#include "lm_interface.h"
21#include "incore.h"
b3b94faa
DT
22#include "bmap.h"
23#include "inode.h"
24#include "page.h"
25#include "trans.h"
257f9b4e 26#include "ops_address.h"
5c676f6d 27#include "util.h"
b3b94faa
DT
28
29/**
30 * gfs2_pte_inval - Sync and invalidate all PTEs associated with a glock
31 * @gl: the glock
32 *
33 */
34
35void gfs2_pte_inval(struct gfs2_glock *gl)
36{
37 struct gfs2_inode *ip;
38 struct inode *inode;
39
5c676f6d 40 ip = gl->gl_object;
feaa7bba 41 inode = &ip->i_inode;
b3b94faa
DT
42 if (!ip || !S_ISREG(ip->i_di.di_mode))
43 return;
44
45 if (!test_bit(GIF_PAGED, &ip->i_flags))
46 return;
47
feaa7bba 48 unmap_shared_mapping_range(inode->i_mapping, 0, 0);
b3b94faa 49
feaa7bba
SW
50 if (test_bit(GIF_SW_PAGED, &ip->i_flags))
51 set_bit(GLF_DIRTY, &gl->gl_flags);
b3b94faa
DT
52
53 clear_bit(GIF_SW_PAGED, &ip->i_flags);
54}
55
56/**
57 * gfs2_page_inval - Invalidate all pages associated with a glock
58 * @gl: the glock
59 *
60 */
61
62void gfs2_page_inval(struct gfs2_glock *gl)
63{
64 struct gfs2_inode *ip;
65 struct inode *inode;
66
5c676f6d 67 ip = gl->gl_object;
feaa7bba 68 inode = &ip->i_inode;
b3b94faa
DT
69 if (!ip || !S_ISREG(ip->i_di.di_mode))
70 return;
71
feaa7bba
SW
72 truncate_inode_pages(inode->i_mapping, 0);
73 gfs2_assert_withdraw(GFS2_SB(&ip->i_inode), !inode->i_mapping->nrpages);
b3b94faa
DT
74 clear_bit(GIF_PAGED, &ip->i_flags);
75}
76
77/**
78 * gfs2_page_sync - Sync the data pages (not metadata) associated with a glock
79 * @gl: the glock
80 * @flags: DIO_START | DIO_WAIT
81 *
82 * Syncs data (not metadata) for a regular file.
83 * No-op for all other types.
84 */
85
86void gfs2_page_sync(struct gfs2_glock *gl, int flags)
87{
88 struct gfs2_inode *ip;
89 struct inode *inode;
feaa7bba
SW
90 struct address_space *mapping;
91 int error = 0;
b3b94faa 92
5c676f6d 93 ip = gl->gl_object;
feaa7bba 94 inode = &ip->i_inode;
b3b94faa
DT
95 if (!ip || !S_ISREG(ip->i_di.di_mode))
96 return;
97
feaa7bba 98 mapping = inode->i_mapping;
b3b94faa 99
feaa7bba
SW
100 if (flags & DIO_START)
101 filemap_fdatawrite(mapping);
102 if (!error && (flags & DIO_WAIT))
103 error = filemap_fdatawait(mapping);
b3b94faa 104
feaa7bba
SW
105 /* Put back any errors cleared by filemap_fdatawait()
106 so they can be caught by someone who can pass them
107 up to user space. */
b3b94faa 108
feaa7bba
SW
109 if (error == -ENOSPC)
110 set_bit(AS_ENOSPC, &mapping->flags);
111 else if (error)
112 set_bit(AS_EIO, &mapping->flags);
b3b94faa 113
b3b94faa
DT
114}
115
116/**
117 * gfs2_unstuffer_page - unstuff a stuffed inode into a block cached by a page
118 * @ip: the inode
119 * @dibh: the dinode buffer
120 * @block: the block number that was allocated
121 * @private: any locked page held by the caller process
122 *
123 * Returns: errno
124 */
125
126int gfs2_unstuffer_page(struct gfs2_inode *ip, struct buffer_head *dibh,
127 uint64_t block, void *private)
128{
feaa7bba
SW
129 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
130 struct inode *inode = &ip->i_inode;
b3b94faa
DT
131 struct page *page = (struct page *)private;
132 struct buffer_head *bh;
133 int release = 0;
134
135 if (!page || page->index) {
136 page = grab_cache_page(inode->i_mapping, 0);
137 if (!page)
138 return -ENOMEM;
139 release = 1;
140 }
141
142 if (!PageUptodate(page)) {
143 void *kaddr = kmap(page);
144
1b50259b 145 memcpy(kaddr, dibh->b_data + sizeof(struct gfs2_dinode),
b3b94faa 146 ip->i_di.di_size);
1b50259b 147 memset(kaddr + ip->i_di.di_size, 0,
b3b94faa
DT
148 PAGE_CACHE_SIZE - ip->i_di.di_size);
149 kunmap(page);
150
151 SetPageUptodate(page);
152 }
153
154 if (!page_has_buffers(page))
155 create_empty_buffers(page, 1 << inode->i_blkbits,
156 (1 << BH_Uptodate));
157
158 bh = page_buffers(page);
159
160 if (!buffer_mapped(bh))
161 map_bh(bh, inode->i_sb, block);
162
163 set_buffer_uptodate(bh);
18ec7d5c
SW
164 if ((sdp->sd_args.ar_data == GFS2_DATA_ORDERED) || gfs2_is_jdata(ip))
165 gfs2_trans_add_bh(ip->i_gl, bh, 0);
b3b94faa
DT
166 mark_buffer_dirty(bh);
167
168 if (release) {
169 unlock_page(page);
170 page_cache_release(page);
171 }
172
173 return 0;
174}
175
176/**
257f9b4e 177 * gfs2_block_truncate_page - Deal with zeroing out data for truncate
b3b94faa 178 *
257f9b4e 179 * This is partly borrowed from ext3.
b3b94faa 180 */
257f9b4e 181int gfs2_block_truncate_page(struct address_space *mapping)
b3b94faa 182{
257f9b4e 183 struct inode *inode = mapping->host;
feaa7bba
SW
184 struct gfs2_inode *ip = GFS2_I(inode);
185 struct gfs2_sbd *sdp = GFS2_SB(inode);
257f9b4e
SW
186 loff_t from = inode->i_size;
187 unsigned long index = from >> PAGE_CACHE_SHIFT;
188 unsigned offset = from & (PAGE_CACHE_SIZE-1);
189 unsigned blocksize, iblock, length, pos;
b3b94faa 190 struct buffer_head *bh;
257f9b4e 191 struct page *page;
b3b94faa 192 void *kaddr;
257f9b4e
SW
193 int err;
194
195 page = grab_cache_page(mapping, index);
196 if (!page)
197 return 0;
b3b94faa 198
257f9b4e
SW
199 blocksize = inode->i_sb->s_blocksize;
200 length = blocksize - (offset & (blocksize - 1));
201 iblock = index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits);
b3b94faa
DT
202
203 if (!page_has_buffers(page))
257f9b4e 204 create_empty_buffers(page, blocksize, 0);
b3b94faa 205
257f9b4e
SW
206 /* Find the buffer that contains "offset" */
207 bh = page_buffers(page);
208 pos = blocksize;
209 while (offset >= pos) {
210 bh = bh->b_this_page;
211 iblock++;
212 pos += blocksize;
213 }
b3b94faa 214
257f9b4e 215 err = 0;
b3b94faa 216
257f9b4e
SW
217 if (!buffer_mapped(bh)) {
218 gfs2_get_block(inode, iblock, bh, 0);
219 /* unmapped? It's a hole - nothing to do */
220 if (!buffer_mapped(bh))
221 goto unlock;
222 }
223
224 /* Ok, it's mapped. Make sure it's up-to-date */
225 if (PageUptodate(page))
226 set_buffer_uptodate(bh);
227
228 if (!buffer_uptodate(bh)) {
229 err = -EIO;
230 ll_rw_block(READ, 1, &bh);
231 wait_on_buffer(bh);
232 /* Uhhuh. Read error. Complain and punt. */
233 if (!buffer_uptodate(bh))
234 goto unlock;
235 }
236
18ec7d5c
SW
237 if (sdp->sd_args.ar_data == GFS2_DATA_ORDERED || gfs2_is_jdata(ip))
238 gfs2_trans_add_bh(ip->i_gl, bh, 0);
b3b94faa 239
257f9b4e
SW
240 kaddr = kmap_atomic(page, KM_USER0);
241 memset(kaddr + offset, 0, length);
242 flush_dcache_page(page);
243 kunmap_atomic(kaddr, KM_USER0);
244
245unlock:
b3b94faa
DT
246 unlock_page(page);
247 page_cache_release(page);
257f9b4e 248 return err;
b3b94faa
DT
249}
250
257f9b4e 251void gfs2_page_add_databufs(struct gfs2_inode *ip, struct page *page,
b3b94faa
DT
252 unsigned int from, unsigned int to)
253{
254 struct buffer_head *head = page_buffers(page);
255 unsigned int bsize = head->b_size;
256 struct buffer_head *bh;
257 unsigned int start, end;
258
29937ac6 259 for (bh = head, start = 0; bh != head || !start;
b3b94faa
DT
260 bh = bh->b_this_page, start = end) {
261 end = start + bsize;
262 if (end <= from || start >= to)
263 continue;
18ec7d5c 264 gfs2_trans_add_bh(ip->i_gl, bh, 0);
b3b94faa
DT
265 }
266}
267