aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2007-10-15 10:40:33 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2008-01-25 03:07:13 -0500
commit3cc3f710ce0effe397b830826a1a081fa81f11c7 (patch)
tree53f69f1b8d1cbc2849c6bac08ce7786f3ecd7447
parent51ff87bdd9f21a5d3672517b75d25ab5842d94a8 (diff)
[GFS2] Use ->page_mkwrite() for mmap()
This cleans up the mmap() code path for GFS2 by implementing the page_mkwrite function for GFS2. We are thus able to use the generic filemap_fault function for our ->fault() implementation. This now means that shared writable mappings will be much more efficiently shared across the cluster if there is a reasonable proportion of read activity (the greater proportion, the better). As a side effect, it also reduces the size of the code, removes special cases from readpage and readpages, and makes the code path easier to follow. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
-rw-r--r--fs/gfs2/Makefile2
-rw-r--r--fs/gfs2/glops.c9
-rw-r--r--fs/gfs2/incore.h8
-rw-r--r--fs/gfs2/ops_address.c45
-rw-r--r--fs/gfs2/ops_file.c131
-rw-r--r--fs/gfs2/ops_vm.c169
-rw-r--r--fs/gfs2/ops_vm.h18
7 files changed, 131 insertions, 251 deletions
diff --git a/fs/gfs2/Makefile b/fs/gfs2/Makefile
index 04ad0caebedb..8fff11058cee 100644
--- a/fs/gfs2/Makefile
+++ b/fs/gfs2/Makefile
@@ -2,7 +2,7 @@ obj-$(CONFIG_GFS2_FS) += gfs2.o
2gfs2-y := acl.o bmap.o daemon.o dir.o eaops.o eattr.o glock.o \ 2gfs2-y := acl.o bmap.o daemon.o dir.o eaops.o eattr.o glock.o \
3 glops.o inode.o lm.o log.o lops.o locking.o main.o meta_io.o \ 3 glops.o inode.o lm.o log.o lops.o locking.o main.o meta_io.o \
4 mount.o ops_address.o ops_dentry.o ops_export.o ops_file.o \ 4 mount.o ops_address.o ops_dentry.o ops_export.o ops_file.o \
5 ops_fstype.o ops_inode.o ops_super.o ops_vm.o quota.o \ 5 ops_fstype.o ops_inode.o ops_super.o quota.o \
6 recovery.o rgrp.o super.o sys.o trans.o util.o 6 recovery.o rgrp.o super.o sys.o trans.o util.o
7 7
8obj-$(CONFIG_GFS2_FS_LOCKING_NOLOCK) += locking/nolock/ 8obj-$(CONFIG_GFS2_FS_LOCKING_NOLOCK) += locking/nolock/
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index 4670dcb2a877..110f03d66f4b 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -86,15 +86,10 @@ static void gfs2_pte_inval(struct gfs2_glock *gl)
86 if (!ip || !S_ISREG(inode->i_mode)) 86 if (!ip || !S_ISREG(inode->i_mode))
87 return; 87 return;
88 88
89 if (!test_bit(GIF_PAGED, &ip->i_flags))
90 return;
91
92 unmap_shared_mapping_range(inode->i_mapping, 0, 0); 89 unmap_shared_mapping_range(inode->i_mapping, 0, 0);
93
94 if (test_bit(GIF_SW_PAGED, &ip->i_flags)) 90 if (test_bit(GIF_SW_PAGED, &ip->i_flags))
95 set_bit(GLF_DIRTY, &gl->gl_flags); 91 set_bit(GLF_DIRTY, &gl->gl_flags);
96 92
97 clear_bit(GIF_SW_PAGED, &ip->i_flags);
98} 93}
99 94
100/** 95/**
@@ -234,10 +229,8 @@ static void inode_go_inval(struct gfs2_glock *gl, int flags)
234 set_bit(GIF_INVALID, &ip->i_flags); 229 set_bit(GIF_INVALID, &ip->i_flags);
235 } 230 }
236 231
237 if (ip && S_ISREG(ip->i_inode.i_mode)) { 232 if (ip && S_ISREG(ip->i_inode.i_mode))
238 truncate_inode_pages(ip->i_inode.i_mapping, 0); 233 truncate_inode_pages(ip->i_inode.i_mapping, 0);
239 clear_bit(GIF_PAGED, &ip->i_flags);
240 }
241} 234}
242 235
243/** 236/**
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index 662182bfbff7..55c72f01cf31 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -241,7 +241,6 @@ struct gfs2_alloc {
241enum { 241enum {
242 GIF_INVALID = 0, 242 GIF_INVALID = 0,
243 GIF_QD_LOCKED = 1, 243 GIF_QD_LOCKED = 1,
244 GIF_PAGED = 2,
245 GIF_SW_PAGED = 3, 244 GIF_SW_PAGED = 3,
246}; 245};
247 246
@@ -289,19 +288,12 @@ static inline struct gfs2_inode *GFS2_I(struct inode *inode)
289 return container_of(inode, struct gfs2_inode, i_inode); 288 return container_of(inode, struct gfs2_inode, i_inode);
290} 289}
291 290
292/* To be removed? */
293static inline struct gfs2_sbd *GFS2_SB(struct inode *inode) 291static inline struct gfs2_sbd *GFS2_SB(struct inode *inode)
294{ 292{
295 return inode->i_sb->s_fs_info; 293 return inode->i_sb->s_fs_info;
296} 294}
297 295
298enum {
299 GFF_DID_DIRECT_ALLOC = 0,
300 GFF_EXLOCK = 1,
301};
302
303struct gfs2_file { 296struct gfs2_file {
304 unsigned long f_flags; /* GFF_... */
305 struct mutex f_fl_mutex; 297 struct mutex f_fl_mutex;
306 struct gfs2_holder f_fl_gh; 298 struct gfs2_holder f_fl_gh;
307}; 299};
diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c
index 9bb24b1d9c05..1696e5d9d112 100644
--- a/fs/gfs2/ops_address.c
+++ b/fs/gfs2/ops_address.c
@@ -265,9 +265,7 @@ static int __gfs2_readpage(void *file, struct page *page)
265 * @file: The file to read 265 * @file: The file to read
266 * @page: The page of the file 266 * @page: The page of the file
267 * 267 *
268 * This deals with the locking required. If the GFF_EXLOCK flags is set 268 * This deals with the locking required. We use a trylock in order to
269 * then we already hold the glock (due to page fault) and thus we call
270 * __gfs2_readpage() directly. Otherwise we use a trylock in order to
271 * avoid the page lock / glock ordering problems returning AOP_TRUNCATED_PAGE 269 * avoid the page lock / glock ordering problems returning AOP_TRUNCATED_PAGE
272 * in the event that we are unable to get the lock. 270 * in the event that we are unable to get the lock.
273 */ 271 */
@@ -278,12 +276,6 @@ static int gfs2_readpage(struct file *file, struct page *page)
278 struct gfs2_holder gh; 276 struct gfs2_holder gh;
279 int error; 277 int error;
280 278
281 if (file) {
282 struct gfs2_file *gf = file->private_data;
283 if (test_bit(GFF_EXLOCK, &gf->f_flags))
284 return __gfs2_readpage(file, page);
285 }
286
287 gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME|LM_FLAG_TRY_1CB, &gh); 279 gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME|LM_FLAG_TRY_1CB, &gh);
288 error = gfs2_glock_nq_atime(&gh); 280 error = gfs2_glock_nq_atime(&gh);
289 if (unlikely(error)) { 281 if (unlikely(error)) {
@@ -354,9 +346,8 @@ int gfs2_internal_read(struct gfs2_inode *ip, struct file_ra_state *ra_state,
354 * 2. We don't handle stuffed files here we let readpage do the honours. 346 * 2. We don't handle stuffed files here we let readpage do the honours.
355 * 3. mpage_readpages() does most of the heavy lifting in the common case. 347 * 3. mpage_readpages() does most of the heavy lifting in the common case.
356 * 4. gfs2_get_block() is relied upon to set BH_Boundary in the right places. 348 * 4. gfs2_get_block() is relied upon to set BH_Boundary in the right places.
357 * 5. We use LM_FLAG_TRY_1CB here, effectively we then have lock-ahead as
358 * well as read-ahead.
359 */ 349 */
350
360static int gfs2_readpages(struct file *file, struct address_space *mapping, 351static int gfs2_readpages(struct file *file, struct address_space *mapping,
361 struct list_head *pages, unsigned nr_pages) 352 struct list_head *pages, unsigned nr_pages)
362{ 353{
@@ -364,40 +355,20 @@ static int gfs2_readpages(struct file *file, struct address_space *mapping,
364 struct gfs2_inode *ip = GFS2_I(inode); 355 struct gfs2_inode *ip = GFS2_I(inode);
365 struct gfs2_sbd *sdp = GFS2_SB(inode); 356 struct gfs2_sbd *sdp = GFS2_SB(inode);
366 struct gfs2_holder gh; 357 struct gfs2_holder gh;
367 int ret = 0; 358 int ret;
368 int do_unlock = 0;
369 359
370 if (file) { 360 gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &gh);
371 struct gfs2_file *gf = file->private_data;
372 if (test_bit(GFF_EXLOCK, &gf->f_flags))
373 goto skip_lock;
374 }
375 gfs2_holder_init(ip->i_gl, LM_ST_SHARED,
376 LM_FLAG_TRY_1CB|GL_ATIME, &gh);
377 do_unlock = 1;
378 ret = gfs2_glock_nq_atime(&gh); 361 ret = gfs2_glock_nq_atime(&gh);
379 if (ret == GLR_TRYFAILED)
380 goto out_noerror;
381 if (unlikely(ret)) 362 if (unlikely(ret))
382 goto out_unlock; 363 goto out_uninit;
383skip_lock:
384 if (!gfs2_is_stuffed(ip)) 364 if (!gfs2_is_stuffed(ip))
385 ret = mpage_readpages(mapping, pages, nr_pages, gfs2_get_block); 365 ret = mpage_readpages(mapping, pages, nr_pages, gfs2_get_block);
386 366 gfs2_glock_dq(&gh);
387 if (do_unlock) { 367out_uninit:
388 gfs2_glock_dq_m(1, &gh); 368 gfs2_holder_uninit(&gh);
389 gfs2_holder_uninit(&gh);
390 }
391out:
392 if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) 369 if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
393 ret = -EIO; 370 ret = -EIO;
394 return ret; 371 return ret;
395out_noerror:
396 ret = 0;
397out_unlock:
398 if (do_unlock)
399 gfs2_holder_uninit(&gh);
400 goto out;
401} 372}
402 373
403/** 374/**
diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c
index a729c86b8be1..6f3aeb059c61 100644
--- a/fs/gfs2/ops_file.c
+++ b/fs/gfs2/ops_file.c
@@ -33,7 +33,6 @@
33#include "lm.h" 33#include "lm.h"
34#include "log.h" 34#include "log.h"
35#include "meta_io.h" 35#include "meta_io.h"
36#include "ops_vm.h"
37#include "quota.h" 36#include "quota.h"
38#include "rgrp.h" 37#include "rgrp.h"
39#include "trans.h" 38#include "trans.h"
@@ -169,7 +168,7 @@ static int gfs2_get_flags(struct file *filp, u32 __user *ptr)
169 if (put_user(fsflags, ptr)) 168 if (put_user(fsflags, ptr))
170 error = -EFAULT; 169 error = -EFAULT;
171 170
172 gfs2_glock_dq_m(1, &gh); 171 gfs2_glock_dq(&gh);
173 gfs2_holder_uninit(&gh); 172 gfs2_holder_uninit(&gh);
174 return error; 173 return error;
175} 174}
@@ -293,6 +292,125 @@ static long gfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
293 return -ENOTTY; 292 return -ENOTTY;
294} 293}
295 294
295/**
296 * gfs2_allocate_page_backing - Use bmap to allocate blocks
297 * @page: The (locked) page to allocate backing for
298 *
299 * We try to allocate all the blocks required for the page in
300 * one go. This might fail for various reasons, so we keep
301 * trying until all the blocks to back this page are allocated.
302 * If some of the blocks are already allocated, thats ok too.
303 */
304
305static int gfs2_allocate_page_backing(struct page *page)
306{
307 struct inode *inode = page->mapping->host;
308 struct buffer_head bh;
309 unsigned long size = PAGE_CACHE_SIZE;
310 u64 lblock = page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits);
311
312 do {
313 bh.b_state = 0;
314 bh.b_size = size;
315 gfs2_block_map(inode, lblock, 1, &bh);
316 if (!buffer_mapped(&bh))
317 return -EIO;
318 size -= bh.b_size;
319 lblock += (bh.b_size >> inode->i_blkbits);
320 } while(size > 0);
321 return 0;
322}
323
324/**
325 * gfs2_page_mkwrite - Make a shared, mmap()ed, page writable
326 * @vma: The virtual memory area
327 * @page: The page which is about to become writable
328 *
329 * When the page becomes writable, we need to ensure that we have
330 * blocks allocated on disk to back that page.
331 */
332
333static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct page *page)
334{
335 struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
336 struct gfs2_inode *ip = GFS2_I(inode);
337 struct gfs2_sbd *sdp = GFS2_SB(inode);
338 unsigned long last_index;
339 u64 pos = page->index << (PAGE_CACHE_SIZE - inode->i_blkbits);
340 unsigned int data_blocks, ind_blocks, rblocks;
341 int alloc_required = 0;
342 struct gfs2_holder gh;
343 struct gfs2_alloc *al;
344 int ret;
345
346 gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_ATIME, &gh);
347 ret = gfs2_glock_nq_atime(&gh);
348 if (ret)
349 goto out;
350
351 set_bit(GIF_SW_PAGED, &ip->i_flags);
352 gfs2_write_calc_reserv(ip, PAGE_CACHE_SIZE, &data_blocks, &ind_blocks);
353 ret = gfs2_write_alloc_required(ip, pos, PAGE_CACHE_SIZE, &alloc_required);
354 if (ret || !alloc_required)
355 goto out_unlock;
356
357 ip->i_alloc.al_requested = 0;
358 al = gfs2_alloc_get(ip);
359 ret = gfs2_quota_lock(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
360 if (ret)
361 goto out_alloc_put;
362 ret = gfs2_quota_check(ip, ip->i_inode.i_uid, ip->i_inode.i_gid);
363 if (ret)
364 goto out_quota_unlock;
365 al->al_requested = data_blocks + ind_blocks;
366 ret = gfs2_inplace_reserve(ip);
367 if (ret)
368 goto out_quota_unlock;
369
370 rblocks = RES_DINODE + ind_blocks;
371 if (gfs2_is_jdata(ip))
372 rblocks += data_blocks ? data_blocks : 1;
373 if (ind_blocks || data_blocks)
374 rblocks += RES_STATFS + RES_QUOTA;
375 ret = gfs2_trans_begin(sdp, rblocks, 0);
376 if (ret)
377 goto out_trans_fail;
378
379 lock_page(page);
380 ret = -EINVAL;
381 last_index = ip->i_inode.i_size >> PAGE_CACHE_SHIFT;
382 if (page->index > last_index)
383 goto out_unlock_page;
384 if (!PageUptodate(page) || page->mapping != ip->i_inode.i_mapping)
385 goto out_unlock_page;
386 if (gfs2_is_stuffed(ip)) {
387 ret = gfs2_unstuff_dinode(ip, page);
388 if (ret)
389 goto out_unlock_page;
390 }
391 ret = gfs2_allocate_page_backing(page);
392
393out_unlock_page:
394 unlock_page(page);
395 gfs2_trans_end(sdp);
396out_trans_fail:
397 gfs2_inplace_release(ip);
398out_quota_unlock:
399 gfs2_quota_unlock(ip);
400out_alloc_put:
401 gfs2_alloc_put(ip);
402out_unlock:
403 gfs2_glock_dq(&gh);
404out:
405 gfs2_holder_uninit(&gh);
406 return ret;
407}
408
409static struct vm_operations_struct gfs2_vm_ops = {
410 .fault = filemap_fault,
411 .page_mkwrite = gfs2_page_mkwrite,
412};
413
296 414
297/** 415/**
298 * gfs2_mmap - 416 * gfs2_mmap -
@@ -315,14 +433,7 @@ static int gfs2_mmap(struct file *file, struct vm_area_struct *vma)
315 return error; 433 return error;
316 } 434 }
317 435
318 /* This is VM_MAYWRITE instead of VM_WRITE because a call 436 vma->vm_ops = &gfs2_vm_ops;
319 to mprotect() can turn on VM_WRITE later. */
320
321 if ((vma->vm_flags & (VM_MAYSHARE | VM_MAYWRITE)) ==
322 (VM_MAYSHARE | VM_MAYWRITE))
323 vma->vm_ops = &gfs2_vm_ops_sharewrite;
324 else
325 vma->vm_ops = &gfs2_vm_ops_private;
326 437
327 gfs2_glock_dq_uninit(&i_gh); 438 gfs2_glock_dq_uninit(&i_gh);
328 439
diff --git a/fs/gfs2/ops_vm.c b/fs/gfs2/ops_vm.c
deleted file mode 100644
index 927d739d4685..000000000000
--- a/fs/gfs2/ops_vm.c
+++ /dev/null
@@ -1,169 +0,0 @@
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 version 2.
8 */
9
10#include <linux/slab.h>
11#include <linux/spinlock.h>
12#include <linux/completion.h>
13#include <linux/buffer_head.h>
14#include <linux/mm.h>
15#include <linux/pagemap.h>
16#include <linux/gfs2_ondisk.h>
17#include <linux/lm_interface.h>
18
19#include "gfs2.h"
20#include "incore.h"
21#include "bmap.h"
22#include "glock.h"
23#include "inode.h"
24#include "ops_vm.h"
25#include "quota.h"
26#include "rgrp.h"
27#include "trans.h"
28#include "util.h"
29
30static int gfs2_private_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
31{
32 struct gfs2_inode *ip = GFS2_I(vma->vm_file->f_mapping->host);
33
34 set_bit(GIF_PAGED, &ip->i_flags);
35 return filemap_fault(vma, vmf);
36}
37
38static int alloc_page_backing(struct gfs2_inode *ip, struct page *page)
39{
40 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
41 unsigned long index = page->index;
42 u64 lblock = index << (PAGE_CACHE_SHIFT -
43 sdp->sd_sb.sb_bsize_shift);
44 unsigned int blocks = PAGE_CACHE_SIZE >> sdp->sd_sb.sb_bsize_shift;
45 struct gfs2_alloc *al;
46 unsigned int data_blocks, ind_blocks;
47 unsigned int x;
48 int error;
49
50 al = gfs2_alloc_get(ip);
51
52 error = gfs2_quota_lock(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
53 if (error)
54 goto out;
55
56 error = gfs2_quota_check(ip, ip->i_inode.i_uid, ip->i_inode.i_gid);
57 if (error)
58 goto out_gunlock_q;
59
60 gfs2_write_calc_reserv(ip, PAGE_CACHE_SIZE, &data_blocks, &ind_blocks);
61
62 al->al_requested = data_blocks + ind_blocks;
63
64 error = gfs2_inplace_reserve(ip);
65 if (error)
66 goto out_gunlock_q;
67
68 error = gfs2_trans_begin(sdp, al->al_rgd->rd_length +
69 ind_blocks + RES_DINODE +
70 RES_STATFS + RES_QUOTA, 0);
71 if (error)
72 goto out_ipres;
73
74 if (gfs2_is_stuffed(ip)) {
75 error = gfs2_unstuff_dinode(ip, NULL);
76 if (error)
77 goto out_trans;
78 }
79
80 for (x = 0; x < blocks; ) {
81 u64 dblock;
82 unsigned int extlen;
83 int new = 1;
84
85 error = gfs2_extent_map(&ip->i_inode, lblock, &new, &dblock, &extlen);
86 if (error)
87 goto out_trans;
88
89 lblock += extlen;
90 x += extlen;
91 }
92
93 gfs2_assert_warn(sdp, al->al_alloced);
94
95out_trans:
96 gfs2_trans_end(sdp);
97out_ipres:
98 gfs2_inplace_release(ip);
99out_gunlock_q:
100 gfs2_quota_unlock(ip);
101out:
102 gfs2_alloc_put(ip);
103 return error;
104}
105
106static int gfs2_sharewrite_fault(struct vm_area_struct *vma,
107 struct vm_fault *vmf)
108{
109 struct file *file = vma->vm_file;
110 struct gfs2_file *gf = file->private_data;
111 struct gfs2_inode *ip = GFS2_I(file->f_mapping->host);
112 struct gfs2_holder i_gh;
113 int alloc_required;
114 int error;
115 int ret = 0;
116
117 error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &i_gh);
118 if (error)
119 goto out;
120
121 set_bit(GIF_PAGED, &ip->i_flags);
122 set_bit(GIF_SW_PAGED, &ip->i_flags);
123
124 error = gfs2_write_alloc_required(ip,
125 (u64)vmf->pgoff << PAGE_CACHE_SHIFT,
126 PAGE_CACHE_SIZE, &alloc_required);
127 if (error) {
128 ret = VM_FAULT_OOM; /* XXX: are these right? */
129 goto out_unlock;
130 }
131
132 set_bit(GFF_EXLOCK, &gf->f_flags);
133 ret = filemap_fault(vma, vmf);
134 clear_bit(GFF_EXLOCK, &gf->f_flags);
135 if (ret & VM_FAULT_ERROR)
136 goto out_unlock;
137
138 if (alloc_required) {
139 /* XXX: do we need to drop page lock around alloc_page_backing?*/
140 error = alloc_page_backing(ip, vmf->page);
141 if (error) {
142 /*
143 * VM_FAULT_LOCKED should always be the case for
144 * filemap_fault, but it may not be in a future
145 * implementation.
146 */
147 if (ret & VM_FAULT_LOCKED)
148 unlock_page(vmf->page);
149 page_cache_release(vmf->page);
150 ret = VM_FAULT_OOM;
151 goto out_unlock;
152 }
153 set_page_dirty(vmf->page);
154 }
155
156out_unlock:
157 gfs2_glock_dq_uninit(&i_gh);
158out:
159 return ret;
160}
161
162struct vm_operations_struct gfs2_vm_ops_private = {
163 .fault = gfs2_private_fault,
164};
165
166struct vm_operations_struct gfs2_vm_ops_sharewrite = {
167 .fault = gfs2_sharewrite_fault,
168};
169
diff --git a/fs/gfs2/ops_vm.h b/fs/gfs2/ops_vm.h
deleted file mode 100644
index 4ae8f43ed5e3..000000000000
--- a/fs/gfs2/ops_vm.h
+++ /dev/null
@@ -1,18 +0,0 @@
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 version 2.
8 */
9
10#ifndef __OPS_VM_DOT_H__
11#define __OPS_VM_DOT_H__
12
13#include <linux/mm.h>
14
15extern struct vm_operations_struct gfs2_vm_ops_private;
16extern struct vm_operations_struct gfs2_vm_ops_sharewrite;
17
18#endif /* __OPS_VM_DOT_H__ */