Blame view
fs/reiserfs/journal.c
121 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 |
/* ** Write ahead logging implementation copyright Chris Mason 2000 ** |
25985edce Fix common misspe... |
4 |
** The background commits make this code very interrelated, and |
1da177e4c Linux-2.6.12-rc2 |
5 6 |
** overly complex. I need to rethink things a bit....The major players: ** |
0222e6571 reiserfs: strip t... |
7 |
** journal_begin -- call with the number of blocks you expect to log. |
1da177e4c Linux-2.6.12-rc2 |
8 |
** If the current transaction is too |
0222e6571 reiserfs: strip t... |
9 |
** old, it will block until the current transaction is |
1da177e4c Linux-2.6.12-rc2 |
10 |
** finished, and then start a new one. |
0222e6571 reiserfs: strip t... |
11 |
** Usually, your transaction will get joined in with |
1da177e4c Linux-2.6.12-rc2 |
12 13 |
** previous ones for speed. ** |
0222e6571 reiserfs: strip t... |
14 |
** journal_join -- same as journal_begin, but won't block on the current |
1da177e4c Linux-2.6.12-rc2 |
15 |
** transaction regardless of age. Don't ever call |
0222e6571 reiserfs: strip t... |
16 |
** this. Ever. There are only two places it should be |
1da177e4c Linux-2.6.12-rc2 |
17 18 |
** called from, and they are both inside this file. ** |
0222e6571 reiserfs: strip t... |
19 |
** journal_mark_dirty -- adds blocks into this transaction. clears any flags |
1da177e4c Linux-2.6.12-rc2 |
20 |
** that might make them get sent to disk |
0222e6571 reiserfs: strip t... |
21 22 |
** and then marks them BH_JDirty. Puts the buffer head ** into the current transaction hash. |
1da177e4c Linux-2.6.12-rc2 |
23 24 25 |
** ** journal_end -- if the current transaction is batchable, it does nothing ** otherwise, it could do an async/synchronous commit, or |
0222e6571 reiserfs: strip t... |
26 |
** a full flush of all log and real blocks in the |
1da177e4c Linux-2.6.12-rc2 |
27 28 |
** transaction. ** |
0222e6571 reiserfs: strip t... |
29 30 31 |
** 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 |
1da177e4c Linux-2.6.12-rc2 |
32 |
** around too long. |
0222e6571 reiserfs: strip t... |
33 |
** -- Note, if you call this as an immediate flush from |
1da177e4c Linux-2.6.12-rc2 |
34 35 |
** from within kupdate, it will ignore the immediate flag */ |
1da177e4c Linux-2.6.12-rc2 |
36 |
#include <linux/time.h> |
6188e10d3 Convert asm/semap... |
37 |
#include <linux/semaphore.h> |
1da177e4c Linux-2.6.12-rc2 |
38 39 |
#include <linux/vmalloc.h> #include <linux/reiserfs_fs.h> |
1da177e4c Linux-2.6.12-rc2 |
40 41 42 43 44 |
#include <linux/kernel.h> #include <linux/errno.h> #include <linux/fcntl.h> #include <linux/stat.h> #include <linux/string.h> |
1da177e4c Linux-2.6.12-rc2 |
45 46 47 48 |
#include <linux/buffer_head.h> #include <linux/workqueue.h> #include <linux/writeback.h> #include <linux/blkdev.h> |
3fcfab16c [PATCH] separate ... |
49 |
#include <linux/backing-dev.h> |
90415deac reiserfs: convert... |
50 |
#include <linux/uaccess.h> |
5a0e3ad6a include cleanup: ... |
51 |
#include <linux/slab.h> |
90415deac reiserfs: convert... |
52 53 |
#include <asm/system.h> |
1da177e4c Linux-2.6.12-rc2 |
54 |
|
1da177e4c Linux-2.6.12-rc2 |
55 56 57 58 59 60 61 62 63 64 65 66 |
/* 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)) /* the number of mounted filesystems. This is used to decide when to ** start and kill the commit workqueue */ static int reiserfs_mounted_fs_count; static struct workqueue_struct *commit_wq; |
bd4c625c0 reiserfs: run scr... |
67 68 69 |
#define JOURNAL_TRANS_HALF 1018 /* must be correct to keep the desc and commit structs at 4k */ #define BUFNR 64 /*read ahead */ |
1da177e4c Linux-2.6.12-rc2 |
70 71 72 73 |
/* cnode stat bits. Move these into reiserfs_fs.h */ #define BLOCK_FREED 2 /* this block was freed, and can't be written. */ |
bd4c625c0 reiserfs: run scr... |
74 |
#define BLOCK_FREED_HOLDER 3 /* this block was freed during this transaction, and can't be written */ |
1da177e4c Linux-2.6.12-rc2 |
75 76 77 |
#define BLOCK_NEEDS_FLUSH 4 /* used in flush_journal_list */ #define BLOCK_DIRTIED 5 |
1da177e4c Linux-2.6.12-rc2 |
78 79 80 |
/* journal list state bits */ #define LIST_TOUCHED 1 #define LIST_DIRTY 2 |
bd4c625c0 reiserfs: run scr... |
81 |
#define LIST_COMMIT_PENDING 4 /* someone will commit this list */ |
1da177e4c Linux-2.6.12-rc2 |
82 83 84 85 |
/* flags for do_journal_end */ #define FLUSH_ALL 1 /* flush commit and real blocks */ #define COMMIT_NOW 2 /* end and commit this transaction */ |
bd4c625c0 reiserfs: run scr... |
86 87 88 89 90 91 92 93 94 95 96 |
#define WAIT 4 /* wait for the log blocks to hit the disk */ static int do_journal_end(struct reiserfs_transaction_handle *, struct super_block *, unsigned long nblocks, int flags); 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, |
a9dd36435 reiserfs: rename ... |
97 |
struct super_block *sb, unsigned long nblocks); |
bd4c625c0 reiserfs: run scr... |
98 99 |
static int release_journal_dev(struct super_block *super, struct reiserfs_journal *journal); |
1da177e4c Linux-2.6.12-rc2 |
100 |
static int dirty_one_transaction(struct super_block *s, |
bd4c625c0 reiserfs: run scr... |
101 |
struct reiserfs_journal_list *jl); |
c4028958b WorkStruct: make ... |
102 |
static void flush_async_commits(struct work_struct *work); |
1da177e4c Linux-2.6.12-rc2 |
103 104 105 106 |
static void queue_log_writer(struct super_block *s); /* values for join in do_journal_begin_r */ enum { |
bd4c625c0 reiserfs: run scr... |
107 108 109 |
JBEGIN_REG = 0, /* regular journal begin */ JBEGIN_JOIN = 1, /* join the running transaction if at all possible */ JBEGIN_ABORT = 2, /* called from cleanup code, ignores aborted flag */ |
1da177e4c Linux-2.6.12-rc2 |
110 111 112 |
}; static int do_journal_begin_r(struct reiserfs_transaction_handle *th, |
a9dd36435 reiserfs: rename ... |
113 |
struct super_block *sb, |
bd4c625c0 reiserfs: run scr... |
114 |
unsigned long nblocks, int join); |
1da177e4c Linux-2.6.12-rc2 |
115 |
|
a9dd36435 reiserfs: rename ... |
116 |
static void init_journal_hash(struct super_block *sb) |
bd4c625c0 reiserfs: run scr... |
117 |
{ |
a9dd36435 reiserfs: rename ... |
118 |
struct reiserfs_journal *journal = SB_JOURNAL(sb); |
bd4c625c0 reiserfs: run scr... |
119 120 |
memset(journal->j_hash_table, 0, JOURNAL_HASH_SIZE * sizeof(struct reiserfs_journal_cnode *)); |
1da177e4c Linux-2.6.12-rc2 |
121 122 123 124 125 126 127 |
} /* ** 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 reiserfs: run scr... |
128 129 130 131 132 133 134 |
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 Linux-2.6.12-rc2 |
135 |
} |
bd4c625c0 reiserfs: run scr... |
136 |
static struct reiserfs_bitmap_node *allocate_bitmap_node(struct super_block |
a9dd36435 reiserfs: rename ... |
137 |
*sb) |
bd4c625c0 reiserfs: run scr... |
138 139 140 |
{ struct reiserfs_bitmap_node *bn; static int id; |
d739b42b8 [PATCH] reiserfs:... |
141 |
bn = kmalloc(sizeof(struct reiserfs_bitmap_node), GFP_NOFS); |
bd4c625c0 reiserfs: run scr... |
142 143 144 |
if (!bn) { return NULL; } |
a9dd36435 reiserfs: rename ... |
145 |
bn->data = kzalloc(sb->s_blocksize, GFP_NOFS); |
bd4c625c0 reiserfs: run scr... |
146 |
if (!bn->data) { |
d739b42b8 [PATCH] reiserfs:... |
147 |
kfree(bn); |
bd4c625c0 reiserfs: run scr... |
148 149 150 |
return NULL; } bn->id = id++; |
bd4c625c0 reiserfs: run scr... |
151 152 153 |
INIT_LIST_HEAD(&bn->list); return bn; } |
a9dd36435 reiserfs: rename ... |
154 |
static struct reiserfs_bitmap_node *get_bitmap_node(struct super_block *sb) |
bd4c625c0 reiserfs: run scr... |
155 |
{ |
a9dd36435 reiserfs: rename ... |
156 |
struct reiserfs_journal *journal = SB_JOURNAL(sb); |
bd4c625c0 reiserfs: run scr... |
157 158 159 160 161 162 163 164 165 |
struct reiserfs_bitmap_node *bn = NULL; struct list_head *entry = journal->j_bitmap_nodes.next; journal->j_used_bitmap_nodes++; repeat: if (entry != &journal->j_bitmap_nodes) { bn = list_entry(entry, struct reiserfs_bitmap_node, list); list_del(entry); |
a9dd36435 reiserfs: rename ... |
166 |
memset(bn->data, 0, sb->s_blocksize); |
bd4c625c0 reiserfs: run scr... |
167 168 169 |
journal->j_free_bitmap_nodes--; return bn; } |
a9dd36435 reiserfs: rename ... |
170 |
bn = allocate_bitmap_node(sb); |
bd4c625c0 reiserfs: run scr... |
171 172 173 174 175 |
if (!bn) { yield(); goto repeat; } return bn; |
1da177e4c Linux-2.6.12-rc2 |
176 |
} |
a9dd36435 reiserfs: rename ... |
177 |
static inline void free_bitmap_node(struct super_block *sb, |
bd4c625c0 reiserfs: run scr... |
178 179 |
struct reiserfs_bitmap_node *bn) { |
a9dd36435 reiserfs: rename ... |
180 |
struct reiserfs_journal *journal = SB_JOURNAL(sb); |
bd4c625c0 reiserfs: run scr... |
181 182 |
journal->j_used_bitmap_nodes--; if (journal->j_free_bitmap_nodes > REISERFS_MAX_BITMAP_NODES) { |
d739b42b8 [PATCH] reiserfs:... |
183 184 |
kfree(bn->data); kfree(bn); |
bd4c625c0 reiserfs: run scr... |
185 186 187 188 189 |
} else { list_add(&bn->list, &journal->j_bitmap_nodes); journal->j_free_bitmap_nodes++; } } |
a9dd36435 reiserfs: rename ... |
190 |
static void allocate_bitmap_nodes(struct super_block *sb) |
bd4c625c0 reiserfs: run scr... |
191 192 |
{ int i; |
a9dd36435 reiserfs: rename ... |
193 |
struct reiserfs_journal *journal = SB_JOURNAL(sb); |
bd4c625c0 reiserfs: run scr... |
194 195 |
struct reiserfs_bitmap_node *bn = NULL; for (i = 0; i < REISERFS_MIN_BITMAP_NODES; i++) { |
a9dd36435 reiserfs: rename ... |
196 |
bn = allocate_bitmap_node(sb); |
bd4c625c0 reiserfs: run scr... |
197 198 199 200 |
if (bn) { list_add(&bn->list, &journal->j_bitmap_nodes); journal->j_free_bitmap_nodes++; } else { |
0222e6571 reiserfs: strip t... |
201 |
break; /* this is ok, we'll try again when more are needed */ |
bd4c625c0 reiserfs: run scr... |
202 203 |
} } |
1da177e4c Linux-2.6.12-rc2 |
204 |
} |
a9dd36435 reiserfs: rename ... |
205 |
static int set_bit_in_list_bitmap(struct super_block *sb, |
3ee166704 reiserfs: fix usa... |
206 |
b_blocknr_t block, |
bd4c625c0 reiserfs: run scr... |
207 208 |
struct reiserfs_list_bitmap *jb) { |
a9dd36435 reiserfs: rename ... |
209 210 |
unsigned int bmap_nr = block / (sb->s_blocksize << 3); unsigned int bit_nr = block % (sb->s_blocksize << 3); |
1da177e4c Linux-2.6.12-rc2 |
211 |
|
bd4c625c0 reiserfs: run scr... |
212 |
if (!jb->bitmaps[bmap_nr]) { |
a9dd36435 reiserfs: rename ... |
213 |
jb->bitmaps[bmap_nr] = get_bitmap_node(sb); |
bd4c625c0 reiserfs: run scr... |
214 215 216 |
} set_bit(bit_nr, (unsigned long *)jb->bitmaps[bmap_nr]->data); return 0; |
1da177e4c Linux-2.6.12-rc2 |
217 |
} |
a9dd36435 reiserfs: rename ... |
218 |
static void cleanup_bitmap_list(struct super_block *sb, |
bd4c625c0 reiserfs: run scr... |
219 220 221 222 223 |
struct reiserfs_list_bitmap *jb) { int i; if (jb->bitmaps == NULL) return; |
a9dd36435 reiserfs: rename ... |
224 |
for (i = 0; i < reiserfs_bmap_count(sb); i++) { |
bd4c625c0 reiserfs: run scr... |
225 |
if (jb->bitmaps[i]) { |
a9dd36435 reiserfs: rename ... |
226 |
free_bitmap_node(sb, jb->bitmaps[i]); |
bd4c625c0 reiserfs: run scr... |
227 228 229 |
jb->bitmaps[i] = NULL; } } |
1da177e4c Linux-2.6.12-rc2 |
230 231 232 233 234 |
} /* ** only call this on FS unmount. */ |
a9dd36435 reiserfs: rename ... |
235 |
static int free_list_bitmaps(struct super_block *sb, |
bd4c625c0 reiserfs: run scr... |
236 237 238 239 240 241 242 |
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 reiserfs: rename ... |
243 |
cleanup_bitmap_list(sb, jb); |
bd4c625c0 reiserfs: run scr... |
244 245 246 247 248 |
vfree(jb->bitmaps); jb->bitmaps = NULL; } return 0; } |
a9dd36435 reiserfs: rename ... |
249 |
static int free_bitmap_nodes(struct super_block *sb) |
bd4c625c0 reiserfs: run scr... |
250 |
{ |
a9dd36435 reiserfs: rename ... |
251 |
struct reiserfs_journal *journal = SB_JOURNAL(sb); |
bd4c625c0 reiserfs: run scr... |
252 253 254 255 256 257 |
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 [PATCH] reiserfs:... |
258 259 |
kfree(bn->data); kfree(bn); |
bd4c625c0 reiserfs: run scr... |
260 261 262 263 264 |
next = journal->j_bitmap_nodes.next; journal->j_free_bitmap_nodes--; } return 0; |
1da177e4c Linux-2.6.12-rc2 |
265 266 267 |
} /* |
0222e6571 reiserfs: strip t... |
268 |
** get memory for JOURNAL_NUM_BITMAPS worth of bitmaps. |
1da177e4c Linux-2.6.12-rc2 |
269 270 |
** jb_array is the array to be filled in. */ |
a9dd36435 reiserfs: rename ... |
271 |
int reiserfs_allocate_list_bitmaps(struct super_block *sb, |
bd4c625c0 reiserfs: run scr... |
272 |
struct reiserfs_list_bitmap *jb_array, |
3ee166704 reiserfs: fix usa... |
273 |
unsigned int bmap_nr) |
bd4c625c0 reiserfs: run scr... |
274 275 276 277 278 279 280 281 282 |
{ 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 fs: Convert vmall... |
283 |
jb->bitmaps = vzalloc(mem); |
bd4c625c0 reiserfs: run scr... |
284 |
if (!jb->bitmaps) { |
a9dd36435 reiserfs: rename ... |
285 |
reiserfs_warning(sb, "clm-2000", "unable to " |
45b03d5e8 reiserfs: rework ... |
286 |
"allocate bitmaps for journal lists"); |
bd4c625c0 reiserfs: run scr... |
287 288 289 |
failed = 1; break; } |
bd4c625c0 reiserfs: run scr... |
290 291 |
} if (failed) { |
a9dd36435 reiserfs: rename ... |
292 |
free_list_bitmaps(sb, jb_array); |
bd4c625c0 reiserfs: run scr... |
293 294 295 |
return -1; } return 0; |
1da177e4c Linux-2.6.12-rc2 |
296 297 298 |
} /* |
0222e6571 reiserfs: strip t... |
299 |
** find an available list bitmap. If you can't find one, flush a commit list |
1da177e4c Linux-2.6.12-rc2 |
300 301 |
** and try again */ |
a9dd36435 reiserfs: rename ... |
302 |
static struct reiserfs_list_bitmap *get_list_bitmap(struct super_block *sb, |
bd4c625c0 reiserfs: run scr... |
303 304 305 306 |
struct reiserfs_journal_list *jl) { int i, j; |
a9dd36435 reiserfs: rename ... |
307 |
struct reiserfs_journal *journal = SB_JOURNAL(sb); |
bd4c625c0 reiserfs: run scr... |
308 309 310 311 312 313 314 |
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 reiserfs: rename ... |
315 |
flush_commit_list(sb, |
bd4c625c0 reiserfs: run scr... |
316 317 318 319 320 321 322 323 324 325 326 327 328 329 |
journal->j_list_bitmap[i]. journal_list, 1); if (!journal->j_list_bitmap[i].journal_list) { break; } } else { break; } } if (jb->journal_list) { /* double check to make sure if flushed correctly */ return NULL; } jb->journal_list = jl; return jb; |
1da177e4c Linux-2.6.12-rc2 |
330 |
} |
0222e6571 reiserfs: strip t... |
331 |
/* |
1da177e4c Linux-2.6.12-rc2 |
332 333 334 335 |
** 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 reiserfs: run scr... |
336 337 338 339 340 341 342 |
static struct reiserfs_journal_cnode *allocate_cnodes(int num_cnodes) { struct reiserfs_journal_cnode *head; int i; if (num_cnodes <= 0) { return NULL; } |
558feb081 fs: Convert vmall... |
343 |
head = vzalloc(num_cnodes * sizeof(struct reiserfs_journal_cnode)); |
bd4c625c0 reiserfs: run scr... |
344 345 346 |
if (!head) { return NULL; } |
bd4c625c0 reiserfs: run scr... |
347 348 349 350 351 352 353 354 |
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 Linux-2.6.12-rc2 |
355 356 357 |
} /* |
0222e6571 reiserfs: strip t... |
358 |
** pulls a cnode off the free list, or returns NULL on failure |
1da177e4c Linux-2.6.12-rc2 |
359 |
*/ |
a9dd36435 reiserfs: rename ... |
360 |
static struct reiserfs_journal_cnode *get_cnode(struct super_block *sb) |
bd4c625c0 reiserfs: run scr... |
361 362 |
{ struct reiserfs_journal_cnode *cn; |
a9dd36435 reiserfs: rename ... |
363 |
struct reiserfs_journal *journal = SB_JOURNAL(sb); |
bd4c625c0 reiserfs: run scr... |
364 |
|
a9dd36435 reiserfs: rename ... |
365 |
reiserfs_check_lock_depth(sb, "get_cnode"); |
bd4c625c0 reiserfs: run scr... |
366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 |
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 Linux-2.6.12-rc2 |
382 383 384 |
} /* |
0222e6571 reiserfs: strip t... |
385 |
** returns a cnode to the free list |
1da177e4c Linux-2.6.12-rc2 |
386 |
*/ |
a9dd36435 reiserfs: rename ... |
387 |
static void free_cnode(struct super_block *sb, |
bd4c625c0 reiserfs: run scr... |
388 389 |
struct reiserfs_journal_cnode *cn) { |
a9dd36435 reiserfs: rename ... |
390 |
struct reiserfs_journal *journal = SB_JOURNAL(sb); |
1da177e4c Linux-2.6.12-rc2 |
391 |
|
a9dd36435 reiserfs: rename ... |
392 |
reiserfs_check_lock_depth(sb, "free_cnode"); |
1da177e4c Linux-2.6.12-rc2 |
393 |
|
bd4c625c0 reiserfs: run scr... |
394 395 396 397 398 399 400 401 402 |
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 Linux-2.6.12-rc2 |
403 |
} |
bd4c625c0 reiserfs: run scr... |
404 405 406 407 |
static void clear_prepared_bits(struct buffer_head *bh) { clear_buffer_journal_prepared(bh); clear_buffer_journal_restore_dirty(bh); |
1da177e4c Linux-2.6.12-rc2 |
408 |
} |
1da177e4c Linux-2.6.12-rc2 |
409 |
/* return a cnode with same dev, block number and size in table, or null if not found */ |
bd4c625c0 reiserfs: run scr... |
410 411 412 413 414 415 416 |
static inline struct reiserfs_journal_cnode *get_journal_hash_dev(struct super_block *sb, struct reiserfs_journal_cnode **table, long bl) |
1da177e4c Linux-2.6.12-rc2 |
417 |
{ |
bd4c625c0 reiserfs: run scr... |
418 419 420 421 422 423 424 425 |
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 Linux-2.6.12-rc2 |
426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 |
} /* ** 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 reiserfs: rename ... |
446 |
int reiserfs_in_journal(struct super_block *sb, |
3ee166704 reiserfs: fix usa... |
447 |
unsigned int bmap_nr, int bit_nr, int search_all, |
bd4c625c0 reiserfs: run scr... |
448 449 |
b_blocknr_t * next_zero_bit) { |
a9dd36435 reiserfs: rename ... |
450 |
struct reiserfs_journal *journal = SB_JOURNAL(sb); |
bd4c625c0 reiserfs: run scr... |
451 452 453 454 455 456 |
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 reiserfs: rename ... |
457 |
PROC_INFO_INC(sb, journal.in_journal); |
bd4c625c0 reiserfs: run scr... |
458 459 460 461 462 463 |
/* 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 */ if (search_all) { for (i = 0; i < JOURNAL_NUM_BITMAPS; i++) { |
a9dd36435 reiserfs: rename ... |
464 |
PROC_INFO_INC(sb, journal.in_journal_bitmap); |
bd4c625c0 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 reiserfs: rename ... |
474 |
sb->s_blocksize << 3, |
bd4c625c0 reiserfs: run scr... |
475 476 477 478 479 |
bit_nr + 1); return 1; } } } |
a9dd36435 reiserfs: rename ... |
480 |
bl = bmap_nr * (sb->s_blocksize << 3) + bit_nr; |
bd4c625c0 reiserfs: run scr... |
481 482 483 |
/* is it in any old transactions? */ if (search_all && (cn = |
a9dd36435 reiserfs: rename ... |
484 |
get_journal_hash_dev(sb, journal->j_list_hash_table, bl))) { |
bd4c625c0 reiserfs: run scr... |
485 486 487 488 |
return 1; } /* is it in the current transaction. This should never happen */ |
a9dd36435 reiserfs: rename ... |
489 |
if ((cn = get_journal_hash_dev(sb, journal->j_hash_table, bl))) { |
bd4c625c0 reiserfs: run scr... |
490 491 492 |
BUG(); return 1; } |
a9dd36435 reiserfs: rename ... |
493 |
PROC_INFO_INC(sb, journal.in_journal_reusable); |
bd4c625c0 reiserfs: run scr... |
494 495 |
/* safe for reuse */ return 0; |
1da177e4c Linux-2.6.12-rc2 |
496 497 498 499 |
} /* insert cn into table */ |
bd4c625c0 reiserfs: run scr... |
500 501 502 503 |
static inline void insert_journal_hash(struct reiserfs_journal_cnode **table, struct reiserfs_journal_cnode *cn) { struct reiserfs_journal_cnode *cn_orig; |
1da177e4c Linux-2.6.12-rc2 |
504 |
|
bd4c625c0 reiserfs: run scr... |
505 506 507 508 509 510 511 |
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 Linux-2.6.12-rc2 |
512 513 514 |
} /* lock the current transaction */ |
a9dd36435 reiserfs: rename ... |
515 |
static inline void lock_journal(struct super_block *sb) |
bd4c625c0 reiserfs: run scr... |
516 |
{ |
a9dd36435 reiserfs: rename ... |
517 |
PROC_INFO_INC(sb, journal.lock_journal); |
8ebc42323 reiserfs: kill-th... |
518 519 |
reiserfs_mutex_lock_safe(&SB_JOURNAL(sb)->j_mutex, sb); |
1da177e4c Linux-2.6.12-rc2 |
520 521 522 |
} /* unlock the current transaction */ |
a9dd36435 reiserfs: rename ... |
523 |
static inline void unlock_journal(struct super_block *sb) |
bd4c625c0 reiserfs: run scr... |
524 |
{ |
a9dd36435 reiserfs: rename ... |
525 |
mutex_unlock(&SB_JOURNAL(sb)->j_mutex); |
1da177e4c Linux-2.6.12-rc2 |
526 527 528 529 |
} static inline void get_journal_list(struct reiserfs_journal_list *jl) { |
bd4c625c0 reiserfs: run scr... |
530 |
jl->j_refcount++; |
1da177e4c Linux-2.6.12-rc2 |
531 532 533 |
} static inline void put_journal_list(struct super_block *s, |
bd4c625c0 reiserfs: run scr... |
534 |
struct reiserfs_journal_list *jl) |
1da177e4c Linux-2.6.12-rc2 |
535 |
{ |
bd4c625c0 reiserfs: run scr... |
536 |
if (jl->j_refcount < 1) { |
c3a9c2109 reiserfs: rework ... |
537 |
reiserfs_panic(s, "journal-2", "trans id %u, refcount at %d", |
bd4c625c0 reiserfs: run scr... |
538 539 540 |
jl->j_trans_id, jl->j_refcount); } if (--jl->j_refcount == 0) |
d739b42b8 [PATCH] reiserfs:... |
541 |
kfree(jl); |
1da177e4c Linux-2.6.12-rc2 |
542 543 544 545 546 547 548 |
} /* ** 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 reiserfs: rename ... |
549 |
static void cleanup_freed_for_journal_list(struct super_block *sb, |
bd4c625c0 reiserfs: run scr... |
550 551 |
struct reiserfs_journal_list *jl) { |
1da177e4c Linux-2.6.12-rc2 |
552 |
|
bd4c625c0 reiserfs: run scr... |
553 554 |
struct reiserfs_list_bitmap *jb = jl->j_list_bitmap; if (jb) { |
a9dd36435 reiserfs: rename ... |
555 |
cleanup_bitmap_list(sb, jb); |
bd4c625c0 reiserfs: run scr... |
556 557 558 |
} jl->j_list_bitmap->journal_list = NULL; jl->j_list_bitmap = NULL; |
1da177e4c Linux-2.6.12-rc2 |
559 560 561 |
} static int journal_list_still_alive(struct super_block *s, |
600ed4167 reiserfs: audit t... |
562 |
unsigned int trans_id) |
bd4c625c0 reiserfs: run scr... |
563 564 565 566 567 568 569 570 571 572 573 574 575 |
{ 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 try to reap reise... |
576 577 578 579 580 581 582 583 584 585 586 587 588 |
/* * 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 * final page_cache_release drop the page from the lru. */ static void release_buffer_page(struct buffer_head *bh) { struct page *page = bh->b_page; |
529ae9aaa mm: rename page t... |
589 |
if (!page->mapping && trylock_page(page)) { |
398c95bdf try to reap reise... |
590 591 592 593 594 595 596 597 598 599 |
page_cache_get(page); put_bh(bh); if (!page->mapping) try_to_free_buffers(page); unlock_page(page); page_cache_release(page); } else { put_bh(bh); } } |
bd4c625c0 reiserfs: run scr... |
600 601 602 603 604 |
static void reiserfs_end_buffer_io_sync(struct buffer_head *bh, int uptodate) { char b[BDEVNAME_SIZE]; if (buffer_journaled(bh)) { |
45b03d5e8 reiserfs: rework ... |
605 606 |
reiserfs_warning(NULL, "clm-2084", "pinned buffer %lu:%s sent to disk", |
bd4c625c0 reiserfs: run scr... |
607 608 609 610 611 612 |
bh->b_blocknr, bdevname(bh->b_bdev, b)); } if (uptodate) set_buffer_uptodate(bh); else clear_buffer_uptodate(bh); |
398c95bdf try to reap reise... |
613 |
|
bd4c625c0 reiserfs: run scr... |
614 |
unlock_buffer(bh); |
398c95bdf try to reap reise... |
615 |
release_buffer_page(bh); |
bd4c625c0 reiserfs: run scr... |
616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 |
} 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(); submit_bh(WRITE, bh); } 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(); submit_bh(WRITE, bh); } |
1da177e4c Linux-2.6.12-rc2 |
650 651 |
#define CHUNK_SIZE 32 struct buffer_chunk { |
bd4c625c0 reiserfs: run scr... |
652 653 |
struct buffer_head *bh[CHUNK_SIZE]; int nr; |
1da177e4c Linux-2.6.12-rc2 |
654 |
}; |
bd4c625c0 reiserfs: run scr... |
655 656 657 |
static void write_chunk(struct buffer_chunk *chunk) { int i; |
bd4c625c0 reiserfs: run scr... |
658 659 660 661 |
for (i = 0; i < chunk->nr; i++) { submit_logged_buffer(chunk->bh[i]); } chunk->nr = 0; |
1da177e4c Linux-2.6.12-rc2 |
662 |
} |
bd4c625c0 reiserfs: run scr... |
663 664 665 |
static void write_ordered_chunk(struct buffer_chunk *chunk) { int i; |
bd4c625c0 reiserfs: run scr... |
666 667 668 669 |
for (i = 0; i < chunk->nr; i++) { submit_ordered_buffer(chunk->bh[i]); } chunk->nr = 0; |
1da177e4c Linux-2.6.12-rc2 |
670 671 672 |
} static int add_to_chunk(struct buffer_chunk *chunk, struct buffer_head *bh, |
bd4c625c0 reiserfs: run scr... |
673 |
spinlock_t * lock, void (fn) (struct buffer_chunk *)) |
1da177e4c Linux-2.6.12-rc2 |
674 |
{ |
bd4c625c0 reiserfs: run scr... |
675 |
int ret = 0; |
14a61442c BUG_ON conversion... |
676 |
BUG_ON(chunk->nr >= CHUNK_SIZE); |
bd4c625c0 reiserfs: run scr... |
677 678 679 680 681 682 683 684 685 686 |
chunk->bh[chunk->nr++] = bh; if (chunk->nr >= CHUNK_SIZE) { ret = 1; if (lock) spin_unlock(lock); fn(chunk); if (lock) spin_lock(lock); } return ret; |
1da177e4c Linux-2.6.12-rc2 |
687 |
} |
1da177e4c Linux-2.6.12-rc2 |
688 |
static atomic_t nr_reiserfs_jh = ATOMIC_INIT(0); |
bd4c625c0 reiserfs: run scr... |
689 690 691 692 693 694 695 696 697 698 |
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 Linux-2.6.12-rc2 |
699 |
} |
1da177e4c Linux-2.6.12-rc2 |
700 701 702 703 704 705 |
} /* * we want to free the jh when the buffer has been written * and waited on */ |
bd4c625c0 reiserfs: run scr... |
706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 |
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 Linux-2.6.12-rc2 |
721 722 723 |
} static inline int __add_jh(struct reiserfs_journal *j, struct buffer_head *bh, |
bd4c625c0 reiserfs: run scr... |
724 |
int tail) |
1da177e4c Linux-2.6.12-rc2 |
725 |
{ |
bd4c625c0 reiserfs: run scr... |
726 |
struct reiserfs_jh *jh; |
1da177e4c Linux-2.6.12-rc2 |
727 |
|
bd4c625c0 reiserfs: run scr... |
728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 |
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 { no_jh: get_bh(bh); jh = alloc_jh(); spin_lock(&j->j_dirty_buffers_lock); /* buffer must be locked for __add_jh, should be able to have * two adds at the same time */ |
14a61442c BUG_ON conversion... |
744 |
BUG_ON(bh->b_private); |
bd4c625c0 reiserfs: run scr... |
745 746 |
jh->bh = bh; bh->b_private = jh; |
1da177e4c Linux-2.6.12-rc2 |
747 |
} |
bd4c625c0 reiserfs: run scr... |
748 749 750 751 752 753 754 755 |
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 Linux-2.6.12-rc2 |
756 |
} |
bd4c625c0 reiserfs: run scr... |
757 758 759 |
int reiserfs_add_tail_list(struct inode *inode, struct buffer_head *bh) { return __add_jh(SB_JOURNAL(inode->i_sb), bh, 1); |
1da177e4c Linux-2.6.12-rc2 |
760 |
} |
bd4c625c0 reiserfs: run scr... |
761 762 763 |
int reiserfs_add_ordered_list(struct inode *inode, struct buffer_head *bh) { return __add_jh(SB_JOURNAL(inode->i_sb), bh, 0); |
1da177e4c Linux-2.6.12-rc2 |
764 765 766 |
} #define JH_ENTRY(l) list_entry((l), struct reiserfs_jh, list) |
bd4c625c0 reiserfs: run scr... |
767 |
static int write_ordered_buffers(spinlock_t * lock, |
1da177e4c Linux-2.6.12-rc2 |
768 |
struct reiserfs_journal *j, |
bd4c625c0 reiserfs: run scr... |
769 |
struct reiserfs_journal_list *jl, |
1da177e4c Linux-2.6.12-rc2 |
770 771 |
struct list_head *list) { |
bd4c625c0 reiserfs: run scr... |
772 773 774 775 776 777 778 779 780 781 782 783 784 |
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 fs: rename buffer... |
785 |
if (!trylock_buffer(bh)) { |
bd4c625c0 reiserfs: run scr... |
786 |
if (!buffer_dirty(bh)) { |
f116629d0 [PATCH] fs: use l... |
787 |
list_move(&jh->list, &tmp); |
bd4c625c0 reiserfs: run scr... |
788 789 790 791 792 793 794 795 796 797 |
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; } |
3d4492f81 [PATCH] reiserfs:... |
798 799 800 801 802 803 804 805 |
/* in theory, dirty non-uptodate buffers should never get here, * 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 reiserfs: run scr... |
806 |
if (buffer_dirty(bh)) { |
f116629d0 [PATCH] fs: use l... |
807 |
list_move(&jh->list, &tmp); |
bd4c625c0 reiserfs: run scr... |
808 809 810 811 812 813 814 815 816 817 818 |
add_to_chunk(&chunk, bh, lock, write_ordered_chunk); } else { reiserfs_free_jh(bh); unlock_buffer(bh); } loop_next: put_bh(bh); cond_resched_lock(lock); } if (chunk.nr) { spin_unlock(lock); |
1da177e4c Linux-2.6.12-rc2 |
819 |
write_ordered_chunk(&chunk); |
bd4c625c0 reiserfs: run scr... |
820 |
spin_lock(lock); |
1da177e4c Linux-2.6.12-rc2 |
821 |
} |
bd4c625c0 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; } |
d62b1b87a [PATCH] resierfs:... |
836 837 838 839 840 841 842 843 844 845 846 847 848 |
/* 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. */ if (buffer_dirty(bh) && unlikely(bh->b_page->mapping == NULL)) { spin_unlock(lock); ll_rw_block(WRITE, 1, &bh); spin_lock(lock); } |
bd4c625c0 reiserfs: run scr... |
849 850 |
put_bh(bh); cond_resched_lock(lock); |
1da177e4c Linux-2.6.12-rc2 |
851 |
} |
bd4c625c0 reiserfs: run scr... |
852 853 854 |
spin_unlock(lock); return ret; } |
1da177e4c Linux-2.6.12-rc2 |
855 |
|
bd4c625c0 reiserfs: run scr... |
856 857 858 859 860 861 862 |
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 reiserfs: audit t... |
863 864 865 |
unsigned int trans_id = jl->j_trans_id; unsigned int other_trans_id; unsigned int first_trans_id; |
bd4c625c0 reiserfs: run scr... |
866 867 868 869 870 871 872 873 874 875 876 877 |
find_first: /* * 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 Linux-2.6.12-rc2 |
878 |
|
bd4c625c0 reiserfs: run scr... |
879 880 881 |
first_jl = other_jl; entry = other_jl->j_list.prev; } |
1da177e4c Linux-2.6.12-rc2 |
882 |
|
bd4c625c0 reiserfs: run scr... |
883 884 885 886 |
/* if we didn't find any older uncommitted transactions, return now */ if (first_jl == jl) { return 0; } |
1da177e4c Linux-2.6.12-rc2 |
887 |
|
bd4c625c0 reiserfs: run scr... |
888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 |
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; /* 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. */ 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 Linux-2.6.12-rc2 |
917 |
} |
1da177e4c Linux-2.6.12-rc2 |
918 |
} |
bd4c625c0 reiserfs: run scr... |
919 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
920 |
} |
deba0f49b fs/reiserfs/: cle... |
921 922 |
static int reiserfs_async_progress_wait(struct super_block *s) |
bd4c625c0 reiserfs: run scr... |
923 |
{ |
bd4c625c0 reiserfs: run scr... |
924 |
struct reiserfs_journal *j = SB_JOURNAL(s); |
8ebc42323 reiserfs: kill-th... |
925 926 927 |
if (atomic_read(&j->j_async_throttle)) { reiserfs_write_unlock(s); |
8aa7e847d Fix congestion_wa... |
928 |
congestion_wait(BLK_RW_ASYNC, HZ / 10); |
8ebc42323 reiserfs: kill-th... |
929 930 |
reiserfs_write_lock(s); } |
bd4c625c0 reiserfs: run scr... |
931 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
932 933 934 935 936 937 938 939 940 |
} /* ** 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 reiserfs: run scr... |
941 942 943 944 |
static int flush_commit_list(struct super_block *s, struct reiserfs_journal_list *jl, int flushall) { int i; |
3ee166704 reiserfs: fix usa... |
945 |
b_blocknr_t bn; |
bd4c625c0 reiserfs: run scr... |
946 |
struct buffer_head *tbh = NULL; |
600ed4167 reiserfs: audit t... |
947 |
unsigned int trans_id = jl->j_trans_id; |
bd4c625c0 reiserfs: run scr... |
948 |
struct reiserfs_journal *journal = SB_JOURNAL(s); |
bd4c625c0 reiserfs: run scr... |
949 |
int retval = 0; |
e0e851cf3 [PATCH] reiserfs:... |
950 |
int write_len; |
bd4c625c0 reiserfs: run scr... |
951 952 953 954 955 956 |
reiserfs_check_lock_depth(s, "flush_commit_list"); if (atomic_read(&jl->j_older_commits_done)) { return 0; } |
bd4c625c0 reiserfs: run scr... |
957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 |
/* before we can put our commit blocks on disk, we have to make sure everyone older than ** us is on disk too */ 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) { /* list disappeared during flush_older_commits. return */ goto put_jl; } } /* make sure nobody is trying to flush this one at the same time */ |
8ebc42323 reiserfs: kill-th... |
972 |
reiserfs_mutex_lock_safe(&jl->j_commit_mutex, s); |
bd4c625c0 reiserfs: run scr... |
973 |
if (!journal_list_still_alive(s, trans_id)) { |
90415deac reiserfs: convert... |
974 |
mutex_unlock(&jl->j_commit_mutex); |
bd4c625c0 reiserfs: run scr... |
975 976 977 978 979 980 981 982 983 |
goto put_jl; } BUG_ON(jl->j_trans_id == 0); /* this commit is done, exit */ if (atomic_read(&(jl->j_commit_left)) <= 0) { if (flushall) { atomic_set(&(jl->j_older_commits_done), 1); } |
90415deac reiserfs: convert... |
984 |
mutex_unlock(&jl->j_commit_mutex); |
bd4c625c0 reiserfs: run scr... |
985 986 987 988 |
goto put_jl; } if (!list_empty(&jl->j_bh_list)) { |
3d4492f81 [PATCH] reiserfs:... |
989 |
int ret; |
8ebc42323 reiserfs: kill-th... |
990 991 992 993 994 995 |
/* * We might sleep in numerous places inside * write_ordered_buffers. Relax the write lock. */ reiserfs_write_unlock(s); |
3d4492f81 [PATCH] reiserfs:... |
996 997 998 999 |
ret = write_ordered_buffers(&journal->j_dirty_buffers_lock, journal, jl, &jl->j_bh_list); if (ret < 0 && retval == 0) retval = ret; |
8ebc42323 reiserfs: kill-th... |
1000 |
reiserfs_write_lock(s); |
bd4c625c0 reiserfs: run scr... |
1001 1002 1003 1004 |
} BUG_ON(!list_empty(&jl->j_bh_list)); /* * for the description block and all the log blocks, submit any buffers |
e0e851cf3 [PATCH] reiserfs:... |
1005 1006 1007 1008 |
* 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 reiserfs: run scr... |
1009 1010 |
*/ atomic_inc(&journal->j_async_throttle); |
e0e851cf3 [PATCH] reiserfs:... |
1011 1012 1013 1014 |
write_len = jl->j_len + 1; if (write_len < 256) write_len = 256; for (i = 0 ; i < write_len ; i++) { |
bd4c625c0 reiserfs: run scr... |
1015 1016 1017 |
bn = SB_ONDISK_JOURNAL_1st_BLOCK(s) + (jl->j_start + i) % SB_ONDISK_JOURNAL_SIZE(s); tbh = journal_find_get_block(s, bn); |
e0e851cf3 [PATCH] reiserfs:... |
1018 |
if (tbh) { |
6e3647acb kill-the-BKL/reis... |
1019 1020 1021 1022 1023 |
if (buffer_dirty(tbh)) { reiserfs_write_unlock(s); ll_rw_block(WRITE, 1, &tbh); reiserfs_write_lock(s); } |
e0e851cf3 [PATCH] reiserfs:... |
1024 1025 |
put_bh(tbh) ; } |
bd4c625c0 reiserfs: run scr... |
1026 1027 |
} atomic_dec(&journal->j_async_throttle); |
bd4c625c0 reiserfs: run scr... |
1028 1029 1030 1031 |
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 reiserfs: kill-th... |
1032 1033 |
reiserfs_write_unlock(s); |
bd4c625c0 reiserfs: run scr... |
1034 |
wait_on_buffer(tbh); |
8ebc42323 reiserfs: kill-th... |
1035 |
reiserfs_write_lock(s); |
bd4c625c0 reiserfs: run scr... |
1036 1037 1038 |
// since we're using ll_rw_blk above, it might have skipped over // a locked buffer. Double check here // |
8ebc42323 reiserfs: kill-th... |
1039 1040 1041 |
/* redundant, sync_dirty_buffer() checks */ if (buffer_dirty(tbh)) { reiserfs_write_unlock(s); |
bd4c625c0 reiserfs: run scr... |
1042 |
sync_dirty_buffer(tbh); |
8ebc42323 reiserfs: kill-th... |
1043 1044 |
reiserfs_write_lock(s); } |
bd4c625c0 reiserfs: run scr... |
1045 |
if (unlikely(!buffer_uptodate(tbh))) { |
1da177e4c Linux-2.6.12-rc2 |
1046 |
#ifdef CONFIG_REISERFS_CHECK |
45b03d5e8 reiserfs: rework ... |
1047 1048 |
reiserfs_warning(s, "journal-601", "buffer write failed"); |
1da177e4c Linux-2.6.12-rc2 |
1049 |
#endif |
bd4c625c0 reiserfs: run scr... |
1050 1051 1052 1053 1054 1055 1056 1057 |
retval = -EIO; } put_bh(tbh); /* once for journal_find_get_block */ put_bh(tbh); /* once due to original getblk in do_journal_end */ atomic_dec(&(jl->j_commit_left)); } BUG_ON(atomic_read(&(jl->j_commit_left)) != 1); |
7cd33ad23 reiserfs: replace... |
1058 1059 1060 1061 1062 1063 1064 1065 |
/* If there was a write error in the journal - we can't commit * this transaction - it will be invalid and, if successful, * will just end up propagating the write error out to * the file system. */ if (likely(!retval && !reiserfs_is_journal_aborted (journal))) { if (buffer_dirty(jl->j_commit_bh)) BUG(); mark_buffer_dirty(jl->j_commit_bh) ; |
8ebc42323 reiserfs: kill-th... |
1066 |
reiserfs_write_unlock(s); |
7cd33ad23 reiserfs: replace... |
1067 1068 1069 1070 |
if (reiserfs_barrier_flush(s)) __sync_dirty_buffer(jl->j_commit_bh, WRITE_FLUSH_FUA); else sync_dirty_buffer(jl->j_commit_bh); |
8ebc42323 reiserfs: kill-th... |
1071 1072 |
reiserfs_write_lock(s); } |
bd4c625c0 reiserfs: run scr... |
1073 |
|
bd4c625c0 reiserfs: run scr... |
1074 1075 |
/* If there was a write error in the journal - we can't commit this * transaction - it will be invalid and, if successful, will just end |
beb7dd86a Fix misspellings ... |
1076 |
* up propagating the write error out to the filesystem. */ |
bd4c625c0 reiserfs: run scr... |
1077 |
if (unlikely(!buffer_uptodate(jl->j_commit_bh))) { |
1da177e4c Linux-2.6.12-rc2 |
1078 |
#ifdef CONFIG_REISERFS_CHECK |
45b03d5e8 reiserfs: rework ... |
1079 |
reiserfs_warning(s, "journal-615", "buffer write failed"); |
1da177e4c Linux-2.6.12-rc2 |
1080 |
#endif |
bd4c625c0 reiserfs: run scr... |
1081 1082 1083 1084 1085 |
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 reiserfs: rework ... |
1086 |
reiserfs_warning(s, "clm-2200", "last commit %lu, current %lu", |
bd4c625c0 reiserfs: run scr... |
1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 |
journal->j_last_commit_id, jl->j_trans_id); } journal->j_last_commit_id = jl->j_trans_id; /* now, every commit block is on the disk. It is safe to allow blocks freed during this transaction to be reallocated */ cleanup_freed_for_journal_list(s, jl); retval = retval ? retval : journal->j_errno; /* mark the metadata dirty */ if (!retval) dirty_one_transaction(s, jl); atomic_dec(&(jl->j_commit_left)); if (flushall) { atomic_set(&(jl->j_older_commits_done), 1); } |
90415deac reiserfs: convert... |
1104 |
mutex_unlock(&jl->j_commit_mutex); |
bd4c625c0 reiserfs: run scr... |
1105 1106 1107 1108 1109 |
put_jl: put_journal_list(s, jl); if (retval) reiserfs_abort(s, retval, "Journal write error in %s", |
fbe5498b3 reiserfs: replace... |
1110 |
__func__); |
bd4c625c0 reiserfs: run scr... |
1111 |
return retval; |
1da177e4c Linux-2.6.12-rc2 |
1112 1113 1114 |
} /* |
0222e6571 reiserfs: strip t... |
1115 1116 |
** 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 |
1da177e4c Linux-2.6.12-rc2 |
1117 |
*/ |
bd4c625c0 reiserfs: run scr... |
1118 1119 1120 1121 1122 1123 |
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 Linux-2.6.12-rc2 |
1124 |
|
bd4c625c0 reiserfs: run scr... |
1125 1126 1127 1128 1129 1130 1131 1132 |
cn = cn->hprev; while (cn) { if (cn->sb == sb && cn->blocknr == blocknr && cn->jlist) { return cn->jlist; } cn = cn->hprev; } return NULL; |
1da177e4c Linux-2.6.12-rc2 |
1133 |
} |
a31720271 [PATCH] Fix reise... |
1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 |
static int newer_jl_done(struct reiserfs_journal_cnode *cn) { struct super_block *sb = cn->sb; b_blocknr_t blocknr = cn->blocknr; cn = cn->hprev; while (cn) { if (cn->sb == sb && cn->blocknr == blocknr && cn->jlist && atomic_read(&cn->jlist->j_commit_left) != 0) return 0; cn = cn->hprev; } return 1; } |
bd4c625c0 reiserfs: run scr... |
1148 1149 1150 1151 |
static void remove_journal_hash(struct super_block *, struct reiserfs_journal_cnode **, struct reiserfs_journal_list *, unsigned long, int); |
1da177e4c Linux-2.6.12-rc2 |
1152 1153 1154 1155 1156 1157 |
/* ** 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 reiserfs: rename ... |
1158 |
static void remove_all_from_journal_list(struct super_block *sb, |
bd4c625c0 reiserfs: run scr... |
1159 1160 1161 |
struct reiserfs_journal_list *jl, int debug) { |
a9dd36435 reiserfs: rename ... |
1162 |
struct reiserfs_journal *journal = SB_JOURNAL(sb); |
bd4c625c0 reiserfs: run scr... |
1163 1164 1165 1166 1167 1168 1169 1170 1171 |
struct reiserfs_journal_cnode *cn, *last; cn = jl->j_realblock; /* which is better, to lock once around the whole loop, or ** to lock for each call to remove_journal_hash? */ while (cn) { if (cn->blocknr != 0) { if (debug) { |
a9dd36435 reiserfs: rename ... |
1172 |
reiserfs_warning(sb, "reiserfs-2201", |
bd4c625c0 reiserfs: run scr... |
1173 1174 1175 1176 1177 |
"block %u, bh is %d, state %ld", cn->blocknr, cn->bh ? 1 : 0, cn->state); } cn->state = 0; |
a9dd36435 reiserfs: rename ... |
1178 |
remove_journal_hash(sb, journal->j_list_hash_table, |
bd4c625c0 reiserfs: run scr... |
1179 1180 1181 1182 |
jl, cn->blocknr, 1); } last = cn; cn = cn->next; |
a9dd36435 reiserfs: rename ... |
1183 |
free_cnode(sb, last); |
bd4c625c0 reiserfs: run scr... |
1184 1185 |
} jl->j_realblock = NULL; |
1da177e4c Linux-2.6.12-rc2 |
1186 1187 1188 1189 1190 1191 1192 1193 1194 |
} /* ** 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 reiserfs: rename ... |
1195 |
static int _update_journal_header_block(struct super_block *sb, |
bd4c625c0 reiserfs: run scr... |
1196 |
unsigned long offset, |
600ed4167 reiserfs: audit t... |
1197 |
unsigned int trans_id) |
bd4c625c0 reiserfs: run scr... |
1198 1199 |
{ struct reiserfs_journal_header *jh; |
a9dd36435 reiserfs: rename ... |
1200 |
struct reiserfs_journal *journal = SB_JOURNAL(sb); |
1da177e4c Linux-2.6.12-rc2 |
1201 |
|
bd4c625c0 reiserfs: run scr... |
1202 1203 |
if (reiserfs_is_journal_aborted(journal)) return -EIO; |
1da177e4c Linux-2.6.12-rc2 |
1204 |
|
bd4c625c0 reiserfs: run scr... |
1205 1206 |
if (trans_id >= journal->j_last_flush_trans_id) { if (buffer_locked((journal->j_header_bh))) { |
8ebc42323 reiserfs: kill-th... |
1207 |
reiserfs_write_unlock(sb); |
bd4c625c0 reiserfs: run scr... |
1208 |
wait_on_buffer((journal->j_header_bh)); |
8ebc42323 reiserfs: kill-th... |
1209 |
reiserfs_write_lock(sb); |
bd4c625c0 reiserfs: run scr... |
1210 |
if (unlikely(!buffer_uptodate(journal->j_header_bh))) { |
1da177e4c Linux-2.6.12-rc2 |
1211 |
#ifdef CONFIG_REISERFS_CHECK |
a9dd36435 reiserfs: rename ... |
1212 |
reiserfs_warning(sb, "journal-699", |
45b03d5e8 reiserfs: rework ... |
1213 |
"buffer write failed"); |
1da177e4c Linux-2.6.12-rc2 |
1214 |
#endif |
bd4c625c0 reiserfs: run scr... |
1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 |
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 reiserfs: replace... |
1225 1226 1227 1228 1229 1230 |
set_buffer_dirty(journal->j_header_bh); reiserfs_write_unlock(sb); if (reiserfs_barrier_flush(sb)) __sync_dirty_buffer(journal->j_header_bh, WRITE_FLUSH_FUA); else |
bd4c625c0 reiserfs: run scr... |
1231 |
sync_dirty_buffer(journal->j_header_bh); |
7cd33ad23 reiserfs: replace... |
1232 1233 |
reiserfs_write_lock(sb); |
bd4c625c0 reiserfs: run scr... |
1234 |
if (!buffer_uptodate(journal->j_header_bh)) { |
a9dd36435 reiserfs: rename ... |
1235 |
reiserfs_warning(sb, "journal-837", |
45b03d5e8 reiserfs: rework ... |
1236 |
"IO error during journal replay"); |
bd4c625c0 reiserfs: run scr... |
1237 1238 1239 1240 1241 |
return -EIO; } } return 0; } |
a9dd36435 reiserfs: rename ... |
1242 |
static int update_journal_header_block(struct super_block *sb, |
bd4c625c0 reiserfs: run scr... |
1243 |
unsigned long offset, |
600ed4167 reiserfs: audit t... |
1244 |
unsigned int trans_id) |
bd4c625c0 reiserfs: run scr... |
1245 |
{ |
a9dd36435 reiserfs: rename ... |
1246 |
return _update_journal_header_block(sb, offset, trans_id); |
1da177e4c Linux-2.6.12-rc2 |
1247 |
} |
bd4c625c0 reiserfs: run scr... |
1248 |
|
0222e6571 reiserfs: strip t... |
1249 1250 |
/* ** flush any and all journal lists older than you are |
1da177e4c Linux-2.6.12-rc2 |
1251 1252 |
** can only be called from flush_journal_list */ |
a9dd36435 reiserfs: rename ... |
1253 |
static int flush_older_journal_lists(struct super_block *sb, |
bd4c625c0 reiserfs: run scr... |
1254 1255 1256 1257 |
struct reiserfs_journal_list *jl) { struct list_head *entry; struct reiserfs_journal_list *other_jl; |
a9dd36435 reiserfs: rename ... |
1258 |
struct reiserfs_journal *journal = SB_JOURNAL(sb); |
600ed4167 reiserfs: audit t... |
1259 |
unsigned int trans_id = jl->j_trans_id; |
bd4c625c0 reiserfs: run scr... |
1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 |
/* we know we are the only ones flushing things, no extra race * protection is required. */ restart: 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 reiserfs: rename ... |
1273 |
flush_journal_list(sb, other_jl, 0); |
bd4c625c0 reiserfs: run scr... |
1274 1275 1276 1277 1278 |
/* other_jl is now deleted from the list */ goto restart; } return 0; |
1da177e4c Linux-2.6.12-rc2 |
1279 1280 1281 |
} static void del_from_work_list(struct super_block *s, |
bd4c625c0 reiserfs: run scr... |
1282 1283 1284 1285 1286 1287 1288 |
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 Linux-2.6.12-rc2 |
1289 1290 1291 1292 1293 1294 1295 |
} /* flush a journal list, both commit and real blocks ** ** always set flushall to 1, unless you are calling from inside ** flush_journal_list ** |
0222e6571 reiserfs: strip t... |
1296 1297 |
** 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 |
1da177e4c Linux-2.6.12-rc2 |
1298 1299 |
** do_journal_end, or by journal_release */ |
bd4c625c0 reiserfs: run scr... |
1300 1301 |
static int flush_journal_list(struct super_block *s, struct reiserfs_journal_list *jl, int flushall) |
1da177e4c Linux-2.6.12-rc2 |
1302 |
{ |
bd4c625c0 reiserfs: run scr... |
1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 |
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; BUG_ON(j_len_saved <= 0); if (atomic_read(&journal->j_wcount) != 0) { |
45b03d5e8 reiserfs: rework ... |
1316 |
reiserfs_warning(s, "clm-2048", "called with wcount %d", |
bd4c625c0 reiserfs: run scr... |
1317 1318 1319 |
atomic_read(&journal->j_wcount)); } BUG_ON(jl->j_trans_id == 0); |
1da177e4c Linux-2.6.12-rc2 |
1320 |
|
bd4c625c0 reiserfs: run scr... |
1321 1322 |
/* if flushall == 0, the lock is already held */ if (flushall) { |
8ebc42323 reiserfs: kill-th... |
1323 |
reiserfs_mutex_lock_safe(&journal->j_flush_mutex, s); |
afe702590 reiserfs: convert... |
1324 |
} else if (mutex_trylock(&journal->j_flush_mutex)) { |
bd4c625c0 reiserfs: run scr... |
1325 1326 |
BUG(); } |
1da177e4c Linux-2.6.12-rc2 |
1327 |
|
bd4c625c0 reiserfs: run scr... |
1328 1329 |
count = 0; if (j_len_saved > journal->j_trans_max) { |
c3a9c2109 reiserfs: rework ... |
1330 |
reiserfs_panic(s, "journal-715", "length is %lu, trans id %lu", |
bd4c625c0 reiserfs: run scr... |
1331 1332 1333 |
j_len_saved, jl->j_trans_id); return 0; } |
1da177e4c Linux-2.6.12-rc2 |
1334 |
|
bd4c625c0 reiserfs: run scr... |
1335 1336 1337 1338 1339 |
/* if all the work is already done, get out of here */ if (atomic_read(&(jl->j_nonzerolen)) <= 0 && atomic_read(&(jl->j_commit_left)) <= 0) { goto flush_older_and_return; } |
0222e6571 reiserfs: strip t... |
1340 |
/* start by putting the commit list on disk. This will also flush |
bd4c625c0 reiserfs: run scr... |
1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 |
** the commit lists of any olders transactions */ flush_commit_list(s, jl, 1); if (!(jl->j_state & LIST_DIRTY) && !reiserfs_is_journal_aborted(journal)) BUG(); /* are we done now? */ if (atomic_read(&(jl->j_nonzerolen)) <= 0 && atomic_read(&(jl->j_commit_left)) <= 0) { goto flush_older_and_return; } |
0222e6571 reiserfs: strip t... |
1354 1355 |
/* loop through each cnode, see if we need to write it, ** or wait on a more recent transaction, or just ignore it |
bd4c625c0 reiserfs: run scr... |
1356 1357 |
*/ if (atomic_read(&(journal->j_wcount)) != 0) { |
c3a9c2109 reiserfs: rework ... |
1358 1359 |
reiserfs_panic(s, "journal-844", "journal list is flushing, " "wcount is not 0"); |
bd4c625c0 reiserfs: run scr... |
1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 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; } /* This transaction failed commit. Don't write out to the disk */ if (!(jl->j_state & LIST_DIRTY)) goto free_cnode; pjl = find_newer_jl_for_cn(cn); /* 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 */ if (!pjl && cn->bh) { saved_bh = cn->bh; |
0222e6571 reiserfs: strip t... |
1382 1383 |
/* we do this to make sure nobody releases the buffer while ** we are working with it |
bd4c625c0 reiserfs: run scr... |
1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 |
*/ 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)) { /* everything with !pjl && jwait should be writable */ BUG(); } } /* if someone has this block in a newer transaction, just make |
0779bf2d2 Fix misc .c/.h co... |
1398 |
** sure they are committed, and don't try writing it to disk |
bd4c625c0 reiserfs: run scr... |
1399 1400 1401 1402 1403 1404 |
*/ if (pjl) { if (atomic_read(&pjl->j_commit_left)) flush_commit_list(s, pjl, 1); goto free_cnode; } |
0222e6571 reiserfs: strip t... |
1405 1406 |
/* bh == NULL when the block got to disk on its own, OR, ** the block got freed in a future transaction |
bd4c625c0 reiserfs: run scr... |
1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 |
*/ if (saved_bh == NULL) { goto free_cnode; } /* 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 */ if ((!was_jwait) && !buffer_locked(saved_bh)) { |
45b03d5e8 reiserfs: rework ... |
1417 1418 |
reiserfs_warning(s, "journal-813", "BAD! buffer %llu %cdirty %cjwait, " |
bd4c625c0 reiserfs: run scr... |
1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 |
"not in a newer tranasction", (unsigned long long)saved_bh-> b_blocknr, was_dirty ? ' ' : '!', was_jwait ? ' ' : '!'); } if (was_dirty) { /* we inc again because saved_bh gets decremented at free_cnode */ 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 reiserfs: rework ... |
1436 1437 |
reiserfs_warning(s, "clm-2082", "Unable to flush buffer %llu in %s", |
bd4c625c0 reiserfs: run scr... |
1438 |
(unsigned long long)saved_bh-> |
fbe5498b3 reiserfs: replace... |
1439 |
b_blocknr, __func__); |
bd4c625c0 reiserfs: run scr... |
1440 1441 1442 1443 1444 1445 1446 1447 |
} free_cnode: last = cn; cn = cn->next; if (saved_bh) { /* we incremented this to keep others from taking the buffer head away */ put_bh(saved_bh); if (atomic_read(&(saved_bh->b_count)) < 0) { |
45b03d5e8 reiserfs: rework ... |
1448 1449 |
reiserfs_warning(s, "journal-945", "saved_bh->b_count < 0"); |
bd4c625c0 reiserfs: run scr... |
1450 1451 1452 1453 1454 1455 1456 1457 |
} } } if (count > 0) { cn = jl->j_realblock; while (cn) { if (test_bit(BLOCK_NEEDS_FLUSH, &cn->state)) { if (!cn->bh) { |
c3a9c2109 reiserfs: rework ... |
1458 1459 |
reiserfs_panic(s, "journal-1011", "cn->bh is NULL"); |
bd4c625c0 reiserfs: run scr... |
1460 |
} |
8ebc42323 reiserfs: kill-th... |
1461 1462 |
reiserfs_write_unlock(s); |
bd4c625c0 reiserfs: run scr... |
1463 |
wait_on_buffer(cn->bh); |
8ebc42323 reiserfs: kill-th... |
1464 |
reiserfs_write_lock(s); |
bd4c625c0 reiserfs: run scr... |
1465 |
if (!cn->bh) { |
c3a9c2109 reiserfs: rework ... |
1466 1467 |
reiserfs_panic(s, "journal-1012", "cn->bh is NULL"); |
bd4c625c0 reiserfs: run scr... |
1468 1469 1470 |
} if (unlikely(!buffer_uptodate(cn->bh))) { #ifdef CONFIG_REISERFS_CHECK |
45b03d5e8 reiserfs: rework ... |
1471 1472 |
reiserfs_warning(s, "journal-949", "buffer write failed"); |
bd4c625c0 reiserfs: run scr... |
1473 1474 1475 1476 1477 1478 1479 1480 |
#endif err = -EIO; } /* note, we must clear the JDirty_wait bit after the up to date ** check, otherwise we race against our flushpage routine */ BUG_ON(!test_clear_buffer_journal_dirty (cn->bh)); |
398c95bdf try to reap reise... |
1481 |
/* drop one ref for us */ |
bd4c625c0 reiserfs: run scr... |
1482 |
put_bh(cn->bh); |
398c95bdf try to reap reise... |
1483 1484 |
/* drop one ref for journal_mark_dirty */ release_buffer_page(cn->bh); |
bd4c625c0 reiserfs: run scr... |
1485 1486 1487 1488 1489 1490 1491 1492 |
} cn = cn->next; } } if (err) reiserfs_abort(s, -EIO, "Write error while pushing transaction to disk in %s", |
fbe5498b3 reiserfs: replace... |
1493 |
__func__); |
bd4c625c0 reiserfs: run scr... |
1494 |
flush_older_and_return: |
0222e6571 reiserfs: strip t... |
1495 |
/* before we can update the journal header block, we _must_ flush all |
bd4c625c0 reiserfs: run scr... |
1496 1497 1498 1499 1500 1501 1502 1503 1504 |
** 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 */ if (flushall) { flush_older_journal_lists(s, jl); } err = journal->j_errno; |
0222e6571 reiserfs: strip t... |
1505 |
/* before we can remove everything from the hash tables for this |
bd4c625c0 reiserfs: run scr... |
1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 |
** 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 */ 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 reiserfs: replace... |
1522 |
__func__); |
bd4c625c0 reiserfs: run scr... |
1523 1524 1525 1526 1527 1528 1529 1530 |
} 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 reiserfs: rework ... |
1531 |
reiserfs_warning(s, "clm-2201", "last flush %lu, current %lu", |
bd4c625c0 reiserfs: run scr... |
1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 |
journal->j_last_flush_id, jl->j_trans_id); } journal->j_last_flush_id = jl->j_trans_id; /* not strictly required since we are freeing the list, but it should * help find code using dead lists later on */ jl->j_len = 0; atomic_set(&(jl->j_nonzerolen), 0); 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 reiserfs: convert... |
1548 |
mutex_unlock(&journal->j_flush_mutex); |
bd4c625c0 reiserfs: run scr... |
1549 1550 |
return err; } |
a31720271 [PATCH] Fix reise... |
1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 |
static int test_transaction(struct super_block *s, struct reiserfs_journal_list *jl) { struct reiserfs_journal_cnode *cn; if (jl->j_len == 0 || atomic_read(&jl->j_nonzerolen) == 0) return 1; cn = jl->j_realblock; while (cn) { /* if the blocknr == 0, this has been cleared from the hash, ** skip it */ if (cn->blocknr == 0) { goto next; } if (cn->bh && !newer_jl_done(cn)) return 0; next: cn = cn->next; cond_resched(); } return 0; } |
bd4c625c0 reiserfs: run scr... |
1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 |
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) { /* if the blocknr == 0, this has been cleared from the hash, ** skip it */ if (cn->blocknr == 0) { goto next; } if (cn->bh && can_dirty(cn) && buffer_dirty(cn->bh)) { struct buffer_head *tmp_bh; /* we can race against journal_mark_freed when we try * 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); } next: 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) { /* 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 */ pjl = find_newer_jl_for_cn(cn); if (!pjl && cn->blocknr && cn->bh && buffer_journal_dirty(cn->bh)) { BUG_ON(!can_dirty(cn)); /* if the buffer is prepared, it will either be logged * 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 reiserfs: audit t... |
1663 |
unsigned int *next_trans_id, |
bd4c625c0 reiserfs: run scr... |
1664 1665 1666 1667 1668 |
int num_blocks, int num_trans) { int ret = 0; int written = 0; int transactions_flushed = 0; |
600ed4167 reiserfs: audit t... |
1669 |
unsigned int orig_trans_id = jl->j_trans_id; |
bd4c625c0 reiserfs: run scr... |
1670 1671 1672 1673 |
struct buffer_chunk chunk; struct list_head *entry; struct reiserfs_journal *journal = SB_JOURNAL(s); chunk.nr = 0; |
a412f9efd reiserfs, kill-th... |
1674 |
reiserfs_mutex_lock_safe(&journal->j_flush_mutex, s); |
bd4c625c0 reiserfs: run scr... |
1675 1676 1677 |
if (!journal_list_still_alive(s, orig_trans_id)) { goto done; } |
afe702590 reiserfs: convert... |
1678 |
/* we've got j_flush_mutex held, nobody is going to delete any |
bd4c625c0 reiserfs: run scr... |
1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 |
* 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); } done: |
afe702590 reiserfs: convert... |
1713 |
mutex_unlock(&journal->j_flush_mutex); |
bd4c625c0 reiserfs: run scr... |
1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 |
return ret; } /* 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 |
1da177e4c Linux-2.6.12-rc2 |
1724 1725 1726 |
** list updates the header block */ static int flush_used_journal_lists(struct super_block *s, |
bd4c625c0 reiserfs: run scr... |
1727 1728 1729 1730 1731 1732 1733 1734 1735 |
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 reiserfs: audit t... |
1736 |
unsigned int trans_id; |
bd4c625c0 reiserfs: run scr... |
1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 |
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); } /* 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 */ if (flush_jl != jl) { ret = kupdate_transactions(s, jl, &tjl, &trans_id, len, i); } flush_journal_list(s, flush_jl, 1); return 0; |
1da177e4c Linux-2.6.12-rc2 |
1769 1770 1771 1772 1773 1774 1775 |
} /* ** removes any nodes in table with name block and dev as bh. ** only touchs the hnext and hprev pointers. */ void remove_journal_hash(struct super_block *sb, |
bd4c625c0 reiserfs: run scr... |
1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 |
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; if (cur->bh && cur->jlist) /* anybody who clears the cur->bh will also dec the nonzerolen */ atomic_dec(&(cur->jlist->j_nonzerolen)); cur->bh = NULL; cur->jlist = NULL; } cur = cur->hnext; } } |
a9dd36435 reiserfs: rename ... |
1811 |
static void free_journal_ram(struct super_block *sb) |
bd4c625c0 reiserfs: run scr... |
1812 |
{ |
a9dd36435 reiserfs: rename ... |
1813 |
struct reiserfs_journal *journal = SB_JOURNAL(sb); |
d739b42b8 [PATCH] reiserfs:... |
1814 |
kfree(journal->j_current_jl); |
bd4c625c0 reiserfs: run scr... |
1815 1816 1817 |
journal->j_num_lists--; vfree(journal->j_cnode_free_orig); |
a9dd36435 reiserfs: rename ... |
1818 1819 |
free_list_bitmaps(sb, journal->j_list_bitmap); free_bitmap_nodes(sb); /* must be after free_list_bitmaps */ |
bd4c625c0 reiserfs: run scr... |
1820 1821 1822 1823 1824 1825 |
if (journal->j_header_bh) { brelse(journal->j_header_bh); } /* j_header_bh is on the journal dev, make sure not to release the journal * dev until we brelse j_header_bh */ |
a9dd36435 reiserfs: rename ... |
1826 |
release_journal_dev(sb, journal); |
bd4c625c0 reiserfs: run scr... |
1827 |
vfree(journal); |
1da177e4c Linux-2.6.12-rc2 |
1828 1829 1830 1831 1832 1833 |
} /* ** 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 reiserfs: run scr... |
1834 |
static int do_journal_release(struct reiserfs_transaction_handle *th, |
a9dd36435 reiserfs: rename ... |
1835 |
struct super_block *sb, int error) |
bd4c625c0 reiserfs: run scr... |
1836 1837 1838 |
{ struct reiserfs_transaction_handle myth; int flushed = 0; |
a9dd36435 reiserfs: rename ... |
1839 |
struct reiserfs_journal *journal = SB_JOURNAL(sb); |
bd4c625c0 reiserfs: run scr... |
1840 1841 1842 |
/* we only want to flush out transactions if we were called with error == 0 */ |
a9dd36435 reiserfs: rename ... |
1843 |
if (!error && !(sb->s_flags & MS_RDONLY)) { |
bd4c625c0 reiserfs: run scr... |
1844 1845 |
/* end the current trans */ BUG_ON(!th->t_trans_id); |
a9dd36435 reiserfs: rename ... |
1846 |
do_journal_end(th, sb, 10, FLUSH_ALL); |
bd4c625c0 reiserfs: run scr... |
1847 1848 |
/* make sure something gets logged to force our way into the flush code */ |
a9dd36435 reiserfs: rename ... |
1849 1850 1851 |
if (!journal_join(&myth, sb, 1)) { reiserfs_prepare_for_journal(sb, SB_BUFFER_WITH_SB(sb), |
bd4c625c0 reiserfs: run scr... |
1852 |
1); |
a9dd36435 reiserfs: rename ... |
1853 1854 1855 |
journal_mark_dirty(&myth, sb, SB_BUFFER_WITH_SB(sb)); do_journal_end(&myth, sb, 1, FLUSH_ALL); |
bd4c625c0 reiserfs: run scr... |
1856 1857 1858 1859 1860 1861 1862 |
flushed = 1; } } /* this also catches errors during the do_journal_end above */ if (!error && reiserfs_is_journal_aborted(journal)) { memset(&myth, 0, sizeof(myth)); |
a9dd36435 reiserfs: rename ... |
1863 1864 1865 |
if (!journal_join_abort(&myth, sb, 1)) { reiserfs_prepare_for_journal(sb, SB_BUFFER_WITH_SB(sb), |
bd4c625c0 reiserfs: run scr... |
1866 |
1); |
a9dd36435 reiserfs: rename ... |
1867 1868 1869 |
journal_mark_dirty(&myth, sb, SB_BUFFER_WITH_SB(sb)); do_journal_end(&myth, sb, 1, FLUSH_ALL); |
bd4c625c0 reiserfs: run scr... |
1870 1871 1872 1873 1874 |
} } reiserfs_mounted_fs_count--; /* wait for all commits to finish */ |
a9dd36435 reiserfs: rename ... |
1875 |
cancel_delayed_work(&SB_JOURNAL(sb)->j_work); |
8ebc42323 reiserfs: kill-th... |
1876 1877 1878 1879 1880 1881 |
/* * We must release the write lock here because * the workqueue job (flush_async_commit) needs this lock */ reiserfs_write_unlock(sb); |
bd4c625c0 reiserfs: run scr... |
1882 |
flush_workqueue(commit_wq); |
8ebc42323 reiserfs: kill-th... |
1883 |
|
bd4c625c0 reiserfs: run scr... |
1884 1885 1886 1887 |
if (!reiserfs_mounted_fs_count) { destroy_workqueue(commit_wq); commit_wq = NULL; } |
a9dd36435 reiserfs: rename ... |
1888 |
free_journal_ram(sb); |
bd4c625c0 reiserfs: run scr... |
1889 |
|
0523676d3 reiserfs: Relax r... |
1890 |
reiserfs_write_lock(sb); |
bd4c625c0 reiserfs: run scr... |
1891 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
1892 1893 1894 1895 1896 |
} /* ** call on unmount. flush all journal trans, release all alloc'd ram */ |
bd4c625c0 reiserfs: run scr... |
1897 |
int journal_release(struct reiserfs_transaction_handle *th, |
a9dd36435 reiserfs: rename ... |
1898 |
struct super_block *sb) |
bd4c625c0 reiserfs: run scr... |
1899 |
{ |
a9dd36435 reiserfs: rename ... |
1900 |
return do_journal_release(th, sb, 0); |
1da177e4c Linux-2.6.12-rc2 |
1901 |
} |
bd4c625c0 reiserfs: run scr... |
1902 |
|
1da177e4c Linux-2.6.12-rc2 |
1903 1904 1905 |
/* ** only call from an error condition inside reiserfs_read_super! */ |
bd4c625c0 reiserfs: run scr... |
1906 |
int journal_release_error(struct reiserfs_transaction_handle *th, |
a9dd36435 reiserfs: rename ... |
1907 |
struct super_block *sb) |
bd4c625c0 reiserfs: run scr... |
1908 |
{ |
a9dd36435 reiserfs: rename ... |
1909 |
return do_journal_release(th, sb, 1); |
1da177e4c Linux-2.6.12-rc2 |
1910 1911 1912 |
} /* compares description block with commit block. returns 1 if they differ, 0 if they are the same */ |
a9dd36435 reiserfs: rename ... |
1913 |
static int journal_compare_desc_commit(struct super_block *sb, |
bd4c625c0 reiserfs: run scr... |
1914 1915 1916 1917 1918 |
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 reiserfs: rename ... |
1919 |
get_commit_trans_len(commit) > SB_JOURNAL(sb)->j_trans_max || |
bd4c625c0 reiserfs: run scr... |
1920 1921 1922 1923 |
get_commit_trans_len(commit) <= 0) { return 1; } return 0; |
1da177e4c Linux-2.6.12-rc2 |
1924 |
} |
bd4c625c0 reiserfs: run scr... |
1925 |
|
0222e6571 reiserfs: strip t... |
1926 |
/* returns 0 if it did not find a description block |
1da177e4c Linux-2.6.12-rc2 |
1927 |
** returns -1 if it found a corrupt commit block |
0222e6571 reiserfs: strip t... |
1928 |
** returns 1 if both desc and commit were valid |
1da177e4c Linux-2.6.12-rc2 |
1929 |
*/ |
a9dd36435 reiserfs: rename ... |
1930 |
static int journal_transaction_is_valid(struct super_block *sb, |
bd4c625c0 reiserfs: run scr... |
1931 |
struct buffer_head *d_bh, |
600ed4167 reiserfs: audit t... |
1932 |
unsigned int *oldest_invalid_trans_id, |
bd4c625c0 reiserfs: run scr... |
1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 |
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 reiserfs: rename ... |
1948 |
reiserfs_debug(sb, REISERFS_DEBUG_CODE, |
bd4c625c0 reiserfs: run scr... |
1949 1950 1951 1952 1953 1954 1955 1956 1957 |
"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 reiserfs: rename ... |
1958 |
reiserfs_debug(sb, REISERFS_DEBUG_CODE, |
bd4c625c0 reiserfs: run scr... |
1959 1960 1961 1962 1963 1964 1965 |
"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 reiserfs: rename ... |
1966 1967 |
if (get_desc_trans_len(desc) > SB_JOURNAL(sb)->j_trans_max) { reiserfs_warning(sb, "journal-2018", |
45b03d5e8 reiserfs: rework ... |
1968 1969 |
"Bad transaction length %d " "encountered, ignoring transaction", |
bd4c625c0 reiserfs: run scr... |
1970 1971 1972 |
get_desc_trans_len(desc)); return -1; } |
a9dd36435 reiserfs: rename ... |
1973 |
offset = d_bh->b_blocknr - SB_ONDISK_JOURNAL_1st_BLOCK(sb); |
bd4c625c0 reiserfs: run scr... |
1974 1975 1976 |
/* ok, we have a journal description block, lets see if the transaction was valid */ c_bh = |
a9dd36435 reiserfs: rename ... |
1977 1978 |
journal_bread(sb, SB_ONDISK_JOURNAL_1st_BLOCK(sb) + |
bd4c625c0 reiserfs: run scr... |
1979 |
((offset + get_desc_trans_len(desc) + |
a9dd36435 reiserfs: rename ... |
1980 |
1) % SB_ONDISK_JOURNAL_SIZE(sb))); |
bd4c625c0 reiserfs: run scr... |
1981 1982 1983 |
if (!c_bh) return 0; commit = (struct reiserfs_journal_commit *)c_bh->b_data; |
a9dd36435 reiserfs: rename ... |
1984 1985 |
if (journal_compare_desc_commit(sb, desc, commit)) { reiserfs_debug(sb, REISERFS_DEBUG_CODE, |
bd4c625c0 reiserfs: run scr... |
1986 1987 1988 |
"journal_transaction_is_valid, commit offset %ld had bad " "time %d or length %d", c_bh->b_blocknr - |
a9dd36435 reiserfs: rename ... |
1989 |
SB_ONDISK_JOURNAL_1st_BLOCK(sb), |
bd4c625c0 reiserfs: run scr... |
1990 1991 1992 1993 1994 1995 |
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 reiserfs: rename ... |
1996 |
reiserfs_debug(sb, REISERFS_DEBUG_CODE, |
bd4c625c0 reiserfs: run scr... |
1997 1998 1999 2000 2001 2002 2003 2004 |
"journal-1004: " "transaction_is_valid setting oldest invalid trans_id " "to %d", get_desc_trans_id(desc)); } return -1; } brelse(c_bh); |
a9dd36435 reiserfs: rename ... |
2005 |
reiserfs_debug(sb, REISERFS_DEBUG_CODE, |
bd4c625c0 reiserfs: run scr... |
2006 2007 2008 |
"journal-1006: found valid " "transaction start offset %llu, len %d id %d", d_bh->b_blocknr - |
a9dd36435 reiserfs: rename ... |
2009 |
SB_ONDISK_JOURNAL_1st_BLOCK(sb), |
bd4c625c0 reiserfs: run scr... |
2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 |
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 Linux-2.6.12-rc2 |
2024 2025 2026 2027 2028 2029 2030 |
} /* ** 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. */ |
a9dd36435 reiserfs: rename ... |
2031 |
static int journal_read_transaction(struct super_block *sb, |
bd4c625c0 reiserfs: run scr... |
2032 2033 |
unsigned long cur_dblock, unsigned long oldest_start, |
600ed4167 reiserfs: audit t... |
2034 |
unsigned int oldest_trans_id, |
bd4c625c0 reiserfs: run scr... |
2035 2036 |
unsigned long newest_mount_id) { |
a9dd36435 reiserfs: rename ... |
2037 |
struct reiserfs_journal *journal = SB_JOURNAL(sb); |
bd4c625c0 reiserfs: run scr... |
2038 2039 |
struct reiserfs_journal_desc *desc; struct reiserfs_journal_commit *commit; |
600ed4167 reiserfs: audit t... |
2040 |
unsigned int trans_id = 0; |
bd4c625c0 reiserfs: run scr... |
2041 2042 2043 2044 |
struct buffer_head *c_bh; struct buffer_head *d_bh; struct buffer_head **log_blocks = NULL; struct buffer_head **real_blocks = NULL; |
600ed4167 reiserfs: audit t... |
2045 |
unsigned int trans_offset; |
bd4c625c0 reiserfs: run scr... |
2046 2047 |
int i; int trans_half; |
a9dd36435 reiserfs: rename ... |
2048 |
d_bh = journal_bread(sb, cur_dblock); |
bd4c625c0 reiserfs: run scr... |
2049 2050 2051 |
if (!d_bh) return 1; desc = (struct reiserfs_journal_desc *)d_bh->b_data; |
a9dd36435 reiserfs: rename ... |
2052 2053 |
trans_offset = d_bh->b_blocknr - SB_ONDISK_JOURNAL_1st_BLOCK(sb); reiserfs_debug(sb, REISERFS_DEBUG_CODE, "journal-1037: " |
bd4c625c0 reiserfs: run scr... |
2054 |
"journal_read_transaction, offset %llu, len %d mount_id %d", |
a9dd36435 reiserfs: rename ... |
2055 |
d_bh->b_blocknr - SB_ONDISK_JOURNAL_1st_BLOCK(sb), |
bd4c625c0 reiserfs: run scr... |
2056 2057 |
get_desc_trans_len(desc), get_desc_mount_id(desc)); if (get_desc_trans_id(desc) < oldest_trans_id) { |
a9dd36435 reiserfs: rename ... |
2058 |
reiserfs_debug(sb, REISERFS_DEBUG_CODE, "journal-1039: " |
bd4c625c0 reiserfs: run scr... |
2059 2060 |
"journal_read_trans skipping because %lu is too old", cur_dblock - |
a9dd36435 reiserfs: rename ... |
2061 |
SB_ONDISK_JOURNAL_1st_BLOCK(sb)); |
bd4c625c0 reiserfs: run scr... |
2062 2063 2064 2065 |
brelse(d_bh); return 1; } if (get_desc_mount_id(desc) != newest_mount_id) { |
a9dd36435 reiserfs: rename ... |
2066 |
reiserfs_debug(sb, REISERFS_DEBUG_CODE, "journal-1146: " |
bd4c625c0 reiserfs: run scr... |
2067 2068 2069 2070 2071 2072 |
"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 reiserfs: rename ... |
2073 |
c_bh = journal_bread(sb, SB_ONDISK_JOURNAL_1st_BLOCK(sb) + |
bd4c625c0 reiserfs: run scr... |
2074 |
((trans_offset + get_desc_trans_len(desc) + 1) % |
a9dd36435 reiserfs: rename ... |
2075 |
SB_ONDISK_JOURNAL_SIZE(sb))); |
bd4c625c0 reiserfs: run scr... |
2076 2077 2078 2079 2080 |
if (!c_bh) { brelse(d_bh); return 1; } commit = (struct reiserfs_journal_commit *)c_bh->b_data; |
a9dd36435 reiserfs: rename ... |
2081 2082 |
if (journal_compare_desc_commit(sb, desc, commit)) { reiserfs_debug(sb, REISERFS_DEBUG_CODE, |
bd4c625c0 reiserfs: run scr... |
2083 2084 2085 |
"journal_read_transaction, " "commit offset %llu had bad time %d or length %d", c_bh->b_blocknr - |
a9dd36435 reiserfs: rename ... |
2086 |
SB_ONDISK_JOURNAL_1st_BLOCK(sb), |
bd4c625c0 reiserfs: run scr... |
2087 2088 2089 2090 2091 2092 |
get_commit_trans_id(commit), get_commit_trans_len(commit)); brelse(c_bh); brelse(d_bh); return 1; } |
3f8b5ee33 reiserfs: properl... |
2093 2094 2095 2096 2097 2098 2099 2100 |
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 reiserfs: run scr... |
2101 2102 |
trans_id = get_desc_trans_id(desc); /* now we know we've got a good transaction, and it was inside the valid time ranges */ |
d739b42b8 [PATCH] reiserfs:... |
2103 2104 2105 2106 |
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 reiserfs: run scr... |
2107 2108 2109 |
if (!log_blocks || !real_blocks) { brelse(c_bh); brelse(d_bh); |
d739b42b8 [PATCH] reiserfs:... |
2110 2111 |
kfree(log_blocks); kfree(real_blocks); |
a9dd36435 reiserfs: rename ... |
2112 |
reiserfs_warning(sb, "journal-1169", |
45b03d5e8 reiserfs: rework ... |
2113 |
"kmalloc failed, unable to mount FS"); |
bd4c625c0 reiserfs: run scr... |
2114 2115 2116 |
return -1; } /* get all the buffer heads */ |
a9dd36435 reiserfs: rename ... |
2117 |
trans_half = journal_trans_half(sb->s_blocksize); |
bd4c625c0 reiserfs: run scr... |
2118 2119 |
for (i = 0; i < get_desc_trans_len(desc); i++) { log_blocks[i] = |
a9dd36435 reiserfs: rename ... |
2120 2121 |
journal_getblk(sb, SB_ONDISK_JOURNAL_1st_BLOCK(sb) + |
bd4c625c0 reiserfs: run scr... |
2122 |
(trans_offset + 1 + |
a9dd36435 reiserfs: rename ... |
2123 |
i) % SB_ONDISK_JOURNAL_SIZE(sb)); |
bd4c625c0 reiserfs: run scr... |
2124 2125 |
if (i < trans_half) { real_blocks[i] = |
a9dd36435 reiserfs: rename ... |
2126 |
sb_getblk(sb, |
bd4c625c0 reiserfs: run scr... |
2127 2128 2129 |
le32_to_cpu(desc->j_realblock[i])); } else { real_blocks[i] = |
a9dd36435 reiserfs: rename ... |
2130 |
sb_getblk(sb, |
bd4c625c0 reiserfs: run scr... |
2131 2132 2133 |
le32_to_cpu(commit-> j_realblock[i - trans_half])); } |
a9dd36435 reiserfs: rename ... |
2134 2135 |
if (real_blocks[i]->b_blocknr > SB_BLOCK_COUNT(sb)) { reiserfs_warning(sb, "journal-1207", |
45b03d5e8 reiserfs: rework ... |
2136 2137 2138 |
"REPLAY FAILURE fsck required! " "Block to replay is outside of " "filesystem"); |
bd4c625c0 reiserfs: run scr... |
2139 2140 2141 2142 |
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 reiserfs: rename ... |
2143 2144 |
(sb, real_blocks[i]->b_blocknr)) { reiserfs_warning(sb, "journal-1204", |
45b03d5e8 reiserfs: rework ... |
2145 2146 |
"REPLAY FAILURE fsck required! " "Trying to replay onto a log block"); |
bd4c625c0 reiserfs: run scr... |
2147 2148 2149 2150 2151 |
abort_replay: brelse_array(log_blocks, i); brelse_array(real_blocks, i); brelse(c_bh); brelse(d_bh); |
d739b42b8 [PATCH] reiserfs:... |
2152 2153 |
kfree(log_blocks); kfree(real_blocks); |
bd4c625c0 reiserfs: run scr... |
2154 2155 2156 2157 2158 2159 |
return -1; } } /* read in the log blocks, memcpy to the corresponding real block */ ll_rw_block(READ, get_desc_trans_len(desc), log_blocks); for (i = 0; i < get_desc_trans_len(desc); i++) { |
8ebc42323 reiserfs: kill-th... |
2160 2161 |
reiserfs_write_unlock(sb); |
bd4c625c0 reiserfs: run scr... |
2162 |
wait_on_buffer(log_blocks[i]); |
8ebc42323 reiserfs: kill-th... |
2163 |
reiserfs_write_lock(sb); |
bd4c625c0 reiserfs: run scr... |
2164 |
if (!buffer_uptodate(log_blocks[i])) { |
a9dd36435 reiserfs: rename ... |
2165 |
reiserfs_warning(sb, "journal-1212", |
45b03d5e8 reiserfs: rework ... |
2166 2167 |
"REPLAY FAILURE fsck required! " "buffer write failed"); |
bd4c625c0 reiserfs: run scr... |
2168 2169 2170 2171 2172 |
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 [PATCH] reiserfs:... |
2173 2174 |
kfree(log_blocks); kfree(real_blocks); |
bd4c625c0 reiserfs: run scr... |
2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 |
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]); |
9cb569d60 remove SWRITE* I/... |
2185 |
write_dirty_buffer(real_blocks[i], WRITE); |
bd4c625c0 reiserfs: run scr... |
2186 2187 2188 2189 |
} for (i = 0; i < get_desc_trans_len(desc); i++) { wait_on_buffer(real_blocks[i]); if (!buffer_uptodate(real_blocks[i])) { |
a9dd36435 reiserfs: rename ... |
2190 |
reiserfs_warning(sb, "journal-1226", |
45b03d5e8 reiserfs: rework ... |
2191 2192 |
"REPLAY FAILURE, fsck required! " "buffer write failed"); |
bd4c625c0 reiserfs: run scr... |
2193 2194 2195 2196 |
brelse_array(real_blocks + i, get_desc_trans_len(desc) - i); brelse(c_bh); brelse(d_bh); |
d739b42b8 [PATCH] reiserfs:... |
2197 2198 |
kfree(log_blocks); kfree(real_blocks); |
bd4c625c0 reiserfs: run scr... |
2199 2200 2201 2202 2203 |
return -1; } brelse(real_blocks[i]); } cur_dblock = |
a9dd36435 reiserfs: rename ... |
2204 |
SB_ONDISK_JOURNAL_1st_BLOCK(sb) + |
bd4c625c0 reiserfs: run scr... |
2205 |
((trans_offset + get_desc_trans_len(desc) + |
a9dd36435 reiserfs: rename ... |
2206 2207 |
2) % SB_ONDISK_JOURNAL_SIZE(sb)); reiserfs_debug(sb, REISERFS_DEBUG_CODE, |
bd4c625c0 reiserfs: run scr... |
2208 |
"journal-1095: setting journal " "start to offset %ld", |
a9dd36435 reiserfs: rename ... |
2209 |
cur_dblock - SB_ONDISK_JOURNAL_1st_BLOCK(sb)); |
bd4c625c0 reiserfs: run scr... |
2210 2211 |
/* init starting values for the first transaction, in case this is the last transaction to be replayed. */ |
a9dd36435 reiserfs: rename ... |
2212 |
journal->j_start = cur_dblock - SB_ONDISK_JOURNAL_1st_BLOCK(sb); |
bd4c625c0 reiserfs: run scr... |
2213 2214 |
journal->j_last_flush_trans_id = trans_id; journal->j_trans_id = trans_id + 1; |
a44c94a7b [PATCH] reiserfs:... |
2215 2216 2217 |
/* check for trans_id overflow */ if (journal->j_trans_id == 0) journal->j_trans_id = 10; |
bd4c625c0 reiserfs: run scr... |
2218 2219 |
brelse(c_bh); brelse(d_bh); |
d739b42b8 [PATCH] reiserfs:... |
2220 2221 |
kfree(log_blocks); kfree(real_blocks); |
bd4c625c0 reiserfs: run scr... |
2222 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
2223 2224 2225 2226 2227 2228 2229 2230 |
} /* 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 reiserfs: fix usa... |
2231 2232 2233 |
static struct buffer_head *reiserfs_breada(struct block_device *dev, b_blocknr_t block, int bufsize, b_blocknr_t max_block) |
1da177e4c Linux-2.6.12-rc2 |
2234 |
{ |
bd4c625c0 reiserfs: run scr... |
2235 |
struct buffer_head *bhlist[BUFNR]; |
1da177e4c Linux-2.6.12-rc2 |
2236 |
unsigned int blocks = BUFNR; |
bd4c625c0 reiserfs: run scr... |
2237 |
struct buffer_head *bh; |
1da177e4c Linux-2.6.12-rc2 |
2238 |
int i, j; |
bd4c625c0 reiserfs: run scr... |
2239 2240 2241 2242 |
bh = __getblk(dev, block, bufsize); if (buffer_uptodate(bh)) return (bh); |
1da177e4c Linux-2.6.12-rc2 |
2243 2244 2245 2246 2247 2248 |
if (block + BUFNR > max_block) { blocks = max_block - block; } bhlist[0] = bh; j = 1; for (i = 1; i < blocks; i++) { |
bd4c625c0 reiserfs: run scr... |
2249 2250 2251 |
bh = __getblk(dev, block + i, bufsize); if (buffer_uptodate(bh)) { brelse(bh); |
1da177e4c Linux-2.6.12-rc2 |
2252 |
break; |
bd4c625c0 reiserfs: run scr... |
2253 2254 |
} else bhlist[j++] = bh; |
1da177e4c Linux-2.6.12-rc2 |
2255 |
} |
bd4c625c0 reiserfs: run scr... |
2256 2257 2258 |
ll_rw_block(READ, j, bhlist); for (i = 1; i < j; i++) brelse(bhlist[i]); |
1da177e4c Linux-2.6.12-rc2 |
2259 |
bh = bhlist[0]; |
bd4c625c0 reiserfs: run scr... |
2260 2261 |
wait_on_buffer(bh); if (buffer_uptodate(bh)) |
1da177e4c Linux-2.6.12-rc2 |
2262 |
return bh; |
bd4c625c0 reiserfs: run scr... |
2263 |
brelse(bh); |
1da177e4c Linux-2.6.12-rc2 |
2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 |
return NULL; } /* ** 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. */ |
a9dd36435 reiserfs: rename ... |
2276 |
static int journal_read(struct super_block *sb) |
bd4c625c0 reiserfs: run scr... |
2277 |
{ |
a9dd36435 reiserfs: rename ... |
2278 |
struct reiserfs_journal *journal = SB_JOURNAL(sb); |
bd4c625c0 reiserfs: run scr... |
2279 |
struct reiserfs_journal_desc *desc; |
600ed4167 reiserfs: audit t... |
2280 2281 |
unsigned int oldest_trans_id = 0; unsigned int oldest_invalid_trans_id = 0; |
bd4c625c0 reiserfs: run scr... |
2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 |
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; char b[BDEVNAME_SIZE]; |
a9dd36435 reiserfs: rename ... |
2293 2294 2295 |
cur_dblock = SB_ONDISK_JOURNAL_1st_BLOCK(sb); reiserfs_info(sb, "checking transaction log (%s) ", |
bd4c625c0 reiserfs: run scr... |
2296 2297 |
bdevname(journal->j_dev_bd, b)); start = get_seconds(); |
0222e6571 reiserfs: strip t... |
2298 2299 |
/* step 1, read in the journal header block. Check the transaction it says ** is the first unflushed, and if that transaction is not valid, |
bd4c625c0 reiserfs: run scr... |
2300 2301 |
** replay is done */ |
a9dd36435 reiserfs: rename ... |
2302 2303 2304 |
journal->j_header_bh = journal_bread(sb, SB_ONDISK_JOURNAL_1st_BLOCK(sb) + SB_ONDISK_JOURNAL_SIZE(sb)); |
bd4c625c0 reiserfs: run scr... |
2305 2306 2307 2308 |
if (!journal->j_header_bh) { return 1; } jh = (struct reiserfs_journal_header *)(journal->j_header_bh->b_data); |
c499ec24c [PATCH] reiserfs:... |
2309 |
if (le32_to_cpu(jh->j_first_unflushed_offset) < |
a9dd36435 reiserfs: rename ... |
2310 |
SB_ONDISK_JOURNAL_SIZE(sb) |
bd4c625c0 reiserfs: run scr... |
2311 2312 |
&& le32_to_cpu(jh->j_last_flush_trans_id) > 0) { oldest_start = |
a9dd36435 reiserfs: rename ... |
2313 |
SB_ONDISK_JOURNAL_1st_BLOCK(sb) + |
bd4c625c0 reiserfs: run scr... |
2314 2315 2316 |
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 reiserfs: rename ... |
2317 |
reiserfs_debug(sb, REISERFS_DEBUG_CODE, |
bd4c625c0 reiserfs: run scr... |
2318 2319 2320 2321 2322 |
"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; |
0222e6571 reiserfs: strip t... |
2323 2324 |
/* 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 |
bd4c625c0 reiserfs: run scr... |
2325 2326 2327 |
** through the whole log. */ d_bh = |
a9dd36435 reiserfs: rename ... |
2328 2329 |
journal_bread(sb, SB_ONDISK_JOURNAL_1st_BLOCK(sb) + |
bd4c625c0 reiserfs: run scr... |
2330 |
le32_to_cpu(jh->j_first_unflushed_offset)); |
a9dd36435 reiserfs: rename ... |
2331 |
ret = journal_transaction_is_valid(sb, d_bh, NULL, NULL); |
bd4c625c0 reiserfs: run scr... |
2332 2333 2334 2335 2336 2337 |
if (!ret) { continue_replay = 0; } brelse(d_bh); goto start_log_replay; } |
bd4c625c0 reiserfs: run scr... |
2338 2339 2340 2341 2342 |
/* 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. */ while (continue_replay && cur_dblock < |
a9dd36435 reiserfs: rename ... |
2343 2344 |
(SB_ONDISK_JOURNAL_1st_BLOCK(sb) + SB_ONDISK_JOURNAL_SIZE(sb))) { |
bd4c625c0 reiserfs: run scr... |
2345 2346 2347 2348 |
/* Note that it is required for blocksize of primary fs device and journal device to be the same */ d_bh = reiserfs_breada(journal->j_dev_bd, cur_dblock, |
a9dd36435 reiserfs: rename ... |
2349 2350 2351 |
sb->s_blocksize, SB_ONDISK_JOURNAL_1st_BLOCK(sb) + SB_ONDISK_JOURNAL_SIZE(sb)); |
bd4c625c0 reiserfs: run scr... |
2352 |
ret = |
a9dd36435 reiserfs: rename ... |
2353 |
journal_transaction_is_valid(sb, d_bh, |
bd4c625c0 reiserfs: run scr... |
2354 2355 2356 2357 2358 2359 2360 2361 |
&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 reiserfs: rename ... |
2362 |
reiserfs_debug(sb, REISERFS_DEBUG_CODE, |
bd4c625c0 reiserfs: run scr... |
2363 2364 2365 2366 |
"journal-1179: Setting " "oldest_start to offset %llu, trans_id %lu", oldest_start - SB_ONDISK_JOURNAL_1st_BLOCK |
a9dd36435 reiserfs: rename ... |
2367 |
(sb), oldest_trans_id); |
bd4c625c0 reiserfs: run scr... |
2368 2369 2370 2371 |
} 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 reiserfs: rename ... |
2372 |
reiserfs_debug(sb, REISERFS_DEBUG_CODE, |
bd4c625c0 reiserfs: run scr... |
2373 2374 2375 2376 |
"journal-1180: Resetting " "oldest_start to offset %lu, trans_id %lu", oldest_start - SB_ONDISK_JOURNAL_1st_BLOCK |
a9dd36435 reiserfs: rename ... |
2377 |
(sb), oldest_trans_id); |
bd4c625c0 reiserfs: run scr... |
2378 2379 2380 |
} if (newest_mount_id < get_desc_mount_id(desc)) { newest_mount_id = get_desc_mount_id(desc); |
a9dd36435 reiserfs: rename ... |
2381 |
reiserfs_debug(sb, REISERFS_DEBUG_CODE, |
bd4c625c0 reiserfs: run scr... |
2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 |
"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); } start_log_replay: cur_dblock = oldest_start; if (oldest_trans_id) { |
a9dd36435 reiserfs: rename ... |
2396 |
reiserfs_debug(sb, REISERFS_DEBUG_CODE, |
bd4c625c0 reiserfs: run scr... |
2397 2398 |
"journal-1206: Starting replay " "from offset %llu, trans_id %lu", |
a9dd36435 reiserfs: rename ... |
2399 |
cur_dblock - SB_ONDISK_JOURNAL_1st_BLOCK(sb), |
bd4c625c0 reiserfs: run scr... |
2400 2401 2402 2403 2404 2405 |
oldest_trans_id); } replay_count = 0; while (continue_replay && oldest_trans_id > 0) { ret = |
a9dd36435 reiserfs: rename ... |
2406 |
journal_read_transaction(sb, cur_dblock, oldest_start, |
bd4c625c0 reiserfs: run scr... |
2407 2408 2409 2410 2411 2412 2413 |
oldest_trans_id, newest_mount_id); if (ret < 0) { return ret; } else if (ret != 0) { break; } cur_dblock = |
a9dd36435 reiserfs: rename ... |
2414 |
SB_ONDISK_JOURNAL_1st_BLOCK(sb) + journal->j_start; |
bd4c625c0 reiserfs: run scr... |
2415 2416 2417 2418 2419 2420 |
replay_count++; if (cur_dblock == oldest_start) break; } if (oldest_trans_id == 0) { |
a9dd36435 reiserfs: rename ... |
2421 |
reiserfs_debug(sb, REISERFS_DEBUG_CODE, |
bd4c625c0 reiserfs: run scr... |
2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 |
"journal-1225: No valid " "transactions found"); } /* 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 */ 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 [PATCH] reiserfs:... |
2432 2433 2434 |
/* check for trans_id overflow */ if (journal->j_trans_id == 0) journal->j_trans_id = 10; |
bd4c625c0 reiserfs: run scr... |
2435 2436 2437 2438 2439 2440 |
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 reiserfs: rename ... |
2441 |
reiserfs_debug(sb, REISERFS_DEBUG_CODE, "journal-1299: Setting " |
bd4c625c0 reiserfs: run scr... |
2442 2443 2444 |
"newest_mount_id to %lu", journal->j_mount_id); journal->j_first_unflushed_offset = journal->j_start; if (replay_count > 0) { |
a9dd36435 reiserfs: rename ... |
2445 |
reiserfs_info(sb, |
bd4c625c0 reiserfs: run scr... |
2446 2447 2448 2449 |
"replayed %d transactions in %lu seconds ", replay_count, get_seconds() - start); } |
a9dd36435 reiserfs: rename ... |
2450 2451 |
if (!bdev_read_only(sb->s_bdev) && _update_journal_header_block(sb, journal->j_start, |
bd4c625c0 reiserfs: run scr... |
2452 2453 2454 2455 2456 2457 2458 |
journal->j_last_flush_trans_id)) { /* replay failed, caller must call free_journal_ram and abort ** the mount */ return -1; } return 0; |
1da177e4c Linux-2.6.12-rc2 |
2459 2460 2461 2462 |
} static struct reiserfs_journal_list *alloc_journal_list(struct super_block *s) { |
bd4c625c0 reiserfs: run scr... |
2463 |
struct reiserfs_journal_list *jl; |
8c777cc4b [PATCH] reiserfs:... |
2464 2465 |
jl = kzalloc(sizeof(struct reiserfs_journal_list), GFP_NOFS | __GFP_NOFAIL); |
bd4c625c0 reiserfs: run scr... |
2466 2467 2468 2469 |
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 reiserfs: convert... |
2470 |
mutex_init(&jl->j_commit_mutex); |
bd4c625c0 reiserfs: run scr... |
2471 2472 2473 2474 |
SB_JOURNAL(s)->j_num_lists++; get_journal_list(jl); return jl; } |
a9dd36435 reiserfs: rename ... |
2475 |
static void journal_list_init(struct super_block *sb) |
bd4c625c0 reiserfs: run scr... |
2476 |
{ |
a9dd36435 reiserfs: rename ... |
2477 |
SB_JOURNAL(sb)->j_current_jl = alloc_journal_list(sb); |
bd4c625c0 reiserfs: run scr... |
2478 2479 2480 2481 2482 2483 2484 2485 |
} static int release_journal_dev(struct super_block *super, struct reiserfs_journal *journal) { int result; result = 0; |
86098fa01 reiserfs: use ope... |
2486 |
if (journal->j_dev_bd != NULL) { |
e5eb8caa8 [PATCH] remember ... |
2487 |
result = blkdev_put(journal->j_dev_bd, journal->j_dev_mode); |
bd4c625c0 reiserfs: run scr... |
2488 2489 2490 2491 |
journal->j_dev_bd = NULL; } if (result != 0) { |
45b03d5e8 reiserfs: rework ... |
2492 2493 |
reiserfs_warning(super, "sh-457", "Cannot release journal device: %i", result); |
bd4c625c0 reiserfs: run scr... |
2494 2495 2496 2497 2498 2499 2500 |
} return result; } static int journal_init_dev(struct super_block *super, struct reiserfs_journal *journal, const char *jdev_name) |
1da177e4c Linux-2.6.12-rc2 |
2501 2502 2503 |
{ int result; dev_t jdev; |
e525fd89d block: make blkde... |
2504 |
fmode_t blkdev_mode = FMODE_READ | FMODE_WRITE | FMODE_EXCL; |
1da177e4c Linux-2.6.12-rc2 |
2505 2506 2507 |
char b[BDEVNAME_SIZE]; result = 0; |
bd4c625c0 reiserfs: run scr... |
2508 |
journal->j_dev_bd = NULL; |
bd4c625c0 reiserfs: run scr... |
2509 2510 |
jdev = SB_ONDISK_JOURNAL_DEVICE(super) ? new_decode_dev(SB_ONDISK_JOURNAL_DEVICE(super)) : super->s_dev; |
1da177e4c Linux-2.6.12-rc2 |
2511 2512 |
if (bdev_read_only(super->s_bdev)) |
bd4c625c0 reiserfs: run scr... |
2513 |
blkdev_mode = FMODE_READ; |
1da177e4c Linux-2.6.12-rc2 |
2514 2515 |
/* there is no "jdev" option and journal is on separate device */ |
bd4c625c0 reiserfs: run scr... |
2516 |
if ((!jdev_name || !jdev_name[0])) { |
e525fd89d block: make blkde... |
2517 2518 |
if (jdev == super->s_dev) blkdev_mode &= ~FMODE_EXCL; |
d4d776299 block: clean up b... |
2519 2520 |
journal->j_dev_bd = blkdev_get_by_dev(jdev, blkdev_mode, journal); |
e5eb8caa8 [PATCH] remember ... |
2521 |
journal->j_dev_mode = blkdev_mode; |
1da177e4c Linux-2.6.12-rc2 |
2522 2523 2524 |
if (IS_ERR(journal->j_dev_bd)) { result = PTR_ERR(journal->j_dev_bd); journal->j_dev_bd = NULL; |
45b03d5e8 reiserfs: rework ... |
2525 |
reiserfs_warning(super, "sh-458", |
bd4c625c0 reiserfs: run scr... |
2526 2527 |
"cannot init journal device '%s': %i", __bdevname(jdev, b), result); |
1da177e4c Linux-2.6.12-rc2 |
2528 |
return result; |
e525fd89d block: make blkde... |
2529 |
} else if (jdev != super->s_dev) |
1da177e4c Linux-2.6.12-rc2 |
2530 |
set_blocksize(journal->j_dev_bd, super->s_blocksize); |
86098fa01 reiserfs: use ope... |
2531 |
|
1da177e4c Linux-2.6.12-rc2 |
2532 2533 |
return 0; } |
e5eb8caa8 [PATCH] remember ... |
2534 |
journal->j_dev_mode = blkdev_mode; |
d4d776299 block: clean up b... |
2535 |
journal->j_dev_bd = blkdev_get_by_path(jdev_name, blkdev_mode, journal); |
86098fa01 reiserfs: use ope... |
2536 2537 2538 |
if (IS_ERR(journal->j_dev_bd)) { result = PTR_ERR(journal->j_dev_bd); journal->j_dev_bd = NULL; |
bd4c625c0 reiserfs: run scr... |
2539 2540 2541 |
reiserfs_warning(super, "journal_init_dev: Cannot open '%s': %i", jdev_name, result); |
86098fa01 reiserfs: use ope... |
2542 |
return result; |
1da177e4c Linux-2.6.12-rc2 |
2543 |
} |
86098fa01 reiserfs: use ope... |
2544 2545 2546 2547 2548 2549 2550 |
set_blocksize(journal->j_dev_bd, super->s_blocksize); reiserfs_info(super, "journal_init_dev: journal device: %s ", bdevname(journal->j_dev_bd, b)); return 0; |
1da177e4c Linux-2.6.12-rc2 |
2551 |
} |
cf3d0b818 reiserfs: do not ... |
2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 |
/** * 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 reiserfs: rename ... |
2565 |
static int check_advise_trans_params(struct super_block *sb, |
cf3d0b818 reiserfs: do not ... |
2566 2567 2568 2569 2570 2571 |
struct reiserfs_journal *journal) { if (journal->j_trans_max) { /* Non-default journal params. Do sanity check for them. */ int ratio = 1; |
a9dd36435 reiserfs: rename ... |
2572 2573 |
if (sb->s_blocksize < REISERFS_STANDARD_BLKSIZE) ratio = REISERFS_STANDARD_BLKSIZE / sb->s_blocksize; |
cf3d0b818 reiserfs: do not ... |
2574 2575 2576 |
if (journal->j_trans_max > JOURNAL_TRANS_MAX_DEFAULT / ratio || journal->j_trans_max < JOURNAL_TRANS_MIN_DEFAULT / ratio || |
a9dd36435 reiserfs: rename ... |
2577 |
SB_ONDISK_JOURNAL_SIZE(sb) / journal->j_trans_max < |
cf3d0b818 reiserfs: do not ... |
2578 |
JOURNAL_MIN_RATIO) { |
a9dd36435 reiserfs: rename ... |
2579 |
reiserfs_warning(sb, "sh-462", |
45b03d5e8 reiserfs: rework ... |
2580 2581 |
"bad transaction max size (%u). " "FSCK?", journal->j_trans_max); |
cf3d0b818 reiserfs: do not ... |
2582 2583 2584 2585 |
return 1; } if (journal->j_max_batch != (journal->j_trans_max) * JOURNAL_MAX_BATCH_DEFAULT/JOURNAL_TRANS_MAX_DEFAULT) { |
a9dd36435 reiserfs: rename ... |
2586 |
reiserfs_warning(sb, "sh-463", |
45b03d5e8 reiserfs: rework ... |
2587 2588 |
"bad transaction max batch (%u). " "FSCK?", journal->j_max_batch); |
cf3d0b818 reiserfs: do not ... |
2589 2590 2591 2592 2593 2594 2595 |
return 1; } } else { /* 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 reiserfs: rename ... |
2596 2597 2598 |
if (sb->s_blocksize != REISERFS_STANDARD_BLKSIZE) { reiserfs_warning(sb, "sh-464", "bad blocksize (%u)", sb->s_blocksize); |
45b03d5e8 reiserfs: rework ... |
2599 2600 |
return 1; } |
cf3d0b818 reiserfs: do not ... |
2601 2602 2603 2604 2605 2606 |
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; } |
1da177e4c Linux-2.6.12-rc2 |
2607 2608 2609 |
/* ** must be called once on fs mount. calls journal_read for you */ |
a9dd36435 reiserfs: rename ... |
2610 |
int journal_init(struct super_block *sb, const char *j_dev_name, |
bd4c625c0 reiserfs: run scr... |
2611 2612 |
int old_format, unsigned int commit_max_age) { |
a9dd36435 reiserfs: rename ... |
2613 |
int num_cnodes = SB_ONDISK_JOURNAL_SIZE(sb) * 2; |
bd4c625c0 reiserfs: run scr... |
2614 2615 2616 2617 2618 2619 |
struct buffer_head *bhjh; struct reiserfs_super_block *rs; struct reiserfs_journal_header *jh; struct reiserfs_journal *journal; struct reiserfs_journal_list *jl; char b[BDEVNAME_SIZE]; |
98ea3f50b reiserfs: Fix rem... |
2620 |
int ret; |
bd4c625c0 reiserfs: run scr... |
2621 |
|
558feb081 fs: Convert vmall... |
2622 |
journal = SB_JOURNAL(sb) = vzalloc(sizeof(struct reiserfs_journal)); |
bd4c625c0 reiserfs: run scr... |
2623 |
if (!journal) { |
a9dd36435 reiserfs: rename ... |
2624 |
reiserfs_warning(sb, "journal-1256", |
45b03d5e8 reiserfs: rework ... |
2625 |
"unable to get memory for journal structure"); |
bd4c625c0 reiserfs: run scr... |
2626 2627 |
return 1; } |
bd4c625c0 reiserfs: run scr... |
2628 2629 2630 2631 2632 |
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 reiserfs: don't l... |
2633 2634 |
if (reiserfs_allocate_list_bitmaps(sb, journal->j_list_bitmap, reiserfs_bmap_count(sb))) |
bd4c625c0 reiserfs: run scr... |
2635 |
goto free_and_return; |
98ea3f50b reiserfs: Fix rem... |
2636 |
|
a9dd36435 reiserfs: rename ... |
2637 |
allocate_bitmap_nodes(sb); |
bd4c625c0 reiserfs: run scr... |
2638 2639 |
/* reserved for journal area support */ |
a9dd36435 reiserfs: rename ... |
2640 |
SB_JOURNAL_1st_RESERVED_BLOCK(sb) = (old_format ? |
bd4c625c0 reiserfs: run scr... |
2641 |
REISERFS_OLD_DISK_OFFSET_IN_BYTES |
a9dd36435 reiserfs: rename ... |
2642 2643 |
/ sb->s_blocksize + reiserfs_bmap_count(sb) + |
bd4c625c0 reiserfs: run scr... |
2644 2645 |
1 : REISERFS_DISK_OFFSET_IN_BYTES / |
a9dd36435 reiserfs: rename ... |
2646 |
sb->s_blocksize + 2); |
bd4c625c0 reiserfs: run scr... |
2647 |
|
25985edce Fix common misspe... |
2648 |
/* Sanity check to see is the standard journal fitting within first bitmap |
bd4c625c0 reiserfs: run scr... |
2649 |
(actual for small blocksizes) */ |
a9dd36435 reiserfs: rename ... |
2650 2651 2652 2653 |
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 reiserfs: rework ... |
2654 2655 |
"journal does not fit for area addressed " "by first of bitmap blocks. It starts at " |
bd4c625c0 reiserfs: run scr... |
2656 |
"%u and its size is %u. Block size %ld", |
a9dd36435 reiserfs: rename ... |
2657 2658 2659 |
SB_JOURNAL_1st_RESERVED_BLOCK(sb), SB_ONDISK_JOURNAL_SIZE(sb), sb->s_blocksize); |
bd4c625c0 reiserfs: run scr... |
2660 2661 |
goto free_and_return; } |
a9dd36435 reiserfs: rename ... |
2662 2663 |
if (journal_init_dev(sb, journal, j_dev_name) != 0) { reiserfs_warning(sb, "sh-462", |
45b03d5e8 reiserfs: rework ... |
2664 |
"unable to initialize jornal device"); |
bd4c625c0 reiserfs: run scr... |
2665 2666 |
goto free_and_return; } |
a9dd36435 reiserfs: rename ... |
2667 |
rs = SB_DISK_SUPER_BLOCK(sb); |
bd4c625c0 reiserfs: run scr... |
2668 2669 |
/* read journal header */ |
a9dd36435 reiserfs: rename ... |
2670 2671 2672 |
bhjh = journal_bread(sb, SB_ONDISK_JOURNAL_1st_BLOCK(sb) + SB_ONDISK_JOURNAL_SIZE(sb)); |
bd4c625c0 reiserfs: run scr... |
2673 |
if (!bhjh) { |
a9dd36435 reiserfs: rename ... |
2674 |
reiserfs_warning(sb, "sh-459", |
45b03d5e8 reiserfs: rework ... |
2675 |
"unable to read journal header"); |
bd4c625c0 reiserfs: run scr... |
2676 2677 2678 2679 2680 2681 2682 2683 |
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 reiserfs: rename ... |
2684 |
reiserfs_warning(sb, "sh-460", |
45b03d5e8 reiserfs: rework ... |
2685 2686 2687 |
"journal header magic %x (device %s) does " "not match to magic found in super block %x", jh->jh_journal.jp_journal_magic, |
bd4c625c0 reiserfs: run scr... |
2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 |
bdevname(journal->j_dev_bd, b), 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 reiserfs: rename ... |
2699 |
if (check_advise_trans_params(sb, journal) != 0) |
cf3d0b818 reiserfs: do not ... |
2700 |
goto free_and_return; |
bd4c625c0 reiserfs: run scr... |
2701 2702 2703 2704 2705 2706 |
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; } |
a9dd36435 reiserfs: rename ... |
2707 |
reiserfs_info(sb, "journal params: device %s, size %u, " |
bd4c625c0 reiserfs: run scr... |
2708 2709 2710 2711 |
"journal first block %u, max trans len %u, max batch %u, " "max commit age %u, max trans age %u ", bdevname(journal->j_dev_bd, b), |
a9dd36435 reiserfs: rename ... |
2712 2713 |
SB_ONDISK_JOURNAL_SIZE(sb), SB_ONDISK_JOURNAL_1st_BLOCK(sb), |
bd4c625c0 reiserfs: run scr... |
2714 2715 2716 2717 2718 2719 2720 |
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 reiserfs: rename ... |
2721 |
journal_list_init(sb); |
bd4c625c0 reiserfs: run scr... |
2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 |
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; atomic_set(&(journal->j_wcount), 0); atomic_set(&(journal->j_async_throttle), 0); journal->j_bcount = 0; journal->j_trans_start_time = 0; journal->j_last = NULL; journal->j_first = NULL; init_waitqueue_head(&(journal->j_join_wait)); |
f68215c46 reiserfs: convert... |
2739 |
mutex_init(&journal->j_mutex); |
afe702590 reiserfs: convert... |
2740 |
mutex_init(&journal->j_flush_mutex); |
bd4c625c0 reiserfs: run scr... |
2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 |
journal->j_trans_id = 10; journal->j_mount_id = 10; journal->j_state = 0; atomic_set(&(journal->j_jlock), 0); 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 [PATCH] reiserfs:... |
2751 |
if (journal->j_cnode_free == 0) { |
a9dd36435 reiserfs: rename ... |
2752 |
reiserfs_warning(sb, "journal-2004", "Journal cnode memory " |
576f6d795 [PATCH] reiserfs:... |
2753 2754 2755 2756 2757 2758 |
"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 reiserfs: rename ... |
2759 |
init_journal_hash(sb); |
bd4c625c0 reiserfs: run scr... |
2760 |
jl = journal->j_current_jl; |
37c69b98d reiserfs: don't l... |
2761 2762 2763 2764 2765 2766 2767 |
/* * 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 reiserfs: rename ... |
2768 |
jl->j_list_bitmap = get_list_bitmap(sb, jl); |
37c69b98d reiserfs: don't l... |
2769 |
reiserfs_write_unlock(sb); |
bd4c625c0 reiserfs: run scr... |
2770 |
if (!jl->j_list_bitmap) { |
a9dd36435 reiserfs: rename ... |
2771 |
reiserfs_warning(sb, "journal-2005", |
45b03d5e8 reiserfs: rework ... |
2772 |
"get_list_bitmap failed for journal list 0"); |
bd4c625c0 reiserfs: run scr... |
2773 2774 |
goto free_and_return; } |
37c69b98d reiserfs: don't l... |
2775 2776 2777 2778 2779 2780 2781 2782 2783 |
/* * Journal_read needs to be inspected in order to push down * the lock further inside (or even remove it). */ reiserfs_write_lock(sb); ret = journal_read(sb); reiserfs_write_unlock(sb); if (ret < 0) { |
a9dd36435 reiserfs: rename ... |
2784 |
reiserfs_warning(sb, "reiserfs-2006", |
45b03d5e8 reiserfs: rework ... |
2785 |
"Replay Failure, unable to mount"); |
bd4c625c0 reiserfs: run scr... |
2786 2787 2788 2789 |
goto free_and_return; } reiserfs_mounted_fs_count++; |
37c69b98d reiserfs: don't l... |
2790 |
if (reiserfs_mounted_fs_count <= 1) |
28aadf516 reiserfs: make co... |
2791 |
commit_wq = alloc_workqueue("reiserfs", WQ_MEM_RECLAIM, 0); |
bd4c625c0 reiserfs: run scr... |
2792 |
|
c4028958b WorkStruct: make ... |
2793 |
INIT_DELAYED_WORK(&journal->j_work, flush_async_commits); |
a9dd36435 reiserfs: rename ... |
2794 |
journal->j_work_sb = sb; |
bd4c625c0 reiserfs: run scr... |
2795 2796 |
return 0; free_and_return: |
a9dd36435 reiserfs: rename ... |
2797 |
free_journal_ram(sb); |
bd4c625c0 reiserfs: run scr... |
2798 |
return 1; |
1da177e4c Linux-2.6.12-rc2 |
2799 2800 2801 2802 2803 2804 2805 |
} /* ** 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 reiserfs: run scr... |
2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 |
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 || atomic_read(&(journal->j_jlock)) || (now - journal->j_trans_start_time) > journal->j_max_trans_age || journal->j_cnode_free < (journal->j_trans_max * 3)) { return 1; } |
b18c1c6e0 reiserfs: delete ... |
2822 |
|
6ae1ea447 [PATCH] reiserfs:... |
2823 2824 |
journal->j_len_alloc += new_alloc; th->t_blocks_allocated += new_alloc ; |
bd4c625c0 reiserfs: run scr... |
2825 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
2826 |
} |
b18c1c6e0 reiserfs: delete ... |
2827 |
/* this must be called inside a transaction |
1da177e4c Linux-2.6.12-rc2 |
2828 |
*/ |
bd4c625c0 reiserfs: run scr... |
2829 2830 2831 2832 2833 2834 2835 |
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 Linux-2.6.12-rc2 |
2836 |
} |
b18c1c6e0 reiserfs: delete ... |
2837 |
/* this must be called without a transaction started |
1da177e4c Linux-2.6.12-rc2 |
2838 |
*/ |
bd4c625c0 reiserfs: run scr... |
2839 2840 2841 2842 2843 |
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 Linux-2.6.12-rc2 |
2844 |
} |
b18c1c6e0 reiserfs: delete ... |
2845 |
/* this must be called without a transaction started |
1da177e4c Linux-2.6.12-rc2 |
2846 |
*/ |
bd4c625c0 reiserfs: run scr... |
2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 |
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) { wait_queue_t wait; 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 Linux-2.6.12-rc2 |
2866 |
set_current_state(TASK_UNINTERRUPTIBLE); |
8ebc42323 reiserfs: kill-th... |
2867 2868 |
if (test_bit(J_WRITERS_QUEUED, &journal->j_state)) { reiserfs_write_unlock(s); |
bd4c625c0 reiserfs: run scr... |
2869 |
schedule(); |
8ebc42323 reiserfs: kill-th... |
2870 2871 |
reiserfs_write_lock(s); } |
5ab2f7e0f reiserfs: use __s... |
2872 |
__set_current_state(TASK_RUNNING); |
bd4c625c0 reiserfs: run scr... |
2873 2874 2875 2876 2877 2878 2879 2880 2881 |
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 reiserfs: audit t... |
2882 |
static void let_transaction_grow(struct super_block *sb, unsigned int trans_id) |
bd4c625c0 reiserfs: run scr... |
2883 2884 2885 2886 |
{ struct reiserfs_journal *journal = SB_JOURNAL(sb); unsigned long bcount = journal->j_bcount; while (1) { |
8ebc42323 reiserfs: kill-th... |
2887 |
reiserfs_write_unlock(sb); |
041e0e3b1 [PATCH] fs: fix-u... |
2888 |
schedule_timeout_uninterruptible(1); |
8ebc42323 reiserfs: kill-th... |
2889 |
reiserfs_write_lock(sb); |
bd4c625c0 reiserfs: run scr... |
2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 |
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 Linux-2.6.12-rc2 |
2901 |
} |
1da177e4c Linux-2.6.12-rc2 |
2902 2903 2904 2905 2906 2907 2908 2909 |
} /* 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. */ |
bd4c625c0 reiserfs: run scr... |
2910 |
static int do_journal_begin_r(struct reiserfs_transaction_handle *th, |
a9dd36435 reiserfs: rename ... |
2911 |
struct super_block *sb, unsigned long nblocks, |
bd4c625c0 reiserfs: run scr... |
2912 2913 2914 |
int join) { time_t now = get_seconds(); |
600ed4167 reiserfs: audit t... |
2915 |
unsigned int old_trans_id; |
a9dd36435 reiserfs: rename ... |
2916 |
struct reiserfs_journal *journal = SB_JOURNAL(sb); |
bd4c625c0 reiserfs: run scr... |
2917 2918 2919 |
struct reiserfs_transaction_handle myth; int sched_count = 0; int retval; |
a9dd36435 reiserfs: rename ... |
2920 |
reiserfs_check_lock_depth(sb, "journal_begin"); |
14a61442c BUG_ON conversion... |
2921 |
BUG_ON(nblocks > journal->j_trans_max); |
bd4c625c0 reiserfs: run scr... |
2922 |
|
a9dd36435 reiserfs: rename ... |
2923 |
PROC_INFO_INC(sb, journal.journal_being); |
bd4c625c0 reiserfs: run scr... |
2924 2925 |
/* set here for journal_join */ th->t_refcount = 1; |
a9dd36435 reiserfs: rename ... |
2926 |
th->t_super = sb; |
bd4c625c0 reiserfs: run scr... |
2927 2928 |
relock: |
a9dd36435 reiserfs: rename ... |
2929 |
lock_journal(sb); |
bd4c625c0 reiserfs: run scr... |
2930 |
if (join != JBEGIN_ABORT && reiserfs_is_journal_aborted(journal)) { |
a9dd36435 reiserfs: rename ... |
2931 |
unlock_journal(sb); |
bd4c625c0 reiserfs: run scr... |
2932 2933 2934 2935 2936 2937 |
retval = journal->j_errno; goto out_fail; } journal->j_bcount++; if (test_bit(J_WRITERS_BLOCKED, &journal->j_state)) { |
a9dd36435 reiserfs: rename ... |
2938 |
unlock_journal(sb); |
8ebc42323 reiserfs: kill-th... |
2939 |
reiserfs_write_unlock(sb); |
a9dd36435 reiserfs: rename ... |
2940 |
reiserfs_wait_on_write_block(sb); |
8ebc42323 reiserfs: kill-th... |
2941 |
reiserfs_write_lock(sb); |
a9dd36435 reiserfs: rename ... |
2942 |
PROC_INFO_INC(sb, journal.journal_relock_writers); |
bd4c625c0 reiserfs: run scr... |
2943 2944 2945 2946 2947 |
goto relock; } now = get_seconds(); /* if there is no room in the journal OR |
0222e6571 reiserfs: strip t... |
2948 |
** if this transaction is too old, and we weren't called joinable, wait for it to finish before beginning |
bd4c625c0 reiserfs: run scr... |
2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 |
** we don't sleep if there aren't other writers */ 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; |
a9dd36435 reiserfs: rename ... |
2963 |
unlock_journal(sb); /* allow others to finish this transaction */ |
bd4c625c0 reiserfs: run scr... |
2964 2965 2966 2967 2968 2969 2970 |
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 reiserfs: rename ... |
2971 |
queue_log_writer(sb); |
bd4c625c0 reiserfs: run scr... |
2972 2973 2974 2975 2976 2977 2978 2979 2980 |
goto relock; } } /* don't mess with joining the transaction if all we have to do is * wait for someone else to do a commit */ if (atomic_read(&journal->j_jlock)) { while (journal->j_trans_id == old_trans_id && atomic_read(&journal->j_jlock)) { |
a9dd36435 reiserfs: rename ... |
2981 |
queue_log_writer(sb); |
bd4c625c0 reiserfs: run scr... |
2982 2983 2984 |
} goto relock; } |
a9dd36435 reiserfs: rename ... |
2985 |
retval = journal_join(&myth, sb, 1); |
bd4c625c0 reiserfs: run scr... |
2986 2987 2988 2989 2990 |
if (retval) goto out_fail; /* someone might have ended the transaction while we joined */ if (old_trans_id != journal->j_trans_id) { |
a9dd36435 reiserfs: rename ... |
2991 |
retval = do_journal_end(&myth, sb, 1, 0); |
bd4c625c0 reiserfs: run scr... |
2992 |
} else { |
a9dd36435 reiserfs: rename ... |
2993 |
retval = do_journal_end(&myth, sb, 1, COMMIT_NOW); |
bd4c625c0 reiserfs: run scr... |
2994 2995 2996 2997 |
} if (retval) goto out_fail; |
a9dd36435 reiserfs: rename ... |
2998 |
PROC_INFO_INC(sb, journal.journal_relock_wcount); |
bd4c625c0 reiserfs: run scr... |
2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 |
goto relock; } /* we are the first writer, set trans_id */ if (journal->j_trans_start_time == 0) { journal->j_trans_start_time = get_seconds(); } atomic_inc(&(journal->j_wcount)); journal->j_len_alloc += nblocks; th->t_blocks_logged = 0; th->t_blocks_allocated = nblocks; th->t_trans_id = journal->j_trans_id; |
a9dd36435 reiserfs: rename ... |
3010 |
unlock_journal(sb); |
bd4c625c0 reiserfs: run scr... |
3011 |
INIT_LIST_HEAD(&th->t_list); |
bd4c625c0 reiserfs: run scr... |
3012 3013 3014 3015 3016 3017 3018 |
return 0; out_fail: memset(th, 0, sizeof(*th)); /* Re-set th->t_super, so we can properly keep track of how many * persistent transactions there are. We need to do this so if this * call is part of a failed restart_transaction, we can free it later */ |
a9dd36435 reiserfs: rename ... |
3019 |
th->t_super = sb; |
bd4c625c0 reiserfs: run scr... |
3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 |
return retval; } struct reiserfs_transaction_handle *reiserfs_persistent_transaction(struct super_block *s, int nblocks) { int ret; struct reiserfs_transaction_handle *th; /* if we're nesting into an existing transaction. It will be ** persistent on its own */ if (reiserfs_transaction_running(s)) { th = current->journal_info; th->t_refcount++; |
14a61442c BUG_ON conversion... |
3037 3038 |
BUG_ON(th->t_refcount < 2); |
bd4c625c0 reiserfs: run scr... |
3039 3040 |
return th; } |
d739b42b8 [PATCH] reiserfs:... |
3041 |
th = kmalloc(sizeof(struct reiserfs_transaction_handle), GFP_NOFS); |
bd4c625c0 reiserfs: run scr... |
3042 3043 3044 3045 |
if (!th) return NULL; ret = journal_begin(th, s, nblocks); if (ret) { |
d739b42b8 [PATCH] reiserfs:... |
3046 |
kfree(th); |
bd4c625c0 reiserfs: run scr... |
3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 |
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) ret = journal_end(th, th->t_super, th->t_blocks_allocated); else ret = -EIO; if (th->t_refcount == 0) { SB_JOURNAL(s)->j_persistent_trans--; |
d739b42b8 [PATCH] reiserfs:... |
3064 |
kfree(th); |
bd4c625c0 reiserfs: run scr... |
3065 3066 3067 3068 3069 |
} return ret; } static int journal_join(struct reiserfs_transaction_handle *th, |
a9dd36435 reiserfs: rename ... |
3070 |
struct super_block *sb, unsigned long nblocks) |
bd4c625c0 reiserfs: run scr... |
3071 3072 3073 3074 3075 3076 3077 |
{ struct reiserfs_transaction_handle *cur_th = current->journal_info; /* this keeps do_journal_end from NULLing out the current->journal_info ** pointer */ th->t_handle_save = cur_th; |
14a61442c BUG_ON conversion... |
3078 |
BUG_ON(cur_th && cur_th->t_refcount > 1); |
a9dd36435 reiserfs: rename ... |
3079 |
return do_journal_begin_r(th, sb, nblocks, JBEGIN_JOIN); |
bd4c625c0 reiserfs: run scr... |
3080 3081 3082 |
} int journal_join_abort(struct reiserfs_transaction_handle *th, |
a9dd36435 reiserfs: rename ... |
3083 |
struct super_block *sb, unsigned long nblocks) |
bd4c625c0 reiserfs: run scr... |
3084 3085 3086 3087 3088 3089 3090 |
{ struct reiserfs_transaction_handle *cur_th = current->journal_info; /* this keeps do_journal_end from NULLing out the current->journal_info ** pointer */ th->t_handle_save = cur_th; |
14a61442c BUG_ON conversion... |
3091 |
BUG_ON(cur_th && cur_th->t_refcount > 1); |
a9dd36435 reiserfs: rename ... |
3092 |
return do_journal_begin_r(th, sb, nblocks, JBEGIN_ABORT); |
bd4c625c0 reiserfs: run scr... |
3093 3094 3095 |
} int journal_begin(struct reiserfs_transaction_handle *th, |
a9dd36435 reiserfs: rename ... |
3096 |
struct super_block *sb, unsigned long nblocks) |
bd4c625c0 reiserfs: run scr... |
3097 3098 3099 3100 3101 3102 3103 |
{ 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 reiserfs: rename ... |
3104 |
if (cur_th->t_super == sb) { |
bd4c625c0 reiserfs: run scr... |
3105 3106 3107 3108 |
BUG_ON(!cur_th->t_refcount); cur_th->t_refcount++; memcpy(th, cur_th, sizeof(*th)); if (th->t_refcount <= 1) |
a9dd36435 reiserfs: rename ... |
3109 |
reiserfs_warning(sb, "reiserfs-2005", |
45b03d5e8 reiserfs: rework ... |
3110 3111 |
"BAD: refcount <= 1, but " "journal_info != 0"); |
bd4c625c0 reiserfs: run scr... |
3112 3113 3114 3115 3116 3117 |
return 0; } else { /* we've ended up with a handle from a different filesystem. ** save it and restore on journal_end. This should never ** really happen... */ |
a9dd36435 reiserfs: rename ... |
3118 |
reiserfs_warning(sb, "clm-2100", |
45b03d5e8 reiserfs: rework ... |
3119 |
"nesting info a different FS"); |
bd4c625c0 reiserfs: run scr... |
3120 3121 3122 |
th->t_handle_save = current->journal_info; current->journal_info = th; } |
1da177e4c Linux-2.6.12-rc2 |
3123 |
} else { |
bd4c625c0 reiserfs: run scr... |
3124 3125 |
current->journal_info = th; } |
a9dd36435 reiserfs: rename ... |
3126 |
ret = do_journal_begin_r(th, sb, nblocks, JBEGIN_REG); |
14a61442c BUG_ON conversion... |
3127 |
BUG_ON(current->journal_info != th); |
1da177e4c Linux-2.6.12-rc2 |
3128 |
|
bd4c625c0 reiserfs: run scr... |
3129 3130 3131 3132 3133 3134 3135 |
/* 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. */ if (ret) current->journal_info = th->t_handle_save; else BUG_ON(!th->t_refcount); |
1da177e4c Linux-2.6.12-rc2 |
3136 |
|
bd4c625c0 reiserfs: run scr... |
3137 |
return ret; |
1da177e4c Linux-2.6.12-rc2 |
3138 3139 3140 3141 3142 3143 3144 3145 |
} /* ** 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. |
0222e6571 reiserfs: strip t... |
3146 |
** |
1da177e4c Linux-2.6.12-rc2 |
3147 3148 |
** if j_len, is bigger than j_len_alloc, it pushes j_len_alloc to 10 + j_len. */ |
bd4c625c0 reiserfs: run scr... |
3149 |
int journal_mark_dirty(struct reiserfs_transaction_handle *th, |
a9dd36435 reiserfs: rename ... |
3150 |
struct super_block *sb, struct buffer_head *bh) |
bd4c625c0 reiserfs: run scr... |
3151 |
{ |
a9dd36435 reiserfs: rename ... |
3152 |
struct reiserfs_journal *journal = SB_JOURNAL(sb); |
bd4c625c0 reiserfs: run scr... |
3153 3154 3155 3156 |
struct reiserfs_journal_cnode *cn = NULL; int count_already_incd = 0; int prepared = 0; BUG_ON(!th->t_trans_id); |
a9dd36435 reiserfs: rename ... |
3157 |
PROC_INFO_INC(sb, journal.mark_dirty); |
bd4c625c0 reiserfs: run scr... |
3158 |
if (th->t_trans_id != journal->j_trans_id) { |
c3a9c2109 reiserfs: rework ... |
3159 3160 |
reiserfs_panic(th->t_super, "journal-1577", "handle trans id %ld != current trans id %ld", |
bd4c625c0 reiserfs: run scr... |
3161 3162 |
th->t_trans_id, journal->j_trans_id); } |
a9dd36435 reiserfs: rename ... |
3163 |
sb->s_dirt = 1; |
bd4c625c0 reiserfs: run scr... |
3164 3165 3166 3167 3168 |
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 reiserfs: rename ... |
3169 |
PROC_INFO_INC(sb, journal.mark_dirty_already); |
bd4c625c0 reiserfs: run scr... |
3170 3171 3172 3173 3174 3175 3176 3177 |
return 0; } /* 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. */ if (!prepared || buffer_dirty(bh)) { |
a9dd36435 reiserfs: rename ... |
3178 |
reiserfs_warning(sb, "journal-1777", |
45b03d5e8 reiserfs: rework ... |
3179 |
"buffer %llu bad state " |
bd4c625c0 reiserfs: run scr... |
3180 3181 3182 3183 3184 3185 3186 3187 3188 |
"%cPREPARED %cLOCKED %cDIRTY %cJDIRTY_WAIT", (unsigned long long)bh->b_blocknr, prepared ? ' ' : '!', buffer_locked(bh) ? ' ' : '!', buffer_dirty(bh) ? ' ' : '!', buffer_journal_dirty(bh) ? ' ' : '!'); } if (atomic_read(&(journal->j_wcount)) <= 0) { |
a9dd36435 reiserfs: rename ... |
3189 |
reiserfs_warning(sb, "journal-1409", |
45b03d5e8 reiserfs: rework ... |
3190 |
"returning because j_wcount was %d", |
bd4c625c0 reiserfs: run scr... |
3191 3192 3193 |
atomic_read(&(journal->j_wcount))); return 1; } |
0222e6571 reiserfs: strip t... |
3194 |
/* this error means I've screwed up, and we've overflowed the transaction. |
bd4c625c0 reiserfs: run scr... |
3195 3196 3197 |
** Nothing can be done here, except make the FS readonly or panic. */ if (journal->j_len >= journal->j_trans_max) { |
c3a9c2109 reiserfs: rework ... |
3198 3199 |
reiserfs_panic(th->t_super, "journal-1413", "j_len (%lu) is too big", |
bd4c625c0 reiserfs: run scr... |
3200 3201 3202 3203 3204 |
journal->j_len); } if (buffer_journal_dirty(bh)) { count_already_incd = 1; |
a9dd36435 reiserfs: rename ... |
3205 |
PROC_INFO_INC(sb, journal.mark_dirty_notjournal); |
bd4c625c0 reiserfs: run scr... |
3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 |
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 reiserfs: rename ... |
3217 |
cn = get_cnode(sb); |
bd4c625c0 reiserfs: run scr... |
3218 |
if (!cn) { |
a9dd36435 reiserfs: rename ... |
3219 |
reiserfs_panic(sb, "journal-4", "get_cnode failed!"); |
bd4c625c0 reiserfs: run scr... |
3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 |
} 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 reiserfs: rename ... |
3231 |
cn->sb = sb; |
bd4c625c0 reiserfs: run scr... |
3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 |
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; } return 0; } int journal_end(struct reiserfs_transaction_handle *th, |
a9dd36435 reiserfs: rename ... |
3252 |
struct super_block *sb, unsigned long nblocks) |
bd4c625c0 reiserfs: run scr... |
3253 3254 |
{ if (!current->journal_info && th->t_refcount > 1) |
a9dd36435 reiserfs: rename ... |
3255 |
reiserfs_warning(sb, "REISER-NESTING", |
45b03d5e8 reiserfs: rework ... |
3256 |
"th NULL, refcount %d", th->t_refcount); |
bd4c625c0 reiserfs: run scr... |
3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 |
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; /* we aren't allowed to close a nested transaction on a different ** filesystem from the one in the task struct */ |
14a61442c BUG_ON conversion... |
3271 |
BUG_ON(cur_th->t_super != th->t_super); |
bd4c625c0 reiserfs: run scr... |
3272 3273 3274 3275 3276 3277 3278 |
if (th != cur_th) { memcpy(current->journal_info, th, sizeof(*th)); th->t_trans_id = 0; } return 0; } else { |
a9dd36435 reiserfs: rename ... |
3279 |
return do_journal_end(th, sb, nblocks, 0); |
bd4c625c0 reiserfs: run scr... |
3280 |
} |
1da177e4c Linux-2.6.12-rc2 |
3281 |
} |
0222e6571 reiserfs: strip t... |
3282 |
/* removes from the current transaction, relsing and descrementing any counters. |
1da177e4c Linux-2.6.12-rc2 |
3283 3284 3285 3286 3287 3288 |
** 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 reiserfs: rename ... |
3289 |
static int remove_from_transaction(struct super_block *sb, |
bd4c625c0 reiserfs: run scr... |
3290 3291 3292 3293 |
b_blocknr_t blocknr, int already_cleaned) { struct buffer_head *bh; struct reiserfs_journal_cnode *cn; |
a9dd36435 reiserfs: rename ... |
3294 |
struct reiserfs_journal *journal = SB_JOURNAL(sb); |
bd4c625c0 reiserfs: run scr... |
3295 |
int ret = 0; |
a9dd36435 reiserfs: rename ... |
3296 |
cn = get_journal_hash_dev(sb, journal->j_hash_table, blocknr); |
bd4c625c0 reiserfs: run scr... |
3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 |
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 reiserfs: rename ... |
3314 |
remove_journal_hash(sb, journal->j_hash_table, NULL, |
bd4c625c0 reiserfs: run scr... |
3315 3316 3317 3318 3319 3320 3321 3322 3323 |
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); if (atomic_read(&(bh->b_count)) < 0) { |
a9dd36435 reiserfs: rename ... |
3324 |
reiserfs_warning(sb, "journal-1752", |
45b03d5e8 reiserfs: rework ... |
3325 |
"b_count < 0"); |
bd4c625c0 reiserfs: run scr... |
3326 3327 3328 3329 3330 |
} ret = 1; } journal->j_len--; journal->j_len_alloc--; |
a9dd36435 reiserfs: rename ... |
3331 |
free_cnode(sb, cn); |
bd4c625c0 reiserfs: run scr... |
3332 |
return ret; |
1da177e4c Linux-2.6.12-rc2 |
3333 3334 3335 3336 |
} /* ** for any cnode in a journal list, it can only be dirtied of all the |
0779bf2d2 Fix misc .c/.h co... |
3337 |
** transactions that include it are committed to disk. |
1da177e4c Linux-2.6.12-rc2 |
3338 3339 3340 3341 3342 3343 3344 |
** 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 reiserfs: run scr... |
3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 |
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; /* 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. */ while (cur && can_dirty) { if (cur->jlist && cur->bh && cur->blocknr && cur->sb == sb && cur->blocknr == blocknr) { can_dirty = 0; } cur = cur->hprev; } /* 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 */ cur = cn->hnext; while (cur && can_dirty) { if (cur->jlist && cur->jlist->j_len > 0 && atomic_read(&(cur->jlist->j_commit_left)) > 0 && cur->bh && cur->blocknr && cur->sb == sb && cur->blocknr == blocknr) { can_dirty = 0; } cur = cur->hnext; } return can_dirty; |
1da177e4c Linux-2.6.12-rc2 |
3376 3377 3378 |
} /* syncs the commit blocks, but does not force the real buffers to disk |
0222e6571 reiserfs: strip t... |
3379 |
** will wait until the current transaction is done/committed before returning |
1da177e4c Linux-2.6.12-rc2 |
3380 |
*/ |
bd4c625c0 reiserfs: run scr... |
3381 |
int journal_end_sync(struct reiserfs_transaction_handle *th, |
a9dd36435 reiserfs: rename ... |
3382 |
struct super_block *sb, unsigned long nblocks) |
bd4c625c0 reiserfs: run scr... |
3383 |
{ |
a9dd36435 reiserfs: rename ... |
3384 |
struct reiserfs_journal *journal = SB_JOURNAL(sb); |
1da177e4c Linux-2.6.12-rc2 |
3385 |
|
bd4c625c0 reiserfs: run scr... |
3386 3387 |
BUG_ON(!th->t_trans_id); /* you can sync while nested, very, very bad */ |
14a61442c BUG_ON conversion... |
3388 |
BUG_ON(th->t_refcount > 1); |
bd4c625c0 reiserfs: run scr... |
3389 |
if (journal->j_len == 0) { |
a9dd36435 reiserfs: rename ... |
3390 |
reiserfs_prepare_for_journal(sb, SB_BUFFER_WITH_SB(sb), |
bd4c625c0 reiserfs: run scr... |
3391 |
1); |
a9dd36435 reiserfs: rename ... |
3392 |
journal_mark_dirty(th, sb, SB_BUFFER_WITH_SB(sb)); |
bd4c625c0 reiserfs: run scr... |
3393 |
} |
a9dd36435 reiserfs: rename ... |
3394 |
return do_journal_end(th, sb, nblocks, COMMIT_NOW | WAIT); |
1da177e4c Linux-2.6.12-rc2 |
3395 3396 3397 3398 3399 |
} /* ** writeback the pending async commits to disk */ |
c4028958b WorkStruct: make ... |
3400 |
static void flush_async_commits(struct work_struct *work) |
bd4c625c0 reiserfs: run scr... |
3401 |
{ |
c4028958b WorkStruct: make ... |
3402 3403 |
struct reiserfs_journal *journal = container_of(work, struct reiserfs_journal, j_work.work); |
a9dd36435 reiserfs: rename ... |
3404 |
struct super_block *sb = journal->j_work_sb; |
bd4c625c0 reiserfs: run scr... |
3405 3406 |
struct reiserfs_journal_list *jl; struct list_head *entry; |
8ebc42323 reiserfs: kill-th... |
3407 |
reiserfs_write_lock(sb); |
bd4c625c0 reiserfs: run scr... |
3408 3409 3410 3411 |
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 reiserfs: rename ... |
3412 |
flush_commit_list(sb, jl, 1); |
bd4c625c0 reiserfs: run scr... |
3413 |
} |
8ebc42323 reiserfs: kill-th... |
3414 |
reiserfs_write_unlock(sb); |
1da177e4c Linux-2.6.12-rc2 |
3415 3416 3417 3418 3419 3420 |
} /* ** flushes any old transactions to disk ** ends the current transaction if it is too old */ |
a9dd36435 reiserfs: rename ... |
3421 |
int reiserfs_flush_old_commits(struct super_block *sb) |
bd4c625c0 reiserfs: run scr... |
3422 3423 3424 |
{ time_t now; struct reiserfs_transaction_handle th; |
a9dd36435 reiserfs: rename ... |
3425 |
struct reiserfs_journal *journal = SB_JOURNAL(sb); |
bd4c625c0 reiserfs: run scr... |
3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 |
now = get_seconds(); /* safety check so we don't flush while we are replaying the log during * mount */ if (list_empty(&journal->j_journal_list)) { return 0; } /* check the current transaction. If there are no writers, and it is * 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) { |
a9dd36435 reiserfs: rename ... |
3442 3443 3444 |
if (!journal_join(&th, sb, 1)) { reiserfs_prepare_for_journal(sb, SB_BUFFER_WITH_SB(sb), |
bd4c625c0 reiserfs: run scr... |
3445 |
1); |
a9dd36435 reiserfs: rename ... |
3446 3447 |
journal_mark_dirty(&th, sb, SB_BUFFER_WITH_SB(sb)); |
bd4c625c0 reiserfs: run scr... |
3448 3449 3450 3451 |
/* we're only being called from kreiserfsd, it makes no sense to do ** an async commit so that kreiserfsd can do it later */ |
a9dd36435 reiserfs: rename ... |
3452 |
do_journal_end(&th, sb, 1, COMMIT_NOW | WAIT); |
bd4c625c0 reiserfs: run scr... |
3453 3454 |
} } |
a9dd36435 reiserfs: rename ... |
3455 |
return sb->s_dirt; |
1da177e4c Linux-2.6.12-rc2 |
3456 3457 3458 3459 |
} /* ** returns 0 if do_journal_end should return right away, returns 1 if do_journal_end should finish the commit |
0222e6571 reiserfs: strip t... |
3460 3461 |
** ** if the current transaction is too old, but still has writers, this will wait on j_join_wait until all |
1da177e4c Linux-2.6.12-rc2 |
3462 3463 3464 3465 |
** 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. |
0222e6571 reiserfs: strip t... |
3466 |
** |
1da177e4c Linux-2.6.12-rc2 |
3467 3468 |
** Note, we can't allow the journal_end to proceed while there are still writers in the log. */ |
bd4c625c0 reiserfs: run scr... |
3469 |
static int check_journal_end(struct reiserfs_transaction_handle *th, |
a9dd36435 reiserfs: rename ... |
3470 |
struct super_block *sb, unsigned long nblocks, |
bd4c625c0 reiserfs: run scr... |
3471 3472 3473 3474 3475 3476 3477 3478 |
int flags) { 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; |
a9dd36435 reiserfs: rename ... |
3479 |
struct reiserfs_journal *journal = SB_JOURNAL(sb); |
bd4c625c0 reiserfs: run scr... |
3480 3481 3482 3483 |
BUG_ON(!th->t_trans_id); if (th->t_trans_id != journal->j_trans_id) { |
c3a9c2109 reiserfs: rework ... |
3484 3485 |
reiserfs_panic(th->t_super, "journal-1577", "handle trans id %ld != current trans id %ld", |
bd4c625c0 reiserfs: run scr... |
3486 3487 3488 3489 3490 3491 3492 |
th->t_trans_id, journal->j_trans_id); } journal->j_len_alloc -= (th->t_blocks_allocated - th->t_blocks_logged); if (atomic_read(&(journal->j_wcount)) > 0) { /* <= 0 is allowed. unmounting might not call begin */ atomic_dec(&(journal->j_wcount)); } |
0222e6571 reiserfs: strip t... |
3493 |
/* BUG, deal with case where j_len is 0, but people previously freed blocks need to be released |
bd4c625c0 reiserfs: run scr... |
3494 3495 3496 |
** will be dealt with by next transaction that actually writes something, but should be taken ** care of in this trans */ |
14a61442c BUG_ON conversion... |
3497 |
BUG_ON(journal->j_len == 0); |
bd4c625c0 reiserfs: run scr... |
3498 3499 3500 |
/* 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. |
0222e6571 reiserfs: strip t... |
3501 |
** Then, we flush the commit or journal list, and just return 0 |
bd4c625c0 reiserfs: run scr... |
3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 |
** because the rest of journal end was already done for this transaction. */ if (atomic_read(&(journal->j_wcount)) > 0) { 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; atomic_set(&(journal->j_jlock), 1); if (flush) { journal->j_next_full_flush = 1; } |
a9dd36435 reiserfs: rename ... |
3516 |
unlock_journal(sb); |
bd4c625c0 reiserfs: run scr... |
3517 3518 3519 3520 |
/* sleep while the current transaction is still j_jlocked */ while (journal->j_trans_id == trans_id) { if (atomic_read(&journal->j_jlock)) { |
a9dd36435 reiserfs: rename ... |
3521 |
queue_log_writer(sb); |
bd4c625c0 reiserfs: run scr... |
3522 |
} else { |
a9dd36435 reiserfs: rename ... |
3523 |
lock_journal(sb); |
bd4c625c0 reiserfs: run scr... |
3524 3525 3526 3527 |
if (journal->j_trans_id == trans_id) { atomic_set(&(journal->j_jlock), 1); } |
a9dd36435 reiserfs: rename ... |
3528 |
unlock_journal(sb); |
bd4c625c0 reiserfs: run scr... |
3529 3530 |
} } |
14a61442c BUG_ON conversion... |
3531 3532 |
BUG_ON(journal->j_trans_id == trans_id); |
bd4c625c0 reiserfs: run scr... |
3533 |
if (commit_now |
a9dd36435 reiserfs: rename ... |
3534 |
&& journal_list_still_alive(sb, trans_id) |
bd4c625c0 reiserfs: run scr... |
3535 |
&& wait_on_commit) { |
a9dd36435 reiserfs: rename ... |
3536 |
flush_commit_list(sb, jl, 1); |
bd4c625c0 reiserfs: run scr... |
3537 3538 3539 |
} return 0; } |
a9dd36435 reiserfs: rename ... |
3540 |
unlock_journal(sb); |
bd4c625c0 reiserfs: run scr... |
3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 |
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 */ if (!(journal->j_must_wait > 0) && !(atomic_read(&(journal->j_jlock))) && !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 reiserfs: rename ... |
3557 |
unlock_journal(sb); |
bd4c625c0 reiserfs: run scr... |
3558 3559 |
return 0; } |
a9dd36435 reiserfs: rename ... |
3560 3561 |
if (journal->j_start > SB_ONDISK_JOURNAL_SIZE(sb)) { reiserfs_panic(sb, "journal-003", |
c3a9c2109 reiserfs: rework ... |
3562 |
"j_start (%ld) is too high", |
bd4c625c0 reiserfs: run scr... |
3563 3564 3565 |
journal->j_start); } return 1; |
1da177e4c Linux-2.6.12-rc2 |
3566 3567 3568 3569 3570 |
} /* ** 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. |
0222e6571 reiserfs: strip t... |
3571 |
** |
1da177e4c Linux-2.6.12-rc2 |
3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 |
** 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 reiserfs: run scr... |
3582 |
int journal_mark_freed(struct reiserfs_transaction_handle *th, |
a9dd36435 reiserfs: rename ... |
3583 |
struct super_block *sb, b_blocknr_t blocknr) |
bd4c625c0 reiserfs: run scr... |
3584 |
{ |
a9dd36435 reiserfs: rename ... |
3585 |
struct reiserfs_journal *journal = SB_JOURNAL(sb); |
bd4c625c0 reiserfs: run scr... |
3586 3587 3588 3589 3590 |
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 reiserfs: rename ... |
3591 |
cn = get_journal_hash_dev(sb, journal->j_hash_table, blocknr); |
bd4c625c0 reiserfs: run scr... |
3592 3593 3594 3595 3596 3597 3598 3599 3600 |
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 reiserfs: rename ... |
3601 |
cleaned = remove_from_transaction(sb, blocknr, cleaned); |
bd4c625c0 reiserfs: run scr... |
3602 3603 3604 3605 |
} else { /* set the bit for this block in the journal bitmap for this transaction */ jb = journal->j_current_jl->j_list_bitmap; if (!jb) { |
a9dd36435 reiserfs: rename ... |
3606 |
reiserfs_panic(sb, "journal-1702", |
c3a9c2109 reiserfs: rework ... |
3607 |
"journal_list_bitmap is NULL"); |
bd4c625c0 reiserfs: run scr... |
3608 |
} |
a9dd36435 reiserfs: rename ... |
3609 |
set_bit_in_list_bitmap(sb, blocknr, jb); |
bd4c625c0 reiserfs: run scr... |
3610 3611 3612 3613 3614 3615 3616 |
/* Note, the entire while loop is not allowed to schedule. */ if (bh) { clear_prepared_bits(bh); reiserfs_clean_and_file_buffer(bh); } |
a9dd36435 reiserfs: rename ... |
3617 |
cleaned = remove_from_transaction(sb, blocknr, cleaned); |
bd4c625c0 reiserfs: run scr... |
3618 3619 |
/* find all older transactions with this block, make sure they don't try to write it out */ |
a9dd36435 reiserfs: rename ... |
3620 |
cn = get_journal_hash_dev(sb, journal->j_list_hash_table, |
bd4c625c0 reiserfs: run scr... |
3621 3622 |
blocknr); while (cn) { |
a9dd36435 reiserfs: rename ... |
3623 |
if (sb == cn->sb && blocknr == cn->blocknr) { |
bd4c625c0 reiserfs: run scr... |
3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 |
set_bit(BLOCK_FREED, &cn->state); if (cn->bh) { if (!cleaned) { /* remove_from_transaction will brelse the buffer if it was ** in the current trans */ 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 (&(cn->bh->b_count)) < 0) { |
a9dd36435 reiserfs: rename ... |
3639 |
reiserfs_warning(sb, |
45b03d5e8 reiserfs: rework ... |
3640 3641 |
"journal-2138", "cn->bh->b_count < 0"); |
bd4c625c0 reiserfs: run scr... |
3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 |
} } if (cn->jlist) { /* since we are clearing the bh, we MUST dec nonzerolen */ atomic_dec(& (cn->jlist-> j_nonzerolen)); } cn->bh = NULL; } } cn = cn->hnext; } } |
398c95bdf try to reap reise... |
3655 3656 |
if (bh) release_buffer_page(bh); /* get_hash grabs the buffer */ |
bd4c625c0 reiserfs: run scr... |
3657 3658 3659 3660 3661 3662 3663 3664 |
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 Linux-2.6.12-rc2 |
3665 3666 3667 3668 3669 3670 3671 |
} /* * 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 reiserfs: run scr... |
3672 |
struct reiserfs_journal_list *jl) |
1da177e4c Linux-2.6.12-rc2 |
3673 |
{ |
bd4c625c0 reiserfs: run scr... |
3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 |
struct reiserfs_transaction_handle th; struct super_block *sb = inode->i_sb; struct reiserfs_journal *journal = SB_JOURNAL(sb); int ret = 0; /* is it from the current transaction, or from an unknown transaction? */ if (id == journal->j_trans_id) { jl = journal->j_current_jl; /* try to let other writers come in and grow this transaction */ let_transaction_grow(sb, id); if (journal->j_trans_id != id) { goto flush_commit_only; } |
1da177e4c Linux-2.6.12-rc2 |
3687 |
|
bd4c625c0 reiserfs: run scr... |
3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 |
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); journal_mark_dirty(&th, sb, SB_BUFFER_WITH_SB(sb)); ret = journal_end(&th, sb, 1); goto flush_commit_only; } |
1da177e4c Linux-2.6.12-rc2 |
3700 |
|
bd4c625c0 reiserfs: run scr... |
3701 3702 3703 |
ret = journal_end_sync(&th, sb, 1); if (!ret) ret = 1; |
1da177e4c Linux-2.6.12-rc2 |
3704 |
|
bd4c625c0 reiserfs: run scr... |
3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 |
} else { /* this gets tricky, we have to make sure the journal list in * the inode still exists. We know the list is still around * if we've got a larger transaction id than the oldest list */ flush_commit_only: 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 Linux-2.6.12-rc2 |
3723 |
} |
bd4c625c0 reiserfs: run scr... |
3724 3725 3726 |
/* otherwise the list is gone, and long since committed */ return ret; } |
1da177e4c Linux-2.6.12-rc2 |
3727 |
|
bd4c625c0 reiserfs: run scr... |
3728 3729 |
int reiserfs_commit_for_inode(struct inode *inode) { |
600ed4167 reiserfs: audit t... |
3730 |
unsigned int id = REISERFS_I(inode)->i_trans_id; |
bd4c625c0 reiserfs: run scr... |
3731 |
struct reiserfs_journal_list *jl = REISERFS_I(inode)->i_jl; |
1da177e4c Linux-2.6.12-rc2 |
3732 |
|
bd4c625c0 reiserfs: run scr... |
3733 3734 |
/* for the whole inode, assume unset id means it was * changed in the current transaction. More conservative |
1da177e4c Linux-2.6.12-rc2 |
3735 |
*/ |
bd4c625c0 reiserfs: run scr... |
3736 3737 3738 3739 3740 3741 3742 3743 |
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 reiserfs: rename ... |
3744 |
void reiserfs_restore_prepared_buffer(struct super_block *sb, |
bd4c625c0 reiserfs: run scr... |
3745 3746 |
struct buffer_head *bh) { |
a9dd36435 reiserfs: rename ... |
3747 3748 |
struct reiserfs_journal *journal = SB_JOURNAL(sb); PROC_INFO_INC(sb, journal.restore_prepared); |
bd4c625c0 reiserfs: run scr... |
3749 3750 3751 3752 3753 3754 |
if (!bh) { return; } if (test_clear_buffer_journal_restore_dirty(bh) && buffer_journal_dirty(bh)) { struct reiserfs_journal_cnode *cn; |
a9dd36435 reiserfs: rename ... |
3755 |
cn = get_journal_hash_dev(sb, |
bd4c625c0 reiserfs: run scr... |
3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 |
journal->j_list_hash_table, bh->b_blocknr); if (cn && can_dirty(cn)) { set_buffer_journal_test(bh); mark_buffer_dirty(bh); } } clear_buffer_journal_prepared(bh); } extern struct tree_balance *cur_tb; |
1da177e4c Linux-2.6.12-rc2 |
3767 3768 3769 3770 3771 |
/* ** 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. |
0222e6571 reiserfs: strip t... |
3772 |
** |
1da177e4c Linux-2.6.12-rc2 |
3773 |
*/ |
a9dd36435 reiserfs: rename ... |
3774 |
int reiserfs_prepare_for_journal(struct super_block *sb, |
bd4c625c0 reiserfs: run scr... |
3775 3776 |
struct buffer_head *bh, int wait) { |
a9dd36435 reiserfs: rename ... |
3777 |
PROC_INFO_INC(sb, journal.prepare); |
bd4c625c0 reiserfs: run scr... |
3778 |
|
ca5de404f fs: rename buffer... |
3779 |
if (!trylock_buffer(bh)) { |
bd4c625c0 reiserfs: run scr... |
3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 |
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; } static void flush_old_journal_lists(struct super_block *s) { struct reiserfs_journal *journal = SB_JOURNAL(s); struct reiserfs_journal_list *jl; struct list_head *entry; time_t now = get_seconds(); while (!list_empty(&journal->j_journal_list)) { entry = journal->j_journal_list.next; jl = JOURNAL_LIST_ENTRY(entry); /* this check should always be run, to send old lists to disk */ |
a31720271 [PATCH] Fix reise... |
3804 3805 3806 |
if (jl->j_timestamp < (now - (JOURNAL_MAX_TRANS_AGE * 4)) && atomic_read(&jl->j_commit_left) == 0 && test_transaction(s, jl)) { |
bd4c625c0 reiserfs: run scr... |
3807 3808 3809 3810 |
flush_used_journal_lists(s, jl); } else { break; } |
1da177e4c Linux-2.6.12-rc2 |
3811 |
} |
1da177e4c Linux-2.6.12-rc2 |
3812 |
} |
0222e6571 reiserfs: strip t... |
3813 |
/* |
1da177e4c Linux-2.6.12-rc2 |
3814 3815 3816 3817 3818 3819 3820 3821 3822 |
** 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. */ |
bd4c625c0 reiserfs: run scr... |
3823 |
static int do_journal_end(struct reiserfs_transaction_handle *th, |
a9dd36435 reiserfs: rename ... |
3824 |
struct super_block *sb, unsigned long nblocks, |
bd4c625c0 reiserfs: run scr... |
3825 3826 |
int flags) { |
a9dd36435 reiserfs: rename ... |
3827 |
struct reiserfs_journal *journal = SB_JOURNAL(sb); |
bd4c625c0 reiserfs: run scr... |
3828 3829 3830 3831 3832 3833 3834 3835 3836 |
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 [PATCH] reiserfs:... |
3837 3838 |
int flush; int wait_on_commit; |
bd4c625c0 reiserfs: run scr... |
3839 3840 3841 |
struct reiserfs_journal_list *jl, *temp_jl; struct list_head *entry, *safe; unsigned long jindex; |
600ed4167 reiserfs: audit t... |
3842 |
unsigned int commit_trans_id; |
bd4c625c0 reiserfs: run scr... |
3843 3844 3845 3846 |
int trans_half; BUG_ON(th->t_refcount > 1); BUG_ON(!th->t_trans_id); |
a44c94a7b [PATCH] reiserfs:... |
3847 3848 |
/* protect flush_older_commits from doing mistakes if the transaction ID counter gets overflowed. */ |
600ed4167 reiserfs: audit t... |
3849 |
if (th->t_trans_id == ~0U) |
a44c94a7b [PATCH] reiserfs:... |
3850 3851 3852 |
flags |= FLUSH_ALL | COMMIT_NOW | WAIT; flush = flags & FLUSH_ALL; wait_on_commit = flags & WAIT; |
bd4c625c0 reiserfs: run scr... |
3853 |
current->journal_info = th->t_handle_save; |
a9dd36435 reiserfs: rename ... |
3854 |
reiserfs_check_lock_depth(sb, "journal end"); |
bd4c625c0 reiserfs: run scr... |
3855 |
if (journal->j_len == 0) { |
a9dd36435 reiserfs: rename ... |
3856 |
reiserfs_prepare_for_journal(sb, SB_BUFFER_WITH_SB(sb), |
bd4c625c0 reiserfs: run scr... |
3857 |
1); |
a9dd36435 reiserfs: rename ... |
3858 |
journal_mark_dirty(th, sb, SB_BUFFER_WITH_SB(sb)); |
bd4c625c0 reiserfs: run scr... |
3859 |
} |
1da177e4c Linux-2.6.12-rc2 |
3860 |
|
a9dd36435 reiserfs: rename ... |
3861 |
lock_journal(sb); |
bd4c625c0 reiserfs: run scr... |
3862 3863 3864 3865 3866 3867 3868 3869 |
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; } |
0222e6571 reiserfs: strip t... |
3870 |
/* check_journal_end locks the journal, and unlocks if it does not return 1 |
bd4c625c0 reiserfs: run scr... |
3871 3872 |
** it tells us if we should continue with the journal_end, or just return */ |
a9dd36435 reiserfs: rename ... |
3873 3874 3875 3876 |
if (!check_journal_end(th, sb, nblocks, flags)) { sb->s_dirt = 1; wake_queued_writers(sb); reiserfs_async_progress_wait(sb); |
bd4c625c0 reiserfs: run scr... |
3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 |
goto out; } /* check_journal_end might set these, check again */ if (journal->j_next_full_flush) { flush = 1; } /* ** j must wait means we have to flush the log blocks, and the real blocks for ** this transaction */ if (journal->j_must_wait > 0) { flush = 1; } |
1da177e4c Linux-2.6.12-rc2 |
3892 |
#ifdef REISERFS_PREALLOCATE |
ef43bc4fc [PATCH] reiserfs:... |
3893 3894 |
/* quota ops might need to nest, setup the journal_info pointer for them * and raise the refcount so that it is > 0. */ |
bd4c625c0 reiserfs: run scr... |
3895 |
current->journal_info = th; |
ef43bc4fc [PATCH] reiserfs:... |
3896 |
th->t_refcount++; |
bd4c625c0 reiserfs: run scr... |
3897 3898 |
reiserfs_discard_all_prealloc(th); /* it should not involve new blocks into * the transaction */ |
ef43bc4fc [PATCH] reiserfs:... |
3899 |
th->t_refcount--; |
bd4c625c0 reiserfs: run scr... |
3900 |
current->journal_info = th->t_handle_save; |
1da177e4c Linux-2.6.12-rc2 |
3901 |
#endif |
bd4c625c0 reiserfs: run scr... |
3902 3903 3904 |
/* setup description block */ d_bh = |
a9dd36435 reiserfs: rename ... |
3905 3906 |
journal_getblk(sb, SB_ONDISK_JOURNAL_1st_BLOCK(sb) + |
bd4c625c0 reiserfs: run scr... |
3907 3908 3909 3910 3911 3912 3913 3914 |
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); /* setup commit block. Don't write (keep it clean too) this one until after everyone else is written */ |
a9dd36435 reiserfs: rename ... |
3915 |
c_bh = journal_getblk(sb, SB_ONDISK_JOURNAL_1st_BLOCK(sb) + |
bd4c625c0 reiserfs: run scr... |
3916 |
((journal->j_start + journal->j_len + |
a9dd36435 reiserfs: rename ... |
3917 |
1) % SB_ONDISK_JOURNAL_SIZE(sb))); |
bd4c625c0 reiserfs: run scr... |
3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 |
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; /* we lock the commit before doing anything because * 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 reiserfs: kill-th... |
3931 |
reiserfs_mutex_lock_safe(&jl->j_commit_mutex, sb); |
bd4c625c0 reiserfs: run scr... |
3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 |
/* 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; /* 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 */ |
a9dd36435 reiserfs: rename ... |
3950 |
trans_half = journal_trans_half(sb->s_blocksize); |
bd4c625c0 reiserfs: run scr... |
3951 3952 |
for (i = 0, cn = journal->j_first; cn; cn = cn->next, i++) { if (buffer_journaled(cn->bh)) { |
a9dd36435 reiserfs: rename ... |
3953 |
jl_cn = get_cnode(sb); |
bd4c625c0 reiserfs: run scr... |
3954 |
if (!jl_cn) { |
a9dd36435 reiserfs: rename ... |
3955 |
reiserfs_panic(sb, "journal-1676", |
c3a9c2109 reiserfs: rework ... |
3956 |
"get_cnode returned NULL"); |
bd4c625c0 reiserfs: run scr... |
3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 |
} 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; |
0222e6571 reiserfs: strip t... |
3967 |
/* make sure the block we are trying to log is not a block |
bd4c625c0 reiserfs: run scr... |
3968 3969 3970 |
of journal or reserved area */ if (is_block_in_log_or_reserved_area |
a9dd36435 reiserfs: rename ... |
3971 3972 |
(sb, cn->bh->b_blocknr)) { reiserfs_panic(sb, "journal-2332", |
c3a9c2109 reiserfs: rework ... |
3973 3974 |
"Trying to log block %lu, " "which is a log block", |
bd4c625c0 reiserfs: run scr... |
3975 3976 3977 3978 |
cn->bh->b_blocknr); } jl_cn->blocknr = cn->bh->b_blocknr; jl_cn->state = 0; |
a9dd36435 reiserfs: rename ... |
3979 |
jl_cn->sb = sb; |
bd4c625c0 reiserfs: run scr... |
3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 |
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); /* special check in case all buffers in the journal were marked for not logging */ |
14a61442c BUG_ON conversion... |
4000 |
BUG_ON(journal->j_len == 0); |
bd4c625c0 reiserfs: run scr... |
4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 |
/* we're about to dirty all the log blocks, mark the description block * dirty now too. Don't mark the commit block dirty until all the * others are on disk */ mark_buffer_dirty(d_bh); /* first data block is j_start + 1, so add one to cur_write_start wherever you use it */ cur_write_start = journal->j_start; cn = journal->j_first; jindex = 1; /* start at one so we don't get the desc again */ 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 reiserfs: rename ... |
4020 4021 |
journal_getblk(sb, SB_ONDISK_JOURNAL_1st_BLOCK(sb) + |
bd4c625c0 reiserfs: run scr... |
4022 4023 |
((cur_write_start + jindex) % |
a9dd36435 reiserfs: rename ... |
4024 |
SB_ONDISK_JOURNAL_SIZE(sb))); |
bd4c625c0 reiserfs: run scr... |
4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 |
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 { /* JDirty cleared sometime during transaction. don't log this one */ |
a9dd36435 reiserfs: rename ... |
4038 |
reiserfs_warning(sb, "journal-2048", |
45b03d5e8 reiserfs: rework ... |
4039 4040 |
"BAD, buffer in journal hash, " "but not JDirty!"); |
bd4c625c0 reiserfs: run scr... |
4041 4042 4043 |
brelse(cn->bh); } next = cn->next; |
a9dd36435 reiserfs: rename ... |
4044 |
free_cnode(sb, cn); |
bd4c625c0 reiserfs: run scr... |
4045 |
cn = next; |
e6950a4da kill-the-BKL/reis... |
4046 |
reiserfs_write_unlock(sb); |
bd4c625c0 reiserfs: run scr... |
4047 |
cond_resched(); |
e6950a4da kill-the-BKL/reis... |
4048 |
reiserfs_write_lock(sb); |
bd4c625c0 reiserfs: run scr... |
4049 4050 4051 4052 4053 4054 |
} /* 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. */ |
a9dd36435 reiserfs: rename ... |
4055 |
journal->j_current_jl = alloc_journal_list(sb); |
bd4c625c0 reiserfs: run scr... |
4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 |
/* 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 reiserfs: rename ... |
4066 |
2) % SB_ONDISK_JOURNAL_SIZE(sb); |
bd4c625c0 reiserfs: run scr... |
4067 4068 4069 4070 4071 4072 |
atomic_set(&(journal->j_wcount), 0); journal->j_bcount = 0; journal->j_last = NULL; journal->j_first = NULL; journal->j_len = 0; journal->j_trans_start_time = 0; |
a44c94a7b [PATCH] reiserfs:... |
4073 4074 4075 |
/* check for trans_id overflow */ if (++journal->j_trans_id == 0) journal->j_trans_id = 10; |
bd4c625c0 reiserfs: run scr... |
4076 4077 4078 4079 4080 |
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 reiserfs: rename ... |
4081 |
init_journal_hash(sb); |
bd4c625c0 reiserfs: run scr... |
4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 |
// make sure reiserfs_add_jh sees the new current_jl before we // write out the tails smp_mb(); /* tail conversion targets have to hit the disk before we end the * transaction. Otherwise a later transaction might repack the tail * before this transaction commits, leaving the data block unflushed and * clean, if we crash before the later transaction commits, the data block * is lost. */ if (!list_empty(&jl->j_tail_bh_list)) { |
8ebc42323 reiserfs: kill-th... |
4094 |
reiserfs_write_unlock(sb); |
bd4c625c0 reiserfs: run scr... |
4095 4096 |
write_ordered_buffers(&journal->j_dirty_buffers_lock, journal, jl, &jl->j_tail_bh_list); |
8ebc42323 reiserfs: kill-th... |
4097 |
reiserfs_write_lock(sb); |
bd4c625c0 reiserfs: run scr... |
4098 |
} |
14a61442c BUG_ON conversion... |
4099 |
BUG_ON(!list_empty(&jl->j_tail_bh_list)); |
90415deac reiserfs: convert... |
4100 |
mutex_unlock(&jl->j_commit_mutex); |
bd4c625c0 reiserfs: run scr... |
4101 4102 4103 4104 4105 4106 4107 4108 4109 |
/* 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. */ if (flush) { |
a9dd36435 reiserfs: rename ... |
4110 4111 |
flush_commit_list(sb, jl, 1); flush_journal_list(sb, jl, 1); |
bd4c625c0 reiserfs: run scr... |
4112 4113 |
} else if (!(jl->j_state & LIST_COMMIT_PENDING)) queue_delayed_work(commit_wq, &journal->j_work, HZ / 10); |
0222e6571 reiserfs: strip t... |
4114 4115 4116 |
/* 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 reiserfs: run scr... |
4117 4118 4119 4120 4121 4122 4123 |
*/ first_jl: 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 reiserfs: rename ... |
4124 |
flush_used_journal_lists(sb, temp_jl); |
bd4c625c0 reiserfs: run scr... |
4125 4126 4127 |
goto first_jl; } else if ((journal->j_start + journal->j_trans_max + 1) < |
a9dd36435 reiserfs: rename ... |
4128 |
SB_ONDISK_JOURNAL_SIZE(sb)) { |
bd4c625c0 reiserfs: run scr... |
4129 4130 4131 4132 4133 4134 4135 4136 |
/* if we don't cross into the next transaction and we don't * wrap, there is no way we can overlap any later transactions * break now */ break; } } else if ((journal->j_start + journal->j_trans_max + 1) > |
a9dd36435 reiserfs: rename ... |
4137 |
SB_ONDISK_JOURNAL_SIZE(sb)) { |
bd4c625c0 reiserfs: run scr... |
4138 |
if (((journal->j_start + journal->j_trans_max + 1) % |
a9dd36435 reiserfs: rename ... |
4139 |
SB_ONDISK_JOURNAL_SIZE(sb)) >= |
bd4c625c0 reiserfs: run scr... |
4140 |
temp_jl->j_start) { |
a9dd36435 reiserfs: rename ... |
4141 |
flush_used_journal_lists(sb, temp_jl); |
bd4c625c0 reiserfs: run scr... |
4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 |
goto first_jl; } else { /* 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 */ break; } } } |
a9dd36435 reiserfs: rename ... |
4152 |
flush_old_journal_lists(sb); |
bd4c625c0 reiserfs: run scr... |
4153 4154 |
journal->j_current_jl->j_list_bitmap = |
a9dd36435 reiserfs: rename ... |
4155 |
get_list_bitmap(sb, journal->j_current_jl); |
bd4c625c0 reiserfs: run scr... |
4156 4157 |
if (!(journal->j_current_jl->j_list_bitmap)) { |
a9dd36435 reiserfs: rename ... |
4158 |
reiserfs_panic(sb, "journal-1996", |
c3a9c2109 reiserfs: rework ... |
4159 |
"could not get a list bitmap"); |
bd4c625c0 reiserfs: run scr... |
4160 4161 4162 |
} atomic_set(&(journal->j_jlock), 0); |
a9dd36435 reiserfs: rename ... |
4163 |
unlock_journal(sb); |
bd4c625c0 reiserfs: run scr... |
4164 4165 4166 4167 4168 |
/* wake up any body waiting to join. */ clear_bit(J_WRITERS_QUEUED, &journal->j_state); wake_up(&(journal->j_join_wait)); if (!flush && wait_on_commit && |
a9dd36435 reiserfs: rename ... |
4169 4170 |
journal_list_still_alive(sb, commit_trans_id)) { flush_commit_list(sb, jl, 1); |
bd4c625c0 reiserfs: run scr... |
4171 4172 |
} out: |
a9dd36435 reiserfs: rename ... |
4173 |
reiserfs_check_lock_depth(sb, "journal end2"); |
bd4c625c0 reiserfs: run scr... |
4174 4175 4176 4177 4178 |
memset(th, 0, sizeof(*th)); /* Re-set th->t_super, so we can properly keep track of how many * persistent transactions there are. We need to do this so if this * call is part of a failed restart_transaction, we can free it later */ |
a9dd36435 reiserfs: rename ... |
4179 |
th->t_super = sb; |
bd4c625c0 reiserfs: run scr... |
4180 4181 4182 |
return journal->j_errno; } |
32e8b1062 reiserfs: rearran... |
4183 4184 |
/* Send the file system read only and refuse new transactions */ void reiserfs_abort_journal(struct super_block *sb, int errno) |
bd4c625c0 reiserfs: run scr... |
4185 4186 4187 4188 |
{ struct reiserfs_journal *journal = SB_JOURNAL(sb); if (test_bit(J_ABORTED, &journal->j_state)) return; |
32e8b1062 reiserfs: rearran... |
4189 4190 |
if (!journal->j_errno) journal->j_errno = errno; |
bd4c625c0 reiserfs: run scr... |
4191 4192 4193 |
sb->s_flags |= MS_RDONLY; set_bit(J_ABORTED, &journal->j_state); |
1da177e4c Linux-2.6.12-rc2 |
4194 4195 |
#ifdef CONFIG_REISERFS_CHECK |
bd4c625c0 reiserfs: run scr... |
4196 |
dump_stack(); |
1da177e4c Linux-2.6.12-rc2 |
4197 4198 |
#endif } |