~ubuntu-branches/ubuntu/saucy/linux-ti-omap4/saucy-proposed

« back to all changes in this revision

Viewing changes to fs/jbd2/recovery.c

  • Committer: Package Import Robot
  • Author(s): Paolo Pisati, Paolo Pisati, Stefan Bader, Upstream Kernel Changes
  • Date: 2012-08-15 17:17:43 UTC
  • Revision ID: package-import@ubuntu.com-20120815171743-h5wnuf51xe7pvdid
Tags: 3.5.0-207.13
[ Paolo Pisati ]

* Start new release

[ Stefan Bader ]

* (config) Enable getabis to use local package copies

[ Upstream Kernel Changes ]

* fixup: gargabe collect iva_seq[0|1] init
* [Config] enable all SND_OMAP_SOC_*s
* fixup: cm2xxx_3xxx.o is needed for omap2_cm_read|write_reg
* fixup: add some snd_soc_dai* helper functions
* fixup: s/snd_soc_dpcm_params/snd_soc_dpcm/g
* fixup: typo, no_host_mode and useless SDP4430 init
* fixup: enable again aess hwmod

Show diffs side-by-side

added added

removed removed

Lines of Context:
174
174
        return 0;
175
175
}
176
176
 
 
177
static int jbd2_descr_block_csum_verify(journal_t *j,
 
178
                                        void *buf)
 
179
{
 
180
        struct jbd2_journal_block_tail *tail;
 
181
        __u32 provided, calculated;
 
182
 
 
183
        if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
 
184
                return 1;
 
185
 
 
186
        tail = (struct jbd2_journal_block_tail *)(buf + j->j_blocksize -
 
187
                        sizeof(struct jbd2_journal_block_tail));
 
188
        provided = tail->t_checksum;
 
189
        tail->t_checksum = 0;
 
190
        calculated = jbd2_chksum(j, j->j_csum_seed, buf, j->j_blocksize);
 
191
        tail->t_checksum = provided;
 
192
 
 
193
        provided = be32_to_cpu(provided);
 
194
        return provided == calculated;
 
195
}
177
196
 
178
197
/*
179
198
 * Count the number of in-use tags in a journal descriptor block.
186
205
        int                     nr = 0, size = journal->j_blocksize;
187
206
        int                     tag_bytes = journal_tag_bytes(journal);
188
207
 
 
208
        if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2))
 
209
                size -= sizeof(struct jbd2_journal_block_tail);
 
210
 
189
211
        tagp = &bh->b_data[sizeof(journal_header_t)];
190
212
 
191
213
        while ((tagp - bh->b_data + tag_bytes) <= size) {
193
215
 
194
216
                nr++;
195
217
                tagp += tag_bytes;
196
 
                if (!(tag->t_flags & cpu_to_be32(JBD2_FLAG_SAME_UUID)))
 
218
                if (!(tag->t_flags & cpu_to_be16(JBD2_FLAG_SAME_UUID)))
197
219
                        tagp += 16;
198
220
 
199
 
                if (tag->t_flags & cpu_to_be32(JBD2_FLAG_LAST_TAG))
 
221
                if (tag->t_flags & cpu_to_be16(JBD2_FLAG_LAST_TAG))
200
222
                        break;
201
223
        }
202
224
 
353
375
        return 0;
354
376
}
355
377
 
 
378
static int jbd2_commit_block_csum_verify(journal_t *j, void *buf)
 
379
{
 
380
        struct commit_header *h;
 
381
        __u32 provided, calculated;
 
382
 
 
383
        if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
 
384
                return 1;
 
385
 
 
386
        h = buf;
 
387
        provided = h->h_chksum[0];
 
388
        h->h_chksum[0] = 0;
 
389
        calculated = jbd2_chksum(j, j->j_csum_seed, buf, j->j_blocksize);
 
390
        h->h_chksum[0] = provided;
 
391
 
 
392
        provided = be32_to_cpu(provided);
 
393
        return provided == calculated;
 
394
}
 
395
 
 
396
static int jbd2_block_tag_csum_verify(journal_t *j, journal_block_tag_t *tag,
 
397
                                      void *buf, __u32 sequence)
 
398
{
 
399
        __u32 provided, calculated;
 
400
 
 
401
        if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
 
402
                return 1;
 
403
 
 
404
        sequence = cpu_to_be32(sequence);
 
405
        calculated = jbd2_chksum(j, j->j_csum_seed, (__u8 *)&sequence,
 
406
                                 sizeof(sequence));
 
407
        calculated = jbd2_chksum(j, calculated, buf, j->j_blocksize);
 
408
        provided = be32_to_cpu(tag->t_checksum);
 
409
 
 
410
        return provided == cpu_to_be32(calculated);
 
411
}
 
412
 
356
413
static int do_one_pass(journal_t *journal,
357
414
                        struct recovery_info *info, enum passtype pass)
358
415
{
366
423
        int                     blocktype;
367
424
        int                     tag_bytes = journal_tag_bytes(journal);
368
425
        __u32                   crc32_sum = ~0; /* Transactional Checksums */
 
426
        int                     descr_csum_size = 0;
369
427
 
370
428
        /*
371
429
         * First thing is to establish what we expect to find in the log
451
509
 
452
510
                switch(blocktype) {
453
511
                case JBD2_DESCRIPTOR_BLOCK:
 
512
                        /* Verify checksum first */
 
513
                        if (JBD2_HAS_INCOMPAT_FEATURE(journal,
 
514
                                        JBD2_FEATURE_INCOMPAT_CSUM_V2))
 
515
                                descr_csum_size =
 
516
                                        sizeof(struct jbd2_journal_block_tail);
 
517
                        if (descr_csum_size > 0 &&
 
518
                            !jbd2_descr_block_csum_verify(journal,
 
519
                                                          bh->b_data)) {
 
520
                                err = -EIO;
 
521
                                goto failed;
 
522
                        }
 
523
 
454
524
                        /* If it is a valid descriptor block, replay it
455
525
                         * in pass REPLAY; if journal_checksums enabled, then
456
526
                         * calculate checksums in PASS_SCAN, otherwise,
481
551
 
482
552
                        tagp = &bh->b_data[sizeof(journal_header_t)];
483
553
                        while ((tagp - bh->b_data + tag_bytes)
484
 
                               <= journal->j_blocksize) {
 
554
                               <= journal->j_blocksize - descr_csum_size) {
485
555
                                unsigned long io_block;
486
556
 
487
557
                                tag = (journal_block_tag_t *) tagp;
488
 
                                flags = be32_to_cpu(tag->t_flags);
 
558
                                flags = be16_to_cpu(tag->t_flags);
489
559
 
490
560
                                io_block = next_log_block++;
491
561
                                wrap(journal, next_log_block);
516
586
                                                goto skip_write;
517
587
                                        }
518
588
 
 
589
                                        /* Look for block corruption */
 
590
                                        if (!jbd2_block_tag_csum_verify(
 
591
                                                journal, tag, obh->b_data,
 
592
                                                be32_to_cpu(tmp->h_sequence))) {
 
593
                                                brelse(obh);
 
594
                                                success = -EIO;
 
595
                                                printk(KERN_ERR "JBD: Invalid "
 
596
                                                       "checksum recovering "
 
597
                                                       "block %llu in log\n",
 
598
                                                       blocknr);
 
599
                                                continue;
 
600
                                        }
 
601
 
519
602
                                        /* Find a buffer for the new
520
603
                                         * data being restored */
521
604
                                        nbh = __getblk(journal->j_fs_dev,
650
733
                                }
651
734
                                crc32_sum = ~0;
652
735
                        }
 
736
                        if (pass == PASS_SCAN &&
 
737
                            !jbd2_commit_block_csum_verify(journal,
 
738
                                                           bh->b_data)) {
 
739
                                info->end_transaction = next_commit_ID;
 
740
 
 
741
                                if (!JBD2_HAS_INCOMPAT_FEATURE(journal,
 
742
                                     JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)) {
 
743
                                        journal->j_failed_commit =
 
744
                                                next_commit_ID;
 
745
                                        brelse(bh);
 
746
                                        break;
 
747
                                }
 
748
                        }
653
749
                        brelse(bh);
654
750
                        next_commit_ID++;
655
751
                        continue;
706
802
        return err;
707
803
}
708
804
 
 
805
static int jbd2_revoke_block_csum_verify(journal_t *j,
 
806
                                         void *buf)
 
807
{
 
808
        struct jbd2_journal_revoke_tail *tail;
 
809
        __u32 provided, calculated;
 
810
 
 
811
        if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
 
812
                return 1;
 
813
 
 
814
        tail = (struct jbd2_journal_revoke_tail *)(buf + j->j_blocksize -
 
815
                        sizeof(struct jbd2_journal_revoke_tail));
 
816
        provided = tail->r_checksum;
 
817
        tail->r_checksum = 0;
 
818
        calculated = jbd2_chksum(j, j->j_csum_seed, buf, j->j_blocksize);
 
819
        tail->r_checksum = provided;
 
820
 
 
821
        provided = be32_to_cpu(provided);
 
822
        return provided == calculated;
 
823
}
709
824
 
710
825
/* Scan a revoke record, marking all blocks mentioned as revoked. */
711
826
 
720
835
        offset = sizeof(jbd2_journal_revoke_header_t);
721
836
        max = be32_to_cpu(header->r_count);
722
837
 
 
838
        if (!jbd2_revoke_block_csum_verify(journal, header))
 
839
                return -EINVAL;
 
840
 
723
841
        if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT))
724
842
                record_len = 8;
725
843