xref: /openbmc/linux/fs/gfs2/recovery.c (revision b3b94faa5fe5968827ba0640ee9fba4b3e7f736e)
1*b3b94faaSDavid Teigland /*
2*b3b94faaSDavid Teigland  * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
3*b3b94faaSDavid Teigland  * Copyright (C) 2004-2005 Red Hat, Inc.  All rights reserved.
4*b3b94faaSDavid Teigland  *
5*b3b94faaSDavid Teigland  * This copyrighted material is made available to anyone wishing to use,
6*b3b94faaSDavid Teigland  * modify, copy, or redistribute it subject to the terms and conditions
7*b3b94faaSDavid Teigland  * of the GNU General Public License v.2.
8*b3b94faaSDavid Teigland  */
9*b3b94faaSDavid Teigland 
10*b3b94faaSDavid Teigland #include <linux/sched.h>
11*b3b94faaSDavid Teigland #include <linux/slab.h>
12*b3b94faaSDavid Teigland #include <linux/spinlock.h>
13*b3b94faaSDavid Teigland #include <linux/completion.h>
14*b3b94faaSDavid Teigland #include <linux/buffer_head.h>
15*b3b94faaSDavid Teigland #include <asm/semaphore.h>
16*b3b94faaSDavid Teigland 
17*b3b94faaSDavid Teigland #include "gfs2.h"
18*b3b94faaSDavid Teigland #include "bmap.h"
19*b3b94faaSDavid Teigland #include "glock.h"
20*b3b94faaSDavid Teigland #include "glops.h"
21*b3b94faaSDavid Teigland #include "lm.h"
22*b3b94faaSDavid Teigland #include "lops.h"
23*b3b94faaSDavid Teigland #include "meta_io.h"
24*b3b94faaSDavid Teigland #include "recovery.h"
25*b3b94faaSDavid Teigland #include "super.h"
26*b3b94faaSDavid Teigland 
27*b3b94faaSDavid Teigland int gfs2_replay_read_block(struct gfs2_jdesc *jd, unsigned int blk,
28*b3b94faaSDavid Teigland 			   struct buffer_head **bh)
29*b3b94faaSDavid Teigland {
30*b3b94faaSDavid Teigland 	struct gfs2_glock *gl = jd->jd_inode->i_gl;
31*b3b94faaSDavid Teigland 	int new = 0;
32*b3b94faaSDavid Teigland 	uint64_t dblock;
33*b3b94faaSDavid Teigland 	uint32_t extlen;
34*b3b94faaSDavid Teigland 	int error;
35*b3b94faaSDavid Teigland 
36*b3b94faaSDavid Teigland 	error = gfs2_block_map(jd->jd_inode, blk, &new, &dblock, &extlen);
37*b3b94faaSDavid Teigland 	if (error)
38*b3b94faaSDavid Teigland 		return error;
39*b3b94faaSDavid Teigland 	if (!dblock) {
40*b3b94faaSDavid Teigland 		gfs2_consist_inode(jd->jd_inode);
41*b3b94faaSDavid Teigland 		return -EIO;
42*b3b94faaSDavid Teigland 	}
43*b3b94faaSDavid Teigland 
44*b3b94faaSDavid Teigland 	gfs2_meta_ra(gl, dblock, extlen);
45*b3b94faaSDavid Teigland 	error = gfs2_meta_read(gl, dblock, DIO_START | DIO_WAIT, bh);
46*b3b94faaSDavid Teigland 
47*b3b94faaSDavid Teigland 	return error;
48*b3b94faaSDavid Teigland }
49*b3b94faaSDavid Teigland 
50*b3b94faaSDavid Teigland int gfs2_revoke_add(struct gfs2_sbd *sdp, uint64_t blkno, unsigned int where)
51*b3b94faaSDavid Teigland {
52*b3b94faaSDavid Teigland 	struct list_head *head = &sdp->sd_revoke_list;
53*b3b94faaSDavid Teigland 	struct gfs2_revoke_replay *rr;
54*b3b94faaSDavid Teigland 	int found = 0;
55*b3b94faaSDavid Teigland 
56*b3b94faaSDavid Teigland 	list_for_each_entry(rr, head, rr_list) {
57*b3b94faaSDavid Teigland 		if (rr->rr_blkno == blkno) {
58*b3b94faaSDavid Teigland 			found = 1;
59*b3b94faaSDavid Teigland 			break;
60*b3b94faaSDavid Teigland 		}
61*b3b94faaSDavid Teigland 	}
62*b3b94faaSDavid Teigland 
63*b3b94faaSDavid Teigland 	if (found) {
64*b3b94faaSDavid Teigland 		rr->rr_where = where;
65*b3b94faaSDavid Teigland 		return 0;
66*b3b94faaSDavid Teigland 	}
67*b3b94faaSDavid Teigland 
68*b3b94faaSDavid Teigland 	rr = kmalloc(sizeof(struct gfs2_revoke_replay), GFP_KERNEL);
69*b3b94faaSDavid Teigland 	if (!rr)
70*b3b94faaSDavid Teigland 		return -ENOMEM;
71*b3b94faaSDavid Teigland 
72*b3b94faaSDavid Teigland 	rr->rr_blkno = blkno;
73*b3b94faaSDavid Teigland 	rr->rr_where = where;
74*b3b94faaSDavid Teigland 	list_add(&rr->rr_list, head);
75*b3b94faaSDavid Teigland 
76*b3b94faaSDavid Teigland 	return 1;
77*b3b94faaSDavid Teigland }
78*b3b94faaSDavid Teigland 
79*b3b94faaSDavid Teigland int gfs2_revoke_check(struct gfs2_sbd *sdp, uint64_t blkno, unsigned int where)
80*b3b94faaSDavid Teigland {
81*b3b94faaSDavid Teigland 	struct gfs2_revoke_replay *rr;
82*b3b94faaSDavid Teigland 	int wrap, a, b, revoke;
83*b3b94faaSDavid Teigland 	int found = 0;
84*b3b94faaSDavid Teigland 
85*b3b94faaSDavid Teigland 	list_for_each_entry(rr, &sdp->sd_revoke_list, rr_list) {
86*b3b94faaSDavid Teigland 		if (rr->rr_blkno == blkno) {
87*b3b94faaSDavid Teigland 			found = 1;
88*b3b94faaSDavid Teigland 			break;
89*b3b94faaSDavid Teigland 		}
90*b3b94faaSDavid Teigland 	}
91*b3b94faaSDavid Teigland 
92*b3b94faaSDavid Teigland 	if (!found)
93*b3b94faaSDavid Teigland 		return 0;
94*b3b94faaSDavid Teigland 
95*b3b94faaSDavid Teigland 	wrap = (rr->rr_where < sdp->sd_replay_tail);
96*b3b94faaSDavid Teigland 	a = (sdp->sd_replay_tail < where);
97*b3b94faaSDavid Teigland 	b = (where < rr->rr_where);
98*b3b94faaSDavid Teigland 	revoke = (wrap) ? (a || b) : (a && b);
99*b3b94faaSDavid Teigland 
100*b3b94faaSDavid Teigland 	return revoke;
101*b3b94faaSDavid Teigland }
102*b3b94faaSDavid Teigland 
103*b3b94faaSDavid Teigland void gfs2_revoke_clean(struct gfs2_sbd *sdp)
104*b3b94faaSDavid Teigland {
105*b3b94faaSDavid Teigland 	struct list_head *head = &sdp->sd_revoke_list;
106*b3b94faaSDavid Teigland 	struct gfs2_revoke_replay *rr;
107*b3b94faaSDavid Teigland 
108*b3b94faaSDavid Teigland 	while (!list_empty(head)) {
109*b3b94faaSDavid Teigland 		rr = list_entry(head->next, struct gfs2_revoke_replay, rr_list);
110*b3b94faaSDavid Teigland 		list_del(&rr->rr_list);
111*b3b94faaSDavid Teigland 		kfree(rr);
112*b3b94faaSDavid Teigland 	}
113*b3b94faaSDavid Teigland }
114*b3b94faaSDavid Teigland 
115*b3b94faaSDavid Teigland /**
116*b3b94faaSDavid Teigland  * get_log_header - read the log header for a given segment
117*b3b94faaSDavid Teigland  * @jd: the journal
118*b3b94faaSDavid Teigland  * @blk: the block to look at
119*b3b94faaSDavid Teigland  * @lh: the log header to return
120*b3b94faaSDavid Teigland  *
121*b3b94faaSDavid Teigland  * Read the log header for a given segement in a given journal.  Do a few
122*b3b94faaSDavid Teigland  * sanity checks on it.
123*b3b94faaSDavid Teigland  *
124*b3b94faaSDavid Teigland  * Returns: 0 on success,
125*b3b94faaSDavid Teigland  *          1 if the header was invalid or incomplete,
126*b3b94faaSDavid Teigland  *          errno on error
127*b3b94faaSDavid Teigland  */
128*b3b94faaSDavid Teigland 
129*b3b94faaSDavid Teigland static int get_log_header(struct gfs2_jdesc *jd, unsigned int blk,
130*b3b94faaSDavid Teigland 			  struct gfs2_log_header *head)
131*b3b94faaSDavid Teigland {
132*b3b94faaSDavid Teigland 	struct buffer_head *bh;
133*b3b94faaSDavid Teigland 	struct gfs2_log_header lh;
134*b3b94faaSDavid Teigland 	uint32_t hash;
135*b3b94faaSDavid Teigland 	int error;
136*b3b94faaSDavid Teigland 
137*b3b94faaSDavid Teigland 	error = gfs2_replay_read_block(jd, blk, &bh);
138*b3b94faaSDavid Teigland 	if (error)
139*b3b94faaSDavid Teigland 		return error;
140*b3b94faaSDavid Teigland 
141*b3b94faaSDavid Teigland 	memcpy(&lh, bh->b_data, sizeof(struct gfs2_log_header));
142*b3b94faaSDavid Teigland 	lh.lh_hash = 0;
143*b3b94faaSDavid Teigland 	hash = gfs2_disk_hash((char *)&lh, sizeof(struct gfs2_log_header));
144*b3b94faaSDavid Teigland 	gfs2_log_header_in(&lh, bh->b_data);
145*b3b94faaSDavid Teigland 
146*b3b94faaSDavid Teigland 	brelse(bh);
147*b3b94faaSDavid Teigland 
148*b3b94faaSDavid Teigland 	if (lh.lh_header.mh_magic != GFS2_MAGIC ||
149*b3b94faaSDavid Teigland 	    lh.lh_header.mh_type != GFS2_METATYPE_LH ||
150*b3b94faaSDavid Teigland 	    lh.lh_blkno != blk ||
151*b3b94faaSDavid Teigland 	    lh.lh_hash != hash)
152*b3b94faaSDavid Teigland 		return 1;
153*b3b94faaSDavid Teigland 
154*b3b94faaSDavid Teigland 	*head = lh;
155*b3b94faaSDavid Teigland 
156*b3b94faaSDavid Teigland 	return 0;
157*b3b94faaSDavid Teigland }
158*b3b94faaSDavid Teigland 
159*b3b94faaSDavid Teigland /**
160*b3b94faaSDavid Teigland  * find_good_lh - find a good log header
161*b3b94faaSDavid Teigland  * @jd: the journal
162*b3b94faaSDavid Teigland  * @blk: the segment to start searching from
163*b3b94faaSDavid Teigland  * @lh: the log header to fill in
164*b3b94faaSDavid Teigland  * @forward: if true search forward in the log, else search backward
165*b3b94faaSDavid Teigland  *
166*b3b94faaSDavid Teigland  * Call get_log_header() to get a log header for a segment, but if the
167*b3b94faaSDavid Teigland  * segment is bad, either scan forward or backward until we find a good one.
168*b3b94faaSDavid Teigland  *
169*b3b94faaSDavid Teigland  * Returns: errno
170*b3b94faaSDavid Teigland  */
171*b3b94faaSDavid Teigland 
172*b3b94faaSDavid Teigland static int find_good_lh(struct gfs2_jdesc *jd, unsigned int *blk,
173*b3b94faaSDavid Teigland 			struct gfs2_log_header *head)
174*b3b94faaSDavid Teigland {
175*b3b94faaSDavid Teigland 	unsigned int orig_blk = *blk;
176*b3b94faaSDavid Teigland 	int error;
177*b3b94faaSDavid Teigland 
178*b3b94faaSDavid Teigland 	for (;;) {
179*b3b94faaSDavid Teigland 		error = get_log_header(jd, *blk, head);
180*b3b94faaSDavid Teigland 		if (error <= 0)
181*b3b94faaSDavid Teigland 			return error;
182*b3b94faaSDavid Teigland 
183*b3b94faaSDavid Teigland 		if (++*blk == jd->jd_blocks)
184*b3b94faaSDavid Teigland 			*blk = 0;
185*b3b94faaSDavid Teigland 
186*b3b94faaSDavid Teigland 		if (*blk == orig_blk) {
187*b3b94faaSDavid Teigland 			gfs2_consist_inode(jd->jd_inode);
188*b3b94faaSDavid Teigland 			return -EIO;
189*b3b94faaSDavid Teigland 		}
190*b3b94faaSDavid Teigland 	}
191*b3b94faaSDavid Teigland }
192*b3b94faaSDavid Teigland 
193*b3b94faaSDavid Teigland /**
194*b3b94faaSDavid Teigland  * jhead_scan - make sure we've found the head of the log
195*b3b94faaSDavid Teigland  * @jd: the journal
196*b3b94faaSDavid Teigland  * @head: this is filled in with the log descriptor of the head
197*b3b94faaSDavid Teigland  *
198*b3b94faaSDavid Teigland  * At this point, seg and lh should be either the head of the log or just
199*b3b94faaSDavid Teigland  * before.  Scan forward until we find the head.
200*b3b94faaSDavid Teigland  *
201*b3b94faaSDavid Teigland  * Returns: errno
202*b3b94faaSDavid Teigland  */
203*b3b94faaSDavid Teigland 
204*b3b94faaSDavid Teigland static int jhead_scan(struct gfs2_jdesc *jd, struct gfs2_log_header *head)
205*b3b94faaSDavid Teigland {
206*b3b94faaSDavid Teigland 	unsigned int blk = head->lh_blkno;
207*b3b94faaSDavid Teigland 	struct gfs2_log_header lh;
208*b3b94faaSDavid Teigland 	int error;
209*b3b94faaSDavid Teigland 
210*b3b94faaSDavid Teigland 	for (;;) {
211*b3b94faaSDavid Teigland 		if (++blk == jd->jd_blocks)
212*b3b94faaSDavid Teigland 			blk = 0;
213*b3b94faaSDavid Teigland 
214*b3b94faaSDavid Teigland 		error = get_log_header(jd, blk, &lh);
215*b3b94faaSDavid Teigland 		if (error < 0)
216*b3b94faaSDavid Teigland 			return error;
217*b3b94faaSDavid Teigland 		if (error == 1)
218*b3b94faaSDavid Teigland 			continue;
219*b3b94faaSDavid Teigland 
220*b3b94faaSDavid Teigland 		if (lh.lh_sequence == head->lh_sequence) {
221*b3b94faaSDavid Teigland 			gfs2_consist_inode(jd->jd_inode);
222*b3b94faaSDavid Teigland 			return -EIO;
223*b3b94faaSDavid Teigland 		}
224*b3b94faaSDavid Teigland 		if (lh.lh_sequence < head->lh_sequence)
225*b3b94faaSDavid Teigland 			break;
226*b3b94faaSDavid Teigland 
227*b3b94faaSDavid Teigland 		*head = lh;
228*b3b94faaSDavid Teigland 	}
229*b3b94faaSDavid Teigland 
230*b3b94faaSDavid Teigland 	return 0;
231*b3b94faaSDavid Teigland }
232*b3b94faaSDavid Teigland 
233*b3b94faaSDavid Teigland /**
234*b3b94faaSDavid Teigland  * gfs2_find_jhead - find the head of a log
235*b3b94faaSDavid Teigland  * @jd: the journal
236*b3b94faaSDavid Teigland  * @head: the log descriptor for the head of the log is returned here
237*b3b94faaSDavid Teigland  *
238*b3b94faaSDavid Teigland  * Do a binary search of a journal and find the valid log entry with the
239*b3b94faaSDavid Teigland  * highest sequence number.  (i.e. the log head)
240*b3b94faaSDavid Teigland  *
241*b3b94faaSDavid Teigland  * Returns: errno
242*b3b94faaSDavid Teigland  */
243*b3b94faaSDavid Teigland 
244*b3b94faaSDavid Teigland int gfs2_find_jhead(struct gfs2_jdesc *jd, struct gfs2_log_header *head)
245*b3b94faaSDavid Teigland {
246*b3b94faaSDavid Teigland 	struct gfs2_log_header lh_1, lh_m;
247*b3b94faaSDavid Teigland 	uint32_t blk_1, blk_2, blk_m;
248*b3b94faaSDavid Teigland 	int error;
249*b3b94faaSDavid Teigland 
250*b3b94faaSDavid Teigland 	blk_1 = 0;
251*b3b94faaSDavid Teigland 	blk_2 = jd->jd_blocks - 1;
252*b3b94faaSDavid Teigland 
253*b3b94faaSDavid Teigland 	for (;;) {
254*b3b94faaSDavid Teigland 		blk_m = (blk_1 + blk_2) / 2;
255*b3b94faaSDavid Teigland 
256*b3b94faaSDavid Teigland 		error = find_good_lh(jd, &blk_1, &lh_1);
257*b3b94faaSDavid Teigland 		if (error)
258*b3b94faaSDavid Teigland 			return error;
259*b3b94faaSDavid Teigland 
260*b3b94faaSDavid Teigland 		error = find_good_lh(jd, &blk_m, &lh_m);
261*b3b94faaSDavid Teigland 		if (error)
262*b3b94faaSDavid Teigland 			return error;
263*b3b94faaSDavid Teigland 
264*b3b94faaSDavid Teigland 		if (blk_1 == blk_m || blk_m == blk_2)
265*b3b94faaSDavid Teigland 			break;
266*b3b94faaSDavid Teigland 
267*b3b94faaSDavid Teigland 		if (lh_1.lh_sequence <= lh_m.lh_sequence)
268*b3b94faaSDavid Teigland 			blk_1 = blk_m;
269*b3b94faaSDavid Teigland 		else
270*b3b94faaSDavid Teigland 			blk_2 = blk_m;
271*b3b94faaSDavid Teigland 	}
272*b3b94faaSDavid Teigland 
273*b3b94faaSDavid Teigland 	error = jhead_scan(jd, &lh_1);
274*b3b94faaSDavid Teigland 	if (error)
275*b3b94faaSDavid Teigland 		return error;
276*b3b94faaSDavid Teigland 
277*b3b94faaSDavid Teigland 	*head = lh_1;
278*b3b94faaSDavid Teigland 
279*b3b94faaSDavid Teigland 	return error;
280*b3b94faaSDavid Teigland }
281*b3b94faaSDavid Teigland 
282*b3b94faaSDavid Teigland /**
283*b3b94faaSDavid Teigland  * foreach_descriptor - go through the active part of the log
284*b3b94faaSDavid Teigland  * @jd: the journal
285*b3b94faaSDavid Teigland  * @start: the first log header in the active region
286*b3b94faaSDavid Teigland  * @end: the last log header (don't process the contents of this entry))
287*b3b94faaSDavid Teigland  *
288*b3b94faaSDavid Teigland  * Call a given function once for every log descriptor in the active
289*b3b94faaSDavid Teigland  * portion of the log.
290*b3b94faaSDavid Teigland  *
291*b3b94faaSDavid Teigland  * Returns: errno
292*b3b94faaSDavid Teigland  */
293*b3b94faaSDavid Teigland 
294*b3b94faaSDavid Teigland static int foreach_descriptor(struct gfs2_jdesc *jd, unsigned int start,
295*b3b94faaSDavid Teigland 			      unsigned int end, int pass)
296*b3b94faaSDavid Teigland {
297*b3b94faaSDavid Teigland 	struct gfs2_sbd *sdp = jd->jd_inode->i_sbd;
298*b3b94faaSDavid Teigland 	struct buffer_head *bh;
299*b3b94faaSDavid Teigland 	struct gfs2_log_descriptor *ld;
300*b3b94faaSDavid Teigland 	int error = 0;
301*b3b94faaSDavid Teigland 	u32 length;
302*b3b94faaSDavid Teigland 	__be64 *ptr;
303*b3b94faaSDavid Teigland 	unsigned int offset = sizeof(struct gfs2_log_descriptor);
304*b3b94faaSDavid Teigland 	offset += (sizeof(__be64)-1);
305*b3b94faaSDavid Teigland 	offset &= ~(sizeof(__be64)-1);
306*b3b94faaSDavid Teigland 
307*b3b94faaSDavid Teigland 	while (start != end) {
308*b3b94faaSDavid Teigland 		error = gfs2_replay_read_block(jd, start, &bh);
309*b3b94faaSDavid Teigland 		if (error)
310*b3b94faaSDavid Teigland 			return error;
311*b3b94faaSDavid Teigland 		if (gfs2_meta_check(sdp, bh)) {
312*b3b94faaSDavid Teigland 			brelse(bh);
313*b3b94faaSDavid Teigland 			return -EIO;
314*b3b94faaSDavid Teigland 		}
315*b3b94faaSDavid Teigland 		ld = (struct gfs2_log_descriptor *)bh->b_data;
316*b3b94faaSDavid Teigland 		length = be32_to_cpu(ld->ld_length);
317*b3b94faaSDavid Teigland 
318*b3b94faaSDavid Teigland 		if (be16_to_cpu(ld->ld_header.mh_type) == GFS2_METATYPE_LH) {
319*b3b94faaSDavid Teigland 			struct gfs2_log_header lh;
320*b3b94faaSDavid Teigland 			error = get_log_header(jd, start, &lh);
321*b3b94faaSDavid Teigland 			if (!error) {
322*b3b94faaSDavid Teigland 				gfs2_replay_incr_blk(sdp, &start);
323*b3b94faaSDavid Teigland 				continue;
324*b3b94faaSDavid Teigland 			}
325*b3b94faaSDavid Teigland 			if (error == 1) {
326*b3b94faaSDavid Teigland 				gfs2_consist_inode(jd->jd_inode);
327*b3b94faaSDavid Teigland 				error = -EIO;
328*b3b94faaSDavid Teigland 			}
329*b3b94faaSDavid Teigland 			brelse(bh);
330*b3b94faaSDavid Teigland 			return error;
331*b3b94faaSDavid Teigland 		} else if (gfs2_metatype_check(sdp, bh, GFS2_METATYPE_LD)) {
332*b3b94faaSDavid Teigland 			brelse(bh);
333*b3b94faaSDavid Teigland 			return -EIO;
334*b3b94faaSDavid Teigland 		}
335*b3b94faaSDavid Teigland 		ptr = (__be64 *)(bh->b_data + offset);
336*b3b94faaSDavid Teigland 		error = lops_scan_elements(jd, start, ld, ptr, pass);
337*b3b94faaSDavid Teigland 		if (error) {
338*b3b94faaSDavid Teigland 			brelse(bh);
339*b3b94faaSDavid Teigland 			return error;
340*b3b94faaSDavid Teigland 		}
341*b3b94faaSDavid Teigland 
342*b3b94faaSDavid Teigland 		while (length--)
343*b3b94faaSDavid Teigland 			gfs2_replay_incr_blk(sdp, &start);
344*b3b94faaSDavid Teigland 
345*b3b94faaSDavid Teigland 		brelse(bh);
346*b3b94faaSDavid Teigland 	}
347*b3b94faaSDavid Teigland 
348*b3b94faaSDavid Teigland 	return 0;
349*b3b94faaSDavid Teigland }
350*b3b94faaSDavid Teigland 
351*b3b94faaSDavid Teigland /**
352*b3b94faaSDavid Teigland  * clean_journal - mark a dirty journal as being clean
353*b3b94faaSDavid Teigland  * @sdp: the filesystem
354*b3b94faaSDavid Teigland  * @jd: the journal
355*b3b94faaSDavid Teigland  * @gl: the journal's glock
356*b3b94faaSDavid Teigland  * @head: the head journal to start from
357*b3b94faaSDavid Teigland  *
358*b3b94faaSDavid Teigland  * Returns: errno
359*b3b94faaSDavid Teigland  */
360*b3b94faaSDavid Teigland 
361*b3b94faaSDavid Teigland static int clean_journal(struct gfs2_jdesc *jd, struct gfs2_log_header *head)
362*b3b94faaSDavid Teigland {
363*b3b94faaSDavid Teigland 	struct gfs2_inode *ip = jd->jd_inode;
364*b3b94faaSDavid Teigland 	struct gfs2_sbd *sdp = ip->i_sbd;
365*b3b94faaSDavid Teigland 	unsigned int lblock;
366*b3b94faaSDavid Teigland 	int new = 0;
367*b3b94faaSDavid Teigland 	uint64_t dblock;
368*b3b94faaSDavid Teigland 	struct gfs2_log_header *lh;
369*b3b94faaSDavid Teigland 	uint32_t hash;
370*b3b94faaSDavid Teigland 	struct buffer_head *bh;
371*b3b94faaSDavid Teigland 	int error;
372*b3b94faaSDavid Teigland 
373*b3b94faaSDavid Teigland 	lblock = head->lh_blkno;
374*b3b94faaSDavid Teigland 	gfs2_replay_incr_blk(sdp, &lblock);
375*b3b94faaSDavid Teigland 	error = gfs2_block_map(ip, lblock, &new, &dblock, NULL);
376*b3b94faaSDavid Teigland 	if (error)
377*b3b94faaSDavid Teigland 		return error;
378*b3b94faaSDavid Teigland 	if (!dblock) {
379*b3b94faaSDavid Teigland 		gfs2_consist_inode(ip);
380*b3b94faaSDavid Teigland 		return -EIO;
381*b3b94faaSDavid Teigland 	}
382*b3b94faaSDavid Teigland 
383*b3b94faaSDavid Teigland 	bh = sb_getblk(sdp->sd_vfs, dblock);
384*b3b94faaSDavid Teigland 	lock_buffer(bh);
385*b3b94faaSDavid Teigland 	memset(bh->b_data, 0, bh->b_size);
386*b3b94faaSDavid Teigland 	set_buffer_uptodate(bh);
387*b3b94faaSDavid Teigland 	clear_buffer_dirty(bh);
388*b3b94faaSDavid Teigland 	unlock_buffer(bh);
389*b3b94faaSDavid Teigland 
390*b3b94faaSDavid Teigland 	lh = (struct gfs2_log_header *)bh->b_data;
391*b3b94faaSDavid Teigland 	memset(lh, 0, sizeof(struct gfs2_log_header));
392*b3b94faaSDavid Teigland 	lh->lh_header.mh_magic = cpu_to_be32(GFS2_MAGIC);
393*b3b94faaSDavid Teigland 	lh->lh_header.mh_type = cpu_to_be16(GFS2_METATYPE_LH);
394*b3b94faaSDavid Teigland 	lh->lh_header.mh_format = cpu_to_be16(GFS2_FORMAT_LH);
395*b3b94faaSDavid Teigland 	lh->lh_sequence = cpu_to_be64(head->lh_sequence + 1);
396*b3b94faaSDavid Teigland 	lh->lh_flags = cpu_to_be32(GFS2_LOG_HEAD_UNMOUNT);
397*b3b94faaSDavid Teigland 	lh->lh_blkno = cpu_to_be32(lblock);
398*b3b94faaSDavid Teigland 	hash = gfs2_disk_hash((const char *)lh, sizeof(struct gfs2_log_header));
399*b3b94faaSDavid Teigland 	lh->lh_hash = cpu_to_be32(hash);
400*b3b94faaSDavid Teigland 
401*b3b94faaSDavid Teigland 	set_buffer_dirty(bh);
402*b3b94faaSDavid Teigland 	if (sync_dirty_buffer(bh))
403*b3b94faaSDavid Teigland 		gfs2_io_error_bh(sdp, bh);
404*b3b94faaSDavid Teigland 	brelse(bh);
405*b3b94faaSDavid Teigland 
406*b3b94faaSDavid Teigland 	return error;
407*b3b94faaSDavid Teigland }
408*b3b94faaSDavid Teigland 
409*b3b94faaSDavid Teigland /**
410*b3b94faaSDavid Teigland  * gfs2_recover_journal - recovery a given journal
411*b3b94faaSDavid Teigland  * @jd: the struct gfs2_jdesc describing the journal
412*b3b94faaSDavid Teigland  * @wait: Don't return until the journal is clean (or an error is encountered)
413*b3b94faaSDavid Teigland  *
414*b3b94faaSDavid Teigland  * Acquire the journal's lock, check to see if the journal is clean, and
415*b3b94faaSDavid Teigland  * do recovery if necessary.
416*b3b94faaSDavid Teigland  *
417*b3b94faaSDavid Teigland  * Returns: errno
418*b3b94faaSDavid Teigland  */
419*b3b94faaSDavid Teigland 
420*b3b94faaSDavid Teigland int gfs2_recover_journal(struct gfs2_jdesc *jd, int wait)
421*b3b94faaSDavid Teigland {
422*b3b94faaSDavid Teigland 	struct gfs2_sbd *sdp = jd->jd_inode->i_sbd;
423*b3b94faaSDavid Teigland 	struct gfs2_log_header head;
424*b3b94faaSDavid Teigland 	struct gfs2_holder j_gh, ji_gh, t_gh;
425*b3b94faaSDavid Teigland 	unsigned long t;
426*b3b94faaSDavid Teigland 	int ro = 0;
427*b3b94faaSDavid Teigland 	unsigned int pass;
428*b3b94faaSDavid Teigland 	int error;
429*b3b94faaSDavid Teigland 
430*b3b94faaSDavid Teigland 	fs_info(sdp, "jid=%u: Trying to acquire journal lock...\n", jd->jd_jid);
431*b3b94faaSDavid Teigland 
432*b3b94faaSDavid Teigland 	/* Aquire the journal lock so we can do recovery */
433*b3b94faaSDavid Teigland 
434*b3b94faaSDavid Teigland 	error = gfs2_glock_nq_num(sdp,
435*b3b94faaSDavid Teigland 				  jd->jd_jid, &gfs2_journal_glops,
436*b3b94faaSDavid Teigland 				  LM_ST_EXCLUSIVE,
437*b3b94faaSDavid Teigland 				  LM_FLAG_NOEXP |
438*b3b94faaSDavid Teigland 				  ((wait) ? 0 : LM_FLAG_TRY) |
439*b3b94faaSDavid Teigland 				  GL_NOCACHE, &j_gh);
440*b3b94faaSDavid Teigland 	switch (error) {
441*b3b94faaSDavid Teigland 	case 0:
442*b3b94faaSDavid Teigland 		break;
443*b3b94faaSDavid Teigland 
444*b3b94faaSDavid Teigland 	case GLR_TRYFAILED:
445*b3b94faaSDavid Teigland 		fs_info(sdp, "jid=%u: Busy\n", jd->jd_jid);
446*b3b94faaSDavid Teigland 		error = 0;
447*b3b94faaSDavid Teigland 
448*b3b94faaSDavid Teigland 	default:
449*b3b94faaSDavid Teigland 		goto fail;
450*b3b94faaSDavid Teigland 	};
451*b3b94faaSDavid Teigland 
452*b3b94faaSDavid Teigland 	error = gfs2_glock_nq_init(jd->jd_inode->i_gl, LM_ST_SHARED,
453*b3b94faaSDavid Teigland 				   LM_FLAG_NOEXP, &ji_gh);
454*b3b94faaSDavid Teigland 	if (error)
455*b3b94faaSDavid Teigland 		goto fail_gunlock_j;
456*b3b94faaSDavid Teigland 
457*b3b94faaSDavid Teigland 	fs_info(sdp, "jid=%u: Looking at journal...\n", jd->jd_jid);
458*b3b94faaSDavid Teigland 
459*b3b94faaSDavid Teigland 	error = gfs2_jdesc_check(jd);
460*b3b94faaSDavid Teigland 	if (error)
461*b3b94faaSDavid Teigland 		goto fail_gunlock_ji;
462*b3b94faaSDavid Teigland 
463*b3b94faaSDavid Teigland 	error = gfs2_find_jhead(jd, &head);
464*b3b94faaSDavid Teigland 	if (error)
465*b3b94faaSDavid Teigland 		goto fail_gunlock_ji;
466*b3b94faaSDavid Teigland 
467*b3b94faaSDavid Teigland 	if (!(head.lh_flags & GFS2_LOG_HEAD_UNMOUNT)) {
468*b3b94faaSDavid Teigland 		fs_info(sdp, "jid=%u: Acquiring the transaction lock...\n",
469*b3b94faaSDavid Teigland 			jd->jd_jid);
470*b3b94faaSDavid Teigland 
471*b3b94faaSDavid Teigland 		t = jiffies;
472*b3b94faaSDavid Teigland 
473*b3b94faaSDavid Teigland 		/* Acquire a shared hold on the transaction lock */
474*b3b94faaSDavid Teigland 
475*b3b94faaSDavid Teigland 		error = gfs2_glock_nq_init(sdp->sd_trans_gl,
476*b3b94faaSDavid Teigland 					   LM_ST_SHARED,
477*b3b94faaSDavid Teigland 					   LM_FLAG_NOEXP |
478*b3b94faaSDavid Teigland 					   LM_FLAG_PRIORITY |
479*b3b94faaSDavid Teigland 					   GL_NEVER_RECURSE |
480*b3b94faaSDavid Teigland 					   GL_NOCANCEL |
481*b3b94faaSDavid Teigland 					   GL_NOCACHE,
482*b3b94faaSDavid Teigland 					   &t_gh);
483*b3b94faaSDavid Teigland 		if (error)
484*b3b94faaSDavid Teigland 			goto fail_gunlock_ji;
485*b3b94faaSDavid Teigland 
486*b3b94faaSDavid Teigland 		if (test_bit(SDF_JOURNAL_CHECKED, &sdp->sd_flags)) {
487*b3b94faaSDavid Teigland 			if (!test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags))
488*b3b94faaSDavid Teigland 				ro = 1;
489*b3b94faaSDavid Teigland 		} else {
490*b3b94faaSDavid Teigland 			if (sdp->sd_vfs->s_flags & MS_RDONLY)
491*b3b94faaSDavid Teigland 				ro = 1;
492*b3b94faaSDavid Teigland 		}
493*b3b94faaSDavid Teigland 
494*b3b94faaSDavid Teigland 		if (ro) {
495*b3b94faaSDavid Teigland 			fs_warn(sdp, "jid=%u: Can't replay: read-only FS\n",
496*b3b94faaSDavid Teigland 				jd->jd_jid);
497*b3b94faaSDavid Teigland 			error = -EROFS;
498*b3b94faaSDavid Teigland 			goto fail_gunlock_tr;
499*b3b94faaSDavid Teigland 		}
500*b3b94faaSDavid Teigland 
501*b3b94faaSDavid Teigland 		fs_info(sdp, "jid=%u: Replaying journal...\n", jd->jd_jid);
502*b3b94faaSDavid Teigland 
503*b3b94faaSDavid Teigland 		for (pass = 0; pass < 2; pass++) {
504*b3b94faaSDavid Teigland 			lops_before_scan(jd, &head, pass);
505*b3b94faaSDavid Teigland 			error = foreach_descriptor(jd, head.lh_tail,
506*b3b94faaSDavid Teigland 						   head.lh_blkno, pass);
507*b3b94faaSDavid Teigland 			lops_after_scan(jd, error, pass);
508*b3b94faaSDavid Teigland 			if (error)
509*b3b94faaSDavid Teigland 				goto fail_gunlock_tr;
510*b3b94faaSDavid Teigland 		}
511*b3b94faaSDavid Teigland 
512*b3b94faaSDavid Teigland 		error = clean_journal(jd, &head);
513*b3b94faaSDavid Teigland 		if (error)
514*b3b94faaSDavid Teigland 			goto fail_gunlock_tr;
515*b3b94faaSDavid Teigland 
516*b3b94faaSDavid Teigland 		gfs2_glock_dq_uninit(&t_gh);
517*b3b94faaSDavid Teigland 
518*b3b94faaSDavid Teigland 		t = DIV_RU(jiffies - t, HZ);
519*b3b94faaSDavid Teigland 
520*b3b94faaSDavid Teigland 		fs_info(sdp, "jid=%u: Journal replayed in %lus\n",
521*b3b94faaSDavid Teigland 			jd->jd_jid, t);
522*b3b94faaSDavid Teigland 	}
523*b3b94faaSDavid Teigland 
524*b3b94faaSDavid Teigland 	gfs2_glock_dq_uninit(&ji_gh);
525*b3b94faaSDavid Teigland 
526*b3b94faaSDavid Teigland 	gfs2_lm_recovery_done(sdp, jd->jd_jid, LM_RD_SUCCESS);
527*b3b94faaSDavid Teigland 
528*b3b94faaSDavid Teigland 	gfs2_glock_dq_uninit(&j_gh);
529*b3b94faaSDavid Teigland 
530*b3b94faaSDavid Teigland 	fs_info(sdp, "jid=%u: Done\n", jd->jd_jid);
531*b3b94faaSDavid Teigland 
532*b3b94faaSDavid Teigland 	return 0;
533*b3b94faaSDavid Teigland 
534*b3b94faaSDavid Teigland  fail_gunlock_tr:
535*b3b94faaSDavid Teigland 	gfs2_glock_dq_uninit(&t_gh);
536*b3b94faaSDavid Teigland 
537*b3b94faaSDavid Teigland  fail_gunlock_ji:
538*b3b94faaSDavid Teigland 	gfs2_glock_dq_uninit(&ji_gh);
539*b3b94faaSDavid Teigland 
540*b3b94faaSDavid Teigland  fail_gunlock_j:
541*b3b94faaSDavid Teigland 	gfs2_glock_dq_uninit(&j_gh);
542*b3b94faaSDavid Teigland 
543*b3b94faaSDavid Teigland 	fs_info(sdp, "jid=%u: %s\n", jd->jd_jid, (error) ? "Failed" : "Done");
544*b3b94faaSDavid Teigland 
545*b3b94faaSDavid Teigland  fail:
546*b3b94faaSDavid Teigland 	gfs2_lm_recovery_done(sdp, jd->jd_jid, LM_RD_GAVEUP);
547*b3b94faaSDavid Teigland 
548*b3b94faaSDavid Teigland 	return error;
549*b3b94faaSDavid Teigland }
550*b3b94faaSDavid Teigland 
551*b3b94faaSDavid Teigland /**
552*b3b94faaSDavid Teigland  * gfs2_check_journals - Recover any dirty journals
553*b3b94faaSDavid Teigland  * @sdp: the filesystem
554*b3b94faaSDavid Teigland  *
555*b3b94faaSDavid Teigland  */
556*b3b94faaSDavid Teigland 
557*b3b94faaSDavid Teigland void gfs2_check_journals(struct gfs2_sbd *sdp)
558*b3b94faaSDavid Teigland {
559*b3b94faaSDavid Teigland 	struct gfs2_jdesc *jd;
560*b3b94faaSDavid Teigland 
561*b3b94faaSDavid Teigland 	for (;;) {
562*b3b94faaSDavid Teigland 		jd = gfs2_jdesc_find_dirty(sdp);
563*b3b94faaSDavid Teigland 		if (!jd)
564*b3b94faaSDavid Teigland 			break;
565*b3b94faaSDavid Teigland 
566*b3b94faaSDavid Teigland 		if (jd != sdp->sd_jdesc)
567*b3b94faaSDavid Teigland 			gfs2_recover_journal(jd, NO_WAIT);
568*b3b94faaSDavid Teigland 	}
569*b3b94faaSDavid Teigland }
570*b3b94faaSDavid Teigland 
571