Blame view

fs/gfs2/lops.c 18.6 KB
b3b94faa5   David Teigland   [GFS2] The core o...
1
2
  /*
   * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
3a8a9a103   Steven Whitehouse   [GFS2] Update cop...
3
   * Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
b3b94faa5   David Teigland   [GFS2] The core o...
4
5
6
   *
   * This copyrighted material is made available to anyone wishing to use,
   * modify, copy, or redistribute it subject to the terms and conditions
e9fc2aa09   Steven Whitehouse   [GFS2] Update cop...
7
   * of the GNU General Public License version 2.
b3b94faa5   David Teigland   [GFS2] The core o...
8
9
10
11
12
13
14
   */
  
  #include <linux/sched.h>
  #include <linux/slab.h>
  #include <linux/spinlock.h>
  #include <linux/completion.h>
  #include <linux/buffer_head.h>
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
15
  #include <linux/gfs2_ondisk.h>
7d308590a   Fabio Massimo Di Nitto   [GFS2] Export lm_...
16
  #include <linux/lm_interface.h>
b3b94faa5   David Teigland   [GFS2] The core o...
17
18
  
  #include "gfs2.h"
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
19
  #include "incore.h"
2332c4435   Robert Peterson   [GFS2] assertion ...
20
  #include "inode.h"
b3b94faa5   David Teigland   [GFS2] The core o...
21
22
23
24
25
26
27
  #include "glock.h"
  #include "log.h"
  #include "lops.h"
  #include "meta_io.h"
  #include "recovery.h"
  #include "rgrp.h"
  #include "trans.h"
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
28
  #include "util.h"
b3b94faa5   David Teigland   [GFS2] The core o...
29

9b9107a5a   Steven Whitehouse   [GFS2] Move pin/u...
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
  /**
   * gfs2_pin - Pin a buffer in memory
   * @sdp: The superblock
   * @bh: The buffer to be pinned
   *
   * The log lock must be held when calling this function
   */
  static void gfs2_pin(struct gfs2_sbd *sdp, struct buffer_head *bh)
  {
  	struct gfs2_bufdata *bd;
  
  	gfs2_assert_withdraw(sdp, test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags));
  
  	clear_buffer_dirty(bh);
  	if (test_set_buffer_pinned(bh))
  		gfs2_assert_withdraw(sdp, 0);
  	if (!buffer_uptodate(bh))
  		gfs2_io_error_bh(sdp, bh);
  	bd = bh->b_private;
  	/* If this buffer is in the AIL and it has already been written
  	 * to in-place disk block, remove it from the AIL.
  	 */
  	if (bd->bd_ail)
  		list_move(&bd->bd_ail_st_list, &bd->bd_ail->ai_ail2_list);
  	get_bh(bh);
  }
  
  /**
   * gfs2_unpin - Unpin a buffer
   * @sdp: the filesystem the buffer belongs to
   * @bh: The buffer to unpin
   * @ai:
   *
   */
  
  static void gfs2_unpin(struct gfs2_sbd *sdp, struct buffer_head *bh,
  		       struct gfs2_ail *ai)
  {
  	struct gfs2_bufdata *bd = bh->b_private;
  
  	gfs2_assert_withdraw(sdp, buffer_uptodate(bh));
  
  	if (!buffer_pinned(bh))
  		gfs2_assert_withdraw(sdp, 0);
  
  	lock_buffer(bh);
  	mark_buffer_dirty(bh);
  	clear_buffer_pinned(bh);
  
  	gfs2_log_lock(sdp);
  	if (bd->bd_ail) {
  		list_del(&bd->bd_ail_st_list);
  		brelse(bh);
  	} else {
  		struct gfs2_glock *gl = bd->bd_gl;
  		list_add(&bd->bd_ail_gl_list, &gl->gl_ail_list);
  		atomic_inc(&gl->gl_ail_count);
  	}
  	bd->bd_ail = ai;
  	list_add(&bd->bd_ail_st_list, &ai->ai_ail1_list);
2bcd610d2   Steven Whitehouse   [GFS2] Don't add ...
90
  	clear_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags);
9b9107a5a   Steven Whitehouse   [GFS2] Move pin/u...
91
92
93
  	gfs2_log_unlock(sdp);
  	unlock_buffer(bh);
  }
16615be18   Steven Whitehouse   [GFS2] Clean up j...
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
  
  static inline struct gfs2_log_descriptor *bh_log_desc(struct buffer_head *bh)
  {
  	return (struct gfs2_log_descriptor *)bh->b_data;
  }
  
  static inline __be64 *bh_log_ptr(struct buffer_head *bh)
  {
  	struct gfs2_log_descriptor *ld = bh_log_desc(bh);
  	return (__force __be64 *)(ld + 1);
  }
  
  static inline __be64 *bh_ptr_end(struct buffer_head *bh)
  {
  	return (__force __be64 *)(bh->b_data + bh->b_size);
  }
  
  
  static struct buffer_head *gfs2_get_log_desc(struct gfs2_sbd *sdp, u32 ld_type)
  {
  	struct buffer_head *bh = gfs2_log_get_buf(sdp);
  	struct gfs2_log_descriptor *ld = bh_log_desc(bh);
  	ld->ld_header.mh_magic = cpu_to_be32(GFS2_MAGIC);
  	ld->ld_header.mh_type = cpu_to_be32(GFS2_METATYPE_LD);
  	ld->ld_header.mh_format = cpu_to_be32(GFS2_FORMAT_LD);
  	ld->ld_type = cpu_to_be32(ld_type);
  	ld->ld_length = 0;
  	ld->ld_data1 = 0;
  	ld->ld_data2 = 0;
  	memset(ld->ld_reserved, 0, sizeof(ld->ld_reserved));
  	return bh;
  }
b3b94faa5   David Teigland   [GFS2] The core o...
126
127
128
129
  static void buf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le)
  {
  	struct gfs2_bufdata *bd = container_of(le, struct gfs2_bufdata, bd_le);
  	struct gfs2_trans *tr;
9b9107a5a   Steven Whitehouse   [GFS2] Move pin/u...
130
  	lock_buffer(bd->bd_bh);
8bd957276   Steven Whitehouse   [GFS2] Fix list c...
131
  	gfs2_log_lock(sdp);
9b9107a5a   Steven Whitehouse   [GFS2] Move pin/u...
132
133
  	if (!list_empty(&bd->bd_list_tr))
  		goto out;
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
134
  	tr = current->journal_info;
b3b94faa5   David Teigland   [GFS2] The core o...
135
136
137
  	tr->tr_touched = 1;
  	tr->tr_num_buf++;
  	list_add(&bd->bd_list_tr, &tr->tr_list_buf);
b3b94faa5   David Teigland   [GFS2] The core o...
138
  	if (!list_empty(&le->le_list))
9b9107a5a   Steven Whitehouse   [GFS2] Move pin/u...
139
  		goto out;
2bcd610d2   Steven Whitehouse   [GFS2] Don't add ...
140
141
  	set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags);
  	set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags);
b3b94faa5   David Teigland   [GFS2] The core o...
142
  	gfs2_meta_check(sdp, bd->bd_bh);
a98ab2204   Steven Whitehouse   [GFS2] Rename gfs...
143
  	gfs2_pin(sdp, bd->bd_bh);
b3b94faa5   David Teigland   [GFS2] The core o...
144
145
  	sdp->sd_log_num_buf++;
  	list_add(&le->le_list, &sdp->sd_log_le_buf);
b3b94faa5   David Teigland   [GFS2] The core o...
146
  	tr->tr_num_buf_new++;
9b9107a5a   Steven Whitehouse   [GFS2] Move pin/u...
147
148
149
  out:
  	gfs2_log_unlock(sdp);
  	unlock_buffer(bd->bd_bh);
b3b94faa5   David Teigland   [GFS2] The core o...
150
  }
b3b94faa5   David Teigland   [GFS2] The core o...
151
152
153
154
155
  static void buf_lo_before_commit(struct gfs2_sbd *sdp)
  {
  	struct buffer_head *bh;
  	struct gfs2_log_descriptor *ld;
  	struct gfs2_bufdata *bd1 = NULL, *bd2;
905d2aefa   Bob Peterson   [GFS2] Move some ...
156
  	unsigned int total;
b3b94faa5   David Teigland   [GFS2] The core o...
157
158
159
160
  	unsigned int limit;
  	unsigned int num;
  	unsigned n;
  	__be64 *ptr;
2332c4435   Robert Peterson   [GFS2] assertion ...
161
  	limit = buf_limit(sdp);
b3b94faa5   David Teigland   [GFS2] The core o...
162
  	/* for 4k blocks, limit = 503 */
905d2aefa   Bob Peterson   [GFS2] Move some ...
163
164
  	gfs2_log_lock(sdp);
  	total = sdp->sd_log_num_buf;
b3b94faa5   David Teigland   [GFS2] The core o...
165
166
167
168
169
  	bd1 = bd2 = list_prepare_entry(bd1, &sdp->sd_log_le_buf, bd_le.le_list);
  	while(total) {
  		num = total;
  		if (total > limit)
  			num = limit;
905d2aefa   Bob Peterson   [GFS2] Move some ...
170
  		gfs2_log_unlock(sdp);
16615be18   Steven Whitehouse   [GFS2] Clean up j...
171
  		bh = gfs2_get_log_desc(sdp, GFS2_LOG_DESC_METADATA);
905d2aefa   Bob Peterson   [GFS2] Move some ...
172
  		gfs2_log_lock(sdp);
16615be18   Steven Whitehouse   [GFS2] Clean up j...
173
174
  		ld = bh_log_desc(bh);
  		ptr = bh_log_ptr(bh);
b3b94faa5   David Teigland   [GFS2] The core o...
175
176
  		ld->ld_length = cpu_to_be32(num + 1);
  		ld->ld_data1 = cpu_to_be32(num);
b3b94faa5   David Teigland   [GFS2] The core o...
177
178
  
  		n = 0;
568f4c965   Steven Whitehouse   [GFS2] 80 Column ...
179
180
  		list_for_each_entry_continue(bd1, &sdp->sd_log_le_buf,
  					     bd_le.le_list) {
b3b94faa5   David Teigland   [GFS2] The core o...
181
182
183
184
  			*ptr++ = cpu_to_be64(bd1->bd_bh->b_blocknr);
  			if (++n >= num)
  				break;
  		}
905d2aefa   Bob Peterson   [GFS2] Move some ...
185
  		gfs2_log_unlock(sdp);
16615be18   Steven Whitehouse   [GFS2] Clean up j...
186
  		submit_bh(WRITE, bh);
905d2aefa   Bob Peterson   [GFS2] Move some ...
187
  		gfs2_log_lock(sdp);
b3b94faa5   David Teigland   [GFS2] The core o...
188
189
  
  		n = 0;
568f4c965   Steven Whitehouse   [GFS2] 80 Column ...
190
191
  		list_for_each_entry_continue(bd2, &sdp->sd_log_le_buf,
  					     bd_le.le_list) {
16615be18   Steven Whitehouse   [GFS2] Clean up j...
192
  			get_bh(bd2->bd_bh);
905d2aefa   Bob Peterson   [GFS2] Move some ...
193
  			gfs2_log_unlock(sdp);
16615be18   Steven Whitehouse   [GFS2] Clean up j...
194
  			lock_buffer(bd2->bd_bh);
b3b94faa5   David Teigland   [GFS2] The core o...
195
  			bh = gfs2_log_fake_buf(sdp, bd2->bd_bh);
16615be18   Steven Whitehouse   [GFS2] Clean up j...
196
  			submit_bh(WRITE, bh);
905d2aefa   Bob Peterson   [GFS2] Move some ...
197
  			gfs2_log_lock(sdp);
b3b94faa5   David Teigland   [GFS2] The core o...
198
199
200
  			if (++n >= num)
  				break;
  		}
905d2aefa   Bob Peterson   [GFS2] Move some ...
201
  		BUG_ON(total < num);
b3b94faa5   David Teigland   [GFS2] The core o...
202
203
  		total -= num;
  	}
905d2aefa   Bob Peterson   [GFS2] Move some ...
204
  	gfs2_log_unlock(sdp);
b3b94faa5   David Teigland   [GFS2] The core o...
205
206
207
208
209
210
211
212
213
214
215
  }
  
  static void buf_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_ail *ai)
  {
  	struct list_head *head = &sdp->sd_log_le_buf;
  	struct gfs2_bufdata *bd;
  
  	while (!list_empty(head)) {
  		bd = list_entry(head->next, struct gfs2_bufdata, bd_le.le_list);
  		list_del_init(&bd->bd_le.le_list);
  		sdp->sd_log_num_buf--;
a98ab2204   Steven Whitehouse   [GFS2] Rename gfs...
216
  		gfs2_unpin(sdp, bd->bd_bh, ai);
b3b94faa5   David Teigland   [GFS2] The core o...
217
218
219
220
221
  	}
  	gfs2_assert_warn(sdp, !sdp->sd_log_num_buf);
  }
  
  static void buf_lo_before_scan(struct gfs2_jdesc *jd,
551676226   Al Viro   [GFS2] split and ...
222
  			       struct gfs2_log_header_host *head, int pass)
b3b94faa5   David Teigland   [GFS2] The core o...
223
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
224
  	struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
b3b94faa5   David Teigland   [GFS2] The core o...
225
226
227
228
229
230
231
232
233
234
235
236
  
  	if (pass != 0)
  		return;
  
  	sdp->sd_found_blocks = 0;
  	sdp->sd_replayed_blocks = 0;
  }
  
  static int buf_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start,
  				struct gfs2_log_descriptor *ld, __be64 *ptr,
  				int pass)
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
237
238
  	struct gfs2_inode *ip = GFS2_I(jd->jd_inode);
  	struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
239
  	struct gfs2_glock *gl = ip->i_gl;
b3b94faa5   David Teigland   [GFS2] The core o...
240
241
  	unsigned int blks = be32_to_cpu(ld->ld_data1);
  	struct buffer_head *bh_log, *bh_ip;
cd915493f   Steven Whitehouse   [GFS2] Change all...
242
  	u64 blkno;
b3b94faa5   David Teigland   [GFS2] The core o...
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
  	int error = 0;
  
  	if (pass != 1 || be32_to_cpu(ld->ld_type) != GFS2_LOG_DESC_METADATA)
  		return 0;
  
  	gfs2_replay_incr_blk(sdp, &start);
  
  	for (; blks; gfs2_replay_incr_blk(sdp, &start), blks--) {
  		blkno = be64_to_cpu(*ptr++);
  
  		sdp->sd_found_blocks++;
  
  		if (gfs2_revoke_check(sdp, blkno, start))
  			continue;
  
  		error = gfs2_replay_read_block(jd, start, &bh_log);
82ffa5163   Steven Whitehouse   [GFS2] More style...
259
260
  		if (error)
  			return error;
b3b94faa5   David Teigland   [GFS2] The core o...
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
  
  		bh_ip = gfs2_meta_new(gl, blkno);
  		memcpy(bh_ip->b_data, bh_log->b_data, bh_log->b_size);
  
  		if (gfs2_meta_check(sdp, bh_ip))
  			error = -EIO;
  		else
  			mark_buffer_dirty(bh_ip);
  
  		brelse(bh_log);
  		brelse(bh_ip);
  
  		if (error)
  			break;
  
  		sdp->sd_replayed_blocks++;
  	}
  
  	return error;
  }
  
  static void buf_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass)
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
284
285
  	struct gfs2_inode *ip = GFS2_I(jd->jd_inode);
  	struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
b3b94faa5   David Teigland   [GFS2] The core o...
286
287
  
  	if (error) {
7276b3b0c   Steven Whitehouse   [GFS2] Tidy up me...
288
  		gfs2_meta_sync(ip->i_gl);
b3b94faa5   David Teigland   [GFS2] The core o...
289
290
291
292
  		return;
  	}
  	if (pass != 1)
  		return;
7276b3b0c   Steven Whitehouse   [GFS2] Tidy up me...
293
  	gfs2_meta_sync(ip->i_gl);
b3b94faa5   David Teigland   [GFS2] The core o...
294
295
296
297
298
299
300
301
302
  
  	fs_info(sdp, "jid=%u: Replayed %u of %u blocks
  ",
  	        jd->jd_jid, sdp->sd_replayed_blocks, sdp->sd_found_blocks);
  }
  
  static void revoke_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le)
  {
  	struct gfs2_trans *tr;
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
303
  	tr = current->journal_info;
b3b94faa5   David Teigland   [GFS2] The core o...
304
305
  	tr->tr_touched = 1;
  	tr->tr_num_revoke++;
b3b94faa5   David Teigland   [GFS2] The core o...
306
307
  	sdp->sd_log_num_revoke++;
  	list_add(&le->le_list, &sdp->sd_log_le_revoke);
b3b94faa5   David Teigland   [GFS2] The core o...
308
309
310
311
312
313
314
315
316
  }
  
  static void revoke_lo_before_commit(struct gfs2_sbd *sdp)
  {
  	struct gfs2_log_descriptor *ld;
  	struct gfs2_meta_header *mh;
  	struct buffer_head *bh;
  	unsigned int offset;
  	struct list_head *head = &sdp->sd_log_le_revoke;
82e86087b   Steven Whitehouse   [GFS2] Replace re...
317
  	struct gfs2_bufdata *bd;
b3b94faa5   David Teigland   [GFS2] The core o...
318
319
320
  
  	if (!sdp->sd_log_num_revoke)
  		return;
16615be18   Steven Whitehouse   [GFS2] Clean up j...
321
322
  	bh = gfs2_get_log_desc(sdp, GFS2_LOG_DESC_REVOKE);
  	ld = bh_log_desc(bh);
568f4c965   Steven Whitehouse   [GFS2] 80 Column ...
323
  	ld->ld_length = cpu_to_be32(gfs2_struct2blk(sdp, sdp->sd_log_num_revoke,
cd915493f   Steven Whitehouse   [GFS2] Change all...
324
  						    sizeof(u64)));
b3b94faa5   David Teigland   [GFS2] The core o...
325
  	ld->ld_data1 = cpu_to_be32(sdp->sd_log_num_revoke);
b3b94faa5   David Teigland   [GFS2] The core o...
326
327
328
  	offset = sizeof(struct gfs2_log_descriptor);
  
  	while (!list_empty(head)) {
82e86087b   Steven Whitehouse   [GFS2] Replace re...
329
330
  		bd = list_entry(head->next, struct gfs2_bufdata, bd_le.le_list);
  		list_del_init(&bd->bd_le.le_list);
b3b94faa5   David Teigland   [GFS2] The core o...
331
  		sdp->sd_log_num_revoke--;
cd915493f   Steven Whitehouse   [GFS2] Change all...
332
  		if (offset + sizeof(u64) > sdp->sd_sb.sb_bsize) {
16615be18   Steven Whitehouse   [GFS2] Clean up j...
333
  			submit_bh(WRITE, bh);
b3b94faa5   David Teigland   [GFS2] The core o...
334
335
336
337
  
  			bh = gfs2_log_get_buf(sdp);
  			mh = (struct gfs2_meta_header *)bh->b_data;
  			mh->mh_magic = cpu_to_be32(GFS2_MAGIC);
e3167ded1   Steven Whitehouse   [GFS] Fix bug in ...
338
339
  			mh->mh_type = cpu_to_be32(GFS2_METATYPE_LB);
  			mh->mh_format = cpu_to_be32(GFS2_FORMAT_LB);
b3b94faa5   David Teigland   [GFS2] The core o...
340
341
  			offset = sizeof(struct gfs2_meta_header);
  		}
82e86087b   Steven Whitehouse   [GFS2] Replace re...
342
  		*(__be64 *)(bh->b_data + offset) = cpu_to_be64(bd->bd_blkno);
0820ab517   Steven Whitehouse   [GFS2] Use slab o...
343
  		kmem_cache_free(gfs2_bufdata_cachep, bd);
b3b94faa5   David Teigland   [GFS2] The core o...
344

cd915493f   Steven Whitehouse   [GFS2] Change all...
345
  		offset += sizeof(u64);
b3b94faa5   David Teigland   [GFS2] The core o...
346
347
  	}
  	gfs2_assert_withdraw(sdp, !sdp->sd_log_num_revoke);
16615be18   Steven Whitehouse   [GFS2] Clean up j...
348
  	submit_bh(WRITE, bh);
b3b94faa5   David Teigland   [GFS2] The core o...
349
350
351
  }
  
  static void revoke_lo_before_scan(struct gfs2_jdesc *jd,
551676226   Al Viro   [GFS2] split and ...
352
  				  struct gfs2_log_header_host *head, int pass)
b3b94faa5   David Teigland   [GFS2] The core o...
353
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
354
  	struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
b3b94faa5   David Teigland   [GFS2] The core o...
355
356
357
358
359
360
361
362
363
364
365
366
  
  	if (pass != 0)
  		return;
  
  	sdp->sd_found_revokes = 0;
  	sdp->sd_replay_tail = head->lh_tail;
  }
  
  static int revoke_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start,
  				   struct gfs2_log_descriptor *ld, __be64 *ptr,
  				   int pass)
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
367
  	struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
b3b94faa5   David Teigland   [GFS2] The core o...
368
369
370
371
  	unsigned int blks = be32_to_cpu(ld->ld_length);
  	unsigned int revokes = be32_to_cpu(ld->ld_data1);
  	struct buffer_head *bh;
  	unsigned int offset;
cd915493f   Steven Whitehouse   [GFS2] Change all...
372
  	u64 blkno;
b3b94faa5   David Teigland   [GFS2] The core o...
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
  	int first = 1;
  	int error;
  
  	if (pass != 0 || be32_to_cpu(ld->ld_type) != GFS2_LOG_DESC_REVOKE)
  		return 0;
  
  	offset = sizeof(struct gfs2_log_descriptor);
  
  	for (; blks; gfs2_replay_incr_blk(sdp, &start), blks--) {
  		error = gfs2_replay_read_block(jd, start, &bh);
  		if (error)
  			return error;
  
  		if (!first)
  			gfs2_metatype_check(sdp, bh, GFS2_METATYPE_LB);
cd915493f   Steven Whitehouse   [GFS2] Change all...
388
  		while (offset + sizeof(u64) <= sdp->sd_sb.sb_bsize) {
b3b94faa5   David Teigland   [GFS2] The core o...
389
390
391
  			blkno = be64_to_cpu(*(__be64 *)(bh->b_data + offset));
  
  			error = gfs2_revoke_add(sdp, blkno, start);
3ad62e87c   Bob Peterson   [GFS2] Plug an un...
392
393
  			if (error < 0) {
  				brelse(bh);
b3b94faa5   David Teigland   [GFS2] The core o...
394
  				return error;
3ad62e87c   Bob Peterson   [GFS2] Plug an un...
395
  			}
b3b94faa5   David Teigland   [GFS2] The core o...
396
397
398
399
400
  			else if (error)
  				sdp->sd_found_revokes++;
  
  			if (!--revokes)
  				break;
cd915493f   Steven Whitehouse   [GFS2] Change all...
401
  			offset += sizeof(u64);
b3b94faa5   David Teigland   [GFS2] The core o...
402
403
404
405
406
407
408
409
410
411
412
413
  		}
  
  		brelse(bh);
  		offset = sizeof(struct gfs2_meta_header);
  		first = 0;
  	}
  
  	return 0;
  }
  
  static void revoke_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass)
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
414
  	struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
b3b94faa5   David Teigland   [GFS2] The core o...
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
  
  	if (error) {
  		gfs2_revoke_clean(sdp);
  		return;
  	}
  	if (pass != 1)
  		return;
  
  	fs_info(sdp, "jid=%u: Found %u revoke tags
  ",
  	        jd->jd_jid, sdp->sd_found_revokes);
  
  	gfs2_revoke_clean(sdp);
  }
  
  static void rg_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le)
  {
  	struct gfs2_rgrpd *rgd;
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
433
  	struct gfs2_trans *tr = current->journal_info;
b3b94faa5   David Teigland   [GFS2] The core o...
434

5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
435
  	tr->tr_touched = 1;
b3b94faa5   David Teigland   [GFS2] The core o...
436

b3b94faa5   David Teigland   [GFS2] The core o...
437
  	rgd = container_of(le, struct gfs2_rgrpd, rd_le);
b3b94faa5   David Teigland   [GFS2] The core o...
438
439
  
  	gfs2_log_lock(sdp);
688356258   Benjamin Marzinski   [GFS2] Fix log en...
440
441
442
443
444
  	if (!list_empty(&le->le_list)){
  		gfs2_log_unlock(sdp);
  		return;
  	}
  	gfs2_rgrp_bh_hold(rgd);
b3b94faa5   David Teigland   [GFS2] The core o...
445
446
  	sdp->sd_log_num_rg++;
  	list_add(&le->le_list, &sdp->sd_log_le_rg);
907b9bceb   Steven Whitehouse   [GFS2/DLM] Fix tr...
447
  	gfs2_log_unlock(sdp);
b3b94faa5   David Teigland   [GFS2] The core o...
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
  }
  
  static void rg_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_ail *ai)
  {
  	struct list_head *head = &sdp->sd_log_le_rg;
  	struct gfs2_rgrpd *rgd;
  
  	while (!list_empty(head)) {
  		rgd = list_entry(head->next, struct gfs2_rgrpd, rd_le.le_list);
  		list_del_init(&rgd->rd_le.le_list);
  		sdp->sd_log_num_rg--;
  
  		gfs2_rgrp_repolish_clones(rgd);
  		gfs2_rgrp_bh_put(rgd);
  	}
  	gfs2_assert_warn(sdp, !sdp->sd_log_num_rg);
  }
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
  /**
   * databuf_lo_add - Add a databuf to the transaction.
   *
   * This is used in two distinct cases:
   * i) In ordered write mode
   *    We put the data buffer on a list so that we can ensure that its
   *    synced to disk at the right time
   * ii) In journaled data mode
   *    We need to journal the data block in the same way as metadata in
   *    the functions above. The difference is that here we have a tag
   *    which is two __be64's being the block number (as per meta data)
   *    and a flag which says whether the data block needs escaping or
   *    not. This means we need a new log entry for each 251 or so data
   *    blocks, which isn't an enormous overhead but twice as much as
   *    for normal metadata blocks.
   */
b3b94faa5   David Teigland   [GFS2] The core o...
481
482
  static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le)
  {
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
483
  	struct gfs2_bufdata *bd = container_of(le, struct gfs2_bufdata, bd_le);
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
484
  	struct gfs2_trans *tr = current->journal_info;
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
485
  	struct address_space *mapping = bd->bd_bh->b_page->mapping;
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
486
  	struct gfs2_inode *ip = GFS2_I(mapping->host);
b3b94faa5   David Teigland   [GFS2] The core o...
487

9b9107a5a   Steven Whitehouse   [GFS2] Move pin/u...
488
  	lock_buffer(bd->bd_bh);
8bd957276   Steven Whitehouse   [GFS2] Fix list c...
489
  	gfs2_log_lock(sdp);
9ff8ec32e   Steven Whitehouse   [GFS2] Split gfs2...
490
491
492
493
494
495
496
497
  	if (tr) {
  		if (!list_empty(&bd->bd_list_tr))
  			goto out;
  		tr->tr_touched = 1;
  		if (gfs2_is_jdata(ip)) {
  			tr->tr_num_buf++;
  			list_add(&bd->bd_list_tr, &tr->tr_list_buf);
  		}
773ed1a04   Robert Peterson   [GFS2] Addendum t...
498
  	}
2332c4435   Robert Peterson   [GFS2] assertion ...
499
  	if (!list_empty(&le->le_list))
9b9107a5a   Steven Whitehouse   [GFS2] Move pin/u...
500
  		goto out;
2332c4435   Robert Peterson   [GFS2] assertion ...
501

2bcd610d2   Steven Whitehouse   [GFS2] Don't add ...
502
503
  	set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags);
  	set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags);
2332c4435   Robert Peterson   [GFS2] assertion ...
504
  	if (gfs2_is_jdata(ip)) {
2332c4435   Robert Peterson   [GFS2] assertion ...
505
506
  		gfs2_pin(sdp, bd->bd_bh);
  		tr->tr_num_databuf_new++;
d7b616e25   Steven Whitehouse   [GFS2] Clean up o...
507
508
509
510
  		sdp->sd_log_num_databuf++;
  		list_add(&le->le_list, &sdp->sd_log_le_databuf);
  	} else {
  		list_add(&le->le_list, &sdp->sd_log_le_ordered);
9b9107a5a   Steven Whitehouse   [GFS2] Move pin/u...
511
  	}
9b9107a5a   Steven Whitehouse   [GFS2] Move pin/u...
512
  out:
b3b94faa5   David Teigland   [GFS2] The core o...
513
  	gfs2_log_unlock(sdp);
9b9107a5a   Steven Whitehouse   [GFS2] Move pin/u...
514
  	unlock_buffer(bd->bd_bh);
b3b94faa5   David Teigland   [GFS2] The core o...
515
  }
16615be18   Steven Whitehouse   [GFS2] Clean up j...
516
  static void gfs2_check_magic(struct buffer_head *bh)
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
517
  {
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
518
519
  	void *kaddr;
  	__be32 *ptr;
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
520

16615be18   Steven Whitehouse   [GFS2] Clean up j...
521
522
  	clear_buffer_escaped(bh);
  	kaddr = kmap_atomic(bh->b_page, KM_USER0);
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
523
524
  	ptr = kaddr + bh_offset(bh);
  	if (*ptr == cpu_to_be32(GFS2_MAGIC))
16615be18   Steven Whitehouse   [GFS2] Clean up j...
525
  		set_buffer_escaped(bh);
c312c4fdc   Russell Cattelan   [GFS2] Pass the c...
526
  	kunmap_atomic(kaddr, KM_USER0);
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
527
  }
16615be18   Steven Whitehouse   [GFS2] Clean up j...
528
529
530
  static void gfs2_write_blocks(struct gfs2_sbd *sdp, struct buffer_head *bh,
  			      struct list_head *list, struct list_head *done,
  			      unsigned int n)
b3b94faa5   David Teigland   [GFS2] The core o...
531
  {
16615be18   Steven Whitehouse   [GFS2] Clean up j...
532
  	struct buffer_head *bh1;
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
533
  	struct gfs2_log_descriptor *ld;
16615be18   Steven Whitehouse   [GFS2] Clean up j...
534
535
  	struct gfs2_bufdata *bd;
  	__be64 *ptr;
d7b616e25   Steven Whitehouse   [GFS2] Clean up o...
536

16615be18   Steven Whitehouse   [GFS2] Clean up j...
537
538
  	if (!bh)
  		return;
b3b94faa5   David Teigland   [GFS2] The core o...
539

16615be18   Steven Whitehouse   [GFS2] Clean up j...
540
541
542
  	ld = bh_log_desc(bh);
  	ld->ld_length = cpu_to_be32(n + 1);
  	ld->ld_data1 = cpu_to_be32(n);
b3b94faa5   David Teigland   [GFS2] The core o...
543

16615be18   Steven Whitehouse   [GFS2] Clean up j...
544
545
546
547
  	ptr = bh_log_ptr(bh);
  	
  	get_bh(bh);
  	submit_bh(WRITE, bh);
f55ab26a8   Steven Whitehouse   [GFS2] Use mutice...
548
  	gfs2_log_lock(sdp);
16615be18   Steven Whitehouse   [GFS2] Clean up j...
549
550
551
552
553
554
555
  	while(!list_empty(list)) {
  		bd = list_entry(list->next, struct gfs2_bufdata, bd_le.le_list);
  		list_move_tail(&bd->bd_le.le_list, done);
  		get_bh(bd->bd_bh);
  		while (be64_to_cpu(*ptr) != bd->bd_bh->b_blocknr) {
  			gfs2_log_incr_head(sdp);
  			ptr += 2;
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
556
  		}
f55ab26a8   Steven Whitehouse   [GFS2] Use mutice...
557
  		gfs2_log_unlock(sdp);
16615be18   Steven Whitehouse   [GFS2] Clean up j...
558
559
560
561
562
563
564
565
566
567
568
569
570
571
  		lock_buffer(bd->bd_bh);
  		if (buffer_escaped(bd->bd_bh)) {
  			void *kaddr;
  			bh1 = gfs2_log_get_buf(sdp);
  			kaddr = kmap_atomic(bd->bd_bh->b_page, KM_USER0);
  			memcpy(bh1->b_data, kaddr + bh_offset(bd->bd_bh),
  			       bh1->b_size);
  			kunmap_atomic(kaddr, KM_USER0);
  			*(__be32 *)bh1->b_data = 0;
  			clear_buffer_escaped(bd->bd_bh);
  			unlock_buffer(bd->bd_bh);
  			brelse(bd->bd_bh);
  		} else {
  			bh1 = gfs2_log_fake_buf(sdp, bd->bd_bh);
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
572
  		}
16615be18   Steven Whitehouse   [GFS2] Clean up j...
573
  		submit_bh(WRITE, bh1);
f55ab26a8   Steven Whitehouse   [GFS2] Use mutice...
574
  		gfs2_log_lock(sdp);
16615be18   Steven Whitehouse   [GFS2] Clean up j...
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
  		ptr += 2;
  	}
  	gfs2_log_unlock(sdp);
  	brelse(bh);
  }
  
  /**
   * databuf_lo_before_commit - Scan the data buffers, writing as we go
   *
   */
  
  static void databuf_lo_before_commit(struct gfs2_sbd *sdp)
  {
  	struct gfs2_bufdata *bd = NULL;
  	struct buffer_head *bh = NULL;
  	unsigned int n = 0;
  	__be64 *ptr = NULL, *end = NULL;
  	LIST_HEAD(processed);
  	LIST_HEAD(in_progress);
  
  	gfs2_log_lock(sdp);
  	while (!list_empty(&sdp->sd_log_le_databuf)) {
  		if (ptr == end) {
f55ab26a8   Steven Whitehouse   [GFS2] Use mutice...
598
  			gfs2_log_unlock(sdp);
16615be18   Steven Whitehouse   [GFS2] Clean up j...
599
600
601
602
603
  			gfs2_write_blocks(sdp, bh, &in_progress, &processed, n);
  			n = 0;
  			bh = gfs2_get_log_desc(sdp, GFS2_LOG_DESC_JDATA);
  			ptr = bh_log_ptr(bh);
  			end = bh_ptr_end(bh) - 1;
f55ab26a8   Steven Whitehouse   [GFS2] Use mutice...
604
  			gfs2_log_lock(sdp);
16615be18   Steven Whitehouse   [GFS2] Clean up j...
605
  			continue;
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
606
  		}
16615be18   Steven Whitehouse   [GFS2] Clean up j...
607
608
609
610
611
612
  		bd = list_entry(sdp->sd_log_le_databuf.next, struct gfs2_bufdata, bd_le.le_list);
  		list_move_tail(&bd->bd_le.le_list, &in_progress);
  		gfs2_check_magic(bd->bd_bh);
  		*ptr++ = cpu_to_be64(bd->bd_bh->b_blocknr);
  		*ptr++ = cpu_to_be64(buffer_escaped(bh) ? 1 : 0);
  		n++;
b3b94faa5   David Teigland   [GFS2] The core o...
613
  	}
f55ab26a8   Steven Whitehouse   [GFS2] Use mutice...
614
  	gfs2_log_unlock(sdp);
16615be18   Steven Whitehouse   [GFS2] Clean up j...
615
616
617
618
  	gfs2_write_blocks(sdp, bh, &in_progress, &processed, n);
  	gfs2_log_lock(sdp);
  	list_splice(&processed, &sdp->sd_log_le_databuf);
  	gfs2_log_unlock(sdp);
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
619
620
621
622
623
624
  }
  
  static int databuf_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start,
  				    struct gfs2_log_descriptor *ld,
  				    __be64 *ptr, int pass)
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
625
626
  	struct gfs2_inode *ip = GFS2_I(jd->jd_inode);
  	struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
627
  	struct gfs2_glock *gl = ip->i_gl;
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
628
629
  	unsigned int blks = be32_to_cpu(ld->ld_data1);
  	struct buffer_head *bh_log, *bh_ip;
cd915493f   Steven Whitehouse   [GFS2] Change all...
630
631
  	u64 blkno;
  	u64 esc;
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
  	int error = 0;
  
  	if (pass != 1 || be32_to_cpu(ld->ld_type) != GFS2_LOG_DESC_JDATA)
  		return 0;
  
  	gfs2_replay_incr_blk(sdp, &start);
  	for (; blks; gfs2_replay_incr_blk(sdp, &start), blks--) {
  		blkno = be64_to_cpu(*ptr++);
  		esc = be64_to_cpu(*ptr++);
  
  		sdp->sd_found_blocks++;
  
  		if (gfs2_revoke_check(sdp, blkno, start))
  			continue;
  
  		error = gfs2_replay_read_block(jd, start, &bh_log);
  		if (error)
  			return error;
  
  		bh_ip = gfs2_meta_new(gl, blkno);
  		memcpy(bh_ip->b_data, bh_log->b_data, bh_log->b_size);
  
  		/* Unescape */
  		if (esc) {
  			__be32 *eptr = (__be32 *)bh_ip->b_data;
  			*eptr = cpu_to_be32(GFS2_MAGIC);
  		}
  		mark_buffer_dirty(bh_ip);
  
  		brelse(bh_log);
  		brelse(bh_ip);
  		if (error)
  			break;
  
  		sdp->sd_replayed_blocks++;
  	}
  
  	return error;
  }
  
  /* FIXME: sort out accounting for log blocks etc. */
  
  static void databuf_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass)
  {
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
676
677
  	struct gfs2_inode *ip = GFS2_I(jd->jd_inode);
  	struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
678
679
  
  	if (error) {
7276b3b0c   Steven Whitehouse   [GFS2] Tidy up me...
680
  		gfs2_meta_sync(ip->i_gl);
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
681
682
683
684
685
686
  		return;
  	}
  	if (pass != 1)
  		return;
  
  	/* data sync? */
7276b3b0c   Steven Whitehouse   [GFS2] Tidy up me...
687
  	gfs2_meta_sync(ip->i_gl);
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
688
689
690
691
692
693
694
695
696
697
698
699
700
  
  	fs_info(sdp, "jid=%u: Replayed %u of %u data blocks
  ",
  		jd->jd_jid, sdp->sd_replayed_blocks, sdp->sd_found_blocks);
  }
  
  static void databuf_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_ail *ai)
  {
  	struct list_head *head = &sdp->sd_log_le_databuf;
  	struct gfs2_bufdata *bd;
  
  	while (!list_empty(head)) {
  		bd = list_entry(head->next, struct gfs2_bufdata, bd_le.le_list);
b8e1aabf2   Steven Whitehouse   [GFS2] Another li...
701
  		list_del_init(&bd->bd_le.le_list);
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
702
  		sdp->sd_log_num_databuf--;
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
703
  		gfs2_unpin(sdp, bd->bd_bh, ai);
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
704
  	}
b3b94faa5   David Teigland   [GFS2] The core o...
705
706
  	gfs2_assert_warn(sdp, !sdp->sd_log_num_databuf);
  }
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
707

b09e593d7   Steven Whitehouse   [GFS2] Fix a ref ...
708
  const struct gfs2_log_operations gfs2_buf_lops = {
b3b94faa5   David Teigland   [GFS2] The core o...
709
  	.lo_add = buf_lo_add,
b3b94faa5   David Teigland   [GFS2] The core o...
710
711
712
713
714
  	.lo_before_commit = buf_lo_before_commit,
  	.lo_after_commit = buf_lo_after_commit,
  	.lo_before_scan = buf_lo_before_scan,
  	.lo_scan_elements = buf_lo_scan_elements,
  	.lo_after_scan = buf_lo_after_scan,
ea67eedb2   Steven Whitehouse   [GFS2] Fix end of...
715
  	.lo_name = "buf",
b3b94faa5   David Teigland   [GFS2] The core o...
716
  };
b09e593d7   Steven Whitehouse   [GFS2] Fix a ref ...
717
  const struct gfs2_log_operations gfs2_revoke_lops = {
b3b94faa5   David Teigland   [GFS2] The core o...
718
719
720
721
722
  	.lo_add = revoke_lo_add,
  	.lo_before_commit = revoke_lo_before_commit,
  	.lo_before_scan = revoke_lo_before_scan,
  	.lo_scan_elements = revoke_lo_scan_elements,
  	.lo_after_scan = revoke_lo_after_scan,
ea67eedb2   Steven Whitehouse   [GFS2] Fix end of...
723
  	.lo_name = "revoke",
b3b94faa5   David Teigland   [GFS2] The core o...
724
  };
b09e593d7   Steven Whitehouse   [GFS2] Fix a ref ...
725
  const struct gfs2_log_operations gfs2_rg_lops = {
b3b94faa5   David Teigland   [GFS2] The core o...
726
727
  	.lo_add = rg_lo_add,
  	.lo_after_commit = rg_lo_after_commit,
ea67eedb2   Steven Whitehouse   [GFS2] Fix end of...
728
  	.lo_name = "rg",
b3b94faa5   David Teigland   [GFS2] The core o...
729
  };
b09e593d7   Steven Whitehouse   [GFS2] Fix a ref ...
730
  const struct gfs2_log_operations gfs2_databuf_lops = {
b3b94faa5   David Teigland   [GFS2] The core o...
731
732
  	.lo_add = databuf_lo_add,
  	.lo_before_commit = databuf_lo_before_commit,
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
733
734
735
  	.lo_after_commit = databuf_lo_after_commit,
  	.lo_scan_elements = databuf_lo_scan_elements,
  	.lo_after_scan = databuf_lo_after_scan,
ea67eedb2   Steven Whitehouse   [GFS2] Fix end of...
736
  	.lo_name = "databuf",
b3b94faa5   David Teigland   [GFS2] The core o...
737
  };
b09e593d7   Steven Whitehouse   [GFS2] Fix a ref ...
738
  const struct gfs2_log_operations *gfs2_log_ops[] = {
16615be18   Steven Whitehouse   [GFS2] Clean up j...
739
  	&gfs2_databuf_lops,
b3b94faa5   David Teigland   [GFS2] The core o...
740
  	&gfs2_buf_lops,
b3b94faa5   David Teigland   [GFS2] The core o...
741
  	&gfs2_rg_lops,
16615be18   Steven Whitehouse   [GFS2] Clean up j...
742
  	&gfs2_revoke_lops,
ea67eedb2   Steven Whitehouse   [GFS2] Fix end of...
743
  	NULL,
b3b94faa5   David Teigland   [GFS2] The core o...
744
  };