Lines Matching +full:long +full:- +full:summary
1 // SPDX-License-Identifier: GPL-2.0+
3 * recovery.c - NILFS recovery logic
5 * Copyright (C) 2005-2008 Nippon Telegraph and Telephone Corporation.
43 unsigned long blkoff; /* File offset of the data block (per block) */
55 return -EIO; in nilfs_warn_segment_error()
76 return -EINVAL; in nilfs_warn_segment_error()
79 return -EINVAL; in nilfs_warn_segment_error()
83 * nilfs_compute_checksum - compute checksum of blocks continuously
94 unsigned long offset, u64 check_bytes, in nilfs_compute_checksum()
95 sector_t start, unsigned long nblock) in nilfs_compute_checksum()
97 unsigned int blocksize = nilfs->ns_blocksize; in nilfs_compute_checksum()
98 unsigned long size; in nilfs_compute_checksum()
102 check_bytes -= offset; in nilfs_compute_checksum()
103 size = min_t(u64, check_bytes, blocksize - offset); in nilfs_compute_checksum()
104 crc = crc32_le(nilfs->ns_crc_seed, in nilfs_compute_checksum()
105 (unsigned char *)bhs->b_data + offset, size); in nilfs_compute_checksum()
106 if (--nblock > 0) { in nilfs_compute_checksum()
110 bh = __bread(nilfs->ns_bdev, ++start, blocksize); in nilfs_compute_checksum()
112 return -EIO; in nilfs_compute_checksum()
113 check_bytes -= size; in nilfs_compute_checksum()
115 crc = crc32_le(crc, bh->b_data, size); in nilfs_compute_checksum()
117 } while (--nblock > 0); in nilfs_compute_checksum()
124 * nilfs_read_super_root_block - read super root block
139 bh_sr = __bread(nilfs->ns_bdev, sr_block, nilfs->ns_blocksize); in nilfs_read_super_root_block()
145 sr = (struct nilfs_super_root *)bh_sr->b_data; in nilfs_read_super_root_block()
147 unsigned int bytes = le16_to_cpu(sr->sr_bytes); in nilfs_read_super_root_block()
149 if (bytes == 0 || bytes > nilfs->ns_blocksize) { in nilfs_read_super_root_block()
154 nilfs, bh_sr, &crc, sizeof(sr->sr_sum), bytes, in nilfs_read_super_root_block()
159 if (crc != le32_to_cpu(sr->sr_sum)) { in nilfs_read_super_root_block()
171 return nilfs_warn_segment_error(nilfs->ns_sb, ret); in nilfs_read_super_root_block()
175 * nilfs_read_log_header - read summary header of the specified log
178 * @sum: pointer to return segment summary structure
186 bh_sum = __bread(nilfs->ns_bdev, start_blocknr, nilfs->ns_blocksize); in nilfs_read_log_header()
188 *sum = (struct nilfs_segment_summary *)bh_sum->b_data; in nilfs_read_log_header()
193 * nilfs_validate_log - verify consistency of log
196 * @bh_sum: buffer head of summary block
197 * @sum: segment summary struct
203 unsigned long nblock; in nilfs_validate_log()
208 if (le32_to_cpu(sum->ss_magic) != NILFS_SEGSUM_MAGIC) in nilfs_validate_log()
212 if (le64_to_cpu(sum->ss_seq) != seg_seq) in nilfs_validate_log()
215 nblock = le32_to_cpu(sum->ss_nblocks); in nilfs_validate_log()
217 if (unlikely(nblock == 0 || nblock > nilfs->ns_blocks_per_segment)) in nilfs_validate_log()
222 if (nilfs_compute_checksum(nilfs, bh_sum, &crc, sizeof(sum->ss_datasum), in nilfs_validate_log()
223 ((u64)nblock << nilfs->ns_blocksize_bits), in nilfs_validate_log()
224 bh_sum->b_blocknr, nblock)) in nilfs_validate_log()
228 if (crc != le32_to_cpu(sum->ss_datasum)) in nilfs_validate_log()
236 * nilfs_read_summary_info - read an item on summary blocks of a log
238 * @pbh: the current buffer head on summary blocks [in, out]
239 * @offset: the current byte offset on summary blocks [in, out]
249 BUG_ON((*pbh)->b_size < *offset); in nilfs_read_summary_info()
250 if (bytes > (*pbh)->b_size - *offset) { in nilfs_read_summary_info()
251 blocknr = (*pbh)->b_blocknr; in nilfs_read_summary_info()
253 *pbh = __bread(nilfs->ns_bdev, blocknr + 1, in nilfs_read_summary_info()
254 nilfs->ns_blocksize); in nilfs_read_summary_info()
259 ptr = (*pbh)->b_data + *offset; in nilfs_read_summary_info()
265 * nilfs_skip_summary_info - skip items on summary blocks of a log
267 * @pbh: the current buffer head on summary blocks [in, out]
268 * @offset: the current byte offset on summary blocks [in, out]
275 unsigned long count) in nilfs_skip_summary_info()
278 = ((*pbh)->b_size - *offset) / bytes; in nilfs_skip_summary_info()
283 sector_t blocknr = (*pbh)->b_blocknr; in nilfs_skip_summary_info()
284 unsigned int nitem_per_block = (*pbh)->b_size / bytes; in nilfs_skip_summary_info()
287 count -= rest_item_in_current_block; in nilfs_skip_summary_info()
289 *offset = bytes * (count - (bcnt - 1) * nitem_per_block); in nilfs_skip_summary_info()
292 *pbh = __bread(nilfs->ns_bdev, blocknr + bcnt, in nilfs_skip_summary_info()
293 nilfs->ns_blocksize); in nilfs_skip_summary_info()
298 * nilfs_scan_dsync_log - get block information of a log written for data sync
301 * @sum: log summary information
313 int err = -EIO; in nilfs_scan_dsync_log()
315 nfinfo = le32_to_cpu(sum->ss_nfinfo); in nilfs_scan_dsync_log()
319 sumbytes = le32_to_cpu(sum->ss_sumbytes); in nilfs_scan_dsync_log()
320 blocknr = start_blocknr + DIV_ROUND_UP(sumbytes, nilfs->ns_blocksize); in nilfs_scan_dsync_log()
321 bh = __bread(nilfs->ns_bdev, start_blocknr, nilfs->ns_blocksize); in nilfs_scan_dsync_log()
325 offset = le16_to_cpu(sum->ss_bytes); in nilfs_scan_dsync_log()
327 unsigned long nblocks, ndatablk, nnodeblk; in nilfs_scan_dsync_log()
335 ino = le64_to_cpu(finfo->fi_ino); in nilfs_scan_dsync_log()
336 nblocks = le32_to_cpu(finfo->fi_nblocks); in nilfs_scan_dsync_log()
337 ndatablk = le32_to_cpu(finfo->fi_ndatablk); in nilfs_scan_dsync_log()
338 nnodeblk = nblocks - ndatablk; in nilfs_scan_dsync_log()
340 while (ndatablk-- > 0) { in nilfs_scan_dsync_log()
351 err = -ENOMEM; in nilfs_scan_dsync_log()
354 rb->ino = ino; in nilfs_scan_dsync_log()
355 rb->blocknr = blocknr++; in nilfs_scan_dsync_log()
356 rb->vblocknr = le64_to_cpu(binfo->bi_vblocknr); in nilfs_scan_dsync_log()
357 rb->blkoff = le64_to_cpu(binfo->bi_blkoff); in nilfs_scan_dsync_log()
358 /* INIT_LIST_HEAD(&rb->list); */ in nilfs_scan_dsync_log()
359 list_add_tail(&rb->list, head); in nilfs_scan_dsync_log()
361 if (--nfinfo == 0) in nilfs_scan_dsync_log()
381 list_del(&rb->list); in dispose_recovery_list()
396 return -ENOMEM; in nilfs_segment_list_add()
398 ent->segnum = segnum; in nilfs_segment_list_add()
399 INIT_LIST_HEAD(&ent->list); in nilfs_segment_list_add()
400 list_add_tail(&ent->list, head); in nilfs_segment_list_add()
410 list_del(&ent->list); in nilfs_dispose_segment_list()
419 struct list_head *head = &ri->ri_used_segments; in nilfs_prepare_segment_for_recovery()
421 struct inode *sufile = nilfs->ns_sufile; in nilfs_prepare_segment_for_recovery()
426 segnum[0] = nilfs->ns_segnum; in nilfs_prepare_segment_for_recovery()
427 segnum[1] = nilfs->ns_nextnum; in nilfs_prepare_segment_for_recovery()
428 segnum[2] = ri->ri_segnum; in nilfs_prepare_segment_for_recovery()
429 segnum[3] = ri->ri_nextnum; in nilfs_prepare_segment_for_recovery()
450 if (ent->segnum != segnum[0]) { in nilfs_prepare_segment_for_recovery()
451 err = nilfs_sufile_scrap(sufile, ent->segnum); in nilfs_prepare_segment_for_recovery()
455 list_del(&ent->list); in nilfs_prepare_segment_for_recovery()
464 nilfs->ns_pseg_offset = 0; in nilfs_prepare_segment_for_recovery()
465 nilfs->ns_seg_seq = ri->ri_seq + 2; in nilfs_prepare_segment_for_recovery()
466 nilfs->ns_nextnum = nilfs->ns_segnum = segnum[0]; in nilfs_prepare_segment_for_recovery()
480 bh_org = __bread(nilfs->ns_bdev, rb->blocknr, nilfs->ns_blocksize); in nilfs_recovery_copy_block()
482 return -EIO; in nilfs_recovery_copy_block()
485 memcpy(kaddr + bh_offset(bh_org), bh_org->b_data, bh_org->b_size); in nilfs_recovery_copy_block()
495 unsigned long *nr_salvaged_blocks) in nilfs_recover_dsync_blocks()
499 unsigned int blocksize = nilfs->ns_blocksize; in nilfs_recover_dsync_blocks()
505 inode = nilfs_iget(sb, root, rb->ino); in nilfs_recover_dsync_blocks()
512 pos = rb->blkoff << inode->i_blkbits; in nilfs_recover_dsync_blocks()
513 err = block_write_begin(inode->i_mapping, pos, blocksize, in nilfs_recover_dsync_blocks()
516 loff_t isize = inode->i_size; in nilfs_recover_dsync_blocks()
519 nilfs_write_failed(inode->i_mapping, in nilfs_recover_dsync_blocks()
532 block_write_end(NULL, inode->i_mapping, pos, blocksize, in nilfs_recover_dsync_blocks()
547 "error %d recovering data block (ino=%lu, block-offset=%llu)", in nilfs_recover_dsync_blocks()
548 err, (unsigned long)rb->ino, in nilfs_recover_dsync_blocks()
549 (unsigned long long)rb->blkoff); in nilfs_recover_dsync_blocks()
554 list_del_init(&rb->list); in nilfs_recover_dsync_blocks()
561 * nilfs_do_roll_forward - salvage logical segments newer than the latest
576 unsigned long nsalvaged_blocks = 0; in nilfs_do_roll_forward()
585 RF_DSYNC_ST, /* scanning data-sync segments */ in nilfs_do_roll_forward()
589 pseg_start = ri->ri_lsegs_start; in nilfs_do_roll_forward()
590 seg_seq = ri->ri_lsegs_start_seq; in nilfs_do_roll_forward()
594 while (segnum != ri->ri_segnum || pseg_start <= ri->ri_pseg_start) { in nilfs_do_roll_forward()
598 err = -EIO; in nilfs_do_roll_forward()
605 err = -EIO; in nilfs_do_roll_forward()
611 flags = le16_to_cpu(sum->ss_flags); in nilfs_do_roll_forward()
617 le64_to_cpu(sum->ss_next)); in nilfs_do_roll_forward()
619 nilfs->ns_ctime = le64_to_cpu(sum->ss_create); in nilfs_do_roll_forward()
621 nilfs->ns_nongc_ctime = nilfs->ns_ctime; in nilfs_do_roll_forward()
650 if (pseg_start == ri->ri_lsegs_end) in nilfs_do_roll_forward()
652 pseg_start += le32_to_cpu(sum->ss_nblocks); in nilfs_do_roll_forward()
658 if (pseg_start == ri->ri_lsegs_end) in nilfs_do_roll_forward()
673 ri->ri_need_recovery = NILFS_RECOVERY_ROLLFORWARD_DONE; in nilfs_do_roll_forward()
681 err = -EINVAL; in nilfs_do_roll_forward()
684 "error %d roll-forwarding partial segment at blocknr = %llu", in nilfs_do_roll_forward()
685 err, (unsigned long long)pseg_start); in nilfs_do_roll_forward()
695 if (nilfs_get_segnum_of_block(nilfs, ri->ri_lsegs_start) != in nilfs_finish_roll_forward()
696 nilfs_get_segnum_of_block(nilfs, ri->ri_super_root)) in nilfs_finish_roll_forward()
699 bh = __getblk(nilfs->ns_bdev, ri->ri_lsegs_start, nilfs->ns_blocksize); in nilfs_finish_roll_forward()
701 memset(bh->b_data, 0, bh->b_size); in nilfs_finish_roll_forward()
705 nilfs_warn(nilfs->ns_sb, in nilfs_finish_roll_forward()
706 "buffer sync write failed during post-cleaning of recovery."); in nilfs_finish_roll_forward()
711 * nilfs_salvage_orphan_logs - salvage logs written after the latest checkpoint
719 * %-EINVAL - Inconsistent filesystem state.
721 * %-EIO - I/O error
723 * %-ENOSPC - No space left on device (only in a panic state).
725 * %-ERESTARTSYS - Interrupted.
727 * %-ENOMEM - Insufficient memory available.
736 if (ri->ri_lsegs_start == 0 || ri->ri_lsegs_end == 0) in nilfs_salvage_orphan_logs()
739 err = nilfs_attach_checkpoint(sb, ri->ri_cno, true, &root); in nilfs_salvage_orphan_logs()
749 if (ri->ri_need_recovery == NILFS_RECOVERY_ROLLFORWARD_DONE) { in nilfs_salvage_orphan_logs()
780 * nilfs_search_super_root - search the latest valid super root
784 * nilfs_search_super_root() looks for the latest super-root from a partial
791 * %-EINVAL - No valid segment found
793 * %-EIO - I/O error
795 * %-ENOMEM - Insufficient memory available.
805 unsigned long nblocks; in nilfs_search_super_root()
814 pseg_start = nilfs->ns_last_pseg; in nilfs_search_super_root()
815 seg_seq = nilfs->ns_last_seq; in nilfs_search_super_root()
816 cno = nilfs->ns_last_cno; in nilfs_search_super_root()
825 __breadahead(nilfs->ns_bdev, b++, nilfs->ns_blocksize); in nilfs_search_super_root()
841 nblocks = le32_to_cpu(sum->ss_nblocks); in nilfs_search_super_root()
842 pseg_end = pseg_start + nblocks - 1; in nilfs_search_super_root()
849 ri->ri_pseg_start = pseg_start; in nilfs_search_super_root()
850 ri->ri_seq = seg_seq; in nilfs_search_super_root()
851 ri->ri_segnum = segnum; in nilfs_search_super_root()
853 le64_to_cpu(sum->ss_next)); in nilfs_search_super_root()
854 ri->ri_nextnum = nextnum; in nilfs_search_super_root()
857 flags = le16_to_cpu(sum->ss_flags); in nilfs_search_super_root()
871 __breadahead(nilfs->ns_bdev, b++, in nilfs_search_super_root()
872 nilfs->ns_blocksize); in nilfs_search_super_root()
875 if (!ri->ri_lsegs_start && (flags & NILFS_SS_LOGBGN)) { in nilfs_search_super_root()
876 ri->ri_lsegs_start = pseg_start; in nilfs_search_super_root()
877 ri->ri_lsegs_start_seq = seg_seq; in nilfs_search_super_root()
880 ri->ri_lsegs_end = pseg_start; in nilfs_search_super_root()
885 ri->ri_cno = cno++; in nilfs_search_super_root()
886 ri->ri_super_root = pseg_end; in nilfs_search_super_root()
887 ri->ri_lsegs_start = ri->ri_lsegs_end = 0; in nilfs_search_super_root()
891 nilfs->ns_pseg_offset = pseg_start + nblocks - seg_start; in nilfs_search_super_root()
892 nilfs->ns_seg_seq = seg_seq; in nilfs_search_super_root()
893 nilfs->ns_segnum = segnum; in nilfs_search_super_root()
894 nilfs->ns_cno = cno; /* nilfs->ns_cno = ri->ri_cno + 1 */ in nilfs_search_super_root()
895 nilfs->ns_ctime = le64_to_cpu(sum->ss_create); in nilfs_search_super_root()
896 nilfs->ns_nextnum = nextnum; in nilfs_search_super_root()
899 ri->ri_need_recovery = NILFS_RECOVERY_SR_UPDATED; in nilfs_search_super_root()
901 if (nilfs->ns_mount_state & NILFS_VALID_FS) in nilfs_search_super_root()
940 list_splice_tail(&segments, &ri->ri_used_segments); in nilfs_search_super_root()
941 nilfs->ns_last_pseg = sr_pseg_start; in nilfs_search_super_root()
942 nilfs->ns_last_seq = nilfs->ns_seg_seq; in nilfs_search_super_root()
943 nilfs->ns_last_cno = ri->ri_cno; in nilfs_search_super_root()
949 return ret < 0 ? ret : nilfs_warn_segment_error(nilfs->ns_sb, ret); in nilfs_search_super_root()