Blame view

fs/gfs2/log.c 24.8 KB
b3b94faa5   David Teigland   [GFS2] The core o...
1
2
  /*
   * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
da6dd40d5   Bob Peterson   [GFS2] Journal ex...
3
   * Copyright (C) 2004-2007 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>
71b86f562   Steven Whitehouse   [GFS2] Further up...
16
  #include <linux/crc32.h>
a25311c8e   Steven Whitehouse   [GFS2] Move gfs2_...
17
  #include <linux/delay.h>
ec69b1888   Steven Whitehouse   [GFS2] Move gfs2_...
18
19
  #include <linux/kthread.h>
  #include <linux/freezer.h>
254db57f9   Steven Whitehouse   GFS2: Support for...
20
  #include <linux/bio.h>
4667a0ec3   Steven Whitehouse   GFS2: Make writeb...
21
  #include <linux/writeback.h>
b3b94faa5   David Teigland   [GFS2] The core o...
22
23
  
  #include "gfs2.h"
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
24
  #include "incore.h"
b3b94faa5   David Teigland   [GFS2] The core o...
25
26
27
28
29
  #include "bmap.h"
  #include "glock.h"
  #include "log.h"
  #include "lops.h"
  #include "meta_io.h"
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
30
  #include "util.h"
71b86f562   Steven Whitehouse   [GFS2] Further up...
31
  #include "dir.h"
63997775b   Steven Whitehouse   GFS2: Add tracepo...
32
  #include "trace_gfs2.h"
b3b94faa5   David Teigland   [GFS2] The core o...
33
34
  
  #define PULL 1
b3b94faa5   David Teigland   [GFS2] The core o...
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
  /**
   * gfs2_struct2blk - compute stuff
   * @sdp: the filesystem
   * @nstruct: the number of structures
   * @ssize: the size of the structures
   *
   * Compute the number of log descriptor blocks needed to hold a certain number
   * of structures of a certain size.
   *
   * Returns: the number of blocks needed (minimum is always 1)
   */
  
  unsigned int gfs2_struct2blk(struct gfs2_sbd *sdp, unsigned int nstruct,
  			     unsigned int ssize)
  {
  	unsigned int blks;
  	unsigned int first, second;
  
  	blks = 1;
faa31ce85   Steven Whitehouse   [GFS2] Tidy up log.c
54
  	first = (sdp->sd_sb.sb_bsize - sizeof(struct gfs2_log_descriptor)) / ssize;
b3b94faa5   David Teigland   [GFS2] The core o...
55
56
  
  	if (nstruct > first) {
568f4c965   Steven Whitehouse   [GFS2] 80 Column ...
57
58
  		second = (sdp->sd_sb.sb_bsize -
  			  sizeof(struct gfs2_meta_header)) / ssize;
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
59
  		blks += DIV_ROUND_UP(nstruct - first, second);
b3b94faa5   David Teigland   [GFS2] The core o...
60
61
62
63
  	}
  
  	return blks;
  }
ddacfaf76   Steven Whitehouse   [GFS2] Move loggi...
64
  /**
1e1a3d03e   Steven Whitehouse   [GFS2] Introduce ...
65
66
67
68
   * gfs2_remove_from_ail - Remove an entry from the ail lists, updating counters
   * @mapping: The associated mapping (maybe NULL)
   * @bd: The gfs2_bufdata to remove
   *
c618e87a5   Steven Whitehouse   GFS2: Update to A...
69
   * The ail lock _must_ be held when calling this function
1e1a3d03e   Steven Whitehouse   [GFS2] Introduce ...
70
71
   *
   */
f91a0d3e2   Steven Whitehouse   [GFS2] Remove use...
72
  void gfs2_remove_from_ail(struct gfs2_bufdata *bd)
1e1a3d03e   Steven Whitehouse   [GFS2] Introduce ...
73
74
  {
  	bd->bd_ail = NULL;
1ad38c437   Steven Whitehouse   [GFS2] Clean up g...
75
76
  	list_del_init(&bd->bd_ail_st_list);
  	list_del_init(&bd->bd_ail_gl_list);
1e1a3d03e   Steven Whitehouse   [GFS2] Introduce ...
77
  	atomic_dec(&bd->bd_gl->gl_ail_count);
1e1a3d03e   Steven Whitehouse   [GFS2] Introduce ...
78
79
80
81
  	brelse(bd->bd_bh);
  }
  
  /**
ddacfaf76   Steven Whitehouse   [GFS2] Move loggi...
82
83
   * gfs2_ail1_start_one - Start I/O on a part of the AIL
   * @sdp: the filesystem
4667a0ec3   Steven Whitehouse   GFS2: Make writeb...
84
85
   * @wbc: The writeback control structure
   * @ai: The ail structure
ddacfaf76   Steven Whitehouse   [GFS2] Move loggi...
86
87
   *
   */
4f1de0182   Steven Whitehouse   GFS2: Fix ail lis...
88
89
90
  static int gfs2_ail1_start_one(struct gfs2_sbd *sdp,
  			       struct writeback_control *wbc,
  			       struct gfs2_ail *ai)
d6a079e82   Dave Chinner   GFS2: introduce A...
91
92
  __releases(&sdp->sd_ail_lock)
  __acquires(&sdp->sd_ail_lock)
ddacfaf76   Steven Whitehouse   [GFS2] Move loggi...
93
  {
5ac048bb7   Steven Whitehouse   GFS2: Use filemap...
94
  	struct gfs2_glock *gl = NULL;
4667a0ec3   Steven Whitehouse   GFS2: Make writeb...
95
  	struct address_space *mapping;
ddacfaf76   Steven Whitehouse   [GFS2] Move loggi...
96
97
  	struct gfs2_bufdata *bd, *s;
  	struct buffer_head *bh;
ddacfaf76   Steven Whitehouse   [GFS2] Move loggi...
98

4667a0ec3   Steven Whitehouse   GFS2: Make writeb...
99
100
  	list_for_each_entry_safe_reverse(bd, s, &ai->ai_ail1_list, bd_ail_st_list) {
  		bh = bd->bd_bh;
ddacfaf76   Steven Whitehouse   [GFS2] Move loggi...
101

4667a0ec3   Steven Whitehouse   GFS2: Make writeb...
102
  		gfs2_assert(sdp, bd->bd_ail == ai);
ddacfaf76   Steven Whitehouse   [GFS2] Move loggi...
103

4667a0ec3   Steven Whitehouse   GFS2: Make writeb...
104
105
106
107
108
109
110
111
112
113
114
115
116
117
  		if (!buffer_busy(bh)) {
  			if (!buffer_uptodate(bh))
  				gfs2_io_error_bh(sdp, bh);
  			list_move(&bd->bd_ail_st_list, &ai->ai_ail2_list);
  			continue;
  		}
  
  		if (!buffer_dirty(bh))
  			continue;
  		if (gl == bd->bd_gl)
  			continue;
  		gl = bd->bd_gl;
  		list_move(&bd->bd_ail_st_list, &ai->ai_ail1_list);
  		mapping = bh->b_page->mapping;
4f1de0182   Steven Whitehouse   GFS2: Fix ail lis...
118
119
  		if (!mapping)
  			continue;
4667a0ec3   Steven Whitehouse   GFS2: Make writeb...
120
121
122
123
124
  		spin_unlock(&sdp->sd_ail_lock);
  		generic_writepages(mapping, wbc);
  		spin_lock(&sdp->sd_ail_lock);
  		if (wbc->nr_to_write <= 0)
  			break;
4f1de0182   Steven Whitehouse   GFS2: Fix ail lis...
125
  		return 1;
4667a0ec3   Steven Whitehouse   GFS2: Make writeb...
126
  	}
4f1de0182   Steven Whitehouse   GFS2: Fix ail lis...
127
128
  
  	return 0;
4667a0ec3   Steven Whitehouse   GFS2: Make writeb...
129
  }
ddacfaf76   Steven Whitehouse   [GFS2] Move loggi...
130

ddacfaf76   Steven Whitehouse   [GFS2] Move loggi...
131

4667a0ec3   Steven Whitehouse   GFS2: Make writeb...
132
133
134
135
136
137
138
139
  /**
   * gfs2_ail1_flush - start writeback of some ail1 entries 
   * @sdp: The super block
   * @wbc: The writeback control structure
   *
   * Writes back some ail1 entries, according to the limits in the
   * writeback control structure
   */
ddacfaf76   Steven Whitehouse   [GFS2] Move loggi...
140

4667a0ec3   Steven Whitehouse   GFS2: Make writeb...
141
142
143
144
  void gfs2_ail1_flush(struct gfs2_sbd *sdp, struct writeback_control *wbc)
  {
  	struct list_head *head = &sdp->sd_ail1_list;
  	struct gfs2_ail *ai;
ddacfaf76   Steven Whitehouse   [GFS2] Move loggi...
145

c83ae9cad   Steven Whitehouse   GFS2: Add an AIL ...
146
  	trace_gfs2_ail_flush(sdp, wbc, 1);
4667a0ec3   Steven Whitehouse   GFS2: Make writeb...
147
  	spin_lock(&sdp->sd_ail_lock);
4f1de0182   Steven Whitehouse   GFS2: Fix ail lis...
148
  restart:
4667a0ec3   Steven Whitehouse   GFS2: Make writeb...
149
150
  	list_for_each_entry_reverse(ai, head, ai_list) {
  		if (wbc->nr_to_write <= 0)
ddacfaf76   Steven Whitehouse   [GFS2] Move loggi...
151
  			break;
4f1de0182   Steven Whitehouse   GFS2: Fix ail lis...
152
153
  		if (gfs2_ail1_start_one(sdp, wbc, ai))
  			goto restart;
4667a0ec3   Steven Whitehouse   GFS2: Make writeb...
154
155
  	}
  	spin_unlock(&sdp->sd_ail_lock);
c83ae9cad   Steven Whitehouse   GFS2: Add an AIL ...
156
  	trace_gfs2_ail_flush(sdp, wbc, 0);
4667a0ec3   Steven Whitehouse   GFS2: Make writeb...
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
  }
  
  /**
   * gfs2_ail1_start - start writeback of all ail1 entries
   * @sdp: The superblock
   */
  
  static void gfs2_ail1_start(struct gfs2_sbd *sdp)
  {
  	struct writeback_control wbc = {
  		.sync_mode = WB_SYNC_NONE,
  		.nr_to_write = LONG_MAX,
  		.range_start = 0,
  		.range_end = LLONG_MAX,
  	};
  
  	return gfs2_ail1_flush(sdp, &wbc);
ddacfaf76   Steven Whitehouse   [GFS2] Move loggi...
174
175
176
177
178
179
180
181
  }
  
  /**
   * gfs2_ail1_empty_one - Check whether or not a trans in the AIL has been synced
   * @sdp: the filesystem
   * @ai: the AIL entry
   *
   */
4667a0ec3   Steven Whitehouse   GFS2: Make writeb...
182
  static void gfs2_ail1_empty_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai)
ddacfaf76   Steven Whitehouse   [GFS2] Move loggi...
183
184
185
186
187
188
189
  {
  	struct gfs2_bufdata *bd, *s;
  	struct buffer_head *bh;
  
  	list_for_each_entry_safe_reverse(bd, s, &ai->ai_ail1_list,
  					 bd_ail_st_list) {
  		bh = bd->bd_bh;
ddacfaf76   Steven Whitehouse   [GFS2] Move loggi...
190
  		gfs2_assert(sdp, bd->bd_ail == ai);
4667a0ec3   Steven Whitehouse   GFS2: Make writeb...
191
192
  		if (buffer_busy(bh))
  			continue;
ddacfaf76   Steven Whitehouse   [GFS2] Move loggi...
193
194
  		if (!buffer_uptodate(bh))
  			gfs2_io_error_bh(sdp, bh);
ddacfaf76   Steven Whitehouse   [GFS2] Move loggi...
195
196
  		list_move(&bd->bd_ail_st_list, &ai->ai_ail2_list);
  	}
ddacfaf76   Steven Whitehouse   [GFS2] Move loggi...
197
  }
4667a0ec3   Steven Whitehouse   GFS2: Make writeb...
198
199
200
201
202
203
  /**
   * gfs2_ail1_empty - Try to empty the ail1 lists
   * @sdp: The superblock
   *
   * Tries to empty the ail1 lists, starting with the oldest first
   */
b3b94faa5   David Teigland   [GFS2] The core o...
204

4667a0ec3   Steven Whitehouse   GFS2: Make writeb...
205
  static int gfs2_ail1_empty(struct gfs2_sbd *sdp)
b3b94faa5   David Teigland   [GFS2] The core o...
206
207
208
  {
  	struct gfs2_ail *ai, *s;
  	int ret;
d6a079e82   Dave Chinner   GFS2: introduce A...
209
  	spin_lock(&sdp->sd_ail_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
210
  	list_for_each_entry_safe_reverse(ai, s, &sdp->sd_ail1_list, ai_list) {
4667a0ec3   Steven Whitehouse   GFS2: Make writeb...
211
212
  		gfs2_ail1_empty_one(sdp, ai);
  		if (list_empty(&ai->ai_ail1_list))
b3b94faa5   David Teigland   [GFS2] The core o...
213
  			list_move(&ai->ai_list, &sdp->sd_ail2_list);
4667a0ec3   Steven Whitehouse   GFS2: Make writeb...
214
  		else
b3b94faa5   David Teigland   [GFS2] The core o...
215
216
  			break;
  	}
b3b94faa5   David Teigland   [GFS2] The core o...
217
  	ret = list_empty(&sdp->sd_ail1_list);
d6a079e82   Dave Chinner   GFS2: introduce A...
218
  	spin_unlock(&sdp->sd_ail_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
219
220
221
  
  	return ret;
  }
26b06a695   Steven Whitehouse   GFS2: Wait proper...
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
  static void gfs2_ail1_wait(struct gfs2_sbd *sdp)
  {
  	struct gfs2_ail *ai;
  	struct gfs2_bufdata *bd;
  	struct buffer_head *bh;
  
  	spin_lock(&sdp->sd_ail_lock);
  	list_for_each_entry_reverse(ai, &sdp->sd_ail1_list, ai_list) {
  		list_for_each_entry(bd, &ai->ai_ail1_list, bd_ail_st_list) {
  			bh = bd->bd_bh;
  			if (!buffer_locked(bh))
  				continue;
  			get_bh(bh);
  			spin_unlock(&sdp->sd_ail_lock);
  			wait_on_buffer(bh);
  			brelse(bh);
  			return;
  		}
  	}
  	spin_unlock(&sdp->sd_ail_lock);
  }
ddacfaf76   Steven Whitehouse   [GFS2] Move loggi...
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
  
  /**
   * gfs2_ail2_empty_one - Check whether or not a trans in the AIL has been synced
   * @sdp: the filesystem
   * @ai: the AIL entry
   *
   */
  
  static void gfs2_ail2_empty_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai)
  {
  	struct list_head *head = &ai->ai_ail2_list;
  	struct gfs2_bufdata *bd;
  
  	while (!list_empty(head)) {
  		bd = list_entry(head->prev, struct gfs2_bufdata,
  				bd_ail_st_list);
  		gfs2_assert(sdp, bd->bd_ail == ai);
f91a0d3e2   Steven Whitehouse   [GFS2] Remove use...
260
  		gfs2_remove_from_ail(bd);
ddacfaf76   Steven Whitehouse   [GFS2] Move loggi...
261
262
  	}
  }
b3b94faa5   David Teigland   [GFS2] The core o...
263
264
265
266
267
268
  static void ail2_empty(struct gfs2_sbd *sdp, unsigned int new_tail)
  {
  	struct gfs2_ail *ai, *safe;
  	unsigned int old_tail = sdp->sd_log_tail;
  	int wrap = (new_tail < old_tail);
  	int a, b, rm;
d6a079e82   Dave Chinner   GFS2: introduce A...
269
  	spin_lock(&sdp->sd_ail_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
270
271
272
273
274
275
276
277
278
279
280
281
282
283
  
  	list_for_each_entry_safe(ai, safe, &sdp->sd_ail2_list, ai_list) {
  		a = (old_tail <= ai->ai_first);
  		b = (ai->ai_first < new_tail);
  		rm = (wrap) ? (a || b) : (a && b);
  		if (!rm)
  			continue;
  
  		gfs2_ail2_empty_one(sdp, ai);
  		list_del(&ai->ai_list);
  		gfs2_assert_warn(sdp, list_empty(&ai->ai_ail1_list));
  		gfs2_assert_warn(sdp, list_empty(&ai->ai_ail2_list));
  		kfree(ai);
  	}
d6a079e82   Dave Chinner   GFS2: introduce A...
284
  	spin_unlock(&sdp->sd_ail_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
285
286
287
288
289
290
291
  }
  
  /**
   * gfs2_log_reserve - Make a log reservation
   * @sdp: The GFS2 superblock
   * @blks: The number of blocks to reserve
   *
89918647a   Steven Whitehouse   [GFS2] Make the l...
292
   * Note that we never give out the last few blocks of the journal. Thats
2332c4435   Robert Peterson   [GFS2] assertion ...
293
   * due to the fact that there is a small number of header blocks
b004157ab   Steven Whitehouse   [GFS2] Fix journa...
294
295
296
297
   * associated with each log flush. The exact number can't be known until
   * flush time, so we ensure that we have just enough free blocks at all
   * times to avoid running out during a log flush.
   *
5e687eac1   Benjamin Marzinski   GFS2: Various gfs...
298
299
300
301
302
303
   * We no longer flush the log here, instead we wake up logd to do that
   * for us. To avoid the thundering herd and to ensure that we deal fairly
   * with queued waiters, we use an exclusive wait. This means that when we
   * get woken with enough journal space to get our reservation, we need to
   * wake the next waiter on the list.
   *
b3b94faa5   David Teigland   [GFS2] The core o...
304
305
306
307
308
   * Returns: errno
   */
  
  int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks)
  {
89918647a   Steven Whitehouse   [GFS2] Make the l...
309
  	unsigned reserved_blks = 6 * (4096 / sdp->sd_vfs->s_blocksize);
5e687eac1   Benjamin Marzinski   GFS2: Various gfs...
310
311
312
313
  	unsigned wanted = blks + reserved_blks;
  	DEFINE_WAIT(wait);
  	int did_wait = 0;
  	unsigned int free_blocks;
b3b94faa5   David Teigland   [GFS2] The core o...
314
315
316
317
  
  	if (gfs2_assert_warn(sdp, blks) ||
  	    gfs2_assert_warn(sdp, blks <= sdp->sd_jdesc->jd_blocks))
  		return -EINVAL;
5e687eac1   Benjamin Marzinski   GFS2: Various gfs...
318
319
320
321
322
323
324
325
326
327
328
329
330
  retry:
  	free_blocks = atomic_read(&sdp->sd_log_blks_free);
  	if (unlikely(free_blocks <= wanted)) {
  		do {
  			prepare_to_wait_exclusive(&sdp->sd_log_waitq, &wait,
  					TASK_UNINTERRUPTIBLE);
  			wake_up(&sdp->sd_logd_waitq);
  			did_wait = 1;
  			if (atomic_read(&sdp->sd_log_blks_free) <= wanted)
  				io_schedule();
  			free_blocks = atomic_read(&sdp->sd_log_blks_free);
  		} while(free_blocks <= wanted);
  		finish_wait(&sdp->sd_log_waitq, &wait);
b3b94faa5   David Teigland   [GFS2] The core o...
331
  	}
5e687eac1   Benjamin Marzinski   GFS2: Various gfs...
332
333
334
  	if (atomic_cmpxchg(&sdp->sd_log_blks_free, free_blocks,
  				free_blocks - blks) != free_blocks)
  		goto retry;
63997775b   Steven Whitehouse   GFS2: Add tracepo...
335
  	trace_gfs2_log_blocks(sdp, -blks);
5e687eac1   Benjamin Marzinski   GFS2: Various gfs...
336
337
338
339
340
341
342
  
  	/*
  	 * If we waited, then so might others, wake them up _after_ we get
  	 * our share of the log.
  	 */
  	if (unlikely(did_wait))
  		wake_up(&sdp->sd_log_waitq);
484adff8a   Steven Whitehouse   [GFS2] Update loc...
343
344
  
  	down_read(&sdp->sd_log_flush_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
345
346
347
  
  	return 0;
  }
cd915493f   Steven Whitehouse   [GFS2] Change all...
348
  static u64 log_bmap(struct gfs2_sbd *sdp, unsigned int lbn)
b3b94faa5   David Teigland   [GFS2] The core o...
349
  {
da6dd40d5   Bob Peterson   [GFS2] Journal ex...
350
351
352
353
  	struct gfs2_journal_extent *je;
  
  	list_for_each_entry(je, &sdp->sd_jdesc->extent_list, extent_list) {
  		if (lbn >= je->lblock && lbn < je->lblock + je->blocks)
ff91cc9bb   Steven Whitehouse   [GFS2] Fix log bl...
354
  			return je->dblock + lbn - je->lblock;
da6dd40d5   Bob Peterson   [GFS2] Journal ex...
355
356
357
  	}
  
  	return -1;
b3b94faa5   David Teigland   [GFS2] The core o...
358
359
360
361
362
363
364
365
366
367
368
369
370
  }
  
  /**
   * log_distance - Compute distance between two journal blocks
   * @sdp: The GFS2 superblock
   * @newer: The most recent journal block of the pair
   * @older: The older journal block of the pair
   *
   *   Compute the distance (in the journal direction) between two
   *   blocks in the journal
   *
   * Returns: the distance in blocks
   */
faa31ce85   Steven Whitehouse   [GFS2] Tidy up log.c
371
  static inline unsigned int log_distance(struct gfs2_sbd *sdp, unsigned int newer,
b3b94faa5   David Teigland   [GFS2] The core o...
372
373
374
375
376
377
378
379
380
381
  					unsigned int older)
  {
  	int dist;
  
  	dist = newer - older;
  	if (dist < 0)
  		dist += sdp->sd_jdesc->jd_blocks;
  
  	return dist;
  }
2332c4435   Robert Peterson   [GFS2] assertion ...
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
  /**
   * calc_reserved - Calculate the number of blocks to reserve when
   *                 refunding a transaction's unused buffers.
   * @sdp: The GFS2 superblock
   *
   * This is complex.  We need to reserve room for all our currently used
   * metadata buffers (e.g. normal file I/O rewriting file time stamps) and 
   * all our journaled data buffers for journaled files (e.g. files in the 
   * meta_fs like rindex, or files for which chattr +j was done.)
   * If we don't reserve enough space, gfs2_log_refund and gfs2_log_flush
   * will count it as free space (sd_log_blks_free) and corruption will follow.
   *
   * We can have metadata bufs and jdata bufs in the same journal.  So each
   * type gets its own log header, for which we need to reserve a block.
   * In fact, each type has the potential for needing more than one header 
   * in cases where we have more buffers than will fit on a journal page.
   * Metadata journal entries take up half the space of journaled buffer entries.
   * Thus, metadata entries have buf_limit (502) and journaled buffers have
   * databuf_limit (251) before they cause a wrap around.
   *
   * Also, we need to reserve blocks for revoke journal entries and one for an
   * overall header for the lot.
   *
   * Returns: the number of blocks reserved
   */
  static unsigned int calc_reserved(struct gfs2_sbd *sdp)
  {
  	unsigned int reserved = 0;
  	unsigned int mbuf_limit, metabufhdrs_needed;
  	unsigned int dbuf_limit, databufhdrs_needed;
  	unsigned int revokes = 0;
  
  	mbuf_limit = buf_limit(sdp);
  	metabufhdrs_needed = (sdp->sd_log_commited_buf +
  			      (mbuf_limit - 1)) / mbuf_limit;
  	dbuf_limit = databuf_limit(sdp);
  	databufhdrs_needed = (sdp->sd_log_commited_databuf +
  			      (dbuf_limit - 1)) / dbuf_limit;
2e95e3f66   Benjamin Marzinski   GFS2: Allow the n...
420
  	if (sdp->sd_log_commited_revoke > 0)
2332c4435   Robert Peterson   [GFS2] assertion ...
421
422
423
424
425
426
427
428
429
430
431
  		revokes = gfs2_struct2blk(sdp, sdp->sd_log_commited_revoke,
  					  sizeof(u64));
  
  	reserved = sdp->sd_log_commited_buf + metabufhdrs_needed +
  		sdp->sd_log_commited_databuf + databufhdrs_needed +
  		revokes;
  	/* One for the overall header */
  	if (reserved)
  		reserved++;
  	return reserved;
  }
b3b94faa5   David Teigland   [GFS2] The core o...
432
433
434
435
  static unsigned int current_tail(struct gfs2_sbd *sdp)
  {
  	struct gfs2_ail *ai;
  	unsigned int tail;
d6a079e82   Dave Chinner   GFS2: introduce A...
436
  	spin_lock(&sdp->sd_ail_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
437

faa31ce85   Steven Whitehouse   [GFS2] Tidy up log.c
438
  	if (list_empty(&sdp->sd_ail1_list)) {
b3b94faa5   David Teigland   [GFS2] The core o...
439
  		tail = sdp->sd_log_head;
faa31ce85   Steven Whitehouse   [GFS2] Tidy up log.c
440
441
  	} else {
  		ai = list_entry(sdp->sd_ail1_list.prev, struct gfs2_ail, ai_list);
b3b94faa5   David Teigland   [GFS2] The core o...
442
443
  		tail = ai->ai_first;
  	}
d6a079e82   Dave Chinner   GFS2: introduce A...
444
  	spin_unlock(&sdp->sd_ail_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
445
446
447
  
  	return tail;
  }
16615be18   Steven Whitehouse   [GFS2] Clean up j...
448
  void gfs2_log_incr_head(struct gfs2_sbd *sdp)
b3b94faa5   David Teigland   [GFS2] The core o...
449
450
  {
  	if (sdp->sd_log_flush_head == sdp->sd_log_tail)
16615be18   Steven Whitehouse   [GFS2] Clean up j...
451
  		BUG_ON(sdp->sd_log_flush_head != sdp->sd_log_head);
b3b94faa5   David Teigland   [GFS2] The core o...
452
453
454
455
456
457
458
459
  
  	if (++sdp->sd_log_flush_head == sdp->sd_jdesc->jd_blocks) {
  		sdp->sd_log_flush_head = 0;
  		sdp->sd_log_flush_wrapped = 1;
  	}
  }
  
  /**
16615be18   Steven Whitehouse   [GFS2] Clean up j...
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
   * gfs2_log_write_endio - End of I/O for a log buffer
   * @bh: The buffer head
   * @uptodate: I/O Status
   *
   */
  
  static void gfs2_log_write_endio(struct buffer_head *bh, int uptodate)
  {
  	struct gfs2_sbd *sdp = bh->b_private;
  	bh->b_private = NULL;
  
  	end_buffer_write_sync(bh, uptodate);
  	if (atomic_dec_and_test(&sdp->sd_log_in_flight))
  		wake_up(&sdp->sd_log_flush_wait);
  }
  
  /**
b3b94faa5   David Teigland   [GFS2] The core o...
477
478
479
480
481
482
483
484
   * gfs2_log_get_buf - Get and initialize a buffer to use for log control data
   * @sdp: The GFS2 superblock
   *
   * Returns: the buffer_head
   */
  
  struct buffer_head *gfs2_log_get_buf(struct gfs2_sbd *sdp)
  {
cd915493f   Steven Whitehouse   [GFS2] Change all...
485
  	u64 blkno = log_bmap(sdp, sdp->sd_log_flush_head);
b3b94faa5   David Teigland   [GFS2] The core o...
486
  	struct buffer_head *bh;
16615be18   Steven Whitehouse   [GFS2] Clean up j...
487
  	bh = sb_getblk(sdp->sd_vfs, blkno);
b3b94faa5   David Teigland   [GFS2] The core o...
488
489
490
491
  	lock_buffer(bh);
  	memset(bh->b_data, 0, bh->b_size);
  	set_buffer_uptodate(bh);
  	clear_buffer_dirty(bh);
16615be18   Steven Whitehouse   [GFS2] Clean up j...
492
493
494
495
  	gfs2_log_incr_head(sdp);
  	atomic_inc(&sdp->sd_log_in_flight);
  	bh->b_private = sdp;
  	bh->b_end_io = gfs2_log_write_endio;
b3b94faa5   David Teigland   [GFS2] The core o...
496
497
498
499
500
  
  	return bh;
  }
  
  /**
16615be18   Steven Whitehouse   [GFS2] Clean up j...
501
502
503
504
505
506
507
508
509
   * gfs2_fake_write_endio - 
   * @bh: The buffer head
   * @uptodate: The I/O Status
   *
   */
  
  static void gfs2_fake_write_endio(struct buffer_head *bh, int uptodate)
  {
  	struct buffer_head *real_bh = bh->b_private;
5a60c532c   Steven Whitehouse   [GFS2] Get superb...
510
511
  	struct gfs2_bufdata *bd = real_bh->b_private;
  	struct gfs2_sbd *sdp = bd->bd_gl->gl_sbd;
16615be18   Steven Whitehouse   [GFS2] Clean up j...
512
513
514
515
516
517
518
519
520
521
  
  	end_buffer_write_sync(bh, uptodate);
  	free_buffer_head(bh);
  	unlock_buffer(real_bh);
  	brelse(real_bh);
  	if (atomic_dec_and_test(&sdp->sd_log_in_flight))
  		wake_up(&sdp->sd_log_flush_wait);
  }
  
  /**
b3b94faa5   David Teigland   [GFS2] The core o...
522
523
524
525
526
527
528
529
530
531
   * gfs2_log_fake_buf - Build a fake buffer head to write metadata buffer to log
   * @sdp: the filesystem
   * @data: the data the buffer_head should point to
   *
   * Returns: the log buffer descriptor
   */
  
  struct buffer_head *gfs2_log_fake_buf(struct gfs2_sbd *sdp,
  				      struct buffer_head *real)
  {
cd915493f   Steven Whitehouse   [GFS2] Change all...
532
  	u64 blkno = log_bmap(sdp, sdp->sd_log_flush_head);
b3b94faa5   David Teigland   [GFS2] The core o...
533
  	struct buffer_head *bh;
16615be18   Steven Whitehouse   [GFS2] Clean up j...
534
  	bh = alloc_buffer_head(GFP_NOFS | __GFP_NOFAIL);
b3b94faa5   David Teigland   [GFS2] The core o...
535
  	atomic_set(&bh->b_count, 1);
16615be18   Steven Whitehouse   [GFS2] Clean up j...
536
  	bh->b_state = (1 << BH_Mapped) | (1 << BH_Uptodate) | (1 << BH_Lock);
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
537
  	set_bh_page(bh, real->b_page, bh_offset(real));
b3b94faa5   David Teigland   [GFS2] The core o...
538
539
540
  	bh->b_blocknr = blkno;
  	bh->b_size = sdp->sd_sb.sb_bsize;
  	bh->b_bdev = sdp->sd_vfs->s_bdev;
16615be18   Steven Whitehouse   [GFS2] Clean up j...
541
542
  	bh->b_private = real;
  	bh->b_end_io = gfs2_fake_write_endio;
b3b94faa5   David Teigland   [GFS2] The core o...
543

16615be18   Steven Whitehouse   [GFS2] Clean up j...
544
545
  	gfs2_log_incr_head(sdp);
  	atomic_inc(&sdp->sd_log_in_flight);
b3b94faa5   David Teigland   [GFS2] The core o...
546
547
548
  
  	return bh;
  }
2332c4435   Robert Peterson   [GFS2] assertion ...
549
  static void log_pull_tail(struct gfs2_sbd *sdp, unsigned int new_tail)
b3b94faa5   David Teigland   [GFS2] The core o...
550
551
552
553
  {
  	unsigned int dist = log_distance(sdp, new_tail, sdp->sd_log_tail);
  
  	ail2_empty(sdp, new_tail);
fd041f0b4   Steven Whitehouse   [GFS2] Use atomic...
554
  	atomic_add(dist, &sdp->sd_log_blks_free);
63997775b   Steven Whitehouse   GFS2: Add tracepo...
555
  	trace_gfs2_log_blocks(sdp, dist);
5e687eac1   Benjamin Marzinski   GFS2: Various gfs...
556
557
  	gfs2_assert_withdraw(sdp, atomic_read(&sdp->sd_log_blks_free) <=
  			     sdp->sd_jdesc->jd_blocks);
b3b94faa5   David Teigland   [GFS2] The core o...
558
559
560
561
562
563
564
565
566
567
  
  	sdp->sd_log_tail = new_tail;
  }
  
  /**
   * log_write_header - Get and initialize a journal header buffer
   * @sdp: The GFS2 superblock
   *
   * Returns: the initialized log buffer descriptor
   */
cd915493f   Steven Whitehouse   [GFS2] Change all...
568
  static void log_write_header(struct gfs2_sbd *sdp, u32 flags, int pull)
b3b94faa5   David Teigland   [GFS2] The core o...
569
  {
cd915493f   Steven Whitehouse   [GFS2] Change all...
570
  	u64 blkno = log_bmap(sdp, sdp->sd_log_flush_head);
b3b94faa5   David Teigland   [GFS2] The core o...
571
572
573
  	struct buffer_head *bh;
  	struct gfs2_log_header *lh;
  	unsigned int tail;
cd915493f   Steven Whitehouse   [GFS2] Change all...
574
  	u32 hash;
b3b94faa5   David Teigland   [GFS2] The core o...
575

b3b94faa5   David Teigland   [GFS2] The core o...
576
577
578
579
580
  	bh = sb_getblk(sdp->sd_vfs, blkno);
  	lock_buffer(bh);
  	memset(bh->b_data, 0, bh->b_size);
  	set_buffer_uptodate(bh);
  	clear_buffer_dirty(bh);
b3b94faa5   David Teigland   [GFS2] The core o...
581

4667a0ec3   Steven Whitehouse   GFS2: Make writeb...
582
  	gfs2_ail1_empty(sdp);
b3b94faa5   David Teigland   [GFS2] The core o...
583
584
585
586
587
  	tail = current_tail(sdp);
  
  	lh = (struct gfs2_log_header *)bh->b_data;
  	memset(lh, 0, sizeof(struct gfs2_log_header));
  	lh->lh_header.mh_magic = cpu_to_be32(GFS2_MAGIC);
e3167ded1   Steven Whitehouse   [GFS] Fix bug in ...
588
  	lh->lh_header.mh_type = cpu_to_be32(GFS2_METATYPE_LH);
0ab7d13fc   Steven Whitehouse   GFS2: Tag all met...
589
  	lh->lh_header.__pad0 = cpu_to_be64(0);
e3167ded1   Steven Whitehouse   [GFS] Fix bug in ...
590
  	lh->lh_header.mh_format = cpu_to_be32(GFS2_FORMAT_LH);
0ab7d13fc   Steven Whitehouse   GFS2: Tag all met...
591
  	lh->lh_header.mh_jid = cpu_to_be32(sdp->sd_jdesc->jd_jid);
e0f2bf780   Steven Whitehouse   [GFS2] Fix endian...
592
593
594
595
  	lh->lh_sequence = cpu_to_be64(sdp->sd_log_sequence++);
  	lh->lh_flags = cpu_to_be32(flags);
  	lh->lh_tail = cpu_to_be32(tail);
  	lh->lh_blkno = cpu_to_be32(sdp->sd_log_flush_head);
b3b94faa5   David Teigland   [GFS2] The core o...
596
597
  	hash = gfs2_disk_hash(bh->b_data, sizeof(struct gfs2_log_header));
  	lh->lh_hash = cpu_to_be32(hash);
254db57f9   Steven Whitehouse   GFS2: Support for...
598
  	bh->b_end_io = end_buffer_write_sync;
254db57f9   Steven Whitehouse   GFS2: Support for...
599
  	get_bh(bh);
f1e4d518c   Christoph Hellwig   gfs2: replace bar...
600
  	if (test_bit(SDF_NOBARRIERS, &sdp->sd_flags))
65299a3b7   Christoph Hellwig   block: separate p...
601
  		submit_bh(WRITE_SYNC | REQ_META | REQ_PRIO, bh);
f1e4d518c   Christoph Hellwig   gfs2: replace bar...
602
  	else
20ed0535d   Steven Whitehouse   GFS2: Fix up REQ ...
603
  		submit_bh(WRITE_FLUSH_FUA | REQ_META, bh);
f1e4d518c   Christoph Hellwig   gfs2: replace bar...
604
  	wait_on_buffer(bh);
254db57f9   Steven Whitehouse   GFS2: Support for...
605
  	if (!buffer_uptodate(bh))
b3b94faa5   David Teigland   [GFS2] The core o...
606
607
608
609
  		gfs2_io_error_bh(sdp, bh);
  	brelse(bh);
  
  	if (sdp->sd_log_tail != tail)
2332c4435   Robert Peterson   [GFS2] assertion ...
610
  		log_pull_tail(sdp, tail);
b3b94faa5   David Teigland   [GFS2] The core o...
611
612
613
614
  	else
  		gfs2_assert_withdraw(sdp, !pull);
  
  	sdp->sd_log_idle = (tail == sdp->sd_log_flush_head);
16615be18   Steven Whitehouse   [GFS2] Clean up j...
615
  	gfs2_log_incr_head(sdp);
b3b94faa5   David Teigland   [GFS2] The core o...
616
617
618
619
  }
  
  static void log_flush_commit(struct gfs2_sbd *sdp)
  {
16615be18   Steven Whitehouse   [GFS2] Clean up j...
620
621
622
623
624
625
626
627
628
629
  	DEFINE_WAIT(wait);
  
  	if (atomic_read(&sdp->sd_log_in_flight)) {
  		do {
  			prepare_to_wait(&sdp->sd_log_flush_wait, &wait,
  					TASK_UNINTERRUPTIBLE);
  			if (atomic_read(&sdp->sd_log_in_flight))
  				io_schedule();
  		} while(atomic_read(&sdp->sd_log_in_flight));
  		finish_wait(&sdp->sd_log_flush_wait, &wait);
b3b94faa5   David Teigland   [GFS2] The core o...
630
  	}
16615be18   Steven Whitehouse   [GFS2] Clean up j...
631
  	log_write_header(sdp, 0, 0);
b3b94faa5   David Teigland   [GFS2] The core o...
632
  }
d7b616e25   Steven Whitehouse   [GFS2] Clean up o...
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
  static void gfs2_ordered_write(struct gfs2_sbd *sdp)
  {
  	struct gfs2_bufdata *bd;
  	struct buffer_head *bh;
  	LIST_HEAD(written);
  
  	gfs2_log_lock(sdp);
  	while (!list_empty(&sdp->sd_log_le_ordered)) {
  		bd = list_entry(sdp->sd_log_le_ordered.next, struct gfs2_bufdata, bd_le.le_list);
  		list_move(&bd->bd_le.le_list, &written);
  		bh = bd->bd_bh;
  		if (!buffer_dirty(bh))
  			continue;
  		get_bh(bh);
  		gfs2_log_unlock(sdp);
  		lock_buffer(bh);
b8e7cbb65   Steven Whitehouse   [GFS2] Add writep...
649
  		if (buffer_mapped(bh) && test_clear_buffer_dirty(bh)) {
d7b616e25   Steven Whitehouse   [GFS2] Clean up o...
650
  			bh->b_end_io = end_buffer_write_sync;
721a9602e   Jens Axboe   block: kill off R...
651
  			submit_bh(WRITE_SYNC, bh);
d7b616e25   Steven Whitehouse   [GFS2] Clean up o...
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
  		} else {
  			unlock_buffer(bh);
  			brelse(bh);
  		}
  		gfs2_log_lock(sdp);
  	}
  	list_splice(&written, &sdp->sd_log_le_ordered);
  	gfs2_log_unlock(sdp);
  }
  
  static void gfs2_ordered_wait(struct gfs2_sbd *sdp)
  {
  	struct gfs2_bufdata *bd;
  	struct buffer_head *bh;
  
  	gfs2_log_lock(sdp);
  	while (!list_empty(&sdp->sd_log_le_ordered)) {
  		bd = list_entry(sdp->sd_log_le_ordered.prev, struct gfs2_bufdata, bd_le.le_list);
  		bh = bd->bd_bh;
  		if (buffer_locked(bh)) {
  			get_bh(bh);
  			gfs2_log_unlock(sdp);
  			wait_on_buffer(bh);
  			brelse(bh);
  			gfs2_log_lock(sdp);
  			continue;
  		}
  		list_del_init(&bd->bd_le.le_list);
  	}
  	gfs2_log_unlock(sdp);
  }
b3b94faa5   David Teigland   [GFS2] The core o...
683
  /**
b09e593d7   Steven Whitehouse   [GFS2] Fix a ref ...
684
   * gfs2_log_flush - flush incore transaction(s)
b3b94faa5   David Teigland   [GFS2] The core o...
685
686
687
688
   * @sdp: the filesystem
   * @gl: The glock structure to flush.  If NULL, flush the whole incore log
   *
   */
ed4878e8a   Bob Peterson   GFS2: Rework recl...
689
  void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
b3b94faa5   David Teigland   [GFS2] The core o...
690
691
  {
  	struct gfs2_ail *ai;
484adff8a   Steven Whitehouse   [GFS2] Update loc...
692
  	down_write(&sdp->sd_log_flush_lock);
f55ab26a8   Steven Whitehouse   [GFS2] Use mutice...
693

2bcd610d2   Steven Whitehouse   [GFS2] Don't add ...
694
695
696
697
  	/* Log might have been flushed while we waited for the flush lock */
  	if (gl && !test_bit(GLF_LFLUSH, &gl->gl_flags)) {
  		up_write(&sdp->sd_log_flush_lock);
  		return;
f55ab26a8   Steven Whitehouse   [GFS2] Use mutice...
698
  	}
63997775b   Steven Whitehouse   GFS2: Add tracepo...
699
  	trace_gfs2_log_flush(sdp, 1);
f55ab26a8   Steven Whitehouse   [GFS2] Use mutice...
700

b09e593d7   Steven Whitehouse   [GFS2] Fix a ref ...
701
702
703
  	ai = kzalloc(sizeof(struct gfs2_ail), GFP_NOFS | __GFP_NOFAIL);
  	INIT_LIST_HEAD(&ai->ai_ail1_list);
  	INIT_LIST_HEAD(&ai->ai_ail2_list);
b3b94faa5   David Teigland   [GFS2] The core o...
704

16615be18   Steven Whitehouse   [GFS2] Clean up j...
705
706
707
708
709
710
711
712
713
714
715
716
  	if (sdp->sd_log_num_buf != sdp->sd_log_commited_buf) {
  		printk(KERN_INFO "GFS2: log buf %u %u
  ", sdp->sd_log_num_buf,
  		       sdp->sd_log_commited_buf);
  		gfs2_assert_withdraw(sdp, 0);
  	}
  	if (sdp->sd_log_num_databuf != sdp->sd_log_commited_databuf) {
  		printk(KERN_INFO "GFS2: log databuf %u %u
  ",
  		       sdp->sd_log_num_databuf, sdp->sd_log_commited_databuf);
  		gfs2_assert_withdraw(sdp, 0);
  	}
b3b94faa5   David Teigland   [GFS2] The core o...
717
718
  	gfs2_assert_withdraw(sdp,
  			sdp->sd_log_num_revoke == sdp->sd_log_commited_revoke);
b3b94faa5   David Teigland   [GFS2] The core o...
719
720
721
  	sdp->sd_log_flush_head = sdp->sd_log_head;
  	sdp->sd_log_flush_wrapped = 0;
  	ai->ai_first = sdp->sd_log_flush_head;
d7b616e25   Steven Whitehouse   [GFS2] Clean up o...
722
  	gfs2_ordered_write(sdp);
b3b94faa5   David Teigland   [GFS2] The core o...
723
  	lops_before_commit(sdp);
d7b616e25   Steven Whitehouse   [GFS2] Clean up o...
724
  	gfs2_ordered_wait(sdp);
16615be18   Steven Whitehouse   [GFS2] Clean up j...
725
  	if (sdp->sd_log_head != sdp->sd_log_flush_head)
b3b94faa5   David Teigland   [GFS2] The core o...
726
  		log_flush_commit(sdp);
2332c4435   Robert Peterson   [GFS2] assertion ...
727
728
  	else if (sdp->sd_log_tail != current_tail(sdp) && !sdp->sd_log_idle){
  		gfs2_log_lock(sdp);
fd041f0b4   Steven Whitehouse   [GFS2] Use atomic...
729
  		atomic_dec(&sdp->sd_log_blks_free); /* Adjust for unreserved buffer */
63997775b   Steven Whitehouse   GFS2: Add tracepo...
730
  		trace_gfs2_log_blocks(sdp, -1);
2332c4435   Robert Peterson   [GFS2] assertion ...
731
  		gfs2_log_unlock(sdp);
b3b94faa5   David Teigland   [GFS2] The core o...
732
  		log_write_header(sdp, 0, PULL);
2332c4435   Robert Peterson   [GFS2] assertion ...
733
  	}
b3b94faa5   David Teigland   [GFS2] The core o...
734
  	lops_after_commit(sdp, ai);
b09e593d7   Steven Whitehouse   [GFS2] Fix a ref ...
735

fe1a698ff   Steven Whitehouse   [GFS2] Fix bug wh...
736
737
  	gfs2_log_lock(sdp);
  	sdp->sd_log_head = sdp->sd_log_flush_head;
faa31ce85   Steven Whitehouse   [GFS2] Tidy up log.c
738
739
  	sdp->sd_log_blks_reserved = 0;
  	sdp->sd_log_commited_buf = 0;
2332c4435   Robert Peterson   [GFS2] assertion ...
740
  	sdp->sd_log_commited_databuf = 0;
faa31ce85   Steven Whitehouse   [GFS2] Tidy up log.c
741
  	sdp->sd_log_commited_revoke = 0;
b3b94faa5   David Teigland   [GFS2] The core o...
742

d6a079e82   Dave Chinner   GFS2: introduce A...
743
  	spin_lock(&sdp->sd_ail_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
744
745
746
747
  	if (!list_empty(&ai->ai_ail1_list)) {
  		list_add(&ai->ai_list, &sdp->sd_ail1_list);
  		ai = NULL;
  	}
d6a079e82   Dave Chinner   GFS2: introduce A...
748
  	spin_unlock(&sdp->sd_ail_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
749
  	gfs2_log_unlock(sdp);
63997775b   Steven Whitehouse   GFS2: Add tracepo...
750
  	trace_gfs2_log_flush(sdp, 0);
484adff8a   Steven Whitehouse   [GFS2] Update loc...
751
  	up_write(&sdp->sd_log_flush_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
752
753
754
755
756
757
  
  	kfree(ai);
  }
  
  static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
  {
2332c4435   Robert Peterson   [GFS2] assertion ...
758
  	unsigned int reserved;
ac39aadd0   Steven Whitehouse   [GFS2] Fix assert...
759
  	unsigned int unused;
b3b94faa5   David Teigland   [GFS2] The core o...
760
761
762
763
  
  	gfs2_log_lock(sdp);
  
  	sdp->sd_log_commited_buf += tr->tr_num_buf_new - tr->tr_num_buf_rm;
2332c4435   Robert Peterson   [GFS2] assertion ...
764
765
766
767
  	sdp->sd_log_commited_databuf += tr->tr_num_databuf_new -
  		tr->tr_num_databuf_rm;
  	gfs2_assert_withdraw(sdp, (((int)sdp->sd_log_commited_buf) >= 0) ||
  			     (((int)sdp->sd_log_commited_databuf) >= 0));
b3b94faa5   David Teigland   [GFS2] The core o...
768
  	sdp->sd_log_commited_revoke += tr->tr_num_revoke - tr->tr_num_revoke_rm;
2332c4435   Robert Peterson   [GFS2] assertion ...
769
  	reserved = calc_reserved(sdp);
62be1f716   Roel Kluin   [GFS2] fix assert...
770
  	gfs2_assert_withdraw(sdp, sdp->sd_log_blks_reserved + tr->tr_reserved >= reserved);
ac39aadd0   Steven Whitehouse   [GFS2] Fix assert...
771
  	unused = sdp->sd_log_blks_reserved - reserved + tr->tr_reserved;
ac39aadd0   Steven Whitehouse   [GFS2] Fix assert...
772
  	atomic_add(unused, &sdp->sd_log_blks_free);
63997775b   Steven Whitehouse   GFS2: Add tracepo...
773
  	trace_gfs2_log_blocks(sdp, unused);
fd041f0b4   Steven Whitehouse   [GFS2] Use atomic...
774
  	gfs2_assert_withdraw(sdp, atomic_read(&sdp->sd_log_blks_free) <=
2332c4435   Robert Peterson   [GFS2] assertion ...
775
  			     sdp->sd_jdesc->jd_blocks);
b3b94faa5   David Teigland   [GFS2] The core o...
776
777
778
779
  	sdp->sd_log_blks_reserved = reserved;
  
  	gfs2_log_unlock(sdp);
  }
d0109bfa8   Bob Peterson   [GFS2] Only do lo...
780
781
782
783
784
785
786
787
788
789
790
791
792
793
  static void buf_lo_incore_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
  {
  	struct list_head *head = &tr->tr_list_buf;
  	struct gfs2_bufdata *bd;
  
  	gfs2_log_lock(sdp);
  	while (!list_empty(head)) {
  		bd = list_entry(head->next, struct gfs2_bufdata, bd_list_tr);
  		list_del_init(&bd->bd_list_tr);
  		tr->tr_num_buf--;
  	}
  	gfs2_log_unlock(sdp);
  	gfs2_assert_warn(sdp, !tr->tr_num_buf);
  }
b3b94faa5   David Teigland   [GFS2] The core o...
794
795
796
797
798
  /**
   * gfs2_log_commit - Commit a transaction to the log
   * @sdp: the filesystem
   * @tr: the transaction
   *
5e687eac1   Benjamin Marzinski   GFS2: Various gfs...
799
800
801
802
803
804
805
   * We wake up gfs2_logd if the number of pinned blocks exceed thresh1
   * or the total number of used blocks (pinned blocks plus AIL blocks)
   * is greater than thresh2.
   *
   * At mount time thresh1 is 1/3rd of journal size, thresh2 is 2/3rd of
   * journal size.
   *
b3b94faa5   David Teigland   [GFS2] The core o...
806
807
808
809
810
811
   * Returns: errno
   */
  
  void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
  {
  	log_refund(sdp, tr);
d0109bfa8   Bob Peterson   [GFS2] Only do lo...
812
  	buf_lo_incore_commit(sdp, tr);
b3b94faa5   David Teigland   [GFS2] The core o...
813

484adff8a   Steven Whitehouse   [GFS2] Update loc...
814
  	up_read(&sdp->sd_log_flush_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
815

5e687eac1   Benjamin Marzinski   GFS2: Various gfs...
816
817
818
819
  	if (atomic_read(&sdp->sd_log_pinned) > atomic_read(&sdp->sd_log_thresh1) ||
  	    ((sdp->sd_jdesc->jd_blocks - atomic_read(&sdp->sd_log_blks_free)) >
  	    atomic_read(&sdp->sd_log_thresh2)))
  		wake_up(&sdp->sd_logd_waitq);
b3b94faa5   David Teigland   [GFS2] The core o...
820
821
822
823
824
825
826
827
828
829
  }
  
  /**
   * gfs2_log_shutdown - write a shutdown header into a journal
   * @sdp: the filesystem
   *
   */
  
  void gfs2_log_shutdown(struct gfs2_sbd *sdp)
  {
484adff8a   Steven Whitehouse   [GFS2] Update loc...
830
  	down_write(&sdp->sd_log_flush_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
831

b3b94faa5   David Teigland   [GFS2] The core o...
832
  	gfs2_assert_withdraw(sdp, !sdp->sd_log_blks_reserved);
b3b94faa5   David Teigland   [GFS2] The core o...
833
834
835
836
837
838
839
840
  	gfs2_assert_withdraw(sdp, !sdp->sd_log_num_buf);
  	gfs2_assert_withdraw(sdp, !sdp->sd_log_num_revoke);
  	gfs2_assert_withdraw(sdp, !sdp->sd_log_num_rg);
  	gfs2_assert_withdraw(sdp, !sdp->sd_log_num_databuf);
  	gfs2_assert_withdraw(sdp, list_empty(&sdp->sd_ail1_list));
  
  	sdp->sd_log_flush_head = sdp->sd_log_head;
  	sdp->sd_log_flush_wrapped = 0;
2332c4435   Robert Peterson   [GFS2] assertion ...
841
842
  	log_write_header(sdp, GFS2_LOG_HEAD_UNMOUNT,
  			 (sdp->sd_log_tail == current_tail(sdp)) ? 0 : PULL);
b3b94faa5   David Teigland   [GFS2] The core o...
843

fd041f0b4   Steven Whitehouse   [GFS2] Use atomic...
844
  	gfs2_assert_warn(sdp, atomic_read(&sdp->sd_log_blks_free) == sdp->sd_jdesc->jd_blocks);
a74604bee   Steven Whitehouse   [GFS2] sem -> mut...
845
846
  	gfs2_assert_warn(sdp, sdp->sd_log_head == sdp->sd_log_tail);
  	gfs2_assert_warn(sdp, list_empty(&sdp->sd_ail2_list));
b3b94faa5   David Teigland   [GFS2] The core o...
847
848
  
  	sdp->sd_log_head = sdp->sd_log_flush_head;
b3b94faa5   David Teigland   [GFS2] The core o...
849
  	sdp->sd_log_tail = sdp->sd_log_head;
484adff8a   Steven Whitehouse   [GFS2] Update loc...
850
  	up_write(&sdp->sd_log_flush_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
851
  }
a25311c8e   Steven Whitehouse   [GFS2] Move gfs2_...
852
853
854
855
856
857
858
859
860
861
862
  
  /**
   * gfs2_meta_syncfs - sync all the buffers in a filesystem
   * @sdp: the filesystem
   *
   */
  
  void gfs2_meta_syncfs(struct gfs2_sbd *sdp)
  {
  	gfs2_log_flush(sdp, NULL);
  	for (;;) {
5e687eac1   Benjamin Marzinski   GFS2: Various gfs...
863
  		gfs2_ail1_start(sdp);
26b06a695   Steven Whitehouse   GFS2: Wait proper...
864
  		gfs2_ail1_wait(sdp);
4667a0ec3   Steven Whitehouse   GFS2: Make writeb...
865
  		if (gfs2_ail1_empty(sdp))
a25311c8e   Steven Whitehouse   [GFS2] Move gfs2_...
866
  			break;
a25311c8e   Steven Whitehouse   [GFS2] Move gfs2_...
867
  	}
380f7c65a   Steven Whitehouse   GFS2: Resolve ino...
868
  	gfs2_log_flush(sdp, NULL);
a25311c8e   Steven Whitehouse   [GFS2] Move gfs2_...
869
  }
5e687eac1   Benjamin Marzinski   GFS2: Various gfs...
870
871
872
873
874
875
876
877
878
879
  static inline int gfs2_jrnl_flush_reqd(struct gfs2_sbd *sdp)
  {
  	return (atomic_read(&sdp->sd_log_pinned) >= atomic_read(&sdp->sd_log_thresh1));
  }
  
  static inline int gfs2_ail_flush_reqd(struct gfs2_sbd *sdp)
  {
  	unsigned int used_blocks = sdp->sd_jdesc->jd_blocks - atomic_read(&sdp->sd_log_blks_free);
  	return used_blocks >= atomic_read(&sdp->sd_log_thresh2);
  }
ec69b1888   Steven Whitehouse   [GFS2] Move gfs2_...
880
881
882
883
884
885
886
887
888
889
890
891
  
  /**
   * gfs2_logd - Update log tail as Active Items get flushed to in-place blocks
   * @sdp: Pointer to GFS2 superblock
   *
   * Also, periodically check to make sure that we're using the most recent
   * journal index.
   */
  
  int gfs2_logd(void *data)
  {
  	struct gfs2_sbd *sdp = data;
5e687eac1   Benjamin Marzinski   GFS2: Various gfs...
892
893
894
  	unsigned long t = 1;
  	DEFINE_WAIT(wait);
  	unsigned preflush;
ec69b1888   Steven Whitehouse   [GFS2] Move gfs2_...
895
896
  
  	while (!kthread_should_stop()) {
ec69b1888   Steven Whitehouse   [GFS2] Move gfs2_...
897

5e687eac1   Benjamin Marzinski   GFS2: Various gfs...
898
899
  		preflush = atomic_read(&sdp->sd_log_pinned);
  		if (gfs2_jrnl_flush_reqd(sdp) || t == 0) {
4667a0ec3   Steven Whitehouse   GFS2: Make writeb...
900
  			gfs2_ail1_empty(sdp);
5e687eac1   Benjamin Marzinski   GFS2: Various gfs...
901
  			gfs2_log_flush(sdp, NULL);
5e687eac1   Benjamin Marzinski   GFS2: Various gfs...
902
  		}
ec69b1888   Steven Whitehouse   [GFS2] Move gfs2_...
903

5e687eac1   Benjamin Marzinski   GFS2: Various gfs...
904
905
  		if (gfs2_ail_flush_reqd(sdp)) {
  			gfs2_ail1_start(sdp);
26b06a695   Steven Whitehouse   GFS2: Wait proper...
906
  			gfs2_ail1_wait(sdp);
4667a0ec3   Steven Whitehouse   GFS2: Make writeb...
907
  			gfs2_ail1_empty(sdp);
ec69b1888   Steven Whitehouse   [GFS2] Move gfs2_...
908
  			gfs2_log_flush(sdp, NULL);
ec69b1888   Steven Whitehouse   [GFS2] Move gfs2_...
909
  		}
26b06a695   Steven Whitehouse   GFS2: Wait proper...
910
911
  		if (!gfs2_ail_flush_reqd(sdp))
  			wake_up(&sdp->sd_log_waitq);
ec69b1888   Steven Whitehouse   [GFS2] Move gfs2_...
912
  		t = gfs2_tune_get(sdp, gt_logd_secs) * HZ;
a0acae0e8   Tejun Heo   freezer: unexport...
913
914
  
  		try_to_freeze();
5e687eac1   Benjamin Marzinski   GFS2: Various gfs...
915
916
917
  
  		do {
  			prepare_to_wait(&sdp->sd_logd_waitq, &wait,
5f4874903   Steven Whitehouse   GFS2: gfs2_logd s...
918
  					TASK_INTERRUPTIBLE);
5e687eac1   Benjamin Marzinski   GFS2: Various gfs...
919
920
921
922
923
924
925
926
  			if (!gfs2_ail_flush_reqd(sdp) &&
  			    !gfs2_jrnl_flush_reqd(sdp) &&
  			    !kthread_should_stop())
  				t = schedule_timeout(t);
  		} while(t && !gfs2_ail_flush_reqd(sdp) &&
  			!gfs2_jrnl_flush_reqd(sdp) &&
  			!kthread_should_stop());
  		finish_wait(&sdp->sd_logd_waitq, &wait);
ec69b1888   Steven Whitehouse   [GFS2] Move gfs2_...
927
928
929
930
  	}
  
  	return 0;
  }