aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ocfs2/Makefile1
-rw-r--r--fs/ocfs2/cluster/masklog.c1
-rw-r--r--fs/ocfs2/cluster/masklog.h1
-rw-r--r--fs/ocfs2/ocfs2.h3
-rw-r--r--fs/ocfs2/refcounttree.c99
5 files changed, 105 insertions, 0 deletions
diff --git a/fs/ocfs2/Makefile b/fs/ocfs2/Makefile
index 01596079dd63..31f25ce32c97 100644
--- a/fs/ocfs2/Makefile
+++ b/fs/ocfs2/Makefile
@@ -28,6 +28,7 @@ ocfs2-objs := \
28 locks.o \ 28 locks.o \
29 mmap.o \ 29 mmap.o \
30 namei.o \ 30 namei.o \
31 refcounttree.o \
31 resize.o \ 32 resize.o \
32 slot_map.o \ 33 slot_map.o \
33 suballoc.o \ 34 suballoc.o \
diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c
index 96df5416993e..1cd2934de615 100644
--- a/fs/ocfs2/cluster/masklog.c
+++ b/fs/ocfs2/cluster/masklog.c
@@ -111,6 +111,7 @@ static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = {
111 define_mask(EXPORT), 111 define_mask(EXPORT),
112 define_mask(XATTR), 112 define_mask(XATTR),
113 define_mask(QUOTA), 113 define_mask(QUOTA),
114 define_mask(REFCOUNT),
114 define_mask(ERROR), 115 define_mask(ERROR),
115 define_mask(NOTICE), 116 define_mask(NOTICE),
116 define_mask(KTHREAD), 117 define_mask(KTHREAD),
diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h
index 696c32e50716..9b4d11726cf2 100644
--- a/fs/ocfs2/cluster/masklog.h
+++ b/fs/ocfs2/cluster/masklog.h
@@ -113,6 +113,7 @@
113#define ML_EXPORT 0x0000000010000000ULL /* ocfs2 export operations */ 113#define ML_EXPORT 0x0000000010000000ULL /* ocfs2 export operations */
114#define ML_XATTR 0x0000000020000000ULL /* ocfs2 extended attributes */ 114#define ML_XATTR 0x0000000020000000ULL /* ocfs2 extended attributes */
115#define ML_QUOTA 0x0000000040000000ULL /* ocfs2 quota operations */ 115#define ML_QUOTA 0x0000000040000000ULL /* ocfs2 quota operations */
116#define ML_REFCOUNT 0x0000000080000000ULL /* refcount tree operations */
116/* bits that are infrequently given and frequently matched in the high word */ 117/* bits that are infrequently given and frequently matched in the high word */
117#define ML_ERROR 0x0000000100000000ULL /* sent to KERN_ERR */ 118#define ML_ERROR 0x0000000100000000ULL /* sent to KERN_ERR */
118#define ML_NOTICE 0x0000000200000000ULL /* setn to KERN_NOTICE */ 119#define ML_NOTICE 0x0000000200000000ULL /* setn to KERN_NOTICE */
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
index d370262b3621..6688d19e4451 100644
--- a/fs/ocfs2/ocfs2.h
+++ b/fs/ocfs2/ocfs2.h
@@ -610,6 +610,9 @@ static inline int ocfs2_uses_extended_slot_map(struct ocfs2_super *osb)
610#define OCFS2_IS_VALID_DX_LEAF(ptr) \ 610#define OCFS2_IS_VALID_DX_LEAF(ptr) \
611 (!strcmp((ptr)->dl_signature, OCFS2_DX_LEAF_SIGNATURE)) 611 (!strcmp((ptr)->dl_signature, OCFS2_DX_LEAF_SIGNATURE))
612 612
613#define OCFS2_IS_VALID_REFCOUNT_BLOCK(ptr) \
614 (!strcmp((ptr)->rf_signature, OCFS2_REFCOUNT_BLOCK_SIGNATURE))
615
613static inline unsigned long ino_from_blkno(struct super_block *sb, 616static inline unsigned long ino_from_blkno(struct super_block *sb,
614 u64 blkno) 617 u64 blkno)
615{ 618{
diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c
new file mode 100644
index 000000000000..a923535d9c37
--- /dev/null
+++ b/fs/ocfs2/refcounttree.c
@@ -0,0 +1,99 @@
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
30static 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
84static 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}