Blame view

fs/gfs2/log.c 23 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>
b3b94faa5   David Teigland   [GFS2] The core o...
21
22
  
  #include "gfs2.h"
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
23
  #include "incore.h"
b3b94faa5   David Teigland   [GFS2] The core o...
24
25
26
27
28
  #include "bmap.h"
  #include "glock.h"
  #include "log.h"
  #include "lops.h"
  #include "meta_io.h"
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
29
  #include "util.h"
71b86f562   Steven Whitehouse   [GFS2] Further up...
30
  #include "dir.h"
63997775b   Steven Whitehouse   GFS2: Add tracepo...
31
  #include "trace_gfs2.h"
b3b94faa5   David Teigland   [GFS2] The core o...
32
33
  
  #define PULL 1
b3b94faa5   David Teigland   [GFS2] The core o...
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
  /**
   * 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
53
  	first = (sdp->sd_sb.sb_bsize - sizeof(struct gfs2_log_descriptor)) / ssize;
b3b94faa5   David Teigland   [GFS2] The core o...
54
55
  
  	if (nstruct > first) {
568f4c965   Steven Whitehouse   [GFS2] 80 Column ...
56
57
  		second = (sdp->sd_sb.sb_bsize -
  			  sizeof(struct gfs2_meta_header)) / ssize;
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
58
  		blks += DIV_ROUND_UP(nstruct - first, second);
b3b94faa5   David Teigland   [GFS2] The core o...
59
60
61
62
  	}
  
  	return blks;
  }
ddacfaf76   Steven Whitehouse   [GFS2] Move loggi...
63
  /**
1e1a3d03e   Steven Whitehouse   [GFS2] Introduce ...
64
65
66
67
68
69
70
   * 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
   *
   * The log lock _must_ be held when calling this function
   *
   */
f91a0d3e2   Steven Whitehouse   [GFS2] Remove use...
71
  void gfs2_remove_from_ail(struct gfs2_bufdata *bd)
1e1a3d03e   Steven Whitehouse   [GFS2] Introduce ...
72
73
  {
  	bd->bd_ail = NULL;
1ad38c437   Steven Whitehouse   [GFS2] Clean up g...
74
75
  	list_del_init(&bd->bd_ail_st_list);
  	list_del_init(&bd->bd_ail_gl_list);
1e1a3d03e   Steven Whitehouse   [GFS2] Introduce ...
76
  	atomic_dec(&bd->bd_gl->gl_ail_count);
1e1a3d03e   Steven Whitehouse   [GFS2] Introduce ...
77
78
79
80
  	brelse(bd->bd_bh);
  }
  
  /**
ddacfaf76   Steven Whitehouse   [GFS2] Move loggi...
81
82
83
84
85
86
87
   * gfs2_ail1_start_one - Start I/O on a part of the AIL
   * @sdp: the filesystem
   * @tr: the part of the AIL
   *
   */
  
  static void gfs2_ail1_start_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai)
2d81afb87   Harvey Harrison   [GFS2] trivial sp...
88
89
  __releases(&sdp->sd_log_lock)
  __acquires(&sdp->sd_log_lock)
ddacfaf76   Steven Whitehouse   [GFS2] Move loggi...
90
91
92
93
  {
  	struct gfs2_bufdata *bd, *s;
  	struct buffer_head *bh;
  	int retry;
ddacfaf76   Steven Whitehouse   [GFS2] Move loggi...
94
95
96
97
98
99
100
101
102
103
  	do {
  		retry = 0;
  
  		list_for_each_entry_safe_reverse(bd, s, &ai->ai_ail1_list,
  						 bd_ail_st_list) {
  			bh = bd->bd_bh;
  
  			gfs2_assert(sdp, bd->bd_ail == ai);
  
  			if (!buffer_busy(bh)) {
16615be18   Steven Whitehouse   [GFS2] Clean up j...
104
  				if (!buffer_uptodate(bh))
ddacfaf76   Steven Whitehouse   [GFS2] Move loggi...
105
  					gfs2_io_error_bh(sdp, bh);
ddacfaf76   Steven Whitehouse   [GFS2] Move loggi...
106
107
108
109
110
111
112
113
  				list_move(&bd->bd_ail_st_list, &ai->ai_ail2_list);
  				continue;
  			}
  
  			if (!buffer_dirty(bh))
  				continue;
  
  			list_move(&bd->bd_ail_st_list, &ai->ai_ail1_list);
16615be18   Steven Whitehouse   [GFS2] Clean up j...
114
  			get_bh(bh);
ddacfaf76   Steven Whitehouse   [GFS2] Move loggi...
115
  			gfs2_log_unlock(sdp);
16615be18   Steven Whitehouse   [GFS2] Clean up j...
116
117
118
  			lock_buffer(bh);
  			if (test_clear_buffer_dirty(bh)) {
  				bh->b_end_io = end_buffer_write_sync;
c969f58ca   Steven Whitehouse   GFS2: Update the ...
119
  				submit_bh(WRITE_SYNC_PLUG, bh);
16615be18   Steven Whitehouse   [GFS2] Clean up j...
120
121
122
123
  			} else {
  				unlock_buffer(bh);
  				brelse(bh);
  			}
ddacfaf76   Steven Whitehouse   [GFS2] Move loggi...
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
  			gfs2_log_lock(sdp);
  
  			retry = 1;
  			break;
  		}
  	} while (retry);
  }
  
  /**
   * gfs2_ail1_empty_one - Check whether or not a trans in the AIL has been synced
   * @sdp: the filesystem
   * @ai: the AIL entry
   *
   */
  
  static int gfs2_ail1_empty_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai, int flags)
  {
  	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;
  
  		gfs2_assert(sdp, bd->bd_ail == ai);
  
  		if (buffer_busy(bh)) {
  			if (flags & DIO_ALL)
  				continue;
  			else
  				break;
  		}
  
  		if (!buffer_uptodate(bh))
  			gfs2_io_error_bh(sdp, bh);
  
  		list_move(&bd->bd_ail_st_list, &ai->ai_ail2_list);
  	}
  
  	return list_empty(&ai->ai_ail1_list);
  }
a25311c8e   Steven Whitehouse   [GFS2] Move gfs2_...
165
  static void gfs2_ail1_start(struct gfs2_sbd *sdp, int flags)
b3b94faa5   David Teigland   [GFS2] The core o...
166
  {
693ddeabb   Bob Peterson   [GFS2] Revert par...
167
  	struct list_head *head;
cd915493f   Steven Whitehouse   [GFS2] Change all...
168
  	u64 sync_gen;
74669416f   Steven Whitehouse   [GFS2] Use list_f...
169
170
171
  	struct list_head *first;
  	struct gfs2_ail *first_ai, *ai, *tmp;
  	int done = 0;
b3b94faa5   David Teigland   [GFS2] The core o...
172
173
  
  	gfs2_log_lock(sdp);
693ddeabb   Bob Peterson   [GFS2] Revert par...
174
  	head = &sdp->sd_ail1_list;
b3b94faa5   David Teigland   [GFS2] The core o...
175
176
177
178
179
180
181
182
183
  	if (list_empty(head)) {
  		gfs2_log_unlock(sdp);
  		return;
  	}
  	sync_gen = sdp->sd_ail_sync_gen++;
  
  	first = head->prev;
  	first_ai = list_entry(first, struct gfs2_ail, ai_list);
  	first_ai->ai_sync_gen = sync_gen;
74669416f   Steven Whitehouse   [GFS2] Use list_f...
184
  	gfs2_ail1_start_one(sdp, first_ai); /* This may drop log lock */
b3b94faa5   David Teigland   [GFS2] The core o...
185
186
187
  
  	if (flags & DIO_ALL)
  		first = NULL;
74669416f   Steven Whitehouse   [GFS2] Use list_f...
188
  	while(!done) {
484adff8a   Steven Whitehouse   [GFS2] Update loc...
189
190
  		if (first && (head->prev != first ||
  			      gfs2_ail1_empty_one(sdp, first_ai, 0)))
b3b94faa5   David Teigland   [GFS2] The core o...
191
  			break;
74669416f   Steven Whitehouse   [GFS2] Use list_f...
192
193
  		done = 1;
  		list_for_each_entry_safe_reverse(ai, tmp, head, ai_list) {
b3b94faa5   David Teigland   [GFS2] The core o...
194
195
196
  			if (ai->ai_sync_gen >= sync_gen)
  				continue;
  			ai->ai_sync_gen = sync_gen;
74669416f   Steven Whitehouse   [GFS2] Use list_f...
197
198
  			gfs2_ail1_start_one(sdp, ai); /* This may drop log lock */
  			done = 0;
b3b94faa5   David Teigland   [GFS2] The core o...
199
200
  			break;
  		}
b3b94faa5   David Teigland   [GFS2] The core o...
201
202
203
204
  	}
  
  	gfs2_log_unlock(sdp);
  }
ec69b1888   Steven Whitehouse   [GFS2] Move gfs2_...
205
  static int gfs2_ail1_empty(struct gfs2_sbd *sdp, int flags)
b3b94faa5   David Teigland   [GFS2] The core o...
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
  {
  	struct gfs2_ail *ai, *s;
  	int ret;
  
  	gfs2_log_lock(sdp);
  
  	list_for_each_entry_safe_reverse(ai, s, &sdp->sd_ail1_list, ai_list) {
  		if (gfs2_ail1_empty_one(sdp, ai, flags))
  			list_move(&ai->ai_list, &sdp->sd_ail2_list);
  		else if (!(flags & DIO_ALL))
  			break;
  	}
  
  	ret = list_empty(&sdp->sd_ail1_list);
  
  	gfs2_log_unlock(sdp);
  
  	return ret;
  }
ddacfaf76   Steven Whitehouse   [GFS2] Move loggi...
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
  
  /**
   * 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...
242
  		gfs2_remove_from_ail(bd);
ddacfaf76   Steven Whitehouse   [GFS2] Move loggi...
243
244
  	}
  }
b3b94faa5   David Teigland   [GFS2] The core o...
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
  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;
  
  	gfs2_log_lock(sdp);
  
  	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);
  	}
  
  	gfs2_log_unlock(sdp);
  }
  
  /**
   * 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...
276
   * Note that we never give out the last few blocks of the journal. Thats
2332c4435   Robert Peterson   [GFS2] assertion ...
277
   * due to the fact that there is a small number of header blocks
b004157ab   Steven Whitehouse   [GFS2] Fix journa...
278
279
280
281
   * 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.
   *
b3b94faa5   David Teigland   [GFS2] The core o...
282
283
284
285
286
   * Returns: errno
   */
  
  int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks)
  {
b3b94faa5   David Teigland   [GFS2] The core o...
287
  	unsigned int try = 0;
89918647a   Steven Whitehouse   [GFS2] Make the l...
288
  	unsigned reserved_blks = 6 * (4096 / sdp->sd_vfs->s_blocksize);
b3b94faa5   David Teigland   [GFS2] The core o...
289
290
291
292
  
  	if (gfs2_assert_warn(sdp, blks) ||
  	    gfs2_assert_warn(sdp, blks <= sdp->sd_jdesc->jd_blocks))
  		return -EINVAL;
71b86f562   Steven Whitehouse   [GFS2] Further up...
293
  	mutex_lock(&sdp->sd_log_reserve_mutex);
484adff8a   Steven Whitehouse   [GFS2] Update loc...
294
  	gfs2_log_lock(sdp);
fd041f0b4   Steven Whitehouse   [GFS2] Use atomic...
295
  	while(atomic_read(&sdp->sd_log_blks_free) <= (blks + reserved_blks)) {
b3b94faa5   David Teigland   [GFS2] The core o...
296
  		gfs2_log_unlock(sdp);
b3b94faa5   David Teigland   [GFS2] The core o...
297
  		gfs2_ail1_empty(sdp, 0);
b09e593d7   Steven Whitehouse   [GFS2] Fix a ref ...
298
  		gfs2_log_flush(sdp, NULL);
b3b94faa5   David Teigland   [GFS2] The core o...
299
300
301
  
  		if (try++)
  			gfs2_ail1_start(sdp, 0);
484adff8a   Steven Whitehouse   [GFS2] Update loc...
302
  		gfs2_log_lock(sdp);
b3b94faa5   David Teigland   [GFS2] The core o...
303
  	}
fd041f0b4   Steven Whitehouse   [GFS2] Use atomic...
304
  	atomic_sub(blks, &sdp->sd_log_blks_free);
63997775b   Steven Whitehouse   GFS2: Add tracepo...
305
  	trace_gfs2_log_blocks(sdp, -blks);
484adff8a   Steven Whitehouse   [GFS2] Update loc...
306
307
308
309
  	gfs2_log_unlock(sdp);
  	mutex_unlock(&sdp->sd_log_reserve_mutex);
  
  	down_read(&sdp->sd_log_flush_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
310
311
312
313
314
315
316
317
318
319
320
321
322
  
  	return 0;
  }
  
  /**
   * gfs2_log_release - Release a given number of log blocks
   * @sdp: The GFS2 superblock
   * @blks: The number of blocks
   *
   */
  
  void gfs2_log_release(struct gfs2_sbd *sdp, unsigned int blks)
  {
b3b94faa5   David Teigland   [GFS2] The core o...
323
324
  
  	gfs2_log_lock(sdp);
fd041f0b4   Steven Whitehouse   [GFS2] Use atomic...
325
  	atomic_add(blks, &sdp->sd_log_blks_free);
63997775b   Steven Whitehouse   GFS2: Add tracepo...
326
  	trace_gfs2_log_blocks(sdp, blks);
b3b94faa5   David Teigland   [GFS2] The core o...
327
  	gfs2_assert_withdraw(sdp,
fd041f0b4   Steven Whitehouse   [GFS2] Use atomic...
328
  			     atomic_read(&sdp->sd_log_blks_free) <= sdp->sd_jdesc->jd_blocks);
b3b94faa5   David Teigland   [GFS2] The core o...
329
  	gfs2_log_unlock(sdp);
ed3865079   Steven Whitehouse   [GFS2] Finally ge...
330
  	up_read(&sdp->sd_log_flush_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
331
  }
cd915493f   Steven Whitehouse   [GFS2] Change all...
332
  static u64 log_bmap(struct gfs2_sbd *sdp, unsigned int lbn)
b3b94faa5   David Teigland   [GFS2] The core o...
333
  {
da6dd40d5   Bob Peterson   [GFS2] Journal ex...
334
335
336
337
  	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...
338
  			return je->dblock + lbn - je->lblock;
da6dd40d5   Bob Peterson   [GFS2] Journal ex...
339
340
341
  	}
  
  	return -1;
b3b94faa5   David Teigland   [GFS2] The core o...
342
343
344
345
346
347
348
349
350
351
352
353
354
  }
  
  /**
   * 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
355
  static inline unsigned int log_distance(struct gfs2_sbd *sdp, unsigned int newer,
b3b94faa5   David Teigland   [GFS2] The core o...
356
357
358
359
360
361
362
363
364
365
  					unsigned int older)
  {
  	int dist;
  
  	dist = newer - older;
  	if (dist < 0)
  		dist += sdp->sd_jdesc->jd_blocks;
  
  	return dist;
  }
2332c4435   Robert Peterson   [GFS2] assertion ...
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
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
  /**
   * 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;
  
  	if (sdp->sd_log_commited_revoke)
  		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...
417
418
419
420
421
422
  static unsigned int current_tail(struct gfs2_sbd *sdp)
  {
  	struct gfs2_ail *ai;
  	unsigned int tail;
  
  	gfs2_log_lock(sdp);
faa31ce85   Steven Whitehouse   [GFS2] Tidy up log.c
423
  	if (list_empty(&sdp->sd_ail1_list)) {
b3b94faa5   David Teigland   [GFS2] The core o...
424
  		tail = sdp->sd_log_head;
faa31ce85   Steven Whitehouse   [GFS2] Tidy up log.c
425
426
  	} else {
  		ai = list_entry(sdp->sd_ail1_list.prev, struct gfs2_ail, ai_list);
b3b94faa5   David Teigland   [GFS2] The core o...
427
428
429
430
431
432
433
  		tail = ai->ai_first;
  	}
  
  	gfs2_log_unlock(sdp);
  
  	return tail;
  }
16615be18   Steven Whitehouse   [GFS2] Clean up j...
434
  void gfs2_log_incr_head(struct gfs2_sbd *sdp)
b3b94faa5   David Teigland   [GFS2] The core o...
435
436
  {
  	if (sdp->sd_log_flush_head == sdp->sd_log_tail)
16615be18   Steven Whitehouse   [GFS2] Clean up j...
437
  		BUG_ON(sdp->sd_log_flush_head != sdp->sd_log_head);
b3b94faa5   David Teigland   [GFS2] The core o...
438
439
440
441
442
443
444
445
  
  	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...
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
   * 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...
463
464
465
466
467
468
469
470
   * 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...
471
  	u64 blkno = log_bmap(sdp, sdp->sd_log_flush_head);
b3b94faa5   David Teigland   [GFS2] The core o...
472
  	struct buffer_head *bh;
16615be18   Steven Whitehouse   [GFS2] Clean up j...
473
  	bh = sb_getblk(sdp->sd_vfs, blkno);
b3b94faa5   David Teigland   [GFS2] The core o...
474
475
476
477
  	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...
478
479
480
481
  	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...
482
483
484
485
486
  
  	return bh;
  }
  
  /**
16615be18   Steven Whitehouse   [GFS2] Clean up j...
487
488
489
490
491
492
493
494
495
   * 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...
496
497
  	struct gfs2_bufdata *bd = real_bh->b_private;
  	struct gfs2_sbd *sdp = bd->bd_gl->gl_sbd;
16615be18   Steven Whitehouse   [GFS2] Clean up j...
498
499
500
501
502
503
504
505
506
507
  
  	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...
508
509
510
511
512
513
514
515
516
517
   * 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...
518
  	u64 blkno = log_bmap(sdp, sdp->sd_log_flush_head);
b3b94faa5   David Teigland   [GFS2] The core o...
519
  	struct buffer_head *bh;
16615be18   Steven Whitehouse   [GFS2] Clean up j...
520
  	bh = alloc_buffer_head(GFP_NOFS | __GFP_NOFAIL);
b3b94faa5   David Teigland   [GFS2] The core o...
521
  	atomic_set(&bh->b_count, 1);
16615be18   Steven Whitehouse   [GFS2] Clean up j...
522
  	bh->b_state = (1 << BH_Mapped) | (1 << BH_Uptodate) | (1 << BH_Lock);
18ec7d5c3   Steven Whitehouse   [GFS2] Make journ...
523
  	set_bh_page(bh, real->b_page, bh_offset(real));
b3b94faa5   David Teigland   [GFS2] The core o...
524
525
526
  	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...
527
528
  	bh->b_private = real;
  	bh->b_end_io = gfs2_fake_write_endio;
b3b94faa5   David Teigland   [GFS2] The core o...
529

16615be18   Steven Whitehouse   [GFS2] Clean up j...
530
531
  	gfs2_log_incr_head(sdp);
  	atomic_inc(&sdp->sd_log_in_flight);
b3b94faa5   David Teigland   [GFS2] The core o...
532
533
534
  
  	return bh;
  }
2332c4435   Robert Peterson   [GFS2] assertion ...
535
  static void log_pull_tail(struct gfs2_sbd *sdp, unsigned int new_tail)
b3b94faa5   David Teigland   [GFS2] The core o...
536
537
538
539
540
541
  {
  	unsigned int dist = log_distance(sdp, new_tail, sdp->sd_log_tail);
  
  	ail2_empty(sdp, new_tail);
  
  	gfs2_log_lock(sdp);
fd041f0b4   Steven Whitehouse   [GFS2] Use atomic...
542
  	atomic_add(dist, &sdp->sd_log_blks_free);
63997775b   Steven Whitehouse   GFS2: Add tracepo...
543
  	trace_gfs2_log_blocks(sdp, dist);
fd041f0b4   Steven Whitehouse   [GFS2] Use atomic...
544
  	gfs2_assert_withdraw(sdp, atomic_read(&sdp->sd_log_blks_free) <= sdp->sd_jdesc->jd_blocks);
b3b94faa5   David Teigland   [GFS2] The core o...
545
546
547
548
549
550
551
552
553
554
555
  	gfs2_log_unlock(sdp);
  
  	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...
556
  static void log_write_header(struct gfs2_sbd *sdp, u32 flags, int pull)
b3b94faa5   David Teigland   [GFS2] The core o...
557
  {
cd915493f   Steven Whitehouse   [GFS2] Change all...
558
  	u64 blkno = log_bmap(sdp, sdp->sd_log_flush_head);
b3b94faa5   David Teigland   [GFS2] The core o...
559
560
561
  	struct buffer_head *bh;
  	struct gfs2_log_header *lh;
  	unsigned int tail;
cd915493f   Steven Whitehouse   [GFS2] Change all...
562
  	u32 hash;
b3b94faa5   David Teigland   [GFS2] The core o...
563

b3b94faa5   David Teigland   [GFS2] The core o...
564
565
566
567
568
  	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...
569
570
571
572
573
574
575
  
  	gfs2_ail1_empty(sdp, 0);
  	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 ...
576
577
  	lh->lh_header.mh_type = cpu_to_be32(GFS2_METATYPE_LH);
  	lh->lh_header.mh_format = cpu_to_be32(GFS2_FORMAT_LH);
e0f2bf780   Steven Whitehouse   [GFS2] Fix endian...
578
579
580
581
  	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...
582
583
  	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...
584
585
586
587
  	bh->b_end_io = end_buffer_write_sync;
  	if (test_bit(SDF_NOBARRIERS, &sdp->sd_flags))
  		goto skip_barrier;
  	get_bh(bh);
c969f58ca   Steven Whitehouse   GFS2: Update the ...
588
  	submit_bh(WRITE_SYNC | (1 << BIO_RW_BARRIER) | (1 << BIO_RW_META), bh);
254db57f9   Steven Whitehouse   GFS2: Support for...
589
590
591
592
593
594
595
596
597
598
599
600
  	wait_on_buffer(bh);
  	if (buffer_eopnotsupp(bh)) {
  		clear_buffer_eopnotsupp(bh);
  		set_buffer_uptodate(bh);
  		set_bit(SDF_NOBARRIERS, &sdp->sd_flags);
  		lock_buffer(bh);
  skip_barrier:
  		get_bh(bh);
  		submit_bh(WRITE_SYNC | (1 << BIO_RW_META), bh);
  		wait_on_buffer(bh);
  	}
  	if (!buffer_uptodate(bh))
b3b94faa5   David Teigland   [GFS2] The core o...
601
602
603
604
  		gfs2_io_error_bh(sdp, bh);
  	brelse(bh);
  
  	if (sdp->sd_log_tail != tail)
2332c4435   Robert Peterson   [GFS2] assertion ...
605
  		log_pull_tail(sdp, tail);
b3b94faa5   David Teigland   [GFS2] The core o...
606
607
608
609
  	else
  		gfs2_assert_withdraw(sdp, !pull);
  
  	sdp->sd_log_idle = (tail == sdp->sd_log_flush_head);
16615be18   Steven Whitehouse   [GFS2] Clean up j...
610
  	gfs2_log_incr_head(sdp);
b3b94faa5   David Teigland   [GFS2] The core o...
611
612
613
614
  }
  
  static void log_flush_commit(struct gfs2_sbd *sdp)
  {
16615be18   Steven Whitehouse   [GFS2] Clean up j...
615
616
617
618
619
620
621
622
623
624
  	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...
625
  	}
16615be18   Steven Whitehouse   [GFS2] Clean up j...
626
  	log_write_header(sdp, 0, 0);
b3b94faa5   David Teigland   [GFS2] The core o...
627
  }
d7b616e25   Steven Whitehouse   [GFS2] Clean up o...
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
  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...
644
  		if (buffer_mapped(bh) && test_clear_buffer_dirty(bh)) {
d7b616e25   Steven Whitehouse   [GFS2] Clean up o...
645
  			bh->b_end_io = end_buffer_write_sync;
c969f58ca   Steven Whitehouse   GFS2: Update the ...
646
  			submit_bh(WRITE_SYNC_PLUG, bh);
d7b616e25   Steven Whitehouse   [GFS2] Clean up o...
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
676
677
  		} 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...
678
  /**
b09e593d7   Steven Whitehouse   [GFS2] Fix a ref ...
679
   * gfs2_log_flush - flush incore transaction(s)
b3b94faa5   David Teigland   [GFS2] The core o...
680
681
682
683
   * @sdp: the filesystem
   * @gl: The glock structure to flush.  If NULL, flush the whole incore log
   *
   */
2bcd610d2   Steven Whitehouse   [GFS2] Don't add ...
684
  void __gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
b3b94faa5   David Teigland   [GFS2] The core o...
685
686
  {
  	struct gfs2_ail *ai;
484adff8a   Steven Whitehouse   [GFS2] Update loc...
687
  	down_write(&sdp->sd_log_flush_lock);
f55ab26a8   Steven Whitehouse   [GFS2] Use mutice...
688

2bcd610d2   Steven Whitehouse   [GFS2] Don't add ...
689
690
691
692
  	/* 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...
693
  	}
63997775b   Steven Whitehouse   GFS2: Add tracepo...
694
  	trace_gfs2_log_flush(sdp, 1);
f55ab26a8   Steven Whitehouse   [GFS2] Use mutice...
695

b09e593d7   Steven Whitehouse   [GFS2] Fix a ref ...
696
697
698
  	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...
699

16615be18   Steven Whitehouse   [GFS2] Clean up j...
700
701
702
703
704
705
706
707
708
709
710
711
  	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...
712
713
  	gfs2_assert_withdraw(sdp,
  			sdp->sd_log_num_revoke == sdp->sd_log_commited_revoke);
b3b94faa5   David Teigland   [GFS2] The core o...
714
715
716
  	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...
717
  	gfs2_ordered_write(sdp);
b3b94faa5   David Teigland   [GFS2] The core o...
718
  	lops_before_commit(sdp);
d7b616e25   Steven Whitehouse   [GFS2] Clean up o...
719
  	gfs2_ordered_wait(sdp);
16615be18   Steven Whitehouse   [GFS2] Clean up j...
720
  	if (sdp->sd_log_head != sdp->sd_log_flush_head)
b3b94faa5   David Teigland   [GFS2] The core o...
721
  		log_flush_commit(sdp);
2332c4435   Robert Peterson   [GFS2] assertion ...
722
723
  	else if (sdp->sd_log_tail != current_tail(sdp) && !sdp->sd_log_idle){
  		gfs2_log_lock(sdp);
fd041f0b4   Steven Whitehouse   [GFS2] Use atomic...
724
  		atomic_dec(&sdp->sd_log_blks_free); /* Adjust for unreserved buffer */
63997775b   Steven Whitehouse   GFS2: Add tracepo...
725
  		trace_gfs2_log_blocks(sdp, -1);
2332c4435   Robert Peterson   [GFS2] assertion ...
726
  		gfs2_log_unlock(sdp);
b3b94faa5   David Teigland   [GFS2] The core o...
727
  		log_write_header(sdp, 0, PULL);
2332c4435   Robert Peterson   [GFS2] assertion ...
728
  	}
b3b94faa5   David Teigland   [GFS2] The core o...
729
  	lops_after_commit(sdp, ai);
b09e593d7   Steven Whitehouse   [GFS2] Fix a ref ...
730

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

b3b94faa5   David Teigland   [GFS2] The core o...
738
739
740
741
742
  	if (!list_empty(&ai->ai_ail1_list)) {
  		list_add(&ai->ai_list, &sdp->sd_ail1_list);
  		ai = NULL;
  	}
  	gfs2_log_unlock(sdp);
63997775b   Steven Whitehouse   GFS2: Add tracepo...
743
  	trace_gfs2_log_flush(sdp, 0);
484adff8a   Steven Whitehouse   [GFS2] Update loc...
744
  	up_write(&sdp->sd_log_flush_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
745
746
747
748
749
750
  
  	kfree(ai);
  }
  
  static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
  {
2332c4435   Robert Peterson   [GFS2] assertion ...
751
  	unsigned int reserved;
ac39aadd0   Steven Whitehouse   [GFS2] Fix assert...
752
  	unsigned int unused;
b3b94faa5   David Teigland   [GFS2] The core o...
753
754
755
756
  
  	gfs2_log_lock(sdp);
  
  	sdp->sd_log_commited_buf += tr->tr_num_buf_new - tr->tr_num_buf_rm;
2332c4435   Robert Peterson   [GFS2] assertion ...
757
758
759
760
  	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...
761
762
  	sdp->sd_log_commited_revoke += tr->tr_num_revoke - tr->tr_num_revoke_rm;
  	gfs2_assert_withdraw(sdp, ((int)sdp->sd_log_commited_revoke) >= 0);
2332c4435   Robert Peterson   [GFS2] assertion ...
763
  	reserved = calc_reserved(sdp);
62be1f716   Roel Kluin   [GFS2] fix assert...
764
  	gfs2_assert_withdraw(sdp, sdp->sd_log_blks_reserved + tr->tr_reserved >= reserved);
ac39aadd0   Steven Whitehouse   [GFS2] Fix assert...
765
  	unused = sdp->sd_log_blks_reserved - reserved + tr->tr_reserved;
ac39aadd0   Steven Whitehouse   [GFS2] Fix assert...
766
  	atomic_add(unused, &sdp->sd_log_blks_free);
63997775b   Steven Whitehouse   GFS2: Add tracepo...
767
  	trace_gfs2_log_blocks(sdp, unused);
fd041f0b4   Steven Whitehouse   [GFS2] Use atomic...
768
  	gfs2_assert_withdraw(sdp, atomic_read(&sdp->sd_log_blks_free) <=
2332c4435   Robert Peterson   [GFS2] assertion ...
769
  			     sdp->sd_jdesc->jd_blocks);
b3b94faa5   David Teigland   [GFS2] The core o...
770
771
772
773
  	sdp->sd_log_blks_reserved = reserved;
  
  	gfs2_log_unlock(sdp);
  }
d0109bfa8   Bob Peterson   [GFS2] Only do lo...
774
775
776
777
778
779
780
781
782
783
784
785
786
787
  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...
788
789
790
791
792
793
794
795
796
797
798
  /**
   * gfs2_log_commit - Commit a transaction to the log
   * @sdp: the filesystem
   * @tr: the transaction
   *
   * 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...
799
  	buf_lo_incore_commit(sdp, tr);
b3b94faa5   David Teigland   [GFS2] The core o...
800

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

b3b94faa5   David Teigland   [GFS2] The core o...
803
  	gfs2_log_lock(sdp);
b004157ab   Steven Whitehouse   [GFS2] Fix journa...
804
805
806
  	if (sdp->sd_log_num_buf > gfs2_tune_get(sdp, gt_incore_log_blocks))
  		wake_up_process(sdp->sd_logd_process);
  	gfs2_log_unlock(sdp);
b3b94faa5   David Teigland   [GFS2] The core o...
807
808
809
810
811
812
813
814
815
816
  }
  
  /**
   * 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...
817
  	down_write(&sdp->sd_log_flush_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
818

b3b94faa5   David Teigland   [GFS2] The core o...
819
  	gfs2_assert_withdraw(sdp, !sdp->sd_log_blks_reserved);
b3b94faa5   David Teigland   [GFS2] The core o...
820
821
822
823
824
825
826
827
  	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 ...
828
829
  	log_write_header(sdp, GFS2_LOG_HEAD_UNMOUNT,
  			 (sdp->sd_log_tail == current_tail(sdp)) ? 0 : PULL);
b3b94faa5   David Teigland   [GFS2] The core o...
830

fd041f0b4   Steven Whitehouse   [GFS2] Use atomic...
831
  	gfs2_assert_warn(sdp, atomic_read(&sdp->sd_log_blks_free) == sdp->sd_jdesc->jd_blocks);
a74604bee   Steven Whitehouse   [GFS2] sem -> mut...
832
833
  	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...
834
835
  
  	sdp->sd_log_head = sdp->sd_log_flush_head;
b3b94faa5   David Teigland   [GFS2] The core o...
836
  	sdp->sd_log_tail = sdp->sd_log_head;
484adff8a   Steven Whitehouse   [GFS2] Update loc...
837
  	up_write(&sdp->sd_log_flush_lock);
b3b94faa5   David Teigland   [GFS2] The core o...
838
  }
a25311c8e   Steven Whitehouse   [GFS2] Move gfs2_...
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
  
  /**
   * 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 (;;) {
  		gfs2_ail1_start(sdp, DIO_ALL);
  		if (gfs2_ail1_empty(sdp, DIO_ALL))
  			break;
  		msleep(10);
  	}
  }
ec69b1888   Steven Whitehouse   [GFS2] Move gfs2_...
856
857
858
859
860
861
862
863
864
865
866
867
  
  /**
   * 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;
ec69b1888   Steven Whitehouse   [GFS2] Move gfs2_...
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
  	unsigned long t;
  	int need_flush;
  
  	while (!kthread_should_stop()) {
  		/* Advance the log tail */
  
  		t = sdp->sd_log_flush_time +
  		    gfs2_tune_get(sdp, gt_log_flush_secs) * HZ;
  
  		gfs2_ail1_empty(sdp, DIO_ALL);
  		gfs2_log_lock(sdp);
  		need_flush = sdp->sd_log_num_buf > gfs2_tune_get(sdp, gt_incore_log_blocks);
  		gfs2_log_unlock(sdp);
  		if (need_flush || time_after_eq(jiffies, t)) {
  			gfs2_log_flush(sdp, NULL);
  			sdp->sd_log_flush_time = jiffies;
  		}
ec69b1888   Steven Whitehouse   [GFS2] Move gfs2_...
885
886
887
888
889
890
891
892
  		t = gfs2_tune_get(sdp, gt_logd_secs) * HZ;
  		if (freezing(current))
  			refrigerator();
  		schedule_timeout_interruptible(t);
  	}
  
  	return 0;
  }