Blame view
fs/gfs2/log.c
23 KB
b3b94faa5 [GFS2] The core o... |
1 2 |
/* * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
da6dd40d5 [GFS2] Journal ex... |
3 |
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. |
b3b94faa5 [GFS2] The core o... |
4 5 6 |
* * This copyrighted material is made available to anyone wishing to use, * modify, copy, or redistribute it subject to the terms and conditions |
e9fc2aa09 [GFS2] Update cop... |
7 |
* of the GNU General Public License version 2. |
b3b94faa5 [GFS2] The core o... |
8 9 10 11 12 13 14 |
*/ #include <linux/sched.h> #include <linux/slab.h> #include <linux/spinlock.h> #include <linux/completion.h> #include <linux/buffer_head.h> |
5c676f6d3 [GFS2] Macros rem... |
15 |
#include <linux/gfs2_ondisk.h> |
71b86f562 [GFS2] Further up... |
16 |
#include <linux/crc32.h> |
a25311c8e [GFS2] Move gfs2_... |
17 |
#include <linux/delay.h> |
ec69b1888 [GFS2] Move gfs2_... |
18 19 |
#include <linux/kthread.h> #include <linux/freezer.h> |
254db57f9 GFS2: Support for... |
20 |
#include <linux/bio.h> |
b3b94faa5 [GFS2] The core o... |
21 22 |
#include "gfs2.h" |
5c676f6d3 [GFS2] Macros rem... |
23 |
#include "incore.h" |
b3b94faa5 [GFS2] The core o... |
24 25 26 27 28 |
#include "bmap.h" #include "glock.h" #include "log.h" #include "lops.h" #include "meta_io.h" |
5c676f6d3 [GFS2] Macros rem... |
29 |
#include "util.h" |
71b86f562 [GFS2] Further up... |
30 |
#include "dir.h" |
63997775b GFS2: Add tracepo... |
31 |
#include "trace_gfs2.h" |
b3b94faa5 [GFS2] The core o... |
32 33 |
#define PULL 1 |
b3b94faa5 [GFS2] The core o... |
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
/** * gfs2_struct2blk - compute stuff * @sdp: the filesystem * @nstruct: the number of structures * @ssize: the size of the structures * * Compute the number of log descriptor blocks needed to hold a certain number * of structures of a certain size. * * Returns: the number of blocks needed (minimum is always 1) */ unsigned int gfs2_struct2blk(struct gfs2_sbd *sdp, unsigned int nstruct, unsigned int ssize) { unsigned int blks; unsigned int first, second; blks = 1; |
faa31ce85 [GFS2] Tidy up log.c |
53 |
first = (sdp->sd_sb.sb_bsize - sizeof(struct gfs2_log_descriptor)) / ssize; |
b3b94faa5 [GFS2] The core o... |
54 55 |
if (nstruct > first) { |
568f4c965 [GFS2] 80 Column ... |
56 57 |
second = (sdp->sd_sb.sb_bsize - sizeof(struct gfs2_meta_header)) / ssize; |
5c676f6d3 [GFS2] Macros rem... |
58 |
blks += DIV_ROUND_UP(nstruct - first, second); |
b3b94faa5 [GFS2] The core o... |
59 60 61 62 |
} return blks; } |
ddacfaf76 [GFS2] Move loggi... |
63 |
/** |
1e1a3d03e [GFS2] Introduce ... |
64 65 66 67 68 69 70 |
* gfs2_remove_from_ail - Remove an entry from the ail lists, updating counters * @mapping: The associated mapping (maybe NULL) * @bd: The gfs2_bufdata to remove * * The log lock _must_ be held when calling this function * */ |
f91a0d3e2 [GFS2] Remove use... |
71 |
void gfs2_remove_from_ail(struct gfs2_bufdata *bd) |
1e1a3d03e [GFS2] Introduce ... |
72 73 |
{ bd->bd_ail = NULL; |
1ad38c437 [GFS2] Clean up g... |
74 75 |
list_del_init(&bd->bd_ail_st_list); list_del_init(&bd->bd_ail_gl_list); |
1e1a3d03e [GFS2] Introduce ... |
76 |
atomic_dec(&bd->bd_gl->gl_ail_count); |
1e1a3d03e [GFS2] Introduce ... |
77 78 79 80 |
brelse(bd->bd_bh); } /** |
ddacfaf76 [GFS2] Move loggi... |
81 82 83 84 85 86 87 |
* gfs2_ail1_start_one - Start I/O on a part of the AIL * @sdp: the filesystem * @tr: the part of the AIL * */ static void gfs2_ail1_start_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai) |
2d81afb87 [GFS2] trivial sp... |
88 89 |
__releases(&sdp->sd_log_lock) __acquires(&sdp->sd_log_lock) |
ddacfaf76 [GFS2] Move loggi... |
90 91 92 93 |
{ struct gfs2_bufdata *bd, *s; struct buffer_head *bh; int retry; |
ddacfaf76 [GFS2] Move loggi... |
94 95 96 97 98 99 100 101 102 103 |
do { retry = 0; list_for_each_entry_safe_reverse(bd, s, &ai->ai_ail1_list, bd_ail_st_list) { bh = bd->bd_bh; gfs2_assert(sdp, bd->bd_ail == ai); if (!buffer_busy(bh)) { |
16615be18 [GFS2] Clean up j... |
104 |
if (!buffer_uptodate(bh)) |
ddacfaf76 [GFS2] Move loggi... |
105 |
gfs2_io_error_bh(sdp, bh); |
ddacfaf76 [GFS2] Move loggi... |
106 107 108 109 110 111 112 113 |
list_move(&bd->bd_ail_st_list, &ai->ai_ail2_list); continue; } if (!buffer_dirty(bh)) continue; list_move(&bd->bd_ail_st_list, &ai->ai_ail1_list); |
16615be18 [GFS2] Clean up j... |
114 |
get_bh(bh); |
ddacfaf76 [GFS2] Move loggi... |
115 |
gfs2_log_unlock(sdp); |
16615be18 [GFS2] Clean up j... |
116 117 118 |
lock_buffer(bh); if (test_clear_buffer_dirty(bh)) { bh->b_end_io = end_buffer_write_sync; |
c969f58ca GFS2: Update the ... |
119 |
submit_bh(WRITE_SYNC_PLUG, bh); |
16615be18 [GFS2] Clean up j... |
120 121 122 123 |
} else { unlock_buffer(bh); brelse(bh); } |
ddacfaf76 [GFS2] Move loggi... |
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
gfs2_log_lock(sdp); retry = 1; break; } } while (retry); } /** * gfs2_ail1_empty_one - Check whether or not a trans in the AIL has been synced * @sdp: the filesystem * @ai: the AIL entry * */ static int gfs2_ail1_empty_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai, int flags) { struct gfs2_bufdata *bd, *s; struct buffer_head *bh; list_for_each_entry_safe_reverse(bd, s, &ai->ai_ail1_list, bd_ail_st_list) { bh = bd->bd_bh; gfs2_assert(sdp, bd->bd_ail == ai); if (buffer_busy(bh)) { if (flags & DIO_ALL) continue; else break; } if (!buffer_uptodate(bh)) gfs2_io_error_bh(sdp, bh); list_move(&bd->bd_ail_st_list, &ai->ai_ail2_list); } return list_empty(&ai->ai_ail1_list); } |
a25311c8e [GFS2] Move gfs2_... |
165 |
static void gfs2_ail1_start(struct gfs2_sbd *sdp, int flags) |
b3b94faa5 [GFS2] The core o... |
166 |
{ |
693ddeabb [GFS2] Revert par... |
167 |
struct list_head *head; |
cd915493f [GFS2] Change all... |
168 |
u64 sync_gen; |
74669416f [GFS2] Use list_f... |
169 170 171 |
struct list_head *first; struct gfs2_ail *first_ai, *ai, *tmp; int done = 0; |
b3b94faa5 [GFS2] The core o... |
172 173 |
gfs2_log_lock(sdp); |
693ddeabb [GFS2] Revert par... |
174 |
head = &sdp->sd_ail1_list; |
b3b94faa5 [GFS2] The core o... |
175 176 177 178 179 180 181 182 183 |
if (list_empty(head)) { gfs2_log_unlock(sdp); return; } sync_gen = sdp->sd_ail_sync_gen++; first = head->prev; first_ai = list_entry(first, struct gfs2_ail, ai_list); first_ai->ai_sync_gen = sync_gen; |
74669416f [GFS2] Use list_f... |
184 |
gfs2_ail1_start_one(sdp, first_ai); /* This may drop log lock */ |
b3b94faa5 [GFS2] The core o... |
185 186 187 |
if (flags & DIO_ALL) first = NULL; |
74669416f [GFS2] Use list_f... |
188 |
while(!done) { |
484adff8a [GFS2] Update loc... |
189 190 |
if (first && (head->prev != first || gfs2_ail1_empty_one(sdp, first_ai, 0))) |
b3b94faa5 [GFS2] The core o... |
191 |
break; |
74669416f [GFS2] Use list_f... |
192 193 |
done = 1; list_for_each_entry_safe_reverse(ai, tmp, head, ai_list) { |
b3b94faa5 [GFS2] The core o... |
194 195 196 |
if (ai->ai_sync_gen >= sync_gen) continue; ai->ai_sync_gen = sync_gen; |
74669416f [GFS2] Use list_f... |
197 198 |
gfs2_ail1_start_one(sdp, ai); /* This may drop log lock */ done = 0; |
b3b94faa5 [GFS2] The core o... |
199 200 |
break; } |
b3b94faa5 [GFS2] The core o... |
201 202 203 204 |
} gfs2_log_unlock(sdp); } |
ec69b1888 [GFS2] Move gfs2_... |
205 |
static int gfs2_ail1_empty(struct gfs2_sbd *sdp, int flags) |
b3b94faa5 [GFS2] The core o... |
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 |
{ struct gfs2_ail *ai, *s; int ret; gfs2_log_lock(sdp); list_for_each_entry_safe_reverse(ai, s, &sdp->sd_ail1_list, ai_list) { if (gfs2_ail1_empty_one(sdp, ai, flags)) list_move(&ai->ai_list, &sdp->sd_ail2_list); else if (!(flags & DIO_ALL)) break; } ret = list_empty(&sdp->sd_ail1_list); gfs2_log_unlock(sdp); return ret; } |
ddacfaf76 [GFS2] Move loggi... |
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 |
/** * gfs2_ail2_empty_one - Check whether or not a trans in the AIL has been synced * @sdp: the filesystem * @ai: the AIL entry * */ static void gfs2_ail2_empty_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai) { struct list_head *head = &ai->ai_ail2_list; struct gfs2_bufdata *bd; while (!list_empty(head)) { bd = list_entry(head->prev, struct gfs2_bufdata, bd_ail_st_list); gfs2_assert(sdp, bd->bd_ail == ai); |
f91a0d3e2 [GFS2] Remove use... |
242 |
gfs2_remove_from_ail(bd); |
ddacfaf76 [GFS2] Move loggi... |
243 244 |
} } |
b3b94faa5 [GFS2] The core o... |
245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 |
static void ail2_empty(struct gfs2_sbd *sdp, unsigned int new_tail) { struct gfs2_ail *ai, *safe; unsigned int old_tail = sdp->sd_log_tail; int wrap = (new_tail < old_tail); int a, b, rm; gfs2_log_lock(sdp); list_for_each_entry_safe(ai, safe, &sdp->sd_ail2_list, ai_list) { a = (old_tail <= ai->ai_first); b = (ai->ai_first < new_tail); rm = (wrap) ? (a || b) : (a && b); if (!rm) continue; gfs2_ail2_empty_one(sdp, ai); list_del(&ai->ai_list); gfs2_assert_warn(sdp, list_empty(&ai->ai_ail1_list)); gfs2_assert_warn(sdp, list_empty(&ai->ai_ail2_list)); kfree(ai); } gfs2_log_unlock(sdp); } /** * gfs2_log_reserve - Make a log reservation * @sdp: The GFS2 superblock * @blks: The number of blocks to reserve * |
89918647a [GFS2] Make the l... |
276 |
* Note that we never give out the last few blocks of the journal. Thats |
2332c4435 [GFS2] assertion ... |
277 |
* due to the fact that there is a small number of header blocks |
b004157ab [GFS2] Fix journa... |
278 279 280 281 |
* associated with each log flush. The exact number can't be known until * flush time, so we ensure that we have just enough free blocks at all * times to avoid running out during a log flush. * |
b3b94faa5 [GFS2] The core o... |
282 283 284 285 286 |
* Returns: errno */ int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks) { |
b3b94faa5 [GFS2] The core o... |
287 |
unsigned int try = 0; |
89918647a [GFS2] Make the l... |
288 |
unsigned reserved_blks = 6 * (4096 / sdp->sd_vfs->s_blocksize); |
b3b94faa5 [GFS2] The core o... |
289 290 291 292 |
if (gfs2_assert_warn(sdp, blks) || gfs2_assert_warn(sdp, blks <= sdp->sd_jdesc->jd_blocks)) return -EINVAL; |
71b86f562 [GFS2] Further up... |
293 |
mutex_lock(&sdp->sd_log_reserve_mutex); |
484adff8a [GFS2] Update loc... |
294 |
gfs2_log_lock(sdp); |
fd041f0b4 [GFS2] Use atomic... |
295 |
while(atomic_read(&sdp->sd_log_blks_free) <= (blks + reserved_blks)) { |
b3b94faa5 [GFS2] The core o... |
296 |
gfs2_log_unlock(sdp); |
b3b94faa5 [GFS2] The core o... |
297 |
gfs2_ail1_empty(sdp, 0); |
b09e593d7 [GFS2] Fix a ref ... |
298 |
gfs2_log_flush(sdp, NULL); |
b3b94faa5 [GFS2] The core o... |
299 300 301 |
if (try++) gfs2_ail1_start(sdp, 0); |
484adff8a [GFS2] Update loc... |
302 |
gfs2_log_lock(sdp); |
b3b94faa5 [GFS2] The core o... |
303 |
} |
fd041f0b4 [GFS2] Use atomic... |
304 |
atomic_sub(blks, &sdp->sd_log_blks_free); |
63997775b GFS2: Add tracepo... |
305 |
trace_gfs2_log_blocks(sdp, -blks); |
484adff8a [GFS2] Update loc... |
306 307 308 309 |
gfs2_log_unlock(sdp); mutex_unlock(&sdp->sd_log_reserve_mutex); down_read(&sdp->sd_log_flush_lock); |
b3b94faa5 [GFS2] The core o... |
310 311 312 313 314 315 316 317 318 319 320 321 322 |
return 0; } /** * gfs2_log_release - Release a given number of log blocks * @sdp: The GFS2 superblock * @blks: The number of blocks * */ void gfs2_log_release(struct gfs2_sbd *sdp, unsigned int blks) { |
b3b94faa5 [GFS2] The core o... |
323 324 |
gfs2_log_lock(sdp); |
fd041f0b4 [GFS2] Use atomic... |
325 |
atomic_add(blks, &sdp->sd_log_blks_free); |
63997775b GFS2: Add tracepo... |
326 |
trace_gfs2_log_blocks(sdp, blks); |
b3b94faa5 [GFS2] The core o... |
327 |
gfs2_assert_withdraw(sdp, |
fd041f0b4 [GFS2] Use atomic... |
328 |
atomic_read(&sdp->sd_log_blks_free) <= sdp->sd_jdesc->jd_blocks); |
b3b94faa5 [GFS2] The core o... |
329 |
gfs2_log_unlock(sdp); |
ed3865079 [GFS2] Finally ge... |
330 |
up_read(&sdp->sd_log_flush_lock); |
b3b94faa5 [GFS2] The core o... |
331 |
} |
cd915493f [GFS2] Change all... |
332 |
static u64 log_bmap(struct gfs2_sbd *sdp, unsigned int lbn) |
b3b94faa5 [GFS2] The core o... |
333 |
{ |
da6dd40d5 [GFS2] Journal ex... |
334 335 336 337 |
struct gfs2_journal_extent *je; list_for_each_entry(je, &sdp->sd_jdesc->extent_list, extent_list) { if (lbn >= je->lblock && lbn < je->lblock + je->blocks) |
ff91cc9bb [GFS2] Fix log bl... |
338 |
return je->dblock + lbn - je->lblock; |
da6dd40d5 [GFS2] Journal ex... |
339 340 341 |
} return -1; |
b3b94faa5 [GFS2] The core o... |
342 343 344 345 346 347 348 349 350 351 352 353 354 |
} /** * log_distance - Compute distance between two journal blocks * @sdp: The GFS2 superblock * @newer: The most recent journal block of the pair * @older: The older journal block of the pair * * Compute the distance (in the journal direction) between two * blocks in the journal * * Returns: the distance in blocks */ |
faa31ce85 [GFS2] Tidy up log.c |
355 |
static inline unsigned int log_distance(struct gfs2_sbd *sdp, unsigned int newer, |
b3b94faa5 [GFS2] The core o... |
356 357 358 359 360 361 362 363 364 365 |
unsigned int older) { int dist; dist = newer - older; if (dist < 0) dist += sdp->sd_jdesc->jd_blocks; return dist; } |
2332c4435 [GFS2] assertion ... |
366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 |
/** * calc_reserved - Calculate the number of blocks to reserve when * refunding a transaction's unused buffers. * @sdp: The GFS2 superblock * * This is complex. We need to reserve room for all our currently used * metadata buffers (e.g. normal file I/O rewriting file time stamps) and * all our journaled data buffers for journaled files (e.g. files in the * meta_fs like rindex, or files for which chattr +j was done.) * If we don't reserve enough space, gfs2_log_refund and gfs2_log_flush * will count it as free space (sd_log_blks_free) and corruption will follow. * * We can have metadata bufs and jdata bufs in the same journal. So each * type gets its own log header, for which we need to reserve a block. * In fact, each type has the potential for needing more than one header * in cases where we have more buffers than will fit on a journal page. * Metadata journal entries take up half the space of journaled buffer entries. * Thus, metadata entries have buf_limit (502) and journaled buffers have * databuf_limit (251) before they cause a wrap around. * * Also, we need to reserve blocks for revoke journal entries and one for an * overall header for the lot. * * Returns: the number of blocks reserved */ static unsigned int calc_reserved(struct gfs2_sbd *sdp) { unsigned int reserved = 0; unsigned int mbuf_limit, metabufhdrs_needed; unsigned int dbuf_limit, databufhdrs_needed; unsigned int revokes = 0; mbuf_limit = buf_limit(sdp); metabufhdrs_needed = (sdp->sd_log_commited_buf + (mbuf_limit - 1)) / mbuf_limit; dbuf_limit = databuf_limit(sdp); databufhdrs_needed = (sdp->sd_log_commited_databuf + (dbuf_limit - 1)) / dbuf_limit; if (sdp->sd_log_commited_revoke) revokes = gfs2_struct2blk(sdp, sdp->sd_log_commited_revoke, sizeof(u64)); reserved = sdp->sd_log_commited_buf + metabufhdrs_needed + sdp->sd_log_commited_databuf + databufhdrs_needed + revokes; /* One for the overall header */ if (reserved) reserved++; return reserved; } |
b3b94faa5 [GFS2] The core o... |
417 418 419 420 421 422 |
static unsigned int current_tail(struct gfs2_sbd *sdp) { struct gfs2_ail *ai; unsigned int tail; gfs2_log_lock(sdp); |
faa31ce85 [GFS2] Tidy up log.c |
423 |
if (list_empty(&sdp->sd_ail1_list)) { |
b3b94faa5 [GFS2] The core o... |
424 |
tail = sdp->sd_log_head; |
faa31ce85 [GFS2] Tidy up log.c |
425 426 |
} else { ai = list_entry(sdp->sd_ail1_list.prev, struct gfs2_ail, ai_list); |
b3b94faa5 [GFS2] The core o... |
427 428 429 430 431 432 433 |
tail = ai->ai_first; } gfs2_log_unlock(sdp); return tail; } |
16615be18 [GFS2] Clean up j... |
434 |
void gfs2_log_incr_head(struct gfs2_sbd *sdp) |
b3b94faa5 [GFS2] The core o... |
435 436 |
{ if (sdp->sd_log_flush_head == sdp->sd_log_tail) |
16615be18 [GFS2] Clean up j... |
437 |
BUG_ON(sdp->sd_log_flush_head != sdp->sd_log_head); |
b3b94faa5 [GFS2] The core o... |
438 439 440 441 442 443 444 445 |
if (++sdp->sd_log_flush_head == sdp->sd_jdesc->jd_blocks) { sdp->sd_log_flush_head = 0; sdp->sd_log_flush_wrapped = 1; } } /** |
16615be18 [GFS2] Clean up j... |
446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 |
* gfs2_log_write_endio - End of I/O for a log buffer * @bh: The buffer head * @uptodate: I/O Status * */ static void gfs2_log_write_endio(struct buffer_head *bh, int uptodate) { struct gfs2_sbd *sdp = bh->b_private; bh->b_private = NULL; end_buffer_write_sync(bh, uptodate); if (atomic_dec_and_test(&sdp->sd_log_in_flight)) wake_up(&sdp->sd_log_flush_wait); } /** |
b3b94faa5 [GFS2] The core o... |
463 464 465 466 467 468 469 470 |
* gfs2_log_get_buf - Get and initialize a buffer to use for log control data * @sdp: The GFS2 superblock * * Returns: the buffer_head */ struct buffer_head *gfs2_log_get_buf(struct gfs2_sbd *sdp) { |
cd915493f [GFS2] Change all... |
471 |
u64 blkno = log_bmap(sdp, sdp->sd_log_flush_head); |
b3b94faa5 [GFS2] The core o... |
472 |
struct buffer_head *bh; |
16615be18 [GFS2] Clean up j... |
473 |
bh = sb_getblk(sdp->sd_vfs, blkno); |
b3b94faa5 [GFS2] The core o... |
474 475 476 477 |
lock_buffer(bh); memset(bh->b_data, 0, bh->b_size); set_buffer_uptodate(bh); clear_buffer_dirty(bh); |
16615be18 [GFS2] Clean up j... |
478 479 480 481 |
gfs2_log_incr_head(sdp); atomic_inc(&sdp->sd_log_in_flight); bh->b_private = sdp; bh->b_end_io = gfs2_log_write_endio; |
b3b94faa5 [GFS2] The core o... |
482 483 484 485 486 |
return bh; } /** |
16615be18 [GFS2] Clean up j... |
487 488 489 490 491 492 493 494 495 |
* gfs2_fake_write_endio - * @bh: The buffer head * @uptodate: The I/O Status * */ static void gfs2_fake_write_endio(struct buffer_head *bh, int uptodate) { struct buffer_head *real_bh = bh->b_private; |
5a60c532c [GFS2] Get superb... |
496 497 |
struct gfs2_bufdata *bd = real_bh->b_private; struct gfs2_sbd *sdp = bd->bd_gl->gl_sbd; |
16615be18 [GFS2] Clean up j... |
498 499 500 501 502 503 504 505 506 507 |
end_buffer_write_sync(bh, uptodate); free_buffer_head(bh); unlock_buffer(real_bh); brelse(real_bh); if (atomic_dec_and_test(&sdp->sd_log_in_flight)) wake_up(&sdp->sd_log_flush_wait); } /** |
b3b94faa5 [GFS2] The core o... |
508 509 510 511 512 513 514 515 516 517 |
* gfs2_log_fake_buf - Build a fake buffer head to write metadata buffer to log * @sdp: the filesystem * @data: the data the buffer_head should point to * * Returns: the log buffer descriptor */ struct buffer_head *gfs2_log_fake_buf(struct gfs2_sbd *sdp, struct buffer_head *real) { |
cd915493f [GFS2] Change all... |
518 |
u64 blkno = log_bmap(sdp, sdp->sd_log_flush_head); |
b3b94faa5 [GFS2] The core o... |
519 |
struct buffer_head *bh; |
16615be18 [GFS2] Clean up j... |
520 |
bh = alloc_buffer_head(GFP_NOFS | __GFP_NOFAIL); |
b3b94faa5 [GFS2] The core o... |
521 |
atomic_set(&bh->b_count, 1); |
16615be18 [GFS2] Clean up j... |
522 |
bh->b_state = (1 << BH_Mapped) | (1 << BH_Uptodate) | (1 << BH_Lock); |
18ec7d5c3 [GFS2] Make journ... |
523 |
set_bh_page(bh, real->b_page, bh_offset(real)); |
b3b94faa5 [GFS2] The core o... |
524 525 526 |
bh->b_blocknr = blkno; bh->b_size = sdp->sd_sb.sb_bsize; bh->b_bdev = sdp->sd_vfs->s_bdev; |
16615be18 [GFS2] Clean up j... |
527 528 |
bh->b_private = real; bh->b_end_io = gfs2_fake_write_endio; |
b3b94faa5 [GFS2] The core o... |
529 |
|
16615be18 [GFS2] Clean up j... |
530 531 |
gfs2_log_incr_head(sdp); atomic_inc(&sdp->sd_log_in_flight); |
b3b94faa5 [GFS2] The core o... |
532 533 534 |
return bh; } |
2332c4435 [GFS2] assertion ... |
535 |
static void log_pull_tail(struct gfs2_sbd *sdp, unsigned int new_tail) |
b3b94faa5 [GFS2] The core o... |
536 537 538 539 540 541 |
{ unsigned int dist = log_distance(sdp, new_tail, sdp->sd_log_tail); ail2_empty(sdp, new_tail); gfs2_log_lock(sdp); |
fd041f0b4 [GFS2] Use atomic... |
542 |
atomic_add(dist, &sdp->sd_log_blks_free); |
63997775b GFS2: Add tracepo... |
543 |
trace_gfs2_log_blocks(sdp, dist); |
fd041f0b4 [GFS2] Use atomic... |
544 |
gfs2_assert_withdraw(sdp, atomic_read(&sdp->sd_log_blks_free) <= sdp->sd_jdesc->jd_blocks); |
b3b94faa5 [GFS2] The core o... |
545 546 547 548 549 550 551 552 553 554 555 |
gfs2_log_unlock(sdp); sdp->sd_log_tail = new_tail; } /** * log_write_header - Get and initialize a journal header buffer * @sdp: The GFS2 superblock * * Returns: the initialized log buffer descriptor */ |
cd915493f [GFS2] Change all... |
556 |
static void log_write_header(struct gfs2_sbd *sdp, u32 flags, int pull) |
b3b94faa5 [GFS2] The core o... |
557 |
{ |
cd915493f [GFS2] Change all... |
558 |
u64 blkno = log_bmap(sdp, sdp->sd_log_flush_head); |
b3b94faa5 [GFS2] The core o... |
559 560 561 |
struct buffer_head *bh; struct gfs2_log_header *lh; unsigned int tail; |
cd915493f [GFS2] Change all... |
562 |
u32 hash; |
b3b94faa5 [GFS2] The core o... |
563 |
|
b3b94faa5 [GFS2] The core o... |
564 565 566 567 568 |
bh = sb_getblk(sdp->sd_vfs, blkno); lock_buffer(bh); memset(bh->b_data, 0, bh->b_size); set_buffer_uptodate(bh); clear_buffer_dirty(bh); |
b3b94faa5 [GFS2] The core o... |
569 570 571 572 573 574 575 |
gfs2_ail1_empty(sdp, 0); tail = current_tail(sdp); lh = (struct gfs2_log_header *)bh->b_data; memset(lh, 0, sizeof(struct gfs2_log_header)); lh->lh_header.mh_magic = cpu_to_be32(GFS2_MAGIC); |
e3167ded1 [GFS] Fix bug in ... |
576 577 |
lh->lh_header.mh_type = cpu_to_be32(GFS2_METATYPE_LH); lh->lh_header.mh_format = cpu_to_be32(GFS2_FORMAT_LH); |
e0f2bf780 [GFS2] Fix endian... |
578 579 580 581 |
lh->lh_sequence = cpu_to_be64(sdp->sd_log_sequence++); lh->lh_flags = cpu_to_be32(flags); lh->lh_tail = cpu_to_be32(tail); lh->lh_blkno = cpu_to_be32(sdp->sd_log_flush_head); |
b3b94faa5 [GFS2] The core o... |
582 583 |
hash = gfs2_disk_hash(bh->b_data, sizeof(struct gfs2_log_header)); lh->lh_hash = cpu_to_be32(hash); |
254db57f9 GFS2: Support for... |
584 585 586 587 |
bh->b_end_io = end_buffer_write_sync; if (test_bit(SDF_NOBARRIERS, &sdp->sd_flags)) goto skip_barrier; get_bh(bh); |
c969f58ca GFS2: Update the ... |
588 |
submit_bh(WRITE_SYNC | (1 << BIO_RW_BARRIER) | (1 << BIO_RW_META), bh); |
254db57f9 GFS2: Support for... |
589 590 591 592 593 594 595 596 597 598 599 600 |
wait_on_buffer(bh); if (buffer_eopnotsupp(bh)) { clear_buffer_eopnotsupp(bh); set_buffer_uptodate(bh); set_bit(SDF_NOBARRIERS, &sdp->sd_flags); lock_buffer(bh); skip_barrier: get_bh(bh); submit_bh(WRITE_SYNC | (1 << BIO_RW_META), bh); wait_on_buffer(bh); } if (!buffer_uptodate(bh)) |
b3b94faa5 [GFS2] The core o... |
601 602 603 604 |
gfs2_io_error_bh(sdp, bh); brelse(bh); if (sdp->sd_log_tail != tail) |
2332c4435 [GFS2] assertion ... |
605 |
log_pull_tail(sdp, tail); |
b3b94faa5 [GFS2] The core o... |
606 607 608 609 |
else gfs2_assert_withdraw(sdp, !pull); sdp->sd_log_idle = (tail == sdp->sd_log_flush_head); |
16615be18 [GFS2] Clean up j... |
610 |
gfs2_log_incr_head(sdp); |
b3b94faa5 [GFS2] The core o... |
611 612 613 614 |
} static void log_flush_commit(struct gfs2_sbd *sdp) { |
16615be18 [GFS2] Clean up j... |
615 616 617 618 619 620 621 622 623 624 |
DEFINE_WAIT(wait); if (atomic_read(&sdp->sd_log_in_flight)) { do { prepare_to_wait(&sdp->sd_log_flush_wait, &wait, TASK_UNINTERRUPTIBLE); if (atomic_read(&sdp->sd_log_in_flight)) io_schedule(); } while(atomic_read(&sdp->sd_log_in_flight)); finish_wait(&sdp->sd_log_flush_wait, &wait); |
b3b94faa5 [GFS2] The core o... |
625 |
} |
16615be18 [GFS2] Clean up j... |
626 |
log_write_header(sdp, 0, 0); |
b3b94faa5 [GFS2] The core o... |
627 |
} |
d7b616e25 [GFS2] Clean up o... |
628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 |
static void gfs2_ordered_write(struct gfs2_sbd *sdp) { struct gfs2_bufdata *bd; struct buffer_head *bh; LIST_HEAD(written); gfs2_log_lock(sdp); while (!list_empty(&sdp->sd_log_le_ordered)) { bd = list_entry(sdp->sd_log_le_ordered.next, struct gfs2_bufdata, bd_le.le_list); list_move(&bd->bd_le.le_list, &written); bh = bd->bd_bh; if (!buffer_dirty(bh)) continue; get_bh(bh); gfs2_log_unlock(sdp); lock_buffer(bh); |
b8e7cbb65 [GFS2] Add writep... |
644 |
if (buffer_mapped(bh) && test_clear_buffer_dirty(bh)) { |
d7b616e25 [GFS2] Clean up o... |
645 |
bh->b_end_io = end_buffer_write_sync; |
c969f58ca GFS2: Update the ... |
646 |
submit_bh(WRITE_SYNC_PLUG, bh); |
d7b616e25 [GFS2] Clean up o... |
647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 |
} else { unlock_buffer(bh); brelse(bh); } gfs2_log_lock(sdp); } list_splice(&written, &sdp->sd_log_le_ordered); gfs2_log_unlock(sdp); } static void gfs2_ordered_wait(struct gfs2_sbd *sdp) { struct gfs2_bufdata *bd; struct buffer_head *bh; gfs2_log_lock(sdp); while (!list_empty(&sdp->sd_log_le_ordered)) { bd = list_entry(sdp->sd_log_le_ordered.prev, struct gfs2_bufdata, bd_le.le_list); bh = bd->bd_bh; if (buffer_locked(bh)) { get_bh(bh); gfs2_log_unlock(sdp); wait_on_buffer(bh); brelse(bh); gfs2_log_lock(sdp); continue; } list_del_init(&bd->bd_le.le_list); } gfs2_log_unlock(sdp); } |
b3b94faa5 [GFS2] The core o... |
678 |
/** |
b09e593d7 [GFS2] Fix a ref ... |
679 |
* gfs2_log_flush - flush incore transaction(s) |
b3b94faa5 [GFS2] The core o... |
680 681 682 683 |
* @sdp: the filesystem * @gl: The glock structure to flush. If NULL, flush the whole incore log * */ |
2bcd610d2 [GFS2] Don't add ... |
684 |
void __gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl) |
b3b94faa5 [GFS2] The core o... |
685 686 |
{ struct gfs2_ail *ai; |
484adff8a [GFS2] Update loc... |
687 |
down_write(&sdp->sd_log_flush_lock); |
f55ab26a8 [GFS2] Use mutice... |
688 |
|
2bcd610d2 [GFS2] Don't add ... |
689 690 691 692 |
/* Log might have been flushed while we waited for the flush lock */ if (gl && !test_bit(GLF_LFLUSH, &gl->gl_flags)) { up_write(&sdp->sd_log_flush_lock); return; |
f55ab26a8 [GFS2] Use mutice... |
693 |
} |
63997775b GFS2: Add tracepo... |
694 |
trace_gfs2_log_flush(sdp, 1); |
f55ab26a8 [GFS2] Use mutice... |
695 |
|
b09e593d7 [GFS2] Fix a ref ... |
696 697 698 |
ai = kzalloc(sizeof(struct gfs2_ail), GFP_NOFS | __GFP_NOFAIL); INIT_LIST_HEAD(&ai->ai_ail1_list); INIT_LIST_HEAD(&ai->ai_ail2_list); |
b3b94faa5 [GFS2] The core o... |
699 |
|
16615be18 [GFS2] Clean up j... |
700 701 702 703 704 705 706 707 708 709 710 711 |
if (sdp->sd_log_num_buf != sdp->sd_log_commited_buf) { printk(KERN_INFO "GFS2: log buf %u %u ", sdp->sd_log_num_buf, sdp->sd_log_commited_buf); gfs2_assert_withdraw(sdp, 0); } if (sdp->sd_log_num_databuf != sdp->sd_log_commited_databuf) { printk(KERN_INFO "GFS2: log databuf %u %u ", sdp->sd_log_num_databuf, sdp->sd_log_commited_databuf); gfs2_assert_withdraw(sdp, 0); } |
b3b94faa5 [GFS2] The core o... |
712 713 |
gfs2_assert_withdraw(sdp, sdp->sd_log_num_revoke == sdp->sd_log_commited_revoke); |
b3b94faa5 [GFS2] The core o... |
714 715 716 |
sdp->sd_log_flush_head = sdp->sd_log_head; sdp->sd_log_flush_wrapped = 0; ai->ai_first = sdp->sd_log_flush_head; |
d7b616e25 [GFS2] Clean up o... |
717 |
gfs2_ordered_write(sdp); |
b3b94faa5 [GFS2] The core o... |
718 |
lops_before_commit(sdp); |
d7b616e25 [GFS2] Clean up o... |
719 |
gfs2_ordered_wait(sdp); |
16615be18 [GFS2] Clean up j... |
720 |
if (sdp->sd_log_head != sdp->sd_log_flush_head) |
b3b94faa5 [GFS2] The core o... |
721 |
log_flush_commit(sdp); |
2332c4435 [GFS2] assertion ... |
722 723 |
else if (sdp->sd_log_tail != current_tail(sdp) && !sdp->sd_log_idle){ gfs2_log_lock(sdp); |
fd041f0b4 [GFS2] Use atomic... |
724 |
atomic_dec(&sdp->sd_log_blks_free); /* Adjust for unreserved buffer */ |
63997775b GFS2: Add tracepo... |
725 |
trace_gfs2_log_blocks(sdp, -1); |
2332c4435 [GFS2] assertion ... |
726 |
gfs2_log_unlock(sdp); |
b3b94faa5 [GFS2] The core o... |
727 |
log_write_header(sdp, 0, PULL); |
2332c4435 [GFS2] assertion ... |
728 |
} |
b3b94faa5 [GFS2] The core o... |
729 |
lops_after_commit(sdp, ai); |
b09e593d7 [GFS2] Fix a ref ... |
730 |
|
fe1a698ff [GFS2] Fix bug wh... |
731 732 |
gfs2_log_lock(sdp); sdp->sd_log_head = sdp->sd_log_flush_head; |
faa31ce85 [GFS2] Tidy up log.c |
733 734 |
sdp->sd_log_blks_reserved = 0; sdp->sd_log_commited_buf = 0; |
2332c4435 [GFS2] assertion ... |
735 |
sdp->sd_log_commited_databuf = 0; |
faa31ce85 [GFS2] Tidy up log.c |
736 |
sdp->sd_log_commited_revoke = 0; |
b3b94faa5 [GFS2] The core o... |
737 |
|
b3b94faa5 [GFS2] The core o... |
738 739 740 741 742 |
if (!list_empty(&ai->ai_ail1_list)) { list_add(&ai->ai_list, &sdp->sd_ail1_list); ai = NULL; } gfs2_log_unlock(sdp); |
63997775b GFS2: Add tracepo... |
743 |
trace_gfs2_log_flush(sdp, 0); |
484adff8a [GFS2] Update loc... |
744 |
up_write(&sdp->sd_log_flush_lock); |
b3b94faa5 [GFS2] The core o... |
745 746 747 748 749 750 |
kfree(ai); } static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr) { |
2332c4435 [GFS2] assertion ... |
751 |
unsigned int reserved; |
ac39aadd0 [GFS2] Fix assert... |
752 |
unsigned int unused; |
b3b94faa5 [GFS2] The core o... |
753 754 755 756 |
gfs2_log_lock(sdp); sdp->sd_log_commited_buf += tr->tr_num_buf_new - tr->tr_num_buf_rm; |
2332c4435 [GFS2] assertion ... |
757 758 759 760 |
sdp->sd_log_commited_databuf += tr->tr_num_databuf_new - tr->tr_num_databuf_rm; gfs2_assert_withdraw(sdp, (((int)sdp->sd_log_commited_buf) >= 0) || (((int)sdp->sd_log_commited_databuf) >= 0)); |
b3b94faa5 [GFS2] The core o... |
761 762 |
sdp->sd_log_commited_revoke += tr->tr_num_revoke - tr->tr_num_revoke_rm; gfs2_assert_withdraw(sdp, ((int)sdp->sd_log_commited_revoke) >= 0); |
2332c4435 [GFS2] assertion ... |
763 |
reserved = calc_reserved(sdp); |
62be1f716 [GFS2] fix assert... |
764 |
gfs2_assert_withdraw(sdp, sdp->sd_log_blks_reserved + tr->tr_reserved >= reserved); |
ac39aadd0 [GFS2] Fix assert... |
765 |
unused = sdp->sd_log_blks_reserved - reserved + tr->tr_reserved; |
ac39aadd0 [GFS2] Fix assert... |
766 |
atomic_add(unused, &sdp->sd_log_blks_free); |
63997775b GFS2: Add tracepo... |
767 |
trace_gfs2_log_blocks(sdp, unused); |
fd041f0b4 [GFS2] Use atomic... |
768 |
gfs2_assert_withdraw(sdp, atomic_read(&sdp->sd_log_blks_free) <= |
2332c4435 [GFS2] assertion ... |
769 |
sdp->sd_jdesc->jd_blocks); |
b3b94faa5 [GFS2] The core o... |
770 771 772 773 |
sdp->sd_log_blks_reserved = reserved; gfs2_log_unlock(sdp); } |
d0109bfa8 [GFS2] Only do lo... |
774 775 776 777 778 779 780 781 782 783 784 785 786 787 |
static void buf_lo_incore_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr) { struct list_head *head = &tr->tr_list_buf; struct gfs2_bufdata *bd; gfs2_log_lock(sdp); while (!list_empty(head)) { bd = list_entry(head->next, struct gfs2_bufdata, bd_list_tr); list_del_init(&bd->bd_list_tr); tr->tr_num_buf--; } gfs2_log_unlock(sdp); gfs2_assert_warn(sdp, !tr->tr_num_buf); } |
b3b94faa5 [GFS2] The core o... |
788 789 790 791 792 793 794 795 796 797 798 |
/** * gfs2_log_commit - Commit a transaction to the log * @sdp: the filesystem * @tr: the transaction * * Returns: errno */ void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr) { log_refund(sdp, tr); |
d0109bfa8 [GFS2] Only do lo... |
799 |
buf_lo_incore_commit(sdp, tr); |
b3b94faa5 [GFS2] The core o... |
800 |
|
484adff8a [GFS2] Update loc... |
801 |
up_read(&sdp->sd_log_flush_lock); |
b3b94faa5 [GFS2] The core o... |
802 |
|
b3b94faa5 [GFS2] The core o... |
803 |
gfs2_log_lock(sdp); |
b004157ab [GFS2] Fix journa... |
804 805 806 |
if (sdp->sd_log_num_buf > gfs2_tune_get(sdp, gt_incore_log_blocks)) wake_up_process(sdp->sd_logd_process); gfs2_log_unlock(sdp); |
b3b94faa5 [GFS2] The core o... |
807 808 809 810 811 812 813 814 815 816 |
} /** * gfs2_log_shutdown - write a shutdown header into a journal * @sdp: the filesystem * */ void gfs2_log_shutdown(struct gfs2_sbd *sdp) { |
484adff8a [GFS2] Update loc... |
817 |
down_write(&sdp->sd_log_flush_lock); |
b3b94faa5 [GFS2] The core o... |
818 |
|
b3b94faa5 [GFS2] The core o... |
819 |
gfs2_assert_withdraw(sdp, !sdp->sd_log_blks_reserved); |
b3b94faa5 [GFS2] The core o... |
820 821 822 823 824 825 826 827 |
gfs2_assert_withdraw(sdp, !sdp->sd_log_num_buf); gfs2_assert_withdraw(sdp, !sdp->sd_log_num_revoke); gfs2_assert_withdraw(sdp, !sdp->sd_log_num_rg); gfs2_assert_withdraw(sdp, !sdp->sd_log_num_databuf); gfs2_assert_withdraw(sdp, list_empty(&sdp->sd_ail1_list)); sdp->sd_log_flush_head = sdp->sd_log_head; sdp->sd_log_flush_wrapped = 0; |
2332c4435 [GFS2] assertion ... |
828 829 |
log_write_header(sdp, GFS2_LOG_HEAD_UNMOUNT, (sdp->sd_log_tail == current_tail(sdp)) ? 0 : PULL); |
b3b94faa5 [GFS2] The core o... |
830 |
|
fd041f0b4 [GFS2] Use atomic... |
831 |
gfs2_assert_warn(sdp, atomic_read(&sdp->sd_log_blks_free) == sdp->sd_jdesc->jd_blocks); |
a74604bee [GFS2] sem -> mut... |
832 833 |
gfs2_assert_warn(sdp, sdp->sd_log_head == sdp->sd_log_tail); gfs2_assert_warn(sdp, list_empty(&sdp->sd_ail2_list)); |
b3b94faa5 [GFS2] The core o... |
834 835 |
sdp->sd_log_head = sdp->sd_log_flush_head; |
b3b94faa5 [GFS2] The core o... |
836 |
sdp->sd_log_tail = sdp->sd_log_head; |
484adff8a [GFS2] Update loc... |
837 |
up_write(&sdp->sd_log_flush_lock); |
b3b94faa5 [GFS2] The core o... |
838 |
} |
a25311c8e [GFS2] Move gfs2_... |
839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 |
/** * gfs2_meta_syncfs - sync all the buffers in a filesystem * @sdp: the filesystem * */ void gfs2_meta_syncfs(struct gfs2_sbd *sdp) { gfs2_log_flush(sdp, NULL); for (;;) { gfs2_ail1_start(sdp, DIO_ALL); if (gfs2_ail1_empty(sdp, DIO_ALL)) break; msleep(10); } } |
ec69b1888 [GFS2] Move gfs2_... |
856 857 858 859 860 861 862 863 864 865 866 867 |
/** * gfs2_logd - Update log tail as Active Items get flushed to in-place blocks * @sdp: Pointer to GFS2 superblock * * Also, periodically check to make sure that we're using the most recent * journal index. */ int gfs2_logd(void *data) { struct gfs2_sbd *sdp = data; |
ec69b1888 [GFS2] Move gfs2_... |
868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 |
unsigned long t; int need_flush; while (!kthread_should_stop()) { /* Advance the log tail */ t = sdp->sd_log_flush_time + gfs2_tune_get(sdp, gt_log_flush_secs) * HZ; gfs2_ail1_empty(sdp, DIO_ALL); gfs2_log_lock(sdp); need_flush = sdp->sd_log_num_buf > gfs2_tune_get(sdp, gt_incore_log_blocks); gfs2_log_unlock(sdp); if (need_flush || time_after_eq(jiffies, t)) { gfs2_log_flush(sdp, NULL); sdp->sd_log_flush_time = jiffies; } |
ec69b1888 [GFS2] Move gfs2_... |
885 886 887 888 889 890 891 892 |
t = gfs2_tune_get(sdp, gt_logd_secs) * HZ; if (freezing(current)) refrigerator(); schedule_timeout_interruptible(t); } return 0; } |