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