blob: eb0f4a047938b1dd7edca49034d1e6e1d5e678d6 [file] [log] [blame]
Tao Maf2c870e2009-08-18 11:19:26 +08001/* -*- 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"
Tao Mac732eb12009-08-18 11:21:00 +080029#include "refcounttree.h"
30
31static inline struct ocfs2_refcount_tree *
32cache_info_to_refcount(struct ocfs2_caching_info *ci)
33{
34 return container_of(ci, struct ocfs2_refcount_tree, rf_ci);
35}
Tao Maf2c870e2009-08-18 11:19:26 +080036
37static int ocfs2_validate_refcount_block(struct super_block *sb,
38 struct buffer_head *bh)
39{
40 int rc;
41 struct ocfs2_refcount_block *rb =
42 (struct ocfs2_refcount_block *)bh->b_data;
43
44 mlog(0, "Validating refcount block %llu\n",
45 (unsigned long long)bh->b_blocknr);
46
47 BUG_ON(!buffer_uptodate(bh));
48
49 /*
50 * If the ecc fails, we return the error but otherwise
51 * leave the filesystem running. We know any error is
52 * local to this block.
53 */
54 rc = ocfs2_validate_meta_ecc(sb, bh->b_data, &rb->rf_check);
55 if (rc) {
56 mlog(ML_ERROR, "Checksum failed for refcount block %llu\n",
57 (unsigned long long)bh->b_blocknr);
58 return rc;
59 }
60
61
62 if (!OCFS2_IS_VALID_REFCOUNT_BLOCK(rb)) {
63 ocfs2_error(sb,
64 "Refcount block #%llu has bad signature %.*s",
65 (unsigned long long)bh->b_blocknr, 7,
66 rb->rf_signature);
67 return -EINVAL;
68 }
69
70 if (le64_to_cpu(rb->rf_blkno) != bh->b_blocknr) {
71 ocfs2_error(sb,
72 "Refcount block #%llu has an invalid rf_blkno "
73 "of %llu",
74 (unsigned long long)bh->b_blocknr,
75 (unsigned long long)le64_to_cpu(rb->rf_blkno));
76 return -EINVAL;
77 }
78
79 if (le32_to_cpu(rb->rf_fs_generation) != OCFS2_SB(sb)->fs_generation) {
80 ocfs2_error(sb,
81 "Refcount block #%llu has an invalid "
82 "rf_fs_generation of #%u",
83 (unsigned long long)bh->b_blocknr,
84 le32_to_cpu(rb->rf_fs_generation));
85 return -EINVAL;
86 }
87
88 return 0;
89}
90
91static int ocfs2_read_refcount_block(struct ocfs2_caching_info *ci,
92 u64 rb_blkno,
93 struct buffer_head **bh)
94{
95 int rc;
96 struct buffer_head *tmp = *bh;
97
98 rc = ocfs2_read_block(ci, rb_blkno, &tmp,
99 ocfs2_validate_refcount_block);
100
101 /* If ocfs2_read_block() got us a new bh, pass it up. */
102 if (!rc && !*bh)
103 *bh = tmp;
104
105 return rc;
106}
Tao Mac732eb12009-08-18 11:21:00 +0800107
108static u64 ocfs2_refcount_cache_owner(struct ocfs2_caching_info *ci)
109{
110 struct ocfs2_refcount_tree *rf = cache_info_to_refcount(ci);
111
112 return rf->rf_blkno;
113}
114
115static struct super_block *
116ocfs2_refcount_cache_get_super(struct ocfs2_caching_info *ci)
117{
118 struct ocfs2_refcount_tree *rf = cache_info_to_refcount(ci);
119
120 return rf->rf_sb;
121}
122
123static void ocfs2_refcount_cache_lock(struct ocfs2_caching_info *ci)
124{
125 struct ocfs2_refcount_tree *rf = cache_info_to_refcount(ci);
126
127 spin_lock(&rf->rf_lock);
128}
129
130static void ocfs2_refcount_cache_unlock(struct ocfs2_caching_info *ci)
131{
132 struct ocfs2_refcount_tree *rf = cache_info_to_refcount(ci);
133
134 spin_unlock(&rf->rf_lock);
135}
136
137static void ocfs2_refcount_cache_io_lock(struct ocfs2_caching_info *ci)
138{
139 struct ocfs2_refcount_tree *rf = cache_info_to_refcount(ci);
140
141 mutex_lock(&rf->rf_io_mutex);
142}
143
144static void ocfs2_refcount_cache_io_unlock(struct ocfs2_caching_info *ci)
145{
146 struct ocfs2_refcount_tree *rf = cache_info_to_refcount(ci);
147
148 mutex_unlock(&rf->rf_io_mutex);
149}
150
151static const struct ocfs2_caching_operations ocfs2_refcount_caching_ops = {
152 .co_owner = ocfs2_refcount_cache_owner,
153 .co_get_super = ocfs2_refcount_cache_get_super,
154 .co_cache_lock = ocfs2_refcount_cache_lock,
155 .co_cache_unlock = ocfs2_refcount_cache_unlock,
156 .co_io_lock = ocfs2_refcount_cache_io_lock,
157 .co_io_unlock = ocfs2_refcount_cache_io_unlock,
158};