aboutsummaryrefslogtreecommitdiff
path: root/e2fsck
diff options
context:
space:
mode:
Diffstat (limited to 'e2fsck')
-rw-r--r--e2fsck/ChangeLog9
-rw-r--r--e2fsck/Makefile.in6
-rw-r--r--e2fsck/jfs_compat.h77
-rw-r--r--e2fsck/jfs_user.h61
-rw-r--r--e2fsck/journal.c120
-rw-r--r--e2fsck/recovery.c145
-rw-r--r--e2fsck/revoke.c262
7 files changed, 378 insertions, 302 deletions
diff --git a/e2fsck/ChangeLog b/e2fsck/ChangeLog
index 466ab46e..d42ff8fc 100644
--- a/e2fsck/ChangeLog
+++ b/e2fsck/ChangeLog
@@ -1,8 +1,15 @@
+2001-12-16 Theodore Tso <tytso@valinux.com>
+
+ * recovery.c, revoke.c: Update to versions from 2.4.17-pre8.
+
+ * journal.c, jfs_user.h: Update support code for new version of
+ recover.c and revoke.c. Fix support for filesystems with
+ external journals.
+
2001-11-30 Gabriel Paubert <paubert@iram.es>
* journal.c (e2fsck_journal_load): Fix an endianness bug.
-
2001-11-26 Theodore Tso <tytso@valinux.com>
* super.c (check_super_block): Make sure that if the inode table
diff --git a/e2fsck/Makefile.in b/e2fsck/Makefile.in
index 55394dea..a4e894fe 100644
--- a/e2fsck/Makefile.in
+++ b/e2fsck/Makefile.in
@@ -218,7 +218,7 @@ journal.o: $(srcdir)/journal.c $(srcdir)/jfs_user.h $(srcdir)/e2fsck.h \
$(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \
$(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
$(top_srcdir)/lib/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
- $(top_srcdir)/lib/ext2fs/bitops.h $(top_srcdir)/include/linux/jfs.h \
+ $(top_srcdir)/lib/ext2fs/bitops.h $(top_srcdir)/include/linux/jbd.h \
$(top_srcdir)/include/linux/jfs_compat.h \
$(top_srcdir)/include/linux/linked_list.h $(srcdir)/problem.h \
$(top_srcdir)/lib/uuid/uuid.h
@@ -226,14 +226,14 @@ recovery.o: $(srcdir)/recovery.c $(srcdir)/jfs_user.h $(srcdir)/e2fsck.h \
$(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \
$(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
$(top_srcdir)/lib/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
- $(top_srcdir)/lib/ext2fs/bitops.h $(top_srcdir)/include/linux/jfs.h \
+ $(top_srcdir)/lib/ext2fs/bitops.h $(top_srcdir)/include/linux/jbd.h \
$(top_srcdir)/include/linux/jfs_compat.h \
$(top_srcdir)/include/linux/linked_list.h
revoke.o: $(srcdir)/revoke.c $(srcdir)/jfs_user.h $(srcdir)/e2fsck.h \
$(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \
$(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
$(top_srcdir)/lib/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
- $(top_srcdir)/lib/ext2fs/bitops.h $(top_srcdir)/include/linux/jfs.h \
+ $(top_srcdir)/lib/ext2fs/bitops.h $(top_srcdir)/include/linux/jbd.h \
$(top_srcdir)/include/linux/jfs_compat.h \
$(top_srcdir)/include/linux/linked_list.h
badblocks.o: $(srcdir)/badblocks.c $(top_srcdir)/lib/et/com_err.h \
diff --git a/e2fsck/jfs_compat.h b/e2fsck/jfs_compat.h
deleted file mode 100644
index 6d35e553..00000000
--- a/e2fsck/jfs_compat.h
+++ /dev/null
@@ -1,77 +0,0 @@
-
-#ifndef _JFS_COMPAT_H
-#define _JFS_COMPAT_H
-
-#include "e2fsck.h"
-#include <errno.h>
-
-#define printk printf
-#define KERN_ERR ""
-#define KERN_DEBUG ""
-
-#define READ 0
-#define WRITE 1
-
-typedef int tid_t;
-typedef e2fsck_t kdev_t;
-typedef struct journal_s journal_t;
-
-struct buffer_head {
- char b_data[8192];
- e2fsck_t b_ctx;
- io_channel b_io;
- int b_size;
- blk_t b_blocknr;
- int b_dirty;
- int b_uptodate;
- int b_err;
-};
-
-struct inode {
- e2fsck_t i_ctx;
- ino_t i_ino;
- struct ext2_inode i_ext2;
-};
-
-struct journal_s
-{
- unsigned long j_flags;
- int j_errno;
- struct buffer_head * j_sb_buffer;
- struct journal_superblock_s *j_superblock;
- unsigned long j_head;
- unsigned long j_tail;
- unsigned long j_free;
- unsigned long j_first, j_last;
- kdev_t j_dev;
- int j_blocksize;
- unsigned int j_blk_offset;
- unsigned int j_maxlen;
- struct inode * j_inode;
- tid_t j_tail_sequence;
- tid_t j_transaction_sequence;
- __u8 j_uuid[16];
-};
-
-int bmap(struct inode *inode, int block);
-struct buffer_head *getblk(e2fsck_t ctx, blk_t blocknr, int blocksize);
-void ll_rw_block(int rw, int dummy, struct buffer_head *bh);
-void mark_buffer_dirty(struct buffer_head *bh, int dummy);
-void brelse(struct buffer_head *bh);
-int buffer_uptodate(struct buffer_head *bh);
-void wait_on_buffer(struct buffer_head *bh);
-#define fsync_dev(dev) do {} while(0)
-#define buffer_req(bh) 1
-#define do_readahead(journal, start) do {} while(0)
-
-extern e2fsck_t e2fsck_global_ctx; /* Try your very best not to use this! */
-
-#define J_ASSERT(assert) \
- do { if (!(assert)) { \
- printf ("Assertion failure in %s() at %s line %d: " \
- "\"%s\"\n", \
- __FUNCTION__, __FILE__, __LINE__, # assert); \
- fatal_error(e2fsck_global_ctx, 0); \
- } } while (0)
-
-#endif /* _JFS_COMPAT_H */
diff --git a/e2fsck/jfs_user.h b/e2fsck/jfs_user.h
index 356a0ec0..f02923b1 100644
--- a/e2fsck/jfs_user.h
+++ b/e2fsck/jfs_user.h
@@ -15,14 +15,14 @@
#include "e2fsck.h"
struct buffer_head {
- char b_data[8192];
- e2fsck_t b_ctx;
- io_channel b_io;
- int b_size;
- blk_t b_blocknr;
- int b_dirty;
- int b_uptodate;
- int b_err;
+ char b_data[8192];
+ e2fsck_t b_ctx;
+ io_channel b_io;
+ int b_size;
+ blk_t b_blocknr;
+ int b_dirty;
+ int b_uptodate;
+ int b_err;
};
struct inode {
@@ -31,20 +31,17 @@ struct inode {
struct ext2_inode i_ext2;
};
-typedef e2fsck_t kdev_t;
+struct kdev_s {
+ e2fsck_t k_ctx;
+ int k_dev;
+};
-/*
- * Kernel compatibility functions are defined in journal.c
- */
-int bmap(struct inode *inode, int block);
-struct buffer_head *getblk(e2fsck_t ctx, blk_t blocknr, int blocksize);
-void ll_rw_block(int rw, int dummy, struct buffer_head *bh[]);
-void mark_buffer_dirty(struct buffer_head *bh, int dummy);
-void mark_buffer_uptodate(struct buffer_head *bh, int val);
-void brelse(struct buffer_head *bh);
-int buffer_uptodate(struct buffer_head *bh);
-void wait_on_buffer(struct buffer_head *bh);
-#define fsync_dev(dev) do {} while(0)
+#define K_DEV_FS 1
+#define K_DEV_JOURNAL 2
+
+typedef struct kdev_s *kdev_t;
+
+#define fsync_no_super(dev) do {} while(0)
#define buffer_req(bh) 1
#define do_readahead(journal, start) do {} while(0)
@@ -57,6 +54,7 @@ typedef struct {
#define kmem_cache_alloc(cache,flags) malloc((cache)->object_length)
#define kmem_cache_free(cache,obj) free(obj)
#define kmem_cache_create(name,len,a,b,c,d) do_cache_create(len)
+#define kmem_cache_destroy(cache) do_cache_destroy(cache)
#define kmalloc(len,flags) malloc(len)
#define kfree(p) free(p)
@@ -65,6 +63,7 @@ typedef struct {
* functions.
*/
extern kmem_cache_t * do_cache_create(int len);
+extern void do_cache_destroy(kmem_cache_t *cache);
#if (defined(E2FSCK_INCLUDE_INLINE_FUNCS) || !defined(NO_INLINE_FUNCS))
#ifdef E2FSCK_INCLUDE_INLINE_FUNCS
@@ -86,10 +85,28 @@ _INLINE_ kmem_cache_t * do_cache_create(int len)
return new_cache;
}
+_INLINE_ void do_cache_destroy(kmem_cache_t *cache)
+{
+ free(cache);
+}
#undef _INLINE_
#endif
+#define __init
+
/*
* Now pull in the real linux/jfs.h definitions.
*/
-#include <linux/jfs.h>
+#include <linux/jbd.h>
+
+/*
+ * Kernel compatibility functions are defined in journal.c
+ */
+int journal_bmap(journal_t *journal, blk_t block, unsigned long *phys);
+struct buffer_head *getblk(kdev_t ctx, blk_t blocknr, int blocksize);
+void ll_rw_block(int rw, int dummy, struct buffer_head *bh[]);
+void mark_buffer_dirty(struct buffer_head *bh);
+void mark_buffer_uptodate(struct buffer_head *bh, int val);
+void brelse(struct buffer_head *bh);
+int buffer_uptodate(struct buffer_head *bh);
+void wait_on_buffer(struct buffer_head *bh);
diff --git a/e2fsck/journal.c b/e2fsck/journal.c
index 89b73ff4..a07c7c1d 100644
--- a/e2fsck/journal.c
+++ b/e2fsck/journal.c
@@ -25,7 +25,7 @@
#include "problem.h"
#include "uuid/uuid.h"
-#ifdef JFS_DEBUG /* Enabled by configure --enable-jfs-debug */
+#ifdef CONFIG_JBD_DEBUG /* Enabled by configure --enable-jfs-debug */
static int bh_count = 0;
int journal_enable_debug = 2;
#endif
@@ -34,34 +34,39 @@ int journal_enable_debug = 2;
* to use the recovery.c file virtually unchanged from the kernel, so we
* don't have to do much to keep kernel and user recovery in sync.
*/
-int bmap(struct inode *inode, int block)
+int journal_bmap(journal_t *journal, blk_t block, unsigned long *phys)
{
- int retval;
- blk_t phys;
-
- retval = ext2fs_bmap(inode->i_ctx->fs, inode->i_ino, &inode->i_ext2,
- NULL, 0, block, &phys);
+ struct inode *inode = journal->j_inode;
+ errcode_t retval;
+ blk_t pblk;
- if (retval)
- com_err(inode->i_ctx->device_name, retval,
- _("bmap journal inode %ld, block %d\n"),
- inode->i_ino, block);
+ if (!inode) {
+ *phys = block;
+ return 0;
+ }
- return phys;
+ retval= ext2fs_bmap(inode->i_ctx->fs, inode->i_ino,
+ &inode->i_ext2, NULL, 0, block, &pblk);
+ *phys = pblk;
+ return (retval);
}
-struct buffer_head *getblk(e2fsck_t ctx, blk_t blocknr, int blocksize)
+struct buffer_head *getblk(kdev_t kdev, blk_t blocknr, int blocksize)
{
struct buffer_head *bh;
- bh = e2fsck_allocate_memory(ctx, sizeof(*bh), "block buffer");
+ bh = e2fsck_allocate_memory(kdev->k_ctx, sizeof(*bh), "block buffer");
if (!bh)
return NULL;
jfs_debug(4, "getblk for block %lu (%d bytes)(total %d)\n",
(unsigned long) blocknr, blocksize, ++bh_count);
- bh->b_ctx = ctx;
+ bh->b_ctx = kdev->k_ctx;
+ if (kdev->k_dev == K_DEV_FS)
+ bh->b_io = kdev->k_ctx->fs->io;
+ else
+ bh->b_io = kdev->k_ctx->journal_io;
bh->b_size = blocksize;
bh->b_blocknr = blocknr;
@@ -78,7 +83,7 @@ void ll_rw_block(int rw, int nr, struct buffer_head *bhp[])
if (rw == READ && !bh->b_uptodate) {
jfs_debug(3, "reading block %lu/%p\n",
(unsigned long) bh->b_blocknr, (void *) bh);
- retval = io_channel_read_blk(bh->b_ctx->journal_io,
+ retval = io_channel_read_blk(bh->b_io,
bh->b_blocknr,
1, bh->b_data);
if (retval) {
@@ -92,7 +97,7 @@ void ll_rw_block(int rw, int nr, struct buffer_head *bhp[])
} else if (rw == WRITE && bh->b_dirty) {
jfs_debug(3, "writing block %lu/%p\n",
(unsigned long) bh->b_blocknr, (void *) bh);
- retval = io_channel_write_blk(bh->b_ctx->journal_io,
+ retval = io_channel_write_blk(bh->b_io,
bh->b_blocknr,
1, bh->b_data);
if (retval) {
@@ -111,9 +116,9 @@ void ll_rw_block(int rw, int nr, struct buffer_head *bhp[])
}
}
-void mark_buffer_dirty(struct buffer_head *bh, int dummy)
+void mark_buffer_dirty(struct buffer_head *bh)
{
- bh->b_dirty = dummy | 1; /* use dummy to avoid unused variable */
+ bh->b_dirty = 1;
}
static void mark_buffer_clean(struct buffer_head * bh)
@@ -161,10 +166,11 @@ static errcode_t e2fsck_journal_init_inode(e2fsck_t ctx,
struct ext2_super_block *s,
journal_t **journal)
{
- struct inode *inode;
+ struct inode *inode = NULL;
struct buffer_head *bh;
- blk_t start;
+ unsigned long start;
int retval;
+ struct kdev_s *dev_fs = NULL, *dev_journal;
jfs_debug(1, "Using journal inode %u\n", s->s_journal_inum);
*journal = e2fsck_allocate_memory(ctx, sizeof(journal_t), "journal");
@@ -172,19 +178,31 @@ static errcode_t e2fsck_journal_init_inode(e2fsck_t ctx,
return EXT2_ET_NO_MEMORY;
}
+ dev_fs = e2fsck_allocate_memory(ctx, 2*sizeof(struct kdev_s), "kdev");
+ if (!dev_fs) {
+ retval = EXT2_ET_NO_MEMORY;
+ goto errout;
+ }
+ dev_journal = dev_fs+1;
+
inode = e2fsck_allocate_memory(ctx, sizeof(*inode), "journal inode");
if (!inode) {
retval = EXT2_ET_NO_MEMORY;
- goto exit_journal;
+ goto errout;
}
inode->i_ctx = ctx;
inode->i_ino = s->s_journal_inum;
retval = ext2fs_read_inode(ctx->fs, s->s_journal_inum, &inode->i_ext2);
if (retval)
- goto exit_inode;
+ goto errout;
- (*journal)->j_dev = ctx;
+ dev_fs->k_ctx = dev_journal->k_ctx = ctx;
+ dev_fs->k_dev = K_DEV_FS;
+ dev_journal->k_dev = K_DEV_JOURNAL;
+
+ (*journal)->j_dev = dev_journal;
+ (*journal)->j_fs_dev = dev_fs;
(*journal)->j_inode = inode;
(*journal)->j_blocksize = ctx->fs->blocksize;
(*journal)->j_maxlen = inode->i_ext2.i_size / (*journal)->j_blocksize;
@@ -193,26 +211,27 @@ static errcode_t e2fsck_journal_init_inode(e2fsck_t ctx,
if (!inode->i_ext2.i_links_count ||
!LINUX_S_ISREG(inode->i_ext2.i_mode) ||
(*journal)->j_maxlen < JFS_MIN_JOURNAL_BLOCKS ||
- (start = bmap(inode, 0)) == 0) {
- retval = EXT2_ET_BAD_INODE_NUM;
- goto exit_inode;
+ (retval = journal_bmap(*journal, 0, &start)) != 0) {
+ goto errout;
}
- bh = getblk(ctx, start, (*journal)->j_blocksize);
+ bh = getblk(dev_journal, start, (*journal)->j_blocksize);
if (!bh) {
retval = EXT2_ET_NO_MEMORY;
- goto exit_inode;
+ goto errout;
}
(*journal)->j_sb_buffer = bh;
(*journal)->j_superblock = (journal_superblock_t *)bh->b_data;
return 0;
-exit_inode:
- ext2fs_free_mem((void **)&inode);
-exit_journal:
- ext2fs_free_mem((void **)journal);
-
+errout:
+ if (dev_fs)
+ ext2fs_free_mem((void **)&dev_fs);
+ if (inode)
+ ext2fs_free_mem((void **)&inode);
+ if (journal)
+ ext2fs_free_mem((void **)journal);
return retval;
}
@@ -228,7 +247,17 @@ static errcode_t e2fsck_journal_init_dev(e2fsck_t ctx,
struct ext2_super_block jsuper;
struct problem_context pctx;
const char *journal_name;
+ struct kdev_s *dev_fs = NULL, *dev_journal;
+ dev_fs = e2fsck_allocate_memory(ctx, 2*sizeof(struct kdev_s), "kdev");
+ if (!dev_fs) {
+ return EXT2_ET_NO_MEMORY;
+ }
+ dev_journal = dev_fs+1;
+ dev_fs->k_ctx = dev_journal->k_ctx = ctx;
+ dev_fs->k_dev = K_DEV_FS;
+ dev_journal->k_dev = K_DEV_JOURNAL;
+
clear_problem_context(&pctx);
journal_name = ctx->journal_name;
if (!journal_name)
@@ -255,7 +284,7 @@ static errcode_t e2fsck_journal_init_dev(e2fsck_t ctx,
io_channel_set_blksize(ctx->journal_io, blocksize);
start = (blocksize == 1024) ? 1 : 0;
- bh = getblk(ctx, start, blocksize);
+ bh = getblk(dev_journal, start, blocksize);
if (!bh)
return EXT2_ET_NO_MEMORY;
ll_rw_block(READ, 1, &bh);
@@ -285,12 +314,13 @@ static errcode_t e2fsck_journal_init_dev(e2fsck_t ctx,
return EXT2_ET_NO_MEMORY;
}
- (*journal)->j_dev = ctx;
+ (*journal)->j_dev = dev_journal;
+ (*journal)->j_fs_dev = dev_fs;
(*journal)->j_inode = NULL;
(*journal)->j_blocksize = ctx->fs->blocksize;
(*journal)->j_maxlen = jsuper.s_blocks_count;
- bh = getblk(ctx, start+1, (*journal)->j_blocksize);
+ bh = getblk(dev_journal, start+1, (*journal)->j_blocksize);
if (!bh) {
retval = EXT2_ET_NO_MEMORY;
goto errout;
@@ -301,6 +331,7 @@ static errcode_t e2fsck_journal_init_dev(e2fsck_t ctx,
return 0;
errout:
+ ext2fs_free_mem((void **)&dev_fs);
ext2fs_free_mem((void **)journal);
return retval;
}
@@ -354,8 +385,7 @@ static errcode_t e2fsck_journal_fix_bad_inode(e2fsck_t ctx,
#define V1_SB_SIZE 0x0024
static void clear_v2_journal_fields(journal_t *journal)
{
- e2fsck_t ctx = journal->j_dev;
- struct buffer_head *jbh = journal->j_sb_buffer;
+ e2fsck_t ctx = journal->j_dev->k_ctx;
struct problem_context pctx;
clear_problem_context(&pctx);
@@ -365,13 +395,13 @@ static void clear_v2_journal_fields(journal_t *journal)
memset(((char *) journal->j_superblock) + V1_SB_SIZE, 0,
ctx->fs->blocksize-V1_SB_SIZE);
- mark_buffer_dirty(journal->j_sb_buffer, 1);
+ mark_buffer_dirty(journal->j_sb_buffer);
}
static errcode_t e2fsck_journal_load(journal_t *journal)
{
- e2fsck_t ctx = journal->j_dev;
+ e2fsck_t ctx = journal->j_dev->k_ctx;
journal_superblock_t *jsb;
struct buffer_head *jbh = journal->j_sb_buffer;
struct problem_context pctx;
@@ -501,7 +531,7 @@ static void e2fsck_journal_reset_super(e2fsck_t ctx, journal_superblock_t *jsb,
new_seq ^= u.val[i];
jsb->s_sequence = htonl(new_seq);
- mark_buffer_dirty(journal->j_sb_buffer, 1);
+ mark_buffer_dirty(journal->j_sb_buffer);
ll_rw_block(WRITE, 1, &journal->j_sb_buffer);
}
@@ -542,7 +572,7 @@ static void e2fsck_journal_release(e2fsck_t ctx, journal_t *journal,
jsb->s_sequence = htonl(journal->j_transaction_sequence);
if (reset)
jsb->s_start = 0; /* this marks the journal as empty */
- mark_buffer_dirty(journal->j_sb_buffer, 1);
+ mark_buffer_dirty(journal->j_sb_buffer);
}
brelse(journal->j_sb_buffer);
@@ -665,6 +695,7 @@ static errcode_t recover_ext3_journal(e2fsck_t ctx)
journal_t *journal;
int retval;
+ journal_init_revoke_caches();
retval = e2fsck_get_journal(ctx, &journal);
if (retval)
return retval;
@@ -685,10 +716,11 @@ static errcode_t recover_ext3_journal(e2fsck_t ctx)
ctx->fs->super->s_state |= EXT2_ERROR_FS;
ext2fs_mark_super_dirty(ctx->fs);
journal->j_superblock->s_errno = 0;
- mark_buffer_dirty(journal->j_sb_buffer, 1);
+ mark_buffer_dirty(journal->j_sb_buffer);
}
errout:
+ journal_destroy_revoke_caches();
e2fsck_journal_release(ctx, journal, 1, 0);
return retval;
}
diff --git a/e2fsck/recovery.c b/e2fsck/recovery.c
index cabf278f..e8e41630 100644
--- a/e2fsck/recovery.c
+++ b/e2fsck/recovery.c
@@ -18,11 +18,10 @@
#else
#include <linux/sched.h>
#include <linux/fs.h>
-#include <linux/jfs.h>
+#include <linux/jbd.h>
#include <linux/errno.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
#include <linux/locks.h>
-#include <linux/buffer.h>
#endif
/*
@@ -40,13 +39,15 @@ struct recovery_info
};
enum passtype {PASS_SCAN, PASS_REVOKE, PASS_REPLAY};
-static int do_one_pass(journal_t *, struct recovery_info *, enum passtype);
-static int scan_revoke_records(journal_t *, struct buffer_head *, tid_t, struct recovery_info *);
+static int do_one_pass(journal_t *journal,
+ struct recovery_info *info, enum passtype pass);
+static int scan_revoke_records(journal_t *, struct buffer_head *,
+ tid_t, struct recovery_info *);
#ifdef __KERNEL__
/* Release readahead buffers after use */
-static void brelse_array(struct buffer_head *b[], int n)
+void journal_brelse_array(struct buffer_head *b[], int n)
{
while (--n >= 0)
brelse (b[n]);
@@ -69,7 +70,8 @@ static void brelse_array(struct buffer_head *b[], int n)
static int do_readahead(journal_t *journal, unsigned int start)
{
int err;
- unsigned int max, nbufs, next, blocknr;
+ unsigned int max, nbufs, next;
+ unsigned long blocknr;
struct buffer_head *bh;
struct buffer_head * bufs[MAXBUF];
@@ -85,16 +87,14 @@ static int do_readahead(journal_t *journal, unsigned int start)
nbufs = 0;
for (next = start; next < max; next++) {
- blocknr = next;
- if (journal->j_inode)
- blocknr = bmap(journal->j_inode, next);
- if (!blocknr) {
- printk (KERN_ERR "JFS: bad block at offset %u\n",
+ err = journal_bmap(journal, next, &blocknr);
+
+ if (err) {
+ printk (KERN_ERR "JBD: bad block at offset %u\n",
next);
- err = -EIO;
goto failed;
}
-
+
bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
if (!bh) {
err = -ENOMEM;
@@ -105,7 +105,7 @@ static int do_readahead(journal_t *journal, unsigned int start)
bufs[nbufs++] = bh;
if (nbufs == MAXBUF) {
ll_rw_block(READ, nbufs, bufs);
- brelse_array(bufs, nbufs);
+ journal_brelse_array(bufs, nbufs);
nbufs = 0;
}
} else
@@ -115,10 +115,10 @@ static int do_readahead(journal_t *journal, unsigned int start)
if (nbufs)
ll_rw_block(READ, nbufs, bufs);
err = 0;
-
+
failed:
if (nbufs)
- brelse_array(bufs, nbufs);
+ journal_brelse_array(bufs, nbufs);
return err;
}
@@ -132,27 +132,26 @@ failed:
static int jread(struct buffer_head **bhp, journal_t *journal,
unsigned int offset)
{
- unsigned int blocknr;
+ int err;
+ unsigned long blocknr;
struct buffer_head *bh;
*bhp = NULL;
J_ASSERT (offset < journal->j_maxlen);
-
- blocknr = offset;
- if (journal->j_inode)
- blocknr = bmap(journal->j_inode, offset);
- if (!blocknr) {
- printk (KERN_ERR "JFS: bad block at offset %u\n",
+ err = journal_bmap(journal, offset, &blocknr);
+
+ if (err) {
+ printk (KERN_ERR "JBD: bad block at offset %u\n",
offset);
- return -EIO;
+ return err;
}
-
+
bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
if (!bh)
return -ENOMEM;
-
+
if (!buffer_uptodate(bh)) {
/* If this is a brand new buffer, start readahead.
Otherwise, we assume we are already reading it. */
@@ -160,14 +159,14 @@ static int jread(struct buffer_head **bhp, journal_t *journal,
do_readahead(journal, offset);
wait_on_buffer(bh);
}
-
+
if (!buffer_uptodate(bh)) {
- printk (KERN_ERR "JFS: Failed to read block at offset %u\n",
+ printk (KERN_ERR "JBD: Failed to read block at offset %u\n",
offset);
brelse(bh);
return -EIO;
}
-
+
*bhp = bh;
return 0;
}
@@ -182,12 +181,12 @@ static int count_tags(struct buffer_head *bh, int size)
char * tagp;
journal_block_tag_t * tag;
int nr = 0;
-
+
tagp = &bh->b_data[sizeof(journal_header_t)];
-
+
while ((tagp - bh->b_data + sizeof(journal_block_tag_t)) <= size) {
tag = (journal_block_tag_t *) tagp;
-
+
nr++;
tagp += sizeof(journal_block_tag_t);
if (!(tag->t_flags & htonl(JFS_FLAG_SAME_UUID)))
@@ -196,7 +195,7 @@ static int count_tags(struct buffer_head *bh, int size)
if (tag->t_flags & htonl(JFS_FLAG_LAST_TAG))
break;
}
-
+
return nr;
}
@@ -237,7 +236,7 @@ int journal_recover(journal_t *journal)
*/
if (!sb->s_start) {
- jfs_debug(1, "No recovery required, last transaction %d\n",
+ jbd_debug(1, "No recovery required, last transaction %d\n",
ntohl(sb->s_sequence));
journal->j_transaction_sequence = ntohl(sb->s_sequence) + 1;
return 0;
@@ -250,10 +249,10 @@ int journal_recover(journal_t *journal)
if (!err)
err = do_one_pass(journal, &info, PASS_REPLAY);
- jfs_debug(0, "JFS: recovery, exit status %d, "
+ jbd_debug(0, "JBD: recovery, exit status %d, "
"recovered transactions %u to %u\n",
err, info.start_transaction, info.end_transaction);
- jfs_debug(0, "JFS: Replayed %d and revoked %d/%d blocks\n",
+ jbd_debug(0, "JBD: Replayed %d and revoked %d/%d blocks\n",
info.nr_replays, info.nr_revoke_hits, info.nr_revokes);
/* Restart the log at the next transaction ID, thus invalidating
@@ -261,7 +260,7 @@ int journal_recover(journal_t *journal)
journal->j_transaction_sequence = ++info.end_transaction;
journal_clear_revoke(journal);
- fsync_dev(journal->j_dev);
+ fsync_no_super(journal->j_fs_dev);
return err;
}
@@ -284,19 +283,21 @@ int journal_skip_recovery(journal_t *journal)
struct recovery_info info;
- memset(&info, 0, sizeof(info));
+ memset (&info, 0, sizeof(info));
sb = journal->j_superblock;
err = do_one_pass(journal, &info, PASS_SCAN);
if (err) {
- printk(KERN_ERR "JFS: error %d scanning journal\n", err);
+ printk(KERN_ERR "JBD: error %d scanning journal\n", err);
++journal->j_transaction_sequence;
} else {
+#ifdef CONFIG_JBD_DEBUG
int dropped = info.end_transaction - ntohl(sb->s_sequence);
+#endif
- jfs_debug(0,
- "JFS: ignoring %d transaction%s from the journal.\n",
+ jbd_debug(0,
+ "JBD: ignoring %d transaction%s from the journal.\n",
dropped, (dropped == 1) ? "" : "s");
journal->j_transaction_sequence = ++info.end_transaction;
}
@@ -306,8 +307,8 @@ int journal_skip_recovery(journal_t *journal)
return err;
}
-static int do_one_pass(journal_t *journal, struct recovery_info *info,
- enum passtype pass)
+static int do_one_pass(journal_t *journal,
+ struct recovery_info *info, enum passtype pass)
{
unsigned int first_commit_ID, next_commit_ID;
@@ -337,9 +338,9 @@ static int do_one_pass(journal_t *journal, struct recovery_info *info,
first_commit_ID = next_commit_ID;
if (pass == PASS_SCAN)
info->start_transaction = first_commit_ID;
-
- jfs_debug(1, "Starting recovery pass %d\n", pass);
-
+
+ jbd_debug(1, "Starting recovery pass %d\n", pass);
+
/*
* Now we walk through the log, transaction by transaction,
* making sure that each transaction has a commit block in the
@@ -361,19 +362,19 @@ static int do_one_pass(journal_t *journal, struct recovery_info *info,
if (pass != PASS_SCAN)
if (tid_geq(next_commit_ID, info->end_transaction))
break;
-
- jfs_debug(2, "Scanning for sequence ID %u at %lu/%lu\n",
+
+ jbd_debug(2, "Scanning for sequence ID %u at %lu/%lu\n",
next_commit_ID, next_log_block, journal->j_last);
/* Skip over each chunk of the transaction looking
* either the next descriptor block or the final commit
* record. */
- jfs_debug(3, "JFS: checking block %ld\n", next_log_block);
+ jbd_debug(3, "JBD: checking block %ld\n", next_log_block);
err = jread(&bh, journal, next_log_block);
if (err)
goto failed;
-
+
next_log_block++;
wrap(journal, next_log_block);
@@ -383,16 +384,16 @@ static int do_one_pass(journal_t *journal, struct recovery_info *info,
* expected sequence number. Otherwise, we're all done
* here. */
- tmp = (journal_header_t *) bh->b_data;
+ tmp = (journal_header_t *)bh->b_data;
if (tmp->h_magic != htonl(JFS_MAGIC_NUMBER)) {
brelse(bh);
break;
}
-
+
blocktype = ntohl(tmp->h_blocktype);
sequence = ntohl(tmp->h_sequence);
- jfs_debug(3, "Found magic %d, sequence %d\n",
+ jbd_debug(3, "Found magic %d, sequence %d\n",
blocktype, sequence);
if (sequence != next_commit_ID) {
@@ -403,14 +404,15 @@ static int do_one_pass(journal_t *journal, struct recovery_info *info,
/* OK, we have a valid descriptor block which matches
* all of the sequence number checks. What are we going
* to do with it? That depends on the pass... */
-
+
switch(blocktype) {
case JFS_DESCRIPTOR_BLOCK:
/* If it is a valid descriptor block, replay it
* in pass REPLAY; otherwise, just skip over the
* blocks it describes. */
if (pass != PASS_REPLAY) {
- next_log_block += count_tags(bh, journal->j_blocksize);
+ next_log_block +=
+ count_tags(bh, journal->j_blocksize);
wrap(journal, next_log_block);
brelse(bh);
continue;
@@ -424,7 +426,7 @@ static int do_one_pass(journal_t *journal, struct recovery_info *info,
while ((tagp - bh->b_data +sizeof(journal_block_tag_t))
<= journal->j_blocksize) {
unsigned long io_block;
-
+
tag = (journal_block_tag_t *) tagp;
flags = ntohl(tag->t_flags);
@@ -436,7 +438,7 @@ static int do_one_pass(journal_t *journal, struct recovery_info *info,
* report failure at the end. */
success = err;
printk (KERN_ERR
- "JFS: IO error %d recovering "
+ "JBD: IO error %d recovering "
"block %ld in log\n",
err, io_block);
} else {
@@ -458,11 +460,11 @@ static int do_one_pass(journal_t *journal, struct recovery_info *info,
/* Find a buffer for the new
* data being restored */
- nbh = getblk(journal->j_dev, blocknr,
+ nbh = getblk(journal->j_fs_dev, blocknr,
journal->j_blocksize);
if (nbh == NULL) {
printk(KERN_ERR
- "JFS: Out of memory "
+ "JBD: Out of memory "
"during recovery.\n");
err = -ENOMEM;
brelse(bh);
@@ -470,13 +472,16 @@ static int do_one_pass(journal_t *journal, struct recovery_info *info,
goto failed;
}
- memcpy(nbh->b_data, obh->b_data,
- journal->j_blocksize);
+ memcpy(nbh->b_data, obh->b_data,
+ journal->j_blocksize);
if (flags & JFS_FLAG_ESCAPE) {
- * ((unsigned int *) bh->b_data) = htonl(JFS_MAGIC_NUMBER);
+ *((unsigned int *)bh->b_data) =
+ htonl(JFS_MAGIC_NUMBER);
}
-
- mark_buffer_dirty(nbh, 1);
+
+ BUFFER_TRACE(nbh, "marking dirty");
+ mark_buffer_dirty(nbh);
+ BUFFER_TRACE(nbh, "marking uptodate");
mark_buffer_uptodate(nbh, 1);
++info->nr_replays;
/* ll_rw_block(WRITE, 1, &nbh); */
@@ -495,7 +500,7 @@ static int do_one_pass(journal_t *journal, struct recovery_info *info,
brelse(bh);
continue;
-
+
case JFS_COMMIT_BLOCK:
/* Found an expected commit block: not much to
* do other than move on to the next sequence
@@ -512,7 +517,7 @@ static int do_one_pass(journal_t *journal, struct recovery_info *info,
continue;
}
- err = scan_revoke_records(journal, bh,
+ err = scan_revoke_records(journal, bh,
next_commit_ID, info);
brelse(bh);
if (err)
@@ -520,7 +525,7 @@ static int do_one_pass(journal_t *journal, struct recovery_info *info,
continue;
default:
- jfs_debug(3, "Unrecognised magic %d, end of scan.\n",
+ jbd_debug(3, "Unrecognised magic %d, end of scan.\n",
blocktype);
goto done;
}
@@ -540,7 +545,7 @@ static int do_one_pass(journal_t *journal, struct recovery_info *info,
/* It's really bad news if different passes end up at
* different places (but possible due to IO errors). */
if (info->end_transaction != next_commit_ID) {
- printk (KERN_ERR "JFS: recovery pass %d ended at "
+ printk (KERN_ERR "JBD: recovery pass %d ended at "
"transaction %u, expected %u\n",
pass, next_commit_ID, info->end_transaction);
if (!success)
@@ -562,7 +567,7 @@ static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
{
journal_revoke_header_t *header;
int offset, max;
-
+
header = (journal_revoke_header_t *) bh->b_data;
offset = sizeof(journal_revoke_header_t);
max = ntohl(header->r_count);
diff --git a/e2fsck/revoke.c b/e2fsck/revoke.c
index cdcf8efb..9866935f 100644
--- a/e2fsck/revoke.c
+++ b/e2fsck/revoke.c
@@ -50,11 +50,11 @@
* Revoke information on buffers is a tri-state value:
*
* RevokeValid clear: no cached revoke status, need to look it up
- * RevokeValid set, Revoke clear:
+ * RevokeValid set, Revoked clear:
* buffer has not been revoked, and cancel_revoke
* need do nothing.
- * RevokeValid set, Revoke set:
- * buffer has been revoked.
+ * RevokeValid set, Revoked set:
+ * buffer has been revoked.
*/
#ifndef __KERNEL__
@@ -62,12 +62,13 @@
#else
#include <linux/sched.h>
#include <linux/fs.h>
-#include <linux/jfs.h>
+#include <linux/jbd.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/locks.h>
-#include <linux/buffer.h>
#include <linux/list.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
#endif
static kmem_cache_t *revoke_record_cache;
@@ -77,7 +78,7 @@ static kmem_cache_t *revoke_table_cache;
journal replay, this involves recording the transaction ID of the
last transaction to revoke this block. */
-struct jfs_revoke_record_s
+struct jbd_revoke_record_s
{
struct list_head hash;
tid_t sequence; /* Used for recovery only */
@@ -86,7 +87,7 @@ struct jfs_revoke_record_s
/* The revoke table is just a simple hash table of revoke records. */
-struct jfs_revoke_table_s
+struct jbd_revoke_table_s
{
/* It is conceivable that we might want a larger hash table
* for recovery. Must be a power of two. */
@@ -98,9 +99,9 @@ struct jfs_revoke_table_s
#ifdef __KERNEL__
static void write_one_revoke_record(journal_t *, transaction_t *,
- struct buffer_head **, int *,
- struct jfs_revoke_record_s *);
-static void flush_descriptor(journal_t *, struct buffer_head *, int);
+ struct journal_head **, int *,
+ struct jbd_revoke_record_s *);
+static void flush_descriptor(journal_t *, struct journal_head *, int);
#endif
/* Utility functions to maintain the revoke table */
@@ -108,7 +109,7 @@ static void flush_descriptor(journal_t *, struct buffer_head *, int);
/* Borrowed from buffer.c: this is a tried and tested block hash function */
static inline int hash(journal_t *journal, unsigned long block)
{
- struct jfs_revoke_table_s *table = journal->j_revoke;
+ struct jbd_revoke_table_s *table = journal->j_revoke;
int hash_shift = table->hash_shift;
return ((block << (hash_shift - 6)) ^
@@ -116,43 +117,80 @@ static inline int hash(journal_t *journal, unsigned long block)
(block << (hash_shift - 12))) & (table->hash_size - 1);
}
-static int insert_revoke_hash(journal_t *journal,
- unsigned long blocknr, tid_t seq)
+int insert_revoke_hash(journal_t *journal, unsigned long blocknr, tid_t seq)
{
struct list_head *hash_list;
- struct jfs_revoke_record_s *record;
-
- record = kmem_cache_alloc(revoke_record_cache, GFP_KERNEL);
+ struct jbd_revoke_record_s *record;
+
+repeat:
+ record = kmem_cache_alloc(revoke_record_cache, GFP_NOFS);
if (!record)
- return -ENOMEM;
+ goto oom;
record->sequence = seq;
record->blocknr = blocknr;
hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
list_add(&record->hash, hash_list);
return 0;
+
+oom:
+#ifdef __KERNEL__
+ if (!journal_oom_retry)
+ return -ENOMEM;
+ jbd_debug(1, "ENOMEM in " __FUNCTION__ ", retrying.\n");
+ current->policy |= SCHED_YIELD;
+ schedule();
+ goto repeat;
+#else
+ return -ENOMEM;
+#endif
}
/* Find a revoke record in the journal's hash table. */
-static struct jfs_revoke_record_s *find_revoke_record(journal_t *journal,
+static struct jbd_revoke_record_s *find_revoke_record(journal_t *journal,
unsigned long blocknr)
{
struct list_head *hash_list;
- struct jfs_revoke_record_s *record;
+ struct jbd_revoke_record_s *record;
hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
- record = (struct jfs_revoke_record_s *) hash_list->next;
+ record = (struct jbd_revoke_record_s *) hash_list->next;
while (&(record->hash) != hash_list) {
if (record->blocknr == blocknr)
return record;
- record = (struct jfs_revoke_record_s *) record->hash.next;
+ record = (struct jbd_revoke_record_s *) record->hash.next;
}
return NULL;
}
+int __init journal_init_revoke_caches(void)
+{
+ revoke_record_cache = kmem_cache_create("revoke_record",
+ sizeof(struct jbd_revoke_record_s),
+ 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
+ if (revoke_record_cache == 0)
+ return -ENOMEM;
+ revoke_table_cache = kmem_cache_create("revoke_table",
+ sizeof(struct jbd_revoke_table_s),
+ 0, 0, NULL, NULL);
+ if (revoke_table_cache == 0) {
+ kmem_cache_destroy(revoke_record_cache);
+ revoke_record_cache = NULL;
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+void journal_destroy_revoke_caches(void)
+{
+ kmem_cache_destroy(revoke_record_cache);
+ revoke_record_cache = 0;
+ kmem_cache_destroy(revoke_table_cache);
+ revoke_table_cache = 0;
+}
/* Initialise the revoke table for a given journal to a given size. */
@@ -162,21 +200,6 @@ int journal_init_revoke(journal_t *journal, int hash_size)
J_ASSERT (journal->j_revoke == NULL);
- if (!revoke_record_cache)
- revoke_record_cache =
- kmem_cache_create ("revoke_record",
- sizeof(struct jfs_revoke_record_s),
- 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
-
- if (!revoke_table_cache)
- revoke_table_cache =
- kmem_cache_create ("revoke_table",
- sizeof(struct jfs_revoke_table_s),
- 0, 0, NULL, NULL);
-
- if (!revoke_record_cache || !revoke_table_cache)
- return -ENOMEM;
-
journal->j_revoke = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL);
if (!journal->j_revoke)
return -ENOMEM;
@@ -210,7 +233,7 @@ int journal_init_revoke(journal_t *journal, int hash_size)
void journal_destroy_revoke(journal_t *journal)
{
- struct jfs_revoke_table_s *table;
+ struct jbd_revoke_table_s *table;
struct list_head *hash_list;
int i;
@@ -248,51 +271,87 @@ void journal_destroy_revoke(journal_t *journal)
* parameter, but does _not_ forget the buffer_head if the bh was only
* found implicitly.
*
- * Revoke must observe the same synchronisation rules as bforget: it
- * must not discard the buffer once it has blocked.
+ * bh_in may not be a journalled buffer - it may have come off
+ * the hash tables without an attached journal_head.
+ *
+ * If bh_in is non-zero, journal_revoke() will decrement its b_count
+ * by one.
*/
int journal_revoke(handle_t *handle, unsigned long blocknr,
struct buffer_head *bh_in)
{
- struct buffer_head *bh;
+ struct buffer_head *bh = NULL;
journal_t *journal;
kdev_t dev;
int err;
+ if (bh_in)
+ BUFFER_TRACE(bh_in, "enter");
+
journal = handle->h_transaction->t_journal;
if (!journal_set_features(journal, 0, 0, JFS_FEATURE_INCOMPAT_REVOKE)){
J_ASSERT (!"Cannot set revoke feature!");
return -EINVAL;
}
-
- dev = journal->j_dev;
+
+ dev = journal->j_fs_dev;
bh = bh_in;
- if (!bh)
+ if (!bh) {
bh = get_hash_table(dev, blocknr, journal->j_blocksize);
+ if (bh)
+ BUFFER_TRACE(bh, "found on hash");
+ }
+#ifdef JBD_EXPENSIVE_CHECKING
+ else {
+ struct buffer_head *bh2;
+
+ /* If there is a different buffer_head lying around in
+ * memory anywhere... */
+ bh2 = get_hash_table(dev, blocknr, journal->j_blocksize);
+ if (bh2) {
+ /* ... and it has RevokeValid status... */
+ if ((bh2 != bh) &&
+ test_bit(BH_RevokeValid, &bh2->b_state))
+ /* ...then it better be revoked too,
+ * since it's illegal to create a revoke
+ * record against a buffer_head which is
+ * not marked revoked --- that would
+ * risk missing a subsequent revoke
+ * cancel. */
+ J_ASSERT_BH(bh2, test_bit(BH_Revoked, &
+ bh2->b_state));
+ __brelse(bh2);
+ }
+ }
+#endif
/* We really ought not ever to revoke twice in a row without
first having the revoke cancelled: it's illegal to free a
block twice without allocating it in between! */
if (bh) {
- J_ASSERT (!test_and_set_bit(BH_Revoked, &bh->b_state));
+ J_ASSERT_BH(bh, !test_bit(BH_Revoked, &bh->b_state));
+ set_bit(BH_Revoked, &bh->b_state);
set_bit(BH_RevokeValid, &bh->b_state);
- if (bh_in)
+ if (bh_in) {
+ BUFFER_TRACE(bh_in, "call journal_forget");
journal_forget(handle, bh_in);
- else
- brelse(bh);
+ } else {
+ BUFFER_TRACE(bh, "call brelse");
+ __brelse(bh);
+ }
}
lock_journal(journal);
- err = insert_revoke_hash(journal, blocknr,
- handle->h_transaction->t_tid);
+ jbd_debug(2, "insert revoke for block %lu, bh_in=%p\n", blocknr, bh_in);
+ err = insert_revoke_hash(journal, blocknr,
+ handle->h_transaction->t_tid);
unlock_journal(journal);
-
+ BUFFER_TRACE(bh_in, "exit");
return err;
}
-
/*
* Cancel an outstanding revoke. For use only internally by the
* journaling code (called from journal_get_write_access).
@@ -309,16 +368,17 @@ int journal_revoke(handle_t *handle, unsigned long blocknr,
* set.
*
* The caller must have the journal locked.
- * */
-
-void journal_cancel_revoke(handle_t *handle, struct buffer_head *bh)
+ */
+int journal_cancel_revoke(handle_t *handle, struct journal_head *jh)
{
- struct jfs_revoke_record_s *record;
+ struct jbd_revoke_record_s *record;
journal_t *journal = handle->h_transaction->t_journal;
int need_cancel;
+ int did_revoke = 0; /* akpm: debug */
+ struct buffer_head *bh = jh2bh(jh);
- J_ASSERT (journal->j_locked);
-
+ jbd_debug(4, "journal_head %p, cancelling revoke\n", jh);
+
/* Is the existing Revoke bit valid? If so, we trust it, and
* only perform the full cancel if the revoke bit is set. If
* not, we can't trust the revoke bit, and we need to do the
@@ -329,14 +389,38 @@ void journal_cancel_revoke(handle_t *handle, struct buffer_head *bh)
need_cancel = 1;
clear_bit(BH_Revoked, &bh->b_state);
}
-
+
if (need_cancel) {
record = find_revoke_record(journal, bh->b_blocknr);
if (record) {
+ jbd_debug(4, "cancelled existing revoke on "
+ "blocknr %lu\n", bh->b_blocknr);
list_del(&record->hash);
kmem_cache_free(revoke_record_cache, record);
+ did_revoke = 1;
}
}
+
+#ifdef JBD_EXPENSIVE_CHECKING
+ /* There better not be one left behind by now! */
+ record = find_revoke_record(journal, bh->b_blocknr);
+ J_ASSERT_JH(jh, record == NULL);
+#endif
+
+ /* Finally, have we just cleared revoke on an unhashed
+ * buffer_head? If so, we'd better make sure we clear the
+ * revoked status on any hashed alias too, otherwise the revoke
+ * state machine will get very upset later on. */
+ if (need_cancel && !bh->b_pprev) {
+ struct buffer_head *bh2;
+ bh2 = get_hash_table(bh->b_dev, bh->b_blocknr, bh->b_size);
+ if (bh2) {
+ clear_bit(BH_Revoked, &bh2->b_state);
+ __brelse(bh2);
+ }
+ }
+
+ return did_revoke;
}
@@ -350,12 +434,12 @@ void journal_cancel_revoke(handle_t *handle, struct buffer_head *bh)
void journal_write_revoke_records(journal_t *journal,
transaction_t *transaction)
{
- struct buffer_head *descriptor;
- struct jfs_revoke_record_s *record;
- struct jfs_revoke_table_s *revoke;
+ struct journal_head *descriptor;
+ struct jbd_revoke_record_s *record;
+ struct jbd_revoke_table_s *revoke;
struct list_head *hash_list;
int i, offset, count;
-
+
descriptor = NULL;
offset = 0;
count = 0;
@@ -365,7 +449,7 @@ void journal_write_revoke_records(journal_t *journal,
hash_list = &revoke->hash_table[i];
while (!list_empty(hash_list)) {
- record = (struct jfs_revoke_record_s *)
+ record = (struct jbd_revoke_record_s *)
hash_list->next;
write_one_revoke_record(journal, transaction,
&descriptor, &offset,
@@ -377,7 +461,7 @@ void journal_write_revoke_records(journal_t *journal,
}
if (descriptor)
flush_descriptor(journal, descriptor, offset);
- jfs_debug(1, "Wrote %d revoke records\n", count);
+ jbd_debug(1, "Wrote %d revoke records\n", count);
}
/*
@@ -387,24 +471,24 @@ void journal_write_revoke_records(journal_t *journal,
static void write_one_revoke_record(journal_t *journal,
transaction_t *transaction,
- struct buffer_head **descriptorp,
+ struct journal_head **descriptorp,
int *offsetp,
- struct jfs_revoke_record_s *record)
+ struct jbd_revoke_record_s *record)
{
- struct buffer_head *descriptor;
+ struct journal_head *descriptor;
int offset;
journal_header_t *header;
-
+
/* If we are already aborting, this all becomes a noop. We
still need to go round the loop in
journal_write_revoke_records in order to free all of the
revoke records: only the IO to the journal is omitted. */
- if (is_journal_abort(journal))
+ if (is_journal_aborted(journal))
return;
descriptor = *descriptorp;
offset = *offsetp;
-
+
/* Make sure we have a descriptor with space left for the record */
if (descriptor) {
if (offset == journal->j_blocksize) {
@@ -415,19 +499,22 @@ static void write_one_revoke_record(journal_t *journal,
if (!descriptor) {
descriptor = journal_get_descriptor_buffer(journal);
- header = (journal_header_t *) &descriptor->b_data[0];
+ if (!descriptor)
+ return;
+ header = (journal_header_t *) &jh2bh(descriptor)->b_data[0];
header->h_magic = htonl(JFS_MAGIC_NUMBER);
header->h_blocktype = htonl(JFS_REVOKE_BLOCK);
header->h_sequence = htonl(transaction->t_tid);
/* Record it so that we can wait for IO completion later */
+ JBUFFER_TRACE(descriptor, "file as BJ_LogCtl");
journal_file_buffer(descriptor, transaction, BJ_LogCtl);
-
+
offset = sizeof(journal_revoke_header_t);
*descriptorp = descriptor;
}
- * ((unsigned int *)(&descriptor->b_data[offset])) =
+ * ((unsigned int *)(&jh2bh(descriptor)->b_data[offset])) =
htonl(record->blocknr);
offset += 4;
*offsetp = offset;
@@ -441,20 +528,25 @@ static void write_one_revoke_record(journal_t *journal,
*/
static void flush_descriptor(journal_t *journal,
- struct buffer_head *descriptor,
+ struct journal_head *descriptor,
int offset)
{
journal_revoke_header_t *header;
-
- if (is_journal_abort(journal)) {
- brelse(descriptor);
+
+ if (is_journal_aborted(journal)) {
+ JBUFFER_TRACE(descriptor, "brelse");
+ __brelse(jh2bh(descriptor));
return;
}
- header = (journal_revoke_header_t *) descriptor->b_data;
+ header = (journal_revoke_header_t *) jh2bh(descriptor)->b_data;
header->r_count = htonl(offset);
- set_bit(BH_JWrite, &descriptor->b_state);
- ll_rw_block (WRITE, 1, &descriptor);
+ set_bit(BH_JWrite, &jh2bh(descriptor)->b_state);
+ {
+ struct buffer_head *bh = jh2bh(descriptor);
+ BUFFER_TRACE(bh, "write");
+ ll_rw_block (WRITE, 1, &bh);
+ }
}
#endif
@@ -485,7 +577,7 @@ int journal_set_revoke(journal_t *journal,
unsigned long blocknr,
tid_t sequence)
{
- struct jfs_revoke_record_s *record;
+ struct jbd_revoke_record_s *record;
record = find_revoke_record(journal, blocknr);
if (record) {
@@ -509,7 +601,7 @@ int journal_test_revoke(journal_t *journal,
unsigned long blocknr,
tid_t sequence)
{
- struct jfs_revoke_record_s *record;
+ struct jbd_revoke_record_s *record;
record = find_revoke_record(journal, blocknr);
if (!record)
@@ -528,15 +620,15 @@ void journal_clear_revoke(journal_t *journal)
{
int i;
struct list_head *hash_list;
- struct jfs_revoke_record_s *record;
- struct jfs_revoke_table_s *revoke;
+ struct jbd_revoke_record_s *record;
+ struct jbd_revoke_table_s *revoke;
revoke = journal->j_revoke;
for (i = 0; i < revoke->hash_size; i++) {
hash_list = &revoke->hash_table[i];
while (!list_empty(hash_list)) {
- record = (struct jfs_revoke_record_s*) hash_list->next;
+ record = (struct jbd_revoke_record_s*) hash_list->next;
list_del(&record->hash);
kmem_cache_free(revoke_record_cache, record);
}