Blame view

fs/reiserfs/journal.c 120 KB
b24413180   Greg Kroah-Hartman   License cleanup: ...
1
  // SPDX-License-Identifier: GPL-2.0
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
  /*
098297b27   Jeff Mahoney   reiserfs: cleanup...
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
   * Write ahead logging implementation copyright Chris Mason 2000
   *
   * The background commits make this code very interrelated, and
   * overly complex.  I need to rethink things a bit....The major players:
   *
   * journal_begin -- call with the number of blocks you expect to log.
   *                  If the current transaction is too
   *		    old, it will block until the current transaction is
   *		    finished, and then start a new one.
   *		    Usually, your transaction will get joined in with
   *                  previous ones for speed.
   *
   * journal_join  -- same as journal_begin, but won't block on the current
   *                  transaction regardless of age.  Don't ever call
   *                  this.  Ever.  There are only two places it should be
   *                  called from, and they are both inside this file.
   *
   * journal_mark_dirty -- adds blocks into this transaction.  clears any flags
   *                       that might make them get sent to disk
   *                       and then marks them BH_JDirty.  Puts the buffer head
   *                       into the current transaction hash.
   *
   * journal_end -- if the current transaction is batchable, it does nothing
   *                   otherwise, it could do an async/synchronous commit, or
   *                   a full flush of all log and real blocks in the
   *                   transaction.
   *
   * flush_old_commits -- if the current transaction is too old, it is ended and
   *                      commit blocks are sent to disk.  Forces commit blocks
   *                      to disk for all backgrounded commits that have been
   *                      around too long.
   *		     -- Note, if you call this as an immediate flush from
   *		        from within kupdate, it will ignore the immediate flag
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38
  #include <linux/time.h>
6188e10d3   Matthew Wilcox   Convert asm/semap...
39
  #include <linux/semaphore.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
  #include <linux/vmalloc.h>
f466c6fdb   Al Viro   move private bits...
41
  #include "reiserfs.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
43
44
45
46
  #include <linux/kernel.h>
  #include <linux/errno.h>
  #include <linux/fcntl.h>
  #include <linux/stat.h>
  #include <linux/string.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
47
48
49
50
  #include <linux/buffer_head.h>
  #include <linux/workqueue.h>
  #include <linux/writeback.h>
  #include <linux/blkdev.h>
3fcfab16c   Andrew Morton   [PATCH] separate ...
51
  #include <linux/backing-dev.h>
90415deac   Jeff Mahoney   reiserfs: convert...
52
  #include <linux/uaccess.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
53
  #include <linux/slab.h>
90415deac   Jeff Mahoney   reiserfs: convert...
54

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
55

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56
57
58
59
60
  /* gets a struct reiserfs_journal_list * from a list head */
  #define JOURNAL_LIST_ENTRY(h) (list_entry((h), struct reiserfs_journal_list, \
                                 j_list))
  #define JOURNAL_WORK_ENTRY(h) (list_entry((h), struct reiserfs_journal_list, \
                                 j_working_list))
098297b27   Jeff Mahoney   reiserfs: cleanup...
61
62
  /* must be correct to keep the desc and commit structs at 4k */
  #define JOURNAL_TRANS_HALF 1018
bd4c625c0   Linus Torvalds   reiserfs: run scr...
63
  #define BUFNR 64		/*read ahead */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64
65
  
  /* cnode stat bits.  Move these into reiserfs_fs.h */
098297b27   Jeff Mahoney   reiserfs: cleanup...
66
67
68
69
  /* this block was freed, and can't be written.  */
  #define BLOCK_FREED 2
  /* this block was freed during this transaction, and can't be written */
  #define BLOCK_FREED_HOLDER 3
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70

098297b27   Jeff Mahoney   reiserfs: cleanup...
71
72
  /* used in flush_journal_list */
  #define BLOCK_NEEDS_FLUSH 4
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
73
  #define BLOCK_DIRTIED 5
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
74
75
76
  /* journal list state bits */
  #define LIST_TOUCHED 1
  #define LIST_DIRTY   2
bd4c625c0   Linus Torvalds   reiserfs: run scr...
77
  #define LIST_COMMIT_PENDING  4	/* someone will commit this list */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78
79
80
81
  
  /* flags for do_journal_end */
  #define FLUSH_ALL   1		/* flush commit and real blocks */
  #define COMMIT_NOW  2		/* end and commit this transaction */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
82
  #define WAIT        4		/* wait for the log blocks to hit the disk */
58d854265   Jeff Mahoney   reiserfs: cleanup...
83
  static int do_journal_end(struct reiserfs_transaction_handle *, int flags);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
84
85
86
87
88
89
  static int flush_journal_list(struct super_block *s,
  			      struct reiserfs_journal_list *jl, int flushall);
  static int flush_commit_list(struct super_block *s,
  			     struct reiserfs_journal_list *jl, int flushall);
  static int can_dirty(struct reiserfs_journal_cnode *cn);
  static int journal_join(struct reiserfs_transaction_handle *th,
b491dd176   Jeff Mahoney   reiserfs: cleanup...
90
  			struct super_block *sb);
4385bab12   Al Viro   make blkdev_put()...
91
  static void release_journal_dev(struct super_block *super,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
92
  			       struct reiserfs_journal *journal);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
93
  static int dirty_one_transaction(struct super_block *s,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
94
  				 struct reiserfs_journal_list *jl);
c4028958b   David Howells   WorkStruct: make ...
95
  static void flush_async_commits(struct work_struct *work);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
96
97
98
99
  static void queue_log_writer(struct super_block *s);
  
  /* values for join in do_journal_begin_r */
  enum {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
100
  	JBEGIN_REG = 0,		/* regular journal begin */
098297b27   Jeff Mahoney   reiserfs: cleanup...
101
102
103
104
  	/* join the running transaction if at all possible */
  	JBEGIN_JOIN = 1,
  	/* called from cleanup code, ignores aborted flag */
  	JBEGIN_ABORT = 2,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
105
106
107
  };
  
  static int do_journal_begin_r(struct reiserfs_transaction_handle *th,
a9dd36435   Jeff Mahoney   reiserfs: rename ...
108
  			      struct super_block *sb,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
109
  			      unsigned long nblocks, int join);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
110

a9dd36435   Jeff Mahoney   reiserfs: rename ...
111
  static void init_journal_hash(struct super_block *sb)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
112
  {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
113
  	struct reiserfs_journal *journal = SB_JOURNAL(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
114
115
  	memset(journal->j_hash_table, 0,
  	       JOURNAL_HASH_SIZE * sizeof(struct reiserfs_journal_cnode *));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
116
117
118
  }
  
  /*
098297b27   Jeff Mahoney   reiserfs: cleanup...
119
120
121
122
123
   * clears BH_Dirty and sticks the buffer on the clean list.  Called because
   * I can't allow refile_buffer to make schedule happen after I've freed a
   * block.  Look at remove_from_transaction and journal_mark_freed for
   * more details.
   */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
124
125
126
127
128
129
130
  static int reiserfs_clean_and_file_buffer(struct buffer_head *bh)
  {
  	if (bh) {
  		clear_buffer_dirty(bh);
  		clear_buffer_journal_test(bh);
  	}
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
131
  }
bd4c625c0   Linus Torvalds   reiserfs: run scr...
132
  static struct reiserfs_bitmap_node *allocate_bitmap_node(struct super_block
a9dd36435   Jeff Mahoney   reiserfs: rename ...
133
  							 *sb)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
134
135
136
  {
  	struct reiserfs_bitmap_node *bn;
  	static int id;
d739b42b8   Pekka Enberg   [PATCH] reiserfs:...
137
  	bn = kmalloc(sizeof(struct reiserfs_bitmap_node), GFP_NOFS);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
138
139
140
  	if (!bn) {
  		return NULL;
  	}
a9dd36435   Jeff Mahoney   reiserfs: rename ...
141
  	bn->data = kzalloc(sb->s_blocksize, GFP_NOFS);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
142
  	if (!bn->data) {
d739b42b8   Pekka Enberg   [PATCH] reiserfs:...
143
  		kfree(bn);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
144
145
146
  		return NULL;
  	}
  	bn->id = id++;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
147
148
149
  	INIT_LIST_HEAD(&bn->list);
  	return bn;
  }
a9dd36435   Jeff Mahoney   reiserfs: rename ...
150
  static struct reiserfs_bitmap_node *get_bitmap_node(struct super_block *sb)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
151
  {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
152
  	struct reiserfs_journal *journal = SB_JOURNAL(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
153
154
155
156
  	struct reiserfs_bitmap_node *bn = NULL;
  	struct list_head *entry = journal->j_bitmap_nodes.next;
  
  	journal->j_used_bitmap_nodes++;
cf776a7a4   Jeff Mahoney   reiserfs: cleanup...
157
  repeat:
bd4c625c0   Linus Torvalds   reiserfs: run scr...
158
159
160
161
  
  	if (entry != &journal->j_bitmap_nodes) {
  		bn = list_entry(entry, struct reiserfs_bitmap_node, list);
  		list_del(entry);
a9dd36435   Jeff Mahoney   reiserfs: rename ...
162
  		memset(bn->data, 0, sb->s_blocksize);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
163
164
165
  		journal->j_free_bitmap_nodes--;
  		return bn;
  	}
a9dd36435   Jeff Mahoney   reiserfs: rename ...
166
  	bn = allocate_bitmap_node(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
167
168
169
170
171
  	if (!bn) {
  		yield();
  		goto repeat;
  	}
  	return bn;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
172
  }
a9dd36435   Jeff Mahoney   reiserfs: rename ...
173
  static inline void free_bitmap_node(struct super_block *sb,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
174
175
  				    struct reiserfs_bitmap_node *bn)
  {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
176
  	struct reiserfs_journal *journal = SB_JOURNAL(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
177
178
  	journal->j_used_bitmap_nodes--;
  	if (journal->j_free_bitmap_nodes > REISERFS_MAX_BITMAP_NODES) {
d739b42b8   Pekka Enberg   [PATCH] reiserfs:...
179
180
  		kfree(bn->data);
  		kfree(bn);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
181
182
183
184
185
  	} else {
  		list_add(&bn->list, &journal->j_bitmap_nodes);
  		journal->j_free_bitmap_nodes++;
  	}
  }
a9dd36435   Jeff Mahoney   reiserfs: rename ...
186
  static void allocate_bitmap_nodes(struct super_block *sb)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
187
188
  {
  	int i;
a9dd36435   Jeff Mahoney   reiserfs: rename ...
189
  	struct reiserfs_journal *journal = SB_JOURNAL(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
190
191
  	struct reiserfs_bitmap_node *bn = NULL;
  	for (i = 0; i < REISERFS_MIN_BITMAP_NODES; i++) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
192
  		bn = allocate_bitmap_node(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
193
194
195
196
  		if (bn) {
  			list_add(&bn->list, &journal->j_bitmap_nodes);
  			journal->j_free_bitmap_nodes++;
  		} else {
098297b27   Jeff Mahoney   reiserfs: cleanup...
197
198
  			/* this is ok, we'll try again when more are needed */
  			break;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
199
200
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
201
  }
a9dd36435   Jeff Mahoney   reiserfs: rename ...
202
  static int set_bit_in_list_bitmap(struct super_block *sb,
3ee166704   Jeff Mahoney   reiserfs: fix usa...
203
  				  b_blocknr_t block,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
204
205
  				  struct reiserfs_list_bitmap *jb)
  {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
206
207
  	unsigned int bmap_nr = block / (sb->s_blocksize << 3);
  	unsigned int bit_nr = block % (sb->s_blocksize << 3);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
208

bd4c625c0   Linus Torvalds   reiserfs: run scr...
209
  	if (!jb->bitmaps[bmap_nr]) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
210
  		jb->bitmaps[bmap_nr] = get_bitmap_node(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
211
212
213
  	}
  	set_bit(bit_nr, (unsigned long *)jb->bitmaps[bmap_nr]->data);
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
214
  }
a9dd36435   Jeff Mahoney   reiserfs: rename ...
215
  static void cleanup_bitmap_list(struct super_block *sb,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
216
217
218
219
220
  				struct reiserfs_list_bitmap *jb)
  {
  	int i;
  	if (jb->bitmaps == NULL)
  		return;
a9dd36435   Jeff Mahoney   reiserfs: rename ...
221
  	for (i = 0; i < reiserfs_bmap_count(sb); i++) {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
222
  		if (jb->bitmaps[i]) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
223
  			free_bitmap_node(sb, jb->bitmaps[i]);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
224
225
226
  			jb->bitmaps[i] = NULL;
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
227
228
229
  }
  
  /*
098297b27   Jeff Mahoney   reiserfs: cleanup...
230
231
   * only call this on FS unmount.
   */
a9dd36435   Jeff Mahoney   reiserfs: rename ...
232
  static int free_list_bitmaps(struct super_block *sb,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
233
234
235
236
237
238
239
  			     struct reiserfs_list_bitmap *jb_array)
  {
  	int i;
  	struct reiserfs_list_bitmap *jb;
  	for (i = 0; i < JOURNAL_NUM_BITMAPS; i++) {
  		jb = jb_array + i;
  		jb->journal_list = NULL;
a9dd36435   Jeff Mahoney   reiserfs: rename ...
240
  		cleanup_bitmap_list(sb, jb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
241
242
243
244
245
  		vfree(jb->bitmaps);
  		jb->bitmaps = NULL;
  	}
  	return 0;
  }
a9dd36435   Jeff Mahoney   reiserfs: rename ...
246
  static int free_bitmap_nodes(struct super_block *sb)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
247
  {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
248
  	struct reiserfs_journal *journal = SB_JOURNAL(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
249
250
251
252
253
254
  	struct list_head *next = journal->j_bitmap_nodes.next;
  	struct reiserfs_bitmap_node *bn;
  
  	while (next != &journal->j_bitmap_nodes) {
  		bn = list_entry(next, struct reiserfs_bitmap_node, list);
  		list_del(next);
d739b42b8   Pekka Enberg   [PATCH] reiserfs:...
255
256
  		kfree(bn->data);
  		kfree(bn);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
257
258
259
260
261
  		next = journal->j_bitmap_nodes.next;
  		journal->j_free_bitmap_nodes--;
  	}
  
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
262
263
264
  }
  
  /*
098297b27   Jeff Mahoney   reiserfs: cleanup...
265
266
267
   * get memory for JOURNAL_NUM_BITMAPS worth of bitmaps.
   * jb_array is the array to be filled in.
   */
a9dd36435   Jeff Mahoney   reiserfs: rename ...
268
  int reiserfs_allocate_list_bitmaps(struct super_block *sb,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
269
  				   struct reiserfs_list_bitmap *jb_array,
3ee166704   Jeff Mahoney   reiserfs: fix usa...
270
  				   unsigned int bmap_nr)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
271
272
273
274
275
276
277
278
279
  {
  	int i;
  	int failed = 0;
  	struct reiserfs_list_bitmap *jb;
  	int mem = bmap_nr * sizeof(struct reiserfs_bitmap_node *);
  
  	for (i = 0; i < JOURNAL_NUM_BITMAPS; i++) {
  		jb = jb_array + i;
  		jb->journal_list = NULL;
558feb081   Joe Perches   fs: Convert vmall...
280
  		jb->bitmaps = vzalloc(mem);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
281
  		if (!jb->bitmaps) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
282
  			reiserfs_warning(sb, "clm-2000", "unable to "
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
283
  					 "allocate bitmaps for journal lists");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
284
285
286
  			failed = 1;
  			break;
  		}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
287
288
  	}
  	if (failed) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
289
  		free_list_bitmaps(sb, jb_array);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
290
291
292
  		return -1;
  	}
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
293
294
295
  }
  
  /*
098297b27   Jeff Mahoney   reiserfs: cleanup...
296
297
298
   * find an available list bitmap.  If you can't find one, flush a commit list
   * and try again
   */
a9dd36435   Jeff Mahoney   reiserfs: rename ...
299
  static struct reiserfs_list_bitmap *get_list_bitmap(struct super_block *sb,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
300
301
302
303
  						    struct reiserfs_journal_list
  						    *jl)
  {
  	int i, j;
a9dd36435   Jeff Mahoney   reiserfs: rename ...
304
  	struct reiserfs_journal *journal = SB_JOURNAL(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
305
306
307
308
309
310
311
  	struct reiserfs_list_bitmap *jb = NULL;
  
  	for (j = 0; j < (JOURNAL_NUM_BITMAPS * 3); j++) {
  		i = journal->j_list_bitmap_index;
  		journal->j_list_bitmap_index = (i + 1) % JOURNAL_NUM_BITMAPS;
  		jb = journal->j_list_bitmap + i;
  		if (journal->j_list_bitmap[i].journal_list) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
312
  			flush_commit_list(sb,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
313
314
315
316
317
318
319
320
321
  					  journal->j_list_bitmap[i].
  					  journal_list, 1);
  			if (!journal->j_list_bitmap[i].journal_list) {
  				break;
  			}
  		} else {
  			break;
  		}
  	}
098297b27   Jeff Mahoney   reiserfs: cleanup...
322
323
  	/* double check to make sure if flushed correctly */
  	if (jb->journal_list)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
324
  		return NULL;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
325
326
  	jb->journal_list = jl;
  	return jb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
327
  }
0222e6571   Jeff Mahoney   reiserfs: strip t...
328
  /*
098297b27   Jeff Mahoney   reiserfs: cleanup...
329
330
331
332
   * allocates a new chunk of X nodes, and links them all together as a list.
   * Uses the cnode->next and cnode->prev pointers
   * returns NULL on failure
   */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
333
334
335
336
337
338
339
  static struct reiserfs_journal_cnode *allocate_cnodes(int num_cnodes)
  {
  	struct reiserfs_journal_cnode *head;
  	int i;
  	if (num_cnodes <= 0) {
  		return NULL;
  	}
558feb081   Joe Perches   fs: Convert vmall...
340
  	head = vzalloc(num_cnodes * sizeof(struct reiserfs_journal_cnode));
bd4c625c0   Linus Torvalds   reiserfs: run scr...
341
342
343
  	if (!head) {
  		return NULL;
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
344
345
346
347
348
349
350
351
  	head[0].prev = NULL;
  	head[0].next = head + 1;
  	for (i = 1; i < num_cnodes; i++) {
  		head[i].prev = head + (i - 1);
  		head[i].next = head + (i + 1);	/* if last one, overwrite it after the if */
  	}
  	head[num_cnodes - 1].next = NULL;
  	return head;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
352
  }
098297b27   Jeff Mahoney   reiserfs: cleanup...
353
  /* pulls a cnode off the free list, or returns NULL on failure */
a9dd36435   Jeff Mahoney   reiserfs: rename ...
354
  static struct reiserfs_journal_cnode *get_cnode(struct super_block *sb)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
355
356
  {
  	struct reiserfs_journal_cnode *cn;
a9dd36435   Jeff Mahoney   reiserfs: rename ...
357
  	struct reiserfs_journal *journal = SB_JOURNAL(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
358

a9dd36435   Jeff Mahoney   reiserfs: rename ...
359
  	reiserfs_check_lock_depth(sb, "get_cnode");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
  
  	if (journal->j_cnode_free <= 0) {
  		return NULL;
  	}
  	journal->j_cnode_used++;
  	journal->j_cnode_free--;
  	cn = journal->j_cnode_free_list;
  	if (!cn) {
  		return cn;
  	}
  	if (cn->next) {
  		cn->next->prev = NULL;
  	}
  	journal->j_cnode_free_list = cn->next;
  	memset(cn, 0, sizeof(struct reiserfs_journal_cnode));
  	return cn;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
376
377
378
  }
  
  /*
098297b27   Jeff Mahoney   reiserfs: cleanup...
379
380
   * returns a cnode to the free list
   */
a9dd36435   Jeff Mahoney   reiserfs: rename ...
381
  static void free_cnode(struct super_block *sb,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
382
383
  		       struct reiserfs_journal_cnode *cn)
  {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
384
  	struct reiserfs_journal *journal = SB_JOURNAL(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
385

a9dd36435   Jeff Mahoney   reiserfs: rename ...
386
  	reiserfs_check_lock_depth(sb, "free_cnode");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
387

bd4c625c0   Linus Torvalds   reiserfs: run scr...
388
389
390
391
392
393
394
395
396
  	journal->j_cnode_used--;
  	journal->j_cnode_free++;
  	/* memset(cn, 0, sizeof(struct reiserfs_journal_cnode)) ; */
  	cn->next = journal->j_cnode_free_list;
  	if (journal->j_cnode_free_list) {
  		journal->j_cnode_free_list->prev = cn;
  	}
  	cn->prev = NULL;	/* not needed with the memset, but I might kill the memset, and forget to do this */
  	journal->j_cnode_free_list = cn;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
397
  }
bd4c625c0   Linus Torvalds   reiserfs: run scr...
398
399
400
401
  static void clear_prepared_bits(struct buffer_head *bh)
  {
  	clear_buffer_journal_prepared(bh);
  	clear_buffer_journal_restore_dirty(bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
402
  }
098297b27   Jeff Mahoney   reiserfs: cleanup...
403
404
405
406
  /*
   * return a cnode with same dev, block number and size in table,
   * or null if not found
   */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
407
408
409
410
411
412
413
  static inline struct reiserfs_journal_cnode *get_journal_hash_dev(struct
  								  super_block
  								  *sb,
  								  struct
  								  reiserfs_journal_cnode
  								  **table,
  								  long bl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
414
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
415
416
417
418
419
420
421
422
  	struct reiserfs_journal_cnode *cn;
  	cn = journal_hash(table, sb, bl);
  	while (cn) {
  		if (cn->blocknr == bl && cn->sb == sb)
  			return cn;
  		cn = cn->hnext;
  	}
  	return (struct reiserfs_journal_cnode *)0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
423
424
425
  }
  
  /*
098297b27   Jeff Mahoney   reiserfs: cleanup...
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
   * this actually means 'can this block be reallocated yet?'.  If you set
   * search_all, a block can only be allocated if it is not in the current
   * transaction, was not freed by the current transaction, and has no chance
   * of ever being overwritten by a replay after crashing.
   *
   * If you don't set search_all, a block can only be allocated if it is not
   * in the current transaction.  Since deleting a block removes it from the
   * current transaction, this case should never happen.  If you don't set
   * search_all, make sure you never write the block without logging it.
   *
   * next_zero_bit is a suggestion about the next block to try for find_forward.
   * when bl is rejected because it is set in a journal list bitmap, we search
   * for the next zero bit in the bitmap that rejected bl.  Then, we return
   * that through next_zero_bit for find_forward to try.
   *
   * Just because we return something in next_zero_bit does not mean we won't
   * reject it on the next call to reiserfs_in_journal
   */
a9dd36435   Jeff Mahoney   reiserfs: rename ...
444
  int reiserfs_in_journal(struct super_block *sb,
3ee166704   Jeff Mahoney   reiserfs: fix usa...
445
  			unsigned int bmap_nr, int bit_nr, int search_all,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
446
447
  			b_blocknr_t * next_zero_bit)
  {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
448
  	struct reiserfs_journal *journal = SB_JOURNAL(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
449
450
451
452
453
454
  	struct reiserfs_journal_cnode *cn;
  	struct reiserfs_list_bitmap *jb;
  	int i;
  	unsigned long bl;
  
  	*next_zero_bit = 0;	/* always start this at zero. */
a9dd36435   Jeff Mahoney   reiserfs: rename ...
455
  	PROC_INFO_INC(sb, journal.in_journal);
098297b27   Jeff Mahoney   reiserfs: cleanup...
456
457
458
459
460
  	/*
  	 * If we aren't doing a search_all, this is a metablock, and it
  	 * will be logged before use.  if we crash before the transaction
  	 * that freed it commits,  this transaction won't have committed
  	 * either, and the block will never be written
bd4c625c0   Linus Torvalds   reiserfs: run scr...
461
462
463
  	 */
  	if (search_all) {
  		for (i = 0; i < JOURNAL_NUM_BITMAPS; i++) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
464
  			PROC_INFO_INC(sb, journal.in_journal_bitmap);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
465
466
467
468
469
470
471
472
473
  			jb = journal->j_list_bitmap + i;
  			if (jb->journal_list && jb->bitmaps[bmap_nr] &&
  			    test_bit(bit_nr,
  				     (unsigned long *)jb->bitmaps[bmap_nr]->
  				     data)) {
  				*next_zero_bit =
  				    find_next_zero_bit((unsigned long *)
  						       (jb->bitmaps[bmap_nr]->
  							data),
a9dd36435   Jeff Mahoney   reiserfs: rename ...
474
  						       sb->s_blocksize << 3,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
475
476
477
478
479
  						       bit_nr + 1);
  				return 1;
  			}
  		}
  	}
a9dd36435   Jeff Mahoney   reiserfs: rename ...
480
  	bl = bmap_nr * (sb->s_blocksize << 3) + bit_nr;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
481
482
483
  	/* is it in any old transactions? */
  	if (search_all
  	    && (cn =
a9dd36435   Jeff Mahoney   reiserfs: rename ...
484
  		get_journal_hash_dev(sb, journal->j_list_hash_table, bl))) {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
485
486
487
488
  		return 1;
  	}
  
  	/* is it in the current transaction.  This should never happen */
a9dd36435   Jeff Mahoney   reiserfs: rename ...
489
  	if ((cn = get_journal_hash_dev(sb, journal->j_hash_table, bl))) {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
490
491
492
  		BUG();
  		return 1;
  	}
a9dd36435   Jeff Mahoney   reiserfs: rename ...
493
  	PROC_INFO_INC(sb, journal.in_journal_reusable);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
494
495
  	/* safe for reuse */
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
496
  }
098297b27   Jeff Mahoney   reiserfs: cleanup...
497
  /* insert cn into table */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
498
499
500
501
  static inline void insert_journal_hash(struct reiserfs_journal_cnode **table,
  				       struct reiserfs_journal_cnode *cn)
  {
  	struct reiserfs_journal_cnode *cn_orig;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
502

bd4c625c0   Linus Torvalds   reiserfs: run scr...
503
504
505
506
507
508
509
  	cn_orig = journal_hash(table, cn->sb, cn->blocknr);
  	cn->hnext = cn_orig;
  	cn->hprev = NULL;
  	if (cn_orig) {
  		cn_orig->hprev = cn;
  	}
  	journal_hash(table, cn->sb, cn->blocknr) = cn;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
510
511
512
  }
  
  /* lock the current transaction */
a9dd36435   Jeff Mahoney   reiserfs: rename ...
513
  static inline void lock_journal(struct super_block *sb)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
514
  {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
515
  	PROC_INFO_INC(sb, journal.lock_journal);
8ebc42323   Frederic Weisbecker   reiserfs: kill-th...
516
517
  
  	reiserfs_mutex_lock_safe(&SB_JOURNAL(sb)->j_mutex, sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
518
519
520
  }
  
  /* unlock the current transaction */
a9dd36435   Jeff Mahoney   reiserfs: rename ...
521
  static inline void unlock_journal(struct super_block *sb)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
522
  {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
523
  	mutex_unlock(&SB_JOURNAL(sb)->j_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
524
525
526
527
  }
  
  static inline void get_journal_list(struct reiserfs_journal_list *jl)
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
528
  	jl->j_refcount++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
529
530
531
  }
  
  static inline void put_journal_list(struct super_block *s,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
532
  				    struct reiserfs_journal_list *jl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
533
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
534
  	if (jl->j_refcount < 1) {
c3a9c2109   Jeff Mahoney   reiserfs: rework ...
535
  		reiserfs_panic(s, "journal-2", "trans id %u, refcount at %d",
bd4c625c0   Linus Torvalds   reiserfs: run scr...
536
537
538
  			       jl->j_trans_id, jl->j_refcount);
  	}
  	if (--jl->j_refcount == 0)
d739b42b8   Pekka Enberg   [PATCH] reiserfs:...
539
  		kfree(jl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
540
541
542
  }
  
  /*
098297b27   Jeff Mahoney   reiserfs: cleanup...
543
544
545
546
   * this used to be much more involved, and I'm keeping it just in case
   * things get ugly again.  it gets called by flush_commit_list, and
   * cleans up any data stored about blocks freed during a transaction.
   */
a9dd36435   Jeff Mahoney   reiserfs: rename ...
547
  static void cleanup_freed_for_journal_list(struct super_block *sb,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
548
549
  					   struct reiserfs_journal_list *jl)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
550

bd4c625c0   Linus Torvalds   reiserfs: run scr...
551
552
  	struct reiserfs_list_bitmap *jb = jl->j_list_bitmap;
  	if (jb) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
553
  		cleanup_bitmap_list(sb, jb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
554
555
556
  	}
  	jl->j_list_bitmap->journal_list = NULL;
  	jl->j_list_bitmap = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
557
558
559
  }
  
  static int journal_list_still_alive(struct super_block *s,
600ed4167   Jeff Mahoney   reiserfs: audit t...
560
  				    unsigned int trans_id)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
561
562
563
564
565
566
567
568
569
570
571
572
573
  {
  	struct reiserfs_journal *journal = SB_JOURNAL(s);
  	struct list_head *entry = &journal->j_journal_list;
  	struct reiserfs_journal_list *jl;
  
  	if (!list_empty(entry)) {
  		jl = JOURNAL_LIST_ENTRY(entry->next);
  		if (jl->j_trans_id <= trans_id) {
  			return 1;
  		}
  	}
  	return 0;
  }
398c95bdf   Chris Mason   try to reap reise...
574
575
576
577
578
579
580
581
  /*
   * If page->mapping was null, we failed to truncate this page for
   * some reason.  Most likely because it was truncated after being
   * logged via data=journal.
   *
   * This does a check to see if the buffer belongs to one of these
   * lost pages before doing the final put_bh.  If page->mapping was
   * null, it tries to free buffers on the page, which should make the
ea1754a08   Kirill A. Shutemov   mm, fs: remove re...
582
   * final put_page drop the page from the lru.
398c95bdf   Chris Mason   try to reap reise...
583
584
585
586
   */
  static void release_buffer_page(struct buffer_head *bh)
  {
  	struct page *page = bh->b_page;
529ae9aaa   Nick Piggin   mm: rename page t...
587
  	if (!page->mapping && trylock_page(page)) {
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
588
  		get_page(page);
398c95bdf   Chris Mason   try to reap reise...
589
590
591
592
  		put_bh(bh);
  		if (!page->mapping)
  			try_to_free_buffers(page);
  		unlock_page(page);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
593
  		put_page(page);
398c95bdf   Chris Mason   try to reap reise...
594
595
596
597
  	} else {
  		put_bh(bh);
  	}
  }
bd4c625c0   Linus Torvalds   reiserfs: run scr...
598
599
  static void reiserfs_end_buffer_io_sync(struct buffer_head *bh, int uptodate)
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
600
  	if (buffer_journaled(bh)) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
601
  		reiserfs_warning(NULL, "clm-2084",
a1c6f0573   Dmitry Monakhov   fs: use block_dev...
602
603
  				 "pinned buffer %lu:%pg sent to disk",
  				 bh->b_blocknr, bh->b_bdev);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
604
605
606
607
608
  	}
  	if (uptodate)
  		set_buffer_uptodate(bh);
  	else
  		clear_buffer_uptodate(bh);
398c95bdf   Chris Mason   try to reap reise...
609

bd4c625c0   Linus Torvalds   reiserfs: run scr...
610
  	unlock_buffer(bh);
398c95bdf   Chris Mason   try to reap reise...
611
  	release_buffer_page(bh);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
  }
  
  static void reiserfs_end_ordered_io(struct buffer_head *bh, int uptodate)
  {
  	if (uptodate)
  		set_buffer_uptodate(bh);
  	else
  		clear_buffer_uptodate(bh);
  	unlock_buffer(bh);
  	put_bh(bh);
  }
  
  static void submit_logged_buffer(struct buffer_head *bh)
  {
  	get_bh(bh);
  	bh->b_end_io = reiserfs_end_buffer_io_sync;
  	clear_buffer_journal_new(bh);
  	clear_buffer_dirty(bh);
  	if (!test_clear_buffer_journal_test(bh))
  		BUG();
  	if (!buffer_uptodate(bh))
  		BUG();
2a222ca99   Mike Christie   fs: have submit_b...
634
  	submit_bh(REQ_OP_WRITE, 0, bh);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
635
636
637
638
639
640
641
642
643
  }
  
  static void submit_ordered_buffer(struct buffer_head *bh)
  {
  	get_bh(bh);
  	bh->b_end_io = reiserfs_end_ordered_io;
  	clear_buffer_dirty(bh);
  	if (!buffer_uptodate(bh))
  		BUG();
2a222ca99   Mike Christie   fs: have submit_b...
644
  	submit_bh(REQ_OP_WRITE, 0, bh);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
645
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
646
647
  #define CHUNK_SIZE 32
  struct buffer_chunk {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
648
649
  	struct buffer_head *bh[CHUNK_SIZE];
  	int nr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
650
  };
bd4c625c0   Linus Torvalds   reiserfs: run scr...
651
652
653
  static void write_chunk(struct buffer_chunk *chunk)
  {
  	int i;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
654
655
656
657
  	for (i = 0; i < chunk->nr; i++) {
  		submit_logged_buffer(chunk->bh[i]);
  	}
  	chunk->nr = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
658
  }
bd4c625c0   Linus Torvalds   reiserfs: run scr...
659
660
661
  static void write_ordered_chunk(struct buffer_chunk *chunk)
  {
  	int i;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
662
663
664
665
  	for (i = 0; i < chunk->nr; i++) {
  		submit_ordered_buffer(chunk->bh[i]);
  	}
  	chunk->nr = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
666
667
668
  }
  
  static int add_to_chunk(struct buffer_chunk *chunk, struct buffer_head *bh,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
669
  			spinlock_t * lock, void (fn) (struct buffer_chunk *))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
670
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
671
  	int ret = 0;
14a61442c   Eric Sesterhenn   BUG_ON conversion...
672
  	BUG_ON(chunk->nr >= CHUNK_SIZE);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
673
674
675
  	chunk->bh[chunk->nr++] = bh;
  	if (chunk->nr >= CHUNK_SIZE) {
  		ret = 1;
54cc6cea7   Fabian Frederick   fs/reiserfs/journ...
676
  		if (lock) {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
677
  			spin_unlock(lock);
54cc6cea7   Fabian Frederick   fs/reiserfs/journ...
678
  			fn(chunk);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
679
  			spin_lock(lock);
54cc6cea7   Fabian Frederick   fs/reiserfs/journ...
680
681
682
  		} else {
  			fn(chunk);
  		}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
683
684
  	}
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
685
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
686
  static atomic_t nr_reiserfs_jh = ATOMIC_INIT(0);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
687
688
689
690
691
692
693
694
695
696
  static struct reiserfs_jh *alloc_jh(void)
  {
  	struct reiserfs_jh *jh;
  	while (1) {
  		jh = kmalloc(sizeof(*jh), GFP_NOFS);
  		if (jh) {
  			atomic_inc(&nr_reiserfs_jh);
  			return jh;
  		}
  		yield();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
697
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
698
699
700
701
702
703
  }
  
  /*
   * we want to free the jh when the buffer has been written
   * and waited on
   */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
  void reiserfs_free_jh(struct buffer_head *bh)
  {
  	struct reiserfs_jh *jh;
  
  	jh = bh->b_private;
  	if (jh) {
  		bh->b_private = NULL;
  		jh->bh = NULL;
  		list_del_init(&jh->list);
  		kfree(jh);
  		if (atomic_read(&nr_reiserfs_jh) <= 0)
  			BUG();
  		atomic_dec(&nr_reiserfs_jh);
  		put_bh(bh);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
719
720
721
  }
  
  static inline int __add_jh(struct reiserfs_journal *j, struct buffer_head *bh,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
722
  			   int tail)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
723
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
724
  	struct reiserfs_jh *jh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
725

bd4c625c0   Linus Torvalds   reiserfs: run scr...
726
727
728
729
730
731
732
733
734
  	if (bh->b_private) {
  		spin_lock(&j->j_dirty_buffers_lock);
  		if (!bh->b_private) {
  			spin_unlock(&j->j_dirty_buffers_lock);
  			goto no_jh;
  		}
  		jh = bh->b_private;
  		list_del_init(&jh->list);
  	} else {
cf776a7a4   Jeff Mahoney   reiserfs: cleanup...
735
  no_jh:
bd4c625c0   Linus Torvalds   reiserfs: run scr...
736
737
738
  		get_bh(bh);
  		jh = alloc_jh();
  		spin_lock(&j->j_dirty_buffers_lock);
098297b27   Jeff Mahoney   reiserfs: cleanup...
739
740
  		/*
  		 * buffer must be locked for __add_jh, should be able to have
bd4c625c0   Linus Torvalds   reiserfs: run scr...
741
742
  		 * two adds at the same time
  		 */
14a61442c   Eric Sesterhenn   BUG_ON conversion...
743
  		BUG_ON(bh->b_private);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
744
745
  		jh->bh = bh;
  		bh->b_private = jh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
746
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
747
748
749
750
751
752
753
754
  	jh->jl = j->j_current_jl;
  	if (tail)
  		list_add_tail(&jh->list, &jh->jl->j_tail_bh_list);
  	else {
  		list_add_tail(&jh->list, &jh->jl->j_bh_list);
  	}
  	spin_unlock(&j->j_dirty_buffers_lock);
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
755
  }
bd4c625c0   Linus Torvalds   reiserfs: run scr...
756
757
758
  int reiserfs_add_tail_list(struct inode *inode, struct buffer_head *bh)
  {
  	return __add_jh(SB_JOURNAL(inode->i_sb), bh, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
759
  }
bd4c625c0   Linus Torvalds   reiserfs: run scr...
760
761
762
  int reiserfs_add_ordered_list(struct inode *inode, struct buffer_head *bh)
  {
  	return __add_jh(SB_JOURNAL(inode->i_sb), bh, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
763
764
765
  }
  
  #define JH_ENTRY(l) list_entry((l), struct reiserfs_jh, list)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
766
  static int write_ordered_buffers(spinlock_t * lock,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
767
  				 struct reiserfs_journal *j,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
768
  				 struct reiserfs_journal_list *jl,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
769
770
  				 struct list_head *list)
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
771
772
773
774
775
776
777
778
779
780
781
782
783
  	struct buffer_head *bh;
  	struct reiserfs_jh *jh;
  	int ret = j->j_errno;
  	struct buffer_chunk chunk;
  	struct list_head tmp;
  	INIT_LIST_HEAD(&tmp);
  
  	chunk.nr = 0;
  	spin_lock(lock);
  	while (!list_empty(list)) {
  		jh = JH_ENTRY(list->next);
  		bh = jh->bh;
  		get_bh(bh);
ca5de404f   Nick Piggin   fs: rename buffer...
784
  		if (!trylock_buffer(bh)) {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
785
  			if (!buffer_dirty(bh)) {
f116629d0   Akinobu Mita   [PATCH] fs: use l...
786
  				list_move(&jh->list, &tmp);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
787
788
789
790
791
792
793
794
795
796
  				goto loop_next;
  			}
  			spin_unlock(lock);
  			if (chunk.nr)
  				write_ordered_chunk(&chunk);
  			wait_on_buffer(bh);
  			cond_resched();
  			spin_lock(lock);
  			goto loop_next;
  		}
098297b27   Jeff Mahoney   reiserfs: cleanup...
797
798
  		/*
  		 * in theory, dirty non-uptodate buffers should never get here,
3d4492f81   Chris Mason   [PATCH] reiserfs:...
799
800
801
802
803
804
805
  		 * but the upper layer io error paths still have a few quirks.
  		 * Handle them here as gracefully as we can
  		 */
  		if (!buffer_uptodate(bh) && buffer_dirty(bh)) {
  			clear_buffer_dirty(bh);
  			ret = -EIO;
  		}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
806
  		if (buffer_dirty(bh)) {
f116629d0   Akinobu Mita   [PATCH] fs: use l...
807
  			list_move(&jh->list, &tmp);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
808
809
810
811
812
  			add_to_chunk(&chunk, bh, lock, write_ordered_chunk);
  		} else {
  			reiserfs_free_jh(bh);
  			unlock_buffer(bh);
  		}
cf776a7a4   Jeff Mahoney   reiserfs: cleanup...
813
  loop_next:
bd4c625c0   Linus Torvalds   reiserfs: run scr...
814
815
816
817
818
  		put_bh(bh);
  		cond_resched_lock(lock);
  	}
  	if (chunk.nr) {
  		spin_unlock(lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
819
  		write_ordered_chunk(&chunk);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
820
  		spin_lock(lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
821
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
822
823
824
825
826
827
828
829
830
831
832
833
834
835
  	while (!list_empty(&tmp)) {
  		jh = JH_ENTRY(tmp.prev);
  		bh = jh->bh;
  		get_bh(bh);
  		reiserfs_free_jh(bh);
  
  		if (buffer_locked(bh)) {
  			spin_unlock(lock);
  			wait_on_buffer(bh);
  			spin_lock(lock);
  		}
  		if (!buffer_uptodate(bh)) {
  			ret = -EIO;
  		}
098297b27   Jeff Mahoney   reiserfs: cleanup...
836
837
838
839
840
841
842
843
  		/*
  		 * ugly interaction with invalidatepage here.
  		 * reiserfs_invalidate_page will pin any buffer that has a
  		 * valid journal head from an older transaction.  If someone
  		 * else sets our buffer dirty after we write it in the first
  		 * loop, and then someone truncates the page away, nobody
  		 * will ever write the buffer. We're safe if we write the
  		 * page one last time after freeing the journal header.
d62b1b87a   Chris Mason   [PATCH] resierfs:...
844
845
846
  		 */
  		if (buffer_dirty(bh) && unlikely(bh->b_page->mapping == NULL)) {
  			spin_unlock(lock);
dfec8a14f   Mike Christie   fs: have ll_rw_bl...
847
  			ll_rw_block(REQ_OP_WRITE, 0, 1, &bh);
d62b1b87a   Chris Mason   [PATCH] resierfs:...
848
849
  			spin_lock(lock);
  		}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
850
851
  		put_bh(bh);
  		cond_resched_lock(lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
852
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
853
854
855
  	spin_unlock(lock);
  	return ret;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
856

bd4c625c0   Linus Torvalds   reiserfs: run scr...
857
858
859
860
861
862
863
  static int flush_older_commits(struct super_block *s,
  			       struct reiserfs_journal_list *jl)
  {
  	struct reiserfs_journal *journal = SB_JOURNAL(s);
  	struct reiserfs_journal_list *other_jl;
  	struct reiserfs_journal_list *first_jl;
  	struct list_head *entry;
600ed4167   Jeff Mahoney   reiserfs: audit t...
864
865
866
  	unsigned int trans_id = jl->j_trans_id;
  	unsigned int other_trans_id;
  	unsigned int first_trans_id;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
867

cf776a7a4   Jeff Mahoney   reiserfs: cleanup...
868
  find_first:
bd4c625c0   Linus Torvalds   reiserfs: run scr...
869
870
871
872
873
874
875
876
877
878
  	/*
  	 * first we walk backwards to find the oldest uncommitted transation
  	 */
  	first_jl = jl;
  	entry = jl->j_list.prev;
  	while (1) {
  		other_jl = JOURNAL_LIST_ENTRY(entry);
  		if (entry == &journal->j_journal_list ||
  		    atomic_read(&other_jl->j_older_commits_done))
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
879

bd4c625c0   Linus Torvalds   reiserfs: run scr...
880
881
882
  		first_jl = other_jl;
  		entry = other_jl->j_list.prev;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
883

bd4c625c0   Linus Torvalds   reiserfs: run scr...
884
885
886
887
  	/* if we didn't find any older uncommitted transactions, return now */
  	if (first_jl == jl) {
  		return 0;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
888

bd4c625c0   Linus Torvalds   reiserfs: run scr...
889
890
891
892
893
894
895
896
897
898
899
900
901
902
  	first_trans_id = first_jl->j_trans_id;
  
  	entry = &first_jl->j_list;
  	while (1) {
  		other_jl = JOURNAL_LIST_ENTRY(entry);
  		other_trans_id = other_jl->j_trans_id;
  
  		if (other_trans_id < trans_id) {
  			if (atomic_read(&other_jl->j_commit_left) != 0) {
  				flush_commit_list(s, other_jl, 0);
  
  				/* list we were called with is gone, return */
  				if (!journal_list_still_alive(s, trans_id))
  					return 1;
098297b27   Jeff Mahoney   reiserfs: cleanup...
903
904
905
906
907
  				/*
  				 * the one we just flushed is gone, this means
  				 * all older lists are also gone, so first_jl
  				 * is no longer valid either.  Go back to the
  				 * beginning.
bd4c625c0   Linus Torvalds   reiserfs: run scr...
908
909
910
911
912
913
914
915
916
917
918
  				 */
  				if (!journal_list_still_alive
  				    (s, other_trans_id)) {
  					goto find_first;
  				}
  			}
  			entry = entry->next;
  			if (entry == &journal->j_journal_list)
  				return 0;
  		} else {
  			return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
919
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
920
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
921
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
922
  }
deba0f49b   Adrian Bunk   fs/reiserfs/: cle...
923
924
  
  static int reiserfs_async_progress_wait(struct super_block *s)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
925
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
926
  	struct reiserfs_journal *j = SB_JOURNAL(s);
8ebc42323   Frederic Weisbecker   reiserfs: kill-th...
927
928
  
  	if (atomic_read(&j->j_async_throttle)) {
278f6679f   Jeff Mahoney   reiserfs: locking...
929
930
931
  		int depth;
  
  		depth = reiserfs_write_unlock_nested(s);
8aa7e847d   Jens Axboe   Fix congestion_wa...
932
  		congestion_wait(BLK_RW_ASYNC, HZ / 10);
278f6679f   Jeff Mahoney   reiserfs: locking...
933
  		reiserfs_write_lock_nested(s, depth);
8ebc42323   Frederic Weisbecker   reiserfs: kill-th...
934
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
935
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
936
937
938
  }
  
  /*
098297b27   Jeff Mahoney   reiserfs: cleanup...
939
940
941
942
943
944
   * if this journal list still has commit blocks unflushed, send them to disk.
   *
   * log areas must be flushed in order (transaction 2 can't commit before
   * transaction 1) Before the commit block can by written, every other log
   * block must be safely on disk
   */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
945
946
947
948
  static int flush_commit_list(struct super_block *s,
  			     struct reiserfs_journal_list *jl, int flushall)
  {
  	int i;
3ee166704   Jeff Mahoney   reiserfs: fix usa...
949
  	b_blocknr_t bn;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
950
  	struct buffer_head *tbh = NULL;
600ed4167   Jeff Mahoney   reiserfs: audit t...
951
  	unsigned int trans_id = jl->j_trans_id;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
952
  	struct reiserfs_journal *journal = SB_JOURNAL(s);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
953
  	int retval = 0;
e0e851cf3   Chris Mason   [PATCH] reiserfs:...
954
  	int write_len;
278f6679f   Jeff Mahoney   reiserfs: locking...
955
  	int depth;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
956
957
958
959
960
961
  
  	reiserfs_check_lock_depth(s, "flush_commit_list");
  
  	if (atomic_read(&jl->j_older_commits_done)) {
  		return 0;
  	}
098297b27   Jeff Mahoney   reiserfs: cleanup...
962
963
964
  	/*
  	 * before we can put our commit blocks on disk, we have to make
  	 * sure everyone older than us is on disk too
bd4c625c0   Linus Torvalds   reiserfs: run scr...
965
966
967
968
969
970
971
  	 */
  	BUG_ON(jl->j_len <= 0);
  	BUG_ON(trans_id == journal->j_trans_id);
  
  	get_journal_list(jl);
  	if (flushall) {
  		if (flush_older_commits(s, jl) == 1) {
098297b27   Jeff Mahoney   reiserfs: cleanup...
972
973
974
975
  			/*
  			 * list disappeared during flush_older_commits.
  			 * return
  			 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
976
977
978
979
980
  			goto put_jl;
  		}
  	}
  
  	/* make sure nobody is trying to flush this one at the same time */
8ebc42323   Frederic Weisbecker   reiserfs: kill-th...
981
  	reiserfs_mutex_lock_safe(&jl->j_commit_mutex, s);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
982
  	if (!journal_list_still_alive(s, trans_id)) {
90415deac   Jeff Mahoney   reiserfs: convert...
983
  		mutex_unlock(&jl->j_commit_mutex);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
984
985
986
987
988
  		goto put_jl;
  	}
  	BUG_ON(jl->j_trans_id == 0);
  
  	/* this commit is done, exit */
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
989
  	if (atomic_read(&jl->j_commit_left) <= 0) {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
990
  		if (flushall) {
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
991
  			atomic_set(&jl->j_older_commits_done, 1);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
992
  		}
90415deac   Jeff Mahoney   reiserfs: convert...
993
  		mutex_unlock(&jl->j_commit_mutex);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
994
995
996
997
  		goto put_jl;
  	}
  
  	if (!list_empty(&jl->j_bh_list)) {
3d4492f81   Chris Mason   [PATCH] reiserfs:...
998
  		int ret;
8ebc42323   Frederic Weisbecker   reiserfs: kill-th...
999
1000
1001
1002
1003
  
  		/*
  		 * We might sleep in numerous places inside
  		 * write_ordered_buffers. Relax the write lock.
  		 */
278f6679f   Jeff Mahoney   reiserfs: locking...
1004
  		depth = reiserfs_write_unlock_nested(s);
3d4492f81   Chris Mason   [PATCH] reiserfs:...
1005
1006
1007
1008
  		ret = write_ordered_buffers(&journal->j_dirty_buffers_lock,
  					    journal, jl, &jl->j_bh_list);
  		if (ret < 0 && retval == 0)
  			retval = ret;
278f6679f   Jeff Mahoney   reiserfs: locking...
1009
  		reiserfs_write_lock_nested(s, depth);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1010
1011
1012
1013
  	}
  	BUG_ON(!list_empty(&jl->j_bh_list));
  	/*
  	 * for the description block and all the log blocks, submit any buffers
e0e851cf3   Chris Mason   [PATCH] reiserfs:...
1014
1015
1016
1017
  	 * that haven't already reached the disk.  Try to write at least 256
  	 * log blocks. later on, we will only wait on blocks that correspond
  	 * to this transaction, but while we're unplugging we might as well
  	 * get a chunk of data on there.
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1018
1019
  	 */
  	atomic_inc(&journal->j_async_throttle);
e0e851cf3   Chris Mason   [PATCH] reiserfs:...
1020
1021
1022
1023
  	write_len = jl->j_len + 1;
  	if (write_len < 256)
  		write_len = 256;
  	for (i = 0 ; i < write_len ; i++) {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1024
1025
1026
  		bn = SB_ONDISK_JOURNAL_1st_BLOCK(s) + (jl->j_start + i) %
  		    SB_ONDISK_JOURNAL_SIZE(s);
  		tbh = journal_find_get_block(s, bn);
e0e851cf3   Chris Mason   [PATCH] reiserfs:...
1027
  		if (tbh) {
6e3647acb   Frederic Weisbecker   kill-the-BKL/reis...
1028
  			if (buffer_dirty(tbh)) {
278f6679f   Jeff Mahoney   reiserfs: locking...
1029
  		            depth = reiserfs_write_unlock_nested(s);
dfec8a14f   Mike Christie   fs: have ll_rw_bl...
1030
  			    ll_rw_block(REQ_OP_WRITE, 0, 1, &tbh);
278f6679f   Jeff Mahoney   reiserfs: locking...
1031
  			    reiserfs_write_lock_nested(s, depth);
6e3647acb   Frederic Weisbecker   kill-the-BKL/reis...
1032
  			}
e0e851cf3   Chris Mason   [PATCH] reiserfs:...
1033
1034
  			put_bh(tbh) ;
  		}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1035
1036
  	}
  	atomic_dec(&journal->j_async_throttle);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1037
1038
1039
1040
  	for (i = 0; i < (jl->j_len + 1); i++) {
  		bn = SB_ONDISK_JOURNAL_1st_BLOCK(s) +
  		    (jl->j_start + i) % SB_ONDISK_JOURNAL_SIZE(s);
  		tbh = journal_find_get_block(s, bn);
8ebc42323   Frederic Weisbecker   reiserfs: kill-th...
1041

278f6679f   Jeff Mahoney   reiserfs: locking...
1042
1043
1044
  		depth = reiserfs_write_unlock_nested(s);
  		__wait_on_buffer(tbh);
  		reiserfs_write_lock_nested(s, depth);
098297b27   Jeff Mahoney   reiserfs: cleanup...
1045
1046
1047
1048
  		/*
  		 * since we're using ll_rw_blk above, it might have skipped
  		 * over a locked buffer.  Double check here
  		 */
8ebc42323   Frederic Weisbecker   reiserfs: kill-th...
1049
1050
  		/* redundant, sync_dirty_buffer() checks */
  		if (buffer_dirty(tbh)) {
278f6679f   Jeff Mahoney   reiserfs: locking...
1051
  			depth = reiserfs_write_unlock_nested(s);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1052
  			sync_dirty_buffer(tbh);
278f6679f   Jeff Mahoney   reiserfs: locking...
1053
  			reiserfs_write_lock_nested(s, depth);
8ebc42323   Frederic Weisbecker   reiserfs: kill-th...
1054
  		}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1055
  		if (unlikely(!buffer_uptodate(tbh))) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1056
  #ifdef CONFIG_REISERFS_CHECK
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1057
1058
  			reiserfs_warning(s, "journal-601",
  					 "buffer write failed");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1059
  #endif
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1060
1061
  			retval = -EIO;
  		}
098297b27   Jeff Mahoney   reiserfs: cleanup...
1062
1063
1064
1065
  		/* once for journal_find_get_block */
  		put_bh(tbh);
  		/* once due to original getblk in do_journal_end */
  		put_bh(tbh);
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
1066
  		atomic_dec(&jl->j_commit_left);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1067
  	}
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
1068
  	BUG_ON(atomic_read(&jl->j_commit_left) != 1);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1069

098297b27   Jeff Mahoney   reiserfs: cleanup...
1070
1071
  	/*
  	 * If there was a write error in the journal - we can't commit
7cd33ad23   Christoph Hellwig   reiserfs: replace...
1072
1073
  	 * this transaction - it will be invalid and, if successful,
  	 * will just end up propagating the write error out to
098297b27   Jeff Mahoney   reiserfs: cleanup...
1074
1075
  	 * the file system.
  	 */
7cd33ad23   Christoph Hellwig   reiserfs: replace...
1076
1077
1078
1079
  	if (likely(!retval && !reiserfs_is_journal_aborted (journal))) {
  		if (buffer_dirty(jl->j_commit_bh))
  			BUG();
  		mark_buffer_dirty(jl->j_commit_bh) ;
278f6679f   Jeff Mahoney   reiserfs: locking...
1080
  		depth = reiserfs_write_unlock_nested(s);
7cd33ad23   Christoph Hellwig   reiserfs: replace...
1081
  		if (reiserfs_barrier_flush(s))
70fd76140   Christoph Hellwig   block,fs: use REQ...
1082
  			__sync_dirty_buffer(jl->j_commit_bh,
d8747d642   Jan Kara   reiserfs: Make fl...
1083
  					REQ_SYNC | REQ_PREFLUSH | REQ_FUA);
7cd33ad23   Christoph Hellwig   reiserfs: replace...
1084
1085
  		else
  			sync_dirty_buffer(jl->j_commit_bh);
278f6679f   Jeff Mahoney   reiserfs: locking...
1086
  		reiserfs_write_lock_nested(s, depth);
8ebc42323   Frederic Weisbecker   reiserfs: kill-th...
1087
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1088

098297b27   Jeff Mahoney   reiserfs: cleanup...
1089
1090
  	/*
  	 * If there was a write error in the journal - we can't commit this
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1091
  	 * transaction - it will be invalid and, if successful, will just end
098297b27   Jeff Mahoney   reiserfs: cleanup...
1092
1093
  	 * up propagating the write error out to the filesystem.
  	 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1094
  	if (unlikely(!buffer_uptodate(jl->j_commit_bh))) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1095
  #ifdef CONFIG_REISERFS_CHECK
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1096
  		reiserfs_warning(s, "journal-615", "buffer write failed");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1097
  #endif
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1098
1099
1100
1101
1102
  		retval = -EIO;
  	}
  	bforget(jl->j_commit_bh);
  	if (journal->j_last_commit_id != 0 &&
  	    (jl->j_trans_id - journal->j_last_commit_id) != 1) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1103
  		reiserfs_warning(s, "clm-2200", "last commit %lu, current %lu",
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1104
1105
1106
  				 journal->j_last_commit_id, jl->j_trans_id);
  	}
  	journal->j_last_commit_id = jl->j_trans_id;
098297b27   Jeff Mahoney   reiserfs: cleanup...
1107
1108
1109
1110
  	/*
  	 * now, every commit block is on the disk.  It is safe to allow
  	 * blocks freed during this transaction to be reallocated
  	 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1111
1112
1113
1114
1115
1116
1117
  	cleanup_freed_for_journal_list(s, jl);
  
  	retval = retval ? retval : journal->j_errno;
  
  	/* mark the metadata dirty */
  	if (!retval)
  		dirty_one_transaction(s, jl);
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
1118
  	atomic_dec(&jl->j_commit_left);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1119
1120
  
  	if (flushall) {
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
1121
  		atomic_set(&jl->j_older_commits_done, 1);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1122
  	}
90415deac   Jeff Mahoney   reiserfs: convert...
1123
  	mutex_unlock(&jl->j_commit_mutex);
cf776a7a4   Jeff Mahoney   reiserfs: cleanup...
1124
  put_jl:
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1125
1126
1127
1128
  	put_journal_list(s, jl);
  
  	if (retval)
  		reiserfs_abort(s, retval, "Journal write error in %s",
fbe5498b3   Harvey Harrison   reiserfs: replace...
1129
  			       __func__);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1130
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1131
1132
1133
  }
  
  /*
098297b27   Jeff Mahoney   reiserfs: cleanup...
1134
1135
1136
   * flush_journal_list frequently needs to find a newer transaction for a
   * given block.  This does that, or returns NULL if it can't find anything
   */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1137
1138
1139
1140
1141
1142
  static struct reiserfs_journal_list *find_newer_jl_for_cn(struct
  							  reiserfs_journal_cnode
  							  *cn)
  {
  	struct super_block *sb = cn->sb;
  	b_blocknr_t blocknr = cn->blocknr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1143

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1144
1145
1146
1147
1148
1149
1150
1151
  	cn = cn->hprev;
  	while (cn) {
  		if (cn->sb == sb && cn->blocknr == blocknr && cn->jlist) {
  			return cn->jlist;
  		}
  		cn = cn->hprev;
  	}
  	return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1152
  }
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1153
1154
1155
1156
  static void remove_journal_hash(struct super_block *,
  				struct reiserfs_journal_cnode **,
  				struct reiserfs_journal_list *, unsigned long,
  				int);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1157
1158
  
  /*
098297b27   Jeff Mahoney   reiserfs: cleanup...
1159
1160
1161
1162
1163
   * once all the real blocks have been flushed, it is safe to remove them
   * from the journal list for this transaction.  Aside from freeing the
   * cnode, this also allows the block to be reallocated for data blocks
   * if it had been deleted.
   */
a9dd36435   Jeff Mahoney   reiserfs: rename ...
1164
  static void remove_all_from_journal_list(struct super_block *sb,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1165
1166
1167
  					 struct reiserfs_journal_list *jl,
  					 int debug)
  {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
1168
  	struct reiserfs_journal *journal = SB_JOURNAL(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1169
1170
  	struct reiserfs_journal_cnode *cn, *last;
  	cn = jl->j_realblock;
098297b27   Jeff Mahoney   reiserfs: cleanup...
1171
1172
1173
  	/*
  	 * which is better, to lock once around the whole loop, or
  	 * to lock for each call to remove_journal_hash?
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1174
1175
1176
1177
  	 */
  	while (cn) {
  		if (cn->blocknr != 0) {
  			if (debug) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
1178
  				reiserfs_warning(sb, "reiserfs-2201",
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1179
1180
1181
1182
1183
  						 "block %u, bh is %d, state %ld",
  						 cn->blocknr, cn->bh ? 1 : 0,
  						 cn->state);
  			}
  			cn->state = 0;
a9dd36435   Jeff Mahoney   reiserfs: rename ...
1184
  			remove_journal_hash(sb, journal->j_list_hash_table,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1185
1186
1187
1188
  					    jl, cn->blocknr, 1);
  		}
  		last = cn;
  		cn = cn->next;
a9dd36435   Jeff Mahoney   reiserfs: rename ...
1189
  		free_cnode(sb, last);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1190
1191
  	}
  	jl->j_realblock = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1192
1193
1194
  }
  
  /*
098297b27   Jeff Mahoney   reiserfs: cleanup...
1195
1196
1197
1198
1199
1200
1201
   * if this timestamp is greater than the timestamp we wrote last to the
   * header block, write it to the header block.  once this is done, I can
   * safely say the log area for this transaction won't ever be replayed,
   * and I can start releasing blocks in this transaction for reuse as data
   * blocks.  called by flush_journal_list, before it calls
   * remove_all_from_journal_list
   */
a9dd36435   Jeff Mahoney   reiserfs: rename ...
1202
  static int _update_journal_header_block(struct super_block *sb,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1203
  					unsigned long offset,
600ed4167   Jeff Mahoney   reiserfs: audit t...
1204
  					unsigned int trans_id)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1205
1206
  {
  	struct reiserfs_journal_header *jh;
a9dd36435   Jeff Mahoney   reiserfs: rename ...
1207
  	struct reiserfs_journal *journal = SB_JOURNAL(sb);
278f6679f   Jeff Mahoney   reiserfs: locking...
1208
  	int depth;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1209

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1210
1211
  	if (reiserfs_is_journal_aborted(journal))
  		return -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1212

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1213
1214
  	if (trans_id >= journal->j_last_flush_trans_id) {
  		if (buffer_locked((journal->j_header_bh))) {
278f6679f   Jeff Mahoney   reiserfs: locking...
1215
1216
1217
  			depth = reiserfs_write_unlock_nested(sb);
  			__wait_on_buffer(journal->j_header_bh);
  			reiserfs_write_lock_nested(sb, depth);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1218
  			if (unlikely(!buffer_uptodate(journal->j_header_bh))) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1219
  #ifdef CONFIG_REISERFS_CHECK
a9dd36435   Jeff Mahoney   reiserfs: rename ...
1220
  				reiserfs_warning(sb, "journal-699",
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1221
  						 "buffer write failed");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1222
  #endif
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
  				return -EIO;
  			}
  		}
  		journal->j_last_flush_trans_id = trans_id;
  		journal->j_first_unflushed_offset = offset;
  		jh = (struct reiserfs_journal_header *)(journal->j_header_bh->
  							b_data);
  		jh->j_last_flush_trans_id = cpu_to_le32(trans_id);
  		jh->j_first_unflushed_offset = cpu_to_le32(offset);
  		jh->j_mount_id = cpu_to_le32(journal->j_mount_id);
7cd33ad23   Christoph Hellwig   reiserfs: replace...
1233
  		set_buffer_dirty(journal->j_header_bh);
278f6679f   Jeff Mahoney   reiserfs: locking...
1234
  		depth = reiserfs_write_unlock_nested(sb);
7cd33ad23   Christoph Hellwig   reiserfs: replace...
1235
1236
  
  		if (reiserfs_barrier_flush(sb))
70fd76140   Christoph Hellwig   block,fs: use REQ...
1237
  			__sync_dirty_buffer(journal->j_header_bh,
d8747d642   Jan Kara   reiserfs: Make fl...
1238
  					REQ_SYNC | REQ_PREFLUSH | REQ_FUA);
7cd33ad23   Christoph Hellwig   reiserfs: replace...
1239
  		else
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1240
  			sync_dirty_buffer(journal->j_header_bh);
7cd33ad23   Christoph Hellwig   reiserfs: replace...
1241

278f6679f   Jeff Mahoney   reiserfs: locking...
1242
  		reiserfs_write_lock_nested(sb, depth);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1243
  		if (!buffer_uptodate(journal->j_header_bh)) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
1244
  			reiserfs_warning(sb, "journal-837",
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1245
  					 "IO error during journal replay");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1246
1247
1248
1249
1250
  			return -EIO;
  		}
  	}
  	return 0;
  }
a9dd36435   Jeff Mahoney   reiserfs: rename ...
1251
  static int update_journal_header_block(struct super_block *sb,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1252
  				       unsigned long offset,
600ed4167   Jeff Mahoney   reiserfs: audit t...
1253
  				       unsigned int trans_id)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1254
  {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
1255
  	return _update_journal_header_block(sb, offset, trans_id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1256
  }
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1257

0222e6571   Jeff Mahoney   reiserfs: strip t...
1258
1259
  /*
  ** flush any and all journal lists older than you are
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1260
1261
  ** can only be called from flush_journal_list
  */
a9dd36435   Jeff Mahoney   reiserfs: rename ...
1262
  static int flush_older_journal_lists(struct super_block *sb,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1263
1264
1265
1266
  				     struct reiserfs_journal_list *jl)
  {
  	struct list_head *entry;
  	struct reiserfs_journal_list *other_jl;
a9dd36435   Jeff Mahoney   reiserfs: rename ...
1267
  	struct reiserfs_journal *journal = SB_JOURNAL(sb);
600ed4167   Jeff Mahoney   reiserfs: audit t...
1268
  	unsigned int trans_id = jl->j_trans_id;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1269

098297b27   Jeff Mahoney   reiserfs: cleanup...
1270
1271
  	/*
  	 * we know we are the only ones flushing things, no extra race
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1272
1273
  	 * protection is required.
  	 */
cf776a7a4   Jeff Mahoney   reiserfs: cleanup...
1274
  restart:
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1275
1276
1277
1278
1279
1280
1281
1282
  	entry = journal->j_journal_list.next;
  	/* Did we wrap? */
  	if (entry == &journal->j_journal_list)
  		return 0;
  	other_jl = JOURNAL_LIST_ENTRY(entry);
  	if (other_jl->j_trans_id < trans_id) {
  		BUG_ON(other_jl->j_refcount <= 0);
  		/* do not flush all */
a9dd36435   Jeff Mahoney   reiserfs: rename ...
1283
  		flush_journal_list(sb, other_jl, 0);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1284
1285
1286
1287
1288
  
  		/* other_jl is now deleted from the list */
  		goto restart;
  	}
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1289
1290
1291
  }
  
  static void del_from_work_list(struct super_block *s,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1292
1293
1294
1295
1296
1297
1298
  			       struct reiserfs_journal_list *jl)
  {
  	struct reiserfs_journal *journal = SB_JOURNAL(s);
  	if (!list_empty(&jl->j_working_list)) {
  		list_del_init(&jl->j_working_list);
  		journal->j_num_work_lists--;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1299
  }
098297b27   Jeff Mahoney   reiserfs: cleanup...
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
  /*
   * flush a journal list, both commit and real blocks
   *
   * always set flushall to 1, unless you are calling from inside
   * flush_journal_list
   *
   * IMPORTANT.  This can only be called while there are no journal writers,
   * and the journal is locked.  That means it can only be called from
   * do_journal_end, or by journal_release
   */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1310
1311
  static int flush_journal_list(struct super_block *s,
  			      struct reiserfs_journal_list *jl, int flushall)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1312
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1313
1314
1315
1316
1317
1318
1319
1320
1321
  	struct reiserfs_journal_list *pjl;
  	struct reiserfs_journal_cnode *cn, *last;
  	int count;
  	int was_jwait = 0;
  	int was_dirty = 0;
  	struct buffer_head *saved_bh;
  	unsigned long j_len_saved = jl->j_len;
  	struct reiserfs_journal *journal = SB_JOURNAL(s);
  	int err = 0;
278f6679f   Jeff Mahoney   reiserfs: locking...
1322
  	int depth;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1323
1324
1325
1326
  
  	BUG_ON(j_len_saved <= 0);
  
  	if (atomic_read(&journal->j_wcount) != 0) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1327
  		reiserfs_warning(s, "clm-2048", "called with wcount %d",
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1328
1329
  				 atomic_read(&journal->j_wcount));
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1330

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1331
1332
  	/* if flushall == 0, the lock is already held */
  	if (flushall) {
8ebc42323   Frederic Weisbecker   reiserfs: kill-th...
1333
  		reiserfs_mutex_lock_safe(&journal->j_flush_mutex, s);
afe702590   Jeff Mahoney   reiserfs: convert...
1334
  	} else if (mutex_trylock(&journal->j_flush_mutex)) {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1335
1336
  		BUG();
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1337

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1338
1339
  	count = 0;
  	if (j_len_saved > journal->j_trans_max) {
c3a9c2109   Jeff Mahoney   reiserfs: rework ...
1340
  		reiserfs_panic(s, "journal-715", "length is %lu, trans id %lu",
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1341
1342
1343
  			       j_len_saved, jl->j_trans_id);
  		return 0;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1344

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1345
  	/* if all the work is already done, get out of here */
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
1346
1347
  	if (atomic_read(&jl->j_nonzerolen) <= 0 &&
  	    atomic_read(&jl->j_commit_left) <= 0) {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1348
1349
  		goto flush_older_and_return;
  	}
098297b27   Jeff Mahoney   reiserfs: cleanup...
1350
1351
1352
  	/*
  	 * start by putting the commit list on disk.  This will also flush
  	 * the commit lists of any olders transactions
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1353
1354
1355
1356
1357
1358
1359
1360
  	 */
  	flush_commit_list(s, jl, 1);
  
  	if (!(jl->j_state & LIST_DIRTY)
  	    && !reiserfs_is_journal_aborted(journal))
  		BUG();
  
  	/* are we done now? */
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
1361
1362
  	if (atomic_read(&jl->j_nonzerolen) <= 0 &&
  	    atomic_read(&jl->j_commit_left) <= 0) {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1363
1364
  		goto flush_older_and_return;
  	}
098297b27   Jeff Mahoney   reiserfs: cleanup...
1365
1366
1367
  	/*
  	 * loop through each cnode, see if we need to write it,
  	 * or wait on a more recent transaction, or just ignore it
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1368
  	 */
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
1369
  	if (atomic_read(&journal->j_wcount) != 0) {
c3a9c2109   Jeff Mahoney   reiserfs: rework ...
1370
1371
  		reiserfs_panic(s, "journal-844", "journal list is flushing, "
  			       "wcount is not 0");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
  	}
  	cn = jl->j_realblock;
  	while (cn) {
  		was_jwait = 0;
  		was_dirty = 0;
  		saved_bh = NULL;
  		/* blocknr of 0 is no longer in the hash, ignore it */
  		if (cn->blocknr == 0) {
  			goto free_cnode;
  		}
098297b27   Jeff Mahoney   reiserfs: cleanup...
1382
1383
1384
1385
  		/*
  		 * This transaction failed commit.
  		 * Don't write out to the disk
  		 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1386
1387
1388
1389
  		if (!(jl->j_state & LIST_DIRTY))
  			goto free_cnode;
  
  		pjl = find_newer_jl_for_cn(cn);
098297b27   Jeff Mahoney   reiserfs: cleanup...
1390
1391
1392
1393
  		/*
  		 * the order is important here.  We check pjl to make sure we
  		 * don't clear BH_JDirty_wait if we aren't the one writing this
  		 * block to disk
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1394
1395
1396
  		 */
  		if (!pjl && cn->bh) {
  			saved_bh = cn->bh;
098297b27   Jeff Mahoney   reiserfs: cleanup...
1397
1398
1399
  			/*
  			 * we do this to make sure nobody releases the
  			 * buffer while we are working with it
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1400
1401
1402
1403
1404
1405
1406
1407
  			 */
  			get_bh(saved_bh);
  
  			if (buffer_journal_dirty(saved_bh)) {
  				BUG_ON(!can_dirty(cn));
  				was_jwait = 1;
  				was_dirty = 1;
  			} else if (can_dirty(cn)) {
098297b27   Jeff Mahoney   reiserfs: cleanup...
1408
1409
1410
1411
  				/*
  				 * everything with !pjl && jwait
  				 * should be writable
  				 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1412
1413
1414
  				BUG();
  			}
  		}
098297b27   Jeff Mahoney   reiserfs: cleanup...
1415
1416
1417
  		/*
  		 * if someone has this block in a newer transaction, just make
  		 * sure they are committed, and don't try writing it to disk
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1418
1419
1420
1421
1422
1423
  		 */
  		if (pjl) {
  			if (atomic_read(&pjl->j_commit_left))
  				flush_commit_list(s, pjl, 1);
  			goto free_cnode;
  		}
098297b27   Jeff Mahoney   reiserfs: cleanup...
1424
1425
1426
  		/*
  		 * bh == NULL when the block got to disk on its own, OR,
  		 * the block got freed in a future transaction
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1427
1428
1429
1430
  		 */
  		if (saved_bh == NULL) {
  			goto free_cnode;
  		}
098297b27   Jeff Mahoney   reiserfs: cleanup...
1431
1432
1433
1434
  		/*
  		 * this should never happen.  kupdate_one_transaction has
  		 * this list locked while it works, so we should never see a
  		 * buffer here that is not marked JDirty_wait
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1435
1436
  		 */
  		if ((!was_jwait) && !buffer_locked(saved_bh)) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1437
1438
  			reiserfs_warning(s, "journal-813",
  					 "BAD! buffer %llu %cdirty %cjwait, "
65f2b2633   Colin Ian King   reiserfs: fix spe...
1439
  					 "not in a newer transaction",
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1440
1441
1442
1443
1444
  					 (unsigned long long)saved_bh->
  					 b_blocknr, was_dirty ? ' ' : '!',
  					 was_jwait ? ' ' : '!');
  		}
  		if (was_dirty) {
098297b27   Jeff Mahoney   reiserfs: cleanup...
1445
1446
1447
1448
  			/*
  			 * we inc again because saved_bh gets decremented
  			 * at free_cnode
  			 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
  			get_bh(saved_bh);
  			set_bit(BLOCK_NEEDS_FLUSH, &cn->state);
  			lock_buffer(saved_bh);
  			BUG_ON(cn->blocknr != saved_bh->b_blocknr);
  			if (buffer_dirty(saved_bh))
  				submit_logged_buffer(saved_bh);
  			else
  				unlock_buffer(saved_bh);
  			count++;
  		} else {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1459
1460
  			reiserfs_warning(s, "clm-2082",
  					 "Unable to flush buffer %llu in %s",
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1461
  					 (unsigned long long)saved_bh->
fbe5498b3   Harvey Harrison   reiserfs: replace...
1462
  					 b_blocknr, __func__);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1463
  		}
cf776a7a4   Jeff Mahoney   reiserfs: cleanup...
1464
  free_cnode:
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1465
1466
1467
  		last = cn;
  		cn = cn->next;
  		if (saved_bh) {
098297b27   Jeff Mahoney   reiserfs: cleanup...
1468
1469
1470
1471
  			/*
  			 * we incremented this to keep others from
  			 * taking the buffer head away
  			 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1472
  			put_bh(saved_bh);
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
1473
  			if (atomic_read(&saved_bh->b_count) < 0) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1474
1475
  				reiserfs_warning(s, "journal-945",
  						 "saved_bh->b_count < 0");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1476
1477
1478
1479
1480
1481
1482
1483
  			}
  		}
  	}
  	if (count > 0) {
  		cn = jl->j_realblock;
  		while (cn) {
  			if (test_bit(BLOCK_NEEDS_FLUSH, &cn->state)) {
  				if (!cn->bh) {
c3a9c2109   Jeff Mahoney   reiserfs: rework ...
1484
1485
  					reiserfs_panic(s, "journal-1011",
  						       "cn->bh is NULL");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1486
  				}
8ebc42323   Frederic Weisbecker   reiserfs: kill-th...
1487

278f6679f   Jeff Mahoney   reiserfs: locking...
1488
1489
1490
  				depth = reiserfs_write_unlock_nested(s);
  				__wait_on_buffer(cn->bh);
  				reiserfs_write_lock_nested(s, depth);
8ebc42323   Frederic Weisbecker   reiserfs: kill-th...
1491

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1492
  				if (!cn->bh) {
c3a9c2109   Jeff Mahoney   reiserfs: rework ...
1493
1494
  					reiserfs_panic(s, "journal-1012",
  						       "cn->bh is NULL");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1495
1496
1497
  				}
  				if (unlikely(!buffer_uptodate(cn->bh))) {
  #ifdef CONFIG_REISERFS_CHECK
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1498
1499
  					reiserfs_warning(s, "journal-949",
  							 "buffer write failed");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1500
1501
1502
  #endif
  					err = -EIO;
  				}
098297b27   Jeff Mahoney   reiserfs: cleanup...
1503
1504
1505
1506
  				/*
  				 * note, we must clear the JDirty_wait bit
  				 * after the up to date check, otherwise we
  				 * race against our flushpage routine
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1507
1508
1509
  				 */
  				BUG_ON(!test_clear_buffer_journal_dirty
  				       (cn->bh));
398c95bdf   Chris Mason   try to reap reise...
1510
  				/* drop one ref for us */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1511
  				put_bh(cn->bh);
398c95bdf   Chris Mason   try to reap reise...
1512
1513
  				/* drop one ref for journal_mark_dirty */
  				release_buffer_page(cn->bh);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1514
1515
1516
1517
1518
1519
1520
1521
  			}
  			cn = cn->next;
  		}
  	}
  
  	if (err)
  		reiserfs_abort(s, -EIO,
  			       "Write error while pushing transaction to disk in %s",
fbe5498b3   Harvey Harrison   reiserfs: replace...
1522
  			       __func__);
cf776a7a4   Jeff Mahoney   reiserfs: cleanup...
1523
  flush_older_and_return:
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1524

098297b27   Jeff Mahoney   reiserfs: cleanup...
1525
1526
1527
1528
1529
  	/*
  	 * before we can update the journal header block, we _must_ flush all
  	 * real blocks from all older transactions to disk.  This is because
  	 * once the header block is updated, this transaction will not be
  	 * replayed after a crash
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1530
1531
1532
1533
1534
1535
  	 */
  	if (flushall) {
  		flush_older_journal_lists(s, jl);
  	}
  
  	err = journal->j_errno;
098297b27   Jeff Mahoney   reiserfs: cleanup...
1536
1537
1538
1539
1540
1541
1542
1543
  	/*
  	 * before we can remove everything from the hash tables for this
  	 * transaction, we must make sure it can never be replayed
  	 *
  	 * since we are only called from do_journal_end, we know for sure there
  	 * are no allocations going on while we are flushing journal lists.  So,
  	 * we only need to update the journal header block for the last list
  	 * being flushed
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
  	 */
  	if (!err && flushall) {
  		err =
  		    update_journal_header_block(s,
  						(jl->j_start + jl->j_len +
  						 2) % SB_ONDISK_JOURNAL_SIZE(s),
  						jl->j_trans_id);
  		if (err)
  			reiserfs_abort(s, -EIO,
  				       "Write error while updating journal header in %s",
fbe5498b3   Harvey Harrison   reiserfs: replace...
1554
  				       __func__);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1555
1556
1557
1558
1559
1560
1561
1562
  	}
  	remove_all_from_journal_list(s, jl, 0);
  	list_del_init(&jl->j_list);
  	journal->j_num_lists--;
  	del_from_work_list(s, jl);
  
  	if (journal->j_last_flush_id != 0 &&
  	    (jl->j_trans_id - journal->j_last_flush_id) != 1) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1563
  		reiserfs_warning(s, "clm-2201", "last flush %lu, current %lu",
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1564
1565
1566
  				 journal->j_last_flush_id, jl->j_trans_id);
  	}
  	journal->j_last_flush_id = jl->j_trans_id;
098297b27   Jeff Mahoney   reiserfs: cleanup...
1567
1568
  	/*
  	 * not strictly required since we are freeing the list, but it should
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1569
1570
1571
  	 * help find code using dead lists later on
  	 */
  	jl->j_len = 0;
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
1572
  	atomic_set(&jl->j_nonzerolen, 0);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1573
1574
1575
1576
1577
1578
1579
  	jl->j_start = 0;
  	jl->j_realblock = NULL;
  	jl->j_commit_bh = NULL;
  	jl->j_trans_id = 0;
  	jl->j_state = 0;
  	put_journal_list(s, jl);
  	if (flushall)
afe702590   Jeff Mahoney   reiserfs: convert...
1580
  		mutex_unlock(&journal->j_flush_mutex);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
  	return err;
  }
  
  static int write_one_transaction(struct super_block *s,
  				 struct reiserfs_journal_list *jl,
  				 struct buffer_chunk *chunk)
  {
  	struct reiserfs_journal_cnode *cn;
  	int ret = 0;
  
  	jl->j_state |= LIST_TOUCHED;
  	del_from_work_list(s, jl);
  	if (jl->j_len == 0 || atomic_read(&jl->j_nonzerolen) == 0) {
  		return 0;
  	}
  
  	cn = jl->j_realblock;
  	while (cn) {
098297b27   Jeff Mahoney   reiserfs: cleanup...
1599
1600
1601
  		/*
  		 * if the blocknr == 0, this has been cleared from the hash,
  		 * skip it
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1602
1603
1604
1605
1606
1607
  		 */
  		if (cn->blocknr == 0) {
  			goto next;
  		}
  		if (cn->bh && can_dirty(cn) && buffer_dirty(cn->bh)) {
  			struct buffer_head *tmp_bh;
098297b27   Jeff Mahoney   reiserfs: cleanup...
1608
1609
  			/*
  			 * we can race against journal_mark_freed when we try
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
  			 * to lock_buffer(cn->bh), so we have to inc the buffer
  			 * count, and recheck things after locking
  			 */
  			tmp_bh = cn->bh;
  			get_bh(tmp_bh);
  			lock_buffer(tmp_bh);
  			if (cn->bh && can_dirty(cn) && buffer_dirty(tmp_bh)) {
  				if (!buffer_journal_dirty(tmp_bh) ||
  				    buffer_journal_prepared(tmp_bh))
  					BUG();
  				add_to_chunk(chunk, tmp_bh, NULL, write_chunk);
  				ret++;
  			} else {
  				/* note, cn->bh might be null now */
  				unlock_buffer(tmp_bh);
  			}
  			put_bh(tmp_bh);
  		}
cf776a7a4   Jeff Mahoney   reiserfs: cleanup...
1628
  next:
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
  		cn = cn->next;
  		cond_resched();
  	}
  	return ret;
  }
  
  /* used by flush_commit_list */
  static int dirty_one_transaction(struct super_block *s,
  				 struct reiserfs_journal_list *jl)
  {
  	struct reiserfs_journal_cnode *cn;
  	struct reiserfs_journal_list *pjl;
  	int ret = 0;
  
  	jl->j_state |= LIST_DIRTY;
  	cn = jl->j_realblock;
  	while (cn) {
098297b27   Jeff Mahoney   reiserfs: cleanup...
1646
1647
1648
1649
  		/*
  		 * look for a more recent transaction that logged this
  		 * buffer.  Only the most recent transaction with a buffer in
  		 * it is allowed to send that buffer to disk
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1650
1651
1652
1653
1654
  		 */
  		pjl = find_newer_jl_for_cn(cn);
  		if (!pjl && cn->blocknr && cn->bh
  		    && buffer_journal_dirty(cn->bh)) {
  			BUG_ON(!can_dirty(cn));
098297b27   Jeff Mahoney   reiserfs: cleanup...
1655
1656
  			/*
  			 * if the buffer is prepared, it will either be logged
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
  			 * or restored.  If restored, we need to make sure
  			 * it actually gets marked dirty
  			 */
  			clear_buffer_journal_new(cn->bh);
  			if (buffer_journal_prepared(cn->bh)) {
  				set_buffer_journal_restore_dirty(cn->bh);
  			} else {
  				set_buffer_journal_test(cn->bh);
  				mark_buffer_dirty(cn->bh);
  			}
  		}
  		cn = cn->next;
  	}
  	return ret;
  }
  
  static int kupdate_transactions(struct super_block *s,
  				struct reiserfs_journal_list *jl,
  				struct reiserfs_journal_list **next_jl,
600ed4167   Jeff Mahoney   reiserfs: audit t...
1676
  				unsigned int *next_trans_id,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1677
1678
1679
1680
1681
  				int num_blocks, int num_trans)
  {
  	int ret = 0;
  	int written = 0;
  	int transactions_flushed = 0;
600ed4167   Jeff Mahoney   reiserfs: audit t...
1682
  	unsigned int orig_trans_id = jl->j_trans_id;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1683
1684
1685
1686
  	struct buffer_chunk chunk;
  	struct list_head *entry;
  	struct reiserfs_journal *journal = SB_JOURNAL(s);
  	chunk.nr = 0;
a412f9efd   Frederic Weisbecker   reiserfs, kill-th...
1687
  	reiserfs_mutex_lock_safe(&journal->j_flush_mutex, s);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1688
1689
1690
  	if (!journal_list_still_alive(s, orig_trans_id)) {
  		goto done;
  	}
098297b27   Jeff Mahoney   reiserfs: cleanup...
1691
1692
  	/*
  	 * we've got j_flush_mutex held, nobody is going to delete any
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
  	 * of these lists out from underneath us
  	 */
  	while ((num_trans && transactions_flushed < num_trans) ||
  	       (!num_trans && written < num_blocks)) {
  
  		if (jl->j_len == 0 || (jl->j_state & LIST_TOUCHED) ||
  		    atomic_read(&jl->j_commit_left)
  		    || !(jl->j_state & LIST_DIRTY)) {
  			del_from_work_list(s, jl);
  			break;
  		}
  		ret = write_one_transaction(s, jl, &chunk);
  
  		if (ret < 0)
  			goto done;
  		transactions_flushed++;
  		written += ret;
  		entry = jl->j_list.next;
  
  		/* did we wrap? */
  		if (entry == &journal->j_journal_list) {
  			break;
  		}
  		jl = JOURNAL_LIST_ENTRY(entry);
  
  		/* don't bother with older transactions */
  		if (jl->j_trans_id <= orig_trans_id)
  			break;
  	}
  	if (chunk.nr) {
  		write_chunk(&chunk);
  	}
cf776a7a4   Jeff Mahoney   reiserfs: cleanup...
1725
  done:
afe702590   Jeff Mahoney   reiserfs: convert...
1726
  	mutex_unlock(&journal->j_flush_mutex);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1727
1728
  	return ret;
  }
098297b27   Jeff Mahoney   reiserfs: cleanup...
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
  /*
   * for o_sync and fsync heavy applications, they tend to use
   * all the journa list slots with tiny transactions.  These
   * trigger lots and lots of calls to update the header block, which
   * adds seeks and slows things down.
   *
   * This function tries to clear out a large chunk of the journal lists
   * at once, which makes everything faster since only the newest journal
   * list updates the header block
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1739
  static int flush_used_journal_lists(struct super_block *s,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1740
1741
1742
1743
1744
1745
1746
1747
1748
  				    struct reiserfs_journal_list *jl)
  {
  	unsigned long len = 0;
  	unsigned long cur_len;
  	int ret;
  	int i;
  	int limit = 256;
  	struct reiserfs_journal_list *tjl;
  	struct reiserfs_journal_list *flush_jl;
600ed4167   Jeff Mahoney   reiserfs: audit t...
1749
  	unsigned int trans_id;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
  	struct reiserfs_journal *journal = SB_JOURNAL(s);
  
  	flush_jl = tjl = jl;
  
  	/* in data logging mode, try harder to flush a lot of blocks */
  	if (reiserfs_data_log(s))
  		limit = 1024;
  	/* flush for 256 transactions or limit blocks, whichever comes first */
  	for (i = 0; i < 256 && len < limit; i++) {
  		if (atomic_read(&tjl->j_commit_left) ||
  		    tjl->j_trans_id < jl->j_trans_id) {
  			break;
  		}
  		cur_len = atomic_read(&tjl->j_nonzerolen);
  		if (cur_len > 0) {
  			tjl->j_state &= ~LIST_TOUCHED;
  		}
  		len += cur_len;
  		flush_jl = tjl;
  		if (tjl->j_list.next == &journal->j_journal_list)
  			break;
  		tjl = JOURNAL_LIST_ENTRY(tjl->j_list.next);
  	}
721a769c0   Jeff Mahoney   reiserfs: fix rac...
1773
1774
  	get_journal_list(jl);
  	get_journal_list(flush_jl);
098297b27   Jeff Mahoney   reiserfs: cleanup...
1775
1776
1777
1778
1779
  
  	/*
  	 * try to find a group of blocks we can flush across all the
  	 * transactions, but only bother if we've actually spanned
  	 * across multiple lists
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1780
1781
1782
1783
1784
  	 */
  	if (flush_jl != jl) {
  		ret = kupdate_transactions(s, jl, &tjl, &trans_id, len, i);
  	}
  	flush_journal_list(s, flush_jl, 1);
721a769c0   Jeff Mahoney   reiserfs: fix rac...
1785
1786
  	put_journal_list(s, flush_jl);
  	put_journal_list(s, jl);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1787
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1788
1789
1790
  }
  
  /*
098297b27   Jeff Mahoney   reiserfs: cleanup...
1791
1792
1793
   * removes any nodes in table with name block and dev as bh.
   * only touchs the hnext and hprev pointers.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1794
  void remove_journal_hash(struct super_block *sb,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
  			 struct reiserfs_journal_cnode **table,
  			 struct reiserfs_journal_list *jl,
  			 unsigned long block, int remove_freed)
  {
  	struct reiserfs_journal_cnode *cur;
  	struct reiserfs_journal_cnode **head;
  
  	head = &(journal_hash(table, sb, block));
  	if (!head) {
  		return;
  	}
  	cur = *head;
  	while (cur) {
  		if (cur->blocknr == block && cur->sb == sb
  		    && (jl == NULL || jl == cur->jlist)
  		    && (!test_bit(BLOCK_FREED, &cur->state) || remove_freed)) {
  			if (cur->hnext) {
  				cur->hnext->hprev = cur->hprev;
  			}
  			if (cur->hprev) {
  				cur->hprev->hnext = cur->hnext;
  			} else {
  				*head = cur->hnext;
  			}
  			cur->blocknr = 0;
  			cur->sb = NULL;
  			cur->state = 0;
098297b27   Jeff Mahoney   reiserfs: cleanup...
1822
1823
1824
1825
1826
  			/*
  			 * anybody who clears the cur->bh will also
  			 * dec the nonzerolen
  			 */
  			if (cur->bh && cur->jlist)
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
1827
  				atomic_dec(&cur->jlist->j_nonzerolen);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1828
1829
1830
1831
1832
1833
  			cur->bh = NULL;
  			cur->jlist = NULL;
  		}
  		cur = cur->hnext;
  	}
  }
a9dd36435   Jeff Mahoney   reiserfs: rename ...
1834
  static void free_journal_ram(struct super_block *sb)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1835
  {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
1836
  	struct reiserfs_journal *journal = SB_JOURNAL(sb);
d739b42b8   Pekka Enberg   [PATCH] reiserfs:...
1837
  	kfree(journal->j_current_jl);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1838
1839
1840
  	journal->j_num_lists--;
  
  	vfree(journal->j_cnode_free_orig);
a9dd36435   Jeff Mahoney   reiserfs: rename ...
1841
1842
  	free_list_bitmaps(sb, journal->j_list_bitmap);
  	free_bitmap_nodes(sb);	/* must be after free_list_bitmaps */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1843
1844
1845
  	if (journal->j_header_bh) {
  		brelse(journal->j_header_bh);
  	}
098297b27   Jeff Mahoney   reiserfs: cleanup...
1846
1847
1848
  	/*
  	 * j_header_bh is on the journal dev, make sure
  	 * not to release the journal dev until we brelse j_header_bh
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1849
  	 */
a9dd36435   Jeff Mahoney   reiserfs: rename ...
1850
  	release_journal_dev(sb, journal);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1851
  	vfree(journal);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1852
1853
1854
  }
  
  /*
098297b27   Jeff Mahoney   reiserfs: cleanup...
1855
1856
1857
   * call on unmount.  Only set error to 1 if you haven't made your way out
   * of read_super() yet.  Any other caller must keep error at 0.
   */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1858
  static int do_journal_release(struct reiserfs_transaction_handle *th,
a9dd36435   Jeff Mahoney   reiserfs: rename ...
1859
  			      struct super_block *sb, int error)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1860
1861
1862
  {
  	struct reiserfs_transaction_handle myth;
  	int flushed = 0;
a9dd36435   Jeff Mahoney   reiserfs: rename ...
1863
  	struct reiserfs_journal *journal = SB_JOURNAL(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1864

098297b27   Jeff Mahoney   reiserfs: cleanup...
1865
1866
1867
  	/*
  	 * we only want to flush out transactions if we were
  	 * called with error == 0
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1868
  	 */
bc98a42c1   David Howells   VFS: Convert sb->...
1869
  	if (!error && !sb_rdonly(sb)) {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1870
1871
  		/* end the current trans */
  		BUG_ON(!th->t_trans_id);
58d854265   Jeff Mahoney   reiserfs: cleanup...
1872
  		do_journal_end(th, FLUSH_ALL);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1873

098297b27   Jeff Mahoney   reiserfs: cleanup...
1874
1875
1876
1877
  		/*
  		 * make sure something gets logged to force
  		 * our way into the flush code
  		 */
b491dd176   Jeff Mahoney   reiserfs: cleanup...
1878
  		if (!journal_join(&myth, sb)) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
1879
1880
  			reiserfs_prepare_for_journal(sb,
  						     SB_BUFFER_WITH_SB(sb),
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1881
  						     1);
09f1b80ba   Jeff Mahoney   reiserfs: cleanup...
1882
  			journal_mark_dirty(&myth, SB_BUFFER_WITH_SB(sb));
58d854265   Jeff Mahoney   reiserfs: cleanup...
1883
  			do_journal_end(&myth, FLUSH_ALL);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1884
1885
1886
1887
1888
1889
1890
  			flushed = 1;
  		}
  	}
  
  	/* this also catches errors during the do_journal_end above */
  	if (!error && reiserfs_is_journal_aborted(journal)) {
  		memset(&myth, 0, sizeof(myth));
b491dd176   Jeff Mahoney   reiserfs: cleanup...
1891
  		if (!journal_join_abort(&myth, sb)) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
1892
1893
  			reiserfs_prepare_for_journal(sb,
  						     SB_BUFFER_WITH_SB(sb),
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1894
  						     1);
09f1b80ba   Jeff Mahoney   reiserfs: cleanup...
1895
  			journal_mark_dirty(&myth, SB_BUFFER_WITH_SB(sb));
58d854265   Jeff Mahoney   reiserfs: cleanup...
1896
  			do_journal_end(&myth, FLUSH_ALL);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1897
1898
  		}
  	}
8ebc42323   Frederic Weisbecker   reiserfs: kill-th...
1899
1900
1901
1902
1903
1904
  
  	/*
  	 * We must release the write lock here because
  	 * the workqueue job (flush_async_commit) needs this lock
  	 */
  	reiserfs_write_unlock(sb);
033369d1a   Artem Bityutskiy   reiserfs: get rid...
1905

01777836c   Jan Kara   reiserfs: Fix use...
1906
1907
1908
1909
1910
  	/*
  	 * Cancel flushing of old commits. Note that neither of these works
  	 * will be requeued because superblock is being shutdown and doesn't
  	 * have MS_ACTIVE set.
  	 */
71b0576bd   Jan Kara   reiserfs: Make ca...
1911
  	reiserfs_cancel_old_flush(sb);
01777836c   Jan Kara   reiserfs: Fix use...
1912
1913
  	/* wait for all commits to finish */
  	cancel_delayed_work_sync(&SB_JOURNAL(sb)->j_work);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1914

a9dd36435   Jeff Mahoney   reiserfs: rename ...
1915
  	free_journal_ram(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1916

0523676d3   Frederic Weisbecker   reiserfs: Relax r...
1917
  	reiserfs_write_lock(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1918
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1919
  }
098297b27   Jeff Mahoney   reiserfs: cleanup...
1920
  /* * call on unmount.  flush all journal trans, release all alloc'd ram */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1921
  int journal_release(struct reiserfs_transaction_handle *th,
a9dd36435   Jeff Mahoney   reiserfs: rename ...
1922
  		    struct super_block *sb)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1923
  {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
1924
  	return do_journal_release(th, sb, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1925
  }
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1926

098297b27   Jeff Mahoney   reiserfs: cleanup...
1927
  /* only call from an error condition inside reiserfs_read_super!  */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1928
  int journal_release_error(struct reiserfs_transaction_handle *th,
a9dd36435   Jeff Mahoney   reiserfs: rename ...
1929
  			  struct super_block *sb)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1930
  {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
1931
  	return do_journal_release(th, sb, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1932
  }
098297b27   Jeff Mahoney   reiserfs: cleanup...
1933
1934
1935
1936
  /*
   * compares description block with commit block.
   * returns 1 if they differ, 0 if they are the same
   */
a9dd36435   Jeff Mahoney   reiserfs: rename ...
1937
  static int journal_compare_desc_commit(struct super_block *sb,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1938
1939
1940
1941
1942
  				       struct reiserfs_journal_desc *desc,
  				       struct reiserfs_journal_commit *commit)
  {
  	if (get_commit_trans_id(commit) != get_desc_trans_id(desc) ||
  	    get_commit_trans_len(commit) != get_desc_trans_len(desc) ||
a9dd36435   Jeff Mahoney   reiserfs: rename ...
1943
  	    get_commit_trans_len(commit) > SB_JOURNAL(sb)->j_trans_max ||
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1944
1945
1946
1947
  	    get_commit_trans_len(commit) <= 0) {
  		return 1;
  	}
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1948
  }
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1949

098297b27   Jeff Mahoney   reiserfs: cleanup...
1950
1951
1952
1953
1954
1955
  /*
   * returns 0 if it did not find a description block
   * returns -1 if it found a corrupt commit block
   * returns 1 if both desc and commit were valid
   * NOTE: only called during fs mount
   */
a9dd36435   Jeff Mahoney   reiserfs: rename ...
1956
  static int journal_transaction_is_valid(struct super_block *sb,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1957
  					struct buffer_head *d_bh,
600ed4167   Jeff Mahoney   reiserfs: audit t...
1958
  					unsigned int *oldest_invalid_trans_id,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
  					unsigned long *newest_mount_id)
  {
  	struct reiserfs_journal_desc *desc;
  	struct reiserfs_journal_commit *commit;
  	struct buffer_head *c_bh;
  	unsigned long offset;
  
  	if (!d_bh)
  		return 0;
  
  	desc = (struct reiserfs_journal_desc *)d_bh->b_data;
  	if (get_desc_trans_len(desc) > 0
  	    && !memcmp(get_journal_desc_magic(d_bh), JOURNAL_DESC_MAGIC, 8)) {
  		if (oldest_invalid_trans_id && *oldest_invalid_trans_id
  		    && get_desc_trans_id(desc) > *oldest_invalid_trans_id) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
1974
  			reiserfs_debug(sb, REISERFS_DEBUG_CODE,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1975
1976
1977
1978
1979
1980
1981
1982
1983
  				       "journal-986: transaction "
  				       "is valid returning because trans_id %d is greater than "
  				       "oldest_invalid %lu",
  				       get_desc_trans_id(desc),
  				       *oldest_invalid_trans_id);
  			return 0;
  		}
  		if (newest_mount_id
  		    && *newest_mount_id > get_desc_mount_id(desc)) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
1984
  			reiserfs_debug(sb, REISERFS_DEBUG_CODE,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1985
1986
1987
1988
1989
1990
1991
  				       "journal-1087: transaction "
  				       "is valid returning because mount_id %d is less than "
  				       "newest_mount_id %lu",
  				       get_desc_mount_id(desc),
  				       *newest_mount_id);
  			return -1;
  		}
a9dd36435   Jeff Mahoney   reiserfs: rename ...
1992
1993
  		if (get_desc_trans_len(desc) > SB_JOURNAL(sb)->j_trans_max) {
  			reiserfs_warning(sb, "journal-2018",
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1994
1995
  					 "Bad transaction length %d "
  					 "encountered, ignoring transaction",
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1996
1997
1998
  					 get_desc_trans_len(desc));
  			return -1;
  		}
a9dd36435   Jeff Mahoney   reiserfs: rename ...
1999
  		offset = d_bh->b_blocknr - SB_ONDISK_JOURNAL_1st_BLOCK(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2000

098297b27   Jeff Mahoney   reiserfs: cleanup...
2001
2002
2003
2004
  		/*
  		 * ok, we have a journal description block,
  		 * let's see if the transaction was valid
  		 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2005
  		c_bh =
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2006
2007
  		    journal_bread(sb,
  				  SB_ONDISK_JOURNAL_1st_BLOCK(sb) +
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2008
  				  ((offset + get_desc_trans_len(desc) +
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2009
  				    1) % SB_ONDISK_JOURNAL_SIZE(sb)));
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2010
2011
2012
  		if (!c_bh)
  			return 0;
  		commit = (struct reiserfs_journal_commit *)c_bh->b_data;
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2013
2014
  		if (journal_compare_desc_commit(sb, desc, commit)) {
  			reiserfs_debug(sb, REISERFS_DEBUG_CODE,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2015
2016
2017
  				       "journal_transaction_is_valid, commit offset %ld had bad "
  				       "time %d or length %d",
  				       c_bh->b_blocknr -
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2018
  				       SB_ONDISK_JOURNAL_1st_BLOCK(sb),
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2019
2020
2021
2022
2023
2024
  				       get_commit_trans_id(commit),
  				       get_commit_trans_len(commit));
  			brelse(c_bh);
  			if (oldest_invalid_trans_id) {
  				*oldest_invalid_trans_id =
  				    get_desc_trans_id(desc);
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2025
  				reiserfs_debug(sb, REISERFS_DEBUG_CODE,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2026
2027
2028
2029
2030
2031
2032
2033
  					       "journal-1004: "
  					       "transaction_is_valid setting oldest invalid trans_id "
  					       "to %d",
  					       get_desc_trans_id(desc));
  			}
  			return -1;
  		}
  		brelse(c_bh);
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2034
  		reiserfs_debug(sb, REISERFS_DEBUG_CODE,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2035
2036
2037
  			       "journal-1006: found valid "
  			       "transaction start offset %llu, len %d id %d",
  			       d_bh->b_blocknr -
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2038
  			       SB_ONDISK_JOURNAL_1st_BLOCK(sb),
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
  			       get_desc_trans_len(desc),
  			       get_desc_trans_id(desc));
  		return 1;
  	} else {
  		return 0;
  	}
  }
  
  static void brelse_array(struct buffer_head **heads, int num)
  {
  	int i;
  	for (i = 0; i < num; i++) {
  		brelse(heads[i]);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2053
2054
2055
  }
  
  /*
098297b27   Jeff Mahoney   reiserfs: cleanup...
2056
2057
2058
2059
2060
   * given the start, and values for the oldest acceptable transactions,
   * this either reads in a replays a transaction, or returns because the
   * transaction is invalid, or too old.
   * NOTE: only called during fs mount
   */
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2061
  static int journal_read_transaction(struct super_block *sb,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2062
2063
  				    unsigned long cur_dblock,
  				    unsigned long oldest_start,
600ed4167   Jeff Mahoney   reiserfs: audit t...
2064
  				    unsigned int oldest_trans_id,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2065
2066
  				    unsigned long newest_mount_id)
  {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2067
  	struct reiserfs_journal *journal = SB_JOURNAL(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2068
2069
  	struct reiserfs_journal_desc *desc;
  	struct reiserfs_journal_commit *commit;
600ed4167   Jeff Mahoney   reiserfs: audit t...
2070
  	unsigned int trans_id = 0;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2071
2072
2073
2074
  	struct buffer_head *c_bh;
  	struct buffer_head *d_bh;
  	struct buffer_head **log_blocks = NULL;
  	struct buffer_head **real_blocks = NULL;
600ed4167   Jeff Mahoney   reiserfs: audit t...
2075
  	unsigned int trans_offset;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2076
2077
  	int i;
  	int trans_half;
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2078
  	d_bh = journal_bread(sb, cur_dblock);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2079
2080
2081
  	if (!d_bh)
  		return 1;
  	desc = (struct reiserfs_journal_desc *)d_bh->b_data;
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2082
2083
  	trans_offset = d_bh->b_blocknr - SB_ONDISK_JOURNAL_1st_BLOCK(sb);
  	reiserfs_debug(sb, REISERFS_DEBUG_CODE, "journal-1037: "
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2084
  		       "journal_read_transaction, offset %llu, len %d mount_id %d",
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2085
  		       d_bh->b_blocknr - SB_ONDISK_JOURNAL_1st_BLOCK(sb),
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2086
2087
  		       get_desc_trans_len(desc), get_desc_mount_id(desc));
  	if (get_desc_trans_id(desc) < oldest_trans_id) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2088
  		reiserfs_debug(sb, REISERFS_DEBUG_CODE, "journal-1039: "
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2089
2090
  			       "journal_read_trans skipping because %lu is too old",
  			       cur_dblock -
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2091
  			       SB_ONDISK_JOURNAL_1st_BLOCK(sb));
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2092
2093
2094
2095
  		brelse(d_bh);
  		return 1;
  	}
  	if (get_desc_mount_id(desc) != newest_mount_id) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2096
  		reiserfs_debug(sb, REISERFS_DEBUG_CODE, "journal-1146: "
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2097
2098
2099
2100
2101
2102
  			       "journal_read_trans skipping because %d is != "
  			       "newest_mount_id %lu", get_desc_mount_id(desc),
  			       newest_mount_id);
  		brelse(d_bh);
  		return 1;
  	}
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2103
  	c_bh = journal_bread(sb, SB_ONDISK_JOURNAL_1st_BLOCK(sb) +
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2104
  			     ((trans_offset + get_desc_trans_len(desc) + 1) %
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2105
  			      SB_ONDISK_JOURNAL_SIZE(sb)));
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2106
2107
2108
2109
2110
  	if (!c_bh) {
  		brelse(d_bh);
  		return 1;
  	}
  	commit = (struct reiserfs_journal_commit *)c_bh->b_data;
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2111
2112
  	if (journal_compare_desc_commit(sb, desc, commit)) {
  		reiserfs_debug(sb, REISERFS_DEBUG_CODE,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2113
2114
2115
  			       "journal_read_transaction, "
  			       "commit offset %llu had bad time %d or length %d",
  			       c_bh->b_blocknr -
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2116
  			       SB_ONDISK_JOURNAL_1st_BLOCK(sb),
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2117
2118
2119
2120
2121
2122
  			       get_commit_trans_id(commit),
  			       get_commit_trans_len(commit));
  		brelse(c_bh);
  		brelse(d_bh);
  		return 1;
  	}
3f8b5ee33   Jeff Mahoney   reiserfs: properl...
2123
2124
2125
2126
2127
2128
2129
2130
  
  	if (bdev_read_only(sb->s_bdev)) {
  		reiserfs_warning(sb, "clm-2076",
  				 "device is readonly, unable to replay log");
  		brelse(c_bh);
  		brelse(d_bh);
  		return -EROFS;
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2131
  	trans_id = get_desc_trans_id(desc);
098297b27   Jeff Mahoney   reiserfs: cleanup...
2132
2133
2134
2135
  	/*
  	 * now we know we've got a good transaction, and it was
  	 * inside the valid time ranges
  	 */
d739b42b8   Pekka Enberg   [PATCH] reiserfs:...
2136
2137
2138
2139
  	log_blocks = kmalloc(get_desc_trans_len(desc) *
  			     sizeof(struct buffer_head *), GFP_NOFS);
  	real_blocks = kmalloc(get_desc_trans_len(desc) *
  			      sizeof(struct buffer_head *), GFP_NOFS);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2140
2141
2142
  	if (!log_blocks || !real_blocks) {
  		brelse(c_bh);
  		brelse(d_bh);
d739b42b8   Pekka Enberg   [PATCH] reiserfs:...
2143
2144
  		kfree(log_blocks);
  		kfree(real_blocks);
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2145
  		reiserfs_warning(sb, "journal-1169",
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
2146
  				 "kmalloc failed, unable to mount FS");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2147
2148
2149
  		return -1;
  	}
  	/* get all the buffer heads */
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2150
  	trans_half = journal_trans_half(sb->s_blocksize);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2151
2152
  	for (i = 0; i < get_desc_trans_len(desc); i++) {
  		log_blocks[i] =
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2153
2154
  		    journal_getblk(sb,
  				   SB_ONDISK_JOURNAL_1st_BLOCK(sb) +
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2155
  				   (trans_offset + 1 +
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2156
  				    i) % SB_ONDISK_JOURNAL_SIZE(sb));
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2157
2158
  		if (i < trans_half) {
  			real_blocks[i] =
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2159
  			    sb_getblk(sb,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2160
2161
2162
  				      le32_to_cpu(desc->j_realblock[i]));
  		} else {
  			real_blocks[i] =
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2163
  			    sb_getblk(sb,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2164
2165
2166
  				      le32_to_cpu(commit->
  						  j_realblock[i - trans_half]));
  		}
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2167
2168
  		if (real_blocks[i]->b_blocknr > SB_BLOCK_COUNT(sb)) {
  			reiserfs_warning(sb, "journal-1207",
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
2169
2170
2171
  					 "REPLAY FAILURE fsck required! "
  					 "Block to replay is outside of "
  					 "filesystem");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2172
2173
2174
2175
  			goto abort_replay;
  		}
  		/* make sure we don't try to replay onto log or reserved area */
  		if (is_block_in_log_or_reserved_area
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2176
2177
  		    (sb, real_blocks[i]->b_blocknr)) {
  			reiserfs_warning(sb, "journal-1204",
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
2178
2179
  					 "REPLAY FAILURE fsck required! "
  					 "Trying to replay onto a log block");
cf776a7a4   Jeff Mahoney   reiserfs: cleanup...
2180
  abort_replay:
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2181
2182
2183
2184
  			brelse_array(log_blocks, i);
  			brelse_array(real_blocks, i);
  			brelse(c_bh);
  			brelse(d_bh);
d739b42b8   Pekka Enberg   [PATCH] reiserfs:...
2185
2186
  			kfree(log_blocks);
  			kfree(real_blocks);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2187
2188
2189
2190
  			return -1;
  		}
  	}
  	/* read in the log blocks, memcpy to the corresponding real block */
dfec8a14f   Mike Christie   fs: have ll_rw_bl...
2191
  	ll_rw_block(REQ_OP_READ, 0, get_desc_trans_len(desc), log_blocks);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2192
  	for (i = 0; i < get_desc_trans_len(desc); i++) {
8ebc42323   Frederic Weisbecker   reiserfs: kill-th...
2193

bd4c625c0   Linus Torvalds   reiserfs: run scr...
2194
2195
  		wait_on_buffer(log_blocks[i]);
  		if (!buffer_uptodate(log_blocks[i])) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2196
  			reiserfs_warning(sb, "journal-1212",
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
2197
2198
  					 "REPLAY FAILURE fsck required! "
  					 "buffer write failed");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2199
2200
2201
2202
2203
  			brelse_array(log_blocks + i,
  				     get_desc_trans_len(desc) - i);
  			brelse_array(real_blocks, get_desc_trans_len(desc));
  			brelse(c_bh);
  			brelse(d_bh);
d739b42b8   Pekka Enberg   [PATCH] reiserfs:...
2204
2205
  			kfree(log_blocks);
  			kfree(real_blocks);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
  			return -1;
  		}
  		memcpy(real_blocks[i]->b_data, log_blocks[i]->b_data,
  		       real_blocks[i]->b_size);
  		set_buffer_uptodate(real_blocks[i]);
  		brelse(log_blocks[i]);
  	}
  	/* flush out the real blocks */
  	for (i = 0; i < get_desc_trans_len(desc); i++) {
  		set_buffer_dirty(real_blocks[i]);
2a222ca99   Mike Christie   fs: have submit_b...
2216
  		write_dirty_buffer(real_blocks[i], 0);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2217
2218
2219
2220
  	}
  	for (i = 0; i < get_desc_trans_len(desc); i++) {
  		wait_on_buffer(real_blocks[i]);
  		if (!buffer_uptodate(real_blocks[i])) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2221
  			reiserfs_warning(sb, "journal-1226",
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
2222
2223
  					 "REPLAY FAILURE, fsck required! "
  					 "buffer write failed");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2224
2225
2226
2227
  			brelse_array(real_blocks + i,
  				     get_desc_trans_len(desc) - i);
  			brelse(c_bh);
  			brelse(d_bh);
d739b42b8   Pekka Enberg   [PATCH] reiserfs:...
2228
2229
  			kfree(log_blocks);
  			kfree(real_blocks);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2230
2231
2232
2233
2234
  			return -1;
  		}
  		brelse(real_blocks[i]);
  	}
  	cur_dblock =
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2235
  	    SB_ONDISK_JOURNAL_1st_BLOCK(sb) +
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2236
  	    ((trans_offset + get_desc_trans_len(desc) +
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2237
2238
  	      2) % SB_ONDISK_JOURNAL_SIZE(sb));
  	reiserfs_debug(sb, REISERFS_DEBUG_CODE,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2239
  		       "journal-1095: setting journal " "start to offset %ld",
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2240
  		       cur_dblock - SB_ONDISK_JOURNAL_1st_BLOCK(sb));
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2241

098297b27   Jeff Mahoney   reiserfs: cleanup...
2242
2243
2244
2245
  	/*
  	 * init starting values for the first transaction, in case
  	 * this is the last transaction to be replayed.
  	 */
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2246
  	journal->j_start = cur_dblock - SB_ONDISK_JOURNAL_1st_BLOCK(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2247
2248
  	journal->j_last_flush_trans_id = trans_id;
  	journal->j_trans_id = trans_id + 1;
a44c94a7b   Alexander Zarochentsev   [PATCH] reiserfs:...
2249
2250
2251
  	/* check for trans_id overflow */
  	if (journal->j_trans_id == 0)
  		journal->j_trans_id = 10;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2252
2253
  	brelse(c_bh);
  	brelse(d_bh);
d739b42b8   Pekka Enberg   [PATCH] reiserfs:...
2254
2255
  	kfree(log_blocks);
  	kfree(real_blocks);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2256
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2257
  }
098297b27   Jeff Mahoney   reiserfs: cleanup...
2258
2259
2260
2261
2262
2263
2264
2265
  /*
   * This function reads blocks starting from block and to max_block of bufsize
   * size (but no more than BUFNR blocks at a time). This proved to improve
   * mounting speed on self-rebuilding raid5 arrays at least.
   * Right now it is only used from journal code. But later we might use it
   * from other places.
   * Note: Do not use journal_getblk/sb_getblk functions here!
   */
3ee166704   Jeff Mahoney   reiserfs: fix usa...
2266
2267
2268
  static struct buffer_head *reiserfs_breada(struct block_device *dev,
  					   b_blocknr_t block, int bufsize,
  					   b_blocknr_t max_block)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2269
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2270
  	struct buffer_head *bhlist[BUFNR];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2271
  	unsigned int blocks = BUFNR;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2272
  	struct buffer_head *bh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2273
  	int i, j;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2274
2275
2276
2277
  
  	bh = __getblk(dev, block, bufsize);
  	if (buffer_uptodate(bh))
  		return (bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2278
2279
2280
2281
2282
2283
  	if (block + BUFNR > max_block) {
  		blocks = max_block - block;
  	}
  	bhlist[0] = bh;
  	j = 1;
  	for (i = 1; i < blocks; i++) {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2284
2285
2286
  		bh = __getblk(dev, block + i, bufsize);
  		if (buffer_uptodate(bh)) {
  			brelse(bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2287
  			break;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2288
2289
  		} else
  			bhlist[j++] = bh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2290
  	}
dfec8a14f   Mike Christie   fs: have ll_rw_bl...
2291
  	ll_rw_block(REQ_OP_READ, 0, j, bhlist);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2292
2293
  	for (i = 1; i < j; i++)
  		brelse(bhlist[i]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2294
  	bh = bhlist[0];
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2295
2296
  	wait_on_buffer(bh);
  	if (buffer_uptodate(bh))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2297
  		return bh;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2298
  	brelse(bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2299
2300
2301
2302
  	return NULL;
  }
  
  /*
098297b27   Jeff Mahoney   reiserfs: cleanup...
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
   * read and replay the log
   * on a clean unmount, the journal header's next unflushed pointer will be
   * to an invalid transaction.  This tests that before finding all the
   * transactions in the log, which makes normal mount times fast.
   *
   * After a crash, this starts with the next unflushed transaction, and
   * replays until it finds one too old, or invalid.
   *
   * On exit, it sets things up so the first transaction will work correctly.
   * NOTE: only called during fs mount
   */
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2314
  static int journal_read(struct super_block *sb)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2315
  {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2316
  	struct reiserfs_journal *journal = SB_JOURNAL(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2317
  	struct reiserfs_journal_desc *desc;
600ed4167   Jeff Mahoney   reiserfs: audit t...
2318
2319
  	unsigned int oldest_trans_id = 0;
  	unsigned int oldest_invalid_trans_id = 0;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
  	time_t start;
  	unsigned long oldest_start = 0;
  	unsigned long cur_dblock = 0;
  	unsigned long newest_mount_id = 9;
  	struct buffer_head *d_bh;
  	struct reiserfs_journal_header *jh;
  	int valid_journal_header = 0;
  	int replay_count = 0;
  	int continue_replay = 1;
  	int ret;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2330

a9dd36435   Jeff Mahoney   reiserfs: rename ...
2331
  	cur_dblock = SB_ONDISK_JOURNAL_1st_BLOCK(sb);
a1c6f0573   Dmitry Monakhov   fs: use block_dev...
2332
2333
2334
  	reiserfs_info(sb, "checking transaction log (%pg)
  ",
  		      journal->j_dev_bd);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2335
  	start = get_seconds();
098297b27   Jeff Mahoney   reiserfs: cleanup...
2336
2337
2338
2339
  	/*
  	 * step 1, read in the journal header block.  Check the transaction
  	 * it says is the first unflushed, and if that transaction is not
  	 * valid, replay is done
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2340
  	 */
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2341
2342
2343
  	journal->j_header_bh = journal_bread(sb,
  					     SB_ONDISK_JOURNAL_1st_BLOCK(sb)
  					     + SB_ONDISK_JOURNAL_SIZE(sb));
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2344
2345
2346
2347
  	if (!journal->j_header_bh) {
  		return 1;
  	}
  	jh = (struct reiserfs_journal_header *)(journal->j_header_bh->b_data);
c499ec24c   Vladimir V. Saveliev   [PATCH] reiserfs:...
2348
  	if (le32_to_cpu(jh->j_first_unflushed_offset) <
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2349
  	    SB_ONDISK_JOURNAL_SIZE(sb)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2350
2351
  	    && le32_to_cpu(jh->j_last_flush_trans_id) > 0) {
  		oldest_start =
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2352
  		    SB_ONDISK_JOURNAL_1st_BLOCK(sb) +
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2353
2354
2355
  		    le32_to_cpu(jh->j_first_unflushed_offset);
  		oldest_trans_id = le32_to_cpu(jh->j_last_flush_trans_id) + 1;
  		newest_mount_id = le32_to_cpu(jh->j_mount_id);
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2356
  		reiserfs_debug(sb, REISERFS_DEBUG_CODE,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2357
2358
2359
2360
2361
  			       "journal-1153: found in "
  			       "header: first_unflushed_offset %d, last_flushed_trans_id "
  			       "%lu", le32_to_cpu(jh->j_first_unflushed_offset),
  			       le32_to_cpu(jh->j_last_flush_trans_id));
  		valid_journal_header = 1;
098297b27   Jeff Mahoney   reiserfs: cleanup...
2362
2363
2364
2365
  		/*
  		 * now, we try to read the first unflushed offset.  If it
  		 * is not valid, there is nothing more we can do, and it
  		 * makes no sense to read through the whole log.
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2366
2367
  		 */
  		d_bh =
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2368
2369
  		    journal_bread(sb,
  				  SB_ONDISK_JOURNAL_1st_BLOCK(sb) +
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2370
  				  le32_to_cpu(jh->j_first_unflushed_offset));
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2371
  		ret = journal_transaction_is_valid(sb, d_bh, NULL, NULL);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2372
2373
2374
2375
2376
2377
  		if (!ret) {
  			continue_replay = 0;
  		}
  		brelse(d_bh);
  		goto start_log_replay;
  	}
098297b27   Jeff Mahoney   reiserfs: cleanup...
2378
2379
2380
2381
  	/*
  	 * ok, there are transactions that need to be replayed.  start
  	 * with the first log block, find all the valid transactions, and
  	 * pick out the oldest.
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2382
2383
2384
  	 */
  	while (continue_replay
  	       && cur_dblock <
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2385
2386
  	       (SB_ONDISK_JOURNAL_1st_BLOCK(sb) +
  		SB_ONDISK_JOURNAL_SIZE(sb))) {
098297b27   Jeff Mahoney   reiserfs: cleanup...
2387
2388
2389
2390
  		/*
  		 * Note that it is required for blocksize of primary fs
  		 * device and journal device to be the same
  		 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2391
2392
  		d_bh =
  		    reiserfs_breada(journal->j_dev_bd, cur_dblock,
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2393
2394
2395
  				    sb->s_blocksize,
  				    SB_ONDISK_JOURNAL_1st_BLOCK(sb) +
  				    SB_ONDISK_JOURNAL_SIZE(sb));
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2396
  		ret =
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2397
  		    journal_transaction_is_valid(sb, d_bh,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2398
2399
2400
2401
2402
2403
2404
2405
  						 &oldest_invalid_trans_id,
  						 &newest_mount_id);
  		if (ret == 1) {
  			desc = (struct reiserfs_journal_desc *)d_bh->b_data;
  			if (oldest_start == 0) {	/* init all oldest_ values */
  				oldest_trans_id = get_desc_trans_id(desc);
  				oldest_start = d_bh->b_blocknr;
  				newest_mount_id = get_desc_mount_id(desc);
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2406
  				reiserfs_debug(sb, REISERFS_DEBUG_CODE,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2407
2408
2409
2410
  					       "journal-1179: Setting "
  					       "oldest_start to offset %llu, trans_id %lu",
  					       oldest_start -
  					       SB_ONDISK_JOURNAL_1st_BLOCK
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2411
  					       (sb), oldest_trans_id);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2412
2413
2414
2415
  			} else if (oldest_trans_id > get_desc_trans_id(desc)) {
  				/* one we just read was older */
  				oldest_trans_id = get_desc_trans_id(desc);
  				oldest_start = d_bh->b_blocknr;
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2416
  				reiserfs_debug(sb, REISERFS_DEBUG_CODE,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2417
2418
2419
2420
  					       "journal-1180: Resetting "
  					       "oldest_start to offset %lu, trans_id %lu",
  					       oldest_start -
  					       SB_ONDISK_JOURNAL_1st_BLOCK
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2421
  					       (sb), oldest_trans_id);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2422
2423
2424
  			}
  			if (newest_mount_id < get_desc_mount_id(desc)) {
  				newest_mount_id = get_desc_mount_id(desc);
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2425
  				reiserfs_debug(sb, REISERFS_DEBUG_CODE,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
  					       "journal-1299: Setting "
  					       "newest_mount_id to %d",
  					       get_desc_mount_id(desc));
  			}
  			cur_dblock += get_desc_trans_len(desc) + 2;
  		} else {
  			cur_dblock++;
  		}
  		brelse(d_bh);
  	}
cf776a7a4   Jeff Mahoney   reiserfs: cleanup...
2436
  start_log_replay:
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2437
2438
  	cur_dblock = oldest_start;
  	if (oldest_trans_id) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2439
  		reiserfs_debug(sb, REISERFS_DEBUG_CODE,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2440
2441
  			       "journal-1206: Starting replay "
  			       "from offset %llu, trans_id %lu",
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2442
  			       cur_dblock - SB_ONDISK_JOURNAL_1st_BLOCK(sb),
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2443
2444
2445
2446
2447
2448
  			       oldest_trans_id);
  
  	}
  	replay_count = 0;
  	while (continue_replay && oldest_trans_id > 0) {
  		ret =
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2449
  		    journal_read_transaction(sb, cur_dblock, oldest_start,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2450
2451
2452
2453
2454
2455
2456
  					     oldest_trans_id, newest_mount_id);
  		if (ret < 0) {
  			return ret;
  		} else if (ret != 0) {
  			break;
  		}
  		cur_dblock =
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2457
  		    SB_ONDISK_JOURNAL_1st_BLOCK(sb) + journal->j_start;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2458
2459
2460
2461
2462
2463
  		replay_count++;
  		if (cur_dblock == oldest_start)
  			break;
  	}
  
  	if (oldest_trans_id == 0) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2464
  		reiserfs_debug(sb, REISERFS_DEBUG_CODE,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2465
2466
  			       "journal-1225: No valid " "transactions found");
  	}
098297b27   Jeff Mahoney   reiserfs: cleanup...
2467
2468
2469
2470
2471
  	/*
  	 * j_start does not get set correctly if we don't replay any
  	 * transactions.  if we had a valid journal_header, set j_start
  	 * to the first unflushed transaction value, copy the trans_id
  	 * from the header
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2472
2473
2474
2475
2476
  	 */
  	if (valid_journal_header && replay_count == 0) {
  		journal->j_start = le32_to_cpu(jh->j_first_unflushed_offset);
  		journal->j_trans_id =
  		    le32_to_cpu(jh->j_last_flush_trans_id) + 1;
a44c94a7b   Alexander Zarochentsev   [PATCH] reiserfs:...
2477
2478
2479
  		/* check for trans_id overflow */
  		if (journal->j_trans_id == 0)
  			journal->j_trans_id = 10;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2480
2481
2482
2483
2484
2485
  		journal->j_last_flush_trans_id =
  		    le32_to_cpu(jh->j_last_flush_trans_id);
  		journal->j_mount_id = le32_to_cpu(jh->j_mount_id) + 1;
  	} else {
  		journal->j_mount_id = newest_mount_id + 1;
  	}
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2486
  	reiserfs_debug(sb, REISERFS_DEBUG_CODE, "journal-1299: Setting "
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2487
2488
2489
  		       "newest_mount_id to %lu", journal->j_mount_id);
  	journal->j_first_unflushed_offset = journal->j_start;
  	if (replay_count > 0) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2490
  		reiserfs_info(sb,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2491
2492
2493
2494
  			      "replayed %d transactions in %lu seconds
  ",
  			      replay_count, get_seconds() - start);
  	}
278f6679f   Jeff Mahoney   reiserfs: locking...
2495
2496
  	/* needed to satisfy the locking in _update_journal_header_block */
  	reiserfs_write_lock(sb);
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2497
2498
  	if (!bdev_read_only(sb->s_bdev) &&
  	    _update_journal_header_block(sb, journal->j_start,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2499
  					 journal->j_last_flush_trans_id)) {
278f6679f   Jeff Mahoney   reiserfs: locking...
2500
  		reiserfs_write_unlock(sb);
098297b27   Jeff Mahoney   reiserfs: cleanup...
2501
2502
2503
  		/*
  		 * replay failed, caller must call free_journal_ram and abort
  		 * the mount
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2504
2505
2506
  		 */
  		return -1;
  	}
278f6679f   Jeff Mahoney   reiserfs: locking...
2507
  	reiserfs_write_unlock(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2508
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2509
2510
2511
2512
  }
  
  static struct reiserfs_journal_list *alloc_journal_list(struct super_block *s)
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2513
  	struct reiserfs_journal_list *jl;
8c777cc4b   Pekka Enberg   [PATCH] reiserfs:...
2514
2515
  	jl = kzalloc(sizeof(struct reiserfs_journal_list),
  		     GFP_NOFS | __GFP_NOFAIL);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2516
2517
2518
2519
  	INIT_LIST_HEAD(&jl->j_list);
  	INIT_LIST_HEAD(&jl->j_working_list);
  	INIT_LIST_HEAD(&jl->j_tail_bh_list);
  	INIT_LIST_HEAD(&jl->j_bh_list);
90415deac   Jeff Mahoney   reiserfs: convert...
2520
  	mutex_init(&jl->j_commit_mutex);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2521
2522
2523
2524
  	SB_JOURNAL(s)->j_num_lists++;
  	get_journal_list(jl);
  	return jl;
  }
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2525
  static void journal_list_init(struct super_block *sb)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2526
  {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2527
  	SB_JOURNAL(sb)->j_current_jl = alloc_journal_list(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2528
  }
4385bab12   Al Viro   make blkdev_put()...
2529
  static void release_journal_dev(struct super_block *super,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2530
2531
  			       struct reiserfs_journal *journal)
  {
86098fa01   Christoph Hellwig   reiserfs: use ope...
2532
  	if (journal->j_dev_bd != NULL) {
4385bab12   Al Viro   make blkdev_put()...
2533
  		blkdev_put(journal->j_dev_bd, journal->j_dev_mode);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2534
2535
  		journal->j_dev_bd = NULL;
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2536
2537
2538
2539
2540
  }
  
  static int journal_init_dev(struct super_block *super,
  			    struct reiserfs_journal *journal,
  			    const char *jdev_name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2541
2542
2543
  {
  	int result;
  	dev_t jdev;
e525fd89d   Tejun Heo   block: make blkde...
2544
  	fmode_t blkdev_mode = FMODE_READ | FMODE_WRITE | FMODE_EXCL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2545
2546
2547
  	char b[BDEVNAME_SIZE];
  
  	result = 0;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2548
  	journal->j_dev_bd = NULL;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2549
2550
  	jdev = SB_ONDISK_JOURNAL_DEVICE(super) ?
  	    new_decode_dev(SB_ONDISK_JOURNAL_DEVICE(super)) : super->s_dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2551
2552
  
  	if (bdev_read_only(super->s_bdev))
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2553
  		blkdev_mode = FMODE_READ;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2554
2555
  
  	/* there is no "jdev" option and journal is on separate device */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2556
  	if ((!jdev_name || !jdev_name[0])) {
e525fd89d   Tejun Heo   block: make blkde...
2557
2558
  		if (jdev == super->s_dev)
  			blkdev_mode &= ~FMODE_EXCL;
d4d776299   Tejun Heo   block: clean up b...
2559
2560
  		journal->j_dev_bd = blkdev_get_by_dev(jdev, blkdev_mode,
  						      journal);
e5eb8caa8   Al Viro   [PATCH] remember ...
2561
  		journal->j_dev_mode = blkdev_mode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2562
2563
2564
  		if (IS_ERR(journal->j_dev_bd)) {
  			result = PTR_ERR(journal->j_dev_bd);
  			journal->j_dev_bd = NULL;
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
2565
  			reiserfs_warning(super, "sh-458",
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2566
2567
  					 "cannot init journal device '%s': %i",
  					 __bdevname(jdev, b), result);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2568
  			return result;
e525fd89d   Tejun Heo   block: make blkde...
2569
  		} else if (jdev != super->s_dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2570
  			set_blocksize(journal->j_dev_bd, super->s_blocksize);
86098fa01   Christoph Hellwig   reiserfs: use ope...
2571

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2572
2573
  		return 0;
  	}
e5eb8caa8   Al Viro   [PATCH] remember ...
2574
  	journal->j_dev_mode = blkdev_mode;
d4d776299   Tejun Heo   block: clean up b...
2575
  	journal->j_dev_bd = blkdev_get_by_path(jdev_name, blkdev_mode, journal);
86098fa01   Christoph Hellwig   reiserfs: use ope...
2576
2577
2578
  	if (IS_ERR(journal->j_dev_bd)) {
  		result = PTR_ERR(journal->j_dev_bd);
  		journal->j_dev_bd = NULL;
f659e7e79   Andrew Morton   fs/reiserfs/journ...
2579
  		reiserfs_warning(super, "sh-457",
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2580
2581
  				 "journal_init_dev: Cannot open '%s': %i",
  				 jdev_name, result);
86098fa01   Christoph Hellwig   reiserfs: use ope...
2582
  		return result;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2583
  	}
86098fa01   Christoph Hellwig   reiserfs: use ope...
2584
2585
2586
  
  	set_blocksize(journal->j_dev_bd, super->s_blocksize);
  	reiserfs_info(super,
a1c6f0573   Dmitry Monakhov   fs: use block_dev...
2587
2588
2589
  		      "journal_init_dev: journal device: %pg
  ",
  		      journal->j_dev_bd);
86098fa01   Christoph Hellwig   reiserfs: use ope...
2590
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2591
  }
098297b27   Jeff Mahoney   reiserfs: cleanup...
2592
  /*
cf3d0b818   Edward Shishkin   reiserfs: do not ...
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
   * When creating/tuning a file system user can assign some
   * journal params within boundaries which depend on the ratio
   * blocksize/standard_blocksize.
   *
   * For blocks >= standard_blocksize transaction size should
   * be not less then JOURNAL_TRANS_MIN_DEFAULT, and not more
   * then JOURNAL_TRANS_MAX_DEFAULT.
   *
   * For blocks < standard_blocksize these boundaries should be
   * decreased proportionally.
   */
  #define REISERFS_STANDARD_BLKSIZE (4096)
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2605
  static int check_advise_trans_params(struct super_block *sb,
cf3d0b818   Edward Shishkin   reiserfs: do not ...
2606
2607
2608
  				     struct reiserfs_journal *journal)
  {
          if (journal->j_trans_max) {
098297b27   Jeff Mahoney   reiserfs: cleanup...
2609
  		/* Non-default journal params.  Do sanity check for them. */
cf3d0b818   Edward Shishkin   reiserfs: do not ...
2610
  	        int ratio = 1;
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2611
2612
  		if (sb->s_blocksize < REISERFS_STANDARD_BLKSIZE)
  		        ratio = REISERFS_STANDARD_BLKSIZE / sb->s_blocksize;
cf3d0b818   Edward Shishkin   reiserfs: do not ...
2613
2614
2615
  
  		if (journal->j_trans_max > JOURNAL_TRANS_MAX_DEFAULT / ratio ||
  		    journal->j_trans_max < JOURNAL_TRANS_MIN_DEFAULT / ratio ||
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2616
  		    SB_ONDISK_JOURNAL_SIZE(sb) / journal->j_trans_max <
cf3d0b818   Edward Shishkin   reiserfs: do not ...
2617
  		    JOURNAL_MIN_RATIO) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2618
  			reiserfs_warning(sb, "sh-462",
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
2619
2620
  					 "bad transaction max size (%u). "
  					 "FSCK?", journal->j_trans_max);
cf3d0b818   Edward Shishkin   reiserfs: do not ...
2621
2622
2623
2624
  			return 1;
  		}
  		if (journal->j_max_batch != (journal->j_trans_max) *
  		        JOURNAL_MAX_BATCH_DEFAULT/JOURNAL_TRANS_MAX_DEFAULT) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2625
  			reiserfs_warning(sb, "sh-463",
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
2626
2627
  					 "bad transaction max batch (%u). "
  					 "FSCK?", journal->j_max_batch);
cf3d0b818   Edward Shishkin   reiserfs: do not ...
2628
2629
2630
  			return 1;
  		}
  	} else {
098297b27   Jeff Mahoney   reiserfs: cleanup...
2631
2632
2633
2634
2635
2636
  		/*
  		 * Default journal params.
  		 * The file system was created by old version
  		 * of mkreiserfs, so some fields contain zeros,
  		 * and we need to advise proper values for them
  		 */
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2637
2638
2639
  		if (sb->s_blocksize != REISERFS_STANDARD_BLKSIZE) {
  			reiserfs_warning(sb, "sh-464", "bad blocksize (%u)",
  					 sb->s_blocksize);
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
2640
2641
  			return 1;
  		}
cf3d0b818   Edward Shishkin   reiserfs: do not ...
2642
2643
2644
2645
2646
2647
  		journal->j_trans_max = JOURNAL_TRANS_MAX_DEFAULT;
  		journal->j_max_batch = JOURNAL_MAX_BATCH_DEFAULT;
  		journal->j_max_commit_age = JOURNAL_MAX_COMMIT_AGE;
  	}
  	return 0;
  }
098297b27   Jeff Mahoney   reiserfs: cleanup...
2648
  /* must be called once on fs mount.  calls journal_read for you */
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2649
  int journal_init(struct super_block *sb, const char *j_dev_name,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2650
2651
  		 int old_format, unsigned int commit_max_age)
  {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2652
  	int num_cnodes = SB_ONDISK_JOURNAL_SIZE(sb) * 2;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2653
2654
2655
2656
2657
  	struct buffer_head *bhjh;
  	struct reiserfs_super_block *rs;
  	struct reiserfs_journal_header *jh;
  	struct reiserfs_journal *journal;
  	struct reiserfs_journal_list *jl;
98ea3f50b   Frederic Weisbecker   reiserfs: Fix rem...
2658
  	int ret;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2659

558feb081   Joe Perches   fs: Convert vmall...
2660
  	journal = SB_JOURNAL(sb) = vzalloc(sizeof(struct reiserfs_journal));
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2661
  	if (!journal) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2662
  		reiserfs_warning(sb, "journal-1256",
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
2663
  				 "unable to get memory for journal structure");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2664
2665
  		return 1;
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2666
2667
2668
2669
2670
  	INIT_LIST_HEAD(&journal->j_bitmap_nodes);
  	INIT_LIST_HEAD(&journal->j_prealloc_list);
  	INIT_LIST_HEAD(&journal->j_working_list);
  	INIT_LIST_HEAD(&journal->j_journal_list);
  	journal->j_persistent_trans = 0;
37c69b98d   Frederic Weisbecker   reiserfs: don't l...
2671
2672
  	if (reiserfs_allocate_list_bitmaps(sb, journal->j_list_bitmap,
  					   reiserfs_bmap_count(sb)))
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2673
  		goto free_and_return;
98ea3f50b   Frederic Weisbecker   reiserfs: Fix rem...
2674

a9dd36435   Jeff Mahoney   reiserfs: rename ...
2675
  	allocate_bitmap_nodes(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2676
2677
  
  	/* reserved for journal area support */
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2678
  	SB_JOURNAL_1st_RESERVED_BLOCK(sb) = (old_format ?
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2679
  						 REISERFS_OLD_DISK_OFFSET_IN_BYTES
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2680
2681
  						 / sb->s_blocksize +
  						 reiserfs_bmap_count(sb) +
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2682
2683
  						 1 :
  						 REISERFS_DISK_OFFSET_IN_BYTES /
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2684
  						 sb->s_blocksize + 2);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2685

098297b27   Jeff Mahoney   reiserfs: cleanup...
2686
2687
2688
2689
  	/*
  	 * Sanity check to see is the standard journal fitting
  	 * within first bitmap (actual for small blocksizes)
  	 */
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2690
2691
2692
2693
  	if (!SB_ONDISK_JOURNAL_DEVICE(sb) &&
  	    (SB_JOURNAL_1st_RESERVED_BLOCK(sb) +
  	     SB_ONDISK_JOURNAL_SIZE(sb) > sb->s_blocksize * 8)) {
  		reiserfs_warning(sb, "journal-1393",
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
2694
2695
  				 "journal does not fit for area addressed "
  				 "by first of bitmap blocks. It starts at "
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2696
  				 "%u and its size is %u. Block size %ld",
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2697
2698
2699
  				 SB_JOURNAL_1st_RESERVED_BLOCK(sb),
  				 SB_ONDISK_JOURNAL_SIZE(sb),
  				 sb->s_blocksize);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2700
2701
  		goto free_and_return;
  	}
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2702
2703
  	if (journal_init_dev(sb, journal, j_dev_name) != 0) {
  		reiserfs_warning(sb, "sh-462",
6774def64   Masanari Iida   treewide: fix typ...
2704
  				 "unable to initialize journal device");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2705
2706
  		goto free_and_return;
  	}
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2707
  	rs = SB_DISK_SUPER_BLOCK(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2708
2709
  
  	/* read journal header */
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2710
2711
2712
  	bhjh = journal_bread(sb,
  			     SB_ONDISK_JOURNAL_1st_BLOCK(sb) +
  			     SB_ONDISK_JOURNAL_SIZE(sb));
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2713
  	if (!bhjh) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2714
  		reiserfs_warning(sb, "sh-459",
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
2715
  				 "unable to read journal header");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2716
2717
2718
2719
2720
2721
2722
2723
  		goto free_and_return;
  	}
  	jh = (struct reiserfs_journal_header *)(bhjh->b_data);
  
  	/* make sure that journal matches to the super block */
  	if (is_reiserfs_jr(rs)
  	    && (le32_to_cpu(jh->jh_journal.jp_journal_magic) !=
  		sb_jp_journal_magic(rs))) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2724
  		reiserfs_warning(sb, "sh-460",
a1c6f0573   Dmitry Monakhov   fs: use block_dev...
2725
  				 "journal header magic %x (device %pg) does "
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
2726
2727
  				 "not match to magic found in super block %x",
  				 jh->jh_journal.jp_journal_magic,
a1c6f0573   Dmitry Monakhov   fs: use block_dev...
2728
  				 journal->j_dev_bd,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
  				 sb_jp_journal_magic(rs));
  		brelse(bhjh);
  		goto free_and_return;
  	}
  
  	journal->j_trans_max = le32_to_cpu(jh->jh_journal.jp_journal_trans_max);
  	journal->j_max_batch = le32_to_cpu(jh->jh_journal.jp_journal_max_batch);
  	journal->j_max_commit_age =
  	    le32_to_cpu(jh->jh_journal.jp_journal_max_commit_age);
  	journal->j_max_trans_age = JOURNAL_MAX_TRANS_AGE;
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2739
  	if (check_advise_trans_params(sb, journal) != 0)
cf3d0b818   Edward Shishkin   reiserfs: do not ...
2740
  	        goto free_and_return;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2741
2742
2743
2744
2745
2746
  	journal->j_default_max_commit_age = journal->j_max_commit_age;
  
  	if (commit_max_age != 0) {
  		journal->j_max_commit_age = commit_max_age;
  		journal->j_max_trans_age = commit_max_age;
  	}
a1c6f0573   Dmitry Monakhov   fs: use block_dev...
2747
  	reiserfs_info(sb, "journal params: device %pg, size %u, "
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2748
2749
2750
  		      "journal first block %u, max trans len %u, max batch %u, "
  		      "max commit age %u, max trans age %u
  ",
a1c6f0573   Dmitry Monakhov   fs: use block_dev...
2751
  		      journal->j_dev_bd,
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2752
2753
  		      SB_ONDISK_JOURNAL_SIZE(sb),
  		      SB_ONDISK_JOURNAL_1st_BLOCK(sb),
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2754
2755
2756
2757
2758
2759
2760
  		      journal->j_trans_max,
  		      journal->j_max_batch,
  		      journal->j_max_commit_age, journal->j_max_trans_age);
  
  	brelse(bhjh);
  
  	journal->j_list_bitmap_index = 0;
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2761
  	journal_list_init(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
  
  	memset(journal->j_list_hash_table, 0,
  	       JOURNAL_HASH_SIZE * sizeof(struct reiserfs_journal_cnode *));
  
  	INIT_LIST_HEAD(&journal->j_dirty_buffers);
  	spin_lock_init(&journal->j_dirty_buffers_lock);
  
  	journal->j_start = 0;
  	journal->j_len = 0;
  	journal->j_len_alloc = 0;
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
2772
2773
  	atomic_set(&journal->j_wcount, 0);
  	atomic_set(&journal->j_async_throttle, 0);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2774
2775
2776
2777
  	journal->j_bcount = 0;
  	journal->j_trans_start_time = 0;
  	journal->j_last = NULL;
  	journal->j_first = NULL;
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
2778
  	init_waitqueue_head(&journal->j_join_wait);
f68215c46   Jeff Mahoney   reiserfs: convert...
2779
  	mutex_init(&journal->j_mutex);
afe702590   Jeff Mahoney   reiserfs: convert...
2780
  	mutex_init(&journal->j_flush_mutex);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2781
2782
2783
2784
  
  	journal->j_trans_id = 10;
  	journal->j_mount_id = 10;
  	journal->j_state = 0;
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
2785
  	atomic_set(&journal->j_jlock, 0);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2786
2787
2788
2789
2790
  	journal->j_cnode_free_list = allocate_cnodes(num_cnodes);
  	journal->j_cnode_free_orig = journal->j_cnode_free_list;
  	journal->j_cnode_free = journal->j_cnode_free_list ? num_cnodes : 0;
  	journal->j_cnode_used = 0;
  	journal->j_must_wait = 0;
576f6d795   Jeff Mahoney   [PATCH] reiserfs:...
2791
  	if (journal->j_cnode_free == 0) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2792
  		reiserfs_warning(sb, "journal-2004", "Journal cnode memory "
576f6d795   Jeff Mahoney   [PATCH] reiserfs:...
2793
2794
2795
2796
2797
2798
  		                 "allocation failed (%ld bytes). Journal is "
  		                 "too large for available memory. Usually "
  		                 "this is due to a journal that is too large.",
  		                 sizeof (struct reiserfs_journal_cnode) * num_cnodes);
          	goto free_and_return;
  	}
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2799
  	init_journal_hash(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2800
  	jl = journal->j_current_jl;
37c69b98d   Frederic Weisbecker   reiserfs: don't l...
2801
2802
2803
2804
2805
2806
2807
  
  	/*
  	 * get_list_bitmap() may call flush_commit_list() which
  	 * requires the lock. Calling flush_commit_list() shouldn't happen
  	 * this early but I like to be paranoid.
  	 */
  	reiserfs_write_lock(sb);
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2808
  	jl->j_list_bitmap = get_list_bitmap(sb, jl);
37c69b98d   Frederic Weisbecker   reiserfs: don't l...
2809
  	reiserfs_write_unlock(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2810
  	if (!jl->j_list_bitmap) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2811
  		reiserfs_warning(sb, "journal-2005",
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
2812
  				 "get_list_bitmap failed for journal list 0");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2813
2814
  		goto free_and_return;
  	}
37c69b98d   Frederic Weisbecker   reiserfs: don't l...
2815

37c69b98d   Frederic Weisbecker   reiserfs: don't l...
2816
  	ret = journal_read(sb);
37c69b98d   Frederic Weisbecker   reiserfs: don't l...
2817
  	if (ret < 0) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2818
  		reiserfs_warning(sb, "reiserfs-2006",
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
2819
  				 "Replay Failure, unable to mount");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2820
2821
  		goto free_and_return;
  	}
c4028958b   David Howells   WorkStruct: make ...
2822
  	INIT_DELAYED_WORK(&journal->j_work, flush_async_commits);
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2823
  	journal->j_work_sb = sb;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2824
  	return 0;
cf776a7a4   Jeff Mahoney   reiserfs: cleanup...
2825
  free_and_return:
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2826
  	free_journal_ram(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2827
  	return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2828
2829
2830
  }
  
  /*
098297b27   Jeff Mahoney   reiserfs: cleanup...
2831
2832
2833
2834
   * test for a polite end of the current transaction.  Used by file_write,
   * and should be used by delete to make sure they don't write more than
   * can fit inside a single transaction
   */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
  int journal_transaction_should_end(struct reiserfs_transaction_handle *th,
  				   int new_alloc)
  {
  	struct reiserfs_journal *journal = SB_JOURNAL(th->t_super);
  	time_t now = get_seconds();
  	/* cannot restart while nested */
  	BUG_ON(!th->t_trans_id);
  	if (th->t_refcount > 1)
  		return 0;
  	if (journal->j_must_wait > 0 ||
  	    (journal->j_len_alloc + new_alloc) >= journal->j_max_batch ||
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
2846
  	    atomic_read(&journal->j_jlock) ||
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2847
2848
2849
2850
  	    (now - journal->j_trans_start_time) > journal->j_max_trans_age ||
  	    journal->j_cnode_free < (journal->j_trans_max * 3)) {
  		return 1;
  	}
b18c1c6e0   Davidlohr Bueso   reiserfs: delete ...
2851

6ae1ea447   Chris Mason   [PATCH] reiserfs:...
2852
2853
  	journal->j_len_alloc += new_alloc;
  	th->t_blocks_allocated += new_alloc ;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2854
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2855
  }
098297b27   Jeff Mahoney   reiserfs: cleanup...
2856
  /* this must be called inside a transaction */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2857
2858
2859
2860
2861
2862
2863
  void reiserfs_block_writes(struct reiserfs_transaction_handle *th)
  {
  	struct reiserfs_journal *journal = SB_JOURNAL(th->t_super);
  	BUG_ON(!th->t_trans_id);
  	journal->j_must_wait = 1;
  	set_bit(J_WRITERS_BLOCKED, &journal->j_state);
  	return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2864
  }
098297b27   Jeff Mahoney   reiserfs: cleanup...
2865
  /* this must be called without a transaction started */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2866
2867
2868
2869
2870
  void reiserfs_allow_writes(struct super_block *s)
  {
  	struct reiserfs_journal *journal = SB_JOURNAL(s);
  	clear_bit(J_WRITERS_BLOCKED, &journal->j_state);
  	wake_up(&journal->j_join_wait);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2871
  }
098297b27   Jeff Mahoney   reiserfs: cleanup...
2872
  /* this must be called without a transaction started */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2873
2874
2875
2876
2877
2878
2879
2880
2881
  void reiserfs_wait_on_write_block(struct super_block *s)
  {
  	struct reiserfs_journal *journal = SB_JOURNAL(s);
  	wait_event(journal->j_join_wait,
  		   !test_bit(J_WRITERS_BLOCKED, &journal->j_state));
  }
  
  static void queue_log_writer(struct super_block *s)
  {
ac6424b98   Ingo Molnar   sched/wait: Renam...
2882
  	wait_queue_entry_t wait;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2883
2884
2885
2886
2887
2888
2889
2890
2891
  	struct reiserfs_journal *journal = SB_JOURNAL(s);
  	set_bit(J_WRITERS_QUEUED, &journal->j_state);
  
  	/*
  	 * we don't want to use wait_event here because
  	 * we only want to wait once.
  	 */
  	init_waitqueue_entry(&wait, current);
  	add_wait_queue(&journal->j_join_wait, &wait);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2892
  	set_current_state(TASK_UNINTERRUPTIBLE);
8ebc42323   Frederic Weisbecker   reiserfs: kill-th...
2893
  	if (test_bit(J_WRITERS_QUEUED, &journal->j_state)) {
278f6679f   Jeff Mahoney   reiserfs: locking...
2894
  		int depth = reiserfs_write_unlock_nested(s);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2895
  		schedule();
278f6679f   Jeff Mahoney   reiserfs: locking...
2896
  		reiserfs_write_lock_nested(s, depth);
8ebc42323   Frederic Weisbecker   reiserfs: kill-th...
2897
  	}
5ab2f7e0f   Milind Arun Choudhary   reiserfs: use __s...
2898
  	__set_current_state(TASK_RUNNING);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2899
2900
2901
2902
2903
2904
2905
2906
2907
  	remove_wait_queue(&journal->j_join_wait, &wait);
  }
  
  static void wake_queued_writers(struct super_block *s)
  {
  	struct reiserfs_journal *journal = SB_JOURNAL(s);
  	if (test_and_clear_bit(J_WRITERS_QUEUED, &journal->j_state))
  		wake_up(&journal->j_join_wait);
  }
600ed4167   Jeff Mahoney   reiserfs: audit t...
2908
  static void let_transaction_grow(struct super_block *sb, unsigned int trans_id)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2909
2910
2911
2912
  {
  	struct reiserfs_journal *journal = SB_JOURNAL(sb);
  	unsigned long bcount = journal->j_bcount;
  	while (1) {
278f6679f   Jeff Mahoney   reiserfs: locking...
2913
2914
2915
  		int depth;
  
  		depth = reiserfs_write_unlock_nested(sb);
041e0e3b1   Nishanth Aravamudan   [PATCH] fs: fix-u...
2916
  		schedule_timeout_uninterruptible(1);
278f6679f   Jeff Mahoney   reiserfs: locking...
2917
  		reiserfs_write_lock_nested(sb, depth);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
  		journal->j_current_jl->j_state |= LIST_COMMIT_PENDING;
  		while ((atomic_read(&journal->j_wcount) > 0 ||
  			atomic_read(&journal->j_jlock)) &&
  		       journal->j_trans_id == trans_id) {
  			queue_log_writer(sb);
  		}
  		if (journal->j_trans_id != trans_id)
  			break;
  		if (bcount == journal->j_bcount)
  			break;
  		bcount = journal->j_bcount;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2929
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2930
  }
098297b27   Jeff Mahoney   reiserfs: cleanup...
2931
2932
2933
2934
2935
2936
  /*
   * join == true if you must join an existing transaction.
   * join == false if you can deal with waiting for others to finish
   *
   * this will block until the transaction is joinable.  send the number of
   * blocks you expect to use in nblocks.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2937
  */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2938
  static int do_journal_begin_r(struct reiserfs_transaction_handle *th,
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2939
  			      struct super_block *sb, unsigned long nblocks,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2940
2941
2942
  			      int join)
  {
  	time_t now = get_seconds();
600ed4167   Jeff Mahoney   reiserfs: audit t...
2943
  	unsigned int old_trans_id;
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2944
  	struct reiserfs_journal *journal = SB_JOURNAL(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2945
2946
2947
  	struct reiserfs_transaction_handle myth;
  	int sched_count = 0;
  	int retval;
278f6679f   Jeff Mahoney   reiserfs: locking...
2948
  	int depth;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2949

a9dd36435   Jeff Mahoney   reiserfs: rename ...
2950
  	reiserfs_check_lock_depth(sb, "journal_begin");
14a61442c   Eric Sesterhenn   BUG_ON conversion...
2951
  	BUG_ON(nblocks > journal->j_trans_max);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2952

a9dd36435   Jeff Mahoney   reiserfs: rename ...
2953
  	PROC_INFO_INC(sb, journal.journal_being);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2954
2955
  	/* set here for journal_join */
  	th->t_refcount = 1;
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2956
  	th->t_super = sb;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2957

cf776a7a4   Jeff Mahoney   reiserfs: cleanup...
2958
  relock:
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2959
  	lock_journal(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2960
  	if (join != JBEGIN_ABORT && reiserfs_is_journal_aborted(journal)) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2961
  		unlock_journal(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2962
2963
2964
2965
2966
2967
  		retval = journal->j_errno;
  		goto out_fail;
  	}
  	journal->j_bcount++;
  
  	if (test_bit(J_WRITERS_BLOCKED, &journal->j_state)) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2968
  		unlock_journal(sb);
278f6679f   Jeff Mahoney   reiserfs: locking...
2969
  		depth = reiserfs_write_unlock_nested(sb);
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2970
  		reiserfs_wait_on_write_block(sb);
278f6679f   Jeff Mahoney   reiserfs: locking...
2971
  		reiserfs_write_lock_nested(sb, depth);
a9dd36435   Jeff Mahoney   reiserfs: rename ...
2972
  		PROC_INFO_INC(sb, journal.journal_relock_writers);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2973
2974
2975
  		goto relock;
  	}
  	now = get_seconds();
098297b27   Jeff Mahoney   reiserfs: cleanup...
2976
2977
2978
2979
2980
  	/*
  	 * if there is no room in the journal OR
  	 * if this transaction is too old, and we weren't called joinable,
  	 * wait for it to finish before beginning we don't sleep if there
  	 * aren't other writers
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
  	 */
  
  	if ((!join && journal->j_must_wait > 0) ||
  	    (!join
  	     && (journal->j_len_alloc + nblocks + 2) >= journal->j_max_batch)
  	    || (!join && atomic_read(&journal->j_wcount) > 0
  		&& journal->j_trans_start_time > 0
  		&& (now - journal->j_trans_start_time) >
  		journal->j_max_trans_age) || (!join
  					      && atomic_read(&journal->j_jlock))
  	    || (!join && journal->j_cnode_free < (journal->j_trans_max * 3))) {
  
  		old_trans_id = journal->j_trans_id;
098297b27   Jeff Mahoney   reiserfs: cleanup...
2994
2995
  		/* allow others to finish this transaction */
  		unlock_journal(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2996
2997
2998
2999
3000
3001
3002
  
  		if (!join && (journal->j_len_alloc + nblocks + 2) >=
  		    journal->j_max_batch &&
  		    ((journal->j_len + nblocks + 2) * 100) <
  		    (journal->j_len_alloc * 75)) {
  			if (atomic_read(&journal->j_wcount) > 10) {
  				sched_count++;
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3003
  				queue_log_writer(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3004
3005
3006
  				goto relock;
  			}
  		}
098297b27   Jeff Mahoney   reiserfs: cleanup...
3007
3008
3009
  		/*
  		 * don't mess with joining the transaction if all we
  		 * have to do is wait for someone else to do a commit
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3010
3011
3012
3013
  		 */
  		if (atomic_read(&journal->j_jlock)) {
  			while (journal->j_trans_id == old_trans_id &&
  			       atomic_read(&journal->j_jlock)) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3014
  				queue_log_writer(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3015
3016
3017
  			}
  			goto relock;
  		}
b491dd176   Jeff Mahoney   reiserfs: cleanup...
3018
  		retval = journal_join(&myth, sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3019
3020
3021
3022
3023
  		if (retval)
  			goto out_fail;
  
  		/* someone might have ended the transaction while we joined */
  		if (old_trans_id != journal->j_trans_id) {
58d854265   Jeff Mahoney   reiserfs: cleanup...
3024
  			retval = do_journal_end(&myth, 0);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3025
  		} else {
58d854265   Jeff Mahoney   reiserfs: cleanup...
3026
  			retval = do_journal_end(&myth, COMMIT_NOW);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3027
3028
3029
3030
  		}
  
  		if (retval)
  			goto out_fail;
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3031
  		PROC_INFO_INC(sb, journal.journal_relock_wcount);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3032
3033
3034
3035
3036
3037
  		goto relock;
  	}
  	/* we are the first writer, set trans_id */
  	if (journal->j_trans_start_time == 0) {
  		journal->j_trans_start_time = get_seconds();
  	}
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
3038
  	atomic_inc(&journal->j_wcount);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3039
3040
3041
3042
  	journal->j_len_alloc += nblocks;
  	th->t_blocks_logged = 0;
  	th->t_blocks_allocated = nblocks;
  	th->t_trans_id = journal->j_trans_id;
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3043
  	unlock_journal(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3044
  	INIT_LIST_HEAD(&th->t_list);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3045
  	return 0;
cf776a7a4   Jeff Mahoney   reiserfs: cleanup...
3046
  out_fail:
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3047
  	memset(th, 0, sizeof(*th));
098297b27   Jeff Mahoney   reiserfs: cleanup...
3048
3049
  	/*
  	 * Re-set th->t_super, so we can properly keep track of how many
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3050
  	 * persistent transactions there are. We need to do this so if this
098297b27   Jeff Mahoney   reiserfs: cleanup...
3051
3052
  	 * call is part of a failed restart_transaction, we can free it later
  	 */
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3053
  	th->t_super = sb;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
  	return retval;
  }
  
  struct reiserfs_transaction_handle *reiserfs_persistent_transaction(struct
  								    super_block
  								    *s,
  								    int nblocks)
  {
  	int ret;
  	struct reiserfs_transaction_handle *th;
098297b27   Jeff Mahoney   reiserfs: cleanup...
3064
3065
3066
  	/*
  	 * if we're nesting into an existing transaction.  It will be
  	 * persistent on its own
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3067
3068
3069
3070
  	 */
  	if (reiserfs_transaction_running(s)) {
  		th = current->journal_info;
  		th->t_refcount++;
14a61442c   Eric Sesterhenn   BUG_ON conversion...
3071
  		BUG_ON(th->t_refcount < 2);
098297b27   Jeff Mahoney   reiserfs: cleanup...
3072

bd4c625c0   Linus Torvalds   reiserfs: run scr...
3073
3074
  		return th;
  	}
d739b42b8   Pekka Enberg   [PATCH] reiserfs:...
3075
  	th = kmalloc(sizeof(struct reiserfs_transaction_handle), GFP_NOFS);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3076
3077
3078
3079
  	if (!th)
  		return NULL;
  	ret = journal_begin(th, s, nblocks);
  	if (ret) {
d739b42b8   Pekka Enberg   [PATCH] reiserfs:...
3080
  		kfree(th);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
  		return NULL;
  	}
  
  	SB_JOURNAL(s)->j_persistent_trans++;
  	return th;
  }
  
  int reiserfs_end_persistent_transaction(struct reiserfs_transaction_handle *th)
  {
  	struct super_block *s = th->t_super;
  	int ret = 0;
  	if (th->t_trans_id)
58d854265   Jeff Mahoney   reiserfs: cleanup...
3093
  		ret = journal_end(th);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3094
3095
3096
3097
  	else
  		ret = -EIO;
  	if (th->t_refcount == 0) {
  		SB_JOURNAL(s)->j_persistent_trans--;
d739b42b8   Pekka Enberg   [PATCH] reiserfs:...
3098
  		kfree(th);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3099
3100
3101
3102
3103
  	}
  	return ret;
  }
  
  static int journal_join(struct reiserfs_transaction_handle *th,
b491dd176   Jeff Mahoney   reiserfs: cleanup...
3104
  			struct super_block *sb)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3105
3106
  {
  	struct reiserfs_transaction_handle *cur_th = current->journal_info;
098297b27   Jeff Mahoney   reiserfs: cleanup...
3107
3108
3109
  	/*
  	 * this keeps do_journal_end from NULLing out the
  	 * current->journal_info pointer
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3110
3111
  	 */
  	th->t_handle_save = cur_th;
14a61442c   Eric Sesterhenn   BUG_ON conversion...
3112
  	BUG_ON(cur_th && cur_th->t_refcount > 1);
b491dd176   Jeff Mahoney   reiserfs: cleanup...
3113
  	return do_journal_begin_r(th, sb, 1, JBEGIN_JOIN);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3114
3115
3116
  }
  
  int journal_join_abort(struct reiserfs_transaction_handle *th,
b491dd176   Jeff Mahoney   reiserfs: cleanup...
3117
  		       struct super_block *sb)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3118
3119
  {
  	struct reiserfs_transaction_handle *cur_th = current->journal_info;
098297b27   Jeff Mahoney   reiserfs: cleanup...
3120
3121
3122
  	/*
  	 * this keeps do_journal_end from NULLing out the
  	 * current->journal_info pointer
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3123
3124
  	 */
  	th->t_handle_save = cur_th;
14a61442c   Eric Sesterhenn   BUG_ON conversion...
3125
  	BUG_ON(cur_th && cur_th->t_refcount > 1);
b491dd176   Jeff Mahoney   reiserfs: cleanup...
3126
  	return do_journal_begin_r(th, sb, 1, JBEGIN_ABORT);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3127
3128
3129
  }
  
  int journal_begin(struct reiserfs_transaction_handle *th,
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3130
  		  struct super_block *sb, unsigned long nblocks)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3131
3132
3133
3134
3135
3136
3137
  {
  	struct reiserfs_transaction_handle *cur_th = current->journal_info;
  	int ret;
  
  	th->t_handle_save = NULL;
  	if (cur_th) {
  		/* we are nesting into the current transaction */
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3138
  		if (cur_th->t_super == sb) {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3139
3140
3141
3142
  			BUG_ON(!cur_th->t_refcount);
  			cur_th->t_refcount++;
  			memcpy(th, cur_th, sizeof(*th));
  			if (th->t_refcount <= 1)
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3143
  				reiserfs_warning(sb, "reiserfs-2005",
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
3144
3145
  						 "BAD: refcount <= 1, but "
  						 "journal_info != 0");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3146
3147
  			return 0;
  		} else {
098297b27   Jeff Mahoney   reiserfs: cleanup...
3148
3149
3150
3151
  			/*
  			 * we've ended up with a handle from a different
  			 * filesystem.  save it and restore on journal_end.
  			 * This should never really happen...
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3152
  			 */
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3153
  			reiserfs_warning(sb, "clm-2100",
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
3154
  					 "nesting info a different FS");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3155
3156
3157
  			th->t_handle_save = current->journal_info;
  			current->journal_info = th;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3158
  	} else {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3159
3160
  		current->journal_info = th;
  	}
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3161
  	ret = do_journal_begin_r(th, sb, nblocks, JBEGIN_REG);
14a61442c   Eric Sesterhenn   BUG_ON conversion...
3162
  	BUG_ON(current->journal_info != th);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3163

098297b27   Jeff Mahoney   reiserfs: cleanup...
3164
3165
3166
3167
  	/*
  	 * I guess this boils down to being the reciprocal of clm-2100 above.
  	 * If do_journal_begin_r fails, we need to put it back, since
  	 * journal_end won't be called to do it. */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3168
3169
3170
3171
  	if (ret)
  		current->journal_info = th->t_handle_save;
  	else
  		BUG_ON(!th->t_refcount);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3172

bd4c625c0   Linus Torvalds   reiserfs: run scr...
3173
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3174
3175
3176
  }
  
  /*
098297b27   Jeff Mahoney   reiserfs: cleanup...
3177
3178
3179
3180
3181
3182
3183
3184
3185
   * puts bh into the current transaction.  If it was already there, reorders
   * removes the old pointers from the hash, and puts new ones in (to make
   * sure replay happen in the right order).
   *
   * if it was dirty, cleans and files onto the clean list.  I can't let it
   * be dirty again until the transaction is committed.
   *
   * if j_len, is bigger than j_len_alloc, it pushes j_len_alloc to 10 + j_len.
   */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3186
  int journal_mark_dirty(struct reiserfs_transaction_handle *th,
09f1b80ba   Jeff Mahoney   reiserfs: cleanup...
3187
  		       struct buffer_head *bh)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3188
  {
09f1b80ba   Jeff Mahoney   reiserfs: cleanup...
3189
  	struct super_block *sb = th->t_super;
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3190
  	struct reiserfs_journal *journal = SB_JOURNAL(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3191
3192
3193
3194
  	struct reiserfs_journal_cnode *cn = NULL;
  	int count_already_incd = 0;
  	int prepared = 0;
  	BUG_ON(!th->t_trans_id);
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3195
  	PROC_INFO_INC(sb, journal.mark_dirty);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3196
  	if (th->t_trans_id != journal->j_trans_id) {
c3a9c2109   Jeff Mahoney   reiserfs: rework ...
3197
3198
  		reiserfs_panic(th->t_super, "journal-1577",
  			       "handle trans id %ld != current trans id %ld",
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3199
3200
  			       th->t_trans_id, journal->j_trans_id);
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3201
3202
3203
3204
  	prepared = test_clear_buffer_journal_prepared(bh);
  	clear_buffer_journal_restore_dirty(bh);
  	/* already in this transaction, we are done */
  	if (buffer_journaled(bh)) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3205
  		PROC_INFO_INC(sb, journal.mark_dirty_already);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3206
3207
  		return 0;
  	}
098297b27   Jeff Mahoney   reiserfs: cleanup...
3208
3209
3210
3211
  	/*
  	 * this must be turned into a panic instead of a warning.  We can't
  	 * allow a dirty or journal_dirty or locked buffer to be logged, as
  	 * some changes could get to disk too early.  NOT GOOD.
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3212
3213
  	 */
  	if (!prepared || buffer_dirty(bh)) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3214
  		reiserfs_warning(sb, "journal-1777",
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
3215
  				 "buffer %llu bad state "
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3216
3217
3218
3219
3220
3221
3222
  				 "%cPREPARED %cLOCKED %cDIRTY %cJDIRTY_WAIT",
  				 (unsigned long long)bh->b_blocknr,
  				 prepared ? ' ' : '!',
  				 buffer_locked(bh) ? ' ' : '!',
  				 buffer_dirty(bh) ? ' ' : '!',
  				 buffer_journal_dirty(bh) ? ' ' : '!');
  	}
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
3223
  	if (atomic_read(&journal->j_wcount) <= 0) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3224
  		reiserfs_warning(sb, "journal-1409",
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
3225
  				 "returning because j_wcount was %d",
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
3226
  				 atomic_read(&journal->j_wcount));
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3227
3228
  		return 1;
  	}
098297b27   Jeff Mahoney   reiserfs: cleanup...
3229
3230
3231
3232
  	/*
  	 * this error means I've screwed up, and we've overflowed
  	 * the transaction.  Nothing can be done here, except make the
  	 * FS readonly or panic.
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3233
3234
  	 */
  	if (journal->j_len >= journal->j_trans_max) {
c3a9c2109   Jeff Mahoney   reiserfs: rework ...
3235
3236
  		reiserfs_panic(th->t_super, "journal-1413",
  			       "j_len (%lu) is too big",
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3237
3238
3239
3240
3241
  			       journal->j_len);
  	}
  
  	if (buffer_journal_dirty(bh)) {
  		count_already_incd = 1;
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3242
  		PROC_INFO_INC(sb, journal.mark_dirty_notjournal);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
  		clear_buffer_journal_dirty(bh);
  	}
  
  	if (journal->j_len > journal->j_len_alloc) {
  		journal->j_len_alloc = journal->j_len + JOURNAL_PER_BALANCE_CNT;
  	}
  
  	set_buffer_journaled(bh);
  
  	/* now put this guy on the end */
  	if (!cn) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3254
  		cn = get_cnode(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3255
  		if (!cn) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3256
  			reiserfs_panic(sb, "journal-4", "get_cnode failed!");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
  		}
  
  		if (th->t_blocks_logged == th->t_blocks_allocated) {
  			th->t_blocks_allocated += JOURNAL_PER_BALANCE_CNT;
  			journal->j_len_alloc += JOURNAL_PER_BALANCE_CNT;
  		}
  		th->t_blocks_logged++;
  		journal->j_len++;
  
  		cn->bh = bh;
  		cn->blocknr = bh->b_blocknr;
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3268
  		cn->sb = sb;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
  		cn->jlist = NULL;
  		insert_journal_hash(journal->j_hash_table, cn);
  		if (!count_already_incd) {
  			get_bh(bh);
  		}
  	}
  	cn->next = NULL;
  	cn->prev = journal->j_last;
  	cn->bh = bh;
  	if (journal->j_last) {
  		journal->j_last->next = cn;
  		journal->j_last = cn;
  	} else {
  		journal->j_first = cn;
  		journal->j_last = cn;
  	}
033369d1a   Artem Bityutskiy   reiserfs: get rid...
3285
  	reiserfs_schedule_old_flush(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3286
3287
  	return 0;
  }
58d854265   Jeff Mahoney   reiserfs: cleanup...
3288
  int journal_end(struct reiserfs_transaction_handle *th)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3289
  {
58d854265   Jeff Mahoney   reiserfs: cleanup...
3290
  	struct super_block *sb = th->t_super;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3291
  	if (!current->journal_info && th->t_refcount > 1)
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3292
  		reiserfs_warning(sb, "REISER-NESTING",
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
3293
  				 "th NULL, refcount %d", th->t_refcount);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
  
  	if (!th->t_trans_id) {
  		WARN_ON(1);
  		return -EIO;
  	}
  
  	th->t_refcount--;
  	if (th->t_refcount > 0) {
  		struct reiserfs_transaction_handle *cur_th =
  		    current->journal_info;
098297b27   Jeff Mahoney   reiserfs: cleanup...
3304
3305
3306
  		/*
  		 * we aren't allowed to close a nested transaction on a
  		 * different filesystem from the one in the task struct
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3307
  		 */
14a61442c   Eric Sesterhenn   BUG_ON conversion...
3308
  		BUG_ON(cur_th->t_super != th->t_super);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3309
3310
3311
3312
3313
3314
3315
  
  		if (th != cur_th) {
  			memcpy(current->journal_info, th, sizeof(*th));
  			th->t_trans_id = 0;
  		}
  		return 0;
  	} else {
58d854265   Jeff Mahoney   reiserfs: cleanup...
3316
  		return do_journal_end(th, 0);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3317
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3318
  }
098297b27   Jeff Mahoney   reiserfs: cleanup...
3319
3320
3321
3322
3323
3324
3325
3326
  /*
   * removes from the current transaction, relsing and descrementing any counters.
   * also files the removed buffer directly onto the clean list
   *
   * called by journal_mark_freed when a block has been deleted
   *
   * returns 1 if it cleaned and relsed the buffer. 0 otherwise
   */
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3327
  static int remove_from_transaction(struct super_block *sb,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3328
3329
3330
3331
  				   b_blocknr_t blocknr, int already_cleaned)
  {
  	struct buffer_head *bh;
  	struct reiserfs_journal_cnode *cn;
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3332
  	struct reiserfs_journal *journal = SB_JOURNAL(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3333
  	int ret = 0;
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3334
  	cn = get_journal_hash_dev(sb, journal->j_hash_table, blocknr);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
  	if (!cn || !cn->bh) {
  		return ret;
  	}
  	bh = cn->bh;
  	if (cn->prev) {
  		cn->prev->next = cn->next;
  	}
  	if (cn->next) {
  		cn->next->prev = cn->prev;
  	}
  	if (cn == journal->j_first) {
  		journal->j_first = cn->next;
  	}
  	if (cn == journal->j_last) {
  		journal->j_last = cn->prev;
  	}
  	if (bh)
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3352
  		remove_journal_hash(sb, journal->j_hash_table, NULL,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3353
3354
3355
3356
3357
3358
3359
3360
  				    bh->b_blocknr, 0);
  	clear_buffer_journaled(bh);	/* don't log this one */
  
  	if (!already_cleaned) {
  		clear_buffer_journal_dirty(bh);
  		clear_buffer_dirty(bh);
  		clear_buffer_journal_test(bh);
  		put_bh(bh);
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
3361
  		if (atomic_read(&bh->b_count) < 0) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3362
  			reiserfs_warning(sb, "journal-1752",
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
3363
  					 "b_count < 0");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3364
3365
3366
3367
3368
  		}
  		ret = 1;
  	}
  	journal->j_len--;
  	journal->j_len_alloc--;
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3369
  	free_cnode(sb, cn);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3370
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3371
3372
3373
  }
  
  /*
098297b27   Jeff Mahoney   reiserfs: cleanup...
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
   * for any cnode in a journal list, it can only be dirtied of all the
   * transactions that include it are committed to disk.
   * this checks through each transaction, and returns 1 if you are allowed
   * to dirty, and 0 if you aren't
   *
   * it is called by dirty_journal_list, which is called after
   * flush_commit_list has gotten all the log blocks for a given
   * transaction on disk
   *
   */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3384
3385
3386
3387
3388
3389
  static int can_dirty(struct reiserfs_journal_cnode *cn)
  {
  	struct super_block *sb = cn->sb;
  	b_blocknr_t blocknr = cn->blocknr;
  	struct reiserfs_journal_cnode *cur = cn->hprev;
  	int can_dirty = 1;
098297b27   Jeff Mahoney   reiserfs: cleanup...
3390
3391
3392
3393
  	/*
  	 * first test hprev.  These are all newer than cn, so any node here
  	 * with the same block number and dev means this node can't be sent
  	 * to disk right now.
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3394
3395
3396
3397
3398
3399
3400
3401
  	 */
  	while (cur && can_dirty) {
  		if (cur->jlist && cur->bh && cur->blocknr && cur->sb == sb &&
  		    cur->blocknr == blocknr) {
  			can_dirty = 0;
  		}
  		cur = cur->hprev;
  	}
098297b27   Jeff Mahoney   reiserfs: cleanup...
3402
3403
3404
  	/*
  	 * then test hnext.  These are all older than cn.  As long as they
  	 * are committed to the log, it is safe to write cn to disk
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3405
3406
3407
3408
  	 */
  	cur = cn->hnext;
  	while (cur && can_dirty) {
  		if (cur->jlist && cur->jlist->j_len > 0 &&
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
3409
  		    atomic_read(&cur->jlist->j_commit_left) > 0 && cur->bh &&
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3410
3411
3412
3413
3414
3415
  		    cur->blocknr && cur->sb == sb && cur->blocknr == blocknr) {
  			can_dirty = 0;
  		}
  		cur = cur->hnext;
  	}
  	return can_dirty;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3416
  }
098297b27   Jeff Mahoney   reiserfs: cleanup...
3417
3418
3419
3420
  /*
   * syncs the commit blocks, but does not force the real buffers to disk
   * will wait until the current transaction is done/committed before returning
   */
58d854265   Jeff Mahoney   reiserfs: cleanup...
3421
  int journal_end_sync(struct reiserfs_transaction_handle *th)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3422
  {
58d854265   Jeff Mahoney   reiserfs: cleanup...
3423
  	struct super_block *sb = th->t_super;
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3424
  	struct reiserfs_journal *journal = SB_JOURNAL(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3425

bd4c625c0   Linus Torvalds   reiserfs: run scr...
3426
3427
  	BUG_ON(!th->t_trans_id);
  	/* you can sync while nested, very, very bad */
14a61442c   Eric Sesterhenn   BUG_ON conversion...
3428
  	BUG_ON(th->t_refcount > 1);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3429
  	if (journal->j_len == 0) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3430
  		reiserfs_prepare_for_journal(sb, SB_BUFFER_WITH_SB(sb),
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3431
  					     1);
09f1b80ba   Jeff Mahoney   reiserfs: cleanup...
3432
  		journal_mark_dirty(th, SB_BUFFER_WITH_SB(sb));
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3433
  	}
58d854265   Jeff Mahoney   reiserfs: cleanup...
3434
  	return do_journal_end(th, COMMIT_NOW | WAIT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3435
  }
098297b27   Jeff Mahoney   reiserfs: cleanup...
3436
  /* writeback the pending async commits to disk */
c4028958b   David Howells   WorkStruct: make ...
3437
  static void flush_async_commits(struct work_struct *work)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3438
  {
c4028958b   David Howells   WorkStruct: make ...
3439
3440
  	struct reiserfs_journal *journal =
  		container_of(work, struct reiserfs_journal, j_work.work);
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3441
  	struct super_block *sb = journal->j_work_sb;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3442
3443
  	struct reiserfs_journal_list *jl;
  	struct list_head *entry;
8ebc42323   Frederic Weisbecker   reiserfs: kill-th...
3444
  	reiserfs_write_lock(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3445
3446
3447
3448
  	if (!list_empty(&journal->j_journal_list)) {
  		/* last entry is the youngest, commit it and you get everything */
  		entry = journal->j_journal_list.prev;
  		jl = JOURNAL_LIST_ENTRY(entry);
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3449
  		flush_commit_list(sb, jl, 1);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3450
  	}
8ebc42323   Frederic Weisbecker   reiserfs: kill-th...
3451
  	reiserfs_write_unlock(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3452
3453
3454
  }
  
  /*
098297b27   Jeff Mahoney   reiserfs: cleanup...
3455
3456
3457
   * flushes any old transactions to disk
   * ends the current transaction if it is too old
   */
25729b0e9   Artem Bityutskiy   reiserfs: clean-u...
3458
  void reiserfs_flush_old_commits(struct super_block *sb)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3459
3460
3461
  {
  	time_t now;
  	struct reiserfs_transaction_handle th;
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3462
  	struct reiserfs_journal *journal = SB_JOURNAL(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3463
3464
  
  	now = get_seconds();
098297b27   Jeff Mahoney   reiserfs: cleanup...
3465
3466
  	/*
  	 * safety check so we don't flush while we are replaying the log during
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3467
3468
  	 * mount
  	 */
25729b0e9   Artem Bityutskiy   reiserfs: clean-u...
3469
3470
  	if (list_empty(&journal->j_journal_list))
  		return;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3471

098297b27   Jeff Mahoney   reiserfs: cleanup...
3472
3473
  	/*
  	 * check the current transaction.  If there are no writers, and it is
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3474
3475
3476
3477
3478
3479
  	 * too old, finish it, and force the commit blocks to disk
  	 */
  	if (atomic_read(&journal->j_wcount) <= 0 &&
  	    journal->j_trans_start_time > 0 &&
  	    journal->j_len > 0 &&
  	    (now - journal->j_trans_start_time) > journal->j_max_trans_age) {
b491dd176   Jeff Mahoney   reiserfs: cleanup...
3480
  		if (!journal_join(&th, sb)) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3481
3482
  			reiserfs_prepare_for_journal(sb,
  						     SB_BUFFER_WITH_SB(sb),
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3483
  						     1);
09f1b80ba   Jeff Mahoney   reiserfs: cleanup...
3484
  			journal_mark_dirty(&th, SB_BUFFER_WITH_SB(sb));
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3485

098297b27   Jeff Mahoney   reiserfs: cleanup...
3486
3487
3488
3489
  			/*
  			 * we're only being called from kreiserfsd, it makes
  			 * no sense to do an async commit so that kreiserfsd
  			 * can do it later
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3490
  			 */
58d854265   Jeff Mahoney   reiserfs: cleanup...
3491
  			do_journal_end(&th, COMMIT_NOW | WAIT);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3492
3493
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3494
3495
3496
  }
  
  /*
098297b27   Jeff Mahoney   reiserfs: cleanup...
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
   * returns 0 if do_journal_end should return right away, returns 1 if
   * do_journal_end should finish the commit
   *
   * if the current transaction is too old, but still has writers, this will
   * wait on j_join_wait until all the writers are done.  By the time it
   * wakes up, the transaction it was called has already ended, so it just
   * flushes the commit list and returns 0.
   *
   * Won't batch when flush or commit_now is set.  Also won't batch when
   * others are waiting on j_join_wait.
   *
   * Note, we can't allow the journal_end to proceed while there are still
   * writers in the log.
   */
58d854265   Jeff Mahoney   reiserfs: cleanup...
3511
  static int check_journal_end(struct reiserfs_transaction_handle *th, int flags)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3512
3513
3514
3515
3516
3517
3518
  {
  
  	time_t now;
  	int flush = flags & FLUSH_ALL;
  	int commit_now = flags & COMMIT_NOW;
  	int wait_on_commit = flags & WAIT;
  	struct reiserfs_journal_list *jl;
58d854265   Jeff Mahoney   reiserfs: cleanup...
3519
  	struct super_block *sb = th->t_super;
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3520
  	struct reiserfs_journal *journal = SB_JOURNAL(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3521
3522
3523
3524
  
  	BUG_ON(!th->t_trans_id);
  
  	if (th->t_trans_id != journal->j_trans_id) {
c3a9c2109   Jeff Mahoney   reiserfs: rework ...
3525
3526
  		reiserfs_panic(th->t_super, "journal-1577",
  			       "handle trans id %ld != current trans id %ld",
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3527
3528
3529
3530
  			       th->t_trans_id, journal->j_trans_id);
  	}
  
  	journal->j_len_alloc -= (th->t_blocks_allocated - th->t_blocks_logged);
098297b27   Jeff Mahoney   reiserfs: cleanup...
3531
  	/* <= 0 is allowed.  unmounting might not call begin */
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
3532
3533
  	if (atomic_read(&journal->j_wcount) > 0)
  		atomic_dec(&journal->j_wcount);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3534

098297b27   Jeff Mahoney   reiserfs: cleanup...
3535
3536
3537
3538
3539
  	/*
  	 * BUG, deal with case where j_len is 0, but people previously
  	 * freed blocks need to be released will be dealt with by next
  	 * transaction that actually writes something, but should be taken
  	 * care of in this trans
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3540
  	 */
14a61442c   Eric Sesterhenn   BUG_ON conversion...
3541
  	BUG_ON(journal->j_len == 0);
098297b27   Jeff Mahoney   reiserfs: cleanup...
3542
3543
3544
3545
3546
3547
3548
  	/*
  	 * if wcount > 0, and we are called to with flush or commit_now,
  	 * we wait on j_join_wait.  We will wake up when the last writer has
  	 * finished the transaction, and started it on its way to the disk.
  	 * Then, we flush the commit or journal list, and just return 0
  	 * because the rest of journal end was already done for this
  	 * transaction.
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3549
  	 */
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
3550
  	if (atomic_read(&journal->j_wcount) > 0) {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3551
3552
3553
3554
3555
3556
3557
  		if (flush || commit_now) {
  			unsigned trans_id;
  
  			jl = journal->j_current_jl;
  			trans_id = jl->j_trans_id;
  			if (wait_on_commit)
  				jl->j_state |= LIST_COMMIT_PENDING;
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
3558
  			atomic_set(&journal->j_jlock, 1);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3559
3560
3561
  			if (flush) {
  				journal->j_next_full_flush = 1;
  			}
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3562
  			unlock_journal(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3563

098297b27   Jeff Mahoney   reiserfs: cleanup...
3564
3565
3566
3567
  			/*
  			 * sleep while the current transaction is
  			 * still j_jlocked
  			 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3568
3569
  			while (journal->j_trans_id == trans_id) {
  				if (atomic_read(&journal->j_jlock)) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3570
  					queue_log_writer(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3571
  				} else {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3572
  					lock_journal(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3573
  					if (journal->j_trans_id == trans_id) {
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
3574
  						atomic_set(&journal->j_jlock,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3575
3576
  							   1);
  					}
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3577
  					unlock_journal(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3578
3579
  				}
  			}
14a61442c   Eric Sesterhenn   BUG_ON conversion...
3580
  			BUG_ON(journal->j_trans_id == trans_id);
098297b27   Jeff Mahoney   reiserfs: cleanup...
3581

bd4c625c0   Linus Torvalds   reiserfs: run scr...
3582
  			if (commit_now
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3583
  			    && journal_list_still_alive(sb, trans_id)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3584
  			    && wait_on_commit) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3585
  				flush_commit_list(sb, jl, 1);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3586
3587
3588
  			}
  			return 0;
  		}
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3589
  		unlock_journal(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
  		return 0;
  	}
  
  	/* deal with old transactions where we are the last writers */
  	now = get_seconds();
  	if ((now - journal->j_trans_start_time) > journal->j_max_trans_age) {
  		commit_now = 1;
  		journal->j_next_async_flush = 1;
  	}
  	/* don't batch when someone is waiting on j_join_wait */
  	/* don't batch when syncing the commit or flushing the whole trans */
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
3601
  	if (!(journal->j_must_wait > 0) && !(atomic_read(&journal->j_jlock))
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3602
3603
3604
3605
  	    && !flush && !commit_now && (journal->j_len < journal->j_max_batch)
  	    && journal->j_len_alloc < journal->j_max_batch
  	    && journal->j_cnode_free > (journal->j_trans_max * 3)) {
  		journal->j_bcount++;
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3606
  		unlock_journal(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3607
3608
  		return 0;
  	}
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3609
3610
  	if (journal->j_start > SB_ONDISK_JOURNAL_SIZE(sb)) {
  		reiserfs_panic(sb, "journal-003",
c3a9c2109   Jeff Mahoney   reiserfs: rework ...
3611
  			       "j_start (%ld) is too high",
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3612
3613
3614
  			       journal->j_start);
  	}
  	return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3615
3616
3617
  }
  
  /*
098297b27   Jeff Mahoney   reiserfs: cleanup...
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
   * Does all the work that makes deleting blocks safe.
   * when deleting a block mark BH_JNew, just remove it from the current
   * transaction, clean it's buffer_head and move on.
   *
   * otherwise:
   * set a bit for the block in the journal bitmap.  That will prevent it from
   * being allocated for unformatted nodes before this transaction has finished.
   *
   * mark any cnodes for this block as BLOCK_FREED, and clear their bh pointers.
   * That will prevent any old transactions with this block from trying to flush
   * to the real location.  Since we aren't removing the cnode from the
   * journal_list_hash, *the block can't be reallocated yet.
   *
   * Then remove it from the current transaction, decrementing any counters and
   * filing it on the clean list.
   */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3634
  int journal_mark_freed(struct reiserfs_transaction_handle *th,
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3635
  		       struct super_block *sb, b_blocknr_t blocknr)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3636
  {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3637
  	struct reiserfs_journal *journal = SB_JOURNAL(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3638
3639
3640
3641
3642
  	struct reiserfs_journal_cnode *cn = NULL;
  	struct buffer_head *bh = NULL;
  	struct reiserfs_list_bitmap *jb = NULL;
  	int cleaned = 0;
  	BUG_ON(!th->t_trans_id);
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3643
  	cn = get_journal_hash_dev(sb, journal->j_hash_table, blocknr);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3644
3645
3646
3647
3648
3649
3650
3651
3652
  	if (cn && cn->bh) {
  		bh = cn->bh;
  		get_bh(bh);
  	}
  	/* if it is journal new, we just remove it from this transaction */
  	if (bh && buffer_journal_new(bh)) {
  		clear_buffer_journal_new(bh);
  		clear_prepared_bits(bh);
  		reiserfs_clean_and_file_buffer(bh);
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3653
  		cleaned = remove_from_transaction(sb, blocknr, cleaned);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3654
  	} else {
098297b27   Jeff Mahoney   reiserfs: cleanup...
3655
3656
3657
3658
  		/*
  		 * set the bit for this block in the journal bitmap
  		 * for this transaction
  		 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3659
3660
  		jb = journal->j_current_jl->j_list_bitmap;
  		if (!jb) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3661
  			reiserfs_panic(sb, "journal-1702",
c3a9c2109   Jeff Mahoney   reiserfs: rework ...
3662
  				       "journal_list_bitmap is NULL");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3663
  		}
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3664
  		set_bit_in_list_bitmap(sb, blocknr, jb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3665
3666
3667
3668
3669
3670
3671
  
  		/* Note, the entire while loop is not allowed to schedule.  */
  
  		if (bh) {
  			clear_prepared_bits(bh);
  			reiserfs_clean_and_file_buffer(bh);
  		}
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3672
  		cleaned = remove_from_transaction(sb, blocknr, cleaned);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3673

098297b27   Jeff Mahoney   reiserfs: cleanup...
3674
3675
3676
3677
  		/*
  		 * find all older transactions with this block,
  		 * make sure they don't try to write it out
  		 */
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3678
  		cn = get_journal_hash_dev(sb, journal->j_list_hash_table,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3679
3680
  					  blocknr);
  		while (cn) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3681
  			if (sb == cn->sb && blocknr == cn->blocknr) {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3682
3683
  				set_bit(BLOCK_FREED, &cn->state);
  				if (cn->bh) {
098297b27   Jeff Mahoney   reiserfs: cleanup...
3684
3685
3686
3687
3688
  					/*
  					 * remove_from_transaction will brelse
  					 * the buffer if it was in the current
  					 * trans
  					 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3689
  					if (!cleaned) {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3690
3691
3692
3693
3694
3695
3696
3697
  						clear_buffer_journal_dirty(cn->
  									   bh);
  						clear_buffer_dirty(cn->bh);
  						clear_buffer_journal_test(cn->
  									  bh);
  						cleaned = 1;
  						put_bh(cn->bh);
  						if (atomic_read
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
3698
  						    (&cn->bh->b_count) < 0) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3699
  							reiserfs_warning(sb,
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
3700
3701
  								 "journal-2138",
  								 "cn->bh->b_count < 0");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3702
3703
  						}
  					}
098297b27   Jeff Mahoney   reiserfs: cleanup...
3704
3705
3706
3707
3708
  					/*
  					 * since we are clearing the bh,
  					 * we MUST dec nonzerolen
  					 */
  					if (cn->jlist) {
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
3709
3710
  						atomic_dec(&cn->jlist->
  							   j_nonzerolen);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3711
3712
3713
3714
3715
3716
3717
  					}
  					cn->bh = NULL;
  				}
  			}
  			cn = cn->hnext;
  		}
  	}
398c95bdf   Chris Mason   try to reap reise...
3718
3719
  	if (bh)
  		release_buffer_page(bh); /* get_hash grabs the buffer */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3720
3721
3722
3723
3724
3725
3726
3727
  	return 0;
  }
  
  void reiserfs_update_inode_transaction(struct inode *inode)
  {
  	struct reiserfs_journal *journal = SB_JOURNAL(inode->i_sb);
  	REISERFS_I(inode)->i_jl = journal->j_current_jl;
  	REISERFS_I(inode)->i_trans_id = journal->j_trans_id;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3728
3729
3730
3731
3732
3733
3734
  }
  
  /*
   * returns -1 on error, 0 if no commits/barriers were done and 1
   * if a transaction was actually committed and the barrier was done
   */
  static int __commit_trans_jl(struct inode *inode, unsigned long id,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3735
  			     struct reiserfs_journal_list *jl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3736
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3737
3738
3739
3740
  	struct reiserfs_transaction_handle th;
  	struct super_block *sb = inode->i_sb;
  	struct reiserfs_journal *journal = SB_JOURNAL(sb);
  	int ret = 0;
098297b27   Jeff Mahoney   reiserfs: cleanup...
3741
3742
3743
3744
  	/*
  	 * is it from the current transaction,
  	 * or from an unknown transaction?
  	 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3745
3746
  	if (id == journal->j_trans_id) {
  		jl = journal->j_current_jl;
098297b27   Jeff Mahoney   reiserfs: cleanup...
3747
3748
3749
3750
  		/*
  		 * try to let other writers come in and
  		 * grow this transaction
  		 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3751
3752
3753
3754
  		let_transaction_grow(sb, id);
  		if (journal->j_trans_id != id) {
  			goto flush_commit_only;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3755

bd4c625c0   Linus Torvalds   reiserfs: run scr...
3756
3757
3758
3759
3760
3761
3762
3763
  		ret = journal_begin(&th, sb, 1);
  		if (ret)
  			return ret;
  
  		/* someone might have ended this transaction while we joined */
  		if (journal->j_trans_id != id) {
  			reiserfs_prepare_for_journal(sb, SB_BUFFER_WITH_SB(sb),
  						     1);
09f1b80ba   Jeff Mahoney   reiserfs: cleanup...
3764
  			journal_mark_dirty(&th, SB_BUFFER_WITH_SB(sb));
58d854265   Jeff Mahoney   reiserfs: cleanup...
3765
  			ret = journal_end(&th);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3766
3767
  			goto flush_commit_only;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3768

58d854265   Jeff Mahoney   reiserfs: cleanup...
3769
  		ret = journal_end_sync(&th);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3770
3771
  		if (!ret)
  			ret = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3772

bd4c625c0   Linus Torvalds   reiserfs: run scr...
3773
  	} else {
098297b27   Jeff Mahoney   reiserfs: cleanup...
3774
3775
  		/*
  		 * this gets tricky, we have to make sure the journal list in
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3776
3777
3778
  		 * the inode still exists.  We know the list is still around
  		 * if we've got a larger transaction id than the oldest list
  		 */
cf776a7a4   Jeff Mahoney   reiserfs: cleanup...
3779
  flush_commit_only:
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
  		if (journal_list_still_alive(inode->i_sb, id)) {
  			/*
  			 * we only set ret to 1 when we know for sure
  			 * the barrier hasn't been started yet on the commit
  			 * block.
  			 */
  			if (atomic_read(&jl->j_commit_left) > 1)
  				ret = 1;
  			flush_commit_list(sb, jl, 1);
  			if (journal->j_errno)
  				ret = journal->j_errno;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3792
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3793
3794
3795
  	/* otherwise the list is gone, and long since committed */
  	return ret;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3796

bd4c625c0   Linus Torvalds   reiserfs: run scr...
3797
3798
  int reiserfs_commit_for_inode(struct inode *inode)
  {
600ed4167   Jeff Mahoney   reiserfs: audit t...
3799
  	unsigned int id = REISERFS_I(inode)->i_trans_id;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3800
  	struct reiserfs_journal_list *jl = REISERFS_I(inode)->i_jl;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3801

098297b27   Jeff Mahoney   reiserfs: cleanup...
3802
3803
  	/*
  	 * for the whole inode, assume unset id means it was
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3804
  	 * changed in the current transaction.  More conservative
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3805
  	 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3806
3807
3808
3809
3810
3811
3812
3813
  	if (!id || !jl) {
  		reiserfs_update_inode_transaction(inode);
  		id = REISERFS_I(inode)->i_trans_id;
  		/* jl will be updated in __commit_trans_jl */
  	}
  
  	return __commit_trans_jl(inode, id, jl);
  }
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3814
  void reiserfs_restore_prepared_buffer(struct super_block *sb,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3815
3816
  				      struct buffer_head *bh)
  {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3817
3818
  	struct reiserfs_journal *journal = SB_JOURNAL(sb);
  	PROC_INFO_INC(sb, journal.restore_prepared);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3819
3820
3821
3822
3823
3824
  	if (!bh) {
  		return;
  	}
  	if (test_clear_buffer_journal_restore_dirty(bh) &&
  	    buffer_journal_dirty(bh)) {
  		struct reiserfs_journal_cnode *cn;
278f6679f   Jeff Mahoney   reiserfs: locking...
3825
  		reiserfs_write_lock(sb);
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3826
  		cn = get_journal_hash_dev(sb,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3827
3828
3829
3830
3831
3832
  					  journal->j_list_hash_table,
  					  bh->b_blocknr);
  		if (cn && can_dirty(cn)) {
  			set_buffer_journal_test(bh);
  			mark_buffer_dirty(bh);
  		}
278f6679f   Jeff Mahoney   reiserfs: locking...
3833
  		reiserfs_write_unlock(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3834
3835
3836
3837
3838
  	}
  	clear_buffer_journal_prepared(bh);
  }
  
  extern struct tree_balance *cur_tb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3839
  /*
098297b27   Jeff Mahoney   reiserfs: cleanup...
3840
3841
3842
3843
3844
   * before we can change a metadata block, we have to make sure it won't
   * be written to disk while we are altering it.  So, we must:
   * clean it
   * wait on it.
   */
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3845
  int reiserfs_prepare_for_journal(struct super_block *sb,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3846
3847
  				 struct buffer_head *bh, int wait)
  {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3848
  	PROC_INFO_INC(sb, journal.prepare);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3849

ca5de404f   Nick Piggin   fs: rename buffer...
3850
  	if (!trylock_buffer(bh)) {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
  		if (!wait)
  			return 0;
  		lock_buffer(bh);
  	}
  	set_buffer_journal_prepared(bh);
  	if (test_clear_buffer_dirty(bh) && buffer_journal_dirty(bh)) {
  		clear_buffer_journal_test(bh);
  		set_buffer_journal_restore_dirty(bh);
  	}
  	unlock_buffer(bh);
  	return 1;
  }
0222e6571   Jeff Mahoney   reiserfs: strip t...
3863
  /*
098297b27   Jeff Mahoney   reiserfs: cleanup...
3864
3865
3866
3867
3868
3869
3870
3871
3872
   * long and ugly.  If flush, will not return until all commit
   * blocks and all real buffers in the trans are on disk.
   * If no_async, won't return until all commit blocks are on disk.
   *
   * keep reading, there are comments as you go along
   *
   * If the journal is aborted, we just clean up. Things like flushing
   * journal lists, etc just won't happen.
   */
58d854265   Jeff Mahoney   reiserfs: cleanup...
3873
  static int do_journal_end(struct reiserfs_transaction_handle *th, int flags)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3874
  {
58d854265   Jeff Mahoney   reiserfs: cleanup...
3875
  	struct super_block *sb = th->t_super;
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3876
  	struct reiserfs_journal *journal = SB_JOURNAL(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3877
3878
3879
3880
3881
3882
3883
3884
3885
  	struct reiserfs_journal_cnode *cn, *next, *jl_cn;
  	struct reiserfs_journal_cnode *last_cn = NULL;
  	struct reiserfs_journal_desc *desc;
  	struct reiserfs_journal_commit *commit;
  	struct buffer_head *c_bh;	/* commit bh */
  	struct buffer_head *d_bh;	/* desc bh */
  	int cur_write_start = 0;	/* start index of current log write */
  	int old_start;
  	int i;
a44c94a7b   Alexander Zarochentsev   [PATCH] reiserfs:...
3886
3887
  	int flush;
  	int wait_on_commit;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3888
3889
3890
  	struct reiserfs_journal_list *jl, *temp_jl;
  	struct list_head *entry, *safe;
  	unsigned long jindex;
600ed4167   Jeff Mahoney   reiserfs: audit t...
3891
  	unsigned int commit_trans_id;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3892
  	int trans_half;
278f6679f   Jeff Mahoney   reiserfs: locking...
3893
  	int depth;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3894
3895
3896
  
  	BUG_ON(th->t_refcount > 1);
  	BUG_ON(!th->t_trans_id);
58d854265   Jeff Mahoney   reiserfs: cleanup...
3897
  	BUG_ON(!th->t_super);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3898

098297b27   Jeff Mahoney   reiserfs: cleanup...
3899
3900
3901
3902
  	/*
  	 * protect flush_older_commits from doing mistakes if the
  	 * transaction ID counter gets overflowed.
  	 */
600ed4167   Jeff Mahoney   reiserfs: audit t...
3903
  	if (th->t_trans_id == ~0U)
a44c94a7b   Alexander Zarochentsev   [PATCH] reiserfs:...
3904
3905
3906
  		flags |= FLUSH_ALL | COMMIT_NOW | WAIT;
  	flush = flags & FLUSH_ALL;
  	wait_on_commit = flags & WAIT;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3907
  	current->journal_info = th->t_handle_save;
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3908
  	reiserfs_check_lock_depth(sb, "journal end");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3909
  	if (journal->j_len == 0) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3910
  		reiserfs_prepare_for_journal(sb, SB_BUFFER_WITH_SB(sb),
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3911
  					     1);
09f1b80ba   Jeff Mahoney   reiserfs: cleanup...
3912
  		journal_mark_dirty(th, SB_BUFFER_WITH_SB(sb));
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3913
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3914

a9dd36435   Jeff Mahoney   reiserfs: rename ...
3915
  	lock_journal(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3916
3917
3918
3919
3920
3921
3922
3923
  	if (journal->j_next_full_flush) {
  		flags |= FLUSH_ALL;
  		flush = 1;
  	}
  	if (journal->j_next_async_flush) {
  		flags |= COMMIT_NOW | WAIT;
  		wait_on_commit = 1;
  	}
098297b27   Jeff Mahoney   reiserfs: cleanup...
3924
3925
3926
3927
  	/*
  	 * check_journal_end locks the journal, and unlocks if it does
  	 * not return 1 it tells us if we should continue with the
  	 * journal_end, or just return
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3928
  	 */
58d854265   Jeff Mahoney   reiserfs: cleanup...
3929
  	if (!check_journal_end(th, flags)) {
033369d1a   Artem Bityutskiy   reiserfs: get rid...
3930
  		reiserfs_schedule_old_flush(sb);
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3931
3932
  		wake_queued_writers(sb);
  		reiserfs_async_progress_wait(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3933
3934
3935
3936
3937
3938
3939
3940
3941
  		goto out;
  	}
  
  	/* check_journal_end might set these, check again */
  	if (journal->j_next_full_flush) {
  		flush = 1;
  	}
  
  	/*
098297b27   Jeff Mahoney   reiserfs: cleanup...
3942
3943
  	 * j must wait means we have to flush the log blocks, and the
  	 * real blocks for this transaction
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3944
3945
3946
3947
  	 */
  	if (journal->j_must_wait > 0) {
  		flush = 1;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3948
  #ifdef REISERFS_PREALLOCATE
098297b27   Jeff Mahoney   reiserfs: cleanup...
3949
3950
3951
3952
  	/*
  	 * quota ops might need to nest, setup the journal_info pointer
  	 * for them and raise the refcount so that it is > 0.
  	 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3953
  	current->journal_info = th;
ef43bc4fc   Jan Kara   [PATCH] reiserfs:...
3954
  	th->t_refcount++;
098297b27   Jeff Mahoney   reiserfs: cleanup...
3955
3956
3957
  
  	/* it should not involve new blocks into the transaction */
  	reiserfs_discard_all_prealloc(th);
ef43bc4fc   Jan Kara   [PATCH] reiserfs:...
3958
  	th->t_refcount--;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3959
  	current->journal_info = th->t_handle_save;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3960
  #endif
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3961
3962
3963
  
  	/* setup description block */
  	d_bh =
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3964
3965
  	    journal_getblk(sb,
  			   SB_ONDISK_JOURNAL_1st_BLOCK(sb) +
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3966
3967
3968
3969
3970
3971
  			   journal->j_start);
  	set_buffer_uptodate(d_bh);
  	desc = (struct reiserfs_journal_desc *)(d_bh)->b_data;
  	memset(d_bh->b_data, 0, d_bh->b_size);
  	memcpy(get_journal_desc_magic(d_bh), JOURNAL_DESC_MAGIC, 8);
  	set_desc_trans_id(desc, journal->j_trans_id);
098297b27   Jeff Mahoney   reiserfs: cleanup...
3972
3973
3974
3975
  	/*
  	 * setup commit block.  Don't write (keep it clean too) this one
  	 * until after everyone else is written
  	 */
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3976
  	c_bh = journal_getblk(sb, SB_ONDISK_JOURNAL_1st_BLOCK(sb) +
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3977
  			      ((journal->j_start + journal->j_len +
a9dd36435   Jeff Mahoney   reiserfs: rename ...
3978
  				1) % SB_ONDISK_JOURNAL_SIZE(sb)));
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3979
3980
3981
3982
3983
3984
3985
  	commit = (struct reiserfs_journal_commit *)c_bh->b_data;
  	memset(c_bh->b_data, 0, c_bh->b_size);
  	set_commit_trans_id(commit, journal->j_trans_id);
  	set_buffer_uptodate(c_bh);
  
  	/* init this journal list */
  	jl = journal->j_current_jl;
098297b27   Jeff Mahoney   reiserfs: cleanup...
3986
3987
  	/*
  	 * we lock the commit before doing anything because
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3988
3989
3990
3991
  	 * we want to make sure nobody tries to run flush_commit_list until
  	 * the new transaction is fully setup, and we've already flushed the
  	 * ordered bh list
  	 */
8ebc42323   Frederic Weisbecker   reiserfs: kill-th...
3992
  	reiserfs_mutex_lock_safe(&jl->j_commit_mutex, sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
  
  	/* save the transaction id in case we need to commit it later */
  	commit_trans_id = jl->j_trans_id;
  
  	atomic_set(&jl->j_older_commits_done, 0);
  	jl->j_trans_id = journal->j_trans_id;
  	jl->j_timestamp = journal->j_trans_start_time;
  	jl->j_commit_bh = c_bh;
  	jl->j_start = journal->j_start;
  	jl->j_len = journal->j_len;
  	atomic_set(&jl->j_nonzerolen, journal->j_len);
  	atomic_set(&jl->j_commit_left, journal->j_len + 2);
  	jl->j_realblock = NULL;
098297b27   Jeff Mahoney   reiserfs: cleanup...
4006
4007
4008
4009
  	/*
  	 * The ENTIRE FOR LOOP MUST not cause schedule to occur.
  	 * for each real block, add it to the journal list hash,
  	 * copy into real block index array in the commit or desc block
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4010
  	 */
a9dd36435   Jeff Mahoney   reiserfs: rename ...
4011
  	trans_half = journal_trans_half(sb->s_blocksize);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4012
4013
  	for (i = 0, cn = journal->j_first; cn; cn = cn->next, i++) {
  		if (buffer_journaled(cn->bh)) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
4014
  			jl_cn = get_cnode(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4015
  			if (!jl_cn) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
4016
  				reiserfs_panic(sb, "journal-1676",
c3a9c2109   Jeff Mahoney   reiserfs: rework ...
4017
  					       "get_cnode returned NULL");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
  			}
  			if (i == 0) {
  				jl->j_realblock = jl_cn;
  			}
  			jl_cn->prev = last_cn;
  			jl_cn->next = NULL;
  			if (last_cn) {
  				last_cn->next = jl_cn;
  			}
  			last_cn = jl_cn;
098297b27   Jeff Mahoney   reiserfs: cleanup...
4028
4029
4030
4031
  			/*
  			 * make sure the block we are trying to log
  			 * is not a block of journal or reserved area
  			 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4032
  			if (is_block_in_log_or_reserved_area
a9dd36435   Jeff Mahoney   reiserfs: rename ...
4033
4034
  			    (sb, cn->bh->b_blocknr)) {
  				reiserfs_panic(sb, "journal-2332",
c3a9c2109   Jeff Mahoney   reiserfs: rework ...
4035
4036
  					       "Trying to log block %lu, "
  					       "which is a log block",
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4037
4038
4039
4040
  					       cn->bh->b_blocknr);
  			}
  			jl_cn->blocknr = cn->bh->b_blocknr;
  			jl_cn->state = 0;
a9dd36435   Jeff Mahoney   reiserfs: rename ...
4041
  			jl_cn->sb = sb;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
  			jl_cn->bh = cn->bh;
  			jl_cn->jlist = jl;
  			insert_journal_hash(journal->j_list_hash_table, jl_cn);
  			if (i < trans_half) {
  				desc->j_realblock[i] =
  				    cpu_to_le32(cn->bh->b_blocknr);
  			} else {
  				commit->j_realblock[i - trans_half] =
  				    cpu_to_le32(cn->bh->b_blocknr);
  			}
  		} else {
  			i--;
  		}
  	}
  	set_desc_trans_len(desc, journal->j_len);
  	set_desc_mount_id(desc, journal->j_mount_id);
  	set_desc_trans_id(desc, journal->j_trans_id);
  	set_commit_trans_len(commit, journal->j_len);
098297b27   Jeff Mahoney   reiserfs: cleanup...
4060
4061
4062
4063
  	/*
  	 * special check in case all buffers in the journal
  	 * were marked for not logging
  	 */
14a61442c   Eric Sesterhenn   BUG_ON conversion...
4064
  	BUG_ON(journal->j_len == 0);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4065

098297b27   Jeff Mahoney   reiserfs: cleanup...
4066
4067
  	/*
  	 * we're about to dirty all the log blocks, mark the description block
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4068
4069
4070
4071
  	 * dirty now too.  Don't mark the commit block dirty until all the
  	 * others are on disk
  	 */
  	mark_buffer_dirty(d_bh);
098297b27   Jeff Mahoney   reiserfs: cleanup...
4072
4073
4074
4075
  	/*
  	 * first data block is j_start + 1, so add one to
  	 * cur_write_start wherever you use it
  	 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4076
4077
  	cur_write_start = journal->j_start;
  	cn = journal->j_first;
098297b27   Jeff Mahoney   reiserfs: cleanup...
4078
  	jindex = 1;	/* start at one so we don't get the desc again */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4079
4080
4081
4082
4083
4084
4085
4086
  	while (cn) {
  		clear_buffer_journal_new(cn->bh);
  		/* copy all the real blocks into log area.  dirty log blocks */
  		if (buffer_journaled(cn->bh)) {
  			struct buffer_head *tmp_bh;
  			char *addr;
  			struct page *page;
  			tmp_bh =
a9dd36435   Jeff Mahoney   reiserfs: rename ...
4087
4088
  			    journal_getblk(sb,
  					   SB_ONDISK_JOURNAL_1st_BLOCK(sb) +
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4089
4090
  					   ((cur_write_start +
  					     jindex) %
a9dd36435   Jeff Mahoney   reiserfs: rename ...
4091
  					    SB_ONDISK_JOURNAL_SIZE(sb)));
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
  			set_buffer_uptodate(tmp_bh);
  			page = cn->bh->b_page;
  			addr = kmap(page);
  			memcpy(tmp_bh->b_data,
  			       addr + offset_in_page(cn->bh->b_data),
  			       cn->bh->b_size);
  			kunmap(page);
  			mark_buffer_dirty(tmp_bh);
  			jindex++;
  			set_buffer_journal_dirty(cn->bh);
  			clear_buffer_journaled(cn->bh);
  		} else {
098297b27   Jeff Mahoney   reiserfs: cleanup...
4104
4105
4106
4107
  			/*
  			 * JDirty cleared sometime during transaction.
  			 * don't log this one
  			 */
a9dd36435   Jeff Mahoney   reiserfs: rename ...
4108
  			reiserfs_warning(sb, "journal-2048",
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
4109
4110
  					 "BAD, buffer in journal hash, "
  					 "but not JDirty!");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4111
4112
4113
  			brelse(cn->bh);
  		}
  		next = cn->next;
a9dd36435   Jeff Mahoney   reiserfs: rename ...
4114
  		free_cnode(sb, cn);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4115
  		cn = next;
278f6679f   Jeff Mahoney   reiserfs: locking...
4116
  		reiserfs_cond_resched(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4117
  	}
098297b27   Jeff Mahoney   reiserfs: cleanup...
4118
4119
4120
4121
  	/*
  	 * we are done with both the c_bh and d_bh, but
  	 * c_bh must be written after all other commit blocks,
  	 * so we dirty/relse c_bh in flush_commit_list, with commit_left <= 1.
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4122
  	 */
a9dd36435   Jeff Mahoney   reiserfs: rename ...
4123
  	journal->j_current_jl = alloc_journal_list(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
  
  	/* now it is safe to insert this transaction on the main list */
  	list_add_tail(&jl->j_list, &journal->j_journal_list);
  	list_add_tail(&jl->j_working_list, &journal->j_working_list);
  	journal->j_num_work_lists++;
  
  	/* reset journal values for the next transaction */
  	old_start = journal->j_start;
  	journal->j_start =
  	    (journal->j_start + journal->j_len +
a9dd36435   Jeff Mahoney   reiserfs: rename ...
4134
  	     2) % SB_ONDISK_JOURNAL_SIZE(sb);
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
4135
  	atomic_set(&journal->j_wcount, 0);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4136
4137
4138
4139
4140
  	journal->j_bcount = 0;
  	journal->j_last = NULL;
  	journal->j_first = NULL;
  	journal->j_len = 0;
  	journal->j_trans_start_time = 0;
a44c94a7b   Alexander Zarochentsev   [PATCH] reiserfs:...
4141
4142
4143
  	/* check for trans_id overflow */
  	if (++journal->j_trans_id == 0)
  		journal->j_trans_id = 10;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4144
4145
4146
4147
4148
  	journal->j_current_jl->j_trans_id = journal->j_trans_id;
  	journal->j_must_wait = 0;
  	journal->j_len_alloc = 0;
  	journal->j_next_full_flush = 0;
  	journal->j_next_async_flush = 0;
a9dd36435   Jeff Mahoney   reiserfs: rename ...
4149
  	init_journal_hash(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4150

098297b27   Jeff Mahoney   reiserfs: cleanup...
4151
4152
4153
4154
  	/*
  	 * make sure reiserfs_add_jh sees the new current_jl before we
  	 * write out the tails
  	 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4155
  	smp_mb();
098297b27   Jeff Mahoney   reiserfs: cleanup...
4156
4157
  	/*
  	 * tail conversion targets have to hit the disk before we end the
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4158
  	 * transaction.  Otherwise a later transaction might repack the tail
098297b27   Jeff Mahoney   reiserfs: cleanup...
4159
4160
4161
  	 * before this transaction commits, leaving the data block unflushed
  	 * and clean, if we crash before the later transaction commits, the
  	 * data block is lost.
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4162
4163
  	 */
  	if (!list_empty(&jl->j_tail_bh_list)) {
278f6679f   Jeff Mahoney   reiserfs: locking...
4164
  		depth = reiserfs_write_unlock_nested(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4165
4166
  		write_ordered_buffers(&journal->j_dirty_buffers_lock,
  				      journal, jl, &jl->j_tail_bh_list);
278f6679f   Jeff Mahoney   reiserfs: locking...
4167
  		reiserfs_write_lock_nested(sb, depth);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4168
  	}
14a61442c   Eric Sesterhenn   BUG_ON conversion...
4169
  	BUG_ON(!list_empty(&jl->j_tail_bh_list));
90415deac   Jeff Mahoney   reiserfs: convert...
4170
  	mutex_unlock(&jl->j_commit_mutex);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4171

098297b27   Jeff Mahoney   reiserfs: cleanup...
4172
4173
4174
4175
4176
4177
4178
  	/*
  	 * honor the flush wishes from the caller, simple commits can
  	 * be done outside the journal lock, they are done below
  	 *
  	 * if we don't flush the commit list right now, we put it into
  	 * the work queue so the people waiting on the async progress work
  	 * queue don't wait for this proc to flush journal lists and such.
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4179
4180
  	 */
  	if (flush) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
4181
4182
  		flush_commit_list(sb, jl, 1);
  		flush_journal_list(sb, jl, 1);
01777836c   Jan Kara   reiserfs: Fix use...
4183
4184
4185
4186
4187
4188
4189
4190
4191
  	} else if (!(jl->j_state & LIST_COMMIT_PENDING)) {
  		/*
  		 * Avoid queueing work when sb is being shut down. Transaction
  		 * will be flushed on journal shutdown.
  		 */
  		if (sb->s_flags & MS_ACTIVE)
  			queue_delayed_work(REISERFS_SB(sb)->commit_wq,
  					   &journal->j_work, HZ / 10);
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4192

098297b27   Jeff Mahoney   reiserfs: cleanup...
4193
4194
4195
4196
  	/*
  	 * if the next transaction has any chance of wrapping, flush
  	 * transactions that might get overwritten.  If any journal lists
  	 * are very old flush them as well.
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4197
  	 */
cf776a7a4   Jeff Mahoney   reiserfs: cleanup...
4198
  first_jl:
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4199
4200
4201
4202
4203
  	list_for_each_safe(entry, safe, &journal->j_journal_list) {
  		temp_jl = JOURNAL_LIST_ENTRY(entry);
  		if (journal->j_start <= temp_jl->j_start) {
  			if ((journal->j_start + journal->j_trans_max + 1) >=
  			    temp_jl->j_start) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
4204
  				flush_used_journal_lists(sb, temp_jl);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4205
4206
4207
  				goto first_jl;
  			} else if ((journal->j_start +
  				    journal->j_trans_max + 1) <
a9dd36435   Jeff Mahoney   reiserfs: rename ...
4208
  				   SB_ONDISK_JOURNAL_SIZE(sb)) {
098297b27   Jeff Mahoney   reiserfs: cleanup...
4209
4210
4211
4212
  				/*
  				 * if we don't cross into the next
  				 * transaction and we don't wrap, there is
  				 * no way we can overlap any later transactions
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4213
4214
4215
4216
4217
4218
  				 * break now
  				 */
  				break;
  			}
  		} else if ((journal->j_start +
  			    journal->j_trans_max + 1) >
a9dd36435   Jeff Mahoney   reiserfs: rename ...
4219
  			   SB_ONDISK_JOURNAL_SIZE(sb)) {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4220
  			if (((journal->j_start + journal->j_trans_max + 1) %
a9dd36435   Jeff Mahoney   reiserfs: rename ...
4221
  			     SB_ONDISK_JOURNAL_SIZE(sb)) >=
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4222
  			    temp_jl->j_start) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
4223
  				flush_used_journal_lists(sb, temp_jl);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4224
4225
  				goto first_jl;
  			} else {
098297b27   Jeff Mahoney   reiserfs: cleanup...
4226
4227
4228
4229
4230
4231
  				/*
  				* we don't overlap anything from out start
  				* to the end of the log, and our wrapped
  				* portion doesn't overlap anything at
  				* the start of the log.  We can break
  				*/
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4232
4233
4234
4235
  				break;
  			}
  		}
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4236
4237
  
  	journal->j_current_jl->j_list_bitmap =
a9dd36435   Jeff Mahoney   reiserfs: rename ...
4238
  	    get_list_bitmap(sb, journal->j_current_jl);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4239
4240
  
  	if (!(journal->j_current_jl->j_list_bitmap)) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
4241
  		reiserfs_panic(sb, "journal-1996",
c3a9c2109   Jeff Mahoney   reiserfs: rework ...
4242
  			       "could not get a list bitmap");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4243
  	}
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
4244
  	atomic_set(&journal->j_jlock, 0);
a9dd36435   Jeff Mahoney   reiserfs: rename ...
4245
  	unlock_journal(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4246
4247
  	/* wake up any body waiting to join. */
  	clear_bit(J_WRITERS_QUEUED, &journal->j_state);
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
4248
  	wake_up(&journal->j_join_wait);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4249
4250
  
  	if (!flush && wait_on_commit &&
a9dd36435   Jeff Mahoney   reiserfs: rename ...
4251
4252
  	    journal_list_still_alive(sb, commit_trans_id)) {
  		flush_commit_list(sb, jl, 1);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4253
  	}
cf776a7a4   Jeff Mahoney   reiserfs: cleanup...
4254
  out:
a9dd36435   Jeff Mahoney   reiserfs: rename ...
4255
  	reiserfs_check_lock_depth(sb, "journal end2");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4256
4257
  
  	memset(th, 0, sizeof(*th));
098297b27   Jeff Mahoney   reiserfs: cleanup...
4258
4259
  	/*
  	 * Re-set th->t_super, so we can properly keep track of how many
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4260
  	 * persistent transactions there are. We need to do this so if this
098297b27   Jeff Mahoney   reiserfs: cleanup...
4261
4262
  	 * call is part of a failed restart_transaction, we can free it later
  	 */
a9dd36435   Jeff Mahoney   reiserfs: rename ...
4263
  	th->t_super = sb;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4264
4265
4266
  
  	return journal->j_errno;
  }
32e8b1062   Jeff Mahoney   reiserfs: rearran...
4267
4268
  /* Send the file system read only and refuse new transactions */
  void reiserfs_abort_journal(struct super_block *sb, int errno)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4269
4270
4271
4272
  {
  	struct reiserfs_journal *journal = SB_JOURNAL(sb);
  	if (test_bit(J_ABORTED, &journal->j_state))
  		return;
32e8b1062   Jeff Mahoney   reiserfs: rearran...
4273
4274
  	if (!journal->j_errno)
  		journal->j_errno = errno;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4275
4276
4277
  
  	sb->s_flags |= MS_RDONLY;
  	set_bit(J_ABORTED, &journal->j_state);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4278
4279
  
  #ifdef CONFIG_REISERFS_CHECK
bd4c625c0   Linus Torvalds   reiserfs: run scr...
4280
  	dump_stack();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4281
4282
  #endif
  }