[PATCH 04/13] GFS: allocation
Code that manages block allocation. Signed-off-by: Ken Preslan <[EMAIL PROTECTED]> Signed-off-by: David Teigland <[EMAIL PROTECTED]> --- fs/gfs2/bits.c | 179 +++ fs/gfs2/bits.h | 28 + fs/gfs2/rgrp.c | 1374 + fs/gfs2/rgrp.h | 62 ++ 4 files changed, 1643 insertions(+) --- a/fs/gfs2/rgrp.c1970-01-01 07:30:00.0 +0730 +++ b/fs/gfs2/rgrp.c2005-09-01 17:36:55.478090696 +0800 @@ -0,0 +1,1374 @@ +/* + * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. + * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU General Public License v.2. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "gfs2.h" +#include "bits.h" +#include "glock.h" +#include "glops.h" +#include "jdata.h" +#include "lops.h" +#include "meta_io.h" +#include "quota.h" +#include "rgrp.h" +#include "super.h" +#include "trans.h" + +/** + * gfs2_rgrp_verify - Verify that a resource group is consistent + * @sdp: the filesystem + * @rgd: the rgrp + * + */ + +void gfs2_rgrp_verify(struct gfs2_rgrpd *rgd) +{ + struct gfs2_sbd *sdp = rgd->rd_sbd; + struct gfs2_bitmap *bi = NULL; + uint32_t length = rgd->rd_ri.ri_length; + uint32_t count[4], tmp; + int buf, x; + + memset(count, 0, 4 * sizeof(uint32_t)); + + /* Count # blocks in each of 4 possible allocation states */ + for (buf = 0; buf < length; buf++) { + bi = rgd->rd_bits + buf; + for (x = 0; x < 4; x++) + count[x] += gfs2_bitcount(rgd, + bi->bi_bh->b_data + + bi->bi_offset, + bi->bi_len, x); + } + + if (count[0] != rgd->rd_rg.rg_free) { + if (gfs2_consist_rgrpd(rgd)) + fs_err(sdp, "free data mismatch: %u != %u\n", + count[0], rgd->rd_rg.rg_free); + return; + } + + tmp = rgd->rd_ri.ri_data - + rgd->rd_rg.rg_free - + rgd->rd_rg.rg_dinodes; + if (count[1] != tmp) { + if (gfs2_consist_rgrpd(rgd)) + fs_err(sdp, "used data mismatch: %u != %u\n", + count[1], tmp); + return; + } + + if (count[2]) { + if (gfs2_consist_rgrpd(rgd)) + fs_err(sdp, "free metadata mismatch: %u != 0\n", + count[2]); + return; + } + + if (count[3] != rgd->rd_rg.rg_dinodes) { + if (gfs2_consist_rgrpd(rgd)) + fs_err(sdp, "used metadata mismatch: %u != %u\n", + count[3], rgd->rd_rg.rg_dinodes); + return; + } +} + +static inline int rgrp_contains_block(struct gfs2_rindex *ri, uint64_t block) +{ + uint64_t first = ri->ri_data0; + uint64_t last = first + ri->ri_data; + return !!(first <= block && block < last); +} + +/** + * gfs2_blk2rgrpd - Find resource group for a given data/meta block number + * @sdp: The GFS2 superblock + * @n: The data block number + * + * Returns: The resource group, or NULL if not found + */ + +struct gfs2_rgrpd *gfs2_blk2rgrpd(struct gfs2_sbd *sdp, uint64_t blk) +{ + struct gfs2_rgrpd *rgd; + + spin_lock(>sd_rindex_spin); + + list_for_each_entry(rgd, >sd_rindex_mru_list, rd_list_mru) { + if (rgrp_contains_block(>rd_ri, blk)) { + list_move(>rd_list_mru, >sd_rindex_mru_list); + spin_unlock(>sd_rindex_spin); + return rgd; + } + } + + spin_unlock(>sd_rindex_spin); + + return NULL; +} + +/** + * gfs2_rgrpd_get_first - get the first Resource Group in the filesystem + * @sdp: The GFS2 superblock + * + * Returns: The first rgrp in the filesystem + */ + +struct gfs2_rgrpd *gfs2_rgrpd_get_first(struct gfs2_sbd *sdp) +{ + gfs2_assert(sdp, !list_empty(>sd_rindex_list),); + return list_entry(sdp->sd_rindex_list.next, struct gfs2_rgrpd, rd_list); +} + +/** + * gfs2_rgrpd_get_next - get the next RG + * @rgd: A RG + * + * Returns: The next rgrp + */ + +struct gfs2_rgrpd *gfs2_rgrpd_get_next(struct gfs2_rgrpd *rgd) +{ + if (rgd->rd_list.next == >rd_sbd->sd_rindex_list) + return NULL; + return list_entry(rgd->rd_list.next, struct gfs2_rgrpd, rd_list); +} + +static void clear_rgrpdi(struct gfs2_sbd *sdp) +{ + struct list_head *head; + struct gfs2_rgrpd *rgd; + struct gfs2_glock *gl; + + spin_lock(>sd_rindex_spin); + sdp->sd_rindex_forward = NULL; + head =
[PATCH 04/13] GFS: allocation
Code that manages block allocation. Signed-off-by: Ken Preslan [EMAIL PROTECTED] Signed-off-by: David Teigland [EMAIL PROTECTED] --- fs/gfs2/bits.c | 179 +++ fs/gfs2/bits.h | 28 + fs/gfs2/rgrp.c | 1374 + fs/gfs2/rgrp.h | 62 ++ 4 files changed, 1643 insertions(+) --- a/fs/gfs2/rgrp.c1970-01-01 07:30:00.0 +0730 +++ b/fs/gfs2/rgrp.c2005-09-01 17:36:55.478090696 +0800 @@ -0,0 +1,1374 @@ +/* + * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. + * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU General Public License v.2. + */ + +#include linux/sched.h +#include linux/slab.h +#include linux/smp_lock.h +#include linux/spinlock.h +#include linux/completion.h +#include linux/buffer_head.h +#include asm/semaphore.h + +#include gfs2.h +#include bits.h +#include glock.h +#include glops.h +#include jdata.h +#include lops.h +#include meta_io.h +#include quota.h +#include rgrp.h +#include super.h +#include trans.h + +/** + * gfs2_rgrp_verify - Verify that a resource group is consistent + * @sdp: the filesystem + * @rgd: the rgrp + * + */ + +void gfs2_rgrp_verify(struct gfs2_rgrpd *rgd) +{ + struct gfs2_sbd *sdp = rgd-rd_sbd; + struct gfs2_bitmap *bi = NULL; + uint32_t length = rgd-rd_ri.ri_length; + uint32_t count[4], tmp; + int buf, x; + + memset(count, 0, 4 * sizeof(uint32_t)); + + /* Count # blocks in each of 4 possible allocation states */ + for (buf = 0; buf length; buf++) { + bi = rgd-rd_bits + buf; + for (x = 0; x 4; x++) + count[x] += gfs2_bitcount(rgd, + bi-bi_bh-b_data + + bi-bi_offset, + bi-bi_len, x); + } + + if (count[0] != rgd-rd_rg.rg_free) { + if (gfs2_consist_rgrpd(rgd)) + fs_err(sdp, free data mismatch: %u != %u\n, + count[0], rgd-rd_rg.rg_free); + return; + } + + tmp = rgd-rd_ri.ri_data - + rgd-rd_rg.rg_free - + rgd-rd_rg.rg_dinodes; + if (count[1] != tmp) { + if (gfs2_consist_rgrpd(rgd)) + fs_err(sdp, used data mismatch: %u != %u\n, + count[1], tmp); + return; + } + + if (count[2]) { + if (gfs2_consist_rgrpd(rgd)) + fs_err(sdp, free metadata mismatch: %u != 0\n, + count[2]); + return; + } + + if (count[3] != rgd-rd_rg.rg_dinodes) { + if (gfs2_consist_rgrpd(rgd)) + fs_err(sdp, used metadata mismatch: %u != %u\n, + count[3], rgd-rd_rg.rg_dinodes); + return; + } +} + +static inline int rgrp_contains_block(struct gfs2_rindex *ri, uint64_t block) +{ + uint64_t first = ri-ri_data0; + uint64_t last = first + ri-ri_data; + return !!(first = block block last); +} + +/** + * gfs2_blk2rgrpd - Find resource group for a given data/meta block number + * @sdp: The GFS2 superblock + * @n: The data block number + * + * Returns: The resource group, or NULL if not found + */ + +struct gfs2_rgrpd *gfs2_blk2rgrpd(struct gfs2_sbd *sdp, uint64_t blk) +{ + struct gfs2_rgrpd *rgd; + + spin_lock(sdp-sd_rindex_spin); + + list_for_each_entry(rgd, sdp-sd_rindex_mru_list, rd_list_mru) { + if (rgrp_contains_block(rgd-rd_ri, blk)) { + list_move(rgd-rd_list_mru, sdp-sd_rindex_mru_list); + spin_unlock(sdp-sd_rindex_spin); + return rgd; + } + } + + spin_unlock(sdp-sd_rindex_spin); + + return NULL; +} + +/** + * gfs2_rgrpd_get_first - get the first Resource Group in the filesystem + * @sdp: The GFS2 superblock + * + * Returns: The first rgrp in the filesystem + */ + +struct gfs2_rgrpd *gfs2_rgrpd_get_first(struct gfs2_sbd *sdp) +{ + gfs2_assert(sdp, !list_empty(sdp-sd_rindex_list),); + return list_entry(sdp-sd_rindex_list.next, struct gfs2_rgrpd, rd_list); +} + +/** + * gfs2_rgrpd_get_next - get the next RG + * @rgd: A RG + * + * Returns: The next rgrp + */ + +struct gfs2_rgrpd *gfs2_rgrpd_get_next(struct gfs2_rgrpd *rgd) +{ + if (rgd-rd_list.next == rgd-rd_sbd-sd_rindex_list) + return NULL; + return list_entry(rgd-rd_list.next, struct gfs2_rgrpd, rd_list); +} + +static void clear_rgrpdi(struct gfs2_sbd *sdp) +{ + struct list_head *head; + struct gfs2_rgrpd *rgd; + struct gfs2_glock *gl; + +