xref: /openbmc/linux/fs/ocfs2/refcounttree.c (revision c732eb16)
1f2c870e3STao Ma /* -*- mode: c; c-basic-offset: 8; -*-
2f2c870e3STao Ma  * vim: noexpandtab sw=8 ts=8 sts=0:
3f2c870e3STao Ma  *
4f2c870e3STao Ma  * refcounttree.c
5f2c870e3STao Ma  *
6f2c870e3STao Ma  * Copyright (C) 2009 Oracle.  All rights reserved.
7f2c870e3STao Ma  *
8f2c870e3STao Ma  * This program is free software; you can redistribute it and/or
9f2c870e3STao Ma  * modify it under the terms of the GNU General Public
10f2c870e3STao Ma  * License version 2 as published by the Free Software Foundation.
11f2c870e3STao Ma  *
12f2c870e3STao Ma  * This program is distributed in the hope that it will be useful,
13f2c870e3STao Ma  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14f2c870e3STao Ma  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15f2c870e3STao Ma  * General Public License for more details.
16f2c870e3STao Ma  */
17f2c870e3STao Ma 
18f2c870e3STao Ma #define MLOG_MASK_PREFIX ML_REFCOUNT
19f2c870e3STao Ma #include <cluster/masklog.h>
20f2c870e3STao Ma #include "ocfs2.h"
21f2c870e3STao Ma #include "inode.h"
22f2c870e3STao Ma #include "alloc.h"
23f2c870e3STao Ma #include "suballoc.h"
24f2c870e3STao Ma #include "journal.h"
25f2c870e3STao Ma #include "uptodate.h"
26f2c870e3STao Ma #include "super.h"
27f2c870e3STao Ma #include "buffer_head_io.h"
28f2c870e3STao Ma #include "blockcheck.h"
29c732eb16STao Ma #include "refcounttree.h"
30c732eb16STao Ma 
31c732eb16STao Ma static inline struct ocfs2_refcount_tree *
32c732eb16STao Ma cache_info_to_refcount(struct ocfs2_caching_info *ci)
33c732eb16STao Ma {
34c732eb16STao Ma 	return container_of(ci, struct ocfs2_refcount_tree, rf_ci);
35c732eb16STao Ma }
36f2c870e3STao Ma 
37f2c870e3STao Ma static int ocfs2_validate_refcount_block(struct super_block *sb,
38f2c870e3STao Ma 					 struct buffer_head *bh)
39f2c870e3STao Ma {
40f2c870e3STao Ma 	int rc;
41f2c870e3STao Ma 	struct ocfs2_refcount_block *rb =
42f2c870e3STao Ma 		(struct ocfs2_refcount_block *)bh->b_data;
43f2c870e3STao Ma 
44f2c870e3STao Ma 	mlog(0, "Validating refcount block %llu\n",
45f2c870e3STao Ma 	     (unsigned long long)bh->b_blocknr);
46f2c870e3STao Ma 
47f2c870e3STao Ma 	BUG_ON(!buffer_uptodate(bh));
48f2c870e3STao Ma 
49f2c870e3STao Ma 	/*
50f2c870e3STao Ma 	 * If the ecc fails, we return the error but otherwise
51f2c870e3STao Ma 	 * leave the filesystem running.  We know any error is
52f2c870e3STao Ma 	 * local to this block.
53f2c870e3STao Ma 	 */
54f2c870e3STao Ma 	rc = ocfs2_validate_meta_ecc(sb, bh->b_data, &rb->rf_check);
55f2c870e3STao Ma 	if (rc) {
56f2c870e3STao Ma 		mlog(ML_ERROR, "Checksum failed for refcount block %llu\n",
57f2c870e3STao Ma 		     (unsigned long long)bh->b_blocknr);
58f2c870e3STao Ma 		return rc;
59f2c870e3STao Ma 	}
60f2c870e3STao Ma 
61f2c870e3STao Ma 
62f2c870e3STao Ma 	if (!OCFS2_IS_VALID_REFCOUNT_BLOCK(rb)) {
63f2c870e3STao Ma 		ocfs2_error(sb,
64f2c870e3STao Ma 			    "Refcount block #%llu has bad signature %.*s",
65f2c870e3STao Ma 			    (unsigned long long)bh->b_blocknr, 7,
66f2c870e3STao Ma 			    rb->rf_signature);
67f2c870e3STao Ma 		return -EINVAL;
68f2c870e3STao Ma 	}
69f2c870e3STao Ma 
70f2c870e3STao Ma 	if (le64_to_cpu(rb->rf_blkno) != bh->b_blocknr) {
71f2c870e3STao Ma 		ocfs2_error(sb,
72f2c870e3STao Ma 			    "Refcount block #%llu has an invalid rf_blkno "
73f2c870e3STao Ma 			    "of %llu",
74f2c870e3STao Ma 			    (unsigned long long)bh->b_blocknr,
75f2c870e3STao Ma 			    (unsigned long long)le64_to_cpu(rb->rf_blkno));
76f2c870e3STao Ma 		return -EINVAL;
77f2c870e3STao Ma 	}
78f2c870e3STao Ma 
79f2c870e3STao Ma 	if (le32_to_cpu(rb->rf_fs_generation) != OCFS2_SB(sb)->fs_generation) {
80f2c870e3STao Ma 		ocfs2_error(sb,
81f2c870e3STao Ma 			    "Refcount block #%llu has an invalid "
82f2c870e3STao Ma 			    "rf_fs_generation of #%u",
83f2c870e3STao Ma 			    (unsigned long long)bh->b_blocknr,
84f2c870e3STao Ma 			    le32_to_cpu(rb->rf_fs_generation));
85f2c870e3STao Ma 		return -EINVAL;
86f2c870e3STao Ma 	}
87f2c870e3STao Ma 
88f2c870e3STao Ma 	return 0;
89f2c870e3STao Ma }
90f2c870e3STao Ma 
91f2c870e3STao Ma static int ocfs2_read_refcount_block(struct ocfs2_caching_info *ci,
92f2c870e3STao Ma 				     u64 rb_blkno,
93f2c870e3STao Ma 				     struct buffer_head **bh)
94f2c870e3STao Ma {
95f2c870e3STao Ma 	int rc;
96f2c870e3STao Ma 	struct buffer_head *tmp = *bh;
97f2c870e3STao Ma 
98f2c870e3STao Ma 	rc = ocfs2_read_block(ci, rb_blkno, &tmp,
99f2c870e3STao Ma 			      ocfs2_validate_refcount_block);
100f2c870e3STao Ma 
101f2c870e3STao Ma 	/* If ocfs2_read_block() got us a new bh, pass it up. */
102f2c870e3STao Ma 	if (!rc && !*bh)
103f2c870e3STao Ma 		*bh = tmp;
104f2c870e3STao Ma 
105f2c870e3STao Ma 	return rc;
106f2c870e3STao Ma }
107c732eb16STao Ma 
108c732eb16STao Ma static u64 ocfs2_refcount_cache_owner(struct ocfs2_caching_info *ci)
109c732eb16STao Ma {
110c732eb16STao Ma 	struct ocfs2_refcount_tree *rf = cache_info_to_refcount(ci);
111c732eb16STao Ma 
112c732eb16STao Ma 	return rf->rf_blkno;
113c732eb16STao Ma }
114c732eb16STao Ma 
115c732eb16STao Ma static struct super_block *
116c732eb16STao Ma ocfs2_refcount_cache_get_super(struct ocfs2_caching_info *ci)
117c732eb16STao Ma {
118c732eb16STao Ma 	struct ocfs2_refcount_tree *rf = cache_info_to_refcount(ci);
119c732eb16STao Ma 
120c732eb16STao Ma 	return rf->rf_sb;
121c732eb16STao Ma }
122c732eb16STao Ma 
123c732eb16STao Ma static void ocfs2_refcount_cache_lock(struct ocfs2_caching_info *ci)
124c732eb16STao Ma {
125c732eb16STao Ma 	struct ocfs2_refcount_tree *rf = cache_info_to_refcount(ci);
126c732eb16STao Ma 
127c732eb16STao Ma 	spin_lock(&rf->rf_lock);
128c732eb16STao Ma }
129c732eb16STao Ma 
130c732eb16STao Ma static void ocfs2_refcount_cache_unlock(struct ocfs2_caching_info *ci)
131c732eb16STao Ma {
132c732eb16STao Ma 	struct ocfs2_refcount_tree *rf = cache_info_to_refcount(ci);
133c732eb16STao Ma 
134c732eb16STao Ma 	spin_unlock(&rf->rf_lock);
135c732eb16STao Ma }
136c732eb16STao Ma 
137c732eb16STao Ma static void ocfs2_refcount_cache_io_lock(struct ocfs2_caching_info *ci)
138c732eb16STao Ma {
139c732eb16STao Ma 	struct ocfs2_refcount_tree *rf = cache_info_to_refcount(ci);
140c732eb16STao Ma 
141c732eb16STao Ma 	mutex_lock(&rf->rf_io_mutex);
142c732eb16STao Ma }
143c732eb16STao Ma 
144c732eb16STao Ma static void ocfs2_refcount_cache_io_unlock(struct ocfs2_caching_info *ci)
145c732eb16STao Ma {
146c732eb16STao Ma 	struct ocfs2_refcount_tree *rf = cache_info_to_refcount(ci);
147c732eb16STao Ma 
148c732eb16STao Ma 	mutex_unlock(&rf->rf_io_mutex);
149c732eb16STao Ma }
150c732eb16STao Ma 
151c732eb16STao Ma static const struct ocfs2_caching_operations ocfs2_refcount_caching_ops = {
152c732eb16STao Ma 	.co_owner		= ocfs2_refcount_cache_owner,
153c732eb16STao Ma 	.co_get_super		= ocfs2_refcount_cache_get_super,
154c732eb16STao Ma 	.co_cache_lock		= ocfs2_refcount_cache_lock,
155c732eb16STao Ma 	.co_cache_unlock	= ocfs2_refcount_cache_unlock,
156c732eb16STao Ma 	.co_io_lock		= ocfs2_refcount_cache_io_lock,
157c732eb16STao Ma 	.co_io_unlock		= ocfs2_refcount_cache_io_unlock,
158c732eb16STao Ma };
159