diff options
Diffstat (limited to 'fs/gfs2/lops.c')
-rw-r--r-- | fs/gfs2/lops.c | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c index 0301be655b12..8e323c4b7983 100644 --- a/fs/gfs2/lops.c +++ b/fs/gfs2/lops.c | |||
@@ -143,6 +143,98 @@ static inline __be64 *bh_ptr_end(struct buffer_head *bh) | |||
143 | return (__force __be64 *)(bh->b_data + bh->b_size); | 143 | return (__force __be64 *)(bh->b_data + bh->b_size); |
144 | } | 144 | } |
145 | 145 | ||
146 | /** | ||
147 | * gfs2_log_write_endio - End of I/O for a log buffer | ||
148 | * @bh: The buffer head | ||
149 | * @uptodate: I/O Status | ||
150 | * | ||
151 | */ | ||
152 | |||
153 | static void gfs2_log_write_endio(struct buffer_head *bh, int uptodate) | ||
154 | { | ||
155 | struct gfs2_sbd *sdp = bh->b_private; | ||
156 | bh->b_private = NULL; | ||
157 | |||
158 | end_buffer_write_sync(bh, uptodate); | ||
159 | if (atomic_dec_and_test(&sdp->sd_log_in_flight)) | ||
160 | wake_up(&sdp->sd_log_flush_wait); | ||
161 | } | ||
162 | |||
163 | /** | ||
164 | * gfs2_log_get_buf - Get and initialize a buffer to use for log control data | ||
165 | * @sdp: The GFS2 superblock | ||
166 | * | ||
167 | * tReturns: the buffer_head | ||
168 | */ | ||
169 | |||
170 | static struct buffer_head *gfs2_log_get_buf(struct gfs2_sbd *sdp) | ||
171 | { | ||
172 | u64 blkno = gfs2_log_bmap(sdp, sdp->sd_log_flush_head); | ||
173 | struct buffer_head *bh; | ||
174 | |||
175 | bh = sb_getblk(sdp->sd_vfs, blkno); | ||
176 | lock_buffer(bh); | ||
177 | memset(bh->b_data, 0, bh->b_size); | ||
178 | set_buffer_uptodate(bh); | ||
179 | clear_buffer_dirty(bh); | ||
180 | gfs2_log_incr_head(sdp); | ||
181 | atomic_inc(&sdp->sd_log_in_flight); | ||
182 | bh->b_private = sdp; | ||
183 | bh->b_end_io = gfs2_log_write_endio; | ||
184 | |||
185 | return bh; | ||
186 | } | ||
187 | |||
188 | /** | ||
189 | * gfs2_fake_write_endio - | ||
190 | * @bh: The buffer head | ||
191 | * @uptodate: The I/O Status | ||
192 | * | ||
193 | */ | ||
194 | |||
195 | static void gfs2_fake_write_endio(struct buffer_head *bh, int uptodate) | ||
196 | { | ||
197 | struct buffer_head *real_bh = bh->b_private; | ||
198 | struct gfs2_bufdata *bd = real_bh->b_private; | ||
199 | struct gfs2_sbd *sdp = bd->bd_gl->gl_sbd; | ||
200 | |||
201 | end_buffer_write_sync(bh, uptodate); | ||
202 | free_buffer_head(bh); | ||
203 | unlock_buffer(real_bh); | ||
204 | brelse(real_bh); | ||
205 | if (atomic_dec_and_test(&sdp->sd_log_in_flight)) | ||
206 | wake_up(&sdp->sd_log_flush_wait); | ||
207 | } | ||
208 | |||
209 | /** | ||
210 | * gfs2_log_fake_buf - Build a fake buffer head to write metadata buffer to log | ||
211 | * @sdp: the filesystem | ||
212 | * @data: the data the buffer_head should point to | ||
213 | * | ||
214 | * Returns: the log buffer descriptor | ||
215 | */ | ||
216 | |||
217 | static struct buffer_head *gfs2_log_fake_buf(struct gfs2_sbd *sdp, | ||
218 | struct buffer_head *real) | ||
219 | { | ||
220 | u64 blkno = gfs2_log_bmap(sdp, sdp->sd_log_flush_head); | ||
221 | struct buffer_head *bh; | ||
222 | |||
223 | bh = alloc_buffer_head(GFP_NOFS | __GFP_NOFAIL); | ||
224 | atomic_set(&bh->b_count, 1); | ||
225 | bh->b_state = (1 << BH_Mapped) | (1 << BH_Uptodate) | (1 << BH_Lock); | ||
226 | set_bh_page(bh, real->b_page, bh_offset(real)); | ||
227 | bh->b_blocknr = blkno; | ||
228 | bh->b_size = sdp->sd_sb.sb_bsize; | ||
229 | bh->b_bdev = sdp->sd_vfs->s_bdev; | ||
230 | bh->b_private = real; | ||
231 | bh->b_end_io = gfs2_fake_write_endio; | ||
232 | |||
233 | gfs2_log_incr_head(sdp); | ||
234 | atomic_inc(&sdp->sd_log_in_flight); | ||
235 | |||
236 | return bh; | ||
237 | } | ||
146 | 238 | ||
147 | static struct buffer_head *gfs2_get_log_desc(struct gfs2_sbd *sdp, u32 ld_type) | 239 | static struct buffer_head *gfs2_get_log_desc(struct gfs2_sbd *sdp, u32 ld_type) |
148 | { | 240 | { |