Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 35adedb8830cf948b43b86231991124b > files > 119

gfs2-utils-0.1.62-39.el5.src.rpm

commit 08fd6f0c99e97b74db27643f93f70fd65b686e9f
Author: Bob Peterson <rpeterso@redhat.com>
Date:   Tue Jun 29 10:54:50 2010 -0500

    fsck.gfs2: unaligned access on ia64
    
    This patch ports the kernel version of the latest gfs2_bitfit function
    back to user space.  This is more efficient and avoids the unaligned
    access errors on ia64.
    
    rhbz#608158

diff --git a/gfs2/fsck/fs_bits.h b/gfs2/fsck/fs_bits.h
index 15d6679..2838785 100644
--- a/gfs2/fsck/fs_bits.h
+++ b/gfs2/fsck/fs_bits.h
@@ -28,15 +28,4 @@ struct fs_bitmap
 };
 typedef struct fs_bitmap fs_bitmap_t;
 
-/* functions with blk #'s that are buffer relative */
-uint32_t gfs2_bitcount(unsigned char *buffer, unsigned int buflen,
-		     unsigned char state);
-uint32_t gfs2_bitfit(unsigned char *buffer, unsigned int buflen,
-		   uint32_t goal, unsigned char old_state);
-
-/* functions with blk #'s that are rgrp relative */
-uint32_t gfs2_blkalloc_internal(struct rgrp_list *rgd, uint32_t goal,
-								unsigned char old_state,
-								unsigned char new_state, int do_it);
-
 #endif /* __FS_BITS_H__ */
diff --git a/gfs2/fsck/pass5.c b/gfs2/fsck/pass5.c
index f76b9dd..e483ade 100644
--- a/gfs2/fsck/pass5.c
+++ b/gfs2/fsck/pass5.c
@@ -20,7 +20,6 @@
 
 #include "libgfs2.h"
 #include "fsck.h"
-#include "fs_bits.h"
 #include "util.h"
 
 static int convert_mark(uint8_t q, uint32_t *count)
diff --git a/gfs2/libgfs2/fs_bits.c b/gfs2/libgfs2/fs_bits.c
index aae2958..ee9dfa7 100644
--- a/gfs2/libgfs2/fs_bits.c
+++ b/gfs2/libgfs2/fs_bits.c
@@ -31,6 +31,41 @@
 #define ALIGN(x,a) (((x)+(a)-1)&~((a)-1))
 
 /**
+ * gfs2_bit_search
+ * @ptr: Pointer to bitmap data
+ * @mask: Mask to use (normally 0x55555.... but adjusted for search start)
+ * @state: The state we are searching for
+ *
+ * We xor the bitmap data with a patter which is the bitwise opposite
+ * of what we are looking for, this gives rise to a pattern of ones
+ * wherever there is a match. Since we have two bits per entry, we
+ * take this pattern, shift it down by one place and then and it with
+ * the original. All the even bit positions (0,2,4, etc) then represent
+ * successful matches, so we mask with 0x55555..... to remove the unwanted
+ * odd bit positions.
+ *
+ * This allows searching of a whole u64 at once (32 blocks) with a
+ * single test (on 64 bit arches).
+ */
+
+static inline uint64_t gfs2_bit_search(const unsigned long long *ptr,
+				       unsigned long long mask,
+				       uint8_t state)
+{
+	unsigned long long tmp;
+	static const unsigned long long search[] = {
+		[0] = 0xffffffffffffffffULL,
+		[1] = 0xaaaaaaaaaaaaaaaaULL,
+		[2] = 0x5555555555555555ULL,
+		[3] = 0x0000000000000000ULL,
+	};
+	tmp = le64_to_cpu(*ptr) ^ search[state];
+	tmp &= (tmp >> 1);
+	tmp &= mask;
+	return tmp;
+}
+
+/**
  * gfs2_bitfit - Find a free block in the bitmaps
  * @buffer: the buffer that holds the bitmaps
  * @buflen: the length (in bytes) of the buffer
@@ -39,60 +74,39 @@
  *
  * Return: the block number that was allocated
  */
-uint32_t gfs2_bitfit(unsigned char *buffer, unsigned int buflen,
-					 uint32_t goal, unsigned char old_state)
+unsigned long gfs2_bitfit(const unsigned char *buf, const unsigned int len,
+			  unsigned long goal, unsigned char state)
 {
-	const uint8_t *byte, *start, *end;
-	int bit, startbit;
-	uint32_t g1, g2, misaligned;
-	unsigned long *plong;
-	unsigned long lskipval;
-
-	lskipval = (old_state & GFS2_BLKST_USED) ? LBITSKIP00 : LBITSKIP55;
-	g1 = (goal / GFS2_NBBY);
-	start = buffer + g1;
-	byte = start;
-        end = buffer + buflen;
-	g2 = ALIGN(g1, sizeof(unsigned long));
-	plong = (unsigned long *)(buffer + g2);
-	startbit = bit = (goal % GFS2_NBBY) * GFS2_BIT_SIZE;
-	misaligned = g2 - g1;
-	if (!misaligned)
-		goto ulong_aligned;
-/* parse the bitmap a byte at a time */
-misaligned:
-	while (byte < end) {
-		if (((*byte >> bit) & GFS2_BIT_MASK) == old_state) {
-			return goal +
-				(((byte - start) * GFS2_NBBY) +
-				 ((bit - startbit) >> 1));
-		}
-		bit += GFS2_BIT_SIZE;
-		if (bit >= GFS2_NBBY * GFS2_BIT_SIZE) {
-			bit = 0;
-			byte++;
-			misaligned--;
-			if (!misaligned) {
-				plong = (unsigned long *)byte;
-				goto ulong_aligned;
-			}
-		}
-	}
-	return BFITNOENT;
-
-/* parse the bitmap a unsigned long at a time */
-ulong_aligned:
-	while ((unsigned char *)plong < end) {
-		if (((*plong) & LBITMASK) != lskipval)
-			break;
-		plong++;
-	}
-	if ((unsigned char *)plong < end) {
-		byte = (const uint8_t *)plong;
-		misaligned += sizeof(unsigned long) - 1;
-		goto misaligned;
+	unsigned long spoint = (goal << 1) & ((8 * sizeof(unsigned long)) - 1);
+	const unsigned long long *ptr = ((unsigned long long *)buf) + (goal >> 5);
+	const unsigned long long *end = (unsigned long long *)
+		(buf + ALIGN(len, sizeof(unsigned long long)));
+	unsigned long long tmp;
+	unsigned long long mask = 0x5555555555555555ULL;
+	unsigned long bit;
+
+	if (state > 3)
+		return 0;
+
+	/* Mask off bits we don't care about at the start of the search */
+	mask <<= spoint;
+	tmp = gfs2_bit_search(ptr, mask, state);
+	ptr++;
+	while(tmp == 0 && ptr < end) {
+		tmp = gfs2_bit_search(ptr, 0x5555555555555555ULL, state);
+		ptr++;
 	}
-	return BFITNOENT;
+	/* Mask off any bits which are more than len bytes from the start */
+	if (ptr == end && (len & (sizeof(unsigned long long) - 1)))
+		tmp &= (((unsigned long long)~0) >>
+			(64 - 8 * (len & (sizeof(unsigned long long) - 1))));
+	/* Didn't find anything, so return */
+	if (tmp == 0)
+		return BFITNOENT;
+	ptr--;
+	bit = ffsll(tmp);
+	bit /= 2;	/* two bits per entry in the bitmap */
+	return (((const unsigned char *)ptr - buf) * GFS2_NBBY) + bit;
 }
 
 /**
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index c8cb958..8b4a135 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -385,8 +385,8 @@ void fix_device_geometry(struct gfs2_sbd *sdp);
 /* functions with blk #'s that are buffer relative */
 uint32_t gfs2_bitcount(unsigned char *buffer, unsigned int buflen,
                      unsigned char state);
-uint32_t gfs2_bitfit(unsigned char *buffer, unsigned int buflen,
-		     uint32_t goal, unsigned char old_state);
+unsigned long gfs2_bitfit(const unsigned char *buf, const unsigned int len,
+			  unsigned long goal, unsigned char state);
 
 /* functions with blk #'s that are rgrp relative */
 uint32_t gfs2_blkalloc_internal(struct rgrp_list *rgd, uint32_t goal,