ocfs2: Add ocfs2_read_refcount_block.
[safe/jmp/linux-2.6] / fs / ocfs2 / refcounttree.c
1 /* -*- mode: c; c-basic-offset: 8; -*-
2  * vim: noexpandtab sw=8 ts=8 sts=0:
3  *
4  * refcounttree.c
5  *
6  * Copyright (C) 2009 Oracle.  All rights reserved.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public
10  * License version 2 as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  */
17
18 #define MLOG_MASK_PREFIX ML_REFCOUNT
19 #include <cluster/masklog.h>
20 #include "ocfs2.h"
21 #include "inode.h"
22 #include "alloc.h"
23 #include "suballoc.h"
24 #include "journal.h"
25 #include "uptodate.h"
26 #include "super.h"
27 #include "buffer_head_io.h"
28 #include "blockcheck.h"
29
30 static int ocfs2_validate_refcount_block(struct super_block *sb,
31                                          struct buffer_head *bh)
32 {
33         int rc;
34         struct ocfs2_refcount_block *rb =
35                 (struct ocfs2_refcount_block *)bh->b_data;
36
37         mlog(0, "Validating refcount block %llu\n",
38              (unsigned long long)bh->b_blocknr);
39
40         BUG_ON(!buffer_uptodate(bh));
41
42         /*
43          * If the ecc fails, we return the error but otherwise
44          * leave the filesystem running.  We know any error is
45          * local to this block.
46          */
47         rc = ocfs2_validate_meta_ecc(sb, bh->b_data, &rb->rf_check);
48         if (rc) {
49                 mlog(ML_ERROR, "Checksum failed for refcount block %llu\n",
50                      (unsigned long long)bh->b_blocknr);
51                 return rc;
52         }
53
54
55         if (!OCFS2_IS_VALID_REFCOUNT_BLOCK(rb)) {
56                 ocfs2_error(sb,
57                             "Refcount block #%llu has bad signature %.*s",
58                             (unsigned long long)bh->b_blocknr, 7,
59                             rb->rf_signature);
60                 return -EINVAL;
61         }
62
63         if (le64_to_cpu(rb->rf_blkno) != bh->b_blocknr) {
64                 ocfs2_error(sb,
65                             "Refcount block #%llu has an invalid rf_blkno "
66                             "of %llu",
67                             (unsigned long long)bh->b_blocknr,
68                             (unsigned long long)le64_to_cpu(rb->rf_blkno));
69                 return -EINVAL;
70         }
71
72         if (le32_to_cpu(rb->rf_fs_generation) != OCFS2_SB(sb)->fs_generation) {
73                 ocfs2_error(sb,
74                             "Refcount block #%llu has an invalid "
75                             "rf_fs_generation of #%u",
76                             (unsigned long long)bh->b_blocknr,
77                             le32_to_cpu(rb->rf_fs_generation));
78                 return -EINVAL;
79         }
80
81         return 0;
82 }
83
84 static int ocfs2_read_refcount_block(struct ocfs2_caching_info *ci,
85                                      u64 rb_blkno,
86                                      struct buffer_head **bh)
87 {
88         int rc;
89         struct buffer_head *tmp = *bh;
90
91         rc = ocfs2_read_block(ci, rb_blkno, &tmp,
92                               ocfs2_validate_refcount_block);
93
94         /* If ocfs2_read_block() got us a new bh, pass it up. */
95         if (!rc && !*bh)
96                 *bh = tmp;
97
98         return rc;
99 }