root/fs/nilfs2/recovery.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. nilfs_warn_segment_error
  2. nilfs_compute_checksum
  3. nilfs_read_super_root_block
  4. nilfs_read_log_header
  5. nilfs_validate_log
  6. nilfs_read_summary_info
  7. nilfs_skip_summary_info
  8. nilfs_scan_dsync_log
  9. dispose_recovery_list
  10. nilfs_segment_list_add
  11. nilfs_dispose_segment_list
  12. nilfs_prepare_segment_for_recovery
  13. nilfs_recovery_copy_block
  14. nilfs_recover_dsync_blocks
  15. nilfs_do_roll_forward
  16. nilfs_finish_roll_forward
  17. nilfs_salvage_orphan_logs
  18. nilfs_search_super_root

   1 // SPDX-License-Identifier: GPL-2.0+
   2 /*
   3  * recovery.c - NILFS recovery logic
   4  *
   5  * Copyright (C) 2005-2008 Nippon Telegraph and Telephone Corporation.
   6  *
   7  * Written by Ryusuke Konishi.
   8  */
   9 
  10 #include <linux/buffer_head.h>
  11 #include <linux/blkdev.h>
  12 #include <linux/swap.h>
  13 #include <linux/slab.h>
  14 #include <linux/crc32.h>
  15 #include "nilfs.h"
  16 #include "segment.h"
  17 #include "sufile.h"
  18 #include "page.h"
  19 #include "segbuf.h"
  20 
  21 /*
  22  * Segment check result
  23  */
  24 enum {
  25         NILFS_SEG_VALID,
  26         NILFS_SEG_NO_SUPER_ROOT,
  27         NILFS_SEG_FAIL_IO,
  28         NILFS_SEG_FAIL_MAGIC,
  29         NILFS_SEG_FAIL_SEQ,
  30         NILFS_SEG_FAIL_CHECKSUM_SUPER_ROOT,
  31         NILFS_SEG_FAIL_CHECKSUM_FULL,
  32         NILFS_SEG_FAIL_CONSISTENCY,
  33 };
  34 
  35 /* work structure for recovery */
  36 struct nilfs_recovery_block {
  37         ino_t ino;              /*
  38                                  * Inode number of the file that this block
  39                                  * belongs to
  40                                  */
  41         sector_t blocknr;       /* block number */
  42         __u64 vblocknr;         /* virtual block number */
  43         unsigned long blkoff;   /* File offset of the data block (per block) */
  44         struct list_head list;
  45 };
  46 
  47 
  48 static int nilfs_warn_segment_error(struct super_block *sb, int err)
  49 {
  50         const char *msg = NULL;
  51 
  52         switch (err) {
  53         case NILFS_SEG_FAIL_IO:
  54                 nilfs_msg(sb, KERN_ERR, "I/O error reading segment");
  55                 return -EIO;
  56         case NILFS_SEG_FAIL_MAGIC:
  57                 msg = "Magic number mismatch";
  58                 break;
  59         case NILFS_SEG_FAIL_SEQ:
  60                 msg = "Sequence number mismatch";
  61                 break;
  62         case NILFS_SEG_FAIL_CHECKSUM_SUPER_ROOT:
  63                 msg = "Checksum error in super root";
  64                 break;
  65         case NILFS_SEG_FAIL_CHECKSUM_FULL:
  66                 msg = "Checksum error in segment payload";
  67                 break;
  68         case NILFS_SEG_FAIL_CONSISTENCY:
  69                 msg = "Inconsistency found";
  70                 break;
  71         case NILFS_SEG_NO_SUPER_ROOT:
  72                 msg = "No super root in the last segment";
  73                 break;
  74         default:
  75                 nilfs_msg(sb, KERN_ERR, "unrecognized segment error %d", err);
  76                 return -EINVAL;
  77         }
  78         nilfs_msg(sb, KERN_WARNING, "invalid segment: %s", msg);
  79         return -EINVAL;
  80 }
  81 
  82 /**
  83  * nilfs_compute_checksum - compute checksum of blocks continuously
  84  * @nilfs: nilfs object
  85  * @bhs: buffer head of start block
  86  * @sum: place to store result
  87  * @offset: offset bytes in the first block
  88  * @check_bytes: number of bytes to be checked
  89  * @start: DBN of start block
  90  * @nblock: number of blocks to be checked
  91  */
  92 static int nilfs_compute_checksum(struct the_nilfs *nilfs,
  93                                   struct buffer_head *bhs, u32 *sum,
  94                                   unsigned long offset, u64 check_bytes,
  95                                   sector_t start, unsigned long nblock)
  96 {
  97         unsigned int blocksize = nilfs->ns_blocksize;
  98         unsigned long size;
  99         u32 crc;
 100 
 101         BUG_ON(offset >= blocksize);
 102         check_bytes -= offset;
 103         size = min_t(u64, check_bytes, blocksize - offset);
 104         crc = crc32_le(nilfs->ns_crc_seed,
 105                        (unsigned char *)bhs->b_data + offset, size);
 106         if (--nblock > 0) {
 107                 do {
 108                         struct buffer_head *bh;
 109 
 110                         bh = __bread(nilfs->ns_bdev, ++start, blocksize);
 111                         if (!bh)
 112                                 return -EIO;
 113                         check_bytes -= size;
 114                         size = min_t(u64, check_bytes, blocksize);
 115                         crc = crc32_le(crc, bh->b_data, size);
 116                         brelse(bh);
 117                 } while (--nblock > 0);
 118         }
 119         *sum = crc;
 120         return 0;
 121 }
 122 
 123 /**
 124  * nilfs_read_super_root_block - read super root block
 125  * @nilfs: nilfs object
 126  * @sr_block: disk block number of the super root block
 127  * @pbh: address of a buffer_head pointer to return super root buffer
 128  * @check: CRC check flag
 129  */
 130 int nilfs_read_super_root_block(struct the_nilfs *nilfs, sector_t sr_block,
 131                                 struct buffer_head **pbh, int check)
 132 {
 133         struct buffer_head *bh_sr;
 134         struct nilfs_super_root *sr;
 135         u32 crc;
 136         int ret;
 137 
 138         *pbh = NULL;
 139         bh_sr = __bread(nilfs->ns_bdev, sr_block, nilfs->ns_blocksize);
 140         if (unlikely(!bh_sr)) {
 141                 ret = NILFS_SEG_FAIL_IO;
 142                 goto failed;
 143         }
 144 
 145         sr = (struct nilfs_super_root *)bh_sr->b_data;
 146         if (check) {
 147                 unsigned int bytes = le16_to_cpu(sr->sr_bytes);
 148 
 149                 if (bytes == 0 || bytes > nilfs->ns_blocksize) {
 150                         ret = NILFS_SEG_FAIL_CHECKSUM_SUPER_ROOT;
 151                         goto failed_bh;
 152                 }
 153                 if (nilfs_compute_checksum(
 154                             nilfs, bh_sr, &crc, sizeof(sr->sr_sum), bytes,
 155                             sr_block, 1)) {
 156                         ret = NILFS_SEG_FAIL_IO;
 157                         goto failed_bh;
 158                 }
 159                 if (crc != le32_to_cpu(sr->sr_sum)) {
 160                         ret = NILFS_SEG_FAIL_CHECKSUM_SUPER_ROOT;
 161                         goto failed_bh;
 162                 }
 163         }
 164         *pbh = bh_sr;
 165         return 0;
 166 
 167  failed_bh:
 168         brelse(bh_sr);
 169 
 170  failed:
 171         return nilfs_warn_segment_error(nilfs->ns_sb, ret);
 172 }
 173 
 174 /**
 175  * nilfs_read_log_header - read summary header of the specified log
 176  * @nilfs: nilfs object
 177  * @start_blocknr: start block number of the log
 178  * @sum: pointer to return segment summary structure
 179  */
 180 static struct buffer_head *
 181 nilfs_read_log_header(struct the_nilfs *nilfs, sector_t start_blocknr,
 182                       struct nilfs_segment_summary **sum)
 183 {
 184         struct buffer_head *bh_sum;
 185 
 186         bh_sum = __bread(nilfs->ns_bdev, start_blocknr, nilfs->ns_blocksize);
 187         if (bh_sum)
 188                 *sum = (struct nilfs_segment_summary *)bh_sum->b_data;
 189         return bh_sum;
 190 }
 191 
 192 /**
 193  * nilfs_validate_log - verify consistency of log
 194  * @nilfs: nilfs object
 195  * @seg_seq: sequence number of segment
 196  * @bh_sum: buffer head of summary block
 197  * @sum: segment summary struct
 198  */
 199 static int nilfs_validate_log(struct the_nilfs *nilfs, u64 seg_seq,
 200                               struct buffer_head *bh_sum,
 201                               struct nilfs_segment_summary *sum)
 202 {
 203         unsigned long nblock;
 204         u32 crc;
 205         int ret;
 206 
 207         ret = NILFS_SEG_FAIL_MAGIC;
 208         if (le32_to_cpu(sum->ss_magic) != NILFS_SEGSUM_MAGIC)
 209                 goto out;
 210 
 211         ret = NILFS_SEG_FAIL_SEQ;
 212         if (le64_to_cpu(sum->ss_seq) != seg_seq)
 213                 goto out;
 214 
 215         nblock = le32_to_cpu(sum->ss_nblocks);
 216         ret = NILFS_SEG_FAIL_CONSISTENCY;
 217         if (unlikely(nblock == 0 || nblock > nilfs->ns_blocks_per_segment))
 218                 /* This limits the number of blocks read in the CRC check */
 219                 goto out;
 220 
 221         ret = NILFS_SEG_FAIL_IO;
 222         if (nilfs_compute_checksum(nilfs, bh_sum, &crc, sizeof(sum->ss_datasum),
 223                                    ((u64)nblock << nilfs->ns_blocksize_bits),
 224                                    bh_sum->b_blocknr, nblock))
 225                 goto out;
 226 
 227         ret = NILFS_SEG_FAIL_CHECKSUM_FULL;
 228         if (crc != le32_to_cpu(sum->ss_datasum))
 229                 goto out;
 230         ret = 0;
 231 out:
 232         return ret;
 233 }
 234 
 235 /**
 236  * nilfs_read_summary_info - read an item on summary blocks of a log
 237  * @nilfs: nilfs object
 238  * @pbh: the current buffer head on summary blocks [in, out]
 239  * @offset: the current byte offset on summary blocks [in, out]
 240  * @bytes: byte size of the item to be read
 241  */
 242 static void *nilfs_read_summary_info(struct the_nilfs *nilfs,
 243                                      struct buffer_head **pbh,
 244                                      unsigned int *offset, unsigned int bytes)
 245 {
 246         void *ptr;
 247         sector_t blocknr;
 248 
 249         BUG_ON((*pbh)->b_size < *offset);
 250         if (bytes > (*pbh)->b_size - *offset) {
 251                 blocknr = (*pbh)->b_blocknr;
 252                 brelse(*pbh);
 253                 *pbh = __bread(nilfs->ns_bdev, blocknr + 1,
 254                                nilfs->ns_blocksize);
 255                 if (unlikely(!*pbh))
 256                         return NULL;
 257                 *offset = 0;
 258         }
 259         ptr = (*pbh)->b_data + *offset;
 260         *offset += bytes;
 261         return ptr;
 262 }
 263 
 264 /**
 265  * nilfs_skip_summary_info - skip items on summary blocks of a log
 266  * @nilfs: nilfs object
 267  * @pbh: the current buffer head on summary blocks [in, out]
 268  * @offset: the current byte offset on summary blocks [in, out]
 269  * @bytes: byte size of the item to be skipped
 270  * @count: number of items to be skipped
 271  */
 272 static void nilfs_skip_summary_info(struct the_nilfs *nilfs,
 273                                     struct buffer_head **pbh,
 274                                     unsigned int *offset, unsigned int bytes,
 275                                     unsigned long count)
 276 {
 277         unsigned int rest_item_in_current_block
 278                 = ((*pbh)->b_size - *offset) / bytes;
 279 
 280         if (count <= rest_item_in_current_block) {
 281                 *offset += bytes * count;
 282         } else {
 283                 sector_t blocknr = (*pbh)->b_blocknr;
 284                 unsigned int nitem_per_block = (*pbh)->b_size / bytes;
 285                 unsigned int bcnt;
 286 
 287                 count -= rest_item_in_current_block;
 288                 bcnt = DIV_ROUND_UP(count, nitem_per_block);
 289                 *offset = bytes * (count - (bcnt - 1) * nitem_per_block);
 290 
 291                 brelse(*pbh);
 292                 *pbh = __bread(nilfs->ns_bdev, blocknr + bcnt,
 293                                nilfs->ns_blocksize);
 294         }
 295 }
 296 
 297 /**
 298  * nilfs_scan_dsync_log - get block information of a log written for data sync
 299  * @nilfs: nilfs object
 300  * @start_blocknr: start block number of the log
 301  * @sum: log summary information
 302  * @head: list head to add nilfs_recovery_block struct
 303  */
 304 static int nilfs_scan_dsync_log(struct the_nilfs *nilfs, sector_t start_blocknr,
 305                                 struct nilfs_segment_summary *sum,
 306                                 struct list_head *head)
 307 {
 308         struct buffer_head *bh;
 309         unsigned int offset;
 310         u32 nfinfo, sumbytes;
 311         sector_t blocknr;
 312         ino_t ino;
 313         int err = -EIO;
 314 
 315         nfinfo = le32_to_cpu(sum->ss_nfinfo);
 316         if (!nfinfo)
 317                 return 0;
 318 
 319         sumbytes = le32_to_cpu(sum->ss_sumbytes);
 320         blocknr = start_blocknr + DIV_ROUND_UP(sumbytes, nilfs->ns_blocksize);
 321         bh = __bread(nilfs->ns_bdev, start_blocknr, nilfs->ns_blocksize);
 322         if (unlikely(!bh))
 323                 goto out;
 324 
 325         offset = le16_to_cpu(sum->ss_bytes);
 326         for (;;) {
 327                 unsigned long nblocks, ndatablk, nnodeblk;
 328                 struct nilfs_finfo *finfo;
 329 
 330                 finfo = nilfs_read_summary_info(nilfs, &bh, &offset,
 331                                                 sizeof(*finfo));
 332                 if (unlikely(!finfo))
 333                         goto out;
 334 
 335                 ino = le64_to_cpu(finfo->fi_ino);
 336                 nblocks = le32_to_cpu(finfo->fi_nblocks);
 337                 ndatablk = le32_to_cpu(finfo->fi_ndatablk);
 338                 nnodeblk = nblocks - ndatablk;
 339 
 340                 while (ndatablk-- > 0) {
 341                         struct nilfs_recovery_block *rb;
 342                         struct nilfs_binfo_v *binfo;
 343 
 344                         binfo = nilfs_read_summary_info(nilfs, &bh, &offset,
 345                                                         sizeof(*binfo));
 346                         if (unlikely(!binfo))
 347                                 goto out;
 348 
 349                         rb = kmalloc(sizeof(*rb), GFP_NOFS);
 350                         if (unlikely(!rb)) {
 351                                 err = -ENOMEM;
 352                                 goto out;
 353                         }
 354                         rb->ino = ino;
 355                         rb->blocknr = blocknr++;
 356                         rb->vblocknr = le64_to_cpu(binfo->bi_vblocknr);
 357                         rb->blkoff = le64_to_cpu(binfo->bi_blkoff);
 358                         /* INIT_LIST_HEAD(&rb->list); */
 359                         list_add_tail(&rb->list, head);
 360                 }
 361                 if (--nfinfo == 0)
 362                         break;
 363                 blocknr += nnodeblk; /* always 0 for data sync logs */
 364                 nilfs_skip_summary_info(nilfs, &bh, &offset, sizeof(__le64),
 365                                         nnodeblk);
 366                 if (unlikely(!bh))
 367                         goto out;
 368         }
 369         err = 0;
 370  out:
 371         brelse(bh);   /* brelse(NULL) is just ignored */
 372         return err;
 373 }
 374 
 375 static void dispose_recovery_list(struct list_head *head)
 376 {
 377         while (!list_empty(head)) {
 378                 struct nilfs_recovery_block *rb;
 379 
 380                 rb = list_first_entry(head, struct nilfs_recovery_block, list);
 381                 list_del(&rb->list);
 382                 kfree(rb);
 383         }
 384 }
 385 
 386 struct nilfs_segment_entry {
 387         struct list_head        list;
 388         __u64                   segnum;
 389 };
 390 
 391 static int nilfs_segment_list_add(struct list_head *head, __u64 segnum)
 392 {
 393         struct nilfs_segment_entry *ent = kmalloc(sizeof(*ent), GFP_NOFS);
 394 
 395         if (unlikely(!ent))
 396                 return -ENOMEM;
 397 
 398         ent->segnum = segnum;
 399         INIT_LIST_HEAD(&ent->list);
 400         list_add_tail(&ent->list, head);
 401         return 0;
 402 }
 403 
 404 void nilfs_dispose_segment_list(struct list_head *head)
 405 {
 406         while (!list_empty(head)) {
 407                 struct nilfs_segment_entry *ent;
 408 
 409                 ent = list_first_entry(head, struct nilfs_segment_entry, list);
 410                 list_del(&ent->list);
 411                 kfree(ent);
 412         }
 413 }
 414 
 415 static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs,
 416                                               struct super_block *sb,
 417                                               struct nilfs_recovery_info *ri)
 418 {
 419         struct list_head *head = &ri->ri_used_segments;
 420         struct nilfs_segment_entry *ent, *n;
 421         struct inode *sufile = nilfs->ns_sufile;
 422         __u64 segnum[4];
 423         int err;
 424         int i;
 425 
 426         segnum[0] = nilfs->ns_segnum;
 427         segnum[1] = nilfs->ns_nextnum;
 428         segnum[2] = ri->ri_segnum;
 429         segnum[3] = ri->ri_nextnum;
 430 
 431         /*
 432          * Releasing the next segment of the latest super root.
 433          * The next segment is invalidated by this recovery.
 434          */
 435         err = nilfs_sufile_free(sufile, segnum[1]);
 436         if (unlikely(err))
 437                 goto failed;
 438 
 439         for (i = 1; i < 4; i++) {
 440                 err = nilfs_segment_list_add(head, segnum[i]);
 441                 if (unlikely(err))
 442                         goto failed;
 443         }
 444 
 445         /*
 446          * Collecting segments written after the latest super root.
 447          * These are marked dirty to avoid being reallocated in the next write.
 448          */
 449         list_for_each_entry_safe(ent, n, head, list) {
 450                 if (ent->segnum != segnum[0]) {
 451                         err = nilfs_sufile_scrap(sufile, ent->segnum);
 452                         if (unlikely(err))
 453                                 goto failed;
 454                 }
 455                 list_del(&ent->list);
 456                 kfree(ent);
 457         }
 458 
 459         /* Allocate new segments for recovery */
 460         err = nilfs_sufile_alloc(sufile, &segnum[0]);
 461         if (unlikely(err))
 462                 goto failed;
 463 
 464         nilfs->ns_pseg_offset = 0;
 465         nilfs->ns_seg_seq = ri->ri_seq + 2;
 466         nilfs->ns_nextnum = nilfs->ns_segnum = segnum[0];
 467 
 468  failed:
 469         /* No need to recover sufile because it will be destroyed on error */
 470         return err;
 471 }
 472 
 473 static int nilfs_recovery_copy_block(struct the_nilfs *nilfs,
 474                                      struct nilfs_recovery_block *rb,
 475                                      struct page *page)
 476 {
 477         struct buffer_head *bh_org;
 478         void *kaddr;
 479 
 480         bh_org = __bread(nilfs->ns_bdev, rb->blocknr, nilfs->ns_blocksize);
 481         if (unlikely(!bh_org))
 482                 return -EIO;
 483 
 484         kaddr = kmap_atomic(page);
 485         memcpy(kaddr + bh_offset(bh_org), bh_org->b_data, bh_org->b_size);
 486         kunmap_atomic(kaddr);
 487         brelse(bh_org);
 488         return 0;
 489 }
 490 
 491 static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs,
 492                                       struct super_block *sb,
 493                                       struct nilfs_root *root,
 494                                       struct list_head *head,
 495                                       unsigned long *nr_salvaged_blocks)
 496 {
 497         struct inode *inode;
 498         struct nilfs_recovery_block *rb, *n;
 499         unsigned int blocksize = nilfs->ns_blocksize;
 500         struct page *page;
 501         loff_t pos;
 502         int err = 0, err2 = 0;
 503 
 504         list_for_each_entry_safe(rb, n, head, list) {
 505                 inode = nilfs_iget(sb, root, rb->ino);
 506                 if (IS_ERR(inode)) {
 507                         err = PTR_ERR(inode);
 508                         inode = NULL;
 509                         goto failed_inode;
 510                 }
 511 
 512                 pos = rb->blkoff << inode->i_blkbits;
 513                 err = block_write_begin(inode->i_mapping, pos, blocksize,
 514                                         0, &page, nilfs_get_block);
 515                 if (unlikely(err)) {
 516                         loff_t isize = inode->i_size;
 517 
 518                         if (pos + blocksize > isize)
 519                                 nilfs_write_failed(inode->i_mapping,
 520                                                         pos + blocksize);
 521                         goto failed_inode;
 522                 }
 523 
 524                 err = nilfs_recovery_copy_block(nilfs, rb, page);
 525                 if (unlikely(err))
 526                         goto failed_page;
 527 
 528                 err = nilfs_set_file_dirty(inode, 1);
 529                 if (unlikely(err))
 530                         goto failed_page;
 531 
 532                 block_write_end(NULL, inode->i_mapping, pos, blocksize,
 533                                 blocksize, page, NULL);
 534 
 535                 unlock_page(page);
 536                 put_page(page);
 537 
 538                 (*nr_salvaged_blocks)++;
 539                 goto next;
 540 
 541  failed_page:
 542                 unlock_page(page);
 543                 put_page(page);
 544 
 545  failed_inode:
 546                 nilfs_msg(sb, KERN_WARNING,
 547                           "error %d recovering data block (ino=%lu, block-offset=%llu)",
 548                           err, (unsigned long)rb->ino,
 549                           (unsigned long long)rb->blkoff);
 550                 if (!err2)
 551                         err2 = err;
 552  next:
 553                 iput(inode); /* iput(NULL) is just ignored */
 554                 list_del_init(&rb->list);
 555                 kfree(rb);
 556         }
 557         return err2;
 558 }
 559 
 560 /**
 561  * nilfs_do_roll_forward - salvage logical segments newer than the latest
 562  * checkpoint
 563  * @nilfs: nilfs object
 564  * @sb: super block instance
 565  * @ri: pointer to a nilfs_recovery_info
 566  */
 567 static int nilfs_do_roll_forward(struct the_nilfs *nilfs,
 568                                  struct super_block *sb,
 569                                  struct nilfs_root *root,
 570                                  struct nilfs_recovery_info *ri)
 571 {
 572         struct buffer_head *bh_sum = NULL;
 573         struct nilfs_segment_summary *sum = NULL;
 574         sector_t pseg_start;
 575         sector_t seg_start, seg_end;  /* Starting/ending DBN of full segment */
 576         unsigned long nsalvaged_blocks = 0;
 577         unsigned int flags;
 578         u64 seg_seq;
 579         __u64 segnum, nextnum = 0;
 580         int empty_seg = 0;
 581         int err = 0, ret;
 582         LIST_HEAD(dsync_blocks);  /* list of data blocks to be recovered */
 583         enum {
 584                 RF_INIT_ST,
 585                 RF_DSYNC_ST,   /* scanning data-sync segments */
 586         };
 587         int state = RF_INIT_ST;
 588 
 589         pseg_start = ri->ri_lsegs_start;
 590         seg_seq = ri->ri_lsegs_start_seq;
 591         segnum = nilfs_get_segnum_of_block(nilfs, pseg_start);
 592         nilfs_get_segment_range(nilfs, segnum, &seg_start, &seg_end);
 593 
 594         while (segnum != ri->ri_segnum || pseg_start <= ri->ri_pseg_start) {
 595                 brelse(bh_sum);
 596                 bh_sum = nilfs_read_log_header(nilfs, pseg_start, &sum);
 597                 if (!bh_sum) {
 598                         err = -EIO;
 599                         goto failed;
 600                 }
 601 
 602                 ret = nilfs_validate_log(nilfs, seg_seq, bh_sum, sum);
 603                 if (ret) {
 604                         if (ret == NILFS_SEG_FAIL_IO) {
 605                                 err = -EIO;
 606                                 goto failed;
 607                         }
 608                         goto strayed;
 609                 }
 610 
 611                 flags = le16_to_cpu(sum->ss_flags);
 612                 if (flags & NILFS_SS_SR)
 613                         goto confused;
 614 
 615                 /* Found a valid partial segment; do recovery actions */
 616                 nextnum = nilfs_get_segnum_of_block(nilfs,
 617                                                     le64_to_cpu(sum->ss_next));
 618                 empty_seg = 0;
 619                 nilfs->ns_ctime = le64_to_cpu(sum->ss_create);
 620                 if (!(flags & NILFS_SS_GC))
 621                         nilfs->ns_nongc_ctime = nilfs->ns_ctime;
 622 
 623                 switch (state) {
 624                 case RF_INIT_ST:
 625                         if (!(flags & NILFS_SS_LOGBGN) ||
 626                             !(flags & NILFS_SS_SYNDT))
 627                                 goto try_next_pseg;
 628                         state = RF_DSYNC_ST;
 629                         /* Fall through */
 630                 case RF_DSYNC_ST:
 631                         if (!(flags & NILFS_SS_SYNDT))
 632                                 goto confused;
 633 
 634                         err = nilfs_scan_dsync_log(nilfs, pseg_start, sum,
 635                                                    &dsync_blocks);
 636                         if (unlikely(err))
 637                                 goto failed;
 638                         if (flags & NILFS_SS_LOGEND) {
 639                                 err = nilfs_recover_dsync_blocks(
 640                                         nilfs, sb, root, &dsync_blocks,
 641                                         &nsalvaged_blocks);
 642                                 if (unlikely(err))
 643                                         goto failed;
 644                                 state = RF_INIT_ST;
 645                         }
 646                         break; /* Fall through to try_next_pseg */
 647                 }
 648 
 649  try_next_pseg:
 650                 if (pseg_start == ri->ri_lsegs_end)
 651                         break;
 652                 pseg_start += le32_to_cpu(sum->ss_nblocks);
 653                 if (pseg_start < seg_end)
 654                         continue;
 655                 goto feed_segment;
 656 
 657  strayed:
 658                 if (pseg_start == ri->ri_lsegs_end)
 659                         break;
 660 
 661  feed_segment:
 662                 /* Looking to the next full segment */
 663                 if (empty_seg++)
 664                         break;
 665                 seg_seq++;
 666                 segnum = nextnum;
 667                 nilfs_get_segment_range(nilfs, segnum, &seg_start, &seg_end);
 668                 pseg_start = seg_start;
 669         }
 670 
 671         if (nsalvaged_blocks) {
 672                 nilfs_msg(sb, KERN_INFO, "salvaged %lu blocks",
 673                           nsalvaged_blocks);
 674                 ri->ri_need_recovery = NILFS_RECOVERY_ROLLFORWARD_DONE;
 675         }
 676  out:
 677         brelse(bh_sum);
 678         dispose_recovery_list(&dsync_blocks);
 679         return err;
 680 
 681  confused:
 682         err = -EINVAL;
 683  failed:
 684         nilfs_msg(sb, KERN_ERR,
 685                   "error %d roll-forwarding partial segment at blocknr = %llu",
 686                   err, (unsigned long long)pseg_start);
 687         goto out;
 688 }
 689 
 690 static void nilfs_finish_roll_forward(struct the_nilfs *nilfs,
 691                                       struct nilfs_recovery_info *ri)
 692 {
 693         struct buffer_head *bh;
 694         int err;
 695 
 696         if (nilfs_get_segnum_of_block(nilfs, ri->ri_lsegs_start) !=
 697             nilfs_get_segnum_of_block(nilfs, ri->ri_super_root))
 698                 return;
 699 
 700         bh = __getblk(nilfs->ns_bdev, ri->ri_lsegs_start, nilfs->ns_blocksize);
 701         BUG_ON(!bh);
 702         memset(bh->b_data, 0, bh->b_size);
 703         set_buffer_dirty(bh);
 704         err = sync_dirty_buffer(bh);
 705         if (unlikely(err))
 706                 nilfs_msg(nilfs->ns_sb, KERN_WARNING,
 707                           "buffer sync write failed during post-cleaning of recovery.");
 708         brelse(bh);
 709 }
 710 
 711 /**
 712  * nilfs_salvage_orphan_logs - salvage logs written after the latest checkpoint
 713  * @nilfs: nilfs object
 714  * @sb: super block instance
 715  * @ri: pointer to a nilfs_recovery_info struct to store search results.
 716  *
 717  * Return Value: On success, 0 is returned.  On error, one of the following
 718  * negative error code is returned.
 719  *
 720  * %-EINVAL - Inconsistent filesystem state.
 721  *
 722  * %-EIO - I/O error
 723  *
 724  * %-ENOSPC - No space left on device (only in a panic state).
 725  *
 726  * %-ERESTARTSYS - Interrupted.
 727  *
 728  * %-ENOMEM - Insufficient memory available.
 729  */
 730 int nilfs_salvage_orphan_logs(struct the_nilfs *nilfs,
 731                               struct super_block *sb,
 732                               struct nilfs_recovery_info *ri)
 733 {
 734         struct nilfs_root *root;
 735         int err;
 736 
 737         if (ri->ri_lsegs_start == 0 || ri->ri_lsegs_end == 0)
 738                 return 0;
 739 
 740         err = nilfs_attach_checkpoint(sb, ri->ri_cno, true, &root);
 741         if (unlikely(err)) {
 742                 nilfs_msg(sb, KERN_ERR,
 743                           "error %d loading the latest checkpoint", err);
 744                 return err;
 745         }
 746 
 747         err = nilfs_do_roll_forward(nilfs, sb, root, ri);
 748         if (unlikely(err))
 749                 goto failed;
 750 
 751         if (ri->ri_need_recovery == NILFS_RECOVERY_ROLLFORWARD_DONE) {
 752                 err = nilfs_prepare_segment_for_recovery(nilfs, sb, ri);
 753                 if (unlikely(err)) {
 754                         nilfs_msg(sb, KERN_ERR,
 755                                   "error %d preparing segment for recovery",
 756                                   err);
 757                         goto failed;
 758                 }
 759 
 760                 err = nilfs_attach_log_writer(sb, root);
 761                 if (unlikely(err))
 762                         goto failed;
 763 
 764                 set_nilfs_discontinued(nilfs);
 765                 err = nilfs_construct_segment(sb);
 766                 nilfs_detach_log_writer(sb);
 767 
 768                 if (unlikely(err)) {
 769                         nilfs_msg(sb, KERN_ERR,
 770                                   "error %d writing segment for recovery",
 771                                   err);
 772                         goto failed;
 773                 }
 774 
 775                 nilfs_finish_roll_forward(nilfs, ri);
 776         }
 777 
 778  failed:
 779         nilfs_put_root(root);
 780         return err;
 781 }
 782 
 783 /**
 784  * nilfs_search_super_root - search the latest valid super root
 785  * @nilfs: the_nilfs
 786  * @ri: pointer to a nilfs_recovery_info struct to store search results.
 787  *
 788  * nilfs_search_super_root() looks for the latest super-root from a partial
 789  * segment pointed by the superblock.  It sets up struct the_nilfs through
 790  * this search. It fills nilfs_recovery_info (ri) required for recovery.
 791  *
 792  * Return Value: On success, 0 is returned.  On error, one of the following
 793  * negative error code is returned.
 794  *
 795  * %-EINVAL - No valid segment found
 796  *
 797  * %-EIO - I/O error
 798  *
 799  * %-ENOMEM - Insufficient memory available.
 800  */
 801 int nilfs_search_super_root(struct the_nilfs *nilfs,
 802                             struct nilfs_recovery_info *ri)
 803 {
 804         struct buffer_head *bh_sum = NULL;
 805         struct nilfs_segment_summary *sum = NULL;
 806         sector_t pseg_start, pseg_end, sr_pseg_start = 0;
 807         sector_t seg_start, seg_end; /* range of full segment (block number) */
 808         sector_t b, end;
 809         unsigned long nblocks;
 810         unsigned int flags;
 811         u64 seg_seq;
 812         __u64 segnum, nextnum = 0;
 813         __u64 cno;
 814         LIST_HEAD(segments);
 815         int empty_seg = 0, scan_newer = 0;
 816         int ret;
 817 
 818         pseg_start = nilfs->ns_last_pseg;
 819         seg_seq = nilfs->ns_last_seq;
 820         cno = nilfs->ns_last_cno;
 821         segnum = nilfs_get_segnum_of_block(nilfs, pseg_start);
 822 
 823         /* Calculate range of segment */
 824         nilfs_get_segment_range(nilfs, segnum, &seg_start, &seg_end);
 825 
 826         /* Read ahead segment */
 827         b = seg_start;
 828         while (b <= seg_end)
 829                 __breadahead(nilfs->ns_bdev, b++, nilfs->ns_blocksize);
 830 
 831         for (;;) {
 832                 brelse(bh_sum);
 833                 ret = NILFS_SEG_FAIL_IO;
 834                 bh_sum = nilfs_read_log_header(nilfs, pseg_start, &sum);
 835                 if (!bh_sum)
 836                         goto failed;
 837 
 838                 ret = nilfs_validate_log(nilfs, seg_seq, bh_sum, sum);
 839                 if (ret) {
 840                         if (ret == NILFS_SEG_FAIL_IO)
 841                                 goto failed;
 842                         goto strayed;
 843                 }
 844 
 845                 nblocks = le32_to_cpu(sum->ss_nblocks);
 846                 pseg_end = pseg_start + nblocks - 1;
 847                 if (unlikely(pseg_end > seg_end)) {
 848                         ret = NILFS_SEG_FAIL_CONSISTENCY;
 849                         goto strayed;
 850                 }
 851 
 852                 /* A valid partial segment */
 853                 ri->ri_pseg_start = pseg_start;
 854                 ri->ri_seq = seg_seq;
 855                 ri->ri_segnum = segnum;
 856                 nextnum = nilfs_get_segnum_of_block(nilfs,
 857                                                     le64_to_cpu(sum->ss_next));
 858                 ri->ri_nextnum = nextnum;
 859                 empty_seg = 0;
 860 
 861                 flags = le16_to_cpu(sum->ss_flags);
 862                 if (!(flags & NILFS_SS_SR) && !scan_newer) {
 863                         /*
 864                          * This will never happen because a superblock
 865                          * (last_segment) always points to a pseg with
 866                          * a super root.
 867                          */
 868                         ret = NILFS_SEG_FAIL_CONSISTENCY;
 869                         goto failed;
 870                 }
 871 
 872                 if (pseg_start == seg_start) {
 873                         nilfs_get_segment_range(nilfs, nextnum, &b, &end);
 874                         while (b <= end)
 875                                 __breadahead(nilfs->ns_bdev, b++,
 876                                              nilfs->ns_blocksize);
 877                 }
 878                 if (!(flags & NILFS_SS_SR)) {
 879                         if (!ri->ri_lsegs_start && (flags & NILFS_SS_LOGBGN)) {
 880                                 ri->ri_lsegs_start = pseg_start;
 881                                 ri->ri_lsegs_start_seq = seg_seq;
 882                         }
 883                         if (flags & NILFS_SS_LOGEND)
 884                                 ri->ri_lsegs_end = pseg_start;
 885                         goto try_next_pseg;
 886                 }
 887 
 888                 /* A valid super root was found. */
 889                 ri->ri_cno = cno++;
 890                 ri->ri_super_root = pseg_end;
 891                 ri->ri_lsegs_start = ri->ri_lsegs_end = 0;
 892 
 893                 nilfs_dispose_segment_list(&segments);
 894                 sr_pseg_start = pseg_start;
 895                 nilfs->ns_pseg_offset = pseg_start + nblocks - seg_start;
 896                 nilfs->ns_seg_seq = seg_seq;
 897                 nilfs->ns_segnum = segnum;
 898                 nilfs->ns_cno = cno;  /* nilfs->ns_cno = ri->ri_cno + 1 */
 899                 nilfs->ns_ctime = le64_to_cpu(sum->ss_create);
 900                 nilfs->ns_nextnum = nextnum;
 901 
 902                 if (scan_newer)
 903                         ri->ri_need_recovery = NILFS_RECOVERY_SR_UPDATED;
 904                 else {
 905                         if (nilfs->ns_mount_state & NILFS_VALID_FS)
 906                                 goto super_root_found;
 907                         scan_newer = 1;
 908                 }
 909 
 910  try_next_pseg:
 911                 /* Standing on a course, or met an inconsistent state */
 912                 pseg_start += nblocks;
 913                 if (pseg_start < seg_end)
 914                         continue;
 915                 goto feed_segment;
 916 
 917  strayed:
 918                 /* Off the trail */
 919                 if (!scan_newer)
 920                         /*
 921                          * This can happen if a checkpoint was written without
 922                          * barriers, or as a result of an I/O failure.
 923                          */
 924                         goto failed;
 925 
 926  feed_segment:
 927                 /* Looking to the next full segment */
 928                 if (empty_seg++)
 929                         goto super_root_found; /* found a valid super root */
 930 
 931                 ret = nilfs_segment_list_add(&segments, segnum);
 932                 if (unlikely(ret))
 933                         goto failed;
 934 
 935                 seg_seq++;
 936                 segnum = nextnum;
 937                 nilfs_get_segment_range(nilfs, segnum, &seg_start, &seg_end);
 938                 pseg_start = seg_start;
 939         }
 940 
 941  super_root_found:
 942         /* Updating pointers relating to the latest checkpoint */
 943         brelse(bh_sum);
 944         list_splice_tail(&segments, &ri->ri_used_segments);
 945         nilfs->ns_last_pseg = sr_pseg_start;
 946         nilfs->ns_last_seq = nilfs->ns_seg_seq;
 947         nilfs->ns_last_cno = ri->ri_cno;
 948         return 0;
 949 
 950  failed:
 951         brelse(bh_sum);
 952         nilfs_dispose_segment_list(&segments);
 953         return ret < 0 ? ret : nilfs_warn_segment_error(nilfs->ns_sb, ret);
 954 }

/* [<][>][^][v][top][bottom][index][help] */