Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:sschapiro:openstack:upstream
cluster
fsck_gfs2_unaligned_access_on_ia64_part1.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File fsck_gfs2_unaligned_access_on_ia64_part1.patch of Package cluster
From 4d6b610339b27a30deac7d9e29dc4236824b58ad Mon Sep 17 00:00:00 2001 From: Bob Peterson <rpeterso@redhat.com> Date: Mon, 28 Jun 2010 17:23:25 -0500 Subject: [PATCH] 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#608154 --- gfs2/fsck/fs_bits.h | 11 ----- gfs2/fsck/pass5.c | 1 - gfs2/libgfs2/fs_bits.c | 115 ++++++++++++++++++++++++++--------------------- gfs2/libgfs2/libgfs2.h | 5 +- 4 files changed, 67 insertions(+), 65 deletions(-) diff --git a/gfs2/fsck/fs_bits.h b/gfs2/fsck/fs_bits.h index 371c6c6..d4f262e 100644 --- a/gfs2/fsck/fs_bits.h +++ b/gfs2/fsck/fs_bits.h @@ -14,15 +14,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 645d81c..79493e1 100644 --- a/gfs2/fsck/pass5.c +++ b/gfs2/fsck/pass5.c @@ -7,7 +7,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 c420dfc..380dd81 100644 --- a/gfs2/libgfs2/fs_bits.c +++ b/gfs2/libgfs2/fs_bits.c @@ -18,6 +18,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 @@ -26,61 +61,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 0c4bc8a..8835a4f 100644 --- a/gfs2/libgfs2/libgfs2.h +++ b/gfs2/libgfs2/libgfs2.h @@ -395,8 +395,9 @@ extern int fix_device_geometry(struct gfs2_sbd *sdp); /* functions with blk #'s that are buffer relative */ extern uint32_t gfs2_bitcount(unsigned char *buffer, unsigned int buflen, unsigned char state); -extern uint32_t gfs2_bitfit(unsigned char *buffer, unsigned int buflen, - uint32_t goal, unsigned char old_state); +extern unsigned long gfs2_bitfit(const unsigned char *buffer, + const unsigned int buflen, + unsigned long goal, unsigned char old_state); /* functions with blk #'s that are rgrp relative */ extern uint32_t gfs2_blkalloc_internal(struct rgrp_list *rgd, uint32_t goal, -- 1.6.2.5
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor