|
PATCH - pvmove doesn't terminate sometimes on 64-bit bigendian machines: msg#00033linux.kernel.device-mapper.devel
Hi, I recently had to track down a problem with pvmove not terminating on an s390x. The patch below fixes the problem. The problem is specific to 64-bit bigendian machines such as s390x or ppc-64. The linux bitset operators (test_bit, set_bit etc) work on arrays of "unsigned long". dm-log uses such bitsets but treats them often as arrays of uint32_t, only allocateing a multiple of 4 bytes (as 'clean_bits' is a uint32_t). Further, it only zeros a multiple of 4 bytes. In the simplest case, if "region_count" were (say) 30, then bitset_size (below) would be 4 and bitset_uint32_count would be 1. Thus the memory for this butset, after allocation and zeroing would be 0 0 0 0 X X X X On a bigendian 64bit machine, bit 0 for this bitset is in the 8th byte! (and every bit that dm-log would use would be in the X area). 0 0 0 0 X X X X ^ here which hasn't been cleared properly. As the dm-raid1 code only syncs and counts regions which have a 0 in the 'sync_bits' bitset, and only finishes when it has counted high enough, a large number of 1's among those 'X's will cause the sync to not complete. It is worth noting that the code uses the same bitsets for in-memory and on-disk logs. As these bitsets are host-endian and host-sized, this means that they cannot safely be moved between computers with different architectures. I don't know if the dm doco makes this clear... NeilBrown Signed-off-by: Neil Brown <neilb@xxxxxxx> ### Diffstat output ./drivers/md/dm-log.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff ./drivers/md/dm-log.c~current~ ./drivers/md/dm-log.c --- ./drivers/md/dm-log.c~current~ 2005-09-14 14:19:51.000000000 +1000 +++ ./drivers/md/dm-log.c 2005-09-14 14:21:56.000000000 +1000 @@ -333,10 +333,10 @@ static int core_ctr(struct dirty_log *lo lc->sync = sync; /* - * Work out how many words we need to hold the bitset. + * Work out how many "unsigned long"s we need to hold the bitset. */ bitset_size = dm_round_up(region_count, - sizeof(*lc->clean_bits) << BYTE_SHIFT); + sizeof(unsigned long) << BYTE_SHIFT); bitset_size >>= BYTE_SHIFT; lc->bitset_uint32_count = bitset_size / 4; |
|
| <Prev in Thread] | Current Thread | [Next in Thread> |
|---|---|---|
| Previous by Date: | RE: How about shortening SCSI timeout value dynamically?: 00033, James . Smart |
|---|---|
| Next by Date: | [SUMMARY] My EMC CX300 and multipath-tools setup: 00033, Nicola Murino |
| Previous by Thread: | lvm - No matching physical volumes foundi: 00033, Ray Stell |
| Next by Thread: | Re: PATCH - pvmove doesn't terminate sometimes on 64-bit bigendian machines: 00033, Alasdair G Kergon |
| Indexes: | [Date] [Thread] [Top] [All Lists] |
| News | FAQ | advertise |