recovery.c (d9a145fb6e5f37b9903dea8371ab5c3e34e8e2d1) recovery.c (155130a4f7848b1aac439cab6bda1a175507c71c)
1/*
2 * recovery.c - NILFS recovery logic
3 *
4 * Copyright (C) 2005-2008 Nippon Telegraph and Telephone Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or

--- 77 unchanged lines hidden (view full) ---

86 case NILFS_SEG_NO_SUPER_ROOT:
87 printk(KERN_WARNING
88 "NILFS warning: No super root in the last segment\n");
89 break;
90 }
91 return -EINVAL;
92}
93
1/*
2 * recovery.c - NILFS recovery logic
3 *
4 * Copyright (C) 2005-2008 Nippon Telegraph and Telephone Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or

--- 77 unchanged lines hidden (view full) ---

86 case NILFS_SEG_NO_SUPER_ROOT:
87 printk(KERN_WARNING
88 "NILFS warning: No super root in the last segment\n");
89 break;
90 }
91 return -EINVAL;
92}
93
94static void store_segsum_info(struct nilfs_segsum_info *ssi,
95 struct nilfs_segment_summary *sum,
96 unsigned int blocksize)
97{
98 ssi->flags = le16_to_cpu(sum->ss_flags);
99 ssi->seg_seq = le64_to_cpu(sum->ss_seq);
100 ssi->ctime = le64_to_cpu(sum->ss_create);
101 ssi->next = le64_to_cpu(sum->ss_next);
102 ssi->nblocks = le32_to_cpu(sum->ss_nblocks);
103 ssi->nfinfo = le32_to_cpu(sum->ss_nfinfo);
104 ssi->sumbytes = le32_to_cpu(sum->ss_sumbytes);
105
106 ssi->nsumblk = DIV_ROUND_UP(ssi->sumbytes, blocksize);
107 ssi->nfileblk = ssi->nblocks - ssi->nsumblk - !!NILFS_SEG_HAS_SR(ssi);
108
109 /* need to verify ->ss_bytes field if read ->ss_cno */
110}
111
94/**
112/**
95 * nilfs_compute_checksum - compute checksum of blocks continuously
96 * @nilfs: nilfs object
113 * calc_crc_cont - check CRC of blocks continuously
114 * @sbi: nilfs_sb_info
97 * @bhs: buffer head of start block
98 * @sum: place to store result
99 * @offset: offset bytes in the first block
100 * @check_bytes: number of bytes to be checked
101 * @start: DBN of start block
102 * @nblock: number of blocks to be checked
103 */
115 * @bhs: buffer head of start block
116 * @sum: place to store result
117 * @offset: offset bytes in the first block
118 * @check_bytes: number of bytes to be checked
119 * @start: DBN of start block
120 * @nblock: number of blocks to be checked
121 */
104static int nilfs_compute_checksum(struct the_nilfs *nilfs,
105 struct buffer_head *bhs, u32 *sum,
106 unsigned long offset, u64 check_bytes,
107 sector_t start, unsigned long nblock)
122static int calc_crc_cont(struct nilfs_sb_info *sbi, struct buffer_head *bhs,
123 u32 *sum, unsigned long offset, u64 check_bytes,
124 sector_t start, unsigned long nblock)
108{
125{
109 unsigned int blocksize = nilfs->ns_blocksize;
126 unsigned long blocksize = sbi->s_super->s_blocksize;
110 unsigned long size;
111 u32 crc;
112
113 BUG_ON(offset >= blocksize);
114 check_bytes -= offset;
115 size = min_t(u64, check_bytes, blocksize - offset);
127 unsigned long size;
128 u32 crc;
129
130 BUG_ON(offset >= blocksize);
131 check_bytes -= offset;
132 size = min_t(u64, check_bytes, blocksize - offset);
116 crc = crc32_le(nilfs->ns_crc_seed,
133 crc = crc32_le(sbi->s_nilfs->ns_crc_seed,
117 (unsigned char *)bhs->b_data + offset, size);
118 if (--nblock > 0) {
119 do {
134 (unsigned char *)bhs->b_data + offset, size);
135 if (--nblock > 0) {
136 do {
120 struct buffer_head *bh;
121
122 bh = __bread(nilfs->ns_bdev, ++start, blocksize);
137 struct buffer_head *bh
138 = sb_bread(sbi->s_super, ++start);
123 if (!bh)
124 return -EIO;
125 check_bytes -= size;
126 size = min_t(u64, check_bytes, blocksize);
127 crc = crc32_le(crc, bh->b_data, size);
128 brelse(bh);
129 } while (--nblock > 0);
130 }
131 *sum = crc;
132 return 0;
133}
134
135/**
136 * nilfs_read_super_root_block - read super root block
139 if (!bh)
140 return -EIO;
141 check_bytes -= size;
142 size = min_t(u64, check_bytes, blocksize);
143 crc = crc32_le(crc, bh->b_data, size);
144 brelse(bh);
145 } while (--nblock > 0);
146 }
147 *sum = crc;
148 return 0;
149}
150
151/**
152 * nilfs_read_super_root_block - read super root block
137 * @nilfs: nilfs object
153 * @sb: super_block
138 * @sr_block: disk block number of the super root block
139 * @pbh: address of a buffer_head pointer to return super root buffer
140 * @check: CRC check flag
141 */
154 * @sr_block: disk block number of the super root block
155 * @pbh: address of a buffer_head pointer to return super root buffer
156 * @check: CRC check flag
157 */
142int nilfs_read_super_root_block(struct the_nilfs *nilfs, sector_t sr_block,
158int nilfs_read_super_root_block(struct super_block *sb, sector_t sr_block,
143 struct buffer_head **pbh, int check)
144{
145 struct buffer_head *bh_sr;
146 struct nilfs_super_root *sr;
147 u32 crc;
148 int ret;
149
150 *pbh = NULL;
159 struct buffer_head **pbh, int check)
160{
161 struct buffer_head *bh_sr;
162 struct nilfs_super_root *sr;
163 u32 crc;
164 int ret;
165
166 *pbh = NULL;
151 bh_sr = __bread(nilfs->ns_bdev, sr_block, nilfs->ns_blocksize);
167 bh_sr = sb_bread(sb, sr_block);
152 if (unlikely(!bh_sr)) {
153 ret = NILFS_SEG_FAIL_IO;
154 goto failed;
155 }
156
157 sr = (struct nilfs_super_root *)bh_sr->b_data;
158 if (check) {
159 unsigned bytes = le16_to_cpu(sr->sr_bytes);
160
168 if (unlikely(!bh_sr)) {
169 ret = NILFS_SEG_FAIL_IO;
170 goto failed;
171 }
172
173 sr = (struct nilfs_super_root *)bh_sr->b_data;
174 if (check) {
175 unsigned bytes = le16_to_cpu(sr->sr_bytes);
176
161 if (bytes == 0 || bytes > nilfs->ns_blocksize) {
177 if (bytes == 0 || bytes > sb->s_blocksize) {
162 ret = NILFS_SEG_FAIL_CHECKSUM_SUPER_ROOT;
163 goto failed_bh;
164 }
178 ret = NILFS_SEG_FAIL_CHECKSUM_SUPER_ROOT;
179 goto failed_bh;
180 }
165 if (nilfs_compute_checksum(
166 nilfs, bh_sr, &crc, sizeof(sr->sr_sum), bytes,
167 sr_block, 1)) {
181 if (calc_crc_cont(NILFS_SB(sb), bh_sr, &crc,
182 sizeof(sr->sr_sum), bytes, sr_block, 1)) {
168 ret = NILFS_SEG_FAIL_IO;
169 goto failed_bh;
170 }
171 if (crc != le32_to_cpu(sr->sr_sum)) {
172 ret = NILFS_SEG_FAIL_CHECKSUM_SUPER_ROOT;
173 goto failed_bh;
174 }
175 }
176 *pbh = bh_sr;
177 return 0;
178
179 failed_bh:
180 brelse(bh_sr);
181
182 failed:
183 return nilfs_warn_segment_error(ret);
184}
185
186/**
183 ret = NILFS_SEG_FAIL_IO;
184 goto failed_bh;
185 }
186 if (crc != le32_to_cpu(sr->sr_sum)) {
187 ret = NILFS_SEG_FAIL_CHECKSUM_SUPER_ROOT;
188 goto failed_bh;
189 }
190 }
191 *pbh = bh_sr;
192 return 0;
193
194 failed_bh:
195 brelse(bh_sr);
196
197 failed:
198 return nilfs_warn_segment_error(ret);
199}
200
201/**
187 * nilfs_read_log_header - read summary header of the specified log
188 * @nilfs: nilfs object
189 * @start_blocknr: start block number of the log
190 * @sum: pointer to return segment summary structure
202 * load_segment_summary - read segment summary of the specified partial segment
203 * @sbi: nilfs_sb_info
204 * @pseg_start: start disk block number of partial segment
205 * @seg_seq: sequence number requested
206 * @ssi: pointer to nilfs_segsum_info struct to store information
191 */
207 */
192static struct buffer_head *
193nilfs_read_log_header(struct the_nilfs *nilfs, sector_t start_blocknr,
194 struct nilfs_segment_summary **sum)
208static int
209load_segment_summary(struct nilfs_sb_info *sbi, sector_t pseg_start,
210 u64 seg_seq, struct nilfs_segsum_info *ssi)
195{
196 struct buffer_head *bh_sum;
211{
212 struct buffer_head *bh_sum;
197
198 bh_sum = __bread(nilfs->ns_bdev, start_blocknr, nilfs->ns_blocksize);
199 if (bh_sum)
200 *sum = (struct nilfs_segment_summary *)bh_sum->b_data;
201 return bh_sum;
202}
203
204/**
205 * nilfs_validate_log - verify consistency of log
206 * @nilfs: nilfs object
207 * @seg_seq: sequence number of segment
208 * @bh_sum: buffer head of summary block
209 * @sum: segment summary struct
210 */
211static int nilfs_validate_log(struct the_nilfs *nilfs, u64 seg_seq,
212 struct buffer_head *bh_sum,
213 struct nilfs_segment_summary *sum)
214{
213 struct nilfs_segment_summary *sum;
215 unsigned long nblock;
216 u32 crc;
214 unsigned long nblock;
215 u32 crc;
217 int ret;
216 int ret = NILFS_SEG_FAIL_IO;
218
217
219 ret = NILFS_SEG_FAIL_MAGIC;
220 if (le32_to_cpu(sum->ss_magic) != NILFS_SEGSUM_MAGIC)
218 bh_sum = sb_bread(sbi->s_super, pseg_start);
219 if (!bh_sum)
221 goto out;
222
220 goto out;
221
223 ret = NILFS_SEG_FAIL_SEQ;
224 if (le64_to_cpu(sum->ss_seq) != seg_seq)
225 goto out;
222 sum = (struct nilfs_segment_summary *)bh_sum->b_data;
226
223
227 nblock = le32_to_cpu(sum->ss_nblocks);
228 ret = NILFS_SEG_FAIL_CONSISTENCY;
229 if (unlikely(nblock == 0 || nblock > nilfs->ns_blocks_per_segment))
230 /* This limits the number of blocks read in the CRC check */
231 goto out;
224 /* Check consistency of segment summary */
225 if (le32_to_cpu(sum->ss_magic) != NILFS_SEGSUM_MAGIC) {
226 ret = NILFS_SEG_FAIL_MAGIC;
227 goto failed;
228 }
229 store_segsum_info(ssi, sum, sbi->s_super->s_blocksize);
230 if (seg_seq != ssi->seg_seq) {
231 ret = NILFS_SEG_FAIL_SEQ;
232 goto failed;
233 }
232
234
233 ret = NILFS_SEG_FAIL_IO;
234 if (nilfs_compute_checksum(nilfs, bh_sum, &crc, sizeof(sum->ss_datasum),
235 ((u64)nblock << nilfs->ns_blocksize_bits),
236 bh_sum->b_blocknr, nblock))
237 goto out;
238
239 ret = NILFS_SEG_FAIL_CHECKSUM_FULL;
240 if (crc != le32_to_cpu(sum->ss_datasum))
241 goto out;
242 ret = 0;
243out:
235 nblock = ssi->nblocks;
236 if (unlikely(nblock == 0 ||
237 nblock > sbi->s_nilfs->ns_blocks_per_segment)) {
238 /* This limits the number of blocks read in the CRC check */
239 ret = NILFS_SEG_FAIL_CONSISTENCY;
240 goto failed;
241 }
242 if (calc_crc_cont(sbi, bh_sum, &crc, sizeof(sum->ss_datasum),
243 ((u64)nblock << sbi->s_super->s_blocksize_bits),
244 pseg_start, nblock)) {
245 ret = NILFS_SEG_FAIL_IO;
246 goto failed;
247 }
248 if (crc == le32_to_cpu(sum->ss_datasum))
249 ret = 0;
250 else
251 ret = NILFS_SEG_FAIL_CHECKSUM_FULL;
252 failed:
253 brelse(bh_sum);
254 out:
244 return ret;
245}
246
255 return ret;
256}
257
247/**
248 * nilfs_read_summary_info - read an item on summary blocks of a log
249 * @nilfs: nilfs object
250 * @pbh: the current buffer head on summary blocks [in, out]
251 * @offset: the current byte offset on summary blocks [in, out]
252 * @bytes: byte size of the item to be read
253 */
254static void *nilfs_read_summary_info(struct the_nilfs *nilfs,
255 struct buffer_head **pbh,
256 unsigned int *offset, unsigned int bytes)
258static void *segsum_get(struct super_block *sb, struct buffer_head **pbh,
259 unsigned int *offset, unsigned int bytes)
257{
258 void *ptr;
259 sector_t blocknr;
260
261 BUG_ON((*pbh)->b_size < *offset);
262 if (bytes > (*pbh)->b_size - *offset) {
263 blocknr = (*pbh)->b_blocknr;
264 brelse(*pbh);
260{
261 void *ptr;
262 sector_t blocknr;
263
264 BUG_ON((*pbh)->b_size < *offset);
265 if (bytes > (*pbh)->b_size - *offset) {
266 blocknr = (*pbh)->b_blocknr;
267 brelse(*pbh);
265 *pbh = __bread(nilfs->ns_bdev, blocknr + 1,
266 nilfs->ns_blocksize);
268 *pbh = sb_bread(sb, blocknr + 1);
267 if (unlikely(!*pbh))
268 return NULL;
269 *offset = 0;
270 }
271 ptr = (*pbh)->b_data + *offset;
272 *offset += bytes;
273 return ptr;
274}
275
269 if (unlikely(!*pbh))
270 return NULL;
271 *offset = 0;
272 }
273 ptr = (*pbh)->b_data + *offset;
274 *offset += bytes;
275 return ptr;
276}
277
276/**
277 * nilfs_skip_summary_info - skip items on summary blocks of a log
278 * @nilfs: nilfs object
279 * @pbh: the current buffer head on summary blocks [in, out]
280 * @offset: the current byte offset on summary blocks [in, out]
281 * @bytes: byte size of the item to be skipped
282 * @count: number of items to be skipped
283 */
284static void nilfs_skip_summary_info(struct the_nilfs *nilfs,
285 struct buffer_head **pbh,
286 unsigned int *offset, unsigned int bytes,
287 unsigned long count)
278static void segsum_skip(struct super_block *sb, struct buffer_head **pbh,
279 unsigned int *offset, unsigned int bytes,
280 unsigned long count)
288{
289 unsigned int rest_item_in_current_block
290 = ((*pbh)->b_size - *offset) / bytes;
291
292 if (count <= rest_item_in_current_block) {
293 *offset += bytes * count;
294 } else {
295 sector_t blocknr = (*pbh)->b_blocknr;
296 unsigned int nitem_per_block = (*pbh)->b_size / bytes;
297 unsigned int bcnt;
298
299 count -= rest_item_in_current_block;
300 bcnt = DIV_ROUND_UP(count, nitem_per_block);
301 *offset = bytes * (count - (bcnt - 1) * nitem_per_block);
302
303 brelse(*pbh);
281{
282 unsigned int rest_item_in_current_block
283 = ((*pbh)->b_size - *offset) / bytes;
284
285 if (count <= rest_item_in_current_block) {
286 *offset += bytes * count;
287 } else {
288 sector_t blocknr = (*pbh)->b_blocknr;
289 unsigned int nitem_per_block = (*pbh)->b_size / bytes;
290 unsigned int bcnt;
291
292 count -= rest_item_in_current_block;
293 bcnt = DIV_ROUND_UP(count, nitem_per_block);
294 *offset = bytes * (count - (bcnt - 1) * nitem_per_block);
295
296 brelse(*pbh);
304 *pbh = __bread(nilfs->ns_bdev, blocknr + bcnt,
305 nilfs->ns_blocksize);
297 *pbh = sb_bread(sb, blocknr + bcnt);
306 }
307}
308
298 }
299}
300
309/**
310 * nilfs_scan_dsync_log - get block information of a log written for data sync
311 * @nilfs: nilfs object
312 * @start_blocknr: start block number of the log
313 * @sum: log summary information
314 * @head: list head to add nilfs_recovery_block struct
315 */
316static int nilfs_scan_dsync_log(struct the_nilfs *nilfs, sector_t start_blocknr,
317 struct nilfs_segment_summary *sum,
318 struct list_head *head)
301static int
302collect_blocks_from_segsum(struct nilfs_sb_info *sbi, sector_t sum_blocknr,
303 struct nilfs_segsum_info *ssi,
304 struct list_head *head)
319{
320 struct buffer_head *bh;
321 unsigned int offset;
305{
306 struct buffer_head *bh;
307 unsigned int offset;
322 u32 nfinfo, sumbytes;
323 sector_t blocknr;
308 unsigned long nfinfo = ssi->nfinfo;
309 sector_t blocknr = sum_blocknr + ssi->nsumblk;
324 ino_t ino;
325 int err = -EIO;
326
310 ino_t ino;
311 int err = -EIO;
312
327 nfinfo = le32_to_cpu(sum->ss_nfinfo);
328 if (!nfinfo)
329 return 0;
330
313 if (!nfinfo)
314 return 0;
315
331 sumbytes = le32_to_cpu(sum->ss_sumbytes);
332 blocknr = start_blocknr + DIV_ROUND_UP(sumbytes, nilfs->ns_blocksize);
333 bh = __bread(nilfs->ns_bdev, start_blocknr, nilfs->ns_blocksize);
316 bh = sb_bread(sbi->s_super, sum_blocknr);
334 if (unlikely(!bh))
335 goto out;
336
317 if (unlikely(!bh))
318 goto out;
319
337 offset = le16_to_cpu(sum->ss_bytes);
320 offset = le16_to_cpu(
321 ((struct nilfs_segment_summary *)bh->b_data)->ss_bytes);
338 for (;;) {
339 unsigned long nblocks, ndatablk, nnodeblk;
340 struct nilfs_finfo *finfo;
341
322 for (;;) {
323 unsigned long nblocks, ndatablk, nnodeblk;
324 struct nilfs_finfo *finfo;
325
342 finfo = nilfs_read_summary_info(nilfs, &bh, &offset,
343 sizeof(*finfo));
326 finfo = segsum_get(sbi->s_super, &bh, &offset, sizeof(*finfo));
344 if (unlikely(!finfo))
345 goto out;
346
347 ino = le64_to_cpu(finfo->fi_ino);
348 nblocks = le32_to_cpu(finfo->fi_nblocks);
349 ndatablk = le32_to_cpu(finfo->fi_ndatablk);
350 nnodeblk = nblocks - ndatablk;
351
352 while (ndatablk-- > 0) {
353 struct nilfs_recovery_block *rb;
354 struct nilfs_binfo_v *binfo;
355
327 if (unlikely(!finfo))
328 goto out;
329
330 ino = le64_to_cpu(finfo->fi_ino);
331 nblocks = le32_to_cpu(finfo->fi_nblocks);
332 ndatablk = le32_to_cpu(finfo->fi_ndatablk);
333 nnodeblk = nblocks - ndatablk;
334
335 while (ndatablk-- > 0) {
336 struct nilfs_recovery_block *rb;
337 struct nilfs_binfo_v *binfo;
338
356 binfo = nilfs_read_summary_info(nilfs, &bh, &offset,
357 sizeof(*binfo));
339 binfo = segsum_get(sbi->s_super, &bh, &offset,
340 sizeof(*binfo));
358 if (unlikely(!binfo))
359 goto out;
360
361 rb = kmalloc(sizeof(*rb), GFP_NOFS);
362 if (unlikely(!rb)) {
363 err = -ENOMEM;
364 goto out;
365 }
366 rb->ino = ino;
367 rb->blocknr = blocknr++;
368 rb->vblocknr = le64_to_cpu(binfo->bi_vblocknr);
369 rb->blkoff = le64_to_cpu(binfo->bi_blkoff);
370 /* INIT_LIST_HEAD(&rb->list); */
371 list_add_tail(&rb->list, head);
372 }
373 if (--nfinfo == 0)
374 break;
341 if (unlikely(!binfo))
342 goto out;
343
344 rb = kmalloc(sizeof(*rb), GFP_NOFS);
345 if (unlikely(!rb)) {
346 err = -ENOMEM;
347 goto out;
348 }
349 rb->ino = ino;
350 rb->blocknr = blocknr++;
351 rb->vblocknr = le64_to_cpu(binfo->bi_vblocknr);
352 rb->blkoff = le64_to_cpu(binfo->bi_blkoff);
353 /* INIT_LIST_HEAD(&rb->list); */
354 list_add_tail(&rb->list, head);
355 }
356 if (--nfinfo == 0)
357 break;
375 blocknr += nnodeblk; /* always 0 for data sync logs */
376 nilfs_skip_summary_info(nilfs, &bh, &offset, sizeof(__le64),
377 nnodeblk);
358 blocknr += nnodeblk; /* always 0 for the data sync segments */
359 segsum_skip(sbi->s_super, &bh, &offset, sizeof(__le64),
360 nnodeblk);
378 if (unlikely(!bh))
379 goto out;
380 }
381 err = 0;
382 out:
383 brelse(bh); /* brelse(NULL) is just ignored */
384 return err;
385}

--- 93 unchanged lines hidden (view full) ---

479 nilfs->ns_nextnum = nilfs->ns_segnum = segnum[0];
480
481 failed:
482 /* No need to recover sufile because it will be destroyed on error */
483 nilfs_detach_writer(nilfs, sbi);
484 return err;
485}
486
361 if (unlikely(!bh))
362 goto out;
363 }
364 err = 0;
365 out:
366 brelse(bh); /* brelse(NULL) is just ignored */
367 return err;
368}

--- 93 unchanged lines hidden (view full) ---

462 nilfs->ns_nextnum = nilfs->ns_segnum = segnum[0];
463
464 failed:
465 /* No need to recover sufile because it will be destroyed on error */
466 nilfs_detach_writer(nilfs, sbi);
467 return err;
468}
469
487static int nilfs_recovery_copy_block(struct the_nilfs *nilfs,
470static int nilfs_recovery_copy_block(struct nilfs_sb_info *sbi,
488 struct nilfs_recovery_block *rb,
489 struct page *page)
490{
491 struct buffer_head *bh_org;
492 void *kaddr;
493
471 struct nilfs_recovery_block *rb,
472 struct page *page)
473{
474 struct buffer_head *bh_org;
475 void *kaddr;
476
494 bh_org = __bread(nilfs->ns_bdev, rb->blocknr, nilfs->ns_blocksize);
477 bh_org = sb_bread(sbi->s_super, rb->blocknr);
495 if (unlikely(!bh_org))
496 return -EIO;
497
498 kaddr = kmap_atomic(page, KM_USER0);
499 memcpy(kaddr + bh_offset(bh_org), bh_org->b_data, bh_org->b_size);
500 kunmap_atomic(kaddr, KM_USER0);
501 brelse(bh_org);
502 return 0;
503}
504
478 if (unlikely(!bh_org))
479 return -EIO;
480
481 kaddr = kmap_atomic(page, KM_USER0);
482 memcpy(kaddr + bh_offset(bh_org), bh_org->b_data, bh_org->b_size);
483 kunmap_atomic(kaddr, KM_USER0);
484 brelse(bh_org);
485 return 0;
486}
487
505static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs,
506 struct nilfs_sb_info *sbi,
507 struct list_head *head,
508 unsigned long *nr_salvaged_blocks)
488static int recover_dsync_blocks(struct nilfs_sb_info *sbi,
489 struct list_head *head,
490 unsigned long *nr_salvaged_blocks)
509{
510 struct inode *inode;
511 struct nilfs_recovery_block *rb, *n;
491{
492 struct inode *inode;
493 struct nilfs_recovery_block *rb, *n;
512 unsigned blocksize = nilfs->ns_blocksize;
494 unsigned blocksize = sbi->s_super->s_blocksize;
513 struct page *page;
514 loff_t pos;
515 int err = 0, err2 = 0;
516
517 list_for_each_entry_safe(rb, n, head, list) {
518 inode = nilfs_iget(sbi->s_super, rb->ino);
519 if (IS_ERR(inode)) {
520 err = PTR_ERR(inode);
521 inode = NULL;
522 goto failed_inode;
523 }
524
525 pos = rb->blkoff << inode->i_blkbits;
495 struct page *page;
496 loff_t pos;
497 int err = 0, err2 = 0;
498
499 list_for_each_entry_safe(rb, n, head, list) {
500 inode = nilfs_iget(sbi->s_super, rb->ino);
501 if (IS_ERR(inode)) {
502 err = PTR_ERR(inode);
503 inode = NULL;
504 goto failed_inode;
505 }
506
507 pos = rb->blkoff << inode->i_blkbits;
526 page = NULL;
527 err = block_write_begin(NULL, inode->i_mapping, pos, blocksize,
528 0, &page, NULL, nilfs_get_block);
529 if (unlikely(err))
508 err = block_write_begin(inode->i_mapping, pos, blocksize,
509 0, &page, nilfs_get_block);
510 if (unlikely(err)) {
511 loff_t isize = inode->i_size;
512 if (pos + blocksize > isize)
513 vmtruncate(inode, isize);
530 goto failed_inode;
514 goto failed_inode;
515 }
531
516
532 err = nilfs_recovery_copy_block(nilfs, rb, page);
517 err = nilfs_recovery_copy_block(sbi, rb, page);
533 if (unlikely(err))
534 goto failed_page;
535
536 err = nilfs_set_file_dirty(sbi, inode, 1);
537 if (unlikely(err))
538 goto failed_page;
539
540 block_write_end(NULL, inode->i_mapping, pos, blocksize,

--- 23 unchanged lines hidden (view full) ---

564 kfree(rb);
565 }
566 return err2;
567}
568
569/**
570 * nilfs_do_roll_forward - salvage logical segments newer than the latest
571 * checkpoint
518 if (unlikely(err))
519 goto failed_page;
520
521 err = nilfs_set_file_dirty(sbi, inode, 1);
522 if (unlikely(err))
523 goto failed_page;
524
525 block_write_end(NULL, inode->i_mapping, pos, blocksize,

--- 23 unchanged lines hidden (view full) ---

549 kfree(rb);
550 }
551 return err2;
552}
553
554/**
555 * nilfs_do_roll_forward - salvage logical segments newer than the latest
556 * checkpoint
572 * @nilfs: nilfs object
573 * @sbi: nilfs_sb_info
557 * @sbi: nilfs_sb_info
558 * @nilfs: the_nilfs
574 * @ri: pointer to a nilfs_recovery_info
575 */
576static int nilfs_do_roll_forward(struct the_nilfs *nilfs,
577 struct nilfs_sb_info *sbi,
578 struct nilfs_recovery_info *ri)
579{
559 * @ri: pointer to a nilfs_recovery_info
560 */
561static int nilfs_do_roll_forward(struct the_nilfs *nilfs,
562 struct nilfs_sb_info *sbi,
563 struct nilfs_recovery_info *ri)
564{
580 struct buffer_head *bh_sum = NULL;
581 struct nilfs_segment_summary *sum;
565 struct nilfs_segsum_info ssi;
582 sector_t pseg_start;
583 sector_t seg_start, seg_end; /* Starting/ending DBN of full segment */
584 unsigned long nsalvaged_blocks = 0;
566 sector_t pseg_start;
567 sector_t seg_start, seg_end; /* Starting/ending DBN of full segment */
568 unsigned long nsalvaged_blocks = 0;
585 unsigned int flags;
586 u64 seg_seq;
587 __u64 segnum, nextnum = 0;
588 int empty_seg = 0;
589 int err = 0, ret;
590 LIST_HEAD(dsync_blocks); /* list of data blocks to be recovered */
591 enum {
592 RF_INIT_ST,
593 RF_DSYNC_ST, /* scanning data-sync segments */
594 };
595 int state = RF_INIT_ST;
596
597 nilfs_attach_writer(nilfs, sbi);
598 pseg_start = ri->ri_lsegs_start;
599 seg_seq = ri->ri_lsegs_start_seq;
600 segnum = nilfs_get_segnum_of_block(nilfs, pseg_start);
601 nilfs_get_segment_range(nilfs, segnum, &seg_start, &seg_end);
602
603 while (segnum != ri->ri_segnum || pseg_start <= ri->ri_pseg_start) {
569 u64 seg_seq;
570 __u64 segnum, nextnum = 0;
571 int empty_seg = 0;
572 int err = 0, ret;
573 LIST_HEAD(dsync_blocks); /* list of data blocks to be recovered */
574 enum {
575 RF_INIT_ST,
576 RF_DSYNC_ST, /* scanning data-sync segments */
577 };
578 int state = RF_INIT_ST;
579
580 nilfs_attach_writer(nilfs, sbi);
581 pseg_start = ri->ri_lsegs_start;
582 seg_seq = ri->ri_lsegs_start_seq;
583 segnum = nilfs_get_segnum_of_block(nilfs, pseg_start);
584 nilfs_get_segment_range(nilfs, segnum, &seg_start, &seg_end);
585
586 while (segnum != ri->ri_segnum || pseg_start <= ri->ri_pseg_start) {
604 brelse(bh_sum);
605 bh_sum = nilfs_read_log_header(nilfs, pseg_start, &sum);
606 if (!bh_sum) {
607 err = -EIO;
608 goto failed;
609 }
610
587
611 ret = nilfs_validate_log(nilfs, seg_seq, bh_sum, sum);
588 ret = load_segment_summary(sbi, pseg_start, seg_seq, &ssi);
612 if (ret) {
613 if (ret == NILFS_SEG_FAIL_IO) {
614 err = -EIO;
615 goto failed;
616 }
617 goto strayed;
618 }
589 if (ret) {
590 if (ret == NILFS_SEG_FAIL_IO) {
591 err = -EIO;
592 goto failed;
593 }
594 goto strayed;
595 }
619
620 flags = le16_to_cpu(sum->ss_flags);
621 if (flags & NILFS_SS_SR)
596 if (unlikely(NILFS_SEG_HAS_SR(&ssi)))
622 goto confused;
623
624 /* Found a valid partial segment; do recovery actions */
597 goto confused;
598
599 /* Found a valid partial segment; do recovery actions */
625 nextnum = nilfs_get_segnum_of_block(nilfs,
626 le64_to_cpu(sum->ss_next));
600 nextnum = nilfs_get_segnum_of_block(nilfs, ssi.next);
627 empty_seg = 0;
601 empty_seg = 0;
628 nilfs->ns_ctime = le64_to_cpu(sum->ss_create);
629 if (!(flags & NILFS_SS_GC))
630 nilfs->ns_nongc_ctime = nilfs->ns_ctime;
602 nilfs->ns_ctime = ssi.ctime;
603 if (!(ssi.flags & NILFS_SS_GC))
604 nilfs->ns_nongc_ctime = ssi.ctime;
631
632 switch (state) {
633 case RF_INIT_ST:
605
606 switch (state) {
607 case RF_INIT_ST:
634 if (!(flags & NILFS_SS_LOGBGN) ||
635 !(flags & NILFS_SS_SYNDT))
608 if (!NILFS_SEG_LOGBGN(&ssi) || !NILFS_SEG_DSYNC(&ssi))
636 goto try_next_pseg;
637 state = RF_DSYNC_ST;
638 /* Fall through */
639 case RF_DSYNC_ST:
609 goto try_next_pseg;
610 state = RF_DSYNC_ST;
611 /* Fall through */
612 case RF_DSYNC_ST:
640 if (!(flags & NILFS_SS_SYNDT))
613 if (!NILFS_SEG_DSYNC(&ssi))
641 goto confused;
642
614 goto confused;
615
643 err = nilfs_scan_dsync_log(nilfs, pseg_start, sum,
644 &dsync_blocks);
616 err = collect_blocks_from_segsum(
617 sbi, pseg_start, &ssi, &dsync_blocks);
645 if (unlikely(err))
646 goto failed;
618 if (unlikely(err))
619 goto failed;
647 if (flags & NILFS_SS_LOGEND) {
648 err = nilfs_recover_dsync_blocks(
649 nilfs, sbi, &dsync_blocks,
650 &nsalvaged_blocks);
620 if (NILFS_SEG_LOGEND(&ssi)) {
621 err = recover_dsync_blocks(
622 sbi, &dsync_blocks, &nsalvaged_blocks);
651 if (unlikely(err))
652 goto failed;
653 state = RF_INIT_ST;
654 }
655 break; /* Fall through to try_next_pseg */
656 }
657
658 try_next_pseg:
659 if (pseg_start == ri->ri_lsegs_end)
660 break;
623 if (unlikely(err))
624 goto failed;
625 state = RF_INIT_ST;
626 }
627 break; /* Fall through to try_next_pseg */
628 }
629
630 try_next_pseg:
631 if (pseg_start == ri->ri_lsegs_end)
632 break;
661 pseg_start += le32_to_cpu(sum->ss_nblocks);
633 pseg_start += ssi.nblocks;
662 if (pseg_start < seg_end)
663 continue;
664 goto feed_segment;
665
666 strayed:
667 if (pseg_start == ri->ri_lsegs_end)
668 break;
669

--- 8 unchanged lines hidden (view full) ---

678 }
679
680 if (nsalvaged_blocks) {
681 printk(KERN_INFO "NILFS (device %s): salvaged %lu blocks\n",
682 sbi->s_super->s_id, nsalvaged_blocks);
683 ri->ri_need_recovery = NILFS_RECOVERY_ROLLFORWARD_DONE;
684 }
685 out:
634 if (pseg_start < seg_end)
635 continue;
636 goto feed_segment;
637
638 strayed:
639 if (pseg_start == ri->ri_lsegs_end)
640 break;
641

--- 8 unchanged lines hidden (view full) ---

650 }
651
652 if (nsalvaged_blocks) {
653 printk(KERN_INFO "NILFS (device %s): salvaged %lu blocks\n",
654 sbi->s_super->s_id, nsalvaged_blocks);
655 ri->ri_need_recovery = NILFS_RECOVERY_ROLLFORWARD_DONE;
656 }
657 out:
686 brelse(bh_sum);
687 dispose_recovery_list(&dsync_blocks);
658 dispose_recovery_list(&dsync_blocks);
688 nilfs_detach_writer(nilfs, sbi);
659 nilfs_detach_writer(sbi->s_nilfs, sbi);
689 return err;
690
691 confused:
692 err = -EINVAL;
693 failed:
694 printk(KERN_ERR
695 "NILFS (device %s): Error roll-forwarding "
696 "(err=%d, pseg block=%llu). ",
697 sbi->s_super->s_id, err, (unsigned long long)pseg_start);
698 goto out;
699}
700
701static void nilfs_finish_roll_forward(struct the_nilfs *nilfs,
660 return err;
661
662 confused:
663 err = -EINVAL;
664 failed:
665 printk(KERN_ERR
666 "NILFS (device %s): Error roll-forwarding "
667 "(err=%d, pseg block=%llu). ",
668 sbi->s_super->s_id, err, (unsigned long long)pseg_start);
669 goto out;
670}
671
672static void nilfs_finish_roll_forward(struct the_nilfs *nilfs,
673 struct nilfs_sb_info *sbi,
702 struct nilfs_recovery_info *ri)
703{
704 struct buffer_head *bh;
705 int err;
706
707 if (nilfs_get_segnum_of_block(nilfs, ri->ri_lsegs_start) !=
708 nilfs_get_segnum_of_block(nilfs, ri->ri_super_root))
709 return;
710
674 struct nilfs_recovery_info *ri)
675{
676 struct buffer_head *bh;
677 int err;
678
679 if (nilfs_get_segnum_of_block(nilfs, ri->ri_lsegs_start) !=
680 nilfs_get_segnum_of_block(nilfs, ri->ri_super_root))
681 return;
682
711 bh = __getblk(nilfs->ns_bdev, ri->ri_lsegs_start, nilfs->ns_blocksize);
683 bh = sb_getblk(sbi->s_super, ri->ri_lsegs_start);
712 BUG_ON(!bh);
713 memset(bh->b_data, 0, bh->b_size);
714 set_buffer_dirty(bh);
715 err = sync_dirty_buffer(bh);
716 if (unlikely(err))
717 printk(KERN_WARNING
718 "NILFS warning: buffer sync write failed during "
719 "post-cleaning of recovery.\n");
720 brelse(bh);
721}
722
723/**
684 BUG_ON(!bh);
685 memset(bh->b_data, 0, bh->b_size);
686 set_buffer_dirty(bh);
687 err = sync_dirty_buffer(bh);
688 if (unlikely(err))
689 printk(KERN_WARNING
690 "NILFS warning: buffer sync write failed during "
691 "post-cleaning of recovery.\n");
692 brelse(bh);
693}
694
695/**
724 * nilfs_salvage_orphan_logs - salvage logs written after the latest checkpoint
725 * @nilfs: nilfs object
696 * nilfs_recover_logical_segments - salvage logical segments written after
697 * the latest super root
698 * @nilfs: the_nilfs
726 * @sbi: nilfs_sb_info
727 * @ri: pointer to a nilfs_recovery_info struct to store search results.
728 *
729 * Return Value: On success, 0 is returned. On error, one of the following
730 * negative error code is returned.
731 *
732 * %-EINVAL - Inconsistent filesystem state.
733 *
734 * %-EIO - I/O error
735 *
736 * %-ENOSPC - No space left on device (only in a panic state).
737 *
738 * %-ERESTARTSYS - Interrupted.
739 *
740 * %-ENOMEM - Insufficient memory available.
741 */
699 * @sbi: nilfs_sb_info
700 * @ri: pointer to a nilfs_recovery_info struct to store search results.
701 *
702 * Return Value: On success, 0 is returned. On error, one of the following
703 * negative error code is returned.
704 *
705 * %-EINVAL - Inconsistent filesystem state.
706 *
707 * %-EIO - I/O error
708 *
709 * %-ENOSPC - No space left on device (only in a panic state).
710 *
711 * %-ERESTARTSYS - Interrupted.
712 *
713 * %-ENOMEM - Insufficient memory available.
714 */
742int nilfs_salvage_orphan_logs(struct the_nilfs *nilfs,
743 struct nilfs_sb_info *sbi,
744 struct nilfs_recovery_info *ri)
715int nilfs_recover_logical_segments(struct the_nilfs *nilfs,
716 struct nilfs_sb_info *sbi,
717 struct nilfs_recovery_info *ri)
745{
746 int err;
747
748 if (ri->ri_lsegs_start == 0 || ri->ri_lsegs_end == 0)
749 return 0;
750
751 err = nilfs_attach_checkpoint(sbi, ri->ri_cno);
752 if (unlikely(err)) {

--- 23 unchanged lines hidden (view full) ---

776 nilfs_detach_segment_constructor(sbi);
777
778 if (unlikely(err)) {
779 printk(KERN_ERR "NILFS: Oops! recovery failed. "
780 "(err=%d)\n", err);
781 goto failed;
782 }
783
718{
719 int err;
720
721 if (ri->ri_lsegs_start == 0 || ri->ri_lsegs_end == 0)
722 return 0;
723
724 err = nilfs_attach_checkpoint(sbi, ri->ri_cno);
725 if (unlikely(err)) {

--- 23 unchanged lines hidden (view full) ---

749 nilfs_detach_segment_constructor(sbi);
750
751 if (unlikely(err)) {
752 printk(KERN_ERR "NILFS: Oops! recovery failed. "
753 "(err=%d)\n", err);
754 goto failed;
755 }
756
784 nilfs_finish_roll_forward(nilfs, ri);
757 nilfs_finish_roll_forward(nilfs, sbi, ri);
785 }
786
787 failed:
788 nilfs_detach_checkpoint(sbi);
789 return err;
790}
791
792/**
793 * nilfs_search_super_root - search the latest valid super root
794 * @nilfs: the_nilfs
758 }
759
760 failed:
761 nilfs_detach_checkpoint(sbi);
762 return err;
763}
764
765/**
766 * nilfs_search_super_root - search the latest valid super root
767 * @nilfs: the_nilfs
768 * @sbi: nilfs_sb_info
795 * @ri: pointer to a nilfs_recovery_info struct to store search results.
796 *
797 * nilfs_search_super_root() looks for the latest super-root from a partial
798 * segment pointed by the superblock. It sets up struct the_nilfs through
799 * this search. It fills nilfs_recovery_info (ri) required for recovery.
800 *
801 * Return Value: On success, 0 is returned. On error, one of the following
802 * negative error code is returned.
803 *
804 * %-EINVAL - No valid segment found
805 *
806 * %-EIO - I/O error
769 * @ri: pointer to a nilfs_recovery_info struct to store search results.
770 *
771 * nilfs_search_super_root() looks for the latest super-root from a partial
772 * segment pointed by the superblock. It sets up struct the_nilfs through
773 * this search. It fills nilfs_recovery_info (ri) required for recovery.
774 *
775 * Return Value: On success, 0 is returned. On error, one of the following
776 * negative error code is returned.
777 *
778 * %-EINVAL - No valid segment found
779 *
780 * %-EIO - I/O error
807 *
808 * %-ENOMEM - Insufficient memory available.
809 */
781 */
810int nilfs_search_super_root(struct the_nilfs *nilfs,
782int nilfs_search_super_root(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi,
811 struct nilfs_recovery_info *ri)
812{
783 struct nilfs_recovery_info *ri)
784{
813 struct buffer_head *bh_sum = NULL;
814 struct nilfs_segment_summary *sum;
785 struct nilfs_segsum_info ssi;
815 sector_t pseg_start, pseg_end, sr_pseg_start = 0;
816 sector_t seg_start, seg_end; /* range of full segment (block number) */
817 sector_t b, end;
786 sector_t pseg_start, pseg_end, sr_pseg_start = 0;
787 sector_t seg_start, seg_end; /* range of full segment (block number) */
788 sector_t b, end;
818 unsigned long nblocks;
819 unsigned int flags;
820 u64 seg_seq;
821 __u64 segnum, nextnum = 0;
822 __u64 cno;
823 LIST_HEAD(segments);
824 int empty_seg = 0, scan_newer = 0;
825 int ret;
826
827 pseg_start = nilfs->ns_last_pseg;
828 seg_seq = nilfs->ns_last_seq;
829 cno = nilfs->ns_last_cno;
830 segnum = nilfs_get_segnum_of_block(nilfs, pseg_start);
831
832 /* Calculate range of segment */
833 nilfs_get_segment_range(nilfs, segnum, &seg_start, &seg_end);
834
835 /* Read ahead segment */
836 b = seg_start;
837 while (b <= seg_end)
789 u64 seg_seq;
790 __u64 segnum, nextnum = 0;
791 __u64 cno;
792 LIST_HEAD(segments);
793 int empty_seg = 0, scan_newer = 0;
794 int ret;
795
796 pseg_start = nilfs->ns_last_pseg;
797 seg_seq = nilfs->ns_last_seq;
798 cno = nilfs->ns_last_cno;
799 segnum = nilfs_get_segnum_of_block(nilfs, pseg_start);
800
801 /* Calculate range of segment */
802 nilfs_get_segment_range(nilfs, segnum, &seg_start, &seg_end);
803
804 /* Read ahead segment */
805 b = seg_start;
806 while (b <= seg_end)
838 __breadahead(nilfs->ns_bdev, b++, nilfs->ns_blocksize);
807 sb_breadahead(sbi->s_super, b++);
839
840 for (;;) {
808
809 for (;;) {
841 brelse(bh_sum);
842 ret = NILFS_SEG_FAIL_IO;
843 bh_sum = nilfs_read_log_header(nilfs, pseg_start, &sum);
844 if (!bh_sum)
845 goto failed;
846
847 ret = nilfs_validate_log(nilfs, seg_seq, bh_sum, sum);
810 /* Load segment summary */
811 ret = load_segment_summary(sbi, pseg_start, seg_seq, &ssi);
848 if (ret) {
849 if (ret == NILFS_SEG_FAIL_IO)
850 goto failed;
851 goto strayed;
852 }
812 if (ret) {
813 if (ret == NILFS_SEG_FAIL_IO)
814 goto failed;
815 goto strayed;
816 }
853
854 nblocks = le32_to_cpu(sum->ss_nblocks);
855 pseg_end = pseg_start + nblocks - 1;
817 pseg_end = pseg_start + ssi.nblocks - 1;
856 if (unlikely(pseg_end > seg_end)) {
857 ret = NILFS_SEG_FAIL_CONSISTENCY;
858 goto strayed;
859 }
860
861 /* A valid partial segment */
862 ri->ri_pseg_start = pseg_start;
863 ri->ri_seq = seg_seq;
864 ri->ri_segnum = segnum;
818 if (unlikely(pseg_end > seg_end)) {
819 ret = NILFS_SEG_FAIL_CONSISTENCY;
820 goto strayed;
821 }
822
823 /* A valid partial segment */
824 ri->ri_pseg_start = pseg_start;
825 ri->ri_seq = seg_seq;
826 ri->ri_segnum = segnum;
865 nextnum = nilfs_get_segnum_of_block(nilfs,
866 le64_to_cpu(sum->ss_next));
827 nextnum = nilfs_get_segnum_of_block(nilfs, ssi.next);
867 ri->ri_nextnum = nextnum;
868 empty_seg = 0;
869
828 ri->ri_nextnum = nextnum;
829 empty_seg = 0;
830
870 flags = le16_to_cpu(sum->ss_flags);
871 if (!(flags & NILFS_SS_SR) && !scan_newer) {
831 if (!NILFS_SEG_HAS_SR(&ssi) && !scan_newer) {
872 /* This will never happen because a superblock
873 (last_segment) always points to a pseg
874 having a super root. */
875 ret = NILFS_SEG_FAIL_CONSISTENCY;
876 goto failed;
877 }
878
879 if (pseg_start == seg_start) {
880 nilfs_get_segment_range(nilfs, nextnum, &b, &end);
881 while (b <= end)
832 /* This will never happen because a superblock
833 (last_segment) always points to a pseg
834 having a super root. */
835 ret = NILFS_SEG_FAIL_CONSISTENCY;
836 goto failed;
837 }
838
839 if (pseg_start == seg_start) {
840 nilfs_get_segment_range(nilfs, nextnum, &b, &end);
841 while (b <= end)
882 __breadahead(nilfs->ns_bdev, b++,
883 nilfs->ns_blocksize);
842 sb_breadahead(sbi->s_super, b++);
884 }
843 }
885 if (!(flags & NILFS_SS_SR)) {
886 if (!ri->ri_lsegs_start && (flags & NILFS_SS_LOGBGN)) {
844 if (!NILFS_SEG_HAS_SR(&ssi)) {
845 if (!ri->ri_lsegs_start && NILFS_SEG_LOGBGN(&ssi)) {
887 ri->ri_lsegs_start = pseg_start;
888 ri->ri_lsegs_start_seq = seg_seq;
889 }
846 ri->ri_lsegs_start = pseg_start;
847 ri->ri_lsegs_start_seq = seg_seq;
848 }
890 if (flags & NILFS_SS_LOGEND)
849 if (NILFS_SEG_LOGEND(&ssi))
891 ri->ri_lsegs_end = pseg_start;
892 goto try_next_pseg;
893 }
894
895 /* A valid super root was found. */
896 ri->ri_cno = cno++;
897 ri->ri_super_root = pseg_end;
898 ri->ri_lsegs_start = ri->ri_lsegs_end = 0;
899
900 nilfs_dispose_segment_list(&segments);
850 ri->ri_lsegs_end = pseg_start;
851 goto try_next_pseg;
852 }
853
854 /* A valid super root was found. */
855 ri->ri_cno = cno++;
856 ri->ri_super_root = pseg_end;
857 ri->ri_lsegs_start = ri->ri_lsegs_end = 0;
858
859 nilfs_dispose_segment_list(&segments);
901 sr_pseg_start = pseg_start;
902 nilfs->ns_pseg_offset = pseg_start + nblocks - seg_start;
860 nilfs->ns_pseg_offset = (sr_pseg_start = pseg_start)
861 + ssi.nblocks - seg_start;
903 nilfs->ns_seg_seq = seg_seq;
904 nilfs->ns_segnum = segnum;
905 nilfs->ns_cno = cno; /* nilfs->ns_cno = ri->ri_cno + 1 */
862 nilfs->ns_seg_seq = seg_seq;
863 nilfs->ns_segnum = segnum;
864 nilfs->ns_cno = cno; /* nilfs->ns_cno = ri->ri_cno + 1 */
906 nilfs->ns_ctime = le64_to_cpu(sum->ss_create);
865 nilfs->ns_ctime = ssi.ctime;
907 nilfs->ns_nextnum = nextnum;
908
909 if (scan_newer)
910 ri->ri_need_recovery = NILFS_RECOVERY_SR_UPDATED;
911 else {
912 if (nilfs->ns_mount_state & NILFS_VALID_FS)
913 goto super_root_found;
914 scan_newer = 1;
915 }
916
866 nilfs->ns_nextnum = nextnum;
867
868 if (scan_newer)
869 ri->ri_need_recovery = NILFS_RECOVERY_SR_UPDATED;
870 else {
871 if (nilfs->ns_mount_state & NILFS_VALID_FS)
872 goto super_root_found;
873 scan_newer = 1;
874 }
875
876 /* reset region for roll-forward */
877 pseg_start += ssi.nblocks;
878 if (pseg_start < seg_end)
879 continue;
880 goto feed_segment;
881
917 try_next_pseg:
918 /* Standing on a course, or met an inconsistent state */
882 try_next_pseg:
883 /* Standing on a course, or met an inconsistent state */
919 pseg_start += nblocks;
884 pseg_start += ssi.nblocks;
920 if (pseg_start < seg_end)
921 continue;
922 goto feed_segment;
923
924 strayed:
925 /* Off the trail */
926 if (!scan_newer)
927 /*

--- 14 unchanged lines hidden (view full) ---

942 seg_seq++;
943 segnum = nextnum;
944 nilfs_get_segment_range(nilfs, segnum, &seg_start, &seg_end);
945 pseg_start = seg_start;
946 }
947
948 super_root_found:
949 /* Updating pointers relating to the latest checkpoint */
885 if (pseg_start < seg_end)
886 continue;
887 goto feed_segment;
888
889 strayed:
890 /* Off the trail */
891 if (!scan_newer)
892 /*

--- 14 unchanged lines hidden (view full) ---

907 seg_seq++;
908 segnum = nextnum;
909 nilfs_get_segment_range(nilfs, segnum, &seg_start, &seg_end);
910 pseg_start = seg_start;
911 }
912
913 super_root_found:
914 /* Updating pointers relating to the latest checkpoint */
950 brelse(bh_sum);
951 list_splice_tail(&segments, &ri->ri_used_segments);
952 nilfs->ns_last_pseg = sr_pseg_start;
953 nilfs->ns_last_seq = nilfs->ns_seg_seq;
954 nilfs->ns_last_cno = ri->ri_cno;
955 return 0;
956
957 failed:
915 list_splice_tail(&segments, &ri->ri_used_segments);
916 nilfs->ns_last_pseg = sr_pseg_start;
917 nilfs->ns_last_seq = nilfs->ns_seg_seq;
918 nilfs->ns_last_cno = ri->ri_cno;
919 return 0;
920
921 failed:
958 brelse(bh_sum);
959 nilfs_dispose_segment_list(&segments);
960 return (ret < 0) ? ret : nilfs_warn_segment_error(ret);
961}
922 nilfs_dispose_segment_list(&segments);
923 return (ret < 0) ? ret : nilfs_warn_segment_error(ret);
924}