Commit b573296a authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] JBD Documentation

Patch from Roger Gammans <roger@computer-surgery.co.uk>

Adds lots of API documentation to the JBD layer.
parent 7260b084
...@@ -141,17 +141,14 @@ you are have done so you need to call journal_dirty_{meta,}data(). ...@@ -141,17 +141,14 @@ you are have done so you need to call journal_dirty_{meta,}data().
Or if you've asked for access to a buffer you now know is now longer Or if you've asked for access to a buffer you now know is now longer
required to be pushed back on the device you can call journal_forget() required to be pushed back on the device you can call journal_forget()
in much the same way as you might have used bforget() in the past. in much the same way as you might have used bforget() in the past.
</para> </para>
<para> <para>
A journal_flush() may be called at any time to commit and checkpoint A journal_flush() may be called at any time to commit and checkpoint
all your transactions. all your transactions.
</para> </para>
<para>
<para>
Then at umount time , in your put_super() (2.4) or write_super() (2.5) Then at umount time , in your put_super() (2.4) or write_super() (2.5)
you can then call journal_destroy() to clean up your in-core journal object. you can then call journal_destroy() to clean up your in-core journal object.
</para> </para>
...@@ -168,8 +165,8 @@ on another journal. Since transactions can't be nested/batched ...@@ -168,8 +165,8 @@ on another journal. Since transactions can't be nested/batched
across differing journals, and another filesystem other than across differing journals, and another filesystem other than
yours (say ext3) may be modified in a later syscall. yours (say ext3) may be modified in a later syscall.
</para> </para>
<para>
<para>
The second case to bear in mind is that journal_start() can The second case to bear in mind is that journal_start() can
block if there isn't enough space in the journal for your transaction block if there isn't enough space in the journal for your transaction
(based on the passed nblocks param) - when it blocks it merely(!) needs to (based on the passed nblocks param) - when it blocks it merely(!) needs to
...@@ -180,10 +177,14 @@ were semaphores and include them in your semaphore ordering rules to prevent ...@@ -180,10 +177,14 @@ were semaphores and include them in your semaphore ordering rules to prevent
deadlocks. Note that journal_extend() has similar blocking behaviour to deadlocks. Note that journal_extend() has similar blocking behaviour to
journal_start() so you can deadlock here just as easily as on journal_start(). journal_start() so you can deadlock here just as easily as on journal_start().
</para> </para>
<para>
Try to reserve the right number of blocks the first time. ;-). <para>
Try to reserve the right number of blocks the first time. ;-). This will
be the maximum number of blocks you are going to touch in this transaction.
I advise having a look at at least ext3_jbd.h to see the basis on which
ext3 uses to make these decisions.
</para> </para>
<para> <para>
Another wriggle to watch out for is your on-disk block allocation strategy. Another wriggle to watch out for is your on-disk block allocation strategy.
why? Because, if you undo a delete, you need to ensure you haven't reused any why? Because, if you undo a delete, you need to ensure you haven't reused any
...@@ -211,6 +212,30 @@ The opportunities for abuse and DOS attacks with this should be obvious, ...@@ -211,6 +212,30 @@ The opportunities for abuse and DOS attacks with this should be obvious,
if you allow unprivileged userspace to trigger codepaths containing these if you allow unprivileged userspace to trigger codepaths containing these
calls. calls.
</para> </para>
<para>
A new feature of jbd since 2.5.25 is commit callbacks with the new
journal_callback_set() function you can now ask the journalling layer
to call you back when the transaction is finally commited to disk, so that
you can do some of your own management. The key to this is the journal_callback
struct, this maintains the internal callback information but you can
extend it like this:-
</para>
<programlisting>
struct myfs_callback_s {
//Data structure element required by jbd..
struct journal_callback for_jbd;
// Stuff for myfs allocated together.
myfs_inode* i_commited;
}
</programlisting>
<para>
this would be useful if you needed to know when data was commited to a
particular inode.
</para>
</sect1> </sect1>
<sect1> <sect1>
......
...@@ -732,14 +732,21 @@ static journal_t * journal_init_common (void) ...@@ -732,14 +732,21 @@ static journal_t * journal_init_common (void)
* need to set up all of the mapping information to tell the journaling * need to set up all of the mapping information to tell the journaling
* system where the journal blocks are. * system where the journal blocks are.
* *
*/
/**
* journal_t * journal_init_dev() - creates an initialises a journal structure
* @bdev: Block device on which to create the journal
* @fs_dev: Device which hold journalled filesystem for this journal.
* @start: Block nr Start of journal.
* @len: Lenght of the journal in blocks.
* @blocksize: blocksize of journalling device
* @returns: a newly created journal_t *
*
* journal_init_dev creates a journal which maps a fixed contiguous * journal_init_dev creates a journal which maps a fixed contiguous
* range of blocks on an arbitrary block device. * range of blocks on an arbitrary block device.
* *
* journal_init_inode creates a journal which maps an on-disk inode as
* the journal. The inode must exist already, must support bmap() and
* must have all data blocks preallocated.
*/ */
journal_t * journal_init_dev(struct block_device *bdev, journal_t * journal_init_dev(struct block_device *bdev,
struct block_device *fs_dev, struct block_device *fs_dev,
int start, int len, int blocksize) int start, int len, int blocksize)
...@@ -764,6 +771,14 @@ journal_t * journal_init_dev(struct block_device *bdev, ...@@ -764,6 +771,14 @@ journal_t * journal_init_dev(struct block_device *bdev,
return journal; return journal;
} }
/**
* journal_t * journal_init_inode () - creates a journal which maps to a inode.
* @inode: An inode to create the journal in
*
* journal_init_inode creates a journal which maps an on-disk inode as
* the journal. The inode must exist already, must support bmap() and
* must have all data blocks preallocated.
*/
journal_t * journal_init_inode (struct inode *inode) journal_t * journal_init_inode (struct inode *inode)
{ {
struct buffer_head *bh; struct buffer_head *bh;
...@@ -852,12 +867,15 @@ static int journal_reset (journal_t *journal) ...@@ -852,12 +867,15 @@ static int journal_reset (journal_t *journal)
return 0; return 0;
} }
/* /**
* int journal_create() - Initialise the new journal file
* @journal: Journal to create. This structure must have been initialised
*
* Given a journal_t structure which tells us which disk blocks we can * Given a journal_t structure which tells us which disk blocks we can
* use, create a new journal superblock and initialise all of the * use, create a new journal superblock and initialise all of the
* journal fields from scratch. */ * journal fields from scratch.
**/
int journal_create (journal_t *journal) int journal_create(journal_t *journal)
{ {
unsigned long blocknr; unsigned long blocknr;
struct buffer_head *bh; struct buffer_head *bh;
...@@ -920,11 +938,14 @@ int journal_create (journal_t *journal) ...@@ -920,11 +938,14 @@ int journal_create (journal_t *journal)
return journal_reset(journal); return journal_reset(journal);
} }
/* /**
* void journal_update_superblock() - Update journal sb on disk.
* @journal: The journal to update.
* @wait: Set to '0' if you don't want to wait for IO completion.
*
* Update a journal's dynamic superblock fields and write it to disk, * Update a journal's dynamic superblock fields and write it to disk,
* optionally waiting for the IO to complete. * optionally waiting for the IO to complete.
*/ */
void journal_update_superblock(journal_t *journal, int wait) void journal_update_superblock(journal_t *journal, int wait)
{ {
journal_superblock_t *sb = journal->j_superblock; journal_superblock_t *sb = journal->j_superblock;
...@@ -1040,12 +1061,14 @@ static int load_superblock(journal_t *journal) ...@@ -1040,12 +1061,14 @@ static int load_superblock(journal_t *journal)
} }
/* /**
* int journal_load() - Read journal from disk.
* @journal: Journal to act on.
*
* Given a journal_t structure which tells us which disk blocks contain * Given a journal_t structure which tells us which disk blocks contain
* a journal, read the journal from disk to initialise the in-memory * a journal, read the journal from disk to initialise the in-memory
* structures. * structures.
*/ */
int journal_load(journal_t *journal) int journal_load(journal_t *journal)
{ {
int err; int err;
...@@ -1090,11 +1113,13 @@ int journal_load(journal_t *journal) ...@@ -1090,11 +1113,13 @@ int journal_load(journal_t *journal)
return -EIO; return -EIO;
} }
/* /**
* void journal_destroy() - Release a journal_t structure.
* @journal: Journal to act on.
*
* Release a journal_t structure once it is no longer in use by the * Release a journal_t structure once it is no longer in use by the
* journaled object. * journaled object.
*/ */
void journal_destroy (journal_t *journal) void journal_destroy (journal_t *journal)
{ {
/* Wait for the commit thread to wake up and die. */ /* Wait for the commit thread to wake up and die. */
...@@ -1131,8 +1156,12 @@ void journal_destroy (journal_t *journal) ...@@ -1131,8 +1156,12 @@ void journal_destroy (journal_t *journal)
} }
/* Published API: Check whether the journal uses all of a given set of /**
* features. Return true (non-zero) if it does. */ *int journal_check_used_features () - Check if features specified are used.
*
* Check whether the journal uses all of a given set of
* features. Return true (non-zero) if it does.
**/
int journal_check_used_features (journal_t *journal, unsigned long compat, int journal_check_used_features (journal_t *journal, unsigned long compat,
unsigned long ro, unsigned long incompat) unsigned long ro, unsigned long incompat)
...@@ -1154,7 +1183,10 @@ int journal_check_used_features (journal_t *journal, unsigned long compat, ...@@ -1154,7 +1183,10 @@ int journal_check_used_features (journal_t *journal, unsigned long compat,
return 0; return 0;
} }
/* Published API: Check whether the journaling code supports the use of /**
* int journal_check_available_features() - Check feature set in journalling layer
*
* Check whether the journaling code supports the use of
* all of a given set of features on this journal. Return true * all of a given set of features on this journal. Return true
* (non-zero) if it can. */ * (non-zero) if it can. */
...@@ -1183,8 +1215,13 @@ int journal_check_available_features (journal_t *journal, unsigned long compat, ...@@ -1183,8 +1215,13 @@ int journal_check_available_features (journal_t *journal, unsigned long compat,
return 0; return 0;
} }
/* Published API: Mark a given journal feature as present on the /**
* superblock. Returns true if the requested features could be set. */ * int journal_set_features () - Mark a given journal feature in the superblock
*
* Mark a given journal feature as present on the
* superblock. Returns true if the requested features could be set.
*
*/
int journal_set_features (journal_t *journal, unsigned long compat, int journal_set_features (journal_t *journal, unsigned long compat,
unsigned long ro, unsigned long incompat) unsigned long ro, unsigned long incompat)
...@@ -1210,12 +1247,12 @@ int journal_set_features (journal_t *journal, unsigned long compat, ...@@ -1210,12 +1247,12 @@ int journal_set_features (journal_t *journal, unsigned long compat,
} }
/* /**
* Published API: * int journal_update_format () - Update on-disk journal structure.
*
* Given an initialised but unloaded journal struct, poke about in the * Given an initialised but unloaded journal struct, poke about in the
* on-disk structure to update it to the most recent supported version. * on-disk structure to update it to the most recent supported version.
*/ */
int journal_update_format (journal_t *journal) int journal_update_format (journal_t *journal)
{ {
journal_superblock_t *sb; journal_superblock_t *sb;
...@@ -1265,7 +1302,10 @@ static int journal_convert_superblock_v1(journal_t *journal, ...@@ -1265,7 +1302,10 @@ static int journal_convert_superblock_v1(journal_t *journal,
} }
/* /**
* int journal_flush () - Flush journal
* @journal: Journal to act on.
*
* Flush all data for a given journal to disk and empty the journal. * Flush all data for a given journal to disk and empty the journal.
* Filesystems can use this when remounting readonly to ensure that * Filesystems can use this when remounting readonly to ensure that
* recovery does not need to happen on remount. * recovery does not need to happen on remount.
...@@ -1319,12 +1359,16 @@ int journal_flush (journal_t *journal) ...@@ -1319,12 +1359,16 @@ int journal_flush (journal_t *journal)
return err; return err;
} }
/* /**
* int journal_wipe() - Wipe journal contents
* @journal: Journal to act on.
* @write: flag (see below)
*
* Wipe out all of the contents of a journal, safely. This will produce * Wipe out all of the contents of a journal, safely. This will produce
* a warning if the journal contains any valid recovery information. * a warning if the journal contains any valid recovery information.
* Must be called between journal_init_*() and journal_load(). * Must be called between journal_init_*() and journal_load().
* *
* If (write) is non-zero, then we wipe out the journal on disk; otherwise * If 'write' is non-zero, then we wipe out the journal on disk; otherwise
* we merely suppress recovery. * we merely suppress recovery.
*/ */
...@@ -1373,43 +1417,11 @@ const char * journal_dev_name(journal_t *journal) ...@@ -1373,43 +1417,11 @@ const char * journal_dev_name(journal_t *journal)
} }
/* /*
* journal_abort: perform a complete, immediate shutdown of the ENTIRE * Journal abort has very specific semantics, which we describe
* journal (not of a single transaction). This operation cannot be * for journal abort.
* undone without closing and reopening the journal.
*
* The journal_abort function is intended to support higher level error
* recovery mechanisms such as the ext2/ext3 remount-readonly error
* mode.
*
* Journal abort has very specific semantics. Any existing dirty,
* unjournaled buffers in the main filesystem will still be written to
* disk by bdflush, but the journaling mechanism will be suspended
* immediately and no further transaction commits will be honoured.
*
* Any dirty, journaled buffers will be written back to disk without
* hitting the journal. Atomicity cannot be guaranteed on an aborted
* filesystem, but we _do_ attempt to leave as much data as possible
* behind for fsck to use for cleanup.
* *
* Any attempt to get a new transaction handle on a journal which is in * Two internal function, which provide abort to te jbd layer
* ABORT state will just result in an -EROFS error return. A * itself are here.
* journal_stop on an existing handle will return -EIO if we have
* entered abort state during the update.
*
* Recursive transactions are not disturbed by journal abort until the
* final journal_stop, which will receive the -EIO error.
*
* Finally, the journal_abort call allows the caller to supply an errno
* which will be recored (if possible) in the journal superblock. This
* allows a client to record failure conditions in the middle of a
* transaction without having to complete the transaction to record the
* failure to disk. ext3_error, for example, now uses this
* functionality.
*
* Errors which originate from within the journaling layer will NOT
* supply an errno; a null errno implies that absolutely no further
* writes are done to the journal (unless there are any already in
* progress).
*/ */
/* Quick version for internal journal use (doesn't lock the journal). /* Quick version for internal journal use (doesn't lock the journal).
...@@ -1447,7 +1459,52 @@ void __journal_abort_soft (journal_t *journal, int errno) ...@@ -1447,7 +1459,52 @@ void __journal_abort_soft (journal_t *journal, int errno)
journal_update_superblock(journal, 1); journal_update_superblock(journal, 1);
} }
/* Full version for external use */ /**
* void journal_abort () - Shutdown the journal immediately.
* @journal: the journal to shutdown.
* @errno: an error number to record in the journal indicating
* the reason for the shutdown.
*
* Perform a complete, immediate shutdown of the ENTIRE
* journal (not of a single transaction). This operation cannot be
* undone without closing and reopening the journal.
*
* The journal_abort function is intended to support higher level error
* recovery mechanisms such as the ext2/ext3 remount-readonly error
* mode.
*
* Journal abort has very specific semantics. Any existing dirty,
* unjournaled buffers in the main filesystem will still be written to
* disk by bdflush, but the journaling mechanism will be suspended
* immediately and no further transaction commits will be honoured.
*
* Any dirty, journaled buffers will be written back to disk without
* hitting the journal. Atomicity cannot be guaranteed on an aborted
* filesystem, but we _do_ attempt to leave as much data as possible
* behind for fsck to use for cleanup.
*
* Any attempt to get a new transaction handle on a journal which is in
* ABORT state will just result in an -EROFS error return. A
* journal_stop on an existing handle will return -EIO if we have
* entered abort state during the update.
*
* Recursive transactions are not disturbed by journal abort until the
* final journal_stop, which will receive the -EIO error.
*
* Finally, the journal_abort call allows the caller to supply an errno
* which will be recorded (if possible) in the journal superblock. This
* allows a client to record failure conditions in the middle of a
* transaction without having to complete the transaction to record the
* failure to disk. ext3_error, for example, now uses this
* functionality.
*
* Errors which originate from within the journaling layer will NOT
* supply an errno; a null errno implies that absolutely no further
* writes are done to the journal (unless there are any already in
* progress).
*
*/
void journal_abort (journal_t *journal, int errno) void journal_abort (journal_t *journal, int errno)
{ {
lock_journal(journal); lock_journal(journal);
...@@ -1455,6 +1512,17 @@ void journal_abort (journal_t *journal, int errno) ...@@ -1455,6 +1512,17 @@ void journal_abort (journal_t *journal, int errno)
unlock_journal(journal); unlock_journal(journal);
} }
/**
* int journal_errno () - returns the journal's error state.
* @journal: journal to examine.
*
* This is the errno numbet set with journal_abort(), the last
* time the journal was mounted - if the journal was stopped
* without calling abort this will be 0.
*
* If the journal has been aborted on this mount time -EROFS will
* be returned.
*/
int journal_errno (journal_t *journal) int journal_errno (journal_t *journal)
{ {
int err; int err;
...@@ -1468,6 +1536,14 @@ int journal_errno (journal_t *journal) ...@@ -1468,6 +1536,14 @@ int journal_errno (journal_t *journal)
return err; return err;
} }
/**
* int journal_clear_err () - clears the journal's error state
*
* An error must be cleared or Acked to take a FS out of readonly
* mode.
*/
int journal_clear_err (journal_t *journal) int journal_clear_err (journal_t *journal)
{ {
int err = 0; int err = 0;
...@@ -1481,6 +1557,13 @@ int journal_clear_err (journal_t *journal) ...@@ -1481,6 +1557,13 @@ int journal_clear_err (journal_t *journal)
return err; return err;
} }
/**
* void journal_ack_err() - Ack journal err.
*
* An error must be cleared or Acked to take a FS out of readonly
* mode.
*/
void journal_ack_err (journal_t *journal) void journal_ack_err (journal_t *journal)
{ {
lock_journal(journal); lock_journal(journal);
......
...@@ -206,20 +206,22 @@ do { \ ...@@ -206,20 +206,22 @@ do { \
var -= ((journal)->j_last - (journal)->j_first); \ var -= ((journal)->j_last - (journal)->j_first); \
} while (0) } while (0)
/* /**
* journal_recover * int journal_recover(journal_t *journal) - recovers a on-disk journal
* @journal: the journal to recover
* *
* The primary function for recovering the log contents when mounting a * The primary function for recovering the log contents when mounting a
* journaled device. * journaled device.
* */
int journal_recover(journal_t *journal)
{
/*
* Recovery is done in three passes. In the first pass, we look for the * Recovery is done in three passes. In the first pass, we look for the
* end of the log. In the second, we assemble the list of revoke * end of the log. In the second, we assemble the list of revoke
* blocks. In the third and final pass, we replay any un-revoked blocks * blocks. In the third and final pass, we replay any un-revoked blocks
* in the log. * in the log.
*/ */
int journal_recover(journal_t *journal)
{
int err; int err;
journal_superblock_t * sb; journal_superblock_t * sb;
...@@ -263,20 +265,23 @@ int journal_recover(journal_t *journal) ...@@ -263,20 +265,23 @@ int journal_recover(journal_t *journal)
return err; return err;
} }
/* /**
* journal_skip_recovery * int journal_skip_recovery() - Start journal and wipe exiting records
* @journal: journal to startup
* *
* Locate any valid recovery information from the journal and set up the * Locate any valid recovery information from the journal and set up the
* journal structures in memory to ignore it (presumably because the * journal structures in memory to ignore it (presumably because the
* caller has evidence that it is out of date). * caller has evidence that it is out of date).
* * This function does'nt appear to be exorted..
*/
int journal_skip_recovery(journal_t *journal)
{
/*
* We perform one pass over the journal to allow us to tell the user how * We perform one pass over the journal to allow us to tell the user how
* much recovery information is being erased, and to let us initialise * much recovery information is being erased, and to let us initialise
* the journal transaction sequence numbers to the next unused ID. * the journal transaction sequence numbers to the next unused ID.
*/ */
int journal_skip_recovery(journal_t *journal)
{
int err; int err;
journal_superblock_t * sb; journal_superblock_t * sb;
......
...@@ -222,19 +222,20 @@ static handle_t *new_handle(int nblocks) ...@@ -222,19 +222,20 @@ static handle_t *new_handle(int nblocks)
return handle; return handle;
} }
/* /**
* Obtain a new handle. * handle_t *journal_start() - Obtain a new handle.
* @journal: Journal to start transaction on.
* @nblocks: number of block buffer we might modify
* *
* We make sure that the transaction can guarantee at least nblocks of * We make sure that the transaction can guarantee at least nblocks of
* modified buffers in the log. We block until the log can guarantee * modified buffers in the log. We block until the log can guarantee
* that much space. * that much space.
* *
* This function is visible to journal users (like ext2fs), so is not * This function is visible to journal users (like ext3fs), so is not
* called with the journal already locked. * called with the journal already locked.
* *
* Return a pointer to a newly allocated handle, or NULL on failure * Return a pointer to a newly allocated handle, or NULL on failure
*/ */
handle_t *journal_start(journal_t *journal, int nblocks) handle_t *journal_start(journal_t *journal, int nblocks)
{ {
handle_t *handle = journal_current_handle(); handle_t *handle = journal_current_handle();
...@@ -324,7 +325,11 @@ static int try_start_this_handle(journal_t *journal, handle_t *handle) ...@@ -324,7 +325,11 @@ static int try_start_this_handle(journal_t *journal, handle_t *handle)
return ret; return ret;
} }
/* /**
* handle_t *journal_try_start() - Don't block, but try and get a handle
* @journal: Journal to start transaction on.
* @nblocks: number of block buffer we might modify
*
* Try to start a handle, but non-blockingly. If we weren't able * Try to start a handle, but non-blockingly. If we weren't able
* to, return an ERR_PTR value. * to, return an ERR_PTR value.
*/ */
...@@ -368,8 +373,10 @@ handle_t *journal_try_start(journal_t *journal, int nblocks) ...@@ -368,8 +373,10 @@ handle_t *journal_try_start(journal_t *journal, int nblocks)
return handle; return handle;
} }
/* /**
* journal_extend: extend buffer credits. * int journal_extend() - extend buffer credits.
* @handle: handle to 'extend'
* @nblocks: nr blocks to try to extend by.
* *
* Some transactions, such as large extends and truncates, can be done * Some transactions, such as large extends and truncates, can be done
* atomically all at once or in several stages. The operation requests * atomically all at once or in several stages. The operation requests
...@@ -377,7 +384,7 @@ handle_t *journal_try_start(journal_t *journal, int nblocks) ...@@ -377,7 +384,7 @@ handle_t *journal_try_start(journal_t *journal, int nblocks)
* extend its credit if it needs more. * extend its credit if it needs more.
* *
* journal_extend tries to give the running handle more buffer credits. * journal_extend tries to give the running handle more buffer credits.
* It does not guarantee that allocation: this is a best-effort only. * It does not guarantee that allocation - this is a best-effort only.
* The calling process MUST be able to deal cleanly with a failure to * The calling process MUST be able to deal cleanly with a failure to
* extend here. * extend here.
* *
...@@ -386,7 +393,6 @@ handle_t *journal_try_start(journal_t *journal, int nblocks) ...@@ -386,7 +393,6 @@ handle_t *journal_try_start(journal_t *journal, int nblocks)
* return code < 0 implies an error * return code < 0 implies an error
* return code > 0 implies normal transaction-full status. * return code > 0 implies normal transaction-full status.
*/ */
int journal_extend (handle_t *handle, int nblocks) int journal_extend (handle_t *handle, int nblocks)
{ {
transaction_t *transaction = handle->h_transaction; transaction_t *transaction = handle->h_transaction;
...@@ -435,8 +441,12 @@ int journal_extend (handle_t *handle, int nblocks) ...@@ -435,8 +441,12 @@ int journal_extend (handle_t *handle, int nblocks)
} }
/* /**
* journal_restart: restart a handle for a multi-transaction filesystem * int journal_restart() - restart a handle .
* @handle: handle to restart
* @nblocks: nr credits requested
*
* Restart a handle for a multi-transaction filesystem
* operation. * operation.
* *
* If the journal_extend() call above fails to grant new buffer credits * If the journal_extend() call above fails to grant new buffer credits
...@@ -478,8 +488,9 @@ int journal_restart(handle_t *handle, int nblocks) ...@@ -478,8 +488,9 @@ int journal_restart(handle_t *handle, int nblocks)
} }
/* /**
* Barrier operation: establish a transaction barrier. * void journal_lock_updates () - establish a transaction barrier.
* @journal: Journal to establish a barrier on.
* *
* This locks out any further updates from being started, and blocks * This locks out any further updates from being started, and blocks
* until all existing updates have completed, returning only once the * until all existing updates have completed, returning only once the
...@@ -487,7 +498,6 @@ int journal_restart(handle_t *handle, int nblocks) ...@@ -487,7 +498,6 @@ int journal_restart(handle_t *handle, int nblocks)
* *
* The journal lock should not be held on entry. * The journal lock should not be held on entry.
*/ */
void journal_lock_updates (journal_t *journal) void journal_lock_updates (journal_t *journal)
{ {
lock_journal(journal); lock_journal(journal);
...@@ -515,12 +525,14 @@ void journal_lock_updates (journal_t *journal) ...@@ -515,12 +525,14 @@ void journal_lock_updates (journal_t *journal)
down(&journal->j_barrier); down(&journal->j_barrier);
} }
/* /**
* void journal_unlock_updates (journal_t* journal) - release barrier
* @journal: Journal to release the barrier on.
*
* Release a transaction barrier obtained with journal_lock_updates(). * Release a transaction barrier obtained with journal_lock_updates().
* *
* Should be called without the journal lock held. * Should be called without the journal lock held.
*/ */
void journal_unlock_updates (journal_t *journal) void journal_unlock_updates (journal_t *journal)
{ {
lock_journal(journal); lock_journal(journal);
...@@ -566,9 +578,6 @@ static void jbd_unexpected_dirty_buffer(struct journal_head *jh) ...@@ -566,9 +578,6 @@ static void jbd_unexpected_dirty_buffer(struct journal_head *jh)
} }
/* /*
* journal_get_write_access: notify intent to modify a buffer for metadata
* (not data) update.
*
* If the buffer is already part of the current transaction, then there * If the buffer is already part of the current transaction, then there
* is nothing we need to do. If it is already part of a prior * is nothing we need to do. If it is already part of a prior
* transaction which we are still committing to disk, then we need to * transaction which we are still committing to disk, then we need to
...@@ -577,7 +586,6 @@ static void jbd_unexpected_dirty_buffer(struct journal_head *jh) ...@@ -577,7 +586,6 @@ static void jbd_unexpected_dirty_buffer(struct journal_head *jh)
* the handle's metadata buffer credits (unless the buffer is already * the handle's metadata buffer credits (unless the buffer is already
* part of the transaction, that is). * part of the transaction, that is).
* *
* Returns an error code or 0 on success.
*/ */
static int static int
...@@ -786,6 +794,17 @@ do_get_write_access(handle_t *handle, struct journal_head *jh, int force_copy) ...@@ -786,6 +794,17 @@ do_get_write_access(handle_t *handle, struct journal_head *jh, int force_copy)
return error; return error;
} }
/**
* int journal_get_write_access() - notify intent to modify a buffer for metadata (not data) update.
* @handle: transaction to add buffer modifications to
* @bh: bh to be used for metadata writes
*
* Returns an error code or 0 on success.
*
* In full data journalling mode the buffer may be of type BJ_AsyncData,
* because we're write()ing a buffer which is also part of a shared mapping.
*/
int journal_get_write_access (handle_t *handle, struct buffer_head *bh) int journal_get_write_access (handle_t *handle, struct buffer_head *bh)
{ {
transaction_t *transaction = handle->h_transaction; transaction_t *transaction = handle->h_transaction;
...@@ -816,6 +835,13 @@ int journal_get_write_access (handle_t *handle, struct buffer_head *bh) ...@@ -816,6 +835,13 @@ int journal_get_write_access (handle_t *handle, struct buffer_head *bh)
* There is no lock ranking violation: it was a newly created, * There is no lock ranking violation: it was a newly created,
* unlocked buffer beforehand. */ * unlocked buffer beforehand. */
/**
* int journal_get_create_access () - notify intent to use newly created bh
* @handle: transaction to new buffer to
* @bh: new buffer.
*
* Call this if you create a new bh.
*/
int journal_get_create_access (handle_t *handle, struct buffer_head *bh) int journal_get_create_access (handle_t *handle, struct buffer_head *bh)
{ {
transaction_t *transaction = handle->h_transaction; transaction_t *transaction = handle->h_transaction;
...@@ -875,13 +901,14 @@ int journal_get_create_access (handle_t *handle, struct buffer_head *bh) ...@@ -875,13 +901,14 @@ int journal_get_create_access (handle_t *handle, struct buffer_head *bh)
/* /**
* journal_get_undo_access: Notify intent to modify metadata with non- * int journal_get_undo_access() - Notify intent to modify metadata with non-rewindable consequences
* rewindable consequences * @handle: transaction
* @bh: buffer to undo
* *
* Sometimes there is a need to distinguish between metadata which has * Sometimes there is a need to distinguish between metadata which has
* been committed to disk and that which has not. The ext3fs code uses * been committed to disk and that which has not. The ext3fs code uses
* this for freeing and allocating space: we have to make sure that we * this for freeing and allocating space, we have to make sure that we
* do not reuse freed space until the deallocation has been committed, * do not reuse freed space until the deallocation has been committed,
* since if we overwrote that space we would make the delete * since if we overwrote that space we would make the delete
* un-rewindable in case of a crash. * un-rewindable in case of a crash.
...@@ -893,13 +920,12 @@ int journal_get_create_access (handle_t *handle, struct buffer_head *bh) ...@@ -893,13 +920,12 @@ int journal_get_create_access (handle_t *handle, struct buffer_head *bh)
* as we know that the buffer has definitely been committed to disk. * as we know that the buffer has definitely been committed to disk.
* *
* We never need to know which transaction the committed data is part * We never need to know which transaction the committed data is part
* of: buffers touched here are guaranteed to be dirtied later and so * of, buffers touched here are guaranteed to be dirtied later and so
* will be committed to a new transaction in due course, at which point * will be committed to a new transaction in due course, at which point
* we can discard the old committed data pointer. * we can discard the old committed data pointer.
* *
* Returns error number or 0 on success. * Returns error number or 0 on success.
*/ */
int journal_get_undo_access (handle_t *handle, struct buffer_head *bh) int journal_get_undo_access (handle_t *handle, struct buffer_head *bh)
{ {
journal_t *journal = handle->h_transaction->t_journal; journal_t *journal = handle->h_transaction->t_journal;
...@@ -942,21 +968,23 @@ int journal_get_undo_access (handle_t *handle, struct buffer_head *bh) ...@@ -942,21 +968,23 @@ int journal_get_undo_access (handle_t *handle, struct buffer_head *bh)
return err; return err;
} }
/* /**
* journal_dirty_data: mark a buffer as containing dirty data which * int journal_dirty_data() - mark a buffer as containing dirty data which needs to be flushed before we can commit the current transaction.
* needs to be flushed before we can commit the current transaction. * @handle: transaction
* @bh: bufferhead to mark
* *
* The buffer is placed on the transaction's data list and is marked as * The buffer is placed on the transaction's data list and is marked as
* belonging to the transaction. * belonging to the transaction.
* *
* Returns error number or 0 on success. * Returns error number or 0 on success.
* */
int journal_dirty_data (handle_t *handle, struct buffer_head *bh)
{
/*
* journal_dirty_data() can be called via page_launder->ext3_writepage * journal_dirty_data() can be called via page_launder->ext3_writepage
* by kswapd. So it cannot block. Happily, there's nothing here * by kswapd. So it cannot block. Happily, there's nothing here
* which needs lock_journal if `async' is set. * which needs lock_journal if `async' is set.
*/ */
int journal_dirty_data (handle_t *handle, struct buffer_head *bh)
{
journal_t *journal = handle->h_transaction->t_journal; journal_t *journal = handle->h_transaction->t_journal;
int need_brelse = 0; int need_brelse = 0;
struct journal_head *jh; struct journal_head *jh;
...@@ -1097,24 +1125,28 @@ int journal_dirty_data (handle_t *handle, struct buffer_head *bh) ...@@ -1097,24 +1125,28 @@ int journal_dirty_data (handle_t *handle, struct buffer_head *bh)
return 0; return 0;
} }
/* /**
* journal_dirty_metadata: mark a buffer as containing dirty metadata * int journal_dirty_metadata() - mark a buffer as containing dirty metadata
* which needs to be journaled as part of the current transaction. * @handle: transaction to add buffer to.
* @bh: buffer to mark
*
* mark dirty metadata which needs to be journaled as part of the current transaction.
* *
* The buffer is placed on the transaction's metadata list and is marked * The buffer is placed on the transaction's metadata list and is marked
* as belonging to the transaction. * as belonging to the transaction.
* *
* Returns error number or 0 on success.
*/
int journal_dirty_metadata (handle_t *handle, struct buffer_head *bh)
{
/*
* Special care needs to be taken if the buffer already belongs to the * Special care needs to be taken if the buffer already belongs to the
* current committing transaction (in which case we should have frozen * current committing transaction (in which case we should have frozen
* data present for that commit). In that case, we don't relink the * data present for that commit). In that case, we don't relink the
* buffer: that only gets done when the old transaction finally * buffer: that only gets done when the old transaction finally
* completes its commit. * completes its commit.
* *
* Returns error number or 0 on success.
*/ */
int journal_dirty_metadata (handle_t *handle, struct buffer_head *bh)
{
transaction_t *transaction = handle->h_transaction; transaction_t *transaction = handle->h_transaction;
journal_t *journal = transaction->t_journal; journal_t *journal = transaction->t_journal;
struct journal_head *jh = bh2jh(bh); struct journal_head *jh = bh2jh(bh);
...@@ -1199,9 +1231,12 @@ void journal_release_buffer (handle_t *handle, struct buffer_head *bh) ...@@ -1199,9 +1231,12 @@ void journal_release_buffer (handle_t *handle, struct buffer_head *bh)
} }
#endif #endif
/* /**
* journal_forget: bforget() for potentially-journaled buffers. We can * void journal_forget() - bforget() for potentially-journaled buffers.
* only do the bforget if there are no commits pending against the * @handle: transaction handle
* @bh: bh to 'forget'
*
* We can only do the bforget if there are no commits pending against the
* buffer. If the buffer is dirty in the current running transaction we * buffer. If the buffer is dirty in the current running transaction we
* can safely unlink it. * can safely unlink it.
* *
...@@ -1213,7 +1248,6 @@ void journal_release_buffer (handle_t *handle, struct buffer_head *bh) ...@@ -1213,7 +1248,6 @@ void journal_release_buffer (handle_t *handle, struct buffer_head *bh)
* Allow this call even if the handle has aborted --- it may be part of * Allow this call even if the handle has aborted --- it may be part of
* the caller's cleanup after an abort. * the caller's cleanup after an abort.
*/ */
void journal_forget (handle_t *handle, struct buffer_head *bh) void journal_forget (handle_t *handle, struct buffer_head *bh)
{ {
transaction_t *transaction = handle->h_transaction; transaction_t *transaction = handle->h_transaction;
...@@ -1352,8 +1386,14 @@ void journal_sync_buffer(struct buffer_head *bh) ...@@ -1352,8 +1386,14 @@ void journal_sync_buffer(struct buffer_head *bh)
} }
#endif #endif
/* /**
* Register a callback function for this handle. The function will be * void journal_callback_set() - Register a callback function for this handle.
* @handle: handle to attach the callback to.
* @func: function to callback.
* @jcb: structure with additional information required by func() , and
* some space for jbd internal information.
*
* The function will be
* called when the transaction that this handle is part of has been * called when the transaction that this handle is part of has been
* committed to disk with the original callback data struct and the * committed to disk with the original callback data struct and the
* error status of the journal as parameters. There is no guarantee of * error status of the journal as parameters. There is no guarantee of
...@@ -1374,7 +1414,11 @@ void journal_callback_set(handle_t *handle, ...@@ -1374,7 +1414,11 @@ void journal_callback_set(handle_t *handle,
jcb->jcb_func = func; jcb->jcb_func = func;
} }
/*
/**
* int journal_stop() - complete a transaction
* @handle: tranaction to complete.
*
* All done for a particular handle. * All done for a particular handle.
* *
* There is not much action needed here. We just return any remaining * There is not much action needed here. We just return any remaining
...@@ -1387,7 +1431,6 @@ void journal_callback_set(handle_t *handle, ...@@ -1387,7 +1431,6 @@ void journal_callback_set(handle_t *handle,
* return -EIO if a journal_abort has been executed since the * return -EIO if a journal_abort has been executed since the
* transaction began. * transaction began.
*/ */
int journal_stop(handle_t *handle) int journal_stop(handle_t *handle)
{ {
transaction_t *transaction = handle->h_transaction; transaction_t *transaction = handle->h_transaction;
...@@ -1473,8 +1516,10 @@ int journal_stop(handle_t *handle) ...@@ -1473,8 +1516,10 @@ int journal_stop(handle_t *handle)
return err; return err;
} }
/* /**int journal_force_commit() - force any uncommitted transactions
* For synchronous operations: force any uncommitted trasnactions * @journal: journal to force
*
* For synchronous operations: force any uncommitted transactions
* to disk. May seem kludgy, but it reuses all the handle batching * to disk. May seem kludgy, but it reuses all the handle batching
* code in a very simple manner. * code in a very simple manner.
*/ */
...@@ -1667,6 +1712,26 @@ static inline int __journal_try_to_free_buffer(struct buffer_head *bh) ...@@ -1667,6 +1712,26 @@ static inline int __journal_try_to_free_buffer(struct buffer_head *bh)
return 0; return 0;
} }
/**
* int journal_try_to_free_buffers() - try to free page buffers.
* @journal: journal for operation
* @page: to try and free
* @gfp_mask: 'IO' mode for try_to_free_buffers()
*
*
* For all the buffers on this page,
* if they are fully written out ordered data, move them onto BUF_CLEAN
* so try_to_free_buffers() can reap them.
*
* This function returns non-zero if we wish try_to_free_buffers()
* to be called. We do this if the page is releasable by try_to_free_buffers().
* We also do it if the page has locked or dirty buffers and the caller wants
* us to perform sync or async writeout.
*/
int journal_try_to_free_buffers(journal_t *journal,
struct page *page, int unused_gfp_mask)
{
/* /*
* journal_try_to_free_buffers(). Try to remove all this page's buffers * journal_try_to_free_buffers(). Try to remove all this page's buffers
* from the journal. * from the journal.
...@@ -1689,9 +1754,6 @@ static inline int __journal_try_to_free_buffer(struct buffer_head *bh) ...@@ -1689,9 +1754,6 @@ static inline int __journal_try_to_free_buffer(struct buffer_head *bh)
* cannot happen because we never reallocate freed data as metadata * cannot happen because we never reallocate freed data as metadata
* while the data is part of a transaction. Yes? * while the data is part of a transaction. Yes?
*/ */
int journal_try_to_free_buffers(journal_t *journal,
struct page *page, int unused_gfp_mask)
{
struct buffer_head *head; struct buffer_head *head;
struct buffer_head *bh; struct buffer_head *bh;
int ret = 0; int ret = 0;
...@@ -1886,8 +1948,15 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) ...@@ -1886,8 +1948,15 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh)
return may_free; return may_free;
} }
/* /**
* Return non-zero if the page's buffers were successfully reaped * int journal_invalidatepage()
* @journal: journal to use for flush...
* @page: page to flush
* @offset: length of page to invalidate.
*
* Reap page buffers containing data after offset in page.
*
* Return non-zero if the page's buffers were successfully reaped.
*/ */
int journal_invalidatepage(journal_t *journal, int journal_invalidatepage(journal_t *journal,
struct page *page, struct page *page,
......
...@@ -63,7 +63,38 @@ extern void * __jbd_kmalloc (const char *where, size_t size, int flags, int retr ...@@ -63,7 +63,38 @@ extern void * __jbd_kmalloc (const char *where, size_t size, int flags, int retr
#define JFS_MIN_JOURNAL_BLOCKS 1024 #define JFS_MIN_JOURNAL_BLOCKS 1024
#ifdef __KERNEL__ #ifdef __KERNEL__
/**
* typedef handle_t - The handle_t type represents a single atomic update being performed by some process.
*
* All filesystem modifications made by the process go
* through this handle. Recursive operations (such as quota operations)
* are gathered into a single update.
*
* The buffer credits field is used to account for journaled buffers
* being modified by the running process. To ensure that there is
* enough log space for all outstanding operations, we need to limit the
* number of outstanding buffers possible at any time. When the
* operation completes, any buffer credits not used are credited back to
* the transaction, so that at all times we know how many buffers the
* outstanding updates on a transaction might possibly touch.
*
* This is an opaque datatype.
**/
typedef struct handle_s handle_t; /* Atomic operation type */ typedef struct handle_s handle_t; /* Atomic operation type */
/**
* typedef journal_t - The journal_t maintains all of the journaling state information for a single filesystem.
*
* journal_t is linked to from the fs superblock structure.
*
* We use the journal_t to keep track of all outstanding transaction
* activity on the filesystem, and to manage the state of the log
* writing process.
*
* This is an opaque datatype.
**/
typedef struct journal_s journal_t; /* Journal control structure */ typedef struct journal_s journal_t; /* Journal control structure */
#endif #endif
...@@ -252,6 +283,20 @@ static inline struct journal_head *bh2jh(struct buffer_head *bh) ...@@ -252,6 +283,20 @@ static inline struct journal_head *bh2jh(struct buffer_head *bh)
} }
#define HAVE_JOURNAL_CALLBACK_STATUS #define HAVE_JOURNAL_CALLBACK_STATUS
/**
* struct journal_callback - Base structure for callback information.
* @jcb_list: list information for other callbacks attached to the same handle.
* @jcb_func: Function to call with this callback structure.
*
* This struct is a 'seed' structure for a using with your own callback
* structs. If you are using callbacks you must allocate one of these
* or another struct of your own definition which has this struct
* as it's first element and pass it to journal_callback_set().
*
* This is used internally by jbd to maintain callback information.
*
* See journal_callback_set for more information.
**/
struct journal_callback { struct journal_callback {
struct list_head jcb_list; struct list_head jcb_list;
void (*jcb_func)(struct journal_callback *jcb, int error); void (*jcb_func)(struct journal_callback *jcb, int error);
...@@ -260,18 +305,21 @@ struct journal_callback { ...@@ -260,18 +305,21 @@ struct journal_callback {
struct jbd_revoke_table_s; struct jbd_revoke_table_s;
/* The handle_t type represents a single atomic update being performed /**
* by some process. All filesystem modifications made by the process go * struct handle_s - The handle_s type is the concrete type associated with handle_t.
* through this handle. Recursive operations (such as quota operations) * @h_transaction: Which compound transaction is this update a part of?
* are gathered into a single update. * @h_buffer_credits: Number of remaining buffers we are allowed to dirty.
* * @h_ref: Reference count on this handle
* The buffer credits field is used to account for journaled buffers * @h_jcb: List of application registered callbacks for this handle.
* being modified by the running process. To ensure that there is * @h_err: Field for caller's use to track errors through large fs operations
* enough log space for all outstanding operations, we need to limit the * @h_sync: flag for sync-on-close
* number of outstanding buffers possible at any time. When the * @h_jdata: flag to force data journaling
* operation completes, any buffer credits not used are credited back to * @h_aborted: flag indicating fatal error on handle
* the transaction, so that at all times we know how many buffers the **/
* outstanding updates on a transaction might possibly touch. */
/* Docbook can't yet cope with the bit fields, but will leave the documentation
* in so it can be fixed later.
*/
struct handle_s struct handle_s
{ {
...@@ -284,8 +332,8 @@ struct handle_s ...@@ -284,8 +332,8 @@ struct handle_s
/* Reference count on this handle */ /* Reference count on this handle */
int h_ref; int h_ref;
/* Field for caller's use to track errors through large fs /* Field for caller's use to track errors through large fs */
operations */ /* operations */
int h_err; int h_err;
/* List of application registered callbacks for this handle. /* List of application registered callbacks for this handle.
...@@ -412,21 +460,58 @@ struct transaction_s ...@@ -412,21 +460,58 @@ struct transaction_s
struct list_head t_jcb; struct list_head t_jcb;
}; };
/**
/* The journal_t maintains all of the journaling state information for a * struct journal_s - The journal_s type is the concrete type associated with journal_t.
* single filesystem. It is linked to from the fs superblock structure. * @j_flags: General journaling state flags
* * @j_errno: Is there an outstanding uncleared error on the journal (from a prior abort)?
* We use the journal_t to keep track of all outstanding transaction * @j_sb_buffer: First part of superblock buffer
* activity on the filesystem, and to manage the state of the log * @j_superblock: Second part of superblock buffer
* writing process. */ * @j_format_version: Version of the superblock format
* @j_barrier_count: Number of processes waiting to create a barrier lock
* @j_barrier: The barrier lock itself
* @j_running_transaction: The current running transaction..
* @j_committing_transaction: the transaction we are pushing to disk
* @j_checkpoint_transactions: a linked circular list of all transactions waiting for checkpointing
* @j_wait_transaction_locked: Wait queue for waiting for a locked transaction to start committing, or for a barrier lock to be released
* @j_wait_logspace: Wait queue for waiting for checkpointing to complete
* @j_wait_done_commit: Wait queue for waiting for commit to complete
* @j_wait_checkpoint: Wait queue to trigger checkpointing
* @j_wait_commit: Wait queue to trigger commit
* @j_wait_updates: Wait queue to wait for updates to complete
* @j_checkpoint_sem: Semaphore for locking against concurrent checkpoints
* @j_sem: The main journal lock, used by lock_journal()
* @j_head: Journal head - identifies the first unused block in the journal
* @j_tail: Journal tail - identifies the oldest still-used block in the journal.
* @j_free: Journal free - how many free blocks are there in the journal?
* @j_first: The block number of the first usable block
* @j_last: The block number one beyond the last usable block
* @j_dev: Device where we store the journal
* @j_blocksize: blocksize for the location where we store the journal.
* @j_blk_offset: starting block offset for into the device where we store the journal
* @j_fs_dev: Device which holds the client fs. For internal journal this will be equal to j_dev
* @j_maxlen: Total maximum capacity of the journal region on disk.
* @j_inode: Optional inode where we store the journal. If present, all journal block numbers are mapped into this inode via bmap().
* @j_tail_sequence: Sequence number of the oldest transaction in the log
* @j_transaction_sequence: Sequence number of the next transaction to grant
* @j_commit_sequence: Sequence number of the most recently committed transaction
* @j_commit_request: Sequence number of the most recent transaction wanting commit
* @j_uuid: Uuid of client object.
* @j_task: Pointer to the current commit thread for this journal
* @j_max_transaction_buffers: Maximum number of metadata buffers to allow in a single compound commit transaction
* @j_commit_interval: What is the maximum transaction lifetime before we begin a commit?
* @j_commit_timer: The timer used to wakeup the commit thread
* @j_commit_timer_active: Timer flag
* @j_all_journals: Link all journals together - system-wide
* @j_revoke: The revoke table - maintains the list of revoked blocks in the current transaction.
**/
struct journal_s struct journal_s
{ {
/* General journaling state flags */ /* General journaling state flags */
unsigned long j_flags; unsigned long j_flags;
/* Is there an outstanding uncleared error on the journal (from /* Is there an outstanding uncleared error on the journal (from */
* a prior abort)? */ /* a prior abort)? */
int j_errno; int j_errno;
/* The superblock buffer */ /* The superblock buffer */
...@@ -448,13 +533,13 @@ struct journal_s ...@@ -448,13 +533,13 @@ struct journal_s
/* ... the transaction we are pushing to disk ... */ /* ... the transaction we are pushing to disk ... */
transaction_t * j_committing_transaction; transaction_t * j_committing_transaction;
/* ... and a linked circular list of all transactions waiting /* ... and a linked circular list of all transactions waiting */
* for checkpointing. */ /* for checkpointing. */
/* Protected by journal_datalist_lock */ /* Protected by journal_datalist_lock */
transaction_t * j_checkpoint_transactions; transaction_t * j_checkpoint_transactions;
/* Wait queue for waiting for a locked transaction to start /* Wait queue for waiting for a locked transaction to start */
committing, or for a barrier lock to be released */ /* committing, or for a barrier lock to be released */
wait_queue_head_t j_wait_transaction_locked; wait_queue_head_t j_wait_transaction_locked;
/* Wait queue for waiting for checkpointing to complete */ /* Wait queue for waiting for checkpointing to complete */
...@@ -481,33 +566,33 @@ struct journal_s ...@@ -481,33 +566,33 @@ struct journal_s
/* Journal head: identifies the first unused block in the journal. */ /* Journal head: identifies the first unused block in the journal. */
unsigned long j_head; unsigned long j_head;
/* Journal tail: identifies the oldest still-used block in the /* Journal tail: identifies the oldest still-used block in the */
* journal. */ /* journal. */
unsigned long j_tail; unsigned long j_tail;
/* Journal free: how many free blocks are there in the journal? */ /* Journal free: how many free blocks are there in the journal? */
unsigned long j_free; unsigned long j_free;
/* Journal start and end: the block numbers of the first usable /* Journal start and end: the block numbers of the first usable */
* block and one beyond the last usable block in the journal. */ /* block and one beyond the last usable block in the journal. */
unsigned long j_first, j_last; unsigned long j_first, j_last;
/* Device, blocksize and starting block offset for the location /* Device, blocksize and starting block offset for the location */
* where we store the journal. */ /* where we store the journal. */
struct block_device * j_dev; struct block_device * j_dev;
int j_blocksize; int j_blocksize;
unsigned int j_blk_offset; unsigned int j_blk_offset;
/* Device which holds the client fs. For internal journal this /* Device which holds the client fs. For internal journal this */
* will be equal to j_dev. */ /* will be equal to j_dev. */
struct block_device * j_fs_dev; struct block_device * j_fs_dev;
/* Total maximum capacity of the journal region on disk. */ /* Total maximum capacity of the journal region on disk. */
unsigned int j_maxlen; unsigned int j_maxlen;
/* Optional inode where we store the journal. If present, all /* Optional inode where we store the journal. If present, all */
* journal block numbers are mapped into this inode via /* journal block numbers are mapped into this inode via */
* bmap(). */ /* bmap(). */
struct inode * j_inode; struct inode * j_inode;
/* Sequence number of the oldest transaction in the log */ /* Sequence number of the oldest transaction in the log */
...@@ -519,23 +604,23 @@ struct journal_s ...@@ -519,23 +604,23 @@ struct journal_s
/* Sequence number of the most recent transaction wanting commit */ /* Sequence number of the most recent transaction wanting commit */
tid_t j_commit_request; tid_t j_commit_request;
/* Journal uuid: identifies the object (filesystem, LVM volume /* Journal uuid: identifies the object (filesystem, LVM volume */
* etc) backed by this journal. This will eventually be /* etc) backed by this journal. This will eventually be */
* replaced by an array of uuids, allowing us to index multiple /* replaced by an array of uuids, allowing us to index multiple */
* devices within a single journal and to perform atomic updates /* devices within a single journal and to perform atomic updates */
* across them. */ /* across them. */
__u8 j_uuid[16]; __u8 j_uuid[16];
/* Pointer to the current commit thread for this journal */ /* Pointer to the current commit thread for this journal */
struct task_struct * j_task; struct task_struct * j_task;
/* Maximum number of metadata buffers to allow in a single /* Maximum number of metadata buffers to allow in a single */
* compound commit transaction */ /* compound commit transaction */
int j_max_transaction_buffers; int j_max_transaction_buffers;
/* What is the maximum transaction lifetime before we begin a /* What is the maximum transaction lifetime before we begin a */
* commit? */ /* commit? */
unsigned long j_commit_interval; unsigned long j_commit_interval;
/* The timer used to wakeup the commit thread: */ /* The timer used to wakeup the commit thread: */
...@@ -545,8 +630,8 @@ struct journal_s ...@@ -545,8 +630,8 @@ struct journal_s
/* Link all journals together - system-wide */ /* Link all journals together - system-wide */
struct list_head j_all_journals; struct list_head j_all_journals;
/* The revoke table: maintains the list of revoked blocks in the /* The revoke table: maintains the list of revoked blocks in the */
current transaction. */ /* current transaction. */
struct jbd_revoke_table_s *j_revoke; struct jbd_revoke_table_s *j_revoke;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment