aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/gfs2/Makefile2
-rw-r--r--fs/gfs2/bmap.c78
-rw-r--r--fs/gfs2/glops.c89
-rw-r--r--fs/gfs2/ops_address.c19
-rw-r--r--fs/gfs2/ops_inode.c1
-rw-r--r--fs/gfs2/ops_super.c1
-rw-r--r--fs/gfs2/ops_vm.c1
-rw-r--r--fs/gfs2/page.c207
-rw-r--r--fs/gfs2/page.h21
9 files changed, 184 insertions, 235 deletions
diff --git a/fs/gfs2/Makefile b/fs/gfs2/Makefile
index 0b7977623b80..b92852b66629 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 lvb.o main.o meta_io.o \ 3 glops.o inode.o lm.o log.o lops.o locking.o lvb.o main.o meta_io.o \
4 mount.o ondisk.o ops_address.o ops_dentry.o ops_export.o ops_file.o \ 4 mount.o ondisk.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 page.o quota.o \ 5 ops_fstype.o ops_inode.o ops_super.o ops_vm.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/bmap.c b/fs/gfs2/bmap.c
index 72b19c5d7807..d20d41e1c028 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -22,12 +22,12 @@
22#include "glock.h" 22#include "glock.h"
23#include "inode.h" 23#include "inode.h"
24#include "meta_io.h" 24#include "meta_io.h"
25#include "page.h"
26#include "quota.h" 25#include "quota.h"
27#include "rgrp.h" 26#include "rgrp.h"
28#include "trans.h" 27#include "trans.h"
29#include "dir.h" 28#include "dir.h"
30#include "util.h" 29#include "util.h"
30#include "ops_address.h"
31 31
32/* This doesn't need to be that large as max 64 bit pointers in a 4k 32/* This doesn't need to be that large as max 64 bit pointers in a 4k
33 * block is 512, so __u16 is fine for that. It saves stack space to 33 * block is 512, so __u16 is fine for that. It saves stack space to
@@ -885,6 +885,82 @@ static int do_grow(struct gfs2_inode *ip, uint64_t size)
885 return error; 885 return error;
886} 886}
887 887
888
889/**
890 * gfs2_block_truncate_page - Deal with zeroing out data for truncate
891 *
892 * This is partly borrowed from ext3.
893 */
894static int gfs2_block_truncate_page(struct address_space *mapping)
895{
896 struct inode *inode = mapping->host;
897 struct gfs2_inode *ip = GFS2_I(inode);
898 struct gfs2_sbd *sdp = GFS2_SB(inode);
899 loff_t from = inode->i_size;
900 unsigned long index = from >> PAGE_CACHE_SHIFT;
901 unsigned offset = from & (PAGE_CACHE_SIZE-1);
902 unsigned blocksize, iblock, length, pos;
903 struct buffer_head *bh;
904 struct page *page;
905 void *kaddr;
906 int err;
907
908 page = grab_cache_page(mapping, index);
909 if (!page)
910 return 0;
911
912 blocksize = inode->i_sb->s_blocksize;
913 length = blocksize - (offset & (blocksize - 1));
914 iblock = index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits);
915
916 if (!page_has_buffers(page))
917 create_empty_buffers(page, blocksize, 0);
918
919 /* Find the buffer that contains "offset" */
920 bh = page_buffers(page);
921 pos = blocksize;
922 while (offset >= pos) {
923 bh = bh->b_this_page;
924 iblock++;
925 pos += blocksize;
926 }
927
928 err = 0;
929
930 if (!buffer_mapped(bh)) {
931 gfs2_get_block(inode, iblock, bh, 0);
932 /* unmapped? It's a hole - nothing to do */
933 if (!buffer_mapped(bh))
934 goto unlock;
935 }
936
937 /* Ok, it's mapped. Make sure it's up-to-date */
938 if (PageUptodate(page))
939 set_buffer_uptodate(bh);
940
941 if (!buffer_uptodate(bh)) {
942 err = -EIO;
943 ll_rw_block(READ, 1, &bh);
944 wait_on_buffer(bh);
945 /* Uhhuh. Read error. Complain and punt. */
946 if (!buffer_uptodate(bh))
947 goto unlock;
948 }
949
950 if (sdp->sd_args.ar_data == GFS2_DATA_ORDERED || gfs2_is_jdata(ip))
951 gfs2_trans_add_bh(ip->i_gl, bh, 0);
952
953 kaddr = kmap_atomic(page, KM_USER0);
954 memset(kaddr + offset, 0, length);
955 flush_dcache_page(page);
956 kunmap_atomic(kaddr, KM_USER0);
957
958unlock:
959 unlock_page(page);
960 page_cache_release(page);
961 return err;
962}
963
888static int trunc_start(struct gfs2_inode *ip, uint64_t size) 964static int trunc_start(struct gfs2_inode *ip, uint64_t size)
889{ 965{
890 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); 966 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index a01874c58834..3f909a81a071 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -23,11 +23,98 @@
23#include "inode.h" 23#include "inode.h"
24#include "log.h" 24#include "log.h"
25#include "meta_io.h" 25#include "meta_io.h"
26#include "page.h"
27#include "recovery.h" 26#include "recovery.h"
28#include "rgrp.h" 27#include "rgrp.h"
29#include "util.h" 28#include "util.h"
30 29
30
31/**
32 * gfs2_pte_inval - Sync and invalidate all PTEs associated with a glock
33 * @gl: the glock
34 *
35 */
36
37static void gfs2_pte_inval(struct gfs2_glock *gl)
38{
39 struct gfs2_inode *ip;
40 struct inode *inode;
41
42 ip = gl->gl_object;
43 inode = &ip->i_inode;
44 if (!ip || !S_ISREG(ip->i_di.di_mode))
45 return;
46
47 if (!test_bit(GIF_PAGED, &ip->i_flags))
48 return;
49
50 unmap_shared_mapping_range(inode->i_mapping, 0, 0);
51
52 if (test_bit(GIF_SW_PAGED, &ip->i_flags))
53 set_bit(GLF_DIRTY, &gl->gl_flags);
54
55 clear_bit(GIF_SW_PAGED, &ip->i_flags);
56}
57
58/**
59 * gfs2_page_inval - Invalidate all pages associated with a glock
60 * @gl: the glock
61 *
62 */
63
64static void gfs2_page_inval(struct gfs2_glock *gl)
65{
66 struct gfs2_inode *ip;
67 struct inode *inode;
68
69 ip = gl->gl_object;
70 inode = &ip->i_inode;
71 if (!ip || !S_ISREG(ip->i_di.di_mode))
72 return;
73
74 truncate_inode_pages(inode->i_mapping, 0);
75 gfs2_assert_withdraw(GFS2_SB(&ip->i_inode), !inode->i_mapping->nrpages);
76 clear_bit(GIF_PAGED, &ip->i_flags);
77}
78
79/**
80 * gfs2_page_sync - Sync the data pages (not metadata) associated with a glock
81 * @gl: the glock
82 * @flags: DIO_START | DIO_WAIT
83 *
84 * Syncs data (not metadata) for a regular file.
85 * No-op for all other types.
86 */
87
88static void gfs2_page_sync(struct gfs2_glock *gl, int flags)
89{
90 struct gfs2_inode *ip;
91 struct inode *inode;
92 struct address_space *mapping;
93 int error = 0;
94
95 ip = gl->gl_object;
96 inode = &ip->i_inode;
97 if (!ip || !S_ISREG(ip->i_di.di_mode))
98 return;
99
100 mapping = inode->i_mapping;
101
102 if (flags & DIO_START)
103 filemap_fdatawrite(mapping);
104 if (!error && (flags & DIO_WAIT))
105 error = filemap_fdatawait(mapping);
106
107 /* Put back any errors cleared by filemap_fdatawait()
108 so they can be caught by someone who can pass them
109 up to user space. */
110
111 if (error == -ENOSPC)
112 set_bit(AS_ENOSPC, &mapping->flags);
113 else if (error)
114 set_bit(AS_EIO, &mapping->flags);
115
116}
117
31/** 118/**
32 * meta_go_sync - sync out the metadata for this glock 119 * meta_go_sync - sync out the metadata for this glock
33 * @gl: the glock 120 * @gl: the glock
diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c
index 93e00a8af8cf..fca69f12e4de 100644
--- a/fs/gfs2/ops_address.c
+++ b/fs/gfs2/ops_address.c
@@ -27,7 +27,6 @@
27#include "log.h" 27#include "log.h"
28#include "meta_io.h" 28#include "meta_io.h"
29#include "ops_address.h" 29#include "ops_address.h"
30#include "page.h"
31#include "quota.h" 30#include "quota.h"
32#include "trans.h" 31#include "trans.h"
33#include "rgrp.h" 32#include "rgrp.h"
@@ -35,6 +34,24 @@
35#include "util.h" 34#include "util.h"
36#include "glops.h" 35#include "glops.h"
37 36
37
38static void gfs2_page_add_databufs(struct gfs2_inode *ip, struct page *page,
39 unsigned int from, unsigned int to)
40{
41 struct buffer_head *head = page_buffers(page);
42 unsigned int bsize = head->b_size;
43 struct buffer_head *bh;
44 unsigned int start, end;
45
46 for (bh = head, start = 0; bh != head || !start;
47 bh = bh->b_this_page, start = end) {
48 end = start + bsize;
49 if (end <= from || start >= to)
50 continue;
51 gfs2_trans_add_bh(ip->i_gl, bh, 0);
52 }
53}
54
38/** 55/**
39 * gfs2_get_block - Fills in a buffer head with details about a block 56 * gfs2_get_block - Fills in a buffer head with details about a block
40 * @inode: The inode 57 * @inode: The inode
diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c
index caecafe0469b..8fb7c5c9a7c3 100644
--- a/fs/gfs2/ops_inode.c
+++ b/fs/gfs2/ops_inode.c
@@ -34,7 +34,6 @@
34#include "meta_io.h" 34#include "meta_io.h"
35#include "ops_dentry.h" 35#include "ops_dentry.h"
36#include "ops_inode.h" 36#include "ops_inode.h"
37#include "page.h"
38#include "quota.h" 37#include "quota.h"
39#include "rgrp.h" 38#include "rgrp.h"
40#include "trans.h" 39#include "trans.h"
diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c
index 50ea7f21f9cf..730c7228f6ad 100644
--- a/fs/gfs2/ops_super.c
+++ b/fs/gfs2/ops_super.c
@@ -30,7 +30,6 @@
30#include "log.h" 30#include "log.h"
31#include "mount.h" 31#include "mount.h"
32#include "ops_super.h" 32#include "ops_super.h"
33#include "page.h"
34#include "quota.h" 33#include "quota.h"
35#include "recovery.h" 34#include "recovery.h"
36#include "rgrp.h" 35#include "rgrp.h"
diff --git a/fs/gfs2/ops_vm.c b/fs/gfs2/ops_vm.c
index 910722d4c483..aff66373b7e1 100644
--- a/fs/gfs2/ops_vm.c
+++ b/fs/gfs2/ops_vm.c
@@ -23,7 +23,6 @@
23#include "glock.h" 23#include "glock.h"
24#include "inode.h" 24#include "inode.h"
25#include "ops_vm.h" 25#include "ops_vm.h"
26#include "page.h"
27#include "quota.h" 26#include "quota.h"
28#include "rgrp.h" 27#include "rgrp.h"
29#include "trans.h" 28#include "trans.h"
diff --git a/fs/gfs2/page.c b/fs/gfs2/page.c
deleted file mode 100644
index 0d6befed1ae5..000000000000
--- a/fs/gfs2/page.c
+++ /dev/null
@@ -1,207 +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 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
35void 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
62void 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
86void 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 */
121int 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
185unlock:
186 unlock_page(page);
187 page_cache_release(page);
188 return err;
189}
190
191void 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
diff --git a/fs/gfs2/page.h b/fs/gfs2/page.h
deleted file mode 100644
index 67a4f4b79aa6..000000000000
--- a/fs/gfs2/page.h
+++ /dev/null
@@ -1,21 +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 v.2.
8 */
9
10#ifndef __PAGE_DOT_H__
11#define __PAGE_DOT_H__
12
13void gfs2_pte_inval(struct gfs2_glock *gl);
14void gfs2_page_inval(struct gfs2_glock *gl);
15void gfs2_page_sync(struct gfs2_glock *gl, int flags);
16
17int gfs2_block_truncate_page(struct address_space *mapping);
18void gfs2_page_add_databufs(struct gfs2_inode *ip, struct page *page,
19 unsigned int from, unsigned int to);
20
21#endif /* __PAGE_DOT_H__ */