xref: /aosp_15_r20/external/e2fsprogs/debugfs/journal.c (revision 6a54128f25917bfc36a8a6e9d722c04a0b4641b6)
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