Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] device-mapper log bitset: fix endian

Clean up the code responsible for the on-disk mirror logs by using the
set_le_bit test_le_bit functions of ext2. That makes the BE machines keep the
bitmap internally in LE order - it does mean you can't use any other type of
operations on the bitmap words but that looks to be OK in this instance. The
efficiency tradeoff is very minimal as you would expect for something that
ext2 uses.

This allows us to remove bits_to_core(), bits_to_disk() and log->disk_bits.

Also increment the mirror log disk version transparently to avoid sharing with
older kernels that suffered from the 64-bit BE bug.

Signed-off-by: Patrick Caulfield <pcaulfie@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

Patrick Caulfield and committed by
Linus Torvalds
a4fc4717 aa14edeb

+11 -34
+11 -34
drivers/md/dm-log.c
··· 112 112 /* 113 113 * The on-disk version of the metadata. 114 114 */ 115 - #define MIRROR_DISK_VERSION 1 115 + #define MIRROR_DISK_VERSION 2 116 116 #define LOG_OFFSET 2 117 117 118 118 struct log_header { ··· 157 157 struct log_header *disk_header; 158 158 159 159 struct io_region bits_location; 160 - uint32_t *disk_bits; 161 160 }; 162 161 163 162 /* ··· 165 166 */ 166 167 static inline int log_test_bit(uint32_t *bs, unsigned bit) 167 168 { 168 - return test_bit(bit, (unsigned long *) bs) ? 1 : 0; 169 + return ext2_test_bit(bit, (unsigned long *) bs) ? 1 : 0; 169 170 } 170 171 171 172 static inline void log_set_bit(struct log_c *l, 172 173 uint32_t *bs, unsigned bit) 173 174 { 174 - set_bit(bit, (unsigned long *) bs); 175 + ext2_set_bit(bit, (unsigned long *) bs); 175 176 l->touched = 1; 176 177 } 177 178 178 179 static inline void log_clear_bit(struct log_c *l, 179 180 uint32_t *bs, unsigned bit) 180 181 { 181 - clear_bit(bit, (unsigned long *) bs); 182 + ext2_clear_bit(bit, (unsigned long *) bs); 182 183 l->touched = 1; 183 184 } 184 185 ··· 218 219 log->header.nr_regions = 0; 219 220 } 220 221 222 + #ifdef __LITTLE_ENDIAN 223 + if (log->header.version == 1) 224 + log->header.version = 2; 225 + #endif 226 + 221 227 if (log->header.version != MIRROR_DISK_VERSION) { 222 228 DMWARN("incompatible disk log version"); 223 229 return -EINVAL; ··· 243 239 /*---------------------------------------------------------------- 244 240 * Bits IO 245 241 *--------------------------------------------------------------*/ 246 - static inline void bits_to_core(uint32_t *core, uint32_t *disk, unsigned count) 247 - { 248 - unsigned i; 249 - 250 - for (i = 0; i < count; i++) 251 - core[i] = le32_to_cpu(disk[i]); 252 - } 253 - 254 - static inline void bits_to_disk(uint32_t *core, uint32_t *disk, unsigned count) 255 - { 256 - unsigned i; 257 - 258 - /* copy across the clean/dirty bitset */ 259 - for (i = 0; i < count; i++) 260 - disk[i] = cpu_to_le32(core[i]); 261 - } 262 - 263 242 static int read_bits(struct log_c *log) 264 243 { 265 244 int r; 266 245 unsigned long ebits; 267 246 268 247 r = dm_io_sync_vm(1, &log->bits_location, READ, 269 - log->disk_bits, &ebits); 248 + log->clean_bits, &ebits); 270 249 if (r) 271 250 return r; 272 251 273 - bits_to_core(log->clean_bits, log->disk_bits, 274 - log->bitset_uint32_count); 275 252 return 0; 276 253 } 277 254 278 255 static int write_bits(struct log_c *log) 279 256 { 280 257 unsigned long ebits; 281 - bits_to_disk(log->clean_bits, log->disk_bits, 282 - log->bitset_uint32_count); 283 258 return dm_io_sync_vm(1, &log->bits_location, WRITE, 284 - log->disk_bits, &ebits); 259 + log->clean_bits, &ebits); 285 260 } 286 261 287 262 /*---------------------------------------------------------------- ··· 416 433 size = dm_round_up(lc->bitset_uint32_count * sizeof(uint32_t), 417 434 1 << SECTOR_SHIFT); 418 435 lc->bits_location.count = size >> SECTOR_SHIFT; 419 - lc->disk_bits = vmalloc(size); 420 - if (!lc->disk_bits) { 421 - vfree(lc->disk_header); 422 - goto bad; 423 - } 424 436 return 0; 425 437 426 438 bad: ··· 429 451 struct log_c *lc = (struct log_c *) log->context; 430 452 dm_put_device(lc->ti, lc->log_dev); 431 453 vfree(lc->disk_header); 432 - vfree(lc->disk_bits); 433 454 core_dtr(log); 434 455 } 435 456