Blame view

fs/nilfs2/recovery.c 24.4 KB
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
  /*
   * recovery.c - NILFS recovery logic
   *
   * Copyright (C) 2005-2008 Nippon Telegraph and Telephone Corporation.
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   *
   * Written by Ryusuke Konishi <ryusuke@osrg.net>
   */
  
  #include <linux/buffer_head.h>
  #include <linux/blkdev.h>
  #include <linux/swap.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
26
  #include <linux/slab.h>
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
27
28
29
30
31
  #include <linux/crc32.h>
  #include "nilfs.h"
  #include "segment.h"
  #include "sufile.h"
  #include "page.h"
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
32
33
34
35
36
37
38
39
40
41
42
  #include "segbuf.h"
  
  /*
   * Segment check result
   */
  enum {
  	NILFS_SEG_VALID,
  	NILFS_SEG_NO_SUPER_ROOT,
  	NILFS_SEG_FAIL_IO,
  	NILFS_SEG_FAIL_MAGIC,
  	NILFS_SEG_FAIL_SEQ,
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
  	NILFS_SEG_FAIL_CHECKSUM_SUPER_ROOT,
  	NILFS_SEG_FAIL_CHECKSUM_FULL,
  	NILFS_SEG_FAIL_CONSISTENCY,
  };
  
  /* work structure for recovery */
  struct nilfs_recovery_block {
  	ino_t ino;		/* Inode number of the file that this block
  				   belongs to */
  	sector_t blocknr;	/* block number */
  	__u64 vblocknr;		/* virtual block number */
  	unsigned long blkoff;	/* File offset of the data block (per block) */
  	struct list_head list;
  };
  
  
  static int nilfs_warn_segment_error(int err)
  {
  	switch (err) {
  	case NILFS_SEG_FAIL_IO:
  		printk(KERN_WARNING
  		       "NILFS warning: I/O error on loading last segment
  ");
  		return -EIO;
  	case NILFS_SEG_FAIL_MAGIC:
  		printk(KERN_WARNING
  		       "NILFS warning: Segment magic number invalid
  ");
  		break;
  	case NILFS_SEG_FAIL_SEQ:
  		printk(KERN_WARNING
  		       "NILFS warning: Sequence number mismatch
  ");
  		break;
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
  	case NILFS_SEG_FAIL_CHECKSUM_SUPER_ROOT:
  		printk(KERN_WARNING
  		       "NILFS warning: Checksum error in super root
  ");
  		break;
  	case NILFS_SEG_FAIL_CHECKSUM_FULL:
  		printk(KERN_WARNING
  		       "NILFS warning: Checksum error in segment payload
  ");
  		break;
  	case NILFS_SEG_FAIL_CONSISTENCY:
  		printk(KERN_WARNING
  		       "NILFS warning: Inconsistent segment
  ");
  		break;
  	case NILFS_SEG_NO_SUPER_ROOT:
  		printk(KERN_WARNING
  		       "NILFS warning: No super root in the last segment
  ");
  		break;
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
97
98
99
  	}
  	return -EINVAL;
  }
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
100
  /**
8b94025c0   Ryusuke Konishi   nilfs2: refactor ...
101
102
   * nilfs_compute_checksum - compute checksum of blocks continuously
   * @nilfs: nilfs object
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
103
104
105
106
107
108
109
   * @bhs: buffer head of start block
   * @sum: place to store result
   * @offset: offset bytes in the first block
   * @check_bytes: number of bytes to be checked
   * @start: DBN of start block
   * @nblock: number of blocks to be checked
   */
8b94025c0   Ryusuke Konishi   nilfs2: refactor ...
110
111
112
113
  static int nilfs_compute_checksum(struct the_nilfs *nilfs,
  				  struct buffer_head *bhs, u32 *sum,
  				  unsigned long offset, u64 check_bytes,
  				  sector_t start, unsigned long nblock)
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
114
  {
8b94025c0   Ryusuke Konishi   nilfs2: refactor ...
115
  	unsigned int blocksize = nilfs->ns_blocksize;
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
116
117
118
119
120
121
  	unsigned long size;
  	u32 crc;
  
  	BUG_ON(offset >= blocksize);
  	check_bytes -= offset;
  	size = min_t(u64, check_bytes, blocksize - offset);
8b94025c0   Ryusuke Konishi   nilfs2: refactor ...
122
  	crc = crc32_le(nilfs->ns_crc_seed,
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
123
124
125
  		       (unsigned char *)bhs->b_data + offset, size);
  	if (--nblock > 0) {
  		do {
8b94025c0   Ryusuke Konishi   nilfs2: refactor ...
126
127
128
  			struct buffer_head *bh;
  
  			bh = __bread(nilfs->ns_bdev, ++start, blocksize);
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
129
130
131
132
133
134
135
136
137
138
139
140
141
142
  			if (!bh)
  				return -EIO;
  			check_bytes -= size;
  			size = min_t(u64, check_bytes, blocksize);
  			crc = crc32_le(crc, bh->b_data, size);
  			brelse(bh);
  		} while (--nblock > 0);
  	}
  	*sum = crc;
  	return 0;
  }
  
  /**
   * nilfs_read_super_root_block - read super root block
8b94025c0   Ryusuke Konishi   nilfs2: refactor ...
143
   * @nilfs: nilfs object
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
144
145
146
147
   * @sr_block: disk block number of the super root block
   * @pbh: address of a buffer_head pointer to return super root buffer
   * @check: CRC check flag
   */
8b94025c0   Ryusuke Konishi   nilfs2: refactor ...
148
  int nilfs_read_super_root_block(struct the_nilfs *nilfs, sector_t sr_block,
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
149
150
151
152
153
154
155
156
  				struct buffer_head **pbh, int check)
  {
  	struct buffer_head *bh_sr;
  	struct nilfs_super_root *sr;
  	u32 crc;
  	int ret;
  
  	*pbh = NULL;
8b94025c0   Ryusuke Konishi   nilfs2: refactor ...
157
  	bh_sr = __bread(nilfs->ns_bdev, sr_block, nilfs->ns_blocksize);
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
158
159
160
161
162
163
164
165
  	if (unlikely(!bh_sr)) {
  		ret = NILFS_SEG_FAIL_IO;
  		goto failed;
  	}
  
  	sr = (struct nilfs_super_root *)bh_sr->b_data;
  	if (check) {
  		unsigned bytes = le16_to_cpu(sr->sr_bytes);
8b94025c0   Ryusuke Konishi   nilfs2: refactor ...
166
  		if (bytes == 0 || bytes > nilfs->ns_blocksize) {
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
167
168
169
  			ret = NILFS_SEG_FAIL_CHECKSUM_SUPER_ROOT;
  			goto failed_bh;
  		}
8b94025c0   Ryusuke Konishi   nilfs2: refactor ...
170
171
172
  		if (nilfs_compute_checksum(
  			    nilfs, bh_sr, &crc, sizeof(sr->sr_sum), bytes,
  			    sr_block, 1)) {
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
  			ret = NILFS_SEG_FAIL_IO;
  			goto failed_bh;
  		}
  		if (crc != le32_to_cpu(sr->sr_sum)) {
  			ret = NILFS_SEG_FAIL_CHECKSUM_SUPER_ROOT;
  			goto failed_bh;
  		}
  	}
  	*pbh = bh_sr;
  	return 0;
  
   failed_bh:
  	brelse(bh_sr);
  
   failed:
  	return nilfs_warn_segment_error(ret);
  }
  
  /**
354fa8be2   Ryusuke Konishi   nilfs2: divide lo...
192
   * nilfs_read_log_header - read summary header of the specified log
8b94025c0   Ryusuke Konishi   nilfs2: refactor ...
193
   * @nilfs: nilfs object
354fa8be2   Ryusuke Konishi   nilfs2: divide lo...
194
195
   * @start_blocknr: start block number of the log
   * @sum: pointer to return segment summary structure
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
196
   */
354fa8be2   Ryusuke Konishi   nilfs2: divide lo...
197
198
199
  static struct buffer_head *
  nilfs_read_log_header(struct the_nilfs *nilfs, sector_t start_blocknr,
  		      struct nilfs_segment_summary **sum)
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
200
201
  {
  	struct buffer_head *bh_sum;
354fa8be2   Ryusuke Konishi   nilfs2: divide lo...
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
  
  	bh_sum = __bread(nilfs->ns_bdev, start_blocknr, nilfs->ns_blocksize);
  	if (bh_sum)
  		*sum = (struct nilfs_segment_summary *)bh_sum->b_data;
  	return bh_sum;
  }
  
  /**
   * nilfs_validate_log - verify consistency of log
   * @nilfs: nilfs object
   * @seg_seq: sequence number of segment
   * @bh_sum: buffer head of summary block
   * @sum: segment summary struct
   */
  static int nilfs_validate_log(struct the_nilfs *nilfs, u64 seg_seq,
  			      struct buffer_head *bh_sum,
  			      struct nilfs_segment_summary *sum)
  {
03f29365e   Jiro SEKIBA   nilfs2: delete un...
220
221
  	unsigned long nblock;
  	u32 crc;
354fa8be2   Ryusuke Konishi   nilfs2: divide lo...
222
  	int ret;
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
223

354fa8be2   Ryusuke Konishi   nilfs2: divide lo...
224
225
  	ret = NILFS_SEG_FAIL_MAGIC;
  	if (le32_to_cpu(sum->ss_magic) != NILFS_SEGSUM_MAGIC)
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
226
  		goto out;
354fa8be2   Ryusuke Konishi   nilfs2: divide lo...
227
228
229
  	ret = NILFS_SEG_FAIL_SEQ;
  	if (le64_to_cpu(sum->ss_seq) != seg_seq)
  		goto out;
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
230

354fa8be2   Ryusuke Konishi   nilfs2: divide lo...
231
232
233
  	nblock = le32_to_cpu(sum->ss_nblocks);
  	ret = NILFS_SEG_FAIL_CONSISTENCY;
  	if (unlikely(nblock == 0 || nblock > nilfs->ns_blocks_per_segment))
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
234
  		/* This limits the number of blocks read in the CRC check */
354fa8be2   Ryusuke Konishi   nilfs2: divide lo...
235
236
237
  		goto out;
  
  	ret = NILFS_SEG_FAIL_IO;
8b94025c0   Ryusuke Konishi   nilfs2: refactor ...
238
239
  	if (nilfs_compute_checksum(nilfs, bh_sum, &crc, sizeof(sum->ss_datasum),
  				   ((u64)nblock << nilfs->ns_blocksize_bits),
354fa8be2   Ryusuke Konishi   nilfs2: divide lo...
240
241
242
243
244
245
246
247
  				   bh_sum->b_blocknr, nblock))
  		goto out;
  
  	ret = NILFS_SEG_FAIL_CHECKSUM_FULL;
  	if (crc != le32_to_cpu(sum->ss_datasum))
  		goto out;
  	ret = 0;
  out:
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
248
249
  	return ret;
  }
8b94025c0   Ryusuke Konishi   nilfs2: refactor ...
250
251
252
253
254
255
256
257
258
259
  /**
   * nilfs_read_summary_info - read an item on summary blocks of a log
   * @nilfs: nilfs object
   * @pbh: the current buffer head on summary blocks [in, out]
   * @offset: the current byte offset on summary blocks [in, out]
   * @bytes: byte size of the item to be read
   */
  static void *nilfs_read_summary_info(struct the_nilfs *nilfs,
  				     struct buffer_head **pbh,
  				     unsigned int *offset, unsigned int bytes)
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
260
261
262
263
264
265
266
267
  {
  	void *ptr;
  	sector_t blocknr;
  
  	BUG_ON((*pbh)->b_size < *offset);
  	if (bytes > (*pbh)->b_size - *offset) {
  		blocknr = (*pbh)->b_blocknr;
  		brelse(*pbh);
8b94025c0   Ryusuke Konishi   nilfs2: refactor ...
268
269
  		*pbh = __bread(nilfs->ns_bdev, blocknr + 1,
  			       nilfs->ns_blocksize);
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
270
271
272
273
274
275
276
277
  		if (unlikely(!*pbh))
  			return NULL;
  		*offset = 0;
  	}
  	ptr = (*pbh)->b_data + *offset;
  	*offset += bytes;
  	return ptr;
  }
8b94025c0   Ryusuke Konishi   nilfs2: refactor ...
278
279
280
281
282
283
284
285
286
287
288
289
  /**
   * nilfs_skip_summary_info - skip items on summary blocks of a log
   * @nilfs: nilfs object
   * @pbh: the current buffer head on summary blocks [in, out]
   * @offset: the current byte offset on summary blocks [in, out]
   * @bytes: byte size of the item to be skipped
   * @count: number of items to be skipped
   */
  static void nilfs_skip_summary_info(struct the_nilfs *nilfs,
  				    struct buffer_head **pbh,
  				    unsigned int *offset, unsigned int bytes,
  				    unsigned long count)
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
  {
  	unsigned int rest_item_in_current_block
  		= ((*pbh)->b_size - *offset) / bytes;
  
  	if (count <= rest_item_in_current_block) {
  		*offset += bytes * count;
  	} else {
  		sector_t blocknr = (*pbh)->b_blocknr;
  		unsigned int nitem_per_block = (*pbh)->b_size / bytes;
  		unsigned int bcnt;
  
  		count -= rest_item_in_current_block;
  		bcnt = DIV_ROUND_UP(count, nitem_per_block);
  		*offset = bytes * (count - (bcnt - 1) * nitem_per_block);
  
  		brelse(*pbh);
8b94025c0   Ryusuke Konishi   nilfs2: refactor ...
306
307
  		*pbh = __bread(nilfs->ns_bdev, blocknr + bcnt,
  			       nilfs->ns_blocksize);
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
308
309
  	}
  }
8b94025c0   Ryusuke Konishi   nilfs2: refactor ...
310
311
312
313
  /**
   * nilfs_scan_dsync_log - get block information of a log written for data sync
   * @nilfs: nilfs object
   * @start_blocknr: start block number of the log
85655484f   Ryusuke Konishi   nilfs2: do not us...
314
   * @sum: log summary information
8b94025c0   Ryusuke Konishi   nilfs2: refactor ...
315
316
317
   * @head: list head to add nilfs_recovery_block struct
   */
  static int nilfs_scan_dsync_log(struct the_nilfs *nilfs, sector_t start_blocknr,
85655484f   Ryusuke Konishi   nilfs2: do not us...
318
  				struct nilfs_segment_summary *sum,
8b94025c0   Ryusuke Konishi   nilfs2: refactor ...
319
  				struct list_head *head)
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
320
321
322
  {
  	struct buffer_head *bh;
  	unsigned int offset;
85655484f   Ryusuke Konishi   nilfs2: do not us...
323
324
  	u32 nfinfo, sumbytes;
  	sector_t blocknr;
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
325
326
  	ino_t ino;
  	int err = -EIO;
85655484f   Ryusuke Konishi   nilfs2: do not us...
327
  	nfinfo = le32_to_cpu(sum->ss_nfinfo);
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
328
329
  	if (!nfinfo)
  		return 0;
85655484f   Ryusuke Konishi   nilfs2: do not us...
330
331
  	sumbytes = le32_to_cpu(sum->ss_sumbytes);
  	blocknr = start_blocknr + DIV_ROUND_UP(sumbytes, nilfs->ns_blocksize);
8b94025c0   Ryusuke Konishi   nilfs2: refactor ...
332
  	bh = __bread(nilfs->ns_bdev, start_blocknr, nilfs->ns_blocksize);
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
333
334
  	if (unlikely(!bh))
  		goto out;
85655484f   Ryusuke Konishi   nilfs2: do not us...
335
  	offset = le16_to_cpu(sum->ss_bytes);
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
336
337
338
  	for (;;) {
  		unsigned long nblocks, ndatablk, nnodeblk;
  		struct nilfs_finfo *finfo;
8b94025c0   Ryusuke Konishi   nilfs2: refactor ...
339
340
  		finfo = nilfs_read_summary_info(nilfs, &bh, &offset,
  						sizeof(*finfo));
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
341
342
343
344
345
346
347
348
349
350
351
  		if (unlikely(!finfo))
  			goto out;
  
  		ino = le64_to_cpu(finfo->fi_ino);
  		nblocks = le32_to_cpu(finfo->fi_nblocks);
  		ndatablk = le32_to_cpu(finfo->fi_ndatablk);
  		nnodeblk = nblocks - ndatablk;
  
  		while (ndatablk-- > 0) {
  			struct nilfs_recovery_block *rb;
  			struct nilfs_binfo_v *binfo;
8b94025c0   Ryusuke Konishi   nilfs2: refactor ...
352
353
  			binfo = nilfs_read_summary_info(nilfs, &bh, &offset,
  							sizeof(*binfo));
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
  			if (unlikely(!binfo))
  				goto out;
  
  			rb = kmalloc(sizeof(*rb), GFP_NOFS);
  			if (unlikely(!rb)) {
  				err = -ENOMEM;
  				goto out;
  			}
  			rb->ino = ino;
  			rb->blocknr = blocknr++;
  			rb->vblocknr = le64_to_cpu(binfo->bi_vblocknr);
  			rb->blkoff = le64_to_cpu(binfo->bi_blkoff);
  			/* INIT_LIST_HEAD(&rb->list); */
  			list_add_tail(&rb->list, head);
  		}
  		if (--nfinfo == 0)
  			break;
8b94025c0   Ryusuke Konishi   nilfs2: refactor ...
371
372
373
  		blocknr += nnodeblk; /* always 0 for data sync logs */
  		nilfs_skip_summary_info(nilfs, &bh, &offset, sizeof(__le64),
  					nnodeblk);
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
374
375
376
377
378
379
380
381
382
383
384
385
  		if (unlikely(!bh))
  			goto out;
  	}
  	err = 0;
   out:
  	brelse(bh);   /* brelse(NULL) is just ignored */
  	return err;
  }
  
  static void dispose_recovery_list(struct list_head *head)
  {
  	while (!list_empty(head)) {
0cc128388   Ryusuke Konishi   nilfs2: use list_...
386
387
388
  		struct nilfs_recovery_block *rb;
  
  		rb = list_first_entry(head, struct nilfs_recovery_block, list);
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
389
390
391
392
  		list_del(&rb->list);
  		kfree(rb);
  	}
  }
654137dd4   Ryusuke Konishi   nilfs2: remove he...
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
  struct nilfs_segment_entry {
  	struct list_head	list;
  	__u64			segnum;
  };
  
  static int nilfs_segment_list_add(struct list_head *head, __u64 segnum)
  {
  	struct nilfs_segment_entry *ent = kmalloc(sizeof(*ent), GFP_NOFS);
  
  	if (unlikely(!ent))
  		return -ENOMEM;
  
  	ent->segnum = segnum;
  	INIT_LIST_HEAD(&ent->list);
  	list_add_tail(&ent->list, head);
  	return 0;
  }
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
410
411
412
  void nilfs_dispose_segment_list(struct list_head *head)
  {
  	while (!list_empty(head)) {
0cc128388   Ryusuke Konishi   nilfs2: use list_...
413
414
415
  		struct nilfs_segment_entry *ent;
  
  		ent = list_first_entry(head, struct nilfs_segment_entry, list);
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
416
  		list_del(&ent->list);
654137dd4   Ryusuke Konishi   nilfs2: remove he...
417
  		kfree(ent);
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
418
419
420
421
  	}
  }
  
  static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs,
f7545144c   Ryusuke Konishi   nilfs2: use sb in...
422
  					      struct super_block *sb,
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
  					      struct nilfs_recovery_info *ri)
  {
  	struct list_head *head = &ri->ri_used_segments;
  	struct nilfs_segment_entry *ent, *n;
  	struct inode *sufile = nilfs->ns_sufile;
  	__u64 segnum[4];
  	int err;
  	int i;
  
  	segnum[0] = nilfs->ns_segnum;
  	segnum[1] = nilfs->ns_nextnum;
  	segnum[2] = ri->ri_segnum;
  	segnum[3] = ri->ri_nextnum;
  
  	/*
  	 * Releasing the next segment of the latest super root.
  	 * The next segment is invalidated by this recovery.
  	 */
  	err = nilfs_sufile_free(sufile, segnum[1]);
  	if (unlikely(err))
  		goto failed;
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
444
  	for (i = 1; i < 4; i++) {
654137dd4   Ryusuke Konishi   nilfs2: remove he...
445
446
  		err = nilfs_segment_list_add(head, segnum[i]);
  		if (unlikely(err))
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
447
  			goto failed;
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
448
449
450
451
  	}
  
  	/*
  	 * Collecting segments written after the latest super root.
2c2e52fc4   Ryusuke Konishi   nilfs2: extend ni...
452
  	 * These are marked dirty to avoid being reallocated in the next write.
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
453
454
  	 */
  	list_for_each_entry_safe(ent, n, head, list) {
c85399c2d   Ryusuke Konishi   nilfs2: fix possi...
455
456
457
458
  		if (ent->segnum != segnum[0]) {
  			err = nilfs_sufile_scrap(sufile, ent->segnum);
  			if (unlikely(err))
  				goto failed;
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
459
  		}
2c2e52fc4   Ryusuke Konishi   nilfs2: extend ni...
460
  		list_del(&ent->list);
654137dd4   Ryusuke Konishi   nilfs2: remove he...
461
  		kfree(ent);
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
462
  	}
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
463

0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
464
465
466
467
468
469
470
471
  	/* Allocate new segments for recovery */
  	err = nilfs_sufile_alloc(sufile, &segnum[0]);
  	if (unlikely(err))
  		goto failed;
  
  	nilfs->ns_pseg_offset = 0;
  	nilfs->ns_seg_seq = ri->ri_seq + 2;
  	nilfs->ns_nextnum = nilfs->ns_segnum = segnum[0];
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
472
473
474
475
476
  
   failed:
  	/* No need to recover sufile because it will be destroyed on error */
  	return err;
  }
8b94025c0   Ryusuke Konishi   nilfs2: refactor ...
477
  static int nilfs_recovery_copy_block(struct the_nilfs *nilfs,
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
478
479
480
481
482
  				     struct nilfs_recovery_block *rb,
  				     struct page *page)
  {
  	struct buffer_head *bh_org;
  	void *kaddr;
8b94025c0   Ryusuke Konishi   nilfs2: refactor ...
483
  	bh_org = __bread(nilfs->ns_bdev, rb->blocknr, nilfs->ns_blocksize);
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
484
485
486
487
488
489
490
491
492
  	if (unlikely(!bh_org))
  		return -EIO;
  
  	kaddr = kmap_atomic(page, KM_USER0);
  	memcpy(kaddr + bh_offset(bh_org), bh_org->b_data, bh_org->b_size);
  	kunmap_atomic(kaddr, KM_USER0);
  	brelse(bh_org);
  	return 0;
  }
8b94025c0   Ryusuke Konishi   nilfs2: refactor ...
493
  static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs,
f7545144c   Ryusuke Konishi   nilfs2: use sb in...
494
  				      struct super_block *sb,
4d8d9293d   Ryusuke Konishi   nilfs2: set point...
495
  				      struct nilfs_root *root,
8b94025c0   Ryusuke Konishi   nilfs2: refactor ...
496
497
  				      struct list_head *head,
  				      unsigned long *nr_salvaged_blocks)
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
498
499
500
  {
  	struct inode *inode;
  	struct nilfs_recovery_block *rb, *n;
8b94025c0   Ryusuke Konishi   nilfs2: refactor ...
501
  	unsigned blocksize = nilfs->ns_blocksize;
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
502
503
504
505
506
  	struct page *page;
  	loff_t pos;
  	int err = 0, err2 = 0;
  
  	list_for_each_entry_safe(rb, n, head, list) {
f7545144c   Ryusuke Konishi   nilfs2: use sb in...
507
  		inode = nilfs_iget(sb, root, rb->ino);
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
508
509
510
511
512
513
514
  		if (IS_ERR(inode)) {
  			err = PTR_ERR(inode);
  			inode = NULL;
  			goto failed_inode;
  		}
  
  		pos = rb->blkoff << inode->i_blkbits;
155130a4f   Christoph Hellwig   get rid of block_...
515
516
517
518
519
520
  		err = block_write_begin(inode->i_mapping, pos, blocksize,
  					0, &page, nilfs_get_block);
  		if (unlikely(err)) {
  			loff_t isize = inode->i_size;
  			if (pos + blocksize > isize)
  				vmtruncate(inode, isize);
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
521
  			goto failed_inode;
155130a4f   Christoph Hellwig   get rid of block_...
522
  		}
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
523

8b94025c0   Ryusuke Konishi   nilfs2: refactor ...
524
  		err = nilfs_recovery_copy_block(nilfs, rb, page);
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
525
526
  		if (unlikely(err))
  			goto failed_page;
bcbc8c648   Ryusuke Konishi   nilfs2: do not pa...
527
  		err = nilfs_set_file_dirty(inode, 1);
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
  		if (unlikely(err))
  			goto failed_page;
  
  		block_write_end(NULL, inode->i_mapping, pos, blocksize,
  				blocksize, page, NULL);
  
  		unlock_page(page);
  		page_cache_release(page);
  
  		(*nr_salvaged_blocks)++;
  		goto next;
  
   failed_page:
  		unlock_page(page);
  		page_cache_release(page);
  
   failed_inode:
  		printk(KERN_WARNING
  		       "NILFS warning: error recovering data block "
  		       "(err=%d, ino=%lu, block-offset=%llu)
  ",
b5696e5e0   Heiko Carstens   nilfs2: fix forma...
549
550
  		       err, (unsigned long)rb->ino,
  		       (unsigned long long)rb->blkoff);
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
551
552
553
554
555
556
557
558
559
560
561
562
563
  		if (!err2)
  			err2 = err;
   next:
  		iput(inode); /* iput(NULL) is just ignored */
  		list_del_init(&rb->list);
  		kfree(rb);
  	}
  	return err2;
  }
  
  /**
   * nilfs_do_roll_forward - salvage logical segments newer than the latest
   * checkpoint
8b94025c0   Ryusuke Konishi   nilfs2: refactor ...
564
   * @nilfs: nilfs object
f7545144c   Ryusuke Konishi   nilfs2: use sb in...
565
   * @sb: super block instance
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
566
567
568
   * @ri: pointer to a nilfs_recovery_info
   */
  static int nilfs_do_roll_forward(struct the_nilfs *nilfs,
f7545144c   Ryusuke Konishi   nilfs2: use sb in...
569
  				 struct super_block *sb,
4d8d9293d   Ryusuke Konishi   nilfs2: set point...
570
  				 struct nilfs_root *root,
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
571
572
  				 struct nilfs_recovery_info *ri)
  {
354fa8be2   Ryusuke Konishi   nilfs2: divide lo...
573
574
  	struct buffer_head *bh_sum = NULL;
  	struct nilfs_segment_summary *sum;
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
575
576
577
  	sector_t pseg_start;
  	sector_t seg_start, seg_end;  /* Starting/ending DBN of full segment */
  	unsigned long nsalvaged_blocks = 0;
85655484f   Ryusuke Konishi   nilfs2: do not us...
578
  	unsigned int flags;
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
579
580
581
582
583
584
585
586
587
588
  	u64 seg_seq;
  	__u64 segnum, nextnum = 0;
  	int empty_seg = 0;
  	int err = 0, ret;
  	LIST_HEAD(dsync_blocks);  /* list of data blocks to be recovered */
  	enum {
  		RF_INIT_ST,
  		RF_DSYNC_ST,   /* scanning data-sync segments */
  	};
  	int state = RF_INIT_ST;
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
589
590
591
592
593
594
  	pseg_start = ri->ri_lsegs_start;
  	seg_seq = ri->ri_lsegs_start_seq;
  	segnum = nilfs_get_segnum_of_block(nilfs, pseg_start);
  	nilfs_get_segment_range(nilfs, segnum, &seg_start, &seg_end);
  
  	while (segnum != ri->ri_segnum || pseg_start <= ri->ri_pseg_start) {
354fa8be2   Ryusuke Konishi   nilfs2: divide lo...
595
596
597
598
599
600
  		brelse(bh_sum);
  		bh_sum = nilfs_read_log_header(nilfs, pseg_start, &sum);
  		if (!bh_sum) {
  			err = -EIO;
  			goto failed;
  		}
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
601

354fa8be2   Ryusuke Konishi   nilfs2: divide lo...
602
  		ret = nilfs_validate_log(nilfs, seg_seq, bh_sum, sum);
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
603
604
605
606
607
608
609
  		if (ret) {
  			if (ret == NILFS_SEG_FAIL_IO) {
  				err = -EIO;
  				goto failed;
  			}
  			goto strayed;
  		}
354fa8be2   Ryusuke Konishi   nilfs2: divide lo...
610

85655484f   Ryusuke Konishi   nilfs2: do not us...
611
612
  		flags = le16_to_cpu(sum->ss_flags);
  		if (flags & NILFS_SS_SR)
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
613
614
615
  			goto confused;
  
  		/* Found a valid partial segment; do recovery actions */
85655484f   Ryusuke Konishi   nilfs2: do not us...
616
617
  		nextnum = nilfs_get_segnum_of_block(nilfs,
  						    le64_to_cpu(sum->ss_next));
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
618
  		empty_seg = 0;
85655484f   Ryusuke Konishi   nilfs2: do not us...
619
620
621
  		nilfs->ns_ctime = le64_to_cpu(sum->ss_create);
  		if (!(flags & NILFS_SS_GC))
  			nilfs->ns_nongc_ctime = nilfs->ns_ctime;
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
622
623
624
  
  		switch (state) {
  		case RF_INIT_ST:
85655484f   Ryusuke Konishi   nilfs2: do not us...
625
626
  			if (!(flags & NILFS_SS_LOGBGN) ||
  			    !(flags & NILFS_SS_SYNDT))
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
627
628
629
630
  				goto try_next_pseg;
  			state = RF_DSYNC_ST;
  			/* Fall through */
  		case RF_DSYNC_ST:
85655484f   Ryusuke Konishi   nilfs2: do not us...
631
  			if (!(flags & NILFS_SS_SYNDT))
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
632
  				goto confused;
85655484f   Ryusuke Konishi   nilfs2: do not us...
633
  			err = nilfs_scan_dsync_log(nilfs, pseg_start, sum,
8b94025c0   Ryusuke Konishi   nilfs2: refactor ...
634
  						   &dsync_blocks);
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
635
636
  			if (unlikely(err))
  				goto failed;
85655484f   Ryusuke Konishi   nilfs2: do not us...
637
  			if (flags & NILFS_SS_LOGEND) {
8b94025c0   Ryusuke Konishi   nilfs2: refactor ...
638
  				err = nilfs_recover_dsync_blocks(
f7545144c   Ryusuke Konishi   nilfs2: use sb in...
639
  					nilfs, sb, root, &dsync_blocks,
8b94025c0   Ryusuke Konishi   nilfs2: refactor ...
640
  					&nsalvaged_blocks);
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
641
642
643
644
645
646
647
648
649
650
  				if (unlikely(err))
  					goto failed;
  				state = RF_INIT_ST;
  			}
  			break; /* Fall through to try_next_pseg */
  		}
  
   try_next_pseg:
  		if (pseg_start == ri->ri_lsegs_end)
  			break;
85655484f   Ryusuke Konishi   nilfs2: do not us...
651
  		pseg_start += le32_to_cpu(sum->ss_nblocks);
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
  		if (pseg_start < seg_end)
  			continue;
  		goto feed_segment;
  
   strayed:
  		if (pseg_start == ri->ri_lsegs_end)
  			break;
  
   feed_segment:
  		/* Looking to the next full segment */
  		if (empty_seg++)
  			break;
  		seg_seq++;
  		segnum = nextnum;
  		nilfs_get_segment_range(nilfs, segnum, &seg_start, &seg_end);
  		pseg_start = seg_start;
  	}
  
  	if (nsalvaged_blocks) {
  		printk(KERN_INFO "NILFS (device %s): salvaged %lu blocks
  ",
f7545144c   Ryusuke Konishi   nilfs2: use sb in...
673
  		       sb->s_id, nsalvaged_blocks);
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
674
675
676
  		ri->ri_need_recovery = NILFS_RECOVERY_ROLLFORWARD_DONE;
  	}
   out:
354fa8be2   Ryusuke Konishi   nilfs2: divide lo...
677
  	brelse(bh_sum);
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
678
  	dispose_recovery_list(&dsync_blocks);
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
679
680
681
682
683
684
685
686
  	return err;
  
   confused:
  	err = -EINVAL;
   failed:
  	printk(KERN_ERR
  	       "NILFS (device %s): Error roll-forwarding "
  	       "(err=%d, pseg block=%llu). ",
f7545144c   Ryusuke Konishi   nilfs2: use sb in...
687
  	       sb->s_id, err, (unsigned long long)pseg_start);
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
688
689
690
691
  	goto out;
  }
  
  static void nilfs_finish_roll_forward(struct the_nilfs *nilfs,
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
692
693
694
695
696
697
698
699
  				      struct nilfs_recovery_info *ri)
  {
  	struct buffer_head *bh;
  	int err;
  
  	if (nilfs_get_segnum_of_block(nilfs, ri->ri_lsegs_start) !=
  	    nilfs_get_segnum_of_block(nilfs, ri->ri_super_root))
  		return;
8b94025c0   Ryusuke Konishi   nilfs2: refactor ...
700
  	bh = __getblk(nilfs->ns_bdev, ri->ri_lsegs_start, nilfs->ns_blocksize);
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
701
702
703
704
705
706
707
708
709
710
711
712
713
  	BUG_ON(!bh);
  	memset(bh->b_data, 0, bh->b_size);
  	set_buffer_dirty(bh);
  	err = sync_dirty_buffer(bh);
  	if (unlikely(err))
  		printk(KERN_WARNING
  		       "NILFS warning: buffer sync write failed during "
  		       "post-cleaning of recovery.
  ");
  	brelse(bh);
  }
  
  /**
aee5ce2f5   Ryusuke Konishi   nilfs2: rename ni...
714
715
   * nilfs_salvage_orphan_logs - salvage logs written after the latest checkpoint
   * @nilfs: nilfs object
f7545144c   Ryusuke Konishi   nilfs2: use sb in...
716
   * @sb: super block instance
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
   * @ri: pointer to a nilfs_recovery_info struct to store search results.
   *
   * Return Value: On success, 0 is returned.  On error, one of the following
   * negative error code is returned.
   *
   * %-EINVAL - Inconsistent filesystem state.
   *
   * %-EIO - I/O error
   *
   * %-ENOSPC - No space left on device (only in a panic state).
   *
   * %-ERESTARTSYS - Interrupted.
   *
   * %-ENOMEM - Insufficient memory available.
   */
aee5ce2f5   Ryusuke Konishi   nilfs2: rename ni...
732
  int nilfs_salvage_orphan_logs(struct the_nilfs *nilfs,
f7545144c   Ryusuke Konishi   nilfs2: use sb in...
733
  			      struct super_block *sb,
aee5ce2f5   Ryusuke Konishi   nilfs2: rename ni...
734
  			      struct nilfs_recovery_info *ri)
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
735
  {
4d8d9293d   Ryusuke Konishi   nilfs2: set point...
736
  	struct nilfs_root *root;
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
737
738
739
740
  	int err;
  
  	if (ri->ri_lsegs_start == 0 || ri->ri_lsegs_end == 0)
  		return 0;
f7545144c   Ryusuke Konishi   nilfs2: use sb in...
741
  	err = nilfs_attach_checkpoint(sb, ri->ri_cno, true, &root);
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
742
743
744
745
746
747
  	if (unlikely(err)) {
  		printk(KERN_ERR
  		       "NILFS: error loading the latest checkpoint.
  ");
  		return err;
  	}
f7545144c   Ryusuke Konishi   nilfs2: use sb in...
748
  	err = nilfs_do_roll_forward(nilfs, sb, root, ri);
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
749
750
751
752
  	if (unlikely(err))
  		goto failed;
  
  	if (ri->ri_need_recovery == NILFS_RECOVERY_ROLLFORWARD_DONE) {
f7545144c   Ryusuke Konishi   nilfs2: use sb in...
753
  		err = nilfs_prepare_segment_for_recovery(nilfs, sb, ri);
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
754
755
756
757
758
759
  		if (unlikely(err)) {
  			printk(KERN_ERR "NILFS: Error preparing segments for "
  			       "recovery.
  ");
  			goto failed;
  		}
f7545144c   Ryusuke Konishi   nilfs2: use sb in...
760
  		err = nilfs_attach_log_writer(sb, root);
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
761
762
763
764
  		if (unlikely(err))
  			goto failed;
  
  		set_nilfs_discontinued(nilfs);
f7545144c   Ryusuke Konishi   nilfs2: use sb in...
765
766
  		err = nilfs_construct_segment(sb);
  		nilfs_detach_log_writer(sb);
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
767
768
769
770
771
772
773
  
  		if (unlikely(err)) {
  			printk(KERN_ERR "NILFS: Oops! recovery failed. "
  			       "(err=%d)
  ", err);
  			goto failed;
  		}
8b94025c0   Ryusuke Konishi   nilfs2: refactor ...
774
  		nilfs_finish_roll_forward(nilfs, ri);
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
775
  	}
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
776
   failed:
4d8d9293d   Ryusuke Konishi   nilfs2: set point...
777
  	nilfs_put_root(root);
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
778
779
780
781
782
783
  	return err;
  }
  
  /**
   * nilfs_search_super_root - search the latest valid super root
   * @nilfs: the_nilfs
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
784
785
786
787
788
789
790
791
792
793
794
795
   * @ri: pointer to a nilfs_recovery_info struct to store search results.
   *
   * nilfs_search_super_root() looks for the latest super-root from a partial
   * segment pointed by the superblock.  It sets up struct the_nilfs through
   * this search. It fills nilfs_recovery_info (ri) required for recovery.
   *
   * Return Value: On success, 0 is returned.  On error, one of the following
   * negative error code is returned.
   *
   * %-EINVAL - No valid segment found
   *
   * %-EIO - I/O error
2d72b99ec   Ryusuke Konishi   nilfs2: add missi...
796
797
   *
   * %-ENOMEM - Insufficient memory available.
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
798
   */
8b94025c0   Ryusuke Konishi   nilfs2: refactor ...
799
  int nilfs_search_super_root(struct the_nilfs *nilfs,
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
800
801
  			    struct nilfs_recovery_info *ri)
  {
354fa8be2   Ryusuke Konishi   nilfs2: divide lo...
802
803
  	struct buffer_head *bh_sum = NULL;
  	struct nilfs_segment_summary *sum;
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
804
805
  	sector_t pseg_start, pseg_end, sr_pseg_start = 0;
  	sector_t seg_start, seg_end; /* range of full segment (block number) */
050b4142c   Ryusuke Konishi   nilfs2: apply rea...
806
  	sector_t b, end;
85655484f   Ryusuke Konishi   nilfs2: do not us...
807
808
  	unsigned long nblocks;
  	unsigned int flags;
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
809
810
811
  	u64 seg_seq;
  	__u64 segnum, nextnum = 0;
  	__u64 cno;
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
812
813
814
815
816
817
818
819
820
821
822
  	LIST_HEAD(segments);
  	int empty_seg = 0, scan_newer = 0;
  	int ret;
  
  	pseg_start = nilfs->ns_last_pseg;
  	seg_seq = nilfs->ns_last_seq;
  	cno = nilfs->ns_last_cno;
  	segnum = nilfs_get_segnum_of_block(nilfs, pseg_start);
  
  	/* Calculate range of segment */
  	nilfs_get_segment_range(nilfs, segnum, &seg_start, &seg_end);
050b4142c   Ryusuke Konishi   nilfs2: apply rea...
823
824
825
  	/* Read ahead segment */
  	b = seg_start;
  	while (b <= seg_end)
8b94025c0   Ryusuke Konishi   nilfs2: refactor ...
826
  		__breadahead(nilfs->ns_bdev, b++, nilfs->ns_blocksize);
050b4142c   Ryusuke Konishi   nilfs2: apply rea...
827

0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
828
  	for (;;) {
354fa8be2   Ryusuke Konishi   nilfs2: divide lo...
829
830
831
832
833
834
835
  		brelse(bh_sum);
  		ret = NILFS_SEG_FAIL_IO;
  		bh_sum = nilfs_read_log_header(nilfs, pseg_start, &sum);
  		if (!bh_sum)
  			goto failed;
  
  		ret = nilfs_validate_log(nilfs, seg_seq, bh_sum, sum);
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
836
837
838
839
840
  		if (ret) {
  			if (ret == NILFS_SEG_FAIL_IO)
  				goto failed;
  			goto strayed;
  		}
354fa8be2   Ryusuke Konishi   nilfs2: divide lo...
841

85655484f   Ryusuke Konishi   nilfs2: do not us...
842
843
  		nblocks = le32_to_cpu(sum->ss_nblocks);
  		pseg_end = pseg_start + nblocks - 1;
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
844
845
846
847
848
849
850
851
852
  		if (unlikely(pseg_end > seg_end)) {
  			ret = NILFS_SEG_FAIL_CONSISTENCY;
  			goto strayed;
  		}
  
  		/* A valid partial segment */
  		ri->ri_pseg_start = pseg_start;
  		ri->ri_seq = seg_seq;
  		ri->ri_segnum = segnum;
85655484f   Ryusuke Konishi   nilfs2: do not us...
853
854
  		nextnum = nilfs_get_segnum_of_block(nilfs,
  						    le64_to_cpu(sum->ss_next));
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
855
856
  		ri->ri_nextnum = nextnum;
  		empty_seg = 0;
85655484f   Ryusuke Konishi   nilfs2: do not us...
857
858
  		flags = le16_to_cpu(sum->ss_flags);
  		if (!(flags & NILFS_SS_SR) && !scan_newer) {
050b4142c   Ryusuke Konishi   nilfs2: apply rea...
859
860
861
862
863
864
865
866
867
868
  			/* This will never happen because a superblock
  			   (last_segment) always points to a pseg
  			   having a super root. */
  			ret = NILFS_SEG_FAIL_CONSISTENCY;
  			goto failed;
  		}
  
  		if (pseg_start == seg_start) {
  			nilfs_get_segment_range(nilfs, nextnum, &b, &end);
  			while (b <= end)
8b94025c0   Ryusuke Konishi   nilfs2: refactor ...
869
870
  				__breadahead(nilfs->ns_bdev, b++,
  					     nilfs->ns_blocksize);
050b4142c   Ryusuke Konishi   nilfs2: apply rea...
871
  		}
85655484f   Ryusuke Konishi   nilfs2: do not us...
872
873
  		if (!(flags & NILFS_SS_SR)) {
  			if (!ri->ri_lsegs_start && (flags & NILFS_SS_LOGBGN)) {
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
874
875
876
  				ri->ri_lsegs_start = pseg_start;
  				ri->ri_lsegs_start_seq = seg_seq;
  			}
85655484f   Ryusuke Konishi   nilfs2: do not us...
877
  			if (flags & NILFS_SS_LOGEND)
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
878
879
880
881
882
883
884
885
886
887
  				ri->ri_lsegs_end = pseg_start;
  			goto try_next_pseg;
  		}
  
  		/* A valid super root was found. */
  		ri->ri_cno = cno++;
  		ri->ri_super_root = pseg_end;
  		ri->ri_lsegs_start = ri->ri_lsegs_end = 0;
  
  		nilfs_dispose_segment_list(&segments);
85655484f   Ryusuke Konishi   nilfs2: do not us...
888
889
  		sr_pseg_start = pseg_start;
  		nilfs->ns_pseg_offset = pseg_start + nblocks - seg_start;
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
890
891
892
  		nilfs->ns_seg_seq = seg_seq;
  		nilfs->ns_segnum = segnum;
  		nilfs->ns_cno = cno;  /* nilfs->ns_cno = ri->ri_cno + 1 */
85655484f   Ryusuke Konishi   nilfs2: do not us...
893
  		nilfs->ns_ctime = le64_to_cpu(sum->ss_create);
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
894
895
896
897
  		nilfs->ns_nextnum = nextnum;
  
  		if (scan_newer)
  			ri->ri_need_recovery = NILFS_RECOVERY_SR_UPDATED;
2c2e52fc4   Ryusuke Konishi   nilfs2: extend ni...
898
  		else {
2c2e52fc4   Ryusuke Konishi   nilfs2: extend ni...
899
900
901
902
  			if (nilfs->ns_mount_state & NILFS_VALID_FS)
  				goto super_root_found;
  			scan_newer = 1;
  		}
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
903

0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
904
905
   try_next_pseg:
  		/* Standing on a course, or met an inconsistent state */
85655484f   Ryusuke Konishi   nilfs2: do not us...
906
  		pseg_start += nblocks;
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
  		if (pseg_start < seg_end)
  			continue;
  		goto feed_segment;
  
   strayed:
  		/* Off the trail */
  		if (!scan_newer)
  			/*
  			 * This can happen if a checkpoint was written without
  			 * barriers, or as a result of an I/O failure.
  			 */
  			goto failed;
  
   feed_segment:
  		/* Looking to the next full segment */
  		if (empty_seg++)
  			goto super_root_found; /* found a valid super root */
654137dd4   Ryusuke Konishi   nilfs2: remove he...
924
925
  		ret = nilfs_segment_list_add(&segments, segnum);
  		if (unlikely(ret))
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
926
  			goto failed;
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
927
928
929
930
931
932
933
934
935
  
  		seg_seq++;
  		segnum = nextnum;
  		nilfs_get_segment_range(nilfs, segnum, &seg_start, &seg_end);
  		pseg_start = seg_start;
  	}
  
   super_root_found:
  	/* Updating pointers relating to the latest checkpoint */
354fa8be2   Ryusuke Konishi   nilfs2: divide lo...
936
  	brelse(bh_sum);
0935db747   Ryusuke Konishi   nilfs2: use list_...
937
  	list_splice_tail(&segments, &ri->ri_used_segments);
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
938
939
940
941
942
943
  	nilfs->ns_last_pseg = sr_pseg_start;
  	nilfs->ns_last_seq = nilfs->ns_seg_seq;
  	nilfs->ns_last_cno = ri->ri_cno;
  	return 0;
  
   failed:
354fa8be2   Ryusuke Konishi   nilfs2: divide lo...
944
  	brelse(bh_sum);
0f3e1c7f2   Ryusuke Konishi   nilfs2: recovery ...
945
946
947
  	nilfs_dispose_segment_list(&segments);
  	return (ret < 0) ? ret : nilfs_warn_segment_error(ret);
  }