]> git.karo-electronics.de Git - mv-sheeva.git/blob - fs/gfs2/page.c
0d6befed1ae54c39312c0e683925caf0c7b454a0
[mv-sheeva.git] / fs / gfs2 / page.c
1 /*
2  * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
3  * Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
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>
17 #include <linux/gfs2_ondisk.h>
18
19 #include "gfs2.h"
20 #include "lm_interface.h"
21 #include "incore.h"
22 #include "bmap.h"
23 #include "inode.h"
24 #include "page.h"
25 #include "trans.h"
26 #include "ops_address.h"
27 #include "util.h"
28
29 /**
30  * gfs2_pte_inval - Sync and invalidate all PTEs associated with a glock
31  * @gl: the glock
32  *
33  */
34
35 void gfs2_pte_inval(struct gfs2_glock *gl)
36 {
37         struct gfs2_inode *ip;
38         struct inode *inode;
39
40         ip = gl->gl_object;
41         inode = &ip->i_inode;
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
48         unmap_shared_mapping_range(inode->i_mapping, 0, 0);
49
50         if (test_bit(GIF_SW_PAGED, &ip->i_flags))
51                 set_bit(GLF_DIRTY, &gl->gl_flags);
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
62 void gfs2_page_inval(struct gfs2_glock *gl)
63 {
64         struct gfs2_inode *ip;
65         struct inode *inode;
66
67         ip = gl->gl_object;
68         inode = &ip->i_inode;
69         if (!ip || !S_ISREG(ip->i_di.di_mode))
70                 return;
71
72         truncate_inode_pages(inode->i_mapping, 0);
73         gfs2_assert_withdraw(GFS2_SB(&ip->i_inode), !inode->i_mapping->nrpages);
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
86 void gfs2_page_sync(struct gfs2_glock *gl, int flags)
87 {
88         struct gfs2_inode *ip;
89         struct inode *inode;
90         struct address_space *mapping;
91         int error = 0;
92
93         ip = gl->gl_object;
94         inode = &ip->i_inode;
95         if (!ip || !S_ISREG(ip->i_di.di_mode))
96                 return;
97
98         mapping = inode->i_mapping;
99
100         if (flags & DIO_START)
101                 filemap_fdatawrite(mapping);
102         if (!error && (flags & DIO_WAIT))
103                 error = filemap_fdatawait(mapping);
104
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. */
108
109         if (error == -ENOSPC)
110                 set_bit(AS_ENOSPC, &mapping->flags);
111         else if (error)
112                 set_bit(AS_EIO, &mapping->flags);
113
114 }
115
116 /**
117  * gfs2_block_truncate_page - Deal with zeroing out data for truncate
118  *
119  * This is partly borrowed from ext3.
120  */
121 int gfs2_block_truncate_page(struct address_space *mapping)
122 {
123         struct inode *inode = mapping->host;
124         struct gfs2_inode *ip = GFS2_I(inode);
125         struct gfs2_sbd *sdp = GFS2_SB(inode);
126         loff_t from = inode->i_size;
127         unsigned long index = from >> PAGE_CACHE_SHIFT;
128         unsigned offset = from & (PAGE_CACHE_SIZE-1);
129         unsigned blocksize, iblock, length, pos;
130         struct buffer_head *bh;
131         struct page *page;
132         void *kaddr;
133         int err;
134
135         page = grab_cache_page(mapping, index);
136         if (!page)
137                 return 0;
138
139         blocksize = inode->i_sb->s_blocksize;
140         length = blocksize - (offset & (blocksize - 1));
141         iblock = index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits);
142
143         if (!page_has_buffers(page))
144                 create_empty_buffers(page, blocksize, 0);
145
146         /* Find the buffer that contains "offset" */
147         bh = page_buffers(page);
148         pos = blocksize;
149         while (offset >= pos) {
150                 bh = bh->b_this_page;
151                 iblock++;
152                 pos += blocksize;
153         }
154
155         err = 0;
156
157         if (!buffer_mapped(bh)) {
158                 gfs2_get_block(inode, iblock, bh, 0);
159                 /* unmapped? It's a hole - nothing to do */
160                 if (!buffer_mapped(bh))
161                         goto unlock;
162         }
163
164         /* Ok, it's mapped. Make sure it's up-to-date */
165         if (PageUptodate(page))
166                 set_buffer_uptodate(bh);
167
168         if (!buffer_uptodate(bh)) {
169                 err = -EIO;
170                 ll_rw_block(READ, 1, &bh);
171                 wait_on_buffer(bh);
172                 /* Uhhuh. Read error. Complain and punt. */
173                 if (!buffer_uptodate(bh))
174                         goto unlock;
175         }
176
177         if (sdp->sd_args.ar_data == GFS2_DATA_ORDERED || gfs2_is_jdata(ip))
178                 gfs2_trans_add_bh(ip->i_gl, bh, 0);
179
180         kaddr = kmap_atomic(page, KM_USER0);
181         memset(kaddr + offset, 0, length);
182         flush_dcache_page(page);
183         kunmap_atomic(kaddr, KM_USER0);
184
185 unlock:
186         unlock_page(page);
187         page_cache_release(page);
188         return err;
189 }
190
191 void gfs2_page_add_databufs(struct gfs2_inode *ip, struct page *page,
192                             unsigned int from, unsigned int to)
193 {
194         struct buffer_head *head = page_buffers(page);
195         unsigned int bsize = head->b_size;
196         struct buffer_head *bh;
197         unsigned int start, end;
198
199         for (bh = head, start = 0; bh != head || !start;
200              bh = bh->b_this_page, start = end) {
201                 end = start + bsize;
202                 if (end <= from || start >= to)
203                         continue;
204                 gfs2_trans_add_bh(ip->i_gl, bh, 0);
205         }
206 }
207