diff options
author | Steven Whitehouse <swhiteho@redhat.com> | 2007-09-28 08:49:05 -0400 |
---|---|---|
committer | Steven Whitehouse <swhiteho@redhat.com> | 2008-01-25 03:07:25 -0500 |
commit | 9ff8ec32e58875022447af619bec6e5aee7c77e4 (patch) | |
tree | 0c626762f334d1cc066113b3e47a2fa02a72af0c /fs/gfs2/ops_address.c | |
parent | 5561093e2cac9f7d2a77e39cc689b8d2b7f9b2bc (diff) |
[GFS2] Split gfs2_writepage into three cases
This patch splits gfs2_writepage into separate functions for each of
the three cases: writeback, ordered and journalled. As a result
it becomes a lot easier to see what each one is doing. The common
code is moved into gfs2_writepage_common.
This fixes a performance bug where we were doing more work than
strictly required in the ordered write case.
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/ops_address.c')
-rw-r--r-- | fs/gfs2/ops_address.c | 112 |
1 files changed, 91 insertions, 21 deletions
diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c index 207014f363d8..4bf73ed945ae 100644 --- a/fs/gfs2/ops_address.c +++ b/fs/gfs2/ops_address.c | |||
@@ -103,16 +103,15 @@ static int gfs2_get_block_direct(struct inode *inode, sector_t lblock, | |||
103 | } | 103 | } |
104 | 104 | ||
105 | /** | 105 | /** |
106 | * gfs2_writepage - Write complete page | 106 | * gfs2_writepage_common - Common bits of writepage |
107 | * @page: Page to write | 107 | * @page: The page to be written |
108 | * | 108 | * @wbc: The writeback control |
109 | * Returns: errno | ||
110 | * | 109 | * |
111 | * Some of this is copied from block_write_full_page() although we still | 110 | * Returns: 1 if writepage is ok, otherwise an error code or zero if no error. |
112 | * call it to do most of the work. | ||
113 | */ | 111 | */ |
114 | 112 | ||
115 | static int gfs2_writepage(struct page *page, struct writeback_control *wbc) | 113 | static int gfs2_writepage_common(struct page *page, |
114 | struct writeback_control *wbc) | ||
116 | { | 115 | { |
117 | struct inode *inode = page->mapping->host; | 116 | struct inode *inode = page->mapping->host; |
118 | struct gfs2_inode *ip = GFS2_I(inode); | 117 | struct gfs2_inode *ip = GFS2_I(inode); |
@@ -120,23 +119,94 @@ static int gfs2_writepage(struct page *page, struct writeback_control *wbc) | |||
120 | loff_t i_size = i_size_read(inode); | 119 | loff_t i_size = i_size_read(inode); |
121 | pgoff_t end_index = i_size >> PAGE_CACHE_SHIFT; | 120 | pgoff_t end_index = i_size >> PAGE_CACHE_SHIFT; |
122 | unsigned offset; | 121 | unsigned offset; |
123 | int error; | 122 | int ret = -EIO; |
124 | int done_trans = 0; | ||
125 | 123 | ||
126 | if (gfs2_assert_withdraw(sdp, gfs2_glock_is_held_excl(ip->i_gl))) { | 124 | if (gfs2_assert_withdraw(sdp, gfs2_glock_is_held_excl(ip->i_gl))) |
127 | unlock_page(page); | 125 | goto out; |
128 | return -EIO; | 126 | ret = 0; |
129 | } | ||
130 | if (current->journal_info) | 127 | if (current->journal_info) |
131 | goto out_ignore; | 128 | goto redirty; |
132 | |||
133 | /* Is the page fully outside i_size? (truncate in progress) */ | 129 | /* Is the page fully outside i_size? (truncate in progress) */ |
134 | offset = i_size & (PAGE_CACHE_SIZE-1); | 130 | offset = i_size & (PAGE_CACHE_SIZE-1); |
135 | if (page->index > end_index || (page->index == end_index && !offset)) { | 131 | if (page->index > end_index || (page->index == end_index && !offset)) { |
136 | page->mapping->a_ops->invalidatepage(page, 0); | 132 | page->mapping->a_ops->invalidatepage(page, 0); |
137 | unlock_page(page); | 133 | goto out; |
138 | return 0; /* don't care */ | ||
139 | } | 134 | } |
135 | return 1; | ||
136 | redirty: | ||
137 | redirty_page_for_writepage(wbc, page); | ||
138 | out: | ||
139 | unlock_page(page); | ||
140 | return 0; | ||
141 | } | ||
142 | |||
143 | /** | ||
144 | * gfs2_writeback_writepage - Write page for writeback mappings | ||
145 | * @page: The page | ||
146 | * @wbc: The writeback control | ||
147 | * | ||
148 | */ | ||
149 | |||
150 | static int gfs2_writeback_writepage(struct page *page, | ||
151 | struct writeback_control *wbc) | ||
152 | { | ||
153 | int ret; | ||
154 | |||
155 | ret = gfs2_writepage_common(page, wbc); | ||
156 | if (ret <= 0) | ||
157 | return ret; | ||
158 | |||
159 | ret = mpage_writepage(page, gfs2_get_block_noalloc, wbc); | ||
160 | if (ret == -EAGAIN) | ||
161 | ret = block_write_full_page(page, gfs2_get_block_noalloc, wbc); | ||
162 | return ret; | ||
163 | } | ||
164 | |||
165 | /** | ||
166 | * gfs2_ordered_writepage - Write page for ordered data files | ||
167 | * @page: The page to write | ||
168 | * @wbc: The writeback control | ||
169 | * | ||
170 | */ | ||
171 | |||
172 | static int gfs2_ordered_writepage(struct page *page, | ||
173 | struct writeback_control *wbc) | ||
174 | { | ||
175 | struct inode *inode = page->mapping->host; | ||
176 | struct gfs2_inode *ip = GFS2_I(inode); | ||
177 | int ret; | ||
178 | |||
179 | ret = gfs2_writepage_common(page, wbc); | ||
180 | if (ret <= 0) | ||
181 | return ret; | ||
182 | |||
183 | if (!page_has_buffers(page)) { | ||
184 | create_empty_buffers(page, inode->i_sb->s_blocksize, | ||
185 | (1 << BH_Dirty)|(1 << BH_Uptodate)); | ||
186 | } | ||
187 | gfs2_page_add_databufs(ip, page, 0, inode->i_sb->s_blocksize-1); | ||
188 | return block_write_full_page(page, gfs2_get_block_noalloc, wbc); | ||
189 | } | ||
190 | |||
191 | /** | ||
192 | * gfs2_jdata_writepage - Write complete page | ||
193 | * @page: Page to write | ||
194 | * | ||
195 | * Returns: errno | ||
196 | * | ||
197 | */ | ||
198 | |||
199 | static int gfs2_jdata_writepage(struct page *page, struct writeback_control *wbc) | ||
200 | { | ||
201 | struct inode *inode = page->mapping->host; | ||
202 | struct gfs2_inode *ip = GFS2_I(inode); | ||
203 | struct gfs2_sbd *sdp = GFS2_SB(inode); | ||
204 | int error; | ||
205 | int done_trans = 0; | ||
206 | |||
207 | error = gfs2_writepage_common(page, wbc); | ||
208 | if (error <= 0) | ||
209 | return error; | ||
140 | 210 | ||
141 | if (PageChecked(page)) { | 211 | if (PageChecked(page)) { |
142 | error = gfs2_trans_begin(sdp, RES_DINODE + 1, 0); | 212 | error = gfs2_trans_begin(sdp, RES_DINODE + 1, 0); |
@@ -838,7 +908,7 @@ cannot_release: | |||
838 | } | 908 | } |
839 | 909 | ||
840 | static const struct address_space_operations gfs2_writeback_aops = { | 910 | static const struct address_space_operations gfs2_writeback_aops = { |
841 | .writepage = gfs2_writepage, | 911 | .writepage = gfs2_writeback_writepage, |
842 | .writepages = gfs2_writeback_writepages, | 912 | .writepages = gfs2_writeback_writepages, |
843 | .readpage = gfs2_readpage, | 913 | .readpage = gfs2_readpage, |
844 | .readpages = gfs2_readpages, | 914 | .readpages = gfs2_readpages, |
@@ -852,7 +922,7 @@ static const struct address_space_operations gfs2_writeback_aops = { | |||
852 | }; | 922 | }; |
853 | 923 | ||
854 | static const struct address_space_operations gfs2_ordered_aops = { | 924 | static const struct address_space_operations gfs2_ordered_aops = { |
855 | .writepage = gfs2_writepage, | 925 | .writepage = gfs2_ordered_writepage, |
856 | .readpage = gfs2_readpage, | 926 | .readpage = gfs2_readpage, |
857 | .readpages = gfs2_readpages, | 927 | .readpages = gfs2_readpages, |
858 | .sync_page = block_sync_page, | 928 | .sync_page = block_sync_page, |
@@ -866,7 +936,7 @@ static const struct address_space_operations gfs2_ordered_aops = { | |||
866 | }; | 936 | }; |
867 | 937 | ||
868 | static const struct address_space_operations gfs2_jdata_aops = { | 938 | static const struct address_space_operations gfs2_jdata_aops = { |
869 | .writepage = gfs2_writepage, | 939 | .writepage = gfs2_jdata_writepage, |
870 | .readpage = gfs2_readpage, | 940 | .readpage = gfs2_readpage, |
871 | .readpages = gfs2_readpages, | 941 | .readpages = gfs2_readpages, |
872 | .sync_page = block_sync_page, | 942 | .sync_page = block_sync_page, |