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" 29f2c870e3STao Ma 30f2c870e3STao Ma static int ocfs2_validate_refcount_block(struct super_block *sb, 31f2c870e3STao Ma struct buffer_head *bh) 32f2c870e3STao Ma { 33f2c870e3STao Ma int rc; 34f2c870e3STao Ma struct ocfs2_refcount_block *rb = 35f2c870e3STao Ma (struct ocfs2_refcount_block *)bh->b_data; 36f2c870e3STao Ma 37f2c870e3STao Ma mlog(0, "Validating refcount block %llu\n", 38f2c870e3STao Ma (unsigned long long)bh->b_blocknr); 39f2c870e3STao Ma 40f2c870e3STao Ma BUG_ON(!buffer_uptodate(bh)); 41f2c870e3STao Ma 42f2c870e3STao Ma /* 43f2c870e3STao Ma * If the ecc fails, we return the error but otherwise 44f2c870e3STao Ma * leave the filesystem running. We know any error is 45f2c870e3STao Ma * local to this block. 46f2c870e3STao Ma */ 47f2c870e3STao Ma rc = ocfs2_validate_meta_ecc(sb, bh->b_data, &rb->rf_check); 48f2c870e3STao Ma if (rc) { 49f2c870e3STao Ma mlog(ML_ERROR, "Checksum failed for refcount block %llu\n", 50f2c870e3STao Ma (unsigned long long)bh->b_blocknr); 51f2c870e3STao Ma return rc; 52f2c870e3STao Ma } 53f2c870e3STao Ma 54f2c870e3STao Ma 55f2c870e3STao Ma if (!OCFS2_IS_VALID_REFCOUNT_BLOCK(rb)) { 56f2c870e3STao Ma ocfs2_error(sb, 57f2c870e3STao Ma "Refcount block #%llu has bad signature %.*s", 58f2c870e3STao Ma (unsigned long long)bh->b_blocknr, 7, 59f2c870e3STao Ma rb->rf_signature); 60f2c870e3STao Ma return -EINVAL; 61f2c870e3STao Ma } 62f2c870e3STao Ma 63f2c870e3STao Ma if (le64_to_cpu(rb->rf_blkno) != bh->b_blocknr) { 64f2c870e3STao Ma ocfs2_error(sb, 65f2c870e3STao Ma "Refcount block #%llu has an invalid rf_blkno " 66f2c870e3STao Ma "of %llu", 67f2c870e3STao Ma (unsigned long long)bh->b_blocknr, 68f2c870e3STao Ma (unsigned long long)le64_to_cpu(rb->rf_blkno)); 69f2c870e3STao Ma return -EINVAL; 70f2c870e3STao Ma } 71f2c870e3STao Ma 72f2c870e3STao Ma if (le32_to_cpu(rb->rf_fs_generation) != OCFS2_SB(sb)->fs_generation) { 73f2c870e3STao Ma ocfs2_error(sb, 74f2c870e3STao Ma "Refcount block #%llu has an invalid " 75f2c870e3STao Ma "rf_fs_generation of #%u", 76f2c870e3STao Ma (unsigned long long)bh->b_blocknr, 77f2c870e3STao Ma le32_to_cpu(rb->rf_fs_generation)); 78f2c870e3STao Ma return -EINVAL; 79f2c870e3STao Ma } 80f2c870e3STao Ma 81f2c870e3STao Ma return 0; 82f2c870e3STao Ma } 83f2c870e3STao Ma 84f2c870e3STao Ma static int ocfs2_read_refcount_block(struct ocfs2_caching_info *ci, 85f2c870e3STao Ma u64 rb_blkno, 86f2c870e3STao Ma struct buffer_head **bh) 87f2c870e3STao Ma { 88f2c870e3STao Ma int rc; 89f2c870e3STao Ma struct buffer_head *tmp = *bh; 90f2c870e3STao Ma 91f2c870e3STao Ma rc = ocfs2_read_block(ci, rb_blkno, &tmp, 92f2c870e3STao Ma ocfs2_validate_refcount_block); 93f2c870e3STao Ma 94f2c870e3STao Ma /* If ocfs2_read_block() got us a new bh, pass it up. */ 95f2c870e3STao Ma if (!rc && !*bh) 96f2c870e3STao Ma *bh = tmp; 97f2c870e3STao Ma 98f2c870e3STao Ma return rc; 99f2c870e3STao Ma } 100