ReactOS 0.4.15-dev-8093-g3285f69
revoke.c
Go to the documentation of this file.
1/*
2 * linux/fs/jbd/revoke.c
3 *
4 * Written by Stephen C. Tweedie <sct@redhat.com>, 2000
5 *
6 * Copyright 2000 Red Hat corp --- All Rights Reserved
7 *
8 * This file is part of the Linux kernel and is made available under
9 * the terms of the GNU General Public License, version 2, or at your
10 * option, any later version, incorporated herein by reference.
11 *
12 * Journal revoke routines for the generic filesystem journaling code;
13 * part of the ext2fs journaling system.
14 *
15 * Revoke is the mechanism used to prevent old log records for deleted
16 * metadata from being replayed on top of newer data using the same
17 * blocks. The revoke mechanism is used in two separate places:
18 *
19 * + Commit: during commit we write the entire list of the current
20 * transaction's revoked blocks to the journal
21 *
22 * + Recovery: during recovery we record the transaction ID of all
23 * revoked blocks. If there are multiple revoke records in the log
24 * for a single block, only the last one counts, and if there is a log
25 * entry for a block beyond the last revoke, then that log entry still
26 * gets replayed.
27 *
28 * We can get interactions between revokes and new log data within a
29 * single transaction:
30 *
31 * Block is revoked and then journaled:
32 * The desired end result is the journaling of the new block, so we
33 * cancel the revoke before the transaction commits.
34 *
35 * Block is journaled and then revoked:
36 * The revoke must take precedence over the write of the block, so we
37 * need either to cancel the journal entry or to write the revoke
38 * later in the log than the log block. In this case, we choose the
39 * latter: journaling a block cancels any revoke record for that block
40 * in the current transaction, so any revoke for that block in the
41 * transaction must have happened after the block was journaled and so
42 * the revoke must take precedence.
43 *
44 * Block is revoked and then written as data:
45 * The data write is allowed to succeed, but the revoke is _not_
46 * cancelled. We still need to prevent old log records from
47 * overwriting the new data. We don't even need to clear the revoke
48 * bit here.
49 *
50 * Revoke information on buffers is a tri-state value:
51 *
52 * RevokeValid clear: no cached revoke status, need to look it up
53 * RevokeValid set, Revoked clear:
54 * buffer has not been revoked, and cancel_revoke
55 * need do nothing.
56 * RevokeValid set, Revoked set:
57 * buffer has been revoked.
58 */
59
60#ifndef __KERNEL__
61#include "jfs_user.h"
62#else
63#include <linux/time.h>
64#include <linux/fs.h>
65#include <linux/jbd.h>
66#include <linux/errno.h>
67#include <linux/slab.h>
68#include <linux/list.h>
69#include <linux/init.h>
70#endif
71#include <linux/log2.h>
72
75
76/* Each revoke record represents one single revoked block. During
77 journal replay, this involves recording the transaction ID of the
78 last transaction to revoke this block. */
79
81{
83 tid_t sequence; /* Used for recovery only */
84 unsigned long blocknr;
85};
86
87
88/* The revoke table is just a simple hash table of revoke records. */
90{
91 /* It is conceivable that we might want a larger hash table
92 * for recovery. Must be a power of two. */
96};
97
98
99#ifdef __KERNEL__
100static void write_one_revoke_record(journal_t *, transaction_t *,
101 struct journal_head **, int *,
102 struct jbd_revoke_record_s *);
103static void flush_descriptor(journal_t *, struct journal_head *, int);
104#endif
105
106/* Utility functions to maintain the revoke table */
107
108/* Borrowed from buffer.c: this is a tried and tested block hash function */
109static inline int hash(journal_t *journal, unsigned long block)
110{
111 struct jbd_revoke_table_s *table = journal->j_revoke;
112 int hash_shift = table->hash_shift;
113
114 return ((block << (hash_shift - 6)) ^
115 (block >> 13) ^
116 (block << (hash_shift - 12))) & (table->hash_size - 1);
117}
118
119static int insert_revoke_hash(journal_t *journal, unsigned long blocknr,
120 tid_t seq)
121{
122 struct list_head *hash_list;
124
125repeat:
126 record = (struct jbd_revoke_record_s *)
128 if (!record)
129 goto oom;
130
131 record->sequence = seq;
132 record->blocknr = blocknr;
133 hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
134 jbd_lock(&journal->j_revoke_lock);
135 list_add(&record->hash, hash_list);
136 jbd_unlock(&journal->j_revoke_lock);
137 return 0;
138
139oom:
140 if (!journal_oom_retry)
141 return -ENOMEM;
142 jbd_debug(1, "ENOMEM in %s, retrying\n", __FUNCTION__);
143 yield();
144 goto repeat;
145}
146
147/* Find a revoke record in the journal's hash table. */
148
149static struct jbd_revoke_record_s *find_revoke_record(journal_t *journal,
150 unsigned long blocknr)
151{
152 struct list_head *hash_list;
154
155 hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
156
157 jbd_lock(&journal->j_revoke_lock);
158 record = (struct jbd_revoke_record_s *) hash_list->next;
159 while (&(record->hash) != hash_list) {
160 if (record->blocknr == blocknr) {
161 jbd_unlock(&journal->j_revoke_lock);
162 return record;
163 }
164 record = (struct jbd_revoke_record_s *) record->hash.next;
165 }
166 jbd_unlock(&journal->j_revoke_lock);
167 return NULL;
168}
169
171{
172 revoke_record_cache = kmem_cache_create("revoke_record",
173 sizeof(struct jbd_revoke_record_s),
174 0,
176 NULL);
177 if (revoke_record_cache == 0)
178 return -ENOMEM;
179
180 revoke_table_cache = kmem_cache_create("revoke_table",
181 sizeof(struct jbd_revoke_table_s),
182 0, SLAB_TEMPORARY, NULL);
183 if (revoke_table_cache == 0) {
186 return -ENOMEM;
187 }
188 return 0;
189}
190
192{
197}
198
199/* Initialise the revoke table for a given journal to a given size. */
200
201int journal_init_revoke(journal_t *journal, int hash_size)
202{
203 int shift, tmp;
204
205 J_ASSERT (journal->j_revoke_table[0] == NULL);
206
207 shift = 0;
208 tmp = hash_size;
209 while ((tmp >>= 1UL) != 0UL)
210 shift++;
211
212 journal->j_revoke_table[0] = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL);
213 if (!journal->j_revoke_table[0])
214 return -ENOMEM;
215 journal->j_revoke = journal->j_revoke_table[0];
216
217 /* Check that the hash_size is a power of two */
218 J_ASSERT(is_power_of_2(hash_size));
219
220 journal->j_revoke->hash_size = hash_size;
221
222 journal->j_revoke->hash_shift = shift;
223
224 journal->j_revoke->hash_table =
225 kmalloc(hash_size * sizeof(struct list_head), GFP_KERNEL);
226 if (!journal->j_revoke->hash_table) {
227 kmem_cache_free(revoke_table_cache, journal->j_revoke_table[0]);
228 journal->j_revoke = NULL;
229 return -ENOMEM;
230 }
231
232 for (tmp = 0; tmp < hash_size; tmp++)
233 INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]);
234
235 journal->j_revoke_table[1] = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL);
236 if (!journal->j_revoke_table[1]) {
237 kfree(journal->j_revoke_table[0]->hash_table);
238 kmem_cache_free(revoke_table_cache, journal->j_revoke_table[0]);
239 return -ENOMEM;
240 }
241
242 journal->j_revoke = journal->j_revoke_table[1];
243
244 /* Check that the hash_size is a power of two */
245 J_ASSERT(is_power_of_2(hash_size));
246
247 journal->j_revoke->hash_size = hash_size;
248
249 journal->j_revoke->hash_shift = shift;
250
251 journal->j_revoke->hash_table =
252 kmalloc(hash_size * sizeof(struct list_head), GFP_KERNEL);
253 if (!journal->j_revoke->hash_table) {
254 kfree(journal->j_revoke_table[0]->hash_table);
255 kmem_cache_free(revoke_table_cache, journal->j_revoke_table[0]);
256 kmem_cache_free(revoke_table_cache, journal->j_revoke_table[1]);
257 journal->j_revoke = NULL;
258 return -ENOMEM;
259 }
260
261 for (tmp = 0; tmp < hash_size; tmp++)
262 INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]);
263
264 jbd_lock_init(&journal->j_revoke_lock);
265
266 return 0;
267}
268
269/* Destoy a journal's revoke table. The table must already be empty! */
270
271void journal_destroy_revoke(journal_t *journal)
272{
274 struct list_head *hash_list;
275 int i;
276
277 table = journal->j_revoke_table[0];
278 if (!table)
279 return;
280
281 for (i=0; i<table->hash_size; i++) {
282 hash_list = &table->hash_table[i];
283 J_ASSERT (list_empty(hash_list));
284 }
285
286 kfree(table->hash_table);
288 journal->j_revoke = NULL;
289
290 table = journal->j_revoke_table[1];
291 if (!table)
292 return;
293
294 for (i=0; i<table->hash_size; i++) {
295 hash_list = &table->hash_table[i];
296 J_ASSERT (list_empty(hash_list));
297 }
298
299 kfree(table->hash_table);
301 journal->j_revoke = NULL;
302}
303
304
305#ifdef __KERNEL__
306
307/*
308 * journal_revoke: revoke a given buffer_head from the journal. This
309 * prevents the block from being replayed during recovery if we take a
310 * crash after this current transaction commits. Any subsequent
311 * metadata writes of the buffer in this transaction cancel the
312 * revoke.
313 *
314 * Note that this call may block --- it is up to the caller to make
315 * sure that there are no further calls to journal_write_metadata
316 * before the revoke is complete. In ext3, this implies calling the
317 * revoke before clearing the block bitmap when we are deleting
318 * metadata.
319 *
320 * Revoke performs a journal_forget on any buffer_head passed in as a
321 * parameter, but does _not_ forget the buffer_head if the bh was only
322 * found implicitly.
323 *
324 * bh_in may not be a journalled buffer - it may have come off
325 * the hash tables without an attached journal_head.
326 *
327 * If bh_in is non-zero, journal_revoke() will decrement its b_count
328 * by one.
329 */
330
331int journal_revoke(handle_t *handle, unsigned long blocknr,
332 struct buffer_head *bh_in)
333{
334 struct buffer_head *bh = NULL;
335 journal_t *journal;
336 struct block_device *bdev;
337 int err;
338
339 might_sleep();
340 if (bh_in)
341 BUFFER_TRACE(bh_in, "enter");
342
343 journal = handle->h_transaction->t_journal;
345 J_ASSERT (!"Cannot set revoke feature!");
346 return -EINVAL;
347 }
348
349 bdev = journal->j_fs_dev;
350 bh = bh_in;
351
352 if (!bh) {
353 bh = __find_get_block(bdev, blocknr, journal->j_blocksize);
354 if (bh)
355 BUFFER_TRACE(bh, "found on hash");
356 }
357#ifdef JBD_EXPENSIVE_CHECKING
358 else {
359 struct buffer_head *bh2;
360
361 /* If there is a different buffer_head lying around in
362 * memory anywhere... */
363 bh2 = __find_get_block(bdev, blocknr, journal->j_blocksize);
364 if (bh2) {
365 /* ... and it has RevokeValid status... */
366 if (bh2 != bh && buffer_revokevalid(bh2))
367 /* ...then it better be revoked too,
368 * since it's illegal to create a revoke
369 * record against a buffer_head which is
370 * not marked revoked --- that would
371 * risk missing a subsequent revoke
372 * cancel. */
373 J_ASSERT_BH(bh2, buffer_revoked(bh2));
374 put_bh(bh2);
375 }
376 }
377#endif
378
379 /* We really ought not ever to revoke twice in a row without
380 first having the revoke cancelled: it's illegal to free a
381 block twice without allocating it in between! */
382 if (bh) {
383 if (!J_EXPECT_BH(bh, !buffer_revoked(bh),
384 "inconsistent data on disk")) {
385 if (!bh_in)
386 brelse(bh);
387 return -EIO;
388 }
389 set_buffer_revoked(bh);
390 set_buffer_revokevalid(bh);
391 if (bh_in) {
392 BUFFER_TRACE(bh_in, "call journal_forget");
393 journal_forget(handle, bh_in);
394 } else {
395 BUFFER_TRACE(bh, "call brelse");
396 __brelse(bh);
397 }
398 }
399
400 jbd_debug(2, "insert revoke for block %lu, bh_in=%p\n", blocknr, bh_in);
401 err = insert_revoke_hash(journal, blocknr,
402 handle->h_transaction->t_tid);
403 BUFFER_TRACE(bh_in, "exit");
404 return err;
405}
406
407/*
408 * Cancel an outstanding revoke. For use only internally by the
409 * journaling code (called from journal_get_write_access).
410 *
411 * We trust buffer_revoked() on the buffer if the buffer is already
412 * being journaled: if there is no revoke pending on the buffer, then we
413 * don't do anything here.
414 *
415 * This would break if it were possible for a buffer to be revoked and
416 * discarded, and then reallocated within the same transaction. In such
417 * a case we would have lost the revoked bit, but when we arrived here
418 * the second time we would still have a pending revoke to cancel. So,
419 * do not trust the Revoked bit on buffers unless RevokeValid is also
420 * set.
421 *
422 * The caller must have the journal locked.
423 */
424int journal_cancel_revoke(handle_t *handle, struct journal_head *jh)
425{
427 journal_t *journal = handle->h_transaction->t_journal;
428 int need_cancel;
429 int did_revoke = 0; /* akpm: debug */
430 struct buffer_head *bh = jh2bh(jh);
431
432 jbd_debug(4, "journal_head %p, cancelling revoke\n", jh);
433
434 /* Is the existing Revoke bit valid? If so, we trust it, and
435 * only perform the full cancel if the revoke bit is set. If
436 * not, we can't trust the revoke bit, and we need to do the
437 * full search for a revoke record. */
438 if (test_set_buffer_revokevalid(bh)) {
439 need_cancel = test_clear_buffer_revoked(bh);
440 } else {
441 need_cancel = 1;
442 clear_buffer_revoked(bh);
443 }
444
445 if (need_cancel) {
446 record = find_revoke_record(journal, (unsigned long)bh->b_blocknr);
447 if (record) {
448 jbd_debug(4, "cancelled existing revoke on "
449 "blocknr %llu\n", (u64)bh->b_blocknr);
450 jbd_lock(&journal->j_revoke_lock);
451 list_del(&record->hash);
452 jbd_unlock(&journal->j_revoke_lock);
454 did_revoke = 1;
455 }
456 }
457
458#ifdef JBD_EXPENSIVE_CHECKING
459 /* There better not be one left behind by now! */
460 record = find_revoke_record(journal, bh->b_blocknr);
461 J_ASSERT_JH(jh, record == NULL);
462#endif
463
464 /* Finally, have we just cleared revoke on an unhashed
465 * buffer_head? If so, we'd better make sure we clear the
466 * revoked status on any hashed alias too, otherwise the revoke
467 * state machine will get very upset later on. */
468 if (need_cancel) {
469 struct buffer_head *bh2;
470 bh2 = __find_get_block(bh->b_bdev, bh->b_blocknr, bh->b_size);
471 if (bh2) {
472 if (bh2 != bh)
473 clear_buffer_revoked(bh2);
474 __brelse(bh2);
475 }
476 }
477 return did_revoke;
478}
479
480/* journal_switch_revoke table select j_revoke for next transaction
481 * we do not want to suspend any processing until all revokes are
482 * written -bzzz
483 */
484void journal_switch_revoke_table(journal_t *journal)
485{
486 int i;
487
488 if (journal->j_revoke == journal->j_revoke_table[0])
489 journal->j_revoke = journal->j_revoke_table[1];
490 else
491 journal->j_revoke = journal->j_revoke_table[0];
492
493 for (i = 0; i < journal->j_revoke->hash_size; i++)
494 INIT_LIST_HEAD(&journal->j_revoke->hash_table[i]);
495}
496
497/*
498 * Write revoke records to the journal for all entries in the current
499 * revoke hash, deleting the entries as we go.
500 *
501 * Called with the journal lock held.
502 */
503
504void journal_write_revoke_records(journal_t *journal,
505 transaction_t *transaction)
506{
507 struct journal_head *descriptor;
509 struct jbd_revoke_table_s *revoke;
510 struct list_head *hash_list;
511 int i, offset, count;
512
514 offset = 0;
515 count = 0;
516
517 /* select revoke table for committing transaction */
518 revoke = journal->j_revoke == journal->j_revoke_table[0] ?
519 journal->j_revoke_table[1] : journal->j_revoke_table[0];
520
521 for (i = 0; i < revoke->hash_size; i++) {
522 hash_list = &revoke->hash_table[i];
523
524 while (!list_empty(hash_list)) {
525 record = (struct jbd_revoke_record_s *)
526 hash_list->next;
527 write_one_revoke_record(journal, transaction,
529 record);
530 count++;
531 list_del(&record->hash);
533 }
534 }
535 if (descriptor)
536 flush_descriptor(journal, descriptor, offset);
537 jbd_debug(1, "Wrote %d revoke records\n", count);
538}
539
540/*
541 * Write out one revoke record. We need to create a new descriptor
542 * block if the old one is full or if we have not already created one.
543 */
544
545static void write_one_revoke_record(journal_t *journal,
546 transaction_t *transaction,
547 struct journal_head **descriptorp,
548 int *offsetp,
550{
551 struct journal_head *descriptor;
552 int offset;
554
555 /* If we are already aborting, this all becomes a noop. We
556 still need to go round the loop in
557 journal_write_revoke_records in order to free all of the
558 revoke records: only the IO to the journal is omitted. */
559 if (is_journal_aborted(journal))
560 return;
561
562 descriptor = *descriptorp;
563 offset = *offsetp;
564
565 /* Make sure we have a descriptor with space left for the record */
566 if (descriptor) {
567 if (offset == journal->j_blocksize) {
568 flush_descriptor(journal, descriptor, offset);
570 }
571 }
572
573 if (!descriptor) {
575 if (!descriptor)
576 return;
577 header = (journal_header_t *) &jh2bh(descriptor)->b_data[0];
579 header->h_blocktype = cpu_to_be32(JFS_REVOKE_BLOCK);
580 header->h_sequence = cpu_to_be32(transaction->t_tid);
581
582 /* Record it so that we can wait for IO completion later */
583 JBUFFER_TRACE(descriptor, "file as BJ_LogCtl");
585
587 *descriptorp = descriptor;
588 }
589
590 * ((__be32 *)(&jh2bh(descriptor)->b_data[offset])) =
591 cpu_to_be32(record->blocknr);
592 offset += 4;
593 *offsetp = offset;
594}
595
596/*
597 * Flush a revoke descriptor out to the journal. If we are aborting,
598 * this is a noop; otherwise we are generating a buffer which needs to
599 * be waited for during commit, so it has to go onto the appropriate
600 * journal buffer list.
601 */
602
603static void flush_descriptor(journal_t *journal,
604 struct journal_head *descriptor,
605 int offset)
606{
608 struct buffer_head *bh = jh2bh(descriptor);
609
610 if (is_journal_aborted(journal)) {
611 put_bh(bh);
612 return;
613 }
614
615 header = (journal_revoke_header_t *) jh2bh(descriptor)->b_data;
616 header->r_count = cpu_to_be32(offset);
617 set_buffer_jwrite(bh);
618 BUFFER_TRACE(bh, "write");
619 set_buffer_dirty(bh);
620 ll_rw_block(SWRITE, 1, &bh);
621}
622#endif
623
624/*
625 * Revoke support for recovery.
626 *
627 * Recovery needs to be able to:
628 *
629 * record all revoke records, including the tid of the latest instance
630 * of each revoke in the journal
631 *
632 * check whether a given block in a given transaction should be replayed
633 * (ie. has not been revoked by a revoke record in that or a subsequent
634 * transaction)
635 *
636 * empty the revoke table after recovery.
637 */
638
639/*
640 * First, setting revoke records. We create a new revoke record for
641 * every block ever revoked in the log as we scan it for recovery, and
642 * we update the existing records if we find multiple revokes for a
643 * single block.
644 */
645
646int journal_set_revoke(journal_t *journal,
647 unsigned long blocknr,
649{
651
653 if (record) {
654 /* If we have multiple occurrences, only record the
655 * latest sequence number in the hashed record */
656 if (tid_gt(sequence, record->sequence))
657 record->sequence = sequence;
658 return 0;
659 }
660 return insert_revoke_hash(journal, blocknr, sequence);
661}
662
663/*
664 * Test revoke records. For a given block referenced in the log, has
665 * that block been revoked? A revoke record with a given transaction
666 * sequence number revokes all blocks in that transaction and earlier
667 * ones, but later transactions still need replayed.
668 */
669
670int journal_test_revoke(journal_t *journal,
671 unsigned long blocknr,
673{
675
677 if (!record)
678 return 0;
679 if (tid_gt(sequence, record->sequence))
680 return 0;
681 return 1;
682}
683
684/*
685 * Finally, once recovery is over, we need to clear the revoke table so
686 * that it can be reused by the running filesystem.
687 */
688
689void journal_clear_revoke(journal_t *journal)
690{
691 int i;
692 struct list_head *hash_list;
694 struct jbd_revoke_table_s *revoke;
695
696 revoke = journal->j_revoke;
697
698 for (i = 0; i < revoke->hash_size; i++) {
699 hash_list = &revoke->hash_table[i];
700 while (!list_empty(hash_list)) {
701 record = (struct jbd_revoke_record_s*) hash_list->next;
702 list_del(&record->hash);
704 }
705 }
706}
static struct recvd_message * sequence
Definition: SystemMenu.c:63
#define EINVAL
Definition: acclib.h:90
#define ENOMEM
Definition: acclib.h:84
#define EIO
Definition: acclib.h:81
#define __init
Definition: aclinux.h:211
static int list_empty(struct list_entry *head)
Definition: list.h:58
static void list_add(struct list_entry *entry, struct list_entry *prev, struct list_entry *next)
Definition: list.h:64
ULONG64 u64
Definition: btrfs.h:15
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))
#define NULL
Definition: types.h:112
#define INIT_LIST_HEAD(ptr)
Definition: list.h:24
static void list_del(struct list_head *entry)
Definition: list.h:89
__u32 __bitwise __be32
Definition: types.h:67
#define __FUNCTION__
Definition: types.h:116
#define is_power_of_2(x)
Definition: memory.c:2306
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLintptr offset
Definition: glext.h:5920
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
tid_t
Definition: ieframe.h:311
#define BJ_LogCtl
Definition: jbd.h:1123
struct journal_revoke_header_s journal_revoke_header_t
#define JFS_REVOKE_BLOCK
Definition: jbd.h:173
static int tid_gt(tid_t x, tid_t y)
Definition: jbd.h:1085
#define JFS_FEATURE_INCOMPAT_REVOKE
Definition: jbd.h:271
#define JFS_MAGIC_NUMBER
Definition: jbd.h:159
struct transaction_s transaction_t
Definition: journal-head.h:14
kmem_cache_t * kmem_cache_create(const char *name, size_t size, size_t offset, unsigned long flags, kmem_cache_cb_t ctor)
Definition: linux.c:48
#define kmalloc(size, gfp)
Definition: module.h:1125
#define SWRITE
Definition: module.h:1178
static void put_bh(struct buffer_head *bh)
Definition: module.h:949
#define SLAB_HWCACHE_ALIGN
Definition: module.h:1131
struct buffer_head * __find_get_block(struct block_device *bdev, sector_t block, unsigned long size)
Definition: linux.c:932
#define GFP_KERNEL
Definition: module.h:668
void kmem_cache_free(kmem_cache_t *kc, void *p)
Definition: linux.c:103
#define GFP_NOFS
Definition: module.h:669
void * kmem_cache_alloc(kmem_cache_t *kc, int flags)
Definition: linux.c:92
#define SLAB_TEMPORARY
Definition: module.h:1133
int kmem_cache_destroy(kmem_cache_t *kc)
Definition: linux.c:82
#define yield()
Definition: module.h:449
void ll_rw_block(int, int, struct buffer_head *bh[])
Definition: linux.c:862
#define kfree(p)
Definition: module.h:1126
#define might_sleep()
Definition: module.h:450
static void brelse(struct buffer_head *bh)
Definition: module.h:955
void __brelse(struct buffer_head *)
Definition: linux.c:808
#define cpu_to_be32
Definition: module.h:156
#define shift
Definition: input.c:1755
#define err(...)
struct journal_head * journal_get_descriptor_buffer(journal_t *journal)
Definition: replay.c:518
int journal_set_features(journal_t *journal, unsigned long compat, unsigned long ro, unsigned long incompat)
Definition: replay.c:804
int journal_forget(handle_t *handle, struct buffer_head *bh)
Definition: replay.c:1447
void journal_file_buffer(struct journal_head *jh, transaction_t *transaction, int jlist)
Definition: replay.c:1408
static struct kmem_cache * revoke_table_cache
Definition: revoke.c:74
static int insert_revoke_hash(journal_t *journal, unsigned long blocknr, tid_t seq)
Definition: revoke.c:119
void journal_destroy_revoke_caches(void)
Definition: revoke.c:191
void journal_destroy_revoke(journal_t *journal)
Definition: revoke.c:271
void journal_clear_revoke(journal_t *journal)
Definition: revoke.c:689
int __init journal_init_revoke_caches(void)
Definition: revoke.c:170
int journal_init_revoke(journal_t *journal, int hash_size)
Definition: revoke.c:201
int journal_set_revoke(journal_t *journal, unsigned long blocknr, tid_t sequence)
Definition: revoke.c:646
static struct kmem_cache * revoke_record_cache
Definition: revoke.c:73
static struct jbd_revoke_record_s * find_revoke_record(journal_t *journal, unsigned long blocknr)
Definition: revoke.c:149
int journal_test_revoke(journal_t *journal, unsigned long blocknr, tid_t sequence)
Definition: revoke.c:670
descriptor
Definition: scsi.h:3951
struct block_device * b_bdev
Definition: module.h:731
size_t b_size
Definition: module.h:734
blkcnt_t b_blocknr
Definition: module.h:733
Definition: _hash_fun.h:40
unsigned long blocknr
Definition: revoke.c:84
struct list_head hash
Definition: revoke.c:82
struct list_head * hash_table
Definition: revoke.c:95
Definition: list.h:15
struct list_head * next
Definition: list.h:16
#define UL
Definition: tui.h:165
static int repeat
Definition: xmllint.c:137
static unsigned int block
Definition: xmlmemory.c:101