1*6a54128fSAndroid Build Coastguard Worker /*
2*6a54128fSAndroid Build Coastguard Worker * journal.c --- code for handling the "ext3" journal
3*6a54128fSAndroid Build Coastguard Worker *
4*6a54128fSAndroid Build Coastguard Worker * Copyright (C) 2000 Andreas Dilger
5*6a54128fSAndroid Build Coastguard Worker * Copyright (C) 2000 Theodore Ts'o
6*6a54128fSAndroid Build Coastguard Worker *
7*6a54128fSAndroid Build Coastguard Worker * Parts of the code are based on fs/jfs/journal.c by Stephen C. Tweedie
8*6a54128fSAndroid Build Coastguard Worker * Copyright (C) 1999 Red Hat Software
9*6a54128fSAndroid Build Coastguard Worker *
10*6a54128fSAndroid Build Coastguard Worker * This file may be redistributed under the terms of the
11*6a54128fSAndroid Build Coastguard Worker * GNU General Public License version 2 or at your discretion
12*6a54128fSAndroid Build Coastguard Worker * any later version.
13*6a54128fSAndroid Build Coastguard Worker */
14*6a54128fSAndroid Build Coastguard Worker
15*6a54128fSAndroid Build Coastguard Worker #include "config.h"
16*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_SYS_MOUNT_H
17*6a54128fSAndroid Build Coastguard Worker #include <sys/param.h>
18*6a54128fSAndroid Build Coastguard Worker #include <sys/mount.h>
19*6a54128fSAndroid Build Coastguard Worker #define MNT_FL (MS_MGC_VAL | MS_RDONLY)
20*6a54128fSAndroid Build Coastguard Worker #endif
21*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_SYS_STAT_H
22*6a54128fSAndroid Build Coastguard Worker #include <sys/stat.h>
23*6a54128fSAndroid Build Coastguard Worker #endif
24*6a54128fSAndroid Build Coastguard Worker
25*6a54128fSAndroid Build Coastguard Worker #define E2FSCK_INCLUDE_INLINE_FUNCS
26*6a54128fSAndroid Build Coastguard Worker #include "uuid/uuid.h"
27*6a54128fSAndroid Build Coastguard Worker #include "journal.h"
28*6a54128fSAndroid Build Coastguard Worker
29*6a54128fSAndroid Build Coastguard Worker static int bh_count = 0;
30*6a54128fSAndroid Build Coastguard Worker
31*6a54128fSAndroid Build Coastguard Worker #if EXT2_FLAT_INCLUDES
32*6a54128fSAndroid Build Coastguard Worker #include "blkid.h"
33*6a54128fSAndroid Build Coastguard Worker #else
34*6a54128fSAndroid Build Coastguard Worker #include "blkid/blkid.h"
35*6a54128fSAndroid Build Coastguard Worker #endif
36*6a54128fSAndroid Build Coastguard Worker
37*6a54128fSAndroid Build Coastguard Worker /*
38*6a54128fSAndroid Build Coastguard Worker * Define USE_INODE_IO to use the inode_io.c / fileio.c codepaths.
39*6a54128fSAndroid Build Coastguard Worker * This creates a larger static binary, and a smaller binary using
40*6a54128fSAndroid Build Coastguard Worker * shared libraries. It's also probably slightly less CPU-efficient,
41*6a54128fSAndroid Build Coastguard Worker * which is why it's not on by default. But, it's a good way of
42*6a54128fSAndroid Build Coastguard Worker * testing the functions in inode_io.c and fileio.c.
43*6a54128fSAndroid Build Coastguard Worker */
44*6a54128fSAndroid Build Coastguard Worker #undef USE_INODE_IO
45*6a54128fSAndroid Build Coastguard Worker
46*6a54128fSAndroid Build Coastguard Worker /* Checksumming functions */
ext2fs_journal_verify_csum_type(journal_t * j,journal_superblock_t * jsb)47*6a54128fSAndroid Build Coastguard Worker static int ext2fs_journal_verify_csum_type(journal_t *j,
48*6a54128fSAndroid Build Coastguard Worker journal_superblock_t *jsb)
49*6a54128fSAndroid Build Coastguard Worker {
50*6a54128fSAndroid Build Coastguard Worker if (!jbd2_journal_has_csum_v2or3(j))
51*6a54128fSAndroid Build Coastguard Worker return 1;
52*6a54128fSAndroid Build Coastguard Worker
53*6a54128fSAndroid Build Coastguard Worker return jsb->s_checksum_type == JBD2_CRC32C_CHKSUM;
54*6a54128fSAndroid Build Coastguard Worker }
55*6a54128fSAndroid Build Coastguard Worker
ext2fs_journal_sb_csum(journal_superblock_t * jsb)56*6a54128fSAndroid Build Coastguard Worker static __u32 ext2fs_journal_sb_csum(journal_superblock_t *jsb)
57*6a54128fSAndroid Build Coastguard Worker {
58*6a54128fSAndroid Build Coastguard Worker __u32 crc, old_crc;
59*6a54128fSAndroid Build Coastguard Worker
60*6a54128fSAndroid Build Coastguard Worker old_crc = jsb->s_checksum;
61*6a54128fSAndroid Build Coastguard Worker jsb->s_checksum = 0;
62*6a54128fSAndroid Build Coastguard Worker crc = ext2fs_crc32c_le(~0, (unsigned char *)jsb,
63*6a54128fSAndroid Build Coastguard Worker sizeof(journal_superblock_t));
64*6a54128fSAndroid Build Coastguard Worker jsb->s_checksum = old_crc;
65*6a54128fSAndroid Build Coastguard Worker
66*6a54128fSAndroid Build Coastguard Worker return crc;
67*6a54128fSAndroid Build Coastguard Worker }
68*6a54128fSAndroid Build Coastguard Worker
ext2fs_journal_sb_csum_verify(journal_t * j,journal_superblock_t * jsb)69*6a54128fSAndroid Build Coastguard Worker static int ext2fs_journal_sb_csum_verify(journal_t *j,
70*6a54128fSAndroid Build Coastguard Worker journal_superblock_t *jsb)
71*6a54128fSAndroid Build Coastguard Worker {
72*6a54128fSAndroid Build Coastguard Worker __u32 provided, calculated;
73*6a54128fSAndroid Build Coastguard Worker
74*6a54128fSAndroid Build Coastguard Worker if (!jbd2_journal_has_csum_v2or3(j))
75*6a54128fSAndroid Build Coastguard Worker return 1;
76*6a54128fSAndroid Build Coastguard Worker
77*6a54128fSAndroid Build Coastguard Worker provided = ext2fs_be32_to_cpu(jsb->s_checksum);
78*6a54128fSAndroid Build Coastguard Worker calculated = ext2fs_journal_sb_csum(jsb);
79*6a54128fSAndroid Build Coastguard Worker
80*6a54128fSAndroid Build Coastguard Worker return provided == calculated;
81*6a54128fSAndroid Build Coastguard Worker }
82*6a54128fSAndroid Build Coastguard Worker
ext2fs_journal_sb_csum_set(journal_t * j,journal_superblock_t * jsb)83*6a54128fSAndroid Build Coastguard Worker static errcode_t ext2fs_journal_sb_csum_set(journal_t *j,
84*6a54128fSAndroid Build Coastguard Worker journal_superblock_t *jsb)
85*6a54128fSAndroid Build Coastguard Worker {
86*6a54128fSAndroid Build Coastguard Worker __u32 crc;
87*6a54128fSAndroid Build Coastguard Worker
88*6a54128fSAndroid Build Coastguard Worker if (!jbd2_journal_has_csum_v2or3(j))
89*6a54128fSAndroid Build Coastguard Worker return 0;
90*6a54128fSAndroid Build Coastguard Worker
91*6a54128fSAndroid Build Coastguard Worker crc = ext2fs_journal_sb_csum(jsb);
92*6a54128fSAndroid Build Coastguard Worker jsb->s_checksum = ext2fs_cpu_to_be32(crc);
93*6a54128fSAndroid Build Coastguard Worker return 0;
94*6a54128fSAndroid Build Coastguard Worker }
95*6a54128fSAndroid Build Coastguard Worker
96*6a54128fSAndroid Build Coastguard Worker /* Kernel compatibility functions for handling the journal. These allow us
97*6a54128fSAndroid Build Coastguard Worker * to use the recovery.c file virtually unchanged from the kernel, so we
98*6a54128fSAndroid Build Coastguard Worker * don't have to do much to keep kernel and user recovery in sync.
99*6a54128fSAndroid Build Coastguard Worker */
jbd2_journal_bmap(journal_t * journal,unsigned long block,unsigned long long * phys)100*6a54128fSAndroid Build Coastguard Worker int jbd2_journal_bmap(journal_t *journal, unsigned long block,
101*6a54128fSAndroid Build Coastguard Worker unsigned long long *phys)
102*6a54128fSAndroid Build Coastguard Worker {
103*6a54128fSAndroid Build Coastguard Worker #ifdef USE_INODE_IO
104*6a54128fSAndroid Build Coastguard Worker *phys = block;
105*6a54128fSAndroid Build Coastguard Worker return 0;
106*6a54128fSAndroid Build Coastguard Worker #else
107*6a54128fSAndroid Build Coastguard Worker struct inode *inode = journal->j_inode;
108*6a54128fSAndroid Build Coastguard Worker errcode_t retval;
109*6a54128fSAndroid Build Coastguard Worker blk64_t pblk;
110*6a54128fSAndroid Build Coastguard Worker
111*6a54128fSAndroid Build Coastguard Worker if (!inode) {
112*6a54128fSAndroid Build Coastguard Worker *phys = block;
113*6a54128fSAndroid Build Coastguard Worker return 0;
114*6a54128fSAndroid Build Coastguard Worker }
115*6a54128fSAndroid Build Coastguard Worker
116*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_bmap2(inode->i_fs, inode->i_ino,
117*6a54128fSAndroid Build Coastguard Worker &inode->i_ext2, NULL, 0, (blk64_t) block,
118*6a54128fSAndroid Build Coastguard Worker 0, &pblk);
119*6a54128fSAndroid Build Coastguard Worker *phys = pblk;
120*6a54128fSAndroid Build Coastguard Worker return (int) retval;
121*6a54128fSAndroid Build Coastguard Worker #endif
122*6a54128fSAndroid Build Coastguard Worker }
123*6a54128fSAndroid Build Coastguard Worker
getblk(kdev_t kdev,unsigned long long blocknr,int blocksize)124*6a54128fSAndroid Build Coastguard Worker struct buffer_head *getblk(kdev_t kdev, unsigned long long blocknr,
125*6a54128fSAndroid Build Coastguard Worker int blocksize)
126*6a54128fSAndroid Build Coastguard Worker {
127*6a54128fSAndroid Build Coastguard Worker struct buffer_head *bh;
128*6a54128fSAndroid Build Coastguard Worker int bufsize = sizeof(*bh) + kdev->k_fs->blocksize -
129*6a54128fSAndroid Build Coastguard Worker sizeof(bh->b_data);
130*6a54128fSAndroid Build Coastguard Worker errcode_t retval;
131*6a54128fSAndroid Build Coastguard Worker
132*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_get_memzero(bufsize, &bh);
133*6a54128fSAndroid Build Coastguard Worker if (retval)
134*6a54128fSAndroid Build Coastguard Worker return NULL;
135*6a54128fSAndroid Build Coastguard Worker
136*6a54128fSAndroid Build Coastguard Worker if (journal_enable_debug >= 3)
137*6a54128fSAndroid Build Coastguard Worker bh_count++;
138*6a54128fSAndroid Build Coastguard Worker jfs_debug(4, "getblk for block %llu (%d bytes)(total %d)\n",
139*6a54128fSAndroid Build Coastguard Worker blocknr, blocksize, bh_count);
140*6a54128fSAndroid Build Coastguard Worker
141*6a54128fSAndroid Build Coastguard Worker bh->b_fs = kdev->k_fs;
142*6a54128fSAndroid Build Coastguard Worker if (kdev->k_dev == K_DEV_FS)
143*6a54128fSAndroid Build Coastguard Worker bh->b_io = kdev->k_fs->io;
144*6a54128fSAndroid Build Coastguard Worker else
145*6a54128fSAndroid Build Coastguard Worker bh->b_io = kdev->k_fs->journal_io;
146*6a54128fSAndroid Build Coastguard Worker bh->b_size = blocksize;
147*6a54128fSAndroid Build Coastguard Worker bh->b_blocknr = blocknr;
148*6a54128fSAndroid Build Coastguard Worker
149*6a54128fSAndroid Build Coastguard Worker return bh;
150*6a54128fSAndroid Build Coastguard Worker }
151*6a54128fSAndroid Build Coastguard Worker
sync_blockdev(kdev_t kdev)152*6a54128fSAndroid Build Coastguard Worker int sync_blockdev(kdev_t kdev)
153*6a54128fSAndroid Build Coastguard Worker {
154*6a54128fSAndroid Build Coastguard Worker io_channel io;
155*6a54128fSAndroid Build Coastguard Worker
156*6a54128fSAndroid Build Coastguard Worker if (kdev->k_dev == K_DEV_FS)
157*6a54128fSAndroid Build Coastguard Worker io = kdev->k_fs->io;
158*6a54128fSAndroid Build Coastguard Worker else
159*6a54128fSAndroid Build Coastguard Worker io = kdev->k_fs->journal_io;
160*6a54128fSAndroid Build Coastguard Worker
161*6a54128fSAndroid Build Coastguard Worker return io_channel_flush(io) ? EIO : 0;
162*6a54128fSAndroid Build Coastguard Worker }
163*6a54128fSAndroid Build Coastguard Worker
ll_rw_block(int rw,int op_flags EXT2FS_ATTR ((unused)),int nr,struct buffer_head * bhp[])164*6a54128fSAndroid Build Coastguard Worker void ll_rw_block(int rw, int op_flags EXT2FS_ATTR((unused)), int nr,
165*6a54128fSAndroid Build Coastguard Worker struct buffer_head *bhp[])
166*6a54128fSAndroid Build Coastguard Worker {
167*6a54128fSAndroid Build Coastguard Worker errcode_t retval;
168*6a54128fSAndroid Build Coastguard Worker struct buffer_head *bh;
169*6a54128fSAndroid Build Coastguard Worker
170*6a54128fSAndroid Build Coastguard Worker for (; nr > 0; --nr) {
171*6a54128fSAndroid Build Coastguard Worker bh = *bhp++;
172*6a54128fSAndroid Build Coastguard Worker if (rw == REQ_OP_READ && !bh->b_uptodate) {
173*6a54128fSAndroid Build Coastguard Worker jfs_debug(3, "reading block %llu/%p\n",
174*6a54128fSAndroid Build Coastguard Worker bh->b_blocknr, (void *) bh);
175*6a54128fSAndroid Build Coastguard Worker retval = io_channel_read_blk64(bh->b_io,
176*6a54128fSAndroid Build Coastguard Worker bh->b_blocknr,
177*6a54128fSAndroid Build Coastguard Worker 1, bh->b_data);
178*6a54128fSAndroid Build Coastguard Worker if (retval) {
179*6a54128fSAndroid Build Coastguard Worker com_err(bh->b_fs->device_name, retval,
180*6a54128fSAndroid Build Coastguard Worker "while reading block %llu\n",
181*6a54128fSAndroid Build Coastguard Worker bh->b_blocknr);
182*6a54128fSAndroid Build Coastguard Worker bh->b_err = (int) retval;
183*6a54128fSAndroid Build Coastguard Worker continue;
184*6a54128fSAndroid Build Coastguard Worker }
185*6a54128fSAndroid Build Coastguard Worker bh->b_uptodate = 1;
186*6a54128fSAndroid Build Coastguard Worker } else if (rw == REQ_OP_WRITE && bh->b_dirty) {
187*6a54128fSAndroid Build Coastguard Worker jfs_debug(3, "writing block %llu/%p\n",
188*6a54128fSAndroid Build Coastguard Worker bh->b_blocknr,
189*6a54128fSAndroid Build Coastguard Worker (void *) bh);
190*6a54128fSAndroid Build Coastguard Worker retval = io_channel_write_blk64(bh->b_io,
191*6a54128fSAndroid Build Coastguard Worker bh->b_blocknr,
192*6a54128fSAndroid Build Coastguard Worker 1, bh->b_data);
193*6a54128fSAndroid Build Coastguard Worker if (retval) {
194*6a54128fSAndroid Build Coastguard Worker com_err(bh->b_fs->device_name, retval,
195*6a54128fSAndroid Build Coastguard Worker "while writing block %llu\n",
196*6a54128fSAndroid Build Coastguard Worker bh->b_blocknr);
197*6a54128fSAndroid Build Coastguard Worker bh->b_err = (int) retval;
198*6a54128fSAndroid Build Coastguard Worker continue;
199*6a54128fSAndroid Build Coastguard Worker }
200*6a54128fSAndroid Build Coastguard Worker bh->b_dirty = 0;
201*6a54128fSAndroid Build Coastguard Worker bh->b_uptodate = 1;
202*6a54128fSAndroid Build Coastguard Worker } else {
203*6a54128fSAndroid Build Coastguard Worker jfs_debug(3, "no-op %s for block %llu\n",
204*6a54128fSAndroid Build Coastguard Worker rw == REQ_OP_READ ? "read" : "write",
205*6a54128fSAndroid Build Coastguard Worker bh->b_blocknr);
206*6a54128fSAndroid Build Coastguard Worker }
207*6a54128fSAndroid Build Coastguard Worker }
208*6a54128fSAndroid Build Coastguard Worker }
209*6a54128fSAndroid Build Coastguard Worker
mark_buffer_dirty(struct buffer_head * bh)210*6a54128fSAndroid Build Coastguard Worker void mark_buffer_dirty(struct buffer_head *bh)
211*6a54128fSAndroid Build Coastguard Worker {
212*6a54128fSAndroid Build Coastguard Worker bh->b_dirty = 1;
213*6a54128fSAndroid Build Coastguard Worker }
214*6a54128fSAndroid Build Coastguard Worker
mark_buffer_clean(struct buffer_head * bh)215*6a54128fSAndroid Build Coastguard Worker static void mark_buffer_clean(struct buffer_head *bh)
216*6a54128fSAndroid Build Coastguard Worker {
217*6a54128fSAndroid Build Coastguard Worker bh->b_dirty = 0;
218*6a54128fSAndroid Build Coastguard Worker }
219*6a54128fSAndroid Build Coastguard Worker
brelse(struct buffer_head * bh)220*6a54128fSAndroid Build Coastguard Worker void brelse(struct buffer_head *bh)
221*6a54128fSAndroid Build Coastguard Worker {
222*6a54128fSAndroid Build Coastguard Worker if (bh->b_dirty)
223*6a54128fSAndroid Build Coastguard Worker ll_rw_block(REQ_OP_WRITE, 0, 1, &bh);
224*6a54128fSAndroid Build Coastguard Worker jfs_debug(3, "freeing block %llu/%p (total %d)\n",
225*6a54128fSAndroid Build Coastguard Worker bh->b_blocknr, (void *) bh, --bh_count);
226*6a54128fSAndroid Build Coastguard Worker ext2fs_free_mem(&bh);
227*6a54128fSAndroid Build Coastguard Worker }
228*6a54128fSAndroid Build Coastguard Worker
buffer_uptodate(struct buffer_head * bh)229*6a54128fSAndroid Build Coastguard Worker int buffer_uptodate(struct buffer_head *bh)
230*6a54128fSAndroid Build Coastguard Worker {
231*6a54128fSAndroid Build Coastguard Worker return bh->b_uptodate;
232*6a54128fSAndroid Build Coastguard Worker }
233*6a54128fSAndroid Build Coastguard Worker
mark_buffer_uptodate(struct buffer_head * bh,int val)234*6a54128fSAndroid Build Coastguard Worker void mark_buffer_uptodate(struct buffer_head *bh, int val)
235*6a54128fSAndroid Build Coastguard Worker {
236*6a54128fSAndroid Build Coastguard Worker bh->b_uptodate = val;
237*6a54128fSAndroid Build Coastguard Worker }
238*6a54128fSAndroid Build Coastguard Worker
wait_on_buffer(struct buffer_head * bh)239*6a54128fSAndroid Build Coastguard Worker void wait_on_buffer(struct buffer_head *bh)
240*6a54128fSAndroid Build Coastguard Worker {
241*6a54128fSAndroid Build Coastguard Worker if (!bh->b_uptodate)
242*6a54128fSAndroid Build Coastguard Worker ll_rw_block(REQ_OP_READ, 0, 1, &bh);
243*6a54128fSAndroid Build Coastguard Worker }
244*6a54128fSAndroid Build Coastguard Worker
245*6a54128fSAndroid Build Coastguard Worker
ext2fs_clear_recover(ext2_filsys fs,int error)246*6a54128fSAndroid Build Coastguard Worker static void ext2fs_clear_recover(ext2_filsys fs, int error)
247*6a54128fSAndroid Build Coastguard Worker {
248*6a54128fSAndroid Build Coastguard Worker ext2fs_clear_feature_journal_needs_recovery(fs->super);
249*6a54128fSAndroid Build Coastguard Worker
250*6a54128fSAndroid Build Coastguard Worker /* if we had an error doing journal recovery, we need a full fsck */
251*6a54128fSAndroid Build Coastguard Worker if (error)
252*6a54128fSAndroid Build Coastguard Worker fs->super->s_state &= ~EXT2_VALID_FS;
253*6a54128fSAndroid Build Coastguard Worker /*
254*6a54128fSAndroid Build Coastguard Worker * If we replayed the journal by definition the file system
255*6a54128fSAndroid Build Coastguard Worker * was mounted since the last time it was checked
256*6a54128fSAndroid Build Coastguard Worker */
257*6a54128fSAndroid Build Coastguard Worker if (fs->super->s_lastcheck >= fs->super->s_mtime)
258*6a54128fSAndroid Build Coastguard Worker fs->super->s_lastcheck = fs->super->s_mtime - 1;
259*6a54128fSAndroid Build Coastguard Worker ext2fs_mark_super_dirty(fs);
260*6a54128fSAndroid Build Coastguard Worker }
261*6a54128fSAndroid Build Coastguard Worker
262*6a54128fSAndroid Build Coastguard Worker /*
263*6a54128fSAndroid Build Coastguard Worker * This is a helper function to check the validity of the journal.
264*6a54128fSAndroid Build Coastguard Worker */
265*6a54128fSAndroid Build Coastguard Worker struct process_block_struct {
266*6a54128fSAndroid Build Coastguard Worker e2_blkcnt_t last_block;
267*6a54128fSAndroid Build Coastguard Worker };
268*6a54128fSAndroid Build Coastguard Worker
process_journal_block(ext2_filsys fs,blk64_t * block_nr,e2_blkcnt_t blockcnt,blk64_t ref_block EXT2FS_ATTR ((unused)),int ref_offset EXT2FS_ATTR ((unused)),void * priv_data)269*6a54128fSAndroid Build Coastguard Worker static int process_journal_block(ext2_filsys fs,
270*6a54128fSAndroid Build Coastguard Worker blk64_t *block_nr,
271*6a54128fSAndroid Build Coastguard Worker e2_blkcnt_t blockcnt,
272*6a54128fSAndroid Build Coastguard Worker blk64_t ref_block EXT2FS_ATTR((unused)),
273*6a54128fSAndroid Build Coastguard Worker int ref_offset EXT2FS_ATTR((unused)),
274*6a54128fSAndroid Build Coastguard Worker void *priv_data)
275*6a54128fSAndroid Build Coastguard Worker {
276*6a54128fSAndroid Build Coastguard Worker struct process_block_struct *p;
277*6a54128fSAndroid Build Coastguard Worker blk64_t blk = *block_nr;
278*6a54128fSAndroid Build Coastguard Worker
279*6a54128fSAndroid Build Coastguard Worker p = (struct process_block_struct *) priv_data;
280*6a54128fSAndroid Build Coastguard Worker
281*6a54128fSAndroid Build Coastguard Worker if (!blk || blk < fs->super->s_first_data_block ||
282*6a54128fSAndroid Build Coastguard Worker blk >= ext2fs_blocks_count(fs->super))
283*6a54128fSAndroid Build Coastguard Worker return BLOCK_ABORT;
284*6a54128fSAndroid Build Coastguard Worker
285*6a54128fSAndroid Build Coastguard Worker if (blockcnt >= 0)
286*6a54128fSAndroid Build Coastguard Worker p->last_block = blockcnt;
287*6a54128fSAndroid Build Coastguard Worker return 0;
288*6a54128fSAndroid Build Coastguard Worker }
289*6a54128fSAndroid Build Coastguard Worker
ext2fs_get_journal(ext2_filsys fs,journal_t ** ret_journal)290*6a54128fSAndroid Build Coastguard Worker static errcode_t ext2fs_get_journal(ext2_filsys fs, journal_t **ret_journal)
291*6a54128fSAndroid Build Coastguard Worker {
292*6a54128fSAndroid Build Coastguard Worker struct process_block_struct pb;
293*6a54128fSAndroid Build Coastguard Worker struct ext2_super_block *sb = fs->super;
294*6a54128fSAndroid Build Coastguard Worker struct ext2_super_block jsuper;
295*6a54128fSAndroid Build Coastguard Worker struct buffer_head *bh;
296*6a54128fSAndroid Build Coastguard Worker struct inode *j_inode = NULL;
297*6a54128fSAndroid Build Coastguard Worker struct kdev_s *dev_fs = NULL, *dev_journal;
298*6a54128fSAndroid Build Coastguard Worker const char *journal_name = 0;
299*6a54128fSAndroid Build Coastguard Worker journal_t *journal = NULL;
300*6a54128fSAndroid Build Coastguard Worker errcode_t retval = 0;
301*6a54128fSAndroid Build Coastguard Worker io_manager io_ptr = 0;
302*6a54128fSAndroid Build Coastguard Worker unsigned long long start = 0;
303*6a54128fSAndroid Build Coastguard Worker int ext_journal = 0;
304*6a54128fSAndroid Build Coastguard Worker int tried_backup_jnl = 0;
305*6a54128fSAndroid Build Coastguard Worker
306*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_get_memzero(sizeof(journal_t), &journal);
307*6a54128fSAndroid Build Coastguard Worker if (retval)
308*6a54128fSAndroid Build Coastguard Worker return retval;
309*6a54128fSAndroid Build Coastguard Worker
310*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_get_memzero(2 * sizeof(struct kdev_s), &dev_fs);
311*6a54128fSAndroid Build Coastguard Worker if (retval)
312*6a54128fSAndroid Build Coastguard Worker goto errout;
313*6a54128fSAndroid Build Coastguard Worker dev_journal = dev_fs+1;
314*6a54128fSAndroid Build Coastguard Worker
315*6a54128fSAndroid Build Coastguard Worker dev_fs->k_fs = dev_journal->k_fs = fs;
316*6a54128fSAndroid Build Coastguard Worker dev_fs->k_dev = K_DEV_FS;
317*6a54128fSAndroid Build Coastguard Worker dev_journal->k_dev = K_DEV_JOURNAL;
318*6a54128fSAndroid Build Coastguard Worker
319*6a54128fSAndroid Build Coastguard Worker journal->j_dev = dev_journal;
320*6a54128fSAndroid Build Coastguard Worker journal->j_fs_dev = dev_fs;
321*6a54128fSAndroid Build Coastguard Worker journal->j_inode = NULL;
322*6a54128fSAndroid Build Coastguard Worker journal->j_blocksize = fs->blocksize;
323*6a54128fSAndroid Build Coastguard Worker
324*6a54128fSAndroid Build Coastguard Worker if (uuid_is_null(sb->s_journal_uuid)) {
325*6a54128fSAndroid Build Coastguard Worker if (!sb->s_journal_inum) {
326*6a54128fSAndroid Build Coastguard Worker retval = EXT2_ET_BAD_INODE_NUM;
327*6a54128fSAndroid Build Coastguard Worker goto errout;
328*6a54128fSAndroid Build Coastguard Worker }
329*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_get_memzero(sizeof(*j_inode), &j_inode);
330*6a54128fSAndroid Build Coastguard Worker if (retval)
331*6a54128fSAndroid Build Coastguard Worker goto errout;
332*6a54128fSAndroid Build Coastguard Worker
333*6a54128fSAndroid Build Coastguard Worker j_inode->i_fs = fs;
334*6a54128fSAndroid Build Coastguard Worker j_inode->i_ino = sb->s_journal_inum;
335*6a54128fSAndroid Build Coastguard Worker
336*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_read_inode(fs, sb->s_journal_inum,
337*6a54128fSAndroid Build Coastguard Worker &j_inode->i_ext2);
338*6a54128fSAndroid Build Coastguard Worker if (retval) {
339*6a54128fSAndroid Build Coastguard Worker try_backup_journal:
340*6a54128fSAndroid Build Coastguard Worker if (sb->s_jnl_backup_type != EXT3_JNL_BACKUP_BLOCKS ||
341*6a54128fSAndroid Build Coastguard Worker tried_backup_jnl)
342*6a54128fSAndroid Build Coastguard Worker goto errout;
343*6a54128fSAndroid Build Coastguard Worker memset(&j_inode->i_ext2, 0, sizeof(struct ext2_inode));
344*6a54128fSAndroid Build Coastguard Worker memcpy(&j_inode->i_ext2.i_block[0], sb->s_jnl_blocks,
345*6a54128fSAndroid Build Coastguard Worker EXT2_N_BLOCKS*4);
346*6a54128fSAndroid Build Coastguard Worker j_inode->i_ext2.i_size_high = sb->s_jnl_blocks[15];
347*6a54128fSAndroid Build Coastguard Worker j_inode->i_ext2.i_size = sb->s_jnl_blocks[16];
348*6a54128fSAndroid Build Coastguard Worker j_inode->i_ext2.i_links_count = 1;
349*6a54128fSAndroid Build Coastguard Worker j_inode->i_ext2.i_mode = LINUX_S_IFREG | 0600;
350*6a54128fSAndroid Build Coastguard Worker tried_backup_jnl++;
351*6a54128fSAndroid Build Coastguard Worker }
352*6a54128fSAndroid Build Coastguard Worker if (!j_inode->i_ext2.i_links_count ||
353*6a54128fSAndroid Build Coastguard Worker !LINUX_S_ISREG(j_inode->i_ext2.i_mode)) {
354*6a54128fSAndroid Build Coastguard Worker retval = EXT2_ET_NO_JOURNAL;
355*6a54128fSAndroid Build Coastguard Worker goto try_backup_journal;
356*6a54128fSAndroid Build Coastguard Worker }
357*6a54128fSAndroid Build Coastguard Worker if (EXT2_I_SIZE(&j_inode->i_ext2) / journal->j_blocksize <
358*6a54128fSAndroid Build Coastguard Worker JBD2_MIN_JOURNAL_BLOCKS) {
359*6a54128fSAndroid Build Coastguard Worker retval = EXT2_ET_JOURNAL_TOO_SMALL;
360*6a54128fSAndroid Build Coastguard Worker goto try_backup_journal;
361*6a54128fSAndroid Build Coastguard Worker }
362*6a54128fSAndroid Build Coastguard Worker pb.last_block = -1;
363*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_block_iterate3(fs, j_inode->i_ino,
364*6a54128fSAndroid Build Coastguard Worker BLOCK_FLAG_HOLE, 0,
365*6a54128fSAndroid Build Coastguard Worker process_journal_block, &pb);
366*6a54128fSAndroid Build Coastguard Worker if ((pb.last_block + 1) * fs->blocksize <
367*6a54128fSAndroid Build Coastguard Worker (int) EXT2_I_SIZE(&j_inode->i_ext2)) {
368*6a54128fSAndroid Build Coastguard Worker retval = EXT2_ET_JOURNAL_TOO_SMALL;
369*6a54128fSAndroid Build Coastguard Worker goto try_backup_journal;
370*6a54128fSAndroid Build Coastguard Worker }
371*6a54128fSAndroid Build Coastguard Worker if (tried_backup_jnl && (fs->flags & EXT2_FLAG_RW)) {
372*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_write_inode(fs, sb->s_journal_inum,
373*6a54128fSAndroid Build Coastguard Worker &j_inode->i_ext2);
374*6a54128fSAndroid Build Coastguard Worker if (retval)
375*6a54128fSAndroid Build Coastguard Worker goto errout;
376*6a54128fSAndroid Build Coastguard Worker }
377*6a54128fSAndroid Build Coastguard Worker
378*6a54128fSAndroid Build Coastguard Worker journal->j_total_len = EXT2_I_SIZE(&j_inode->i_ext2) /
379*6a54128fSAndroid Build Coastguard Worker journal->j_blocksize;
380*6a54128fSAndroid Build Coastguard Worker
381*6a54128fSAndroid Build Coastguard Worker #ifdef USE_INODE_IO
382*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_inode_io_intern2(fs, sb->s_journal_inum,
383*6a54128fSAndroid Build Coastguard Worker &j_inode->i_ext2,
384*6a54128fSAndroid Build Coastguard Worker &journal_name);
385*6a54128fSAndroid Build Coastguard Worker if (retval)
386*6a54128fSAndroid Build Coastguard Worker goto errout;
387*6a54128fSAndroid Build Coastguard Worker
388*6a54128fSAndroid Build Coastguard Worker io_ptr = inode_io_manager;
389*6a54128fSAndroid Build Coastguard Worker #else
390*6a54128fSAndroid Build Coastguard Worker journal->j_inode = j_inode;
391*6a54128fSAndroid Build Coastguard Worker fs->journal_io = fs->io;
392*6a54128fSAndroid Build Coastguard Worker retval = (errcode_t) jbd2_journal_bmap(journal, 0, &start);
393*6a54128fSAndroid Build Coastguard Worker if (retval)
394*6a54128fSAndroid Build Coastguard Worker goto errout;
395*6a54128fSAndroid Build Coastguard Worker #endif
396*6a54128fSAndroid Build Coastguard Worker } else {
397*6a54128fSAndroid Build Coastguard Worker ext_journal = 1;
398*6a54128fSAndroid Build Coastguard Worker if (!fs->journal_name) {
399*6a54128fSAndroid Build Coastguard Worker char uuid[37];
400*6a54128fSAndroid Build Coastguard Worker blkid_cache blkid;
401*6a54128fSAndroid Build Coastguard Worker
402*6a54128fSAndroid Build Coastguard Worker blkid_get_cache(&blkid, NULL);
403*6a54128fSAndroid Build Coastguard Worker uuid_unparse(sb->s_journal_uuid, uuid);
404*6a54128fSAndroid Build Coastguard Worker fs->journal_name = blkid_get_devname(blkid,
405*6a54128fSAndroid Build Coastguard Worker "UUID", uuid);
406*6a54128fSAndroid Build Coastguard Worker if (!fs->journal_name)
407*6a54128fSAndroid Build Coastguard Worker fs->journal_name = blkid_devno_to_devname(sb->s_journal_dev);
408*6a54128fSAndroid Build Coastguard Worker blkid_put_cache(blkid);
409*6a54128fSAndroid Build Coastguard Worker }
410*6a54128fSAndroid Build Coastguard Worker journal_name = fs->journal_name;
411*6a54128fSAndroid Build Coastguard Worker
412*6a54128fSAndroid Build Coastguard Worker if (!journal_name) {
413*6a54128fSAndroid Build Coastguard Worker retval = EXT2_ET_LOAD_EXT_JOURNAL;
414*6a54128fSAndroid Build Coastguard Worker goto errout;
415*6a54128fSAndroid Build Coastguard Worker }
416*6a54128fSAndroid Build Coastguard Worker
417*6a54128fSAndroid Build Coastguard Worker jfs_debug(1, "Using journal file %s\n", journal_name);
418*6a54128fSAndroid Build Coastguard Worker io_ptr = unix_io_manager;
419*6a54128fSAndroid Build Coastguard Worker }
420*6a54128fSAndroid Build Coastguard Worker
421*6a54128fSAndroid Build Coastguard Worker #if 0
422*6a54128fSAndroid Build Coastguard Worker test_io_backing_manager = io_ptr;
423*6a54128fSAndroid Build Coastguard Worker io_ptr = test_io_manager;
424*6a54128fSAndroid Build Coastguard Worker #endif
425*6a54128fSAndroid Build Coastguard Worker #ifndef USE_INODE_IO
426*6a54128fSAndroid Build Coastguard Worker if (ext_journal)
427*6a54128fSAndroid Build Coastguard Worker #endif
428*6a54128fSAndroid Build Coastguard Worker {
429*6a54128fSAndroid Build Coastguard Worker retval = io_ptr->open(journal_name, fs->flags & EXT2_FLAG_RW,
430*6a54128fSAndroid Build Coastguard Worker &fs->journal_io);
431*6a54128fSAndroid Build Coastguard Worker }
432*6a54128fSAndroid Build Coastguard Worker if (retval)
433*6a54128fSAndroid Build Coastguard Worker goto errout;
434*6a54128fSAndroid Build Coastguard Worker
435*6a54128fSAndroid Build Coastguard Worker io_channel_set_blksize(fs->journal_io, fs->blocksize);
436*6a54128fSAndroid Build Coastguard Worker
437*6a54128fSAndroid Build Coastguard Worker if (ext_journal) {
438*6a54128fSAndroid Build Coastguard Worker blk64_t maxlen;
439*6a54128fSAndroid Build Coastguard Worker
440*6a54128fSAndroid Build Coastguard Worker start = ext2fs_journal_sb_start(fs->blocksize) - 1;
441*6a54128fSAndroid Build Coastguard Worker bh = getblk(dev_journal, start, fs->blocksize);
442*6a54128fSAndroid Build Coastguard Worker if (!bh) {
443*6a54128fSAndroid Build Coastguard Worker retval = EXT2_ET_NO_MEMORY;
444*6a54128fSAndroid Build Coastguard Worker goto errout;
445*6a54128fSAndroid Build Coastguard Worker }
446*6a54128fSAndroid Build Coastguard Worker ll_rw_block(REQ_OP_READ, 0, 1, &bh);
447*6a54128fSAndroid Build Coastguard Worker retval = bh->b_err;
448*6a54128fSAndroid Build Coastguard Worker if (retval) {
449*6a54128fSAndroid Build Coastguard Worker brelse(bh);
450*6a54128fSAndroid Build Coastguard Worker goto errout;
451*6a54128fSAndroid Build Coastguard Worker }
452*6a54128fSAndroid Build Coastguard Worker memcpy(&jsuper, start ? bh->b_data :
453*6a54128fSAndroid Build Coastguard Worker bh->b_data + SUPERBLOCK_OFFSET,
454*6a54128fSAndroid Build Coastguard Worker sizeof(jsuper));
455*6a54128fSAndroid Build Coastguard Worker #ifdef WORDS_BIGENDIAN
456*6a54128fSAndroid Build Coastguard Worker if (jsuper.s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
457*6a54128fSAndroid Build Coastguard Worker ext2fs_swap_super(&jsuper);
458*6a54128fSAndroid Build Coastguard Worker #endif
459*6a54128fSAndroid Build Coastguard Worker if (jsuper.s_magic != EXT2_SUPER_MAGIC ||
460*6a54128fSAndroid Build Coastguard Worker !ext2fs_has_feature_journal_dev(&jsuper)) {
461*6a54128fSAndroid Build Coastguard Worker retval = EXT2_ET_LOAD_EXT_JOURNAL;
462*6a54128fSAndroid Build Coastguard Worker brelse(bh);
463*6a54128fSAndroid Build Coastguard Worker goto errout;
464*6a54128fSAndroid Build Coastguard Worker }
465*6a54128fSAndroid Build Coastguard Worker /* Make sure the journal UUID is correct */
466*6a54128fSAndroid Build Coastguard Worker if (memcmp(jsuper.s_uuid, fs->super->s_journal_uuid,
467*6a54128fSAndroid Build Coastguard Worker sizeof(jsuper.s_uuid))) {
468*6a54128fSAndroid Build Coastguard Worker retval = EXT2_ET_LOAD_EXT_JOURNAL;
469*6a54128fSAndroid Build Coastguard Worker brelse(bh);
470*6a54128fSAndroid Build Coastguard Worker goto errout;
471*6a54128fSAndroid Build Coastguard Worker }
472*6a54128fSAndroid Build Coastguard Worker
473*6a54128fSAndroid Build Coastguard Worker /* Check the superblock checksum */
474*6a54128fSAndroid Build Coastguard Worker if (ext2fs_has_feature_metadata_csum(&jsuper)) {
475*6a54128fSAndroid Build Coastguard Worker struct struct_ext2_filsys fsx;
476*6a54128fSAndroid Build Coastguard Worker struct ext2_super_block superx;
477*6a54128fSAndroid Build Coastguard Worker void *p;
478*6a54128fSAndroid Build Coastguard Worker
479*6a54128fSAndroid Build Coastguard Worker p = start ? bh->b_data : bh->b_data + SUPERBLOCK_OFFSET;
480*6a54128fSAndroid Build Coastguard Worker memcpy(&fsx, fs, sizeof(fsx));
481*6a54128fSAndroid Build Coastguard Worker memcpy(&superx, fs->super, sizeof(superx));
482*6a54128fSAndroid Build Coastguard Worker fsx.super = &superx;
483*6a54128fSAndroid Build Coastguard Worker ext2fs_set_feature_metadata_csum(fsx.super);
484*6a54128fSAndroid Build Coastguard Worker if (!ext2fs_superblock_csum_verify(&fsx, p)) {
485*6a54128fSAndroid Build Coastguard Worker retval = EXT2_ET_LOAD_EXT_JOURNAL;
486*6a54128fSAndroid Build Coastguard Worker brelse(bh);
487*6a54128fSAndroid Build Coastguard Worker goto errout;
488*6a54128fSAndroid Build Coastguard Worker }
489*6a54128fSAndroid Build Coastguard Worker }
490*6a54128fSAndroid Build Coastguard Worker brelse(bh);
491*6a54128fSAndroid Build Coastguard Worker
492*6a54128fSAndroid Build Coastguard Worker maxlen = ext2fs_blocks_count(&jsuper);
493*6a54128fSAndroid Build Coastguard Worker journal->j_total_len = (maxlen < 1ULL << 32) ? maxlen :
494*6a54128fSAndroid Build Coastguard Worker (1ULL << 32) - 1;
495*6a54128fSAndroid Build Coastguard Worker start++;
496*6a54128fSAndroid Build Coastguard Worker }
497*6a54128fSAndroid Build Coastguard Worker
498*6a54128fSAndroid Build Coastguard Worker bh = getblk(dev_journal, start, journal->j_blocksize);
499*6a54128fSAndroid Build Coastguard Worker if (!bh) {
500*6a54128fSAndroid Build Coastguard Worker retval = EXT2_ET_NO_MEMORY;
501*6a54128fSAndroid Build Coastguard Worker goto errout;
502*6a54128fSAndroid Build Coastguard Worker }
503*6a54128fSAndroid Build Coastguard Worker
504*6a54128fSAndroid Build Coastguard Worker journal->j_sb_buffer = bh;
505*6a54128fSAndroid Build Coastguard Worker journal->j_superblock = (journal_superblock_t *)bh->b_data;
506*6a54128fSAndroid Build Coastguard Worker
507*6a54128fSAndroid Build Coastguard Worker #ifdef USE_INODE_IO
508*6a54128fSAndroid Build Coastguard Worker if (j_inode)
509*6a54128fSAndroid Build Coastguard Worker ext2fs_free_mem(&j_inode);
510*6a54128fSAndroid Build Coastguard Worker #endif
511*6a54128fSAndroid Build Coastguard Worker
512*6a54128fSAndroid Build Coastguard Worker *ret_journal = journal;
513*6a54128fSAndroid Build Coastguard Worker return 0;
514*6a54128fSAndroid Build Coastguard Worker
515*6a54128fSAndroid Build Coastguard Worker errout:
516*6a54128fSAndroid Build Coastguard Worker if (dev_fs)
517*6a54128fSAndroid Build Coastguard Worker ext2fs_free_mem(&dev_fs);
518*6a54128fSAndroid Build Coastguard Worker if (j_inode)
519*6a54128fSAndroid Build Coastguard Worker ext2fs_free_mem(&j_inode);
520*6a54128fSAndroid Build Coastguard Worker if (journal)
521*6a54128fSAndroid Build Coastguard Worker ext2fs_free_mem(&journal);
522*6a54128fSAndroid Build Coastguard Worker return retval;
523*6a54128fSAndroid Build Coastguard Worker }
524*6a54128fSAndroid Build Coastguard Worker
ext2fs_journal_fix_bad_inode(ext2_filsys fs)525*6a54128fSAndroid Build Coastguard Worker static errcode_t ext2fs_journal_fix_bad_inode(ext2_filsys fs)
526*6a54128fSAndroid Build Coastguard Worker {
527*6a54128fSAndroid Build Coastguard Worker struct ext2_super_block *sb = fs->super;
528*6a54128fSAndroid Build Coastguard Worker int recover = ext2fs_has_feature_journal_needs_recovery(fs->super);
529*6a54128fSAndroid Build Coastguard Worker int has_journal = ext2fs_has_feature_journal(fs->super);
530*6a54128fSAndroid Build Coastguard Worker
531*6a54128fSAndroid Build Coastguard Worker if (has_journal || sb->s_journal_inum) {
532*6a54128fSAndroid Build Coastguard Worker /* The journal inode is bogus, remove and force full fsck */
533*6a54128fSAndroid Build Coastguard Worker return EXT2_ET_BAD_INODE_NUM;
534*6a54128fSAndroid Build Coastguard Worker } else if (recover) {
535*6a54128fSAndroid Build Coastguard Worker return EXT2_ET_UNSUPP_FEATURE;
536*6a54128fSAndroid Build Coastguard Worker }
537*6a54128fSAndroid Build Coastguard Worker return 0;
538*6a54128fSAndroid Build Coastguard Worker }
539*6a54128fSAndroid Build Coastguard Worker
540*6a54128fSAndroid Build Coastguard Worker #define V1_SB_SIZE 0x0024
clear_v2_journal_fields(journal_t * journal)541*6a54128fSAndroid Build Coastguard Worker static void clear_v2_journal_fields(journal_t *journal)
542*6a54128fSAndroid Build Coastguard Worker {
543*6a54128fSAndroid Build Coastguard Worker ext2_filsys fs = journal->j_dev->k_fs;
544*6a54128fSAndroid Build Coastguard Worker
545*6a54128fSAndroid Build Coastguard Worker memset(((char *) journal->j_superblock) + V1_SB_SIZE, 0,
546*6a54128fSAndroid Build Coastguard Worker fs->blocksize-V1_SB_SIZE);
547*6a54128fSAndroid Build Coastguard Worker mark_buffer_dirty(journal->j_sb_buffer);
548*6a54128fSAndroid Build Coastguard Worker }
549*6a54128fSAndroid Build Coastguard Worker
550*6a54128fSAndroid Build Coastguard Worker
ext2fs_journal_load(journal_t * journal)551*6a54128fSAndroid Build Coastguard Worker static errcode_t ext2fs_journal_load(journal_t *journal)
552*6a54128fSAndroid Build Coastguard Worker {
553*6a54128fSAndroid Build Coastguard Worker ext2_filsys fs = journal->j_dev->k_fs;
554*6a54128fSAndroid Build Coastguard Worker journal_superblock_t *jsb;
555*6a54128fSAndroid Build Coastguard Worker struct buffer_head *jbh = journal->j_sb_buffer;
556*6a54128fSAndroid Build Coastguard Worker
557*6a54128fSAndroid Build Coastguard Worker ll_rw_block(REQ_OP_READ, 0, 1, &jbh);
558*6a54128fSAndroid Build Coastguard Worker if (jbh->b_err)
559*6a54128fSAndroid Build Coastguard Worker return jbh->b_err;
560*6a54128fSAndroid Build Coastguard Worker
561*6a54128fSAndroid Build Coastguard Worker jsb = journal->j_superblock;
562*6a54128fSAndroid Build Coastguard Worker /* If we don't even have JBD2_MAGIC, we probably have a wrong inode */
563*6a54128fSAndroid Build Coastguard Worker if (jsb->s_header.h_magic != htonl(JBD2_MAGIC_NUMBER))
564*6a54128fSAndroid Build Coastguard Worker return ext2fs_journal_fix_bad_inode(fs);
565*6a54128fSAndroid Build Coastguard Worker
566*6a54128fSAndroid Build Coastguard Worker switch (ntohl(jsb->s_header.h_blocktype)) {
567*6a54128fSAndroid Build Coastguard Worker case JBD2_SUPERBLOCK_V1:
568*6a54128fSAndroid Build Coastguard Worker journal->j_format_version = 1;
569*6a54128fSAndroid Build Coastguard Worker if (jsb->s_feature_compat ||
570*6a54128fSAndroid Build Coastguard Worker jsb->s_feature_incompat ||
571*6a54128fSAndroid Build Coastguard Worker jsb->s_feature_ro_compat ||
572*6a54128fSAndroid Build Coastguard Worker jsb->s_nr_users)
573*6a54128fSAndroid Build Coastguard Worker clear_v2_journal_fields(journal);
574*6a54128fSAndroid Build Coastguard Worker break;
575*6a54128fSAndroid Build Coastguard Worker
576*6a54128fSAndroid Build Coastguard Worker case JBD2_SUPERBLOCK_V2:
577*6a54128fSAndroid Build Coastguard Worker journal->j_format_version = 2;
578*6a54128fSAndroid Build Coastguard Worker if (ntohl(jsb->s_nr_users) > 1 &&
579*6a54128fSAndroid Build Coastguard Worker uuid_is_null(fs->super->s_journal_uuid))
580*6a54128fSAndroid Build Coastguard Worker clear_v2_journal_fields(journal);
581*6a54128fSAndroid Build Coastguard Worker if (ntohl(jsb->s_nr_users) > 1)
582*6a54128fSAndroid Build Coastguard Worker return EXT2_ET_JOURNAL_UNSUPP_VERSION;
583*6a54128fSAndroid Build Coastguard Worker break;
584*6a54128fSAndroid Build Coastguard Worker
585*6a54128fSAndroid Build Coastguard Worker /*
586*6a54128fSAndroid Build Coastguard Worker * These should never appear in a journal super block, so if
587*6a54128fSAndroid Build Coastguard Worker * they do, the journal is badly corrupted.
588*6a54128fSAndroid Build Coastguard Worker */
589*6a54128fSAndroid Build Coastguard Worker case JBD2_DESCRIPTOR_BLOCK:
590*6a54128fSAndroid Build Coastguard Worker case JBD2_COMMIT_BLOCK:
591*6a54128fSAndroid Build Coastguard Worker case JBD2_REVOKE_BLOCK:
592*6a54128fSAndroid Build Coastguard Worker return EXT2_ET_CORRUPT_JOURNAL_SB;
593*6a54128fSAndroid Build Coastguard Worker
594*6a54128fSAndroid Build Coastguard Worker /* If we don't understand the superblock major type, but there
595*6a54128fSAndroid Build Coastguard Worker * is a magic number, then it is likely to be a new format we
596*6a54128fSAndroid Build Coastguard Worker * just don't understand, so leave it alone. */
597*6a54128fSAndroid Build Coastguard Worker default:
598*6a54128fSAndroid Build Coastguard Worker return EXT2_ET_JOURNAL_UNSUPP_VERSION;
599*6a54128fSAndroid Build Coastguard Worker }
600*6a54128fSAndroid Build Coastguard Worker
601*6a54128fSAndroid Build Coastguard Worker if (JBD2_HAS_INCOMPAT_FEATURE(journal, ~JBD2_KNOWN_INCOMPAT_FEATURES))
602*6a54128fSAndroid Build Coastguard Worker return EXT2_ET_UNSUPP_FEATURE;
603*6a54128fSAndroid Build Coastguard Worker
604*6a54128fSAndroid Build Coastguard Worker if (JBD2_HAS_RO_COMPAT_FEATURE(journal, ~JBD2_KNOWN_ROCOMPAT_FEATURES))
605*6a54128fSAndroid Build Coastguard Worker return EXT2_ET_RO_UNSUPP_FEATURE;
606*6a54128fSAndroid Build Coastguard Worker
607*6a54128fSAndroid Build Coastguard Worker /* Checksum v1-3 are mutually exclusive features. */
608*6a54128fSAndroid Build Coastguard Worker if (jbd2_has_feature_csum2(journal) && jbd2_has_feature_csum3(journal))
609*6a54128fSAndroid Build Coastguard Worker return EXT2_ET_CORRUPT_JOURNAL_SB;
610*6a54128fSAndroid Build Coastguard Worker
611*6a54128fSAndroid Build Coastguard Worker if (jbd2_journal_has_csum_v2or3(journal) &&
612*6a54128fSAndroid Build Coastguard Worker jbd2_has_feature_checksum(journal))
613*6a54128fSAndroid Build Coastguard Worker return EXT2_ET_CORRUPT_JOURNAL_SB;
614*6a54128fSAndroid Build Coastguard Worker
615*6a54128fSAndroid Build Coastguard Worker if (!ext2fs_journal_verify_csum_type(journal, jsb) ||
616*6a54128fSAndroid Build Coastguard Worker !ext2fs_journal_sb_csum_verify(journal, jsb))
617*6a54128fSAndroid Build Coastguard Worker return EXT2_ET_CORRUPT_JOURNAL_SB;
618*6a54128fSAndroid Build Coastguard Worker
619*6a54128fSAndroid Build Coastguard Worker if (jbd2_journal_has_csum_v2or3(journal))
620*6a54128fSAndroid Build Coastguard Worker journal->j_csum_seed = jbd2_chksum(journal, ~0, jsb->s_uuid,
621*6a54128fSAndroid Build Coastguard Worker sizeof(jsb->s_uuid));
622*6a54128fSAndroid Build Coastguard Worker
623*6a54128fSAndroid Build Coastguard Worker /* We have now checked whether we know enough about the journal
624*6a54128fSAndroid Build Coastguard Worker * format to be able to proceed safely, so any other checks that
625*6a54128fSAndroid Build Coastguard Worker * fail we should attempt to recover from. */
626*6a54128fSAndroid Build Coastguard Worker if (jsb->s_blocksize != htonl(journal->j_blocksize))
627*6a54128fSAndroid Build Coastguard Worker return EXT2_ET_CORRUPT_JOURNAL_SB;
628*6a54128fSAndroid Build Coastguard Worker
629*6a54128fSAndroid Build Coastguard Worker if (ntohl(jsb->s_maxlen) < journal->j_total_len)
630*6a54128fSAndroid Build Coastguard Worker journal->j_total_len = ntohl(jsb->s_maxlen);
631*6a54128fSAndroid Build Coastguard Worker else if (ntohl(jsb->s_maxlen) > journal->j_total_len)
632*6a54128fSAndroid Build Coastguard Worker return EXT2_ET_CORRUPT_JOURNAL_SB;
633*6a54128fSAndroid Build Coastguard Worker
634*6a54128fSAndroid Build Coastguard Worker journal->j_tail_sequence = ntohl(jsb->s_sequence);
635*6a54128fSAndroid Build Coastguard Worker journal->j_transaction_sequence = journal->j_tail_sequence;
636*6a54128fSAndroid Build Coastguard Worker journal->j_tail = ntohl(jsb->s_start);
637*6a54128fSAndroid Build Coastguard Worker journal->j_first = ntohl(jsb->s_first);
638*6a54128fSAndroid Build Coastguard Worker journal->j_last = ntohl(jsb->s_maxlen);
639*6a54128fSAndroid Build Coastguard Worker
640*6a54128fSAndroid Build Coastguard Worker return 0;
641*6a54128fSAndroid Build Coastguard Worker }
642*6a54128fSAndroid Build Coastguard Worker
ext2fs_journal_release(ext2_filsys fs,journal_t * journal,int reset,int drop)643*6a54128fSAndroid Build Coastguard Worker static void ext2fs_journal_release(ext2_filsys fs, journal_t *journal,
644*6a54128fSAndroid Build Coastguard Worker int reset, int drop)
645*6a54128fSAndroid Build Coastguard Worker {
646*6a54128fSAndroid Build Coastguard Worker journal_superblock_t *jsb;
647*6a54128fSAndroid Build Coastguard Worker
648*6a54128fSAndroid Build Coastguard Worker if (drop)
649*6a54128fSAndroid Build Coastguard Worker mark_buffer_clean(journal->j_sb_buffer);
650*6a54128fSAndroid Build Coastguard Worker else if (fs->flags & EXT2_FLAG_RW) {
651*6a54128fSAndroid Build Coastguard Worker jsb = journal->j_superblock;
652*6a54128fSAndroid Build Coastguard Worker jsb->s_sequence = htonl(journal->j_tail_sequence);
653*6a54128fSAndroid Build Coastguard Worker if (reset)
654*6a54128fSAndroid Build Coastguard Worker jsb->s_start = 0; /* this marks the journal as empty */
655*6a54128fSAndroid Build Coastguard Worker ext2fs_journal_sb_csum_set(journal, jsb);
656*6a54128fSAndroid Build Coastguard Worker mark_buffer_dirty(journal->j_sb_buffer);
657*6a54128fSAndroid Build Coastguard Worker }
658*6a54128fSAndroid Build Coastguard Worker brelse(journal->j_sb_buffer);
659*6a54128fSAndroid Build Coastguard Worker
660*6a54128fSAndroid Build Coastguard Worker if (fs && fs->journal_io) {
661*6a54128fSAndroid Build Coastguard Worker if (fs->io != fs->journal_io)
662*6a54128fSAndroid Build Coastguard Worker io_channel_close(fs->journal_io);
663*6a54128fSAndroid Build Coastguard Worker fs->journal_io = NULL;
664*6a54128fSAndroid Build Coastguard Worker free(fs->journal_name);
665*6a54128fSAndroid Build Coastguard Worker fs->journal_name = NULL;
666*6a54128fSAndroid Build Coastguard Worker }
667*6a54128fSAndroid Build Coastguard Worker
668*6a54128fSAndroid Build Coastguard Worker #ifndef USE_INODE_IO
669*6a54128fSAndroid Build Coastguard Worker if (journal->j_inode)
670*6a54128fSAndroid Build Coastguard Worker ext2fs_free_mem(&journal->j_inode);
671*6a54128fSAndroid Build Coastguard Worker #endif
672*6a54128fSAndroid Build Coastguard Worker if (journal->j_fs_dev)
673*6a54128fSAndroid Build Coastguard Worker ext2fs_free_mem(&journal->j_fs_dev);
674*6a54128fSAndroid Build Coastguard Worker ext2fs_free_mem(&journal);
675*6a54128fSAndroid Build Coastguard Worker }
676*6a54128fSAndroid Build Coastguard Worker
677*6a54128fSAndroid Build Coastguard Worker /*
678*6a54128fSAndroid Build Coastguard Worker * This function makes sure that the superblock fields regarding the
679*6a54128fSAndroid Build Coastguard Worker * journal are consistent.
680*6a54128fSAndroid Build Coastguard Worker */
ext2fs_check_ext3_journal(ext2_filsys fs)681*6a54128fSAndroid Build Coastguard Worker static errcode_t ext2fs_check_ext3_journal(ext2_filsys fs)
682*6a54128fSAndroid Build Coastguard Worker {
683*6a54128fSAndroid Build Coastguard Worker struct ext2_super_block *sb = fs->super;
684*6a54128fSAndroid Build Coastguard Worker journal_t *journal;
685*6a54128fSAndroid Build Coastguard Worker int recover = ext2fs_has_feature_journal_needs_recovery(fs->super);
686*6a54128fSAndroid Build Coastguard Worker errcode_t retval;
687*6a54128fSAndroid Build Coastguard Worker
688*6a54128fSAndroid Build Coastguard Worker /* If we don't have any journal features, don't do anything more */
689*6a54128fSAndroid Build Coastguard Worker if (!ext2fs_has_feature_journal(sb) &&
690*6a54128fSAndroid Build Coastguard Worker !recover && sb->s_journal_inum == 0 && sb->s_journal_dev == 0 &&
691*6a54128fSAndroid Build Coastguard Worker uuid_is_null(sb->s_journal_uuid))
692*6a54128fSAndroid Build Coastguard Worker return 0;
693*6a54128fSAndroid Build Coastguard Worker
694*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_get_journal(fs, &journal);
695*6a54128fSAndroid Build Coastguard Worker if (retval)
696*6a54128fSAndroid Build Coastguard Worker return retval;
697*6a54128fSAndroid Build Coastguard Worker
698*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_journal_load(journal);
699*6a54128fSAndroid Build Coastguard Worker if (retval)
700*6a54128fSAndroid Build Coastguard Worker goto err;
701*6a54128fSAndroid Build Coastguard Worker
702*6a54128fSAndroid Build Coastguard Worker /*
703*6a54128fSAndroid Build Coastguard Worker * We want to make the flags consistent here. We will not leave with
704*6a54128fSAndroid Build Coastguard Worker * needs_recovery set but has_journal clear. We can't get in a loop
705*6a54128fSAndroid Build Coastguard Worker * with -y, -n, or -p, only if a user isn't making up their mind.
706*6a54128fSAndroid Build Coastguard Worker */
707*6a54128fSAndroid Build Coastguard Worker if (!ext2fs_has_feature_journal(sb)) {
708*6a54128fSAndroid Build Coastguard Worker retval = EXT2_ET_JOURNAL_FLAGS_WRONG;
709*6a54128fSAndroid Build Coastguard Worker goto err;
710*6a54128fSAndroid Build Coastguard Worker }
711*6a54128fSAndroid Build Coastguard Worker
712*6a54128fSAndroid Build Coastguard Worker if (ext2fs_has_feature_journal(sb) &&
713*6a54128fSAndroid Build Coastguard Worker !ext2fs_has_feature_journal_needs_recovery(sb) &&
714*6a54128fSAndroid Build Coastguard Worker journal->j_superblock->s_start != 0) {
715*6a54128fSAndroid Build Coastguard Worker retval = EXT2_ET_JOURNAL_FLAGS_WRONG;
716*6a54128fSAndroid Build Coastguard Worker goto err;
717*6a54128fSAndroid Build Coastguard Worker }
718*6a54128fSAndroid Build Coastguard Worker
719*6a54128fSAndroid Build Coastguard Worker /*
720*6a54128fSAndroid Build Coastguard Worker * If we don't need to do replay the journal, check to see if
721*6a54128fSAndroid Build Coastguard Worker * the journal's errno is set; if so, we need to mark the file
722*6a54128fSAndroid Build Coastguard Worker * system as being corrupt and clear the journal's s_errno.
723*6a54128fSAndroid Build Coastguard Worker */
724*6a54128fSAndroid Build Coastguard Worker if (!ext2fs_has_feature_journal_needs_recovery(sb) &&
725*6a54128fSAndroid Build Coastguard Worker journal->j_superblock->s_errno) {
726*6a54128fSAndroid Build Coastguard Worker fs->super->s_state |= EXT2_ERROR_FS;
727*6a54128fSAndroid Build Coastguard Worker ext2fs_mark_super_dirty(fs);
728*6a54128fSAndroid Build Coastguard Worker journal->j_superblock->s_errno = 0;
729*6a54128fSAndroid Build Coastguard Worker ext2fs_journal_sb_csum_set(journal, journal->j_superblock);
730*6a54128fSAndroid Build Coastguard Worker mark_buffer_dirty(journal->j_sb_buffer);
731*6a54128fSAndroid Build Coastguard Worker }
732*6a54128fSAndroid Build Coastguard Worker
733*6a54128fSAndroid Build Coastguard Worker err:
734*6a54128fSAndroid Build Coastguard Worker ext2fs_journal_release(fs, journal, 0, retval ? 1 : 0);
735*6a54128fSAndroid Build Coastguard Worker return retval;
736*6a54128fSAndroid Build Coastguard Worker }
737*6a54128fSAndroid Build Coastguard Worker
recover_ext3_journal(ext2_filsys fs)738*6a54128fSAndroid Build Coastguard Worker static errcode_t recover_ext3_journal(ext2_filsys fs)
739*6a54128fSAndroid Build Coastguard Worker {
740*6a54128fSAndroid Build Coastguard Worker journal_t *journal;
741*6a54128fSAndroid Build Coastguard Worker errcode_t retval;
742*6a54128fSAndroid Build Coastguard Worker
743*6a54128fSAndroid Build Coastguard Worker retval = jbd2_journal_init_revoke_record_cache();
744*6a54128fSAndroid Build Coastguard Worker if (retval)
745*6a54128fSAndroid Build Coastguard Worker return retval;
746*6a54128fSAndroid Build Coastguard Worker
747*6a54128fSAndroid Build Coastguard Worker retval = jbd2_journal_init_revoke_table_cache();
748*6a54128fSAndroid Build Coastguard Worker if (retval)
749*6a54128fSAndroid Build Coastguard Worker return retval;
750*6a54128fSAndroid Build Coastguard Worker
751*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_get_journal(fs, &journal);
752*6a54128fSAndroid Build Coastguard Worker if (retval)
753*6a54128fSAndroid Build Coastguard Worker return retval;
754*6a54128fSAndroid Build Coastguard Worker
755*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_journal_load(journal);
756*6a54128fSAndroid Build Coastguard Worker if (retval)
757*6a54128fSAndroid Build Coastguard Worker goto errout;
758*6a54128fSAndroid Build Coastguard Worker
759*6a54128fSAndroid Build Coastguard Worker retval = jbd2_journal_init_revoke(journal, 1024);
760*6a54128fSAndroid Build Coastguard Worker if (retval)
761*6a54128fSAndroid Build Coastguard Worker goto errout;
762*6a54128fSAndroid Build Coastguard Worker
763*6a54128fSAndroid Build Coastguard Worker retval = -jbd2_journal_recover(journal);
764*6a54128fSAndroid Build Coastguard Worker if (retval)
765*6a54128fSAndroid Build Coastguard Worker goto errout;
766*6a54128fSAndroid Build Coastguard Worker
767*6a54128fSAndroid Build Coastguard Worker if (journal->j_failed_commit) {
768*6a54128fSAndroid Build Coastguard Worker journal->j_superblock->s_errno = -EINVAL;
769*6a54128fSAndroid Build Coastguard Worker mark_buffer_dirty(journal->j_sb_buffer);
770*6a54128fSAndroid Build Coastguard Worker }
771*6a54128fSAndroid Build Coastguard Worker
772*6a54128fSAndroid Build Coastguard Worker journal->j_tail_sequence = journal->j_transaction_sequence;
773*6a54128fSAndroid Build Coastguard Worker
774*6a54128fSAndroid Build Coastguard Worker errout:
775*6a54128fSAndroid Build Coastguard Worker jbd2_journal_destroy_revoke(journal);
776*6a54128fSAndroid Build Coastguard Worker jbd2_journal_destroy_revoke_record_cache();
777*6a54128fSAndroid Build Coastguard Worker jbd2_journal_destroy_revoke_table_cache();
778*6a54128fSAndroid Build Coastguard Worker ext2fs_journal_release(fs, journal, 1, 0);
779*6a54128fSAndroid Build Coastguard Worker return retval;
780*6a54128fSAndroid Build Coastguard Worker }
781*6a54128fSAndroid Build Coastguard Worker
ext2fs_run_ext3_journal(ext2_filsys * fsp)782*6a54128fSAndroid Build Coastguard Worker errcode_t ext2fs_run_ext3_journal(ext2_filsys *fsp)
783*6a54128fSAndroid Build Coastguard Worker {
784*6a54128fSAndroid Build Coastguard Worker ext2_filsys fs = *fsp;
785*6a54128fSAndroid Build Coastguard Worker io_manager io_ptr = fs->io->manager;
786*6a54128fSAndroid Build Coastguard Worker errcode_t retval, recover_retval;
787*6a54128fSAndroid Build Coastguard Worker io_stats stats = 0;
788*6a54128fSAndroid Build Coastguard Worker unsigned long long kbytes_written = 0;
789*6a54128fSAndroid Build Coastguard Worker char *fsname;
790*6a54128fSAndroid Build Coastguard Worker int fsflags;
791*6a54128fSAndroid Build Coastguard Worker int fsblocksize;
792*6a54128fSAndroid Build Coastguard Worker
793*6a54128fSAndroid Build Coastguard Worker if (!(fs->flags & EXT2_FLAG_RW))
794*6a54128fSAndroid Build Coastguard Worker return EXT2_ET_FILE_RO;
795*6a54128fSAndroid Build Coastguard Worker
796*6a54128fSAndroid Build Coastguard Worker if (fs->flags & EXT2_FLAG_DIRTY)
797*6a54128fSAndroid Build Coastguard Worker ext2fs_flush(fs); /* Force out any modifications */
798*6a54128fSAndroid Build Coastguard Worker
799*6a54128fSAndroid Build Coastguard Worker recover_retval = recover_ext3_journal(fs);
800*6a54128fSAndroid Build Coastguard Worker
801*6a54128fSAndroid Build Coastguard Worker /*
802*6a54128fSAndroid Build Coastguard Worker * Reload the filesystem context to get up-to-date data from disk
803*6a54128fSAndroid Build Coastguard Worker * because journal recovery will change the filesystem under us.
804*6a54128fSAndroid Build Coastguard Worker */
805*6a54128fSAndroid Build Coastguard Worker if (fs->super->s_kbytes_written &&
806*6a54128fSAndroid Build Coastguard Worker fs->io->manager->get_stats)
807*6a54128fSAndroid Build Coastguard Worker fs->io->manager->get_stats(fs->io, &stats);
808*6a54128fSAndroid Build Coastguard Worker if (stats && stats->bytes_written)
809*6a54128fSAndroid Build Coastguard Worker kbytes_written = stats->bytes_written >> 10;
810*6a54128fSAndroid Build Coastguard Worker
811*6a54128fSAndroid Build Coastguard Worker ext2fs_mmp_stop(fs);
812*6a54128fSAndroid Build Coastguard Worker fsname = fs->device_name;
813*6a54128fSAndroid Build Coastguard Worker fs->device_name = NULL;
814*6a54128fSAndroid Build Coastguard Worker fsflags = fs->flags;
815*6a54128fSAndroid Build Coastguard Worker fsblocksize = fs->blocksize;
816*6a54128fSAndroid Build Coastguard Worker ext2fs_free(fs);
817*6a54128fSAndroid Build Coastguard Worker *fsp = NULL;
818*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_open(fsname, fsflags, 0, fsblocksize, io_ptr, fsp);
819*6a54128fSAndroid Build Coastguard Worker ext2fs_free_mem(&fsname);
820*6a54128fSAndroid Build Coastguard Worker if (retval)
821*6a54128fSAndroid Build Coastguard Worker return retval;
822*6a54128fSAndroid Build Coastguard Worker
823*6a54128fSAndroid Build Coastguard Worker fs = *fsp;
824*6a54128fSAndroid Build Coastguard Worker fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
825*6a54128fSAndroid Build Coastguard Worker fs->super->s_kbytes_written += kbytes_written;
826*6a54128fSAndroid Build Coastguard Worker
827*6a54128fSAndroid Build Coastguard Worker /* Set the superblock flags */
828*6a54128fSAndroid Build Coastguard Worker ext2fs_clear_recover(fs, recover_retval != 0);
829*6a54128fSAndroid Build Coastguard Worker
830*6a54128fSAndroid Build Coastguard Worker /*
831*6a54128fSAndroid Build Coastguard Worker * Do one last sanity check, and propagate journal->s_errno to
832*6a54128fSAndroid Build Coastguard Worker * the EXT2_ERROR_FS flag in the fs superblock if needed.
833*6a54128fSAndroid Build Coastguard Worker */
834*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_check_ext3_journal(fs);
835*6a54128fSAndroid Build Coastguard Worker return retval ? retval : recover_retval;
836*6a54128fSAndroid Build Coastguard Worker }
837*6a54128fSAndroid Build Coastguard Worker
ext2fs_open_journal(ext2_filsys fs,journal_t ** j)838*6a54128fSAndroid Build Coastguard Worker errcode_t ext2fs_open_journal(ext2_filsys fs, journal_t **j)
839*6a54128fSAndroid Build Coastguard Worker {
840*6a54128fSAndroid Build Coastguard Worker journal_t *journal;
841*6a54128fSAndroid Build Coastguard Worker errcode_t retval;
842*6a54128fSAndroid Build Coastguard Worker
843*6a54128fSAndroid Build Coastguard Worker retval = jbd2_journal_init_revoke_record_cache();
844*6a54128fSAndroid Build Coastguard Worker if (retval)
845*6a54128fSAndroid Build Coastguard Worker return retval;
846*6a54128fSAndroid Build Coastguard Worker
847*6a54128fSAndroid Build Coastguard Worker retval = jbd2_journal_init_revoke_table_cache();
848*6a54128fSAndroid Build Coastguard Worker if (retval)
849*6a54128fSAndroid Build Coastguard Worker return retval;
850*6a54128fSAndroid Build Coastguard Worker
851*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_get_journal(fs, &journal);
852*6a54128fSAndroid Build Coastguard Worker if (retval)
853*6a54128fSAndroid Build Coastguard Worker return retval;
854*6a54128fSAndroid Build Coastguard Worker
855*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_journal_load(journal);
856*6a54128fSAndroid Build Coastguard Worker if (retval)
857*6a54128fSAndroid Build Coastguard Worker goto errout;
858*6a54128fSAndroid Build Coastguard Worker
859*6a54128fSAndroid Build Coastguard Worker retval = jbd2_journal_init_revoke(journal, 1024);
860*6a54128fSAndroid Build Coastguard Worker if (retval)
861*6a54128fSAndroid Build Coastguard Worker goto errout;
862*6a54128fSAndroid Build Coastguard Worker
863*6a54128fSAndroid Build Coastguard Worker if (journal->j_failed_commit) {
864*6a54128fSAndroid Build Coastguard Worker journal->j_superblock->s_errno = -EINVAL;
865*6a54128fSAndroid Build Coastguard Worker mark_buffer_dirty(journal->j_sb_buffer);
866*6a54128fSAndroid Build Coastguard Worker }
867*6a54128fSAndroid Build Coastguard Worker
868*6a54128fSAndroid Build Coastguard Worker *j = journal;
869*6a54128fSAndroid Build Coastguard Worker return 0;
870*6a54128fSAndroid Build Coastguard Worker
871*6a54128fSAndroid Build Coastguard Worker errout:
872*6a54128fSAndroid Build Coastguard Worker jbd2_journal_destroy_revoke(journal);
873*6a54128fSAndroid Build Coastguard Worker jbd2_journal_destroy_revoke_record_cache();
874*6a54128fSAndroid Build Coastguard Worker jbd2_journal_destroy_revoke_table_cache();
875*6a54128fSAndroid Build Coastguard Worker ext2fs_journal_release(fs, journal, 1, 0);
876*6a54128fSAndroid Build Coastguard Worker return retval;
877*6a54128fSAndroid Build Coastguard Worker }
878*6a54128fSAndroid Build Coastguard Worker
ext2fs_close_journal(ext2_filsys fs,journal_t ** j)879*6a54128fSAndroid Build Coastguard Worker errcode_t ext2fs_close_journal(ext2_filsys fs, journal_t **j)
880*6a54128fSAndroid Build Coastguard Worker {
881*6a54128fSAndroid Build Coastguard Worker journal_t *journal = *j;
882*6a54128fSAndroid Build Coastguard Worker
883*6a54128fSAndroid Build Coastguard Worker jbd2_journal_destroy_revoke(journal);
884*6a54128fSAndroid Build Coastguard Worker jbd2_journal_destroy_revoke_record_cache();
885*6a54128fSAndroid Build Coastguard Worker jbd2_journal_destroy_revoke_table_cache();
886*6a54128fSAndroid Build Coastguard Worker ext2fs_journal_release(fs, journal, 0, 0);
887*6a54128fSAndroid Build Coastguard Worker *j = NULL;
888*6a54128fSAndroid Build Coastguard Worker
889*6a54128fSAndroid Build Coastguard Worker return 0;
890*6a54128fSAndroid Build Coastguard Worker }
891*6a54128fSAndroid Build Coastguard Worker
jbd2_commit_block_csum_set(journal_t * j,struct buffer_head * bh)892*6a54128fSAndroid Build Coastguard Worker void jbd2_commit_block_csum_set(journal_t *j, struct buffer_head *bh)
893*6a54128fSAndroid Build Coastguard Worker {
894*6a54128fSAndroid Build Coastguard Worker struct commit_header *h;
895*6a54128fSAndroid Build Coastguard Worker __u32 csum;
896*6a54128fSAndroid Build Coastguard Worker
897*6a54128fSAndroid Build Coastguard Worker if (!jbd2_journal_has_csum_v2or3(j))
898*6a54128fSAndroid Build Coastguard Worker return;
899*6a54128fSAndroid Build Coastguard Worker
900*6a54128fSAndroid Build Coastguard Worker h = (struct commit_header *)(bh->b_data);
901*6a54128fSAndroid Build Coastguard Worker h->h_chksum_type = 0;
902*6a54128fSAndroid Build Coastguard Worker h->h_chksum_size = 0;
903*6a54128fSAndroid Build Coastguard Worker h->h_chksum[0] = 0;
904*6a54128fSAndroid Build Coastguard Worker csum = jbd2_chksum(j, j->j_csum_seed, bh->b_data, j->j_blocksize);
905*6a54128fSAndroid Build Coastguard Worker h->h_chksum[0] = ext2fs_cpu_to_be32(csum);
906*6a54128fSAndroid Build Coastguard Worker }
907*6a54128fSAndroid Build Coastguard Worker
jbd2_revoke_csum_set(journal_t * j,struct buffer_head * bh)908*6a54128fSAndroid Build Coastguard Worker void jbd2_revoke_csum_set(journal_t *j, struct buffer_head *bh)
909*6a54128fSAndroid Build Coastguard Worker {
910*6a54128fSAndroid Build Coastguard Worker jbd2_descr_block_csum_set(j, bh);
911*6a54128fSAndroid Build Coastguard Worker }
912*6a54128fSAndroid Build Coastguard Worker
jbd2_descr_block_csum_set(journal_t * j,struct buffer_head * bh)913*6a54128fSAndroid Build Coastguard Worker void jbd2_descr_block_csum_set(journal_t *j, struct buffer_head *bh)
914*6a54128fSAndroid Build Coastguard Worker {
915*6a54128fSAndroid Build Coastguard Worker struct jbd2_journal_block_tail *tail;
916*6a54128fSAndroid Build Coastguard Worker __u32 csum;
917*6a54128fSAndroid Build Coastguard Worker
918*6a54128fSAndroid Build Coastguard Worker if (!jbd2_journal_has_csum_v2or3(j))
919*6a54128fSAndroid Build Coastguard Worker return;
920*6a54128fSAndroid Build Coastguard Worker
921*6a54128fSAndroid Build Coastguard Worker tail = (struct jbd2_journal_block_tail *)(bh->b_data + j->j_blocksize -
922*6a54128fSAndroid Build Coastguard Worker sizeof(struct jbd2_journal_block_tail));
923*6a54128fSAndroid Build Coastguard Worker tail->t_checksum = 0;
924*6a54128fSAndroid Build Coastguard Worker csum = jbd2_chksum(j, j->j_csum_seed, bh->b_data, j->j_blocksize);
925*6a54128fSAndroid Build Coastguard Worker tail->t_checksum = ext2fs_cpu_to_be32(csum);
926*6a54128fSAndroid Build Coastguard Worker }
927*6a54128fSAndroid Build Coastguard Worker
jbd2_block_tag_csum_set(journal_t * j,journal_block_tag_t * tag,struct buffer_head * bh,__u32 sequence)928*6a54128fSAndroid Build Coastguard Worker void jbd2_block_tag_csum_set(journal_t *j, journal_block_tag_t *tag,
929*6a54128fSAndroid Build Coastguard Worker struct buffer_head *bh, __u32 sequence)
930*6a54128fSAndroid Build Coastguard Worker {
931*6a54128fSAndroid Build Coastguard Worker journal_block_tag3_t *tag3 = (journal_block_tag3_t *)tag;
932*6a54128fSAndroid Build Coastguard Worker __u32 csum32;
933*6a54128fSAndroid Build Coastguard Worker __be32 seq;
934*6a54128fSAndroid Build Coastguard Worker
935*6a54128fSAndroid Build Coastguard Worker if (!jbd2_journal_has_csum_v2or3(j))
936*6a54128fSAndroid Build Coastguard Worker return;
937*6a54128fSAndroid Build Coastguard Worker
938*6a54128fSAndroid Build Coastguard Worker seq = ext2fs_cpu_to_be32(sequence);
939*6a54128fSAndroid Build Coastguard Worker csum32 = jbd2_chksum(j, j->j_csum_seed, (__u8 *)&seq, sizeof(seq));
940*6a54128fSAndroid Build Coastguard Worker csum32 = jbd2_chksum(j, csum32, bh->b_data, bh->b_size);
941*6a54128fSAndroid Build Coastguard Worker
942*6a54128fSAndroid Build Coastguard Worker if (jbd2_has_feature_csum3(j))
943*6a54128fSAndroid Build Coastguard Worker tag3->t_checksum = ext2fs_cpu_to_be32(csum32);
944*6a54128fSAndroid Build Coastguard Worker else
945*6a54128fSAndroid Build Coastguard Worker tag->t_checksum = ext2fs_cpu_to_be16(csum32);
946*6a54128fSAndroid Build Coastguard Worker }
947*6a54128fSAndroid Build Coastguard Worker
948