[PATCH 04/13] GFS: allocation

2005-09-01 Thread David Teigland
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

2005-09-01 Thread David Teigland
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;
+
+