ocfs2: Add caching info for refcount tree.
[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 #include "refcounttree.h"
30
31 static inline struct ocfs2_refcount_tree *
32 cache_info_to_refcount(struct ocfs2_caching_info *ci)
33 {
34         return container_of(ci, struct ocfs2_refcount_tree, rf_ci);
35 }
36
37 static 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
91 static 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 }
107
108 static 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
115 static struct super_block *
116 ocfs2_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
123 static 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
130 static 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
137 static 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
144 static 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
151 static 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 };