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