aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md
diff options
context:
space:
mode:
authorJoe Thornber <ejt@redhat.com>2012-07-27 10:08:15 -0400
committerAlasdair G Kergon <agk@redhat.com>2012-07-27 10:08:15 -0400
commit310975573ba40ab526b0d76d28225d8d0999d72b (patch)
tree3ad362bb4fc0c70662c7337723222df16611f2eb /drivers/md
parent4afdd680f7c106e1c87b6dd7af9751c282ecb4b0 (diff)
dm persistent data: introduce dm_bm_set_read_only
Introduce dm_bm_set_read_only to switch the block manager into a read-only mode. To be used when dm-thin degrades due to io errors on the metadata device. Signed-off-by: Joe Thornber <ejt@redhat.com> Signed-off-by: Mike Snitzer <snitzer@redhat.com> Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Diffstat (limited to 'drivers/md')
-rw-r--r--drivers/md/persistent-data/dm-block-manager.c18
-rw-r--r--drivers/md/persistent-data/dm-block-manager.h13
2 files changed, 31 insertions, 0 deletions
diff --git a/drivers/md/persistent-data/dm-block-manager.c b/drivers/md/persistent-data/dm-block-manager.c
index ad1712e802f6..5ba277768d99 100644
--- a/drivers/md/persistent-data/dm-block-manager.c
+++ b/drivers/md/persistent-data/dm-block-manager.c
@@ -364,6 +364,7 @@ static void dm_block_manager_write_callback(struct dm_buffer *buf)
364 *--------------------------------------------------------------*/ 364 *--------------------------------------------------------------*/
365struct dm_block_manager { 365struct dm_block_manager {
366 struct dm_bufio_client *bufio; 366 struct dm_bufio_client *bufio;
367 bool read_only:1;
367}; 368};
368 369
369struct dm_block_manager *dm_block_manager_create(struct block_device *bdev, 370struct dm_block_manager *dm_block_manager_create(struct block_device *bdev,
@@ -390,6 +391,8 @@ struct dm_block_manager *dm_block_manager_create(struct block_device *bdev,
390 goto bad; 391 goto bad;
391 } 392 }
392 393
394 bm->read_only = false;
395
393 return bm; 396 return bm;
394 397
395bad: 398bad:
@@ -481,6 +484,9 @@ int dm_bm_write_lock(struct dm_block_manager *bm,
481 void *p; 484 void *p;
482 int r; 485 int r;
483 486
487 if (bm->read_only)
488 return -EPERM;
489
484 p = dm_bufio_read(bm->bufio, b, (struct dm_buffer **) result); 490 p = dm_bufio_read(bm->bufio, b, (struct dm_buffer **) result);
485 if (unlikely(IS_ERR(p))) 491 if (unlikely(IS_ERR(p)))
486 return PTR_ERR(p); 492 return PTR_ERR(p);
@@ -547,6 +553,9 @@ int dm_bm_write_lock_zero(struct dm_block_manager *bm,
547 struct buffer_aux *aux; 553 struct buffer_aux *aux;
548 void *p; 554 void *p;
549 555
556 if (bm->read_only)
557 return -EPERM;
558
550 p = dm_bufio_new(bm->bufio, b, (struct dm_buffer **) result); 559 p = dm_bufio_new(bm->bufio, b, (struct dm_buffer **) result);
551 if (unlikely(IS_ERR(p))) 560 if (unlikely(IS_ERR(p)))
552 return PTR_ERR(p); 561 return PTR_ERR(p);
@@ -589,6 +598,9 @@ int dm_bm_flush_and_unlock(struct dm_block_manager *bm,
589{ 598{
590 int r; 599 int r;
591 600
601 if (bm->read_only)
602 return -EPERM;
603
592 r = dm_bufio_write_dirty_buffers(bm->bufio); 604 r = dm_bufio_write_dirty_buffers(bm->bufio);
593 if (unlikely(r)) { 605 if (unlikely(r)) {
594 dm_bm_unlock(superblock); 606 dm_bm_unlock(superblock);
@@ -600,6 +612,12 @@ int dm_bm_flush_and_unlock(struct dm_block_manager *bm,
600 return dm_bufio_write_dirty_buffers(bm->bufio); 612 return dm_bufio_write_dirty_buffers(bm->bufio);
601} 613}
602 614
615void dm_bm_set_read_only(struct dm_block_manager *bm)
616{
617 bm->read_only = true;
618}
619EXPORT_SYMBOL_GPL(dm_bm_set_read_only);
620
603u32 dm_bm_checksum(const void *data, size_t len, u32 init_xor) 621u32 dm_bm_checksum(const void *data, size_t len, u32 init_xor)
604{ 622{
605 return crc32c(~(u32) 0, data, len) ^ init_xor; 623 return crc32c(~(u32) 0, data, len) ^ init_xor;
diff --git a/drivers/md/persistent-data/dm-block-manager.h b/drivers/md/persistent-data/dm-block-manager.h
index 327885566631..be5bff61be28 100644
--- a/drivers/md/persistent-data/dm-block-manager.h
+++ b/drivers/md/persistent-data/dm-block-manager.h
@@ -108,6 +108,19 @@ int dm_bm_unlock(struct dm_block *b);
108int dm_bm_flush_and_unlock(struct dm_block_manager *bm, 108int dm_bm_flush_and_unlock(struct dm_block_manager *bm,
109 struct dm_block *superblock); 109 struct dm_block *superblock);
110 110
111/*
112 * Switches the bm to a read only mode. Once read-only mode
113 * has been entered the following functions will return -EPERM.
114 *
115 * dm_bm_write_lock
116 * dm_bm_write_lock_zero
117 * dm_bm_flush_and_unlock
118 *
119 * Additionally you should not use dm_bm_unlock_move, however no error will
120 * be returned if you do.
121 */
122void dm_bm_set_read_only(struct dm_block_manager *bm);
123
111u32 dm_bm_checksum(const void *data, size_t len, u32 init_xor); 124u32 dm_bm_checksum(const void *data, size_t len, u32 init_xor);
112 125
113/*----------------------------------------------------------------*/ 126/*----------------------------------------------------------------*/