blob: 16bb4b4561aed9d653a4f7b23746b70495e7718b [file] [log] [blame]
David Teiglandb3b94fa2006-01-16 16:50:04 +00001/*
2 * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
Steven Whitehouse3a8a9a12006-05-18 15:09:15 -04003 * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
David Teiglandb3b94fa2006-01-16 16:50:04 +00004 *
5 * This copyrighted material is made available to anyone wishing to use,
6 * modify, copy, or redistribute it subject to the terms and conditions
Steven Whitehousee9fc2aa2006-09-01 11:05:15 -04007 * of the GNU General Public License version 2.
David Teiglandb3b94fa2006-01-16 16:50:04 +00008 */
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>
Steven Whitehouse5c676f62006-02-27 17:23:27 -050015#include <linux/gfs2_ondisk.h>
Fabio Massimo Di Nitto7d308592006-09-19 07:56:29 +020016#include <linux/lm_interface.h>
David Teiglandb3b94fa2006-01-16 16:50:04 +000017
18#include "gfs2.h"
Steven Whitehouse5c676f62006-02-27 17:23:27 -050019#include "incore.h"
David Teiglandb3b94fa2006-01-16 16:50:04 +000020#include "glock.h"
21#include "log.h"
22#include "lops.h"
23#include "meta_io.h"
24#include "recovery.h"
25#include "rgrp.h"
26#include "trans.h"
Steven Whitehouse5c676f62006-02-27 17:23:27 -050027#include "util.h"
David Teiglandb3b94fa2006-01-16 16:50:04 +000028
29static void glock_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le)
30{
31 struct gfs2_glock *gl;
Steven Whitehouse5c676f62006-02-27 17:23:27 -050032 struct gfs2_trans *tr = current->journal_info;
David Teiglandb3b94fa2006-01-16 16:50:04 +000033
Steven Whitehouse5c676f62006-02-27 17:23:27 -050034 tr->tr_touched = 1;
David Teiglandb3b94fa2006-01-16 16:50:04 +000035
36 if (!list_empty(&le->le_list))
37 return;
38
39 gl = container_of(le, struct gfs2_glock, gl_le);
40 if (gfs2_assert_withdraw(sdp, gfs2_glock_is_held_excl(gl)))
41 return;
42 gfs2_glock_hold(gl);
43 set_bit(GLF_DIRTY, &gl->gl_flags);
44
45 gfs2_log_lock(sdp);
46 sdp->sd_log_num_gl++;
47 list_add(&le->le_list, &sdp->sd_log_le_gl);
48 gfs2_log_unlock(sdp);
49}
50
51static void glock_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_ail *ai)
52{
53 struct list_head *head = &sdp->sd_log_le_gl;
54 struct gfs2_glock *gl;
55
56 while (!list_empty(head)) {
57 gl = list_entry(head->next, struct gfs2_glock, gl_le.le_list);
58 list_del_init(&gl->gl_le.le_list);
59 sdp->sd_log_num_gl--;
60
61 gfs2_assert_withdraw(sdp, gfs2_glock_is_held_excl(gl));
62 gfs2_glock_put(gl);
63 }
64 gfs2_assert_warn(sdp, !sdp->sd_log_num_gl);
65}
66
67static void buf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le)
68{
69 struct gfs2_bufdata *bd = container_of(le, struct gfs2_bufdata, bd_le);
70 struct gfs2_trans *tr;
71
Steven Whitehouse8bd95722007-01-25 10:04:20 +000072 gfs2_log_lock(sdp);
73 if (!list_empty(&bd->bd_list_tr)) {
74 gfs2_log_unlock(sdp);
David Teiglandb3b94fa2006-01-16 16:50:04 +000075 return;
Steven Whitehouse8bd95722007-01-25 10:04:20 +000076 }
Steven Whitehouse5c676f62006-02-27 17:23:27 -050077 tr = current->journal_info;
David Teiglandb3b94fa2006-01-16 16:50:04 +000078 tr->tr_touched = 1;
79 tr->tr_num_buf++;
80 list_add(&bd->bd_list_tr, &tr->tr_list_buf);
Steven Whitehouse8bd95722007-01-25 10:04:20 +000081 gfs2_log_unlock(sdp);
David Teiglandb3b94fa2006-01-16 16:50:04 +000082
83 if (!list_empty(&le->le_list))
84 return;
85
86 gfs2_trans_add_gl(bd->bd_gl);
87
88 gfs2_meta_check(sdp, bd->bd_bh);
Steven Whitehousea98ab222006-01-18 13:38:44 +000089 gfs2_pin(sdp, bd->bd_bh);
David Teiglandb3b94fa2006-01-16 16:50:04 +000090 gfs2_log_lock(sdp);
91 sdp->sd_log_num_buf++;
92 list_add(&le->le_list, &sdp->sd_log_le_buf);
93 gfs2_log_unlock(sdp);
94
95 tr->tr_num_buf_new++;
96}
97
98static void buf_lo_incore_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
99{
100 struct list_head *head = &tr->tr_list_buf;
101 struct gfs2_bufdata *bd;
102
Steven Whitehouse8bd95722007-01-25 10:04:20 +0000103 gfs2_log_lock(sdp);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000104 while (!list_empty(head)) {
105 bd = list_entry(head->next, struct gfs2_bufdata, bd_list_tr);
106 list_del_init(&bd->bd_list_tr);
107 tr->tr_num_buf--;
108 }
Steven Whitehouse8bd95722007-01-25 10:04:20 +0000109 gfs2_log_unlock(sdp);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000110 gfs2_assert_warn(sdp, !tr->tr_num_buf);
111}
112
113static void buf_lo_before_commit(struct gfs2_sbd *sdp)
114{
115 struct buffer_head *bh;
116 struct gfs2_log_descriptor *ld;
117 struct gfs2_bufdata *bd1 = NULL, *bd2;
118 unsigned int total = sdp->sd_log_num_buf;
119 unsigned int offset = sizeof(struct gfs2_log_descriptor);
120 unsigned int limit;
121 unsigned int num;
122 unsigned n;
123 __be64 *ptr;
124
Steven Whitehouse82ffa512006-09-04 14:47:06 -0400125 offset += sizeof(__be64) - 1;
David Teiglandb3b94fa2006-01-16 16:50:04 +0000126 offset &= ~(sizeof(__be64) - 1);
127 limit = (sdp->sd_sb.sb_bsize - offset)/sizeof(__be64);
128 /* for 4k blocks, limit = 503 */
129
130 bd1 = bd2 = list_prepare_entry(bd1, &sdp->sd_log_le_buf, bd_le.le_list);
131 while(total) {
132 num = total;
133 if (total > limit)
134 num = limit;
135 bh = gfs2_log_get_buf(sdp);
Steven Whitehouseb09e5932006-04-07 11:17:32 -0400136 sdp->sd_log_num_hdrs++;
David Teiglandb3b94fa2006-01-16 16:50:04 +0000137 ld = (struct gfs2_log_descriptor *)bh->b_data;
138 ptr = (__be64 *)(bh->b_data + offset);
139 ld->ld_header.mh_magic = cpu_to_be32(GFS2_MAGIC);
Steven Whitehousee3167de2006-03-30 15:46:23 -0500140 ld->ld_header.mh_type = cpu_to_be32(GFS2_METATYPE_LD);
141 ld->ld_header.mh_format = cpu_to_be32(GFS2_FORMAT_LD);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000142 ld->ld_type = cpu_to_be32(GFS2_LOG_DESC_METADATA);
143 ld->ld_length = cpu_to_be32(num + 1);
144 ld->ld_data1 = cpu_to_be32(num);
145 ld->ld_data2 = cpu_to_be32(0);
146 memset(ld->ld_reserved, 0, sizeof(ld->ld_reserved));
147
148 n = 0;
Steven Whitehouse568f4c92006-02-27 12:00:42 -0500149 list_for_each_entry_continue(bd1, &sdp->sd_log_le_buf,
150 bd_le.le_list) {
David Teiglandb3b94fa2006-01-16 16:50:04 +0000151 *ptr++ = cpu_to_be64(bd1->bd_bh->b_blocknr);
152 if (++n >= num)
153 break;
154 }
155
156 set_buffer_dirty(bh);
157 ll_rw_block(WRITE, 1, &bh);
158
159 n = 0;
Steven Whitehouse568f4c92006-02-27 12:00:42 -0500160 list_for_each_entry_continue(bd2, &sdp->sd_log_le_buf,
161 bd_le.le_list) {
David Teiglandb3b94fa2006-01-16 16:50:04 +0000162 bh = gfs2_log_fake_buf(sdp, bd2->bd_bh);
163 set_buffer_dirty(bh);
164 ll_rw_block(WRITE, 1, &bh);
165 if (++n >= num)
166 break;
167 }
168
169 total -= num;
170 }
171}
172
173static void buf_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_ail *ai)
174{
175 struct list_head *head = &sdp->sd_log_le_buf;
176 struct gfs2_bufdata *bd;
177
178 while (!list_empty(head)) {
179 bd = list_entry(head->next, struct gfs2_bufdata, bd_le.le_list);
180 list_del_init(&bd->bd_le.le_list);
181 sdp->sd_log_num_buf--;
182
Steven Whitehousea98ab222006-01-18 13:38:44 +0000183 gfs2_unpin(sdp, bd->bd_bh, ai);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000184 }
185 gfs2_assert_warn(sdp, !sdp->sd_log_num_buf);
186}
187
188static void buf_lo_before_scan(struct gfs2_jdesc *jd,
Al Viro55167622006-10-13 21:47:13 -0400189 struct gfs2_log_header_host *head, int pass)
David Teiglandb3b94fa2006-01-16 16:50:04 +0000190{
Steven Whitehousefeaa7bb2006-06-14 15:32:57 -0400191 struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000192
193 if (pass != 0)
194 return;
195
196 sdp->sd_found_blocks = 0;
197 sdp->sd_replayed_blocks = 0;
198}
199
200static int buf_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start,
201 struct gfs2_log_descriptor *ld, __be64 *ptr,
202 int pass)
203{
Steven Whitehousefeaa7bb2006-06-14 15:32:57 -0400204 struct gfs2_inode *ip = GFS2_I(jd->jd_inode);
205 struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
Steven Whitehouse5c676f62006-02-27 17:23:27 -0500206 struct gfs2_glock *gl = ip->i_gl;
David Teiglandb3b94fa2006-01-16 16:50:04 +0000207 unsigned int blks = be32_to_cpu(ld->ld_data1);
208 struct buffer_head *bh_log, *bh_ip;
Steven Whitehousecd915492006-09-04 12:49:07 -0400209 u64 blkno;
David Teiglandb3b94fa2006-01-16 16:50:04 +0000210 int error = 0;
211
212 if (pass != 1 || be32_to_cpu(ld->ld_type) != GFS2_LOG_DESC_METADATA)
213 return 0;
214
215 gfs2_replay_incr_blk(sdp, &start);
216
217 for (; blks; gfs2_replay_incr_blk(sdp, &start), blks--) {
218 blkno = be64_to_cpu(*ptr++);
219
220 sdp->sd_found_blocks++;
221
222 if (gfs2_revoke_check(sdp, blkno, start))
223 continue;
224
225 error = gfs2_replay_read_block(jd, start, &bh_log);
Steven Whitehouse82ffa512006-09-04 14:47:06 -0400226 if (error)
227 return error;
David Teiglandb3b94fa2006-01-16 16:50:04 +0000228
229 bh_ip = gfs2_meta_new(gl, blkno);
230 memcpy(bh_ip->b_data, bh_log->b_data, bh_log->b_size);
231
232 if (gfs2_meta_check(sdp, bh_ip))
233 error = -EIO;
234 else
235 mark_buffer_dirty(bh_ip);
236
237 brelse(bh_log);
238 brelse(bh_ip);
239
240 if (error)
241 break;
242
243 sdp->sd_replayed_blocks++;
244 }
245
246 return error;
247}
248
249static void buf_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass)
250{
Steven Whitehousefeaa7bb2006-06-14 15:32:57 -0400251 struct gfs2_inode *ip = GFS2_I(jd->jd_inode);
252 struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000253
254 if (error) {
Steven Whitehouse7276b3b2006-09-21 17:05:23 -0400255 gfs2_meta_sync(ip->i_gl);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000256 return;
257 }
258 if (pass != 1)
259 return;
260
Steven Whitehouse7276b3b2006-09-21 17:05:23 -0400261 gfs2_meta_sync(ip->i_gl);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000262
263 fs_info(sdp, "jid=%u: Replayed %u of %u blocks\n",
264 jd->jd_jid, sdp->sd_replayed_blocks, sdp->sd_found_blocks);
265}
266
267static void revoke_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le)
268{
269 struct gfs2_trans *tr;
270
Steven Whitehouse5c676f62006-02-27 17:23:27 -0500271 tr = current->journal_info;
David Teiglandb3b94fa2006-01-16 16:50:04 +0000272 tr->tr_touched = 1;
273 tr->tr_num_revoke++;
274
275 gfs2_log_lock(sdp);
276 sdp->sd_log_num_revoke++;
277 list_add(&le->le_list, &sdp->sd_log_le_revoke);
278 gfs2_log_unlock(sdp);
279}
280
281static void revoke_lo_before_commit(struct gfs2_sbd *sdp)
282{
283 struct gfs2_log_descriptor *ld;
284 struct gfs2_meta_header *mh;
285 struct buffer_head *bh;
286 unsigned int offset;
287 struct list_head *head = &sdp->sd_log_le_revoke;
288 struct gfs2_revoke *rv;
289
290 if (!sdp->sd_log_num_revoke)
291 return;
292
293 bh = gfs2_log_get_buf(sdp);
294 ld = (struct gfs2_log_descriptor *)bh->b_data;
295 ld->ld_header.mh_magic = cpu_to_be32(GFS2_MAGIC);
Steven Whitehousee3167de2006-03-30 15:46:23 -0500296 ld->ld_header.mh_type = cpu_to_be32(GFS2_METATYPE_LD);
297 ld->ld_header.mh_format = cpu_to_be32(GFS2_FORMAT_LD);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000298 ld->ld_type = cpu_to_be32(GFS2_LOG_DESC_REVOKE);
Steven Whitehouse568f4c92006-02-27 12:00:42 -0500299 ld->ld_length = cpu_to_be32(gfs2_struct2blk(sdp, sdp->sd_log_num_revoke,
Steven Whitehousecd915492006-09-04 12:49:07 -0400300 sizeof(u64)));
David Teiglandb3b94fa2006-01-16 16:50:04 +0000301 ld->ld_data1 = cpu_to_be32(sdp->sd_log_num_revoke);
302 ld->ld_data2 = cpu_to_be32(0);
303 memset(ld->ld_reserved, 0, sizeof(ld->ld_reserved));
304 offset = sizeof(struct gfs2_log_descriptor);
305
306 while (!list_empty(head)) {
307 rv = list_entry(head->next, struct gfs2_revoke, rv_le.le_list);
Steven Whitehouse13538b82006-02-22 11:15:03 +0000308 list_del_init(&rv->rv_le.le_list);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000309 sdp->sd_log_num_revoke--;
310
Steven Whitehousecd915492006-09-04 12:49:07 -0400311 if (offset + sizeof(u64) > sdp->sd_sb.sb_bsize) {
David Teiglandb3b94fa2006-01-16 16:50:04 +0000312 set_buffer_dirty(bh);
313 ll_rw_block(WRITE, 1, &bh);
314
315 bh = gfs2_log_get_buf(sdp);
316 mh = (struct gfs2_meta_header *)bh->b_data;
317 mh->mh_magic = cpu_to_be32(GFS2_MAGIC);
Steven Whitehousee3167de2006-03-30 15:46:23 -0500318 mh->mh_type = cpu_to_be32(GFS2_METATYPE_LB);
319 mh->mh_format = cpu_to_be32(GFS2_FORMAT_LB);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000320 offset = sizeof(struct gfs2_meta_header);
321 }
322
323 *(__be64 *)(bh->b_data + offset) = cpu_to_be64(rv->rv_blkno);
324 kfree(rv);
325
Steven Whitehousecd915492006-09-04 12:49:07 -0400326 offset += sizeof(u64);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000327 }
328 gfs2_assert_withdraw(sdp, !sdp->sd_log_num_revoke);
329
330 set_buffer_dirty(bh);
331 ll_rw_block(WRITE, 1, &bh);
332}
333
334static void revoke_lo_before_scan(struct gfs2_jdesc *jd,
Al Viro55167622006-10-13 21:47:13 -0400335 struct gfs2_log_header_host *head, int pass)
David Teiglandb3b94fa2006-01-16 16:50:04 +0000336{
Steven Whitehousefeaa7bb2006-06-14 15:32:57 -0400337 struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000338
339 if (pass != 0)
340 return;
341
342 sdp->sd_found_revokes = 0;
343 sdp->sd_replay_tail = head->lh_tail;
344}
345
346static int revoke_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start,
347 struct gfs2_log_descriptor *ld, __be64 *ptr,
348 int pass)
349{
Steven Whitehousefeaa7bb2006-06-14 15:32:57 -0400350 struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000351 unsigned int blks = be32_to_cpu(ld->ld_length);
352 unsigned int revokes = be32_to_cpu(ld->ld_data1);
353 struct buffer_head *bh;
354 unsigned int offset;
Steven Whitehousecd915492006-09-04 12:49:07 -0400355 u64 blkno;
David Teiglandb3b94fa2006-01-16 16:50:04 +0000356 int first = 1;
357 int error;
358
359 if (pass != 0 || be32_to_cpu(ld->ld_type) != GFS2_LOG_DESC_REVOKE)
360 return 0;
361
362 offset = sizeof(struct gfs2_log_descriptor);
363
364 for (; blks; gfs2_replay_incr_blk(sdp, &start), blks--) {
365 error = gfs2_replay_read_block(jd, start, &bh);
366 if (error)
367 return error;
368
369 if (!first)
370 gfs2_metatype_check(sdp, bh, GFS2_METATYPE_LB);
371
Steven Whitehousecd915492006-09-04 12:49:07 -0400372 while (offset + sizeof(u64) <= sdp->sd_sb.sb_bsize) {
David Teiglandb3b94fa2006-01-16 16:50:04 +0000373 blkno = be64_to_cpu(*(__be64 *)(bh->b_data + offset));
374
375 error = gfs2_revoke_add(sdp, blkno, start);
376 if (error < 0)
377 return error;
378 else if (error)
379 sdp->sd_found_revokes++;
380
381 if (!--revokes)
382 break;
Steven Whitehousecd915492006-09-04 12:49:07 -0400383 offset += sizeof(u64);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000384 }
385
386 brelse(bh);
387 offset = sizeof(struct gfs2_meta_header);
388 first = 0;
389 }
390
391 return 0;
392}
393
394static void revoke_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass)
395{
Steven Whitehousefeaa7bb2006-06-14 15:32:57 -0400396 struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000397
398 if (error) {
399 gfs2_revoke_clean(sdp);
400 return;
401 }
402 if (pass != 1)
403 return;
404
405 fs_info(sdp, "jid=%u: Found %u revoke tags\n",
406 jd->jd_jid, sdp->sd_found_revokes);
407
408 gfs2_revoke_clean(sdp);
409}
410
411static void rg_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le)
412{
413 struct gfs2_rgrpd *rgd;
Steven Whitehouse5c676f62006-02-27 17:23:27 -0500414 struct gfs2_trans *tr = current->journal_info;
David Teiglandb3b94fa2006-01-16 16:50:04 +0000415
Steven Whitehouse5c676f62006-02-27 17:23:27 -0500416 tr->tr_touched = 1;
David Teiglandb3b94fa2006-01-16 16:50:04 +0000417
418 if (!list_empty(&le->le_list))
419 return;
420
421 rgd = container_of(le, struct gfs2_rgrpd, rd_le);
422 gfs2_rgrp_bh_hold(rgd);
423
424 gfs2_log_lock(sdp);
425 sdp->sd_log_num_rg++;
426 list_add(&le->le_list, &sdp->sd_log_le_rg);
Steven Whitehouse907b9bc2006-09-25 09:26:04 -0400427 gfs2_log_unlock(sdp);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000428}
429
430static void rg_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_ail *ai)
431{
432 struct list_head *head = &sdp->sd_log_le_rg;
433 struct gfs2_rgrpd *rgd;
434
435 while (!list_empty(head)) {
436 rgd = list_entry(head->next, struct gfs2_rgrpd, rd_le.le_list);
437 list_del_init(&rgd->rd_le.le_list);
438 sdp->sd_log_num_rg--;
439
440 gfs2_rgrp_repolish_clones(rgd);
441 gfs2_rgrp_bh_put(rgd);
442 }
443 gfs2_assert_warn(sdp, !sdp->sd_log_num_rg);
444}
445
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000446/**
447 * databuf_lo_add - Add a databuf to the transaction.
448 *
449 * This is used in two distinct cases:
450 * i) In ordered write mode
451 * We put the data buffer on a list so that we can ensure that its
452 * synced to disk at the right time
453 * ii) In journaled data mode
454 * We need to journal the data block in the same way as metadata in
455 * the functions above. The difference is that here we have a tag
456 * which is two __be64's being the block number (as per meta data)
457 * and a flag which says whether the data block needs escaping or
458 * not. This means we need a new log entry for each 251 or so data
459 * blocks, which isn't an enormous overhead but twice as much as
460 * for normal metadata blocks.
461 */
David Teiglandb3b94fa2006-01-16 16:50:04 +0000462static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le)
463{
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000464 struct gfs2_bufdata *bd = container_of(le, struct gfs2_bufdata, bd_le);
Steven Whitehouse5c676f62006-02-27 17:23:27 -0500465 struct gfs2_trans *tr = current->journal_info;
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000466 struct address_space *mapping = bd->bd_bh->b_page->mapping;
Steven Whitehousefeaa7bb2006-06-14 15:32:57 -0400467 struct gfs2_inode *ip = GFS2_I(mapping->host);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000468
Steven Whitehouse8bd95722007-01-25 10:04:20 +0000469 gfs2_log_lock(sdp);
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000470 tr->tr_touched = 1;
Steven Whitehouse15d00c02006-08-18 15:51:09 -0400471 if (list_empty(&bd->bd_list_tr) &&
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000472 (ip->i_di.di_flags & GFS2_DIF_JDATA)) {
473 tr->tr_num_buf++;
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000474 list_add(&bd->bd_list_tr, &tr->tr_list_buf);
Steven Whitehouse8bd95722007-01-25 10:04:20 +0000475 gfs2_log_unlock(sdp);
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000476 gfs2_pin(sdp, bd->bd_bh);
Steven Whitehouseb4dc7292006-03-01 17:41:58 -0500477 tr->tr_num_buf_new++;
Steven Whitehouse8bd95722007-01-25 10:04:20 +0000478 } else {
479 gfs2_log_unlock(sdp);
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000480 }
Steven Whitehouseb61dde72006-06-19 10:51:11 -0400481 gfs2_trans_add_gl(bd->bd_gl);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000482 gfs2_log_lock(sdp);
Steven Whitehouse15d00c02006-08-18 15:51:09 -0400483 if (list_empty(&le->le_list)) {
Steven Whitehouse13538b82006-02-22 11:15:03 +0000484 if (ip->i_di.di_flags & GFS2_DIF_JDATA)
485 sdp->sd_log_num_jdata++;
486 sdp->sd_log_num_databuf++;
487 list_add(&le->le_list, &sdp->sd_log_le_databuf);
488 }
David Teiglandb3b94fa2006-01-16 16:50:04 +0000489 gfs2_log_unlock(sdp);
490}
491
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000492static int gfs2_check_magic(struct buffer_head *bh)
493{
494 struct page *page = bh->b_page;
495 void *kaddr;
496 __be32 *ptr;
497 int rv = 0;
498
499 kaddr = kmap_atomic(page, KM_USER0);
500 ptr = kaddr + bh_offset(bh);
501 if (*ptr == cpu_to_be32(GFS2_MAGIC))
502 rv = 1;
Russell Cattelanc312c4f2006-10-12 09:23:41 -0400503 kunmap_atomic(kaddr, KM_USER0);
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000504
505 return rv;
506}
507
508/**
509 * databuf_lo_before_commit - Scan the data buffers, writing as we go
510 *
511 * Here we scan through the lists of buffers and make the assumption
512 * that any buffer thats been pinned is being journaled, and that
513 * any unpinned buffer is an ordered write data buffer and therefore
514 * will be written back rather than journaled.
515 */
David Teiglandb3b94fa2006-01-16 16:50:04 +0000516static void databuf_lo_before_commit(struct gfs2_sbd *sdp)
517{
David Teiglandb3b94fa2006-01-16 16:50:04 +0000518 LIST_HEAD(started);
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000519 struct gfs2_bufdata *bd1 = NULL, *bd2, *bdt;
Russell Cattelan70209332006-11-09 11:28:08 -0500520 struct buffer_head *bh = NULL,*bh1 = NULL;
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000521 unsigned int offset = sizeof(struct gfs2_log_descriptor);
522 struct gfs2_log_descriptor *ld;
523 unsigned int limit;
524 unsigned int total_dbuf = sdp->sd_log_num_databuf;
525 unsigned int total_jdata = sdp->sd_log_num_jdata;
526 unsigned int num, n;
Steven Whitehousef55ab262006-02-21 12:51:39 +0000527 __be64 *ptr = NULL;
David Teiglandb3b94fa2006-01-16 16:50:04 +0000528
Steven Whitehousea67cdbd2006-09-05 14:41:30 -0400529 offset += 2*sizeof(__be64) - 1;
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000530 offset &= ~(2*sizeof(__be64) - 1);
531 limit = (sdp->sd_sb.sb_bsize - offset)/sizeof(__be64);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000532
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000533 /*
534 * Start writing ordered buffers, write journaled buffers
535 * into the log along with a header
536 */
Steven Whitehousef55ab262006-02-21 12:51:39 +0000537 gfs2_log_lock(sdp);
Steven Whitehouse568f4c92006-02-27 12:00:42 -0500538 bd2 = bd1 = list_prepare_entry(bd1, &sdp->sd_log_le_databuf,
539 bd_le.le_list);
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000540 while(total_dbuf) {
541 num = total_jdata;
542 if (num > limit)
543 num = limit;
544 n = 0;
Steven Whitehouse568f4c92006-02-27 12:00:42 -0500545 list_for_each_entry_safe_continue(bd1, bdt,
546 &sdp->sd_log_le_databuf,
547 bd_le.le_list) {
Russell Cattelan70209332006-11-09 11:28:08 -0500548 /* store off the buffer head in a local ptr since
549 * gfs2_bufdata might change when we drop the log lock
550 */
551 bh1 = bd1->bd_bh;
552
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000553 /* An ordered write buffer */
Russell Cattelan70209332006-11-09 11:28:08 -0500554 if (bh1 && !buffer_pinned(bh1)) {
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000555 list_move(&bd1->bd_le.le_list, &started);
556 if (bd1 == bd2) {
557 bd2 = NULL;
Steven Whitehouse568f4c92006-02-27 12:00:42 -0500558 bd2 = list_prepare_entry(bd2,
559 &sdp->sd_log_le_databuf,
560 bd_le.le_list);
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000561 }
562 total_dbuf--;
Russell Cattelan70209332006-11-09 11:28:08 -0500563 if (bh1) {
564 if (buffer_dirty(bh1)) {
565 get_bh(bh1);
566
Steven Whitehousef55ab262006-02-21 12:51:39 +0000567 gfs2_log_unlock(sdp);
Russell Cattelan70209332006-11-09 11:28:08 -0500568
569 ll_rw_block(SWRITE, 1, &bh1);
570 brelse(bh1);
571
Steven Whitehousef55ab262006-02-21 12:51:39 +0000572 gfs2_log_lock(sdp);
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000573 }
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000574 continue;
575 }
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000576 continue;
Russell Cattelan70209332006-11-09 11:28:08 -0500577 } else if (bh1) { /* A journaled buffer */
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000578 int magic;
579 gfs2_log_unlock(sdp);
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000580 if (!bh) {
581 bh = gfs2_log_get_buf(sdp);
Steven Whitehouseb09e5932006-04-07 11:17:32 -0400582 sdp->sd_log_num_hdrs++;
Steven Whitehouse568f4c92006-02-27 12:00:42 -0500583 ld = (struct gfs2_log_descriptor *)
584 bh->b_data;
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000585 ptr = (__be64 *)(bh->b_data + offset);
Steven Whitehouse568f4c92006-02-27 12:00:42 -0500586 ld->ld_header.mh_magic =
587 cpu_to_be32(GFS2_MAGIC);
588 ld->ld_header.mh_type =
Steven Whitehousee3167de2006-03-30 15:46:23 -0500589 cpu_to_be32(GFS2_METATYPE_LD);
Steven Whitehouse568f4c92006-02-27 12:00:42 -0500590 ld->ld_header.mh_format =
Steven Whitehousee3167de2006-03-30 15:46:23 -0500591 cpu_to_be32(GFS2_FORMAT_LD);
Steven Whitehouse568f4c92006-02-27 12:00:42 -0500592 ld->ld_type =
593 cpu_to_be32(GFS2_LOG_DESC_JDATA);
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000594 ld->ld_length = cpu_to_be32(num + 1);
595 ld->ld_data1 = cpu_to_be32(num);
596 ld->ld_data2 = cpu_to_be32(0);
597 memset(ld->ld_reserved, 0, sizeof(ld->ld_reserved));
598 }
Russell Cattelan70209332006-11-09 11:28:08 -0500599 magic = gfs2_check_magic(bh1);
600 *ptr++ = cpu_to_be64(bh1->b_blocknr);
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000601 *ptr++ = cpu_to_be64((__u64)magic);
Russell Cattelan70209332006-11-09 11:28:08 -0500602 clear_buffer_escaped(bh1);
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000603 if (unlikely(magic != 0))
Russell Cattelan70209332006-11-09 11:28:08 -0500604 set_buffer_escaped(bh1);
Steven Whitehousef55ab262006-02-21 12:51:39 +0000605 gfs2_log_lock(sdp);
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000606 if (n++ > num)
607 break;
Russell Cattelan70209332006-11-09 11:28:08 -0500608 } else if (!bh1) {
Steven Whitehouse623d9352006-08-31 12:14:44 -0400609 total_dbuf--;
610 sdp->sd_log_num_databuf--;
611 list_del_init(&bd1->bd_le.le_list);
612 if (bd1 == bd2) {
613 bd2 = NULL;
614 bd2 = list_prepare_entry(bd2,
615 &sdp->sd_log_le_databuf,
616 bd_le.le_list);
617 }
618 kmem_cache_free(gfs2_bufdata_cachep, bd1);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000619 }
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000620 }
Steven Whitehousef55ab262006-02-21 12:51:39 +0000621 gfs2_log_unlock(sdp);
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000622 if (bh) {
623 set_buffer_dirty(bh);
624 ll_rw_block(WRITE, 1, &bh);
625 bh = NULL;
626 }
627 n = 0;
Steven Whitehousef55ab262006-02-21 12:51:39 +0000628 gfs2_log_lock(sdp);
Steven Whitehouse568f4c92006-02-27 12:00:42 -0500629 list_for_each_entry_continue(bd2, &sdp->sd_log_le_databuf,
630 bd_le.le_list) {
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000631 if (!bd2->bd_bh)
632 continue;
633 /* copy buffer if it needs escaping */
Steven Whitehousef55ab262006-02-21 12:51:39 +0000634 gfs2_log_unlock(sdp);
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000635 if (unlikely(buffer_escaped(bd2->bd_bh))) {
636 void *kaddr;
637 struct page *page = bd2->bd_bh->b_page;
638 bh = gfs2_log_get_buf(sdp);
639 kaddr = kmap_atomic(page, KM_USER0);
Steven Whitehouse568f4c92006-02-27 12:00:42 -0500640 memcpy(bh->b_data,
641 kaddr + bh_offset(bd2->bd_bh),
642 sdp->sd_sb.sb_bsize);
Russell Cattelanc312c4f2006-10-12 09:23:41 -0400643 kunmap_atomic(kaddr, KM_USER0);
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000644 *(__be32 *)bh->b_data = 0;
645 } else {
646 bh = gfs2_log_fake_buf(sdp, bd2->bd_bh);
647 }
648 set_buffer_dirty(bh);
649 ll_rw_block(WRITE, 1, &bh);
Steven Whitehousef55ab262006-02-21 12:51:39 +0000650 gfs2_log_lock(sdp);
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000651 if (++n >= num)
652 break;
653 }
654 bh = NULL;
655 total_dbuf -= num;
656 total_jdata -= num;
David Teiglandb3b94fa2006-01-16 16:50:04 +0000657 }
Steven Whitehousef55ab262006-02-21 12:51:39 +0000658 gfs2_log_unlock(sdp);
659
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000660 /* Wait on all ordered buffers */
David Teiglandb3b94fa2006-01-16 16:50:04 +0000661 while (!list_empty(&started)) {
Steven Whitehouse13538b82006-02-22 11:15:03 +0000662 gfs2_log_lock(sdp);
Steven Whitehouse568f4c92006-02-27 12:00:42 -0500663 bd1 = list_entry(started.next, struct gfs2_bufdata,
664 bd_le.le_list);
Steven Whitehouse08867602006-08-22 11:03:57 -0400665 list_del_init(&bd1->bd_le.le_list);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000666 sdp->sd_log_num_databuf--;
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000667 bh = bd1->bd_bh;
David Teiglandb3b94fa2006-01-16 16:50:04 +0000668 if (bh) {
Steven Whitehouse5c676f62006-02-27 17:23:27 -0500669 bh->b_private = NULL;
Steven Whitehouse15d00c02006-08-18 15:51:09 -0400670 get_bh(bh);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000671 gfs2_log_unlock(sdp);
672 wait_on_buffer(bh);
673 brelse(bh);
674 } else
675 gfs2_log_unlock(sdp);
676
Steven Whitehouse3a8476d2006-06-19 09:10:39 -0400677 kmem_cache_free(gfs2_bufdata_cachep, bd1);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000678 }
679
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000680 /* We've removed all the ordered write bufs here, so only jdata left */
681 gfs2_assert_warn(sdp, sdp->sd_log_num_databuf == sdp->sd_log_num_jdata);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000682}
683
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000684static int databuf_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start,
685 struct gfs2_log_descriptor *ld,
686 __be64 *ptr, int pass)
687{
Steven Whitehousefeaa7bb2006-06-14 15:32:57 -0400688 struct gfs2_inode *ip = GFS2_I(jd->jd_inode);
689 struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
Steven Whitehouse5c676f62006-02-27 17:23:27 -0500690 struct gfs2_glock *gl = ip->i_gl;
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000691 unsigned int blks = be32_to_cpu(ld->ld_data1);
692 struct buffer_head *bh_log, *bh_ip;
Steven Whitehousecd915492006-09-04 12:49:07 -0400693 u64 blkno;
694 u64 esc;
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000695 int error = 0;
696
697 if (pass != 1 || be32_to_cpu(ld->ld_type) != GFS2_LOG_DESC_JDATA)
698 return 0;
699
700 gfs2_replay_incr_blk(sdp, &start);
701 for (; blks; gfs2_replay_incr_blk(sdp, &start), blks--) {
702 blkno = be64_to_cpu(*ptr++);
703 esc = be64_to_cpu(*ptr++);
704
705 sdp->sd_found_blocks++;
706
707 if (gfs2_revoke_check(sdp, blkno, start))
708 continue;
709
710 error = gfs2_replay_read_block(jd, start, &bh_log);
711 if (error)
712 return error;
713
714 bh_ip = gfs2_meta_new(gl, blkno);
715 memcpy(bh_ip->b_data, bh_log->b_data, bh_log->b_size);
716
717 /* Unescape */
718 if (esc) {
719 __be32 *eptr = (__be32 *)bh_ip->b_data;
720 *eptr = cpu_to_be32(GFS2_MAGIC);
721 }
722 mark_buffer_dirty(bh_ip);
723
724 brelse(bh_log);
725 brelse(bh_ip);
726 if (error)
727 break;
728
729 sdp->sd_replayed_blocks++;
730 }
731
732 return error;
733}
734
735/* FIXME: sort out accounting for log blocks etc. */
736
737static void databuf_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass)
738{
Steven Whitehousefeaa7bb2006-06-14 15:32:57 -0400739 struct gfs2_inode *ip = GFS2_I(jd->jd_inode);
740 struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000741
742 if (error) {
Steven Whitehouse7276b3b2006-09-21 17:05:23 -0400743 gfs2_meta_sync(ip->i_gl);
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000744 return;
745 }
746 if (pass != 1)
747 return;
748
749 /* data sync? */
Steven Whitehouse7276b3b2006-09-21 17:05:23 -0400750 gfs2_meta_sync(ip->i_gl);
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000751
752 fs_info(sdp, "jid=%u: Replayed %u of %u data blocks\n",
753 jd->jd_jid, sdp->sd_replayed_blocks, sdp->sd_found_blocks);
754}
755
756static void databuf_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_ail *ai)
757{
758 struct list_head *head = &sdp->sd_log_le_databuf;
759 struct gfs2_bufdata *bd;
760
761 while (!list_empty(head)) {
762 bd = list_entry(head->next, struct gfs2_bufdata, bd_le.le_list);
Steven Whitehouseb8e1aab2006-08-22 16:25:50 -0400763 list_del_init(&bd->bd_le.le_list);
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000764 sdp->sd_log_num_databuf--;
765 sdp->sd_log_num_jdata--;
766 gfs2_unpin(sdp, bd->bd_bh, ai);
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000767 }
768 gfs2_assert_warn(sdp, !sdp->sd_log_num_databuf);
769 gfs2_assert_warn(sdp, !sdp->sd_log_num_jdata);
770}
771
772
Steven Whitehouseb09e5932006-04-07 11:17:32 -0400773const struct gfs2_log_operations gfs2_glock_lops = {
David Teiglandb3b94fa2006-01-16 16:50:04 +0000774 .lo_add = glock_lo_add,
775 .lo_after_commit = glock_lo_after_commit,
Steven Whitehouseea67eed2006-09-05 10:53:09 -0400776 .lo_name = "glock",
David Teiglandb3b94fa2006-01-16 16:50:04 +0000777};
778
Steven Whitehouseb09e5932006-04-07 11:17:32 -0400779const struct gfs2_log_operations gfs2_buf_lops = {
David Teiglandb3b94fa2006-01-16 16:50:04 +0000780 .lo_add = buf_lo_add,
781 .lo_incore_commit = buf_lo_incore_commit,
782 .lo_before_commit = buf_lo_before_commit,
783 .lo_after_commit = buf_lo_after_commit,
784 .lo_before_scan = buf_lo_before_scan,
785 .lo_scan_elements = buf_lo_scan_elements,
786 .lo_after_scan = buf_lo_after_scan,
Steven Whitehouseea67eed2006-09-05 10:53:09 -0400787 .lo_name = "buf",
David Teiglandb3b94fa2006-01-16 16:50:04 +0000788};
789
Steven Whitehouseb09e5932006-04-07 11:17:32 -0400790const struct gfs2_log_operations gfs2_revoke_lops = {
David Teiglandb3b94fa2006-01-16 16:50:04 +0000791 .lo_add = revoke_lo_add,
792 .lo_before_commit = revoke_lo_before_commit,
793 .lo_before_scan = revoke_lo_before_scan,
794 .lo_scan_elements = revoke_lo_scan_elements,
795 .lo_after_scan = revoke_lo_after_scan,
Steven Whitehouseea67eed2006-09-05 10:53:09 -0400796 .lo_name = "revoke",
David Teiglandb3b94fa2006-01-16 16:50:04 +0000797};
798
Steven Whitehouseb09e5932006-04-07 11:17:32 -0400799const struct gfs2_log_operations gfs2_rg_lops = {
David Teiglandb3b94fa2006-01-16 16:50:04 +0000800 .lo_add = rg_lo_add,
801 .lo_after_commit = rg_lo_after_commit,
Steven Whitehouseea67eed2006-09-05 10:53:09 -0400802 .lo_name = "rg",
David Teiglandb3b94fa2006-01-16 16:50:04 +0000803};
804
Steven Whitehouseb09e5932006-04-07 11:17:32 -0400805const struct gfs2_log_operations gfs2_databuf_lops = {
David Teiglandb3b94fa2006-01-16 16:50:04 +0000806 .lo_add = databuf_lo_add,
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000807 .lo_incore_commit = buf_lo_incore_commit,
David Teiglandb3b94fa2006-01-16 16:50:04 +0000808 .lo_before_commit = databuf_lo_before_commit,
Steven Whitehouse18ec7d52006-02-08 11:50:51 +0000809 .lo_after_commit = databuf_lo_after_commit,
810 .lo_scan_elements = databuf_lo_scan_elements,
811 .lo_after_scan = databuf_lo_after_scan,
Steven Whitehouseea67eed2006-09-05 10:53:09 -0400812 .lo_name = "databuf",
David Teiglandb3b94fa2006-01-16 16:50:04 +0000813};
814
Steven Whitehouseb09e5932006-04-07 11:17:32 -0400815const struct gfs2_log_operations *gfs2_log_ops[] = {
David Teiglandb3b94fa2006-01-16 16:50:04 +0000816 &gfs2_glock_lops,
817 &gfs2_buf_lops,
818 &gfs2_revoke_lops,
819 &gfs2_rg_lops,
820 &gfs2_databuf_lops,
Steven Whitehouseea67eed2006-09-05 10:53:09 -0400821 NULL,
David Teiglandb3b94fa2006-01-16 16:50:04 +0000822};
823