forked from Minki/linux
ocfs2: Add ocfs2_read_refcount_block.
Signed-off-by: Tao Ma <tao.ma@oracle.com>
This commit is contained in:
parent
93c97087a6
commit
f2c870e3b1
@ -28,6 +28,7 @@ ocfs2-objs := \
|
||||
locks.o \
|
||||
mmap.o \
|
||||
namei.o \
|
||||
refcounttree.o \
|
||||
resize.o \
|
||||
slot_map.o \
|
||||
suballoc.o \
|
||||
|
@ -111,6 +111,7 @@ static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = {
|
||||
define_mask(EXPORT),
|
||||
define_mask(XATTR),
|
||||
define_mask(QUOTA),
|
||||
define_mask(REFCOUNT),
|
||||
define_mask(ERROR),
|
||||
define_mask(NOTICE),
|
||||
define_mask(KTHREAD),
|
||||
|
@ -113,6 +113,7 @@
|
||||
#define ML_EXPORT 0x0000000010000000ULL /* ocfs2 export operations */
|
||||
#define ML_XATTR 0x0000000020000000ULL /* ocfs2 extended attributes */
|
||||
#define ML_QUOTA 0x0000000040000000ULL /* ocfs2 quota operations */
|
||||
#define ML_REFCOUNT 0x0000000080000000ULL /* refcount tree operations */
|
||||
/* bits that are infrequently given and frequently matched in the high word */
|
||||
#define ML_ERROR 0x0000000100000000ULL /* sent to KERN_ERR */
|
||||
#define ML_NOTICE 0x0000000200000000ULL /* setn to KERN_NOTICE */
|
||||
|
@ -610,6 +610,9 @@ static inline int ocfs2_uses_extended_slot_map(struct ocfs2_super *osb)
|
||||
#define OCFS2_IS_VALID_DX_LEAF(ptr) \
|
||||
(!strcmp((ptr)->dl_signature, OCFS2_DX_LEAF_SIGNATURE))
|
||||
|
||||
#define OCFS2_IS_VALID_REFCOUNT_BLOCK(ptr) \
|
||||
(!strcmp((ptr)->rf_signature, OCFS2_REFCOUNT_BLOCK_SIGNATURE))
|
||||
|
||||
static inline unsigned long ino_from_blkno(struct super_block *sb,
|
||||
u64 blkno)
|
||||
{
|
||||
|
99
fs/ocfs2/refcounttree.c
Normal file
99
fs/ocfs2/refcounttree.c
Normal file
@ -0,0 +1,99 @@
|
||||
/* -*- mode: c; c-basic-offset: 8; -*-
|
||||
* vim: noexpandtab sw=8 ts=8 sts=0:
|
||||
*
|
||||
* refcounttree.c
|
||||
*
|
||||
* Copyright (C) 2009 Oracle. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*/
|
||||
|
||||
#define MLOG_MASK_PREFIX ML_REFCOUNT
|
||||
#include <cluster/masklog.h>
|
||||
#include "ocfs2.h"
|
||||
#include "inode.h"
|
||||
#include "alloc.h"
|
||||
#include "suballoc.h"
|
||||
#include "journal.h"
|
||||
#include "uptodate.h"
|
||||
#include "super.h"
|
||||
#include "buffer_head_io.h"
|
||||
#include "blockcheck.h"
|
||||
|
||||
static int ocfs2_validate_refcount_block(struct super_block *sb,
|
||||
struct buffer_head *bh)
|
||||
{
|
||||
int rc;
|
||||
struct ocfs2_refcount_block *rb =
|
||||
(struct ocfs2_refcount_block *)bh->b_data;
|
||||
|
||||
mlog(0, "Validating refcount block %llu\n",
|
||||
(unsigned long long)bh->b_blocknr);
|
||||
|
||||
BUG_ON(!buffer_uptodate(bh));
|
||||
|
||||
/*
|
||||
* If the ecc fails, we return the error but otherwise
|
||||
* leave the filesystem running. We know any error is
|
||||
* local to this block.
|
||||
*/
|
||||
rc = ocfs2_validate_meta_ecc(sb, bh->b_data, &rb->rf_check);
|
||||
if (rc) {
|
||||
mlog(ML_ERROR, "Checksum failed for refcount block %llu\n",
|
||||
(unsigned long long)bh->b_blocknr);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
if (!OCFS2_IS_VALID_REFCOUNT_BLOCK(rb)) {
|
||||
ocfs2_error(sb,
|
||||
"Refcount block #%llu has bad signature %.*s",
|
||||
(unsigned long long)bh->b_blocknr, 7,
|
||||
rb->rf_signature);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (le64_to_cpu(rb->rf_blkno) != bh->b_blocknr) {
|
||||
ocfs2_error(sb,
|
||||
"Refcount block #%llu has an invalid rf_blkno "
|
||||
"of %llu",
|
||||
(unsigned long long)bh->b_blocknr,
|
||||
(unsigned long long)le64_to_cpu(rb->rf_blkno));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (le32_to_cpu(rb->rf_fs_generation) != OCFS2_SB(sb)->fs_generation) {
|
||||
ocfs2_error(sb,
|
||||
"Refcount block #%llu has an invalid "
|
||||
"rf_fs_generation of #%u",
|
||||
(unsigned long long)bh->b_blocknr,
|
||||
le32_to_cpu(rb->rf_fs_generation));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ocfs2_read_refcount_block(struct ocfs2_caching_info *ci,
|
||||
u64 rb_blkno,
|
||||
struct buffer_head **bh)
|
||||
{
|
||||
int rc;
|
||||
struct buffer_head *tmp = *bh;
|
||||
|
||||
rc = ocfs2_read_block(ci, rb_blkno, &tmp,
|
||||
ocfs2_validate_refcount_block);
|
||||
|
||||
/* If ocfs2_read_block() got us a new bh, pass it up. */
|
||||
if (!rc && !*bh)
|
||||
*bh = tmp;
|
||||
|
||||
return rc;
|
||||
}
|
Loading…
Reference in New Issue
Block a user