1*6a54128fSAndroid Build Coastguard Worker /*
2*6a54128fSAndroid Build Coastguard Worker * do_journal.c --- Scribble onto the journal!
3*6a54128fSAndroid Build Coastguard Worker *
4*6a54128fSAndroid Build Coastguard Worker * Copyright (C) 2014 Oracle. This file may be redistributed
5*6a54128fSAndroid Build Coastguard Worker * under the terms of the GNU Public License.
6*6a54128fSAndroid Build Coastguard Worker */
7*6a54128fSAndroid Build Coastguard Worker
8*6a54128fSAndroid Build Coastguard Worker #include "config.h"
9*6a54128fSAndroid Build Coastguard Worker #include <stdio.h>
10*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_GETOPT_H
11*6a54128fSAndroid Build Coastguard Worker #include <getopt.h>
12*6a54128fSAndroid Build Coastguard Worker #else
13*6a54128fSAndroid Build Coastguard Worker extern int optind;
14*6a54128fSAndroid Build Coastguard Worker extern char *optarg;
15*6a54128fSAndroid Build Coastguard Worker #endif
16*6a54128fSAndroid Build Coastguard Worker #include <ctype.h>
17*6a54128fSAndroid Build Coastguard Worker #include <unistd.h>
18*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_SYS_TIME_H
19*6a54128fSAndroid Build Coastguard Worker #include <sys/time.h>
20*6a54128fSAndroid Build Coastguard Worker #endif
21*6a54128fSAndroid Build Coastguard Worker
22*6a54128fSAndroid Build Coastguard Worker #include "debugfs.h"
23*6a54128fSAndroid Build Coastguard Worker #include "ext2fs/kernel-jbd.h"
24*6a54128fSAndroid Build Coastguard Worker #include "journal.h"
25*6a54128fSAndroid Build Coastguard Worker
26*6a54128fSAndroid Build Coastguard Worker #undef DEBUG
27*6a54128fSAndroid Build Coastguard Worker
28*6a54128fSAndroid Build Coastguard Worker #ifdef DEBUG
29*6a54128fSAndroid Build Coastguard Worker # define dbg_printf(f, a...) do {printf("JFS DEBUG: " f, ## a); \
30*6a54128fSAndroid Build Coastguard Worker fflush(stdout); \
31*6a54128fSAndroid Build Coastguard Worker } while (0)
32*6a54128fSAndroid Build Coastguard Worker #else
33*6a54128fSAndroid Build Coastguard Worker # define dbg_printf(f, a...)
34*6a54128fSAndroid Build Coastguard Worker #endif
35*6a54128fSAndroid Build Coastguard Worker
36*6a54128fSAndroid Build Coastguard Worker #define JOURNAL_CHECK_TRANS_MAGIC(x) \
37*6a54128fSAndroid Build Coastguard Worker do { \
38*6a54128fSAndroid Build Coastguard Worker if ((x)->magic != J_TRANS_MAGIC) \
39*6a54128fSAndroid Build Coastguard Worker return EXT2_ET_INVALID_ARGUMENT; \
40*6a54128fSAndroid Build Coastguard Worker } while (0)
41*6a54128fSAndroid Build Coastguard Worker
42*6a54128fSAndroid Build Coastguard Worker #define J_TRANS_MAGIC 0xD15EA5ED
43*6a54128fSAndroid Build Coastguard Worker #define J_TRANS_OPEN 1
44*6a54128fSAndroid Build Coastguard Worker #define J_TRANS_COMMITTED 2
45*6a54128fSAndroid Build Coastguard Worker struct journal_transaction_s {
46*6a54128fSAndroid Build Coastguard Worker unsigned int magic;
47*6a54128fSAndroid Build Coastguard Worker ext2_filsys fs;
48*6a54128fSAndroid Build Coastguard Worker journal_t *journal;
49*6a54128fSAndroid Build Coastguard Worker blk64_t block;
50*6a54128fSAndroid Build Coastguard Worker blk64_t start, end;
51*6a54128fSAndroid Build Coastguard Worker tid_t tid;
52*6a54128fSAndroid Build Coastguard Worker int flags;
53*6a54128fSAndroid Build Coastguard Worker };
54*6a54128fSAndroid Build Coastguard Worker
55*6a54128fSAndroid Build Coastguard Worker typedef struct journal_transaction_s journal_transaction_t;
56*6a54128fSAndroid Build Coastguard Worker
57*6a54128fSAndroid Build Coastguard Worker static journal_t *current_journal = NULL;
58*6a54128fSAndroid Build Coastguard Worker
journal_dump_trans(journal_transaction_t * trans EXT2FS_ATTR ((unused)),const char * tag EXT2FS_ATTR ((unused)))59*6a54128fSAndroid Build Coastguard Worker static void journal_dump_trans(journal_transaction_t *trans EXT2FS_ATTR((unused)),
60*6a54128fSAndroid Build Coastguard Worker const char *tag EXT2FS_ATTR((unused)))
61*6a54128fSAndroid Build Coastguard Worker {
62*6a54128fSAndroid Build Coastguard Worker dbg_printf("TRANS %p(%s): tid=%u start=%llu block=%llu end=%llu "
63*6a54128fSAndroid Build Coastguard Worker "flags=0x%x\n", trans, tag, trans->tid, trans->start,
64*6a54128fSAndroid Build Coastguard Worker trans->block, trans->end, trans->flags);
65*6a54128fSAndroid Build Coastguard Worker }
66*6a54128fSAndroid Build Coastguard Worker
journal_commit_trans(journal_transaction_t * trans)67*6a54128fSAndroid Build Coastguard Worker static errcode_t journal_commit_trans(journal_transaction_t *trans)
68*6a54128fSAndroid Build Coastguard Worker {
69*6a54128fSAndroid Build Coastguard Worker struct buffer_head *bh, *cbh = NULL;
70*6a54128fSAndroid Build Coastguard Worker struct commit_header *commit;
71*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_SYS_TIME_H
72*6a54128fSAndroid Build Coastguard Worker struct timeval tv;
73*6a54128fSAndroid Build Coastguard Worker #endif
74*6a54128fSAndroid Build Coastguard Worker errcode_t err;
75*6a54128fSAndroid Build Coastguard Worker
76*6a54128fSAndroid Build Coastguard Worker JOURNAL_CHECK_TRANS_MAGIC(trans);
77*6a54128fSAndroid Build Coastguard Worker
78*6a54128fSAndroid Build Coastguard Worker if ((trans->flags & J_TRANS_COMMITTED) ||
79*6a54128fSAndroid Build Coastguard Worker !(trans->flags & J_TRANS_OPEN))
80*6a54128fSAndroid Build Coastguard Worker return EXT2_ET_INVALID_ARGUMENT;
81*6a54128fSAndroid Build Coastguard Worker
82*6a54128fSAndroid Build Coastguard Worker bh = getblk(trans->journal->j_dev, 0, trans->journal->j_blocksize);
83*6a54128fSAndroid Build Coastguard Worker if (bh == NULL)
84*6a54128fSAndroid Build Coastguard Worker return ENOMEM;
85*6a54128fSAndroid Build Coastguard Worker
86*6a54128fSAndroid Build Coastguard Worker /* write the descriptor block header */
87*6a54128fSAndroid Build Coastguard Worker commit = (struct commit_header *)bh->b_data;
88*6a54128fSAndroid Build Coastguard Worker commit->h_magic = ext2fs_cpu_to_be32(JBD2_MAGIC_NUMBER);
89*6a54128fSAndroid Build Coastguard Worker commit->h_blocktype = ext2fs_cpu_to_be32(JBD2_COMMIT_BLOCK);
90*6a54128fSAndroid Build Coastguard Worker commit->h_sequence = ext2fs_cpu_to_be32(trans->tid);
91*6a54128fSAndroid Build Coastguard Worker if (jbd2_has_feature_checksum(trans->journal)) {
92*6a54128fSAndroid Build Coastguard Worker __u32 csum_v1 = ~0;
93*6a54128fSAndroid Build Coastguard Worker blk64_t cblk;
94*6a54128fSAndroid Build Coastguard Worker
95*6a54128fSAndroid Build Coastguard Worker cbh = getblk(trans->journal->j_dev, 0,
96*6a54128fSAndroid Build Coastguard Worker trans->journal->j_blocksize);
97*6a54128fSAndroid Build Coastguard Worker if (cbh == NULL) {
98*6a54128fSAndroid Build Coastguard Worker err = ENOMEM;
99*6a54128fSAndroid Build Coastguard Worker goto error;
100*6a54128fSAndroid Build Coastguard Worker }
101*6a54128fSAndroid Build Coastguard Worker
102*6a54128fSAndroid Build Coastguard Worker for (cblk = trans->start; cblk < trans->block; cblk++) {
103*6a54128fSAndroid Build Coastguard Worker err = jbd2_journal_bmap(trans->journal, cblk,
104*6a54128fSAndroid Build Coastguard Worker &cbh->b_blocknr);
105*6a54128fSAndroid Build Coastguard Worker if (err)
106*6a54128fSAndroid Build Coastguard Worker goto error;
107*6a54128fSAndroid Build Coastguard Worker mark_buffer_uptodate(cbh, 0);
108*6a54128fSAndroid Build Coastguard Worker ll_rw_block(REQ_OP_READ, 0, 1, &cbh);
109*6a54128fSAndroid Build Coastguard Worker err = cbh->b_err;
110*6a54128fSAndroid Build Coastguard Worker if (err)
111*6a54128fSAndroid Build Coastguard Worker goto error;
112*6a54128fSAndroid Build Coastguard Worker csum_v1 = ext2fs_crc32_be(csum_v1,
113*6a54128fSAndroid Build Coastguard Worker (unsigned char const *)cbh->b_data,
114*6a54128fSAndroid Build Coastguard Worker cbh->b_size);
115*6a54128fSAndroid Build Coastguard Worker }
116*6a54128fSAndroid Build Coastguard Worker
117*6a54128fSAndroid Build Coastguard Worker commit->h_chksum_type = JBD2_CRC32_CHKSUM;
118*6a54128fSAndroid Build Coastguard Worker commit->h_chksum_size = JBD2_CRC32_CHKSUM_SIZE;
119*6a54128fSAndroid Build Coastguard Worker commit->h_chksum[0] = ext2fs_cpu_to_be32(csum_v1);
120*6a54128fSAndroid Build Coastguard Worker } else {
121*6a54128fSAndroid Build Coastguard Worker commit->h_chksum_type = 0;
122*6a54128fSAndroid Build Coastguard Worker commit->h_chksum_size = 0;
123*6a54128fSAndroid Build Coastguard Worker commit->h_chksum[0] = 0;
124*6a54128fSAndroid Build Coastguard Worker }
125*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_SYS_TIME_H
126*6a54128fSAndroid Build Coastguard Worker gettimeofday(&tv, NULL);
127*6a54128fSAndroid Build Coastguard Worker commit->h_commit_sec = ext2fs_cpu_to_be32(tv.tv_sec);
128*6a54128fSAndroid Build Coastguard Worker commit->h_commit_nsec = ext2fs_cpu_to_be32(tv.tv_usec * 1000);
129*6a54128fSAndroid Build Coastguard Worker #else
130*6a54128fSAndroid Build Coastguard Worker commit->h_commit_sec = 0;
131*6a54128fSAndroid Build Coastguard Worker commit->h_commit_nsec = 0;
132*6a54128fSAndroid Build Coastguard Worker #endif
133*6a54128fSAndroid Build Coastguard Worker
134*6a54128fSAndroid Build Coastguard Worker /* Write block */
135*6a54128fSAndroid Build Coastguard Worker jbd2_commit_block_csum_set(trans->journal, bh);
136*6a54128fSAndroid Build Coastguard Worker err = jbd2_journal_bmap(trans->journal, trans->block, &bh->b_blocknr);
137*6a54128fSAndroid Build Coastguard Worker if (err)
138*6a54128fSAndroid Build Coastguard Worker goto error;
139*6a54128fSAndroid Build Coastguard Worker
140*6a54128fSAndroid Build Coastguard Worker dbg_printf("Writing commit block at %llu:%llu\n", trans->block,
141*6a54128fSAndroid Build Coastguard Worker bh->b_blocknr);
142*6a54128fSAndroid Build Coastguard Worker mark_buffer_dirty(bh);
143*6a54128fSAndroid Build Coastguard Worker ll_rw_block(REQ_OP_WRITE, 0, 1, &bh);
144*6a54128fSAndroid Build Coastguard Worker err = bh->b_err;
145*6a54128fSAndroid Build Coastguard Worker if (err)
146*6a54128fSAndroid Build Coastguard Worker goto error;
147*6a54128fSAndroid Build Coastguard Worker trans->flags |= J_TRANS_COMMITTED;
148*6a54128fSAndroid Build Coastguard Worker trans->flags &= ~J_TRANS_OPEN;
149*6a54128fSAndroid Build Coastguard Worker trans->block++;
150*6a54128fSAndroid Build Coastguard Worker
151*6a54128fSAndroid Build Coastguard Worker ext2fs_set_feature_journal_needs_recovery(trans->fs->super);
152*6a54128fSAndroid Build Coastguard Worker ext2fs_mark_super_dirty(trans->fs);
153*6a54128fSAndroid Build Coastguard Worker error:
154*6a54128fSAndroid Build Coastguard Worker if (cbh)
155*6a54128fSAndroid Build Coastguard Worker brelse(cbh);
156*6a54128fSAndroid Build Coastguard Worker brelse(bh);
157*6a54128fSAndroid Build Coastguard Worker return err;
158*6a54128fSAndroid Build Coastguard Worker }
159*6a54128fSAndroid Build Coastguard Worker
journal_add_revoke_to_trans(journal_transaction_t * trans,blk64_t * revoke_list,size_t revoke_len)160*6a54128fSAndroid Build Coastguard Worker static errcode_t journal_add_revoke_to_trans(journal_transaction_t *trans,
161*6a54128fSAndroid Build Coastguard Worker blk64_t *revoke_list,
162*6a54128fSAndroid Build Coastguard Worker size_t revoke_len)
163*6a54128fSAndroid Build Coastguard Worker {
164*6a54128fSAndroid Build Coastguard Worker jbd2_journal_revoke_header_t *jrb;
165*6a54128fSAndroid Build Coastguard Worker void *buf;
166*6a54128fSAndroid Build Coastguard Worker size_t i, offset;
167*6a54128fSAndroid Build Coastguard Worker blk64_t curr_blk;
168*6a54128fSAndroid Build Coastguard Worker unsigned int sz;
169*6a54128fSAndroid Build Coastguard Worker unsigned csum_size = 0;
170*6a54128fSAndroid Build Coastguard Worker struct buffer_head *bh;
171*6a54128fSAndroid Build Coastguard Worker errcode_t err;
172*6a54128fSAndroid Build Coastguard Worker
173*6a54128fSAndroid Build Coastguard Worker JOURNAL_CHECK_TRANS_MAGIC(trans);
174*6a54128fSAndroid Build Coastguard Worker
175*6a54128fSAndroid Build Coastguard Worker if ((trans->flags & J_TRANS_COMMITTED) ||
176*6a54128fSAndroid Build Coastguard Worker !(trans->flags & J_TRANS_OPEN))
177*6a54128fSAndroid Build Coastguard Worker return EXT2_ET_INVALID_ARGUMENT;
178*6a54128fSAndroid Build Coastguard Worker
179*6a54128fSAndroid Build Coastguard Worker if (revoke_len == 0)
180*6a54128fSAndroid Build Coastguard Worker return 0;
181*6a54128fSAndroid Build Coastguard Worker
182*6a54128fSAndroid Build Coastguard Worker /* Do we need to leave space at the end for a checksum? */
183*6a54128fSAndroid Build Coastguard Worker if (jbd2_journal_has_csum_v2or3(trans->journal))
184*6a54128fSAndroid Build Coastguard Worker csum_size = sizeof(struct jbd2_journal_block_tail);
185*6a54128fSAndroid Build Coastguard Worker
186*6a54128fSAndroid Build Coastguard Worker curr_blk = trans->block;
187*6a54128fSAndroid Build Coastguard Worker
188*6a54128fSAndroid Build Coastguard Worker bh = getblk(trans->journal->j_dev, curr_blk,
189*6a54128fSAndroid Build Coastguard Worker trans->journal->j_blocksize);
190*6a54128fSAndroid Build Coastguard Worker if (bh == NULL)
191*6a54128fSAndroid Build Coastguard Worker return ENOMEM;
192*6a54128fSAndroid Build Coastguard Worker jrb = buf = bh->b_data;
193*6a54128fSAndroid Build Coastguard Worker jrb->r_header.h_magic = ext2fs_cpu_to_be32(JBD2_MAGIC_NUMBER);
194*6a54128fSAndroid Build Coastguard Worker jrb->r_header.h_blocktype = ext2fs_cpu_to_be32(JBD2_REVOKE_BLOCK);
195*6a54128fSAndroid Build Coastguard Worker jrb->r_header.h_sequence = ext2fs_cpu_to_be32(trans->tid);
196*6a54128fSAndroid Build Coastguard Worker offset = sizeof(*jrb);
197*6a54128fSAndroid Build Coastguard Worker
198*6a54128fSAndroid Build Coastguard Worker if (jbd2_has_feature_64bit(trans->journal))
199*6a54128fSAndroid Build Coastguard Worker sz = 8;
200*6a54128fSAndroid Build Coastguard Worker else
201*6a54128fSAndroid Build Coastguard Worker sz = 4;
202*6a54128fSAndroid Build Coastguard Worker
203*6a54128fSAndroid Build Coastguard Worker for (i = 0; i < revoke_len; i++) {
204*6a54128fSAndroid Build Coastguard Worker /* Block full, write to journal */
205*6a54128fSAndroid Build Coastguard Worker if (offset + sz > trans->journal->j_blocksize - csum_size) {
206*6a54128fSAndroid Build Coastguard Worker jrb->r_count = ext2fs_cpu_to_be32(offset);
207*6a54128fSAndroid Build Coastguard Worker jbd2_revoke_csum_set(trans->journal, bh);
208*6a54128fSAndroid Build Coastguard Worker
209*6a54128fSAndroid Build Coastguard Worker err = jbd2_journal_bmap(trans->journal, curr_blk,
210*6a54128fSAndroid Build Coastguard Worker &bh->b_blocknr);
211*6a54128fSAndroid Build Coastguard Worker if (err)
212*6a54128fSAndroid Build Coastguard Worker goto error;
213*6a54128fSAndroid Build Coastguard Worker dbg_printf("Writing revoke block at %llu:%llu\n",
214*6a54128fSAndroid Build Coastguard Worker curr_blk, bh->b_blocknr);
215*6a54128fSAndroid Build Coastguard Worker mark_buffer_dirty(bh);
216*6a54128fSAndroid Build Coastguard Worker ll_rw_block(REQ_OP_WRITE, 0, 1, &bh);
217*6a54128fSAndroid Build Coastguard Worker err = bh->b_err;
218*6a54128fSAndroid Build Coastguard Worker if (err)
219*6a54128fSAndroid Build Coastguard Worker goto error;
220*6a54128fSAndroid Build Coastguard Worker
221*6a54128fSAndroid Build Coastguard Worker offset = sizeof(*jrb);
222*6a54128fSAndroid Build Coastguard Worker curr_blk++;
223*6a54128fSAndroid Build Coastguard Worker }
224*6a54128fSAndroid Build Coastguard Worker
225*6a54128fSAndroid Build Coastguard Worker if (revoke_list[i] >=
226*6a54128fSAndroid Build Coastguard Worker ext2fs_blocks_count(trans->journal->j_fs_dev->k_fs->super)) {
227*6a54128fSAndroid Build Coastguard Worker err = EXT2_ET_BAD_BLOCK_NUM;
228*6a54128fSAndroid Build Coastguard Worker goto error;
229*6a54128fSAndroid Build Coastguard Worker }
230*6a54128fSAndroid Build Coastguard Worker
231*6a54128fSAndroid Build Coastguard Worker if (jbd2_has_feature_64bit(trans->journal))
232*6a54128fSAndroid Build Coastguard Worker *((__u64 *)(&((char *)buf)[offset])) =
233*6a54128fSAndroid Build Coastguard Worker ext2fs_cpu_to_be64(revoke_list[i]);
234*6a54128fSAndroid Build Coastguard Worker else
235*6a54128fSAndroid Build Coastguard Worker *((__u32 *)(&((char *)buf)[offset])) =
236*6a54128fSAndroid Build Coastguard Worker ext2fs_cpu_to_be32(revoke_list[i]);
237*6a54128fSAndroid Build Coastguard Worker offset += sz;
238*6a54128fSAndroid Build Coastguard Worker }
239*6a54128fSAndroid Build Coastguard Worker
240*6a54128fSAndroid Build Coastguard Worker if (offset > 0) {
241*6a54128fSAndroid Build Coastguard Worker jrb->r_count = ext2fs_cpu_to_be32(offset);
242*6a54128fSAndroid Build Coastguard Worker jbd2_revoke_csum_set(trans->journal, bh);
243*6a54128fSAndroid Build Coastguard Worker
244*6a54128fSAndroid Build Coastguard Worker err = jbd2_journal_bmap(trans->journal, curr_blk,
245*6a54128fSAndroid Build Coastguard Worker &bh->b_blocknr);
246*6a54128fSAndroid Build Coastguard Worker if (err)
247*6a54128fSAndroid Build Coastguard Worker goto error;
248*6a54128fSAndroid Build Coastguard Worker dbg_printf("Writing revoke block at %llu:%llu\n",
249*6a54128fSAndroid Build Coastguard Worker curr_blk, bh->b_blocknr);
250*6a54128fSAndroid Build Coastguard Worker mark_buffer_dirty(bh);
251*6a54128fSAndroid Build Coastguard Worker ll_rw_block(REQ_OP_WRITE, 0, 1, &bh);
252*6a54128fSAndroid Build Coastguard Worker err = bh->b_err;
253*6a54128fSAndroid Build Coastguard Worker if (err)
254*6a54128fSAndroid Build Coastguard Worker goto error;
255*6a54128fSAndroid Build Coastguard Worker curr_blk++;
256*6a54128fSAndroid Build Coastguard Worker }
257*6a54128fSAndroid Build Coastguard Worker
258*6a54128fSAndroid Build Coastguard Worker error:
259*6a54128fSAndroid Build Coastguard Worker trans->block = curr_blk;
260*6a54128fSAndroid Build Coastguard Worker brelse(bh);
261*6a54128fSAndroid Build Coastguard Worker return err;
262*6a54128fSAndroid Build Coastguard Worker }
263*6a54128fSAndroid Build Coastguard Worker
journal_add_blocks_to_trans(journal_transaction_t * trans,blk64_t * block_list,size_t block_len,FILE * fp)264*6a54128fSAndroid Build Coastguard Worker static errcode_t journal_add_blocks_to_trans(journal_transaction_t *trans,
265*6a54128fSAndroid Build Coastguard Worker blk64_t *block_list, size_t block_len,
266*6a54128fSAndroid Build Coastguard Worker FILE *fp)
267*6a54128fSAndroid Build Coastguard Worker {
268*6a54128fSAndroid Build Coastguard Worker blk64_t curr_blk, jdb_blk;
269*6a54128fSAndroid Build Coastguard Worker size_t i, j;
270*6a54128fSAndroid Build Coastguard Worker int csum_size = 0;
271*6a54128fSAndroid Build Coastguard Worker journal_header_t *jdb;
272*6a54128fSAndroid Build Coastguard Worker journal_block_tag_t *jdbt;
273*6a54128fSAndroid Build Coastguard Worker int tag_bytes;
274*6a54128fSAndroid Build Coastguard Worker void *buf = NULL, *jdb_buf = NULL;
275*6a54128fSAndroid Build Coastguard Worker struct buffer_head *bh = NULL, *data_bh;
276*6a54128fSAndroid Build Coastguard Worker errcode_t err;
277*6a54128fSAndroid Build Coastguard Worker
278*6a54128fSAndroid Build Coastguard Worker JOURNAL_CHECK_TRANS_MAGIC(trans);
279*6a54128fSAndroid Build Coastguard Worker
280*6a54128fSAndroid Build Coastguard Worker if ((trans->flags & J_TRANS_COMMITTED) ||
281*6a54128fSAndroid Build Coastguard Worker !(trans->flags & J_TRANS_OPEN))
282*6a54128fSAndroid Build Coastguard Worker return EXT2_ET_INVALID_ARGUMENT;
283*6a54128fSAndroid Build Coastguard Worker
284*6a54128fSAndroid Build Coastguard Worker if (block_len == 0)
285*6a54128fSAndroid Build Coastguard Worker return 0;
286*6a54128fSAndroid Build Coastguard Worker
287*6a54128fSAndroid Build Coastguard Worker /* Do we need to leave space at the end for a checksum? */
288*6a54128fSAndroid Build Coastguard Worker if (jbd2_journal_has_csum_v2or3(trans->journal))
289*6a54128fSAndroid Build Coastguard Worker csum_size = sizeof(struct jbd2_journal_block_tail);
290*6a54128fSAndroid Build Coastguard Worker
291*6a54128fSAndroid Build Coastguard Worker curr_blk = jdb_blk = trans->block;
292*6a54128fSAndroid Build Coastguard Worker
293*6a54128fSAndroid Build Coastguard Worker data_bh = getblk(trans->journal->j_dev, curr_blk,
294*6a54128fSAndroid Build Coastguard Worker trans->journal->j_blocksize);
295*6a54128fSAndroid Build Coastguard Worker if (data_bh == NULL)
296*6a54128fSAndroid Build Coastguard Worker return ENOMEM;
297*6a54128fSAndroid Build Coastguard Worker buf = data_bh->b_data;
298*6a54128fSAndroid Build Coastguard Worker
299*6a54128fSAndroid Build Coastguard Worker /* write the descriptor block header */
300*6a54128fSAndroid Build Coastguard Worker bh = getblk(trans->journal->j_dev, curr_blk,
301*6a54128fSAndroid Build Coastguard Worker trans->journal->j_blocksize);
302*6a54128fSAndroid Build Coastguard Worker if (bh == NULL) {
303*6a54128fSAndroid Build Coastguard Worker err = ENOMEM;
304*6a54128fSAndroid Build Coastguard Worker goto error;
305*6a54128fSAndroid Build Coastguard Worker }
306*6a54128fSAndroid Build Coastguard Worker jdb = jdb_buf = bh->b_data;
307*6a54128fSAndroid Build Coastguard Worker jdb->h_magic = ext2fs_cpu_to_be32(JBD2_MAGIC_NUMBER);
308*6a54128fSAndroid Build Coastguard Worker jdb->h_blocktype = ext2fs_cpu_to_be32(JBD2_DESCRIPTOR_BLOCK);
309*6a54128fSAndroid Build Coastguard Worker jdb->h_sequence = ext2fs_cpu_to_be32(trans->tid);
310*6a54128fSAndroid Build Coastguard Worker jdbt = (journal_block_tag_t *)(jdb + 1);
311*6a54128fSAndroid Build Coastguard Worker
312*6a54128fSAndroid Build Coastguard Worker curr_blk++;
313*6a54128fSAndroid Build Coastguard Worker for (i = 0; i < block_len; i++) {
314*6a54128fSAndroid Build Coastguard Worker j = fread(data_bh->b_data, trans->journal->j_blocksize, 1, fp);
315*6a54128fSAndroid Build Coastguard Worker if (j != 1) {
316*6a54128fSAndroid Build Coastguard Worker err = errno;
317*6a54128fSAndroid Build Coastguard Worker goto error;
318*6a54128fSAndroid Build Coastguard Worker }
319*6a54128fSAndroid Build Coastguard Worker
320*6a54128fSAndroid Build Coastguard Worker tag_bytes = journal_tag_bytes(trans->journal);
321*6a54128fSAndroid Build Coastguard Worker
322*6a54128fSAndroid Build Coastguard Worker /* No space left in descriptor block, write it out */
323*6a54128fSAndroid Build Coastguard Worker if ((char *)jdbt + tag_bytes >
324*6a54128fSAndroid Build Coastguard Worker (char *)jdb_buf + trans->journal->j_blocksize - csum_size) {
325*6a54128fSAndroid Build Coastguard Worker jbd2_descr_block_csum_set(trans->journal, bh);
326*6a54128fSAndroid Build Coastguard Worker err = jbd2_journal_bmap(trans->journal, jdb_blk,
327*6a54128fSAndroid Build Coastguard Worker &bh->b_blocknr);
328*6a54128fSAndroid Build Coastguard Worker if (err)
329*6a54128fSAndroid Build Coastguard Worker goto error;
330*6a54128fSAndroid Build Coastguard Worker dbg_printf("Writing descriptor block at %llu:%llu\n",
331*6a54128fSAndroid Build Coastguard Worker jdb_blk, bh->b_blocknr);
332*6a54128fSAndroid Build Coastguard Worker mark_buffer_dirty(bh);
333*6a54128fSAndroid Build Coastguard Worker ll_rw_block(REQ_OP_WRITE, 0, 1, &bh);
334*6a54128fSAndroid Build Coastguard Worker err = bh->b_err;
335*6a54128fSAndroid Build Coastguard Worker if (err)
336*6a54128fSAndroid Build Coastguard Worker goto error;
337*6a54128fSAndroid Build Coastguard Worker
338*6a54128fSAndroid Build Coastguard Worker jdbt = (journal_block_tag_t *)(jdb + 1);
339*6a54128fSAndroid Build Coastguard Worker jdb_blk = curr_blk;
340*6a54128fSAndroid Build Coastguard Worker curr_blk++;
341*6a54128fSAndroid Build Coastguard Worker }
342*6a54128fSAndroid Build Coastguard Worker
343*6a54128fSAndroid Build Coastguard Worker if (block_list[i] >=
344*6a54128fSAndroid Build Coastguard Worker ext2fs_blocks_count(trans->journal->j_fs_dev->k_fs->super)) {
345*6a54128fSAndroid Build Coastguard Worker err = EXT2_ET_BAD_BLOCK_NUM;
346*6a54128fSAndroid Build Coastguard Worker goto error;
347*6a54128fSAndroid Build Coastguard Worker }
348*6a54128fSAndroid Build Coastguard Worker
349*6a54128fSAndroid Build Coastguard Worker /* Fill out the block tag */
350*6a54128fSAndroid Build Coastguard Worker jdbt->t_blocknr = ext2fs_cpu_to_be32(block_list[i] & 0xFFFFFFFF);
351*6a54128fSAndroid Build Coastguard Worker jdbt->t_flags = 0;
352*6a54128fSAndroid Build Coastguard Worker if (jdbt != (journal_block_tag_t *)(jdb + 1))
353*6a54128fSAndroid Build Coastguard Worker jdbt->t_flags |= ext2fs_cpu_to_be16(JBD2_FLAG_SAME_UUID);
354*6a54128fSAndroid Build Coastguard Worker else {
355*6a54128fSAndroid Build Coastguard Worker memcpy(jdbt + tag_bytes,
356*6a54128fSAndroid Build Coastguard Worker trans->journal->j_superblock->s_uuid,
357*6a54128fSAndroid Build Coastguard Worker sizeof(trans->journal->j_superblock->s_uuid));
358*6a54128fSAndroid Build Coastguard Worker tag_bytes += 16;
359*6a54128fSAndroid Build Coastguard Worker }
360*6a54128fSAndroid Build Coastguard Worker if (i == block_len - 1)
361*6a54128fSAndroid Build Coastguard Worker jdbt->t_flags |= ext2fs_cpu_to_be16(JBD2_FLAG_LAST_TAG);
362*6a54128fSAndroid Build Coastguard Worker if (*((__u32 *)buf) == ext2fs_cpu_to_be32(JBD2_MAGIC_NUMBER)) {
363*6a54128fSAndroid Build Coastguard Worker *((__u32 *)buf) = 0;
364*6a54128fSAndroid Build Coastguard Worker jdbt->t_flags |= ext2fs_cpu_to_be16(JBD2_FLAG_ESCAPE);
365*6a54128fSAndroid Build Coastguard Worker }
366*6a54128fSAndroid Build Coastguard Worker if (jbd2_has_feature_64bit(trans->journal))
367*6a54128fSAndroid Build Coastguard Worker jdbt->t_blocknr_high = ext2fs_cpu_to_be32(block_list[i] >> 32);
368*6a54128fSAndroid Build Coastguard Worker jbd2_block_tag_csum_set(trans->journal, jdbt, data_bh,
369*6a54128fSAndroid Build Coastguard Worker trans->tid);
370*6a54128fSAndroid Build Coastguard Worker
371*6a54128fSAndroid Build Coastguard Worker /* Write the data block */
372*6a54128fSAndroid Build Coastguard Worker err = jbd2_journal_bmap(trans->journal, curr_blk,
373*6a54128fSAndroid Build Coastguard Worker &data_bh->b_blocknr);
374*6a54128fSAndroid Build Coastguard Worker if (err)
375*6a54128fSAndroid Build Coastguard Worker goto error;
376*6a54128fSAndroid Build Coastguard Worker dbg_printf("Writing data block %llu at %llu:%llu tag %d\n",
377*6a54128fSAndroid Build Coastguard Worker block_list[i], curr_blk, data_bh->b_blocknr,
378*6a54128fSAndroid Build Coastguard Worker tag_bytes);
379*6a54128fSAndroid Build Coastguard Worker mark_buffer_dirty(data_bh);
380*6a54128fSAndroid Build Coastguard Worker ll_rw_block(REQ_OP_WRITE, 0, 1, &data_bh);
381*6a54128fSAndroid Build Coastguard Worker err = data_bh->b_err;
382*6a54128fSAndroid Build Coastguard Worker if (err)
383*6a54128fSAndroid Build Coastguard Worker goto error;
384*6a54128fSAndroid Build Coastguard Worker
385*6a54128fSAndroid Build Coastguard Worker curr_blk++;
386*6a54128fSAndroid Build Coastguard Worker jdbt = (journal_block_tag_t *)(((char *)jdbt) + tag_bytes);
387*6a54128fSAndroid Build Coastguard Worker }
388*6a54128fSAndroid Build Coastguard Worker
389*6a54128fSAndroid Build Coastguard Worker /* Write out the last descriptor block */
390*6a54128fSAndroid Build Coastguard Worker if (jdbt != (journal_block_tag_t *)(jdb + 1)) {
391*6a54128fSAndroid Build Coastguard Worker jbd2_descr_block_csum_set(trans->journal, bh);
392*6a54128fSAndroid Build Coastguard Worker err = jbd2_journal_bmap(trans->journal, jdb_blk,
393*6a54128fSAndroid Build Coastguard Worker &bh->b_blocknr);
394*6a54128fSAndroid Build Coastguard Worker if (err)
395*6a54128fSAndroid Build Coastguard Worker goto error;
396*6a54128fSAndroid Build Coastguard Worker dbg_printf("Writing descriptor block at %llu:%llu\n",
397*6a54128fSAndroid Build Coastguard Worker jdb_blk, bh->b_blocknr);
398*6a54128fSAndroid Build Coastguard Worker mark_buffer_dirty(bh);
399*6a54128fSAndroid Build Coastguard Worker ll_rw_block(REQ_OP_WRITE, 0, 1, &bh);
400*6a54128fSAndroid Build Coastguard Worker err = bh->b_err;
401*6a54128fSAndroid Build Coastguard Worker if (err)
402*6a54128fSAndroid Build Coastguard Worker goto error;
403*6a54128fSAndroid Build Coastguard Worker }
404*6a54128fSAndroid Build Coastguard Worker
405*6a54128fSAndroid Build Coastguard Worker error:
406*6a54128fSAndroid Build Coastguard Worker trans->block = curr_blk;
407*6a54128fSAndroid Build Coastguard Worker if (bh)
408*6a54128fSAndroid Build Coastguard Worker brelse(bh);
409*6a54128fSAndroid Build Coastguard Worker brelse(data_bh);
410*6a54128fSAndroid Build Coastguard Worker return err;
411*6a54128fSAndroid Build Coastguard Worker }
412*6a54128fSAndroid Build Coastguard Worker
journal_guess_blocks(journal_t * journal,blk64_t data_blocks,blk64_t revoke_blocks)413*6a54128fSAndroid Build Coastguard Worker static blk64_t journal_guess_blocks(journal_t *journal, blk64_t data_blocks,
414*6a54128fSAndroid Build Coastguard Worker blk64_t revoke_blocks)
415*6a54128fSAndroid Build Coastguard Worker {
416*6a54128fSAndroid Build Coastguard Worker blk64_t ret = 1;
417*6a54128fSAndroid Build Coastguard Worker unsigned int bs, sz;
418*6a54128fSAndroid Build Coastguard Worker
419*6a54128fSAndroid Build Coastguard Worker /* Estimate # of revoke blocks */
420*6a54128fSAndroid Build Coastguard Worker bs = journal->j_blocksize;
421*6a54128fSAndroid Build Coastguard Worker if (jbd2_journal_has_csum_v2or3(journal))
422*6a54128fSAndroid Build Coastguard Worker bs -= sizeof(struct jbd2_journal_block_tail);
423*6a54128fSAndroid Build Coastguard Worker sz = jbd2_has_feature_64bit(journal) ? sizeof(__u64) : sizeof(__u32);
424*6a54128fSAndroid Build Coastguard Worker ret += revoke_blocks * sz / bs;
425*6a54128fSAndroid Build Coastguard Worker
426*6a54128fSAndroid Build Coastguard Worker /* Estimate # of data blocks */
427*6a54128fSAndroid Build Coastguard Worker bs = journal->j_blocksize - 16;
428*6a54128fSAndroid Build Coastguard Worker if (jbd2_journal_has_csum_v2or3(journal))
429*6a54128fSAndroid Build Coastguard Worker bs -= sizeof(struct jbd2_journal_block_tail);
430*6a54128fSAndroid Build Coastguard Worker sz = journal_tag_bytes(journal);
431*6a54128fSAndroid Build Coastguard Worker ret += data_blocks * sz / bs;
432*6a54128fSAndroid Build Coastguard Worker
433*6a54128fSAndroid Build Coastguard Worker ret += data_blocks;
434*6a54128fSAndroid Build Coastguard Worker
435*6a54128fSAndroid Build Coastguard Worker return ret;
436*6a54128fSAndroid Build Coastguard Worker }
437*6a54128fSAndroid Build Coastguard Worker
journal_open_trans(journal_t * journal,journal_transaction_t * trans,blk64_t blocks)438*6a54128fSAndroid Build Coastguard Worker static errcode_t journal_open_trans(journal_t *journal,
439*6a54128fSAndroid Build Coastguard Worker journal_transaction_t *trans,
440*6a54128fSAndroid Build Coastguard Worker blk64_t blocks)
441*6a54128fSAndroid Build Coastguard Worker {
442*6a54128fSAndroid Build Coastguard Worker trans->fs = journal->j_fs_dev->k_fs;
443*6a54128fSAndroid Build Coastguard Worker trans->journal = journal;
444*6a54128fSAndroid Build Coastguard Worker trans->flags = J_TRANS_OPEN;
445*6a54128fSAndroid Build Coastguard Worker
446*6a54128fSAndroid Build Coastguard Worker if (journal->j_tail == 0) {
447*6a54128fSAndroid Build Coastguard Worker /* Clean journal, start at the tail */
448*6a54128fSAndroid Build Coastguard Worker trans->tid = journal->j_tail_sequence;
449*6a54128fSAndroid Build Coastguard Worker trans->start = journal->j_first;
450*6a54128fSAndroid Build Coastguard Worker } else {
451*6a54128fSAndroid Build Coastguard Worker /* Put new transaction at the head of the list */
452*6a54128fSAndroid Build Coastguard Worker trans->tid = journal->j_transaction_sequence;
453*6a54128fSAndroid Build Coastguard Worker trans->start = journal->j_head;
454*6a54128fSAndroid Build Coastguard Worker }
455*6a54128fSAndroid Build Coastguard Worker
456*6a54128fSAndroid Build Coastguard Worker trans->block = trans->start;
457*6a54128fSAndroid Build Coastguard Worker if (trans->start + blocks > journal->j_last)
458*6a54128fSAndroid Build Coastguard Worker return ENOSPC;
459*6a54128fSAndroid Build Coastguard Worker trans->end = trans->block + blocks;
460*6a54128fSAndroid Build Coastguard Worker journal_dump_trans(trans, "new transaction");
461*6a54128fSAndroid Build Coastguard Worker
462*6a54128fSAndroid Build Coastguard Worker trans->magic = J_TRANS_MAGIC;
463*6a54128fSAndroid Build Coastguard Worker return 0;
464*6a54128fSAndroid Build Coastguard Worker }
465*6a54128fSAndroid Build Coastguard Worker
journal_close_trans(journal_transaction_t * trans)466*6a54128fSAndroid Build Coastguard Worker static errcode_t journal_close_trans(journal_transaction_t *trans)
467*6a54128fSAndroid Build Coastguard Worker {
468*6a54128fSAndroid Build Coastguard Worker journal_t *journal;
469*6a54128fSAndroid Build Coastguard Worker
470*6a54128fSAndroid Build Coastguard Worker JOURNAL_CHECK_TRANS_MAGIC(trans);
471*6a54128fSAndroid Build Coastguard Worker
472*6a54128fSAndroid Build Coastguard Worker if (!(trans->flags & J_TRANS_COMMITTED))
473*6a54128fSAndroid Build Coastguard Worker return 0;
474*6a54128fSAndroid Build Coastguard Worker
475*6a54128fSAndroid Build Coastguard Worker journal = trans->journal;
476*6a54128fSAndroid Build Coastguard Worker if (journal->j_tail == 0) {
477*6a54128fSAndroid Build Coastguard Worker /* Update the tail */
478*6a54128fSAndroid Build Coastguard Worker journal->j_tail_sequence = trans->tid;
479*6a54128fSAndroid Build Coastguard Worker journal->j_tail = trans->start;
480*6a54128fSAndroid Build Coastguard Worker journal->j_superblock->s_start = ext2fs_cpu_to_be32(trans->start);
481*6a54128fSAndroid Build Coastguard Worker }
482*6a54128fSAndroid Build Coastguard Worker
483*6a54128fSAndroid Build Coastguard Worker /* Update the head */
484*6a54128fSAndroid Build Coastguard Worker journal->j_head = trans->end + 1;
485*6a54128fSAndroid Build Coastguard Worker journal->j_transaction_sequence = trans->tid + 1;
486*6a54128fSAndroid Build Coastguard Worker
487*6a54128fSAndroid Build Coastguard Worker trans->magic = 0;
488*6a54128fSAndroid Build Coastguard Worker
489*6a54128fSAndroid Build Coastguard Worker /* Mark ourselves as needing recovery */
490*6a54128fSAndroid Build Coastguard Worker if (!ext2fs_has_feature_journal_needs_recovery(trans->fs->super)) {
491*6a54128fSAndroid Build Coastguard Worker ext2fs_set_feature_journal_needs_recovery(trans->fs->super);
492*6a54128fSAndroid Build Coastguard Worker ext2fs_mark_super_dirty(trans->fs);
493*6a54128fSAndroid Build Coastguard Worker }
494*6a54128fSAndroid Build Coastguard Worker
495*6a54128fSAndroid Build Coastguard Worker return 0;
496*6a54128fSAndroid Build Coastguard Worker }
497*6a54128fSAndroid Build Coastguard Worker
498*6a54128fSAndroid Build Coastguard Worker #define JOURNAL_WRITE_NO_COMMIT 1
journal_write(journal_t * journal,int flags,blk64_t * block_list,size_t block_len,blk64_t * revoke_list,size_t revoke_len,FILE * fp)499*6a54128fSAndroid Build Coastguard Worker static errcode_t journal_write(journal_t *journal,
500*6a54128fSAndroid Build Coastguard Worker int flags, blk64_t *block_list,
501*6a54128fSAndroid Build Coastguard Worker size_t block_len, blk64_t *revoke_list,
502*6a54128fSAndroid Build Coastguard Worker size_t revoke_len, FILE *fp)
503*6a54128fSAndroid Build Coastguard Worker {
504*6a54128fSAndroid Build Coastguard Worker blk64_t blocks;
505*6a54128fSAndroid Build Coastguard Worker journal_transaction_t trans;
506*6a54128fSAndroid Build Coastguard Worker errcode_t err;
507*6a54128fSAndroid Build Coastguard Worker
508*6a54128fSAndroid Build Coastguard Worker if (revoke_len > 0) {
509*6a54128fSAndroid Build Coastguard Worker jbd2_set_feature_revoke(journal);
510*6a54128fSAndroid Build Coastguard Worker mark_buffer_dirty(journal->j_sb_buffer);
511*6a54128fSAndroid Build Coastguard Worker }
512*6a54128fSAndroid Build Coastguard Worker
513*6a54128fSAndroid Build Coastguard Worker blocks = journal_guess_blocks(journal, block_len, revoke_len);
514*6a54128fSAndroid Build Coastguard Worker err = journal_open_trans(journal, &trans, blocks);
515*6a54128fSAndroid Build Coastguard Worker if (err)
516*6a54128fSAndroid Build Coastguard Worker goto error;
517*6a54128fSAndroid Build Coastguard Worker
518*6a54128fSAndroid Build Coastguard Worker err = journal_add_blocks_to_trans(&trans, block_list, block_len, fp);
519*6a54128fSAndroid Build Coastguard Worker if (err)
520*6a54128fSAndroid Build Coastguard Worker goto error;
521*6a54128fSAndroid Build Coastguard Worker
522*6a54128fSAndroid Build Coastguard Worker err = journal_add_revoke_to_trans(&trans, revoke_list, revoke_len);
523*6a54128fSAndroid Build Coastguard Worker if (err)
524*6a54128fSAndroid Build Coastguard Worker goto error;
525*6a54128fSAndroid Build Coastguard Worker
526*6a54128fSAndroid Build Coastguard Worker if (!(flags & JOURNAL_WRITE_NO_COMMIT)) {
527*6a54128fSAndroid Build Coastguard Worker err = journal_commit_trans(&trans);
528*6a54128fSAndroid Build Coastguard Worker if (err)
529*6a54128fSAndroid Build Coastguard Worker goto error;
530*6a54128fSAndroid Build Coastguard Worker }
531*6a54128fSAndroid Build Coastguard Worker
532*6a54128fSAndroid Build Coastguard Worker err = journal_close_trans(&trans);
533*6a54128fSAndroid Build Coastguard Worker error:
534*6a54128fSAndroid Build Coastguard Worker return err;
535*6a54128fSAndroid Build Coastguard Worker }
536*6a54128fSAndroid Build Coastguard Worker
do_journal_write(int argc,char * argv[],int sci_idx EXT2FS_ATTR ((unused)),void * infop EXT2FS_ATTR ((unused)))537*6a54128fSAndroid Build Coastguard Worker void do_journal_write(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)),
538*6a54128fSAndroid Build Coastguard Worker void *infop EXT2FS_ATTR((unused)))
539*6a54128fSAndroid Build Coastguard Worker {
540*6a54128fSAndroid Build Coastguard Worker blk64_t *blist = NULL, *rlist = NULL;
541*6a54128fSAndroid Build Coastguard Worker size_t bn = 0, rn = 0;
542*6a54128fSAndroid Build Coastguard Worker FILE *fp = NULL;
543*6a54128fSAndroid Build Coastguard Worker int opt;
544*6a54128fSAndroid Build Coastguard Worker int flags = 0;
545*6a54128fSAndroid Build Coastguard Worker errcode_t err;
546*6a54128fSAndroid Build Coastguard Worker
547*6a54128fSAndroid Build Coastguard Worker if (current_journal == NULL) {
548*6a54128fSAndroid Build Coastguard Worker printf("Journal not open.\n");
549*6a54128fSAndroid Build Coastguard Worker return;
550*6a54128fSAndroid Build Coastguard Worker }
551*6a54128fSAndroid Build Coastguard Worker
552*6a54128fSAndroid Build Coastguard Worker reset_getopt();
553*6a54128fSAndroid Build Coastguard Worker while ((opt = getopt(argc, argv, "b:r:c")) != -1) {
554*6a54128fSAndroid Build Coastguard Worker switch (opt) {
555*6a54128fSAndroid Build Coastguard Worker case 'b':
556*6a54128fSAndroid Build Coastguard Worker err = read_list(optarg, &blist, &bn);
557*6a54128fSAndroid Build Coastguard Worker if (err) {
558*6a54128fSAndroid Build Coastguard Worker com_err(argv[0], err,
559*6a54128fSAndroid Build Coastguard Worker "while reading block list");
560*6a54128fSAndroid Build Coastguard Worker goto out;
561*6a54128fSAndroid Build Coastguard Worker }
562*6a54128fSAndroid Build Coastguard Worker break;
563*6a54128fSAndroid Build Coastguard Worker case 'r':
564*6a54128fSAndroid Build Coastguard Worker err = read_list(optarg, &rlist, &rn);
565*6a54128fSAndroid Build Coastguard Worker if (err) {
566*6a54128fSAndroid Build Coastguard Worker com_err(argv[0], err,
567*6a54128fSAndroid Build Coastguard Worker "while reading revoke list");
568*6a54128fSAndroid Build Coastguard Worker goto out;
569*6a54128fSAndroid Build Coastguard Worker }
570*6a54128fSAndroid Build Coastguard Worker break;
571*6a54128fSAndroid Build Coastguard Worker case 'c':
572*6a54128fSAndroid Build Coastguard Worker flags |= JOURNAL_WRITE_NO_COMMIT;
573*6a54128fSAndroid Build Coastguard Worker break;
574*6a54128fSAndroid Build Coastguard Worker default:
575*6a54128fSAndroid Build Coastguard Worker printf("%s [-b blocks] [-r revoke] [-c] file\n",
576*6a54128fSAndroid Build Coastguard Worker argv[0]);
577*6a54128fSAndroid Build Coastguard Worker printf("-b: Write these blocks into transaction.\n");
578*6a54128fSAndroid Build Coastguard Worker printf("-c: Do not commit transaction.\n");
579*6a54128fSAndroid Build Coastguard Worker printf("-r: Revoke these blocks from transaction.\n");
580*6a54128fSAndroid Build Coastguard Worker
581*6a54128fSAndroid Build Coastguard Worker goto out;
582*6a54128fSAndroid Build Coastguard Worker }
583*6a54128fSAndroid Build Coastguard Worker }
584*6a54128fSAndroid Build Coastguard Worker
585*6a54128fSAndroid Build Coastguard Worker if (bn > 0 && optind != argc - 1) {
586*6a54128fSAndroid Build Coastguard Worker printf("Need a file to read blocks from.\n");
587*6a54128fSAndroid Build Coastguard Worker return;
588*6a54128fSAndroid Build Coastguard Worker }
589*6a54128fSAndroid Build Coastguard Worker
590*6a54128fSAndroid Build Coastguard Worker if (bn > 0) {
591*6a54128fSAndroid Build Coastguard Worker fp = fopen(argv[optind], "r");
592*6a54128fSAndroid Build Coastguard Worker if (fp == NULL) {
593*6a54128fSAndroid Build Coastguard Worker com_err(argv[0], errno,
594*6a54128fSAndroid Build Coastguard Worker "while opening journal data file");
595*6a54128fSAndroid Build Coastguard Worker goto out;
596*6a54128fSAndroid Build Coastguard Worker }
597*6a54128fSAndroid Build Coastguard Worker }
598*6a54128fSAndroid Build Coastguard Worker
599*6a54128fSAndroid Build Coastguard Worker err = journal_write(current_journal, flags, blist, bn,
600*6a54128fSAndroid Build Coastguard Worker rlist, rn, fp);
601*6a54128fSAndroid Build Coastguard Worker if (err)
602*6a54128fSAndroid Build Coastguard Worker com_err("journal_write", err, "while writing journal");
603*6a54128fSAndroid Build Coastguard Worker
604*6a54128fSAndroid Build Coastguard Worker if (fp)
605*6a54128fSAndroid Build Coastguard Worker fclose(fp);
606*6a54128fSAndroid Build Coastguard Worker out:
607*6a54128fSAndroid Build Coastguard Worker if (blist)
608*6a54128fSAndroid Build Coastguard Worker free(blist);
609*6a54128fSAndroid Build Coastguard Worker if (rlist)
610*6a54128fSAndroid Build Coastguard Worker free(rlist);
611*6a54128fSAndroid Build Coastguard Worker }
612*6a54128fSAndroid Build Coastguard Worker
613*6a54128fSAndroid Build Coastguard Worker /* Make sure we wrap around the log correctly! */
614*6a54128fSAndroid Build Coastguard Worker #define wrap(journal, var) \
615*6a54128fSAndroid Build Coastguard Worker do { \
616*6a54128fSAndroid Build Coastguard Worker if (var >= (journal)->j_last) \
617*6a54128fSAndroid Build Coastguard Worker var -= ((journal)->j_last - (journal)->j_first); \
618*6a54128fSAndroid Build Coastguard Worker } while (0)
619*6a54128fSAndroid Build Coastguard Worker
620*6a54128fSAndroid Build Coastguard Worker /*
621*6a54128fSAndroid Build Coastguard Worker * Count the number of in-use tags in a journal descriptor block.
622*6a54128fSAndroid Build Coastguard Worker */
623*6a54128fSAndroid Build Coastguard Worker
count_tags(journal_t * journal,char * buf)624*6a54128fSAndroid Build Coastguard Worker static int count_tags(journal_t *journal, char *buf)
625*6a54128fSAndroid Build Coastguard Worker {
626*6a54128fSAndroid Build Coastguard Worker char *tagp;
627*6a54128fSAndroid Build Coastguard Worker journal_block_tag_t *tag;
628*6a54128fSAndroid Build Coastguard Worker int nr = 0, size = journal->j_blocksize;
629*6a54128fSAndroid Build Coastguard Worker int tag_bytes = journal_tag_bytes(journal);
630*6a54128fSAndroid Build Coastguard Worker
631*6a54128fSAndroid Build Coastguard Worker if (jbd2_journal_has_csum_v2or3(journal))
632*6a54128fSAndroid Build Coastguard Worker size -= sizeof(struct jbd2_journal_block_tail);
633*6a54128fSAndroid Build Coastguard Worker
634*6a54128fSAndroid Build Coastguard Worker tagp = buf + sizeof(journal_header_t);
635*6a54128fSAndroid Build Coastguard Worker
636*6a54128fSAndroid Build Coastguard Worker while ((tagp - buf + tag_bytes) <= size) {
637*6a54128fSAndroid Build Coastguard Worker tag = (journal_block_tag_t *) tagp;
638*6a54128fSAndroid Build Coastguard Worker
639*6a54128fSAndroid Build Coastguard Worker nr++;
640*6a54128fSAndroid Build Coastguard Worker tagp += tag_bytes;
641*6a54128fSAndroid Build Coastguard Worker if (!(tag->t_flags & ext2fs_cpu_to_be16(JBD2_FLAG_SAME_UUID)))
642*6a54128fSAndroid Build Coastguard Worker tagp += 16;
643*6a54128fSAndroid Build Coastguard Worker
644*6a54128fSAndroid Build Coastguard Worker if (tag->t_flags & ext2fs_cpu_to_be16(JBD2_FLAG_LAST_TAG))
645*6a54128fSAndroid Build Coastguard Worker break;
646*6a54128fSAndroid Build Coastguard Worker }
647*6a54128fSAndroid Build Coastguard Worker
648*6a54128fSAndroid Build Coastguard Worker return nr;
649*6a54128fSAndroid Build Coastguard Worker }
650*6a54128fSAndroid Build Coastguard Worker
journal_find_head(journal_t * journal)651*6a54128fSAndroid Build Coastguard Worker static errcode_t journal_find_head(journal_t *journal)
652*6a54128fSAndroid Build Coastguard Worker {
653*6a54128fSAndroid Build Coastguard Worker unsigned int next_commit_ID;
654*6a54128fSAndroid Build Coastguard Worker blk64_t next_log_block, head_block;
655*6a54128fSAndroid Build Coastguard Worker int err;
656*6a54128fSAndroid Build Coastguard Worker journal_superblock_t *sb;
657*6a54128fSAndroid Build Coastguard Worker journal_header_t *tmp;
658*6a54128fSAndroid Build Coastguard Worker struct buffer_head *bh;
659*6a54128fSAndroid Build Coastguard Worker unsigned int sequence;
660*6a54128fSAndroid Build Coastguard Worker int blocktype;
661*6a54128fSAndroid Build Coastguard Worker
662*6a54128fSAndroid Build Coastguard Worker /*
663*6a54128fSAndroid Build Coastguard Worker * First thing is to establish what we expect to find in the log
664*6a54128fSAndroid Build Coastguard Worker * (in terms of transaction IDs), and where (in terms of log
665*6a54128fSAndroid Build Coastguard Worker * block offsets): query the superblock.
666*6a54128fSAndroid Build Coastguard Worker */
667*6a54128fSAndroid Build Coastguard Worker
668*6a54128fSAndroid Build Coastguard Worker sb = journal->j_superblock;
669*6a54128fSAndroid Build Coastguard Worker next_commit_ID = ext2fs_be32_to_cpu(sb->s_sequence);
670*6a54128fSAndroid Build Coastguard Worker next_log_block = ext2fs_be32_to_cpu(sb->s_start);
671*6a54128fSAndroid Build Coastguard Worker head_block = next_log_block;
672*6a54128fSAndroid Build Coastguard Worker
673*6a54128fSAndroid Build Coastguard Worker if (next_log_block == 0)
674*6a54128fSAndroid Build Coastguard Worker return 0;
675*6a54128fSAndroid Build Coastguard Worker
676*6a54128fSAndroid Build Coastguard Worker bh = getblk(journal->j_dev, 0, journal->j_blocksize);
677*6a54128fSAndroid Build Coastguard Worker if (bh == NULL)
678*6a54128fSAndroid Build Coastguard Worker return ENOMEM;
679*6a54128fSAndroid Build Coastguard Worker
680*6a54128fSAndroid Build Coastguard Worker /*
681*6a54128fSAndroid Build Coastguard Worker * Now we walk through the log, transaction by transaction,
682*6a54128fSAndroid Build Coastguard Worker * making sure that each transaction has a commit block in the
683*6a54128fSAndroid Build Coastguard Worker * expected place. Each complete transaction gets replayed back
684*6a54128fSAndroid Build Coastguard Worker * into the main filesystem.
685*6a54128fSAndroid Build Coastguard Worker */
686*6a54128fSAndroid Build Coastguard Worker while (1) {
687*6a54128fSAndroid Build Coastguard Worker dbg_printf("Scanning for sequence ID %u at %lu/%lu\n",
688*6a54128fSAndroid Build Coastguard Worker next_commit_ID, (unsigned long)next_log_block,
689*6a54128fSAndroid Build Coastguard Worker journal->j_last);
690*6a54128fSAndroid Build Coastguard Worker
691*6a54128fSAndroid Build Coastguard Worker /* Skip over each chunk of the transaction looking
692*6a54128fSAndroid Build Coastguard Worker * either the next descriptor block or the final commit
693*6a54128fSAndroid Build Coastguard Worker * record. */
694*6a54128fSAndroid Build Coastguard Worker err = jbd2_journal_bmap(journal, next_log_block,
695*6a54128fSAndroid Build Coastguard Worker &bh->b_blocknr);
696*6a54128fSAndroid Build Coastguard Worker if (err)
697*6a54128fSAndroid Build Coastguard Worker goto err;
698*6a54128fSAndroid Build Coastguard Worker mark_buffer_uptodate(bh, 0);
699*6a54128fSAndroid Build Coastguard Worker ll_rw_block(REQ_OP_READ, 0, 1, &bh);
700*6a54128fSAndroid Build Coastguard Worker err = bh->b_err;
701*6a54128fSAndroid Build Coastguard Worker if (err)
702*6a54128fSAndroid Build Coastguard Worker goto err;
703*6a54128fSAndroid Build Coastguard Worker
704*6a54128fSAndroid Build Coastguard Worker next_log_block++;
705*6a54128fSAndroid Build Coastguard Worker wrap(journal, next_log_block);
706*6a54128fSAndroid Build Coastguard Worker
707*6a54128fSAndroid Build Coastguard Worker /* What kind of buffer is it?
708*6a54128fSAndroid Build Coastguard Worker *
709*6a54128fSAndroid Build Coastguard Worker * If it is a descriptor block, check that it has the
710*6a54128fSAndroid Build Coastguard Worker * expected sequence number. Otherwise, we're all done
711*6a54128fSAndroid Build Coastguard Worker * here. */
712*6a54128fSAndroid Build Coastguard Worker
713*6a54128fSAndroid Build Coastguard Worker tmp = (journal_header_t *)bh->b_data;
714*6a54128fSAndroid Build Coastguard Worker
715*6a54128fSAndroid Build Coastguard Worker if (tmp->h_magic != ext2fs_cpu_to_be32(JBD2_MAGIC_NUMBER)) {
716*6a54128fSAndroid Build Coastguard Worker dbg_printf("JBD2: wrong magic 0x%x\n", tmp->h_magic);
717*6a54128fSAndroid Build Coastguard Worker goto err;
718*6a54128fSAndroid Build Coastguard Worker }
719*6a54128fSAndroid Build Coastguard Worker
720*6a54128fSAndroid Build Coastguard Worker blocktype = ext2fs_be32_to_cpu(tmp->h_blocktype);
721*6a54128fSAndroid Build Coastguard Worker sequence = ext2fs_be32_to_cpu(tmp->h_sequence);
722*6a54128fSAndroid Build Coastguard Worker dbg_printf("Found magic %d, sequence %d\n",
723*6a54128fSAndroid Build Coastguard Worker blocktype, sequence);
724*6a54128fSAndroid Build Coastguard Worker
725*6a54128fSAndroid Build Coastguard Worker if (sequence != next_commit_ID) {
726*6a54128fSAndroid Build Coastguard Worker dbg_printf("JBD2: Wrong sequence %d (wanted %d)\n",
727*6a54128fSAndroid Build Coastguard Worker sequence, next_commit_ID);
728*6a54128fSAndroid Build Coastguard Worker goto err;
729*6a54128fSAndroid Build Coastguard Worker }
730*6a54128fSAndroid Build Coastguard Worker
731*6a54128fSAndroid Build Coastguard Worker /* OK, we have a valid descriptor block which matches
732*6a54128fSAndroid Build Coastguard Worker * all of the sequence number checks. What are we going
733*6a54128fSAndroid Build Coastguard Worker * to do with it? That depends on the pass... */
734*6a54128fSAndroid Build Coastguard Worker
735*6a54128fSAndroid Build Coastguard Worker switch (blocktype) {
736*6a54128fSAndroid Build Coastguard Worker case JBD2_DESCRIPTOR_BLOCK:
737*6a54128fSAndroid Build Coastguard Worker next_log_block += count_tags(journal, bh->b_data);
738*6a54128fSAndroid Build Coastguard Worker wrap(journal, next_log_block);
739*6a54128fSAndroid Build Coastguard Worker continue;
740*6a54128fSAndroid Build Coastguard Worker
741*6a54128fSAndroid Build Coastguard Worker case JBD2_COMMIT_BLOCK:
742*6a54128fSAndroid Build Coastguard Worker head_block = next_log_block;
743*6a54128fSAndroid Build Coastguard Worker next_commit_ID++;
744*6a54128fSAndroid Build Coastguard Worker continue;
745*6a54128fSAndroid Build Coastguard Worker
746*6a54128fSAndroid Build Coastguard Worker case JBD2_REVOKE_BLOCK:
747*6a54128fSAndroid Build Coastguard Worker continue;
748*6a54128fSAndroid Build Coastguard Worker
749*6a54128fSAndroid Build Coastguard Worker default:
750*6a54128fSAndroid Build Coastguard Worker dbg_printf("Unrecognised magic %d, end of scan.\n",
751*6a54128fSAndroid Build Coastguard Worker blocktype);
752*6a54128fSAndroid Build Coastguard Worker err = -EINVAL;
753*6a54128fSAndroid Build Coastguard Worker goto err;
754*6a54128fSAndroid Build Coastguard Worker }
755*6a54128fSAndroid Build Coastguard Worker }
756*6a54128fSAndroid Build Coastguard Worker
757*6a54128fSAndroid Build Coastguard Worker err:
758*6a54128fSAndroid Build Coastguard Worker if (err == 0) {
759*6a54128fSAndroid Build Coastguard Worker dbg_printf("head seq=%d blk=%llu\n", next_commit_ID,
760*6a54128fSAndroid Build Coastguard Worker head_block);
761*6a54128fSAndroid Build Coastguard Worker journal->j_transaction_sequence = next_commit_ID;
762*6a54128fSAndroid Build Coastguard Worker journal->j_head = head_block;
763*6a54128fSAndroid Build Coastguard Worker }
764*6a54128fSAndroid Build Coastguard Worker brelse(bh);
765*6a54128fSAndroid Build Coastguard Worker return err;
766*6a54128fSAndroid Build Coastguard Worker }
767*6a54128fSAndroid Build Coastguard Worker
update_journal_csum(journal_t * journal,int ver)768*6a54128fSAndroid Build Coastguard Worker static void update_journal_csum(journal_t *journal, int ver)
769*6a54128fSAndroid Build Coastguard Worker {
770*6a54128fSAndroid Build Coastguard Worker journal_superblock_t *jsb;
771*6a54128fSAndroid Build Coastguard Worker
772*6a54128fSAndroid Build Coastguard Worker if (journal->j_format_version < 2)
773*6a54128fSAndroid Build Coastguard Worker return;
774*6a54128fSAndroid Build Coastguard Worker
775*6a54128fSAndroid Build Coastguard Worker if (journal->j_tail != 0 ||
776*6a54128fSAndroid Build Coastguard Worker ext2fs_has_feature_journal_needs_recovery(
777*6a54128fSAndroid Build Coastguard Worker journal->j_fs_dev->k_fs->super)) {
778*6a54128fSAndroid Build Coastguard Worker printf("Journal needs recovery, will not add csums.\n");
779*6a54128fSAndroid Build Coastguard Worker return;
780*6a54128fSAndroid Build Coastguard Worker }
781*6a54128fSAndroid Build Coastguard Worker
782*6a54128fSAndroid Build Coastguard Worker /* metadata_csum implies journal csum v3 */
783*6a54128fSAndroid Build Coastguard Worker jsb = journal->j_superblock;
784*6a54128fSAndroid Build Coastguard Worker if (ext2fs_has_feature_metadata_csum(journal->j_fs_dev->k_fs->super)) {
785*6a54128fSAndroid Build Coastguard Worker printf("Setting csum v%d\n", ver);
786*6a54128fSAndroid Build Coastguard Worker switch (ver) {
787*6a54128fSAndroid Build Coastguard Worker case 2:
788*6a54128fSAndroid Build Coastguard Worker jbd2_clear_feature_csum3(journal);
789*6a54128fSAndroid Build Coastguard Worker jbd2_set_feature_csum2(journal);
790*6a54128fSAndroid Build Coastguard Worker jbd2_clear_feature_checksum(journal);
791*6a54128fSAndroid Build Coastguard Worker break;
792*6a54128fSAndroid Build Coastguard Worker case 3:
793*6a54128fSAndroid Build Coastguard Worker jbd2_set_feature_csum3(journal);
794*6a54128fSAndroid Build Coastguard Worker jbd2_clear_feature_csum2(journal);
795*6a54128fSAndroid Build Coastguard Worker jbd2_clear_feature_checksum(journal);
796*6a54128fSAndroid Build Coastguard Worker break;
797*6a54128fSAndroid Build Coastguard Worker default:
798*6a54128fSAndroid Build Coastguard Worker printf("Unknown checksum v%d\n", ver);
799*6a54128fSAndroid Build Coastguard Worker break;
800*6a54128fSAndroid Build Coastguard Worker }
801*6a54128fSAndroid Build Coastguard Worker journal->j_superblock->s_checksum_type = JBD2_CRC32C_CHKSUM;
802*6a54128fSAndroid Build Coastguard Worker journal->j_csum_seed = jbd2_chksum(journal, ~0, jsb->s_uuid,
803*6a54128fSAndroid Build Coastguard Worker sizeof(jsb->s_uuid));
804*6a54128fSAndroid Build Coastguard Worker } else {
805*6a54128fSAndroid Build Coastguard Worker jbd2_clear_feature_csum3(journal);
806*6a54128fSAndroid Build Coastguard Worker jbd2_clear_feature_csum2(journal);
807*6a54128fSAndroid Build Coastguard Worker jbd2_set_feature_checksum(journal);
808*6a54128fSAndroid Build Coastguard Worker }
809*6a54128fSAndroid Build Coastguard Worker }
810*6a54128fSAndroid Build Coastguard Worker
update_uuid(journal_t * journal)811*6a54128fSAndroid Build Coastguard Worker static void update_uuid(journal_t *journal)
812*6a54128fSAndroid Build Coastguard Worker {
813*6a54128fSAndroid Build Coastguard Worker size_t z;
814*6a54128fSAndroid Build Coastguard Worker ext2_filsys fs;
815*6a54128fSAndroid Build Coastguard Worker
816*6a54128fSAndroid Build Coastguard Worker if (journal->j_format_version < 2)
817*6a54128fSAndroid Build Coastguard Worker return;
818*6a54128fSAndroid Build Coastguard Worker
819*6a54128fSAndroid Build Coastguard Worker for (z = 0; z < sizeof(journal->j_superblock->s_uuid); z++)
820*6a54128fSAndroid Build Coastguard Worker if (journal->j_superblock->s_uuid[z])
821*6a54128fSAndroid Build Coastguard Worker break;
822*6a54128fSAndroid Build Coastguard Worker if (z == 0)
823*6a54128fSAndroid Build Coastguard Worker return;
824*6a54128fSAndroid Build Coastguard Worker
825*6a54128fSAndroid Build Coastguard Worker fs = journal->j_fs_dev->k_fs;
826*6a54128fSAndroid Build Coastguard Worker if (!ext2fs_has_feature_64bit(fs->super))
827*6a54128fSAndroid Build Coastguard Worker return;
828*6a54128fSAndroid Build Coastguard Worker
829*6a54128fSAndroid Build Coastguard Worker if (jbd2_has_feature_64bit(journal) &&
830*6a54128fSAndroid Build Coastguard Worker ext2fs_has_feature_64bit(fs->super))
831*6a54128fSAndroid Build Coastguard Worker return;
832*6a54128fSAndroid Build Coastguard Worker
833*6a54128fSAndroid Build Coastguard Worker if (journal->j_tail != 0 ||
834*6a54128fSAndroid Build Coastguard Worker ext2fs_has_feature_journal_needs_recovery(fs->super)) {
835*6a54128fSAndroid Build Coastguard Worker printf("Journal needs recovery, will not set 64bit.\n");
836*6a54128fSAndroid Build Coastguard Worker return;
837*6a54128fSAndroid Build Coastguard Worker }
838*6a54128fSAndroid Build Coastguard Worker
839*6a54128fSAndroid Build Coastguard Worker memcpy(journal->j_superblock->s_uuid, fs->super->s_uuid,
840*6a54128fSAndroid Build Coastguard Worker sizeof(fs->super->s_uuid));
841*6a54128fSAndroid Build Coastguard Worker }
842*6a54128fSAndroid Build Coastguard Worker
update_64bit_flag(journal_t * journal)843*6a54128fSAndroid Build Coastguard Worker static void update_64bit_flag(journal_t *journal)
844*6a54128fSAndroid Build Coastguard Worker {
845*6a54128fSAndroid Build Coastguard Worker if (journal->j_format_version < 2)
846*6a54128fSAndroid Build Coastguard Worker return;
847*6a54128fSAndroid Build Coastguard Worker
848*6a54128fSAndroid Build Coastguard Worker if (!ext2fs_has_feature_64bit(journal->j_fs_dev->k_fs->super))
849*6a54128fSAndroid Build Coastguard Worker return;
850*6a54128fSAndroid Build Coastguard Worker
851*6a54128fSAndroid Build Coastguard Worker if (jbd2_has_feature_64bit(journal) &&
852*6a54128fSAndroid Build Coastguard Worker ext2fs_has_feature_64bit(journal->j_fs_dev->k_fs->super))
853*6a54128fSAndroid Build Coastguard Worker return;
854*6a54128fSAndroid Build Coastguard Worker
855*6a54128fSAndroid Build Coastguard Worker if (journal->j_tail != 0 ||
856*6a54128fSAndroid Build Coastguard Worker ext2fs_has_feature_journal_needs_recovery(
857*6a54128fSAndroid Build Coastguard Worker journal->j_fs_dev->k_fs->super)) {
858*6a54128fSAndroid Build Coastguard Worker printf("Journal needs recovery, will not set 64bit.\n");
859*6a54128fSAndroid Build Coastguard Worker return;
860*6a54128fSAndroid Build Coastguard Worker }
861*6a54128fSAndroid Build Coastguard Worker
862*6a54128fSAndroid Build Coastguard Worker jbd2_set_feature_64bit(journal);
863*6a54128fSAndroid Build Coastguard Worker }
864*6a54128fSAndroid Build Coastguard Worker
do_journal_open(int argc,char * argv[],int sci_idx EXT2FS_ATTR ((unused)),void * infop EXT2FS_ATTR ((unused)))865*6a54128fSAndroid Build Coastguard Worker void do_journal_open(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)),
866*6a54128fSAndroid Build Coastguard Worker void *infop EXT2FS_ATTR((unused)))
867*6a54128fSAndroid Build Coastguard Worker {
868*6a54128fSAndroid Build Coastguard Worker int opt, enable_csum = 0, csum_ver = 3;
869*6a54128fSAndroid Build Coastguard Worker journal_t *journal;
870*6a54128fSAndroid Build Coastguard Worker errcode_t err;
871*6a54128fSAndroid Build Coastguard Worker
872*6a54128fSAndroid Build Coastguard Worker if (check_fs_open(argv[0]))
873*6a54128fSAndroid Build Coastguard Worker return;
874*6a54128fSAndroid Build Coastguard Worker if (check_fs_read_write(argv[0]))
875*6a54128fSAndroid Build Coastguard Worker return;
876*6a54128fSAndroid Build Coastguard Worker if (check_fs_bitmaps(argv[0]))
877*6a54128fSAndroid Build Coastguard Worker return;
878*6a54128fSAndroid Build Coastguard Worker if (current_journal) {
879*6a54128fSAndroid Build Coastguard Worker printf("Journal is already open.\n");
880*6a54128fSAndroid Build Coastguard Worker return;
881*6a54128fSAndroid Build Coastguard Worker }
882*6a54128fSAndroid Build Coastguard Worker if (!ext2fs_has_feature_journal(current_fs->super)) {
883*6a54128fSAndroid Build Coastguard Worker printf("Journalling is not enabled on this filesystem.\n");
884*6a54128fSAndroid Build Coastguard Worker return;
885*6a54128fSAndroid Build Coastguard Worker }
886*6a54128fSAndroid Build Coastguard Worker
887*6a54128fSAndroid Build Coastguard Worker reset_getopt();
888*6a54128fSAndroid Build Coastguard Worker while ((opt = getopt(argc, argv, "cv:f:")) != -1) {
889*6a54128fSAndroid Build Coastguard Worker switch (opt) {
890*6a54128fSAndroid Build Coastguard Worker case 'c':
891*6a54128fSAndroid Build Coastguard Worker enable_csum = 1;
892*6a54128fSAndroid Build Coastguard Worker break;
893*6a54128fSAndroid Build Coastguard Worker case 'f':
894*6a54128fSAndroid Build Coastguard Worker if (current_fs->journal_name)
895*6a54128fSAndroid Build Coastguard Worker free(current_fs->journal_name);
896*6a54128fSAndroid Build Coastguard Worker current_fs->journal_name = strdup(optarg);
897*6a54128fSAndroid Build Coastguard Worker break;
898*6a54128fSAndroid Build Coastguard Worker case 'v':
899*6a54128fSAndroid Build Coastguard Worker csum_ver = atoi(optarg);
900*6a54128fSAndroid Build Coastguard Worker if (csum_ver != 2 && csum_ver != 3) {
901*6a54128fSAndroid Build Coastguard Worker printf("Unknown journal csum v%d\n", csum_ver);
902*6a54128fSAndroid Build Coastguard Worker csum_ver = 3;
903*6a54128fSAndroid Build Coastguard Worker }
904*6a54128fSAndroid Build Coastguard Worker break;
905*6a54128fSAndroid Build Coastguard Worker default:
906*6a54128fSAndroid Build Coastguard Worker printf("%s: [-c] [-v ver] [-f ext_jnl]\n", argv[0]);
907*6a54128fSAndroid Build Coastguard Worker printf("-c: Enable journal checksumming.\n");
908*6a54128fSAndroid Build Coastguard Worker printf("-v: Use this version checksum format.\n");
909*6a54128fSAndroid Build Coastguard Worker printf("-f: Load this external journal.\n");
910*6a54128fSAndroid Build Coastguard Worker }
911*6a54128fSAndroid Build Coastguard Worker }
912*6a54128fSAndroid Build Coastguard Worker
913*6a54128fSAndroid Build Coastguard Worker err = ext2fs_open_journal(current_fs, ¤t_journal);
914*6a54128fSAndroid Build Coastguard Worker if (err) {
915*6a54128fSAndroid Build Coastguard Worker com_err(argv[0], err, "while opening journal");
916*6a54128fSAndroid Build Coastguard Worker return;
917*6a54128fSAndroid Build Coastguard Worker }
918*6a54128fSAndroid Build Coastguard Worker journal = current_journal;
919*6a54128fSAndroid Build Coastguard Worker
920*6a54128fSAndroid Build Coastguard Worker dbg_printf("JOURNAL: seq=%u tailseq=%u start=%lu first=%lu "
921*6a54128fSAndroid Build Coastguard Worker "maxlen=%lu\n", journal->j_tail_sequence,
922*6a54128fSAndroid Build Coastguard Worker journal->j_transaction_sequence, journal->j_tail,
923*6a54128fSAndroid Build Coastguard Worker journal->j_first, journal->j_last);
924*6a54128fSAndroid Build Coastguard Worker
925*6a54128fSAndroid Build Coastguard Worker update_uuid(journal);
926*6a54128fSAndroid Build Coastguard Worker update_64bit_flag(journal);
927*6a54128fSAndroid Build Coastguard Worker if (enable_csum)
928*6a54128fSAndroid Build Coastguard Worker update_journal_csum(journal, csum_ver);
929*6a54128fSAndroid Build Coastguard Worker
930*6a54128fSAndroid Build Coastguard Worker err = journal_find_head(journal);
931*6a54128fSAndroid Build Coastguard Worker if (err)
932*6a54128fSAndroid Build Coastguard Worker com_err(argv[0], err, "while examining journal");
933*6a54128fSAndroid Build Coastguard Worker }
934*6a54128fSAndroid Build Coastguard Worker
do_journal_close(int argc EXT2FS_ATTR ((unused)),char * argv[]EXT2FS_ATTR ((unused)),int sci_idx EXT2FS_ATTR ((unused)),void * infop EXT2FS_ATTR ((unused)))935*6a54128fSAndroid Build Coastguard Worker void do_journal_close(int argc EXT2FS_ATTR((unused)),
936*6a54128fSAndroid Build Coastguard Worker char *argv[] EXT2FS_ATTR((unused)),
937*6a54128fSAndroid Build Coastguard Worker int sci_idx EXT2FS_ATTR((unused)),
938*6a54128fSAndroid Build Coastguard Worker void *infop EXT2FS_ATTR((unused)))
939*6a54128fSAndroid Build Coastguard Worker {
940*6a54128fSAndroid Build Coastguard Worker if (current_journal == NULL) {
941*6a54128fSAndroid Build Coastguard Worker printf("Journal not open.\n");
942*6a54128fSAndroid Build Coastguard Worker return;
943*6a54128fSAndroid Build Coastguard Worker }
944*6a54128fSAndroid Build Coastguard Worker
945*6a54128fSAndroid Build Coastguard Worker ext2fs_close_journal(current_fs, ¤t_journal);
946*6a54128fSAndroid Build Coastguard Worker }
947*6a54128fSAndroid Build Coastguard Worker
do_journal_run(int argc EXT2FS_ATTR ((unused)),char * argv[],int sci_idx EXT2FS_ATTR ((unused)),void * infop EXT2FS_ATTR ((unused)))948*6a54128fSAndroid Build Coastguard Worker void do_journal_run(int argc EXT2FS_ATTR((unused)), char *argv[],
949*6a54128fSAndroid Build Coastguard Worker int sci_idx EXT2FS_ATTR((unused)),
950*6a54128fSAndroid Build Coastguard Worker void *infop EXT2FS_ATTR((unused)))
951*6a54128fSAndroid Build Coastguard Worker {
952*6a54128fSAndroid Build Coastguard Worker errcode_t err;
953*6a54128fSAndroid Build Coastguard Worker
954*6a54128fSAndroid Build Coastguard Worker if (check_fs_open(argv[0]))
955*6a54128fSAndroid Build Coastguard Worker return;
956*6a54128fSAndroid Build Coastguard Worker if (check_fs_read_write(argv[0]))
957*6a54128fSAndroid Build Coastguard Worker return;
958*6a54128fSAndroid Build Coastguard Worker if (check_fs_bitmaps(argv[0]))
959*6a54128fSAndroid Build Coastguard Worker return;
960*6a54128fSAndroid Build Coastguard Worker if (current_journal) {
961*6a54128fSAndroid Build Coastguard Worker printf("Please close the journal before recovering it.\n");
962*6a54128fSAndroid Build Coastguard Worker return;
963*6a54128fSAndroid Build Coastguard Worker }
964*6a54128fSAndroid Build Coastguard Worker
965*6a54128fSAndroid Build Coastguard Worker err = ext2fs_run_ext3_journal(¤t_fs);
966*6a54128fSAndroid Build Coastguard Worker if (err)
967*6a54128fSAndroid Build Coastguard Worker com_err("journal_run", err, "while recovering journal");
968*6a54128fSAndroid Build Coastguard Worker else {
969*6a54128fSAndroid Build Coastguard Worker ext2fs_clear_feature_journal_needs_recovery(current_fs->super);
970*6a54128fSAndroid Build Coastguard Worker ext2fs_mark_super_dirty(current_fs);
971*6a54128fSAndroid Build Coastguard Worker }
972*6a54128fSAndroid Build Coastguard Worker }
973