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

[PATCH] dm mirror log: refactor context

Refactor the code that creates the core and disk log contexts to avoid the
repeated allocation of clean_bits introduced by the last patch.

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

Alasdair G Kergon and committed by
Linus Torvalds
b7cca195 702ca6f0

+63 -50
+63 -50
drivers/md/dm-log.c
··· 244 244 * argv contains region_size followed optionally by [no]sync 245 245 *--------------------------------------------------------------*/ 246 246 #define BYTE_SHIFT 3 247 - static int core_ctr(struct dirty_log *log, struct dm_target *ti, 248 - unsigned int argc, char **argv) 247 + static int create_log_context(struct dirty_log *log, struct dm_target *ti, 248 + unsigned int argc, char **argv, 249 + struct dm_dev *dev) 249 250 { 250 251 enum sync sync = DEFAULTSYNC; 251 252 252 253 struct log_c *lc; 253 254 uint32_t region_size; 254 255 unsigned int region_count; 255 - size_t bitset_size; 256 + size_t bitset_size, buf_size; 256 257 257 258 if (argc < 1 || argc > 2) { 258 259 DMWARN("wrong number of arguments to mirror log"); ··· 299 298 bitset_size >>= BYTE_SHIFT; 300 299 301 300 lc->bitset_uint32_count = bitset_size / 4; 302 - lc->clean_bits = vmalloc(bitset_size); 303 - if (!lc->clean_bits) { 304 - DMWARN("couldn't allocate clean bitset"); 305 - kfree(lc); 306 - return -ENOMEM; 301 + 302 + /* 303 + * Disk log? 304 + */ 305 + if (!dev) { 306 + lc->clean_bits = vmalloc(bitset_size); 307 + if (!lc->clean_bits) { 308 + DMWARN("couldn't allocate clean bitset"); 309 + kfree(lc); 310 + return -ENOMEM; 311 + } 312 + lc->disk_header = NULL; 313 + } else { 314 + lc->log_dev = dev; 315 + lc->header_location.bdev = lc->log_dev->bdev; 316 + lc->header_location.sector = 0; 317 + 318 + /* 319 + * Buffer holds both header and bitset. 320 + */ 321 + buf_size = dm_round_up((LOG_OFFSET << SECTOR_SHIFT) + 322 + bitset_size, ti->limits.hardsect_size); 323 + lc->header_location.count = buf_size >> SECTOR_SHIFT; 324 + 325 + lc->disk_header = vmalloc(buf_size); 326 + if (!lc->disk_header) { 327 + DMWARN("couldn't allocate disk log buffer"); 328 + kfree(lc); 329 + return -ENOMEM; 330 + } 331 + 332 + lc->clean_bits = (void *)lc->disk_header + 333 + (LOG_OFFSET << SECTOR_SHIFT); 307 334 } 335 + 308 336 memset(lc->clean_bits, -1, bitset_size); 309 337 310 338 lc->sync_bits = vmalloc(bitset_size); 311 339 if (!lc->sync_bits) { 312 340 DMWARN("couldn't allocate sync bitset"); 313 - vfree(lc->clean_bits); 341 + if (!dev) 342 + vfree(lc->clean_bits); 343 + vfree(lc->disk_header); 314 344 kfree(lc); 315 345 return -ENOMEM; 316 346 } ··· 352 320 if (!lc->recovering_bits) { 353 321 DMWARN("couldn't allocate sync bitset"); 354 322 vfree(lc->sync_bits); 355 - vfree(lc->clean_bits); 323 + if (!dev) 324 + vfree(lc->clean_bits); 325 + vfree(lc->disk_header); 356 326 kfree(lc); 357 327 return -ENOMEM; 358 328 } 359 329 memset(lc->recovering_bits, 0, bitset_size); 360 330 lc->sync_search = 0; 361 331 log->context = lc; 332 + 362 333 return 0; 334 + } 335 + 336 + static int core_ctr(struct dirty_log *log, struct dm_target *ti, 337 + unsigned int argc, char **argv) 338 + { 339 + return create_log_context(log, ti, argc, argv, NULL); 340 + } 341 + 342 + static void destroy_log_context(struct log_c *lc) 343 + { 344 + vfree(lc->sync_bits); 345 + vfree(lc->recovering_bits); 346 + kfree(lc); 363 347 } 364 348 365 349 static void core_dtr(struct dirty_log *log) 366 350 { 367 351 struct log_c *lc = (struct log_c *) log->context; 352 + 368 353 vfree(lc->clean_bits); 369 - vfree(lc->sync_bits); 370 - vfree(lc->recovering_bits); 371 - kfree(lc); 354 + destroy_log_context(lc); 372 355 } 373 356 374 357 /*---------------------------------------------------------------- ··· 395 348 unsigned int argc, char **argv) 396 349 { 397 350 int r; 398 - size_t size, bitset_size; 399 - struct log_c *lc; 400 351 struct dm_dev *dev; 401 - uint32_t *clean_bits; 402 352 403 353 if (argc < 2 || argc > 3) { 404 354 DMWARN("wrong number of arguments to disk mirror log"); ··· 407 363 if (r) 408 364 return r; 409 365 410 - r = core_ctr(log, ti, argc - 1, argv + 1); 366 + r = create_log_context(log, ti, argc - 1, argv + 1, dev); 411 367 if (r) { 412 368 dm_put_device(ti, dev); 413 369 return r; 414 370 } 415 371 416 - lc = (struct log_c *) log->context; 417 - lc->log_dev = dev; 418 - 419 - /* setup the disk header fields */ 420 - lc->header_location.bdev = lc->log_dev->bdev; 421 - lc->header_location.sector = 0; 422 - 423 - /* Include both the header and the bitset in one buffer. */ 424 - bitset_size = lc->bitset_uint32_count * sizeof(uint32_t); 425 - size = dm_round_up((LOG_OFFSET << SECTOR_SHIFT) + bitset_size, 426 - ti->limits.hardsect_size); 427 - lc->header_location.count = size >> SECTOR_SHIFT; 428 - 429 - lc->disk_header = vmalloc(size); 430 - if (!lc->disk_header) 431 - goto bad; 432 - 433 - /* 434 - * Deallocate the clean_bits buffer that was allocated in core_ctr() 435 - * and point it at the appropriate place in the disk_header buffer. 436 - */ 437 - clean_bits = lc->clean_bits; 438 - lc->clean_bits = (void *)lc->disk_header + (LOG_OFFSET << SECTOR_SHIFT); 439 - memcpy(lc->clean_bits, clean_bits, bitset_size); 440 - vfree(clean_bits); 441 - 442 372 return 0; 443 - 444 - bad: 445 - dm_put_device(ti, lc->log_dev); 446 - core_dtr(log); 447 - return -ENOMEM; 448 373 } 449 374 450 375 static void disk_dtr(struct dirty_log *log) 451 376 { 452 377 struct log_c *lc = (struct log_c *) log->context; 378 + 453 379 dm_put_device(lc->ti, lc->log_dev); 454 380 vfree(lc->disk_header); 455 - lc->clean_bits = NULL; 456 - core_dtr(log); 381 + destroy_log_context(lc); 457 382 } 458 383 459 384 static int count_bits32(uint32_t *addr, unsigned size)