public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: Greg KH <gregkh@linuxfoundation.org>,
	torvalds@linux-foundation.org, akpm@linux-foundation.org,
	alan@lxorguk.ukuu.org.uk, Mikulas Patocka <mpatocka@redhat.com>,
	Alasdair G Kergon <agk@redhat.com>
Subject: [ 20/23] dm raid1: fix crash with mirror recovery and discard
Date: Thu, 26 Jul 2012 14:19:59 -0700	[thread overview]
Message-ID: <20120726211407.699019627@linuxfoundation.org> (raw)
In-Reply-To: <20120726211405.959857593@linuxfoundation.org>

From: Greg KH <gregkh@linuxfoundation.org>

3.4-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Mikulas Patocka <mpatocka@redhat.com>

commit 751f188dd5ab95b3f2b5f2f467c38aae5a2877eb upstream.

This patch fixes a crash when a discard request is sent during mirror
recovery.

Firstly, some background.  Generally, the following sequence happens during
mirror synchronization:
- function do_recovery is called
- do_recovery calls dm_rh_recovery_prepare
- dm_rh_recovery_prepare uses a semaphore to limit the number
  simultaneously recovered regions (by default the semaphore value is 1,
  so only one region at a time is recovered)
- dm_rh_recovery_prepare calls __rh_recovery_prepare,
  __rh_recovery_prepare asks the log driver for the next region to
  recover. Then, it sets the region state to DM_RH_RECOVERING. If there
  are no pending I/Os on this region, the region is added to
  quiesced_regions list. If there are pending I/Os, the region is not
  added to any list. It is added to the quiesced_regions list later (by
  dm_rh_dec function) when all I/Os finish.
- when the region is on quiesced_regions list, there are no I/Os in
  flight on this region. The region is popped from the list in
  dm_rh_recovery_start function. Then, a kcopyd job is started in the
  recover function.
- when the kcopyd job finishes, recovery_complete is called. It calls
  dm_rh_recovery_end. dm_rh_recovery_end adds the region to
  recovered_regions or failed_recovered_regions list (depending on
  whether the copy operation was successful or not).

The above mechanism assumes that if the region is in DM_RH_RECOVERING
state, no new I/Os are started on this region. When I/O is started,
dm_rh_inc_pending is called, which increases reg->pending count. When
I/O is finished, dm_rh_dec is called. It decreases reg->pending count.
If the count is zero and the region was in DM_RH_RECOVERING state,
dm_rh_dec adds it to the quiesced_regions list.

Consequently, if we call dm_rh_inc_pending/dm_rh_dec while the region is
in DM_RH_RECOVERING state, it could be added to quiesced_regions list
multiple times or it could be added to this list when kcopyd is copying
data (it is assumed that the region is not on any list while kcopyd does
its jobs). This results in memory corruption and crash.

There already exist bypasses for REQ_FLUSH requests: REQ_FLUSH requests
do not belong to any region, so they are always added to the sync list
in do_writes. dm_rh_inc_pending does not increase count for REQ_FLUSH
requests. In mirror_end_io, dm_rh_dec is never called for REQ_FLUSH
requests. These bypasses avoid the crash possibility described above.

These bypasses were improperly implemented for REQ_DISCARD when
the mirror target gained discard support in commit
5fc2ffeabb9ee0fc0e71ff16b49f34f0ed3d05b4 (dm raid1: support discard).

In do_writes, REQ_DISCARD requests is always added to the sync queue and
immediately dispatched (even if the region is in DM_RH_RECOVERING).  However,
dm_rh_inc and dm_rh_dec is called for REQ_DISCARD resusts.  So it violates the
rule that no I/Os are started on DM_RH_RECOVERING regions, and causes the list
corruption described above.

This patch changes it so that REQ_DISCARD requests follow the same path
as REQ_FLUSH. This avoids the crash.

Reference: https://bugzilla.redhat.com/837607

Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

---
 drivers/md/dm-raid1.c       |    2 +-
 drivers/md/dm-region-hash.c |    5 ++++-
 2 files changed, 5 insertions(+), 2 deletions(-)

--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -1214,7 +1214,7 @@ static int mirror_end_io(struct dm_targe
 	 * We need to dec pending if this was a write.
 	 */
 	if (rw == WRITE) {
-		if (!(bio->bi_rw & REQ_FLUSH))
+		if (!(bio->bi_rw & (REQ_FLUSH | REQ_DISCARD)))
 			dm_rh_dec(ms->rh, map_context->ll);
 		return error;
 	}
--- a/drivers/md/dm-region-hash.c
+++ b/drivers/md/dm-region-hash.c
@@ -404,6 +404,9 @@ void dm_rh_mark_nosync(struct dm_region_
 		return;
 	}
 
+	if (bio->bi_rw & REQ_DISCARD)
+		return;
+
 	/* We must inform the log that the sync count has changed. */
 	log->type->set_region_sync(log, region, 0);
 
@@ -524,7 +527,7 @@ void dm_rh_inc_pending(struct dm_region_
 	struct bio *bio;
 
 	for (bio = bios->head; bio; bio = bio->bi_next) {
-		if (bio->bi_rw & REQ_FLUSH)
+		if (bio->bi_rw & (REQ_FLUSH | REQ_DISCARD))
 			continue;
 		rh_inc(rh, dm_rh_bio_to_region(rh, bio));
 	}



  parent reply	other threads:[~2012-07-26 21:22 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-07-26 21:14 [ 00/23] 3.4.7-stable review Greg KH
2012-07-26 21:19 ` [ 01/23] md: avoid crash when stopping md array races with closing other open fds Greg Kroah-Hartman
2012-07-26 21:19   ` [ 02/23] md/raid1: close some possible races on write errors during resync Greg Kroah-Hartman
2012-07-26 21:19   ` [ 03/23] cifs: always update the inode cache with the results from a FIND_* Greg Kroah-Hartman
2012-07-26 21:19   ` [ 04/23] cifs: on CONFIG_HIGHMEM machines, limit the rsize/wsize to the kmap space Greg Kroah-Hartman
2012-07-26 21:19   ` [ 05/23] target: Clean up returning errors in PR handling code Greg Kroah-Hartman
2012-07-26 21:19   ` [ 06/23] target: Fix range calculation in WRITE SAME emulation when num blocks == 0 Greg Kroah-Hartman
2012-07-26 21:19   ` [ 07/23] ntp: Fix STA_INS/DEL clearing bug Greg Kroah-Hartman
2012-07-26 21:19   ` [ 08/23] tcm_fc: Fix crash seen with aborts and large reads Greg Kroah-Hartman
2012-07-26 21:19   ` [ 09/23] ext4: fix duplicated mnt_drop_write call in EXT4_IOC_MOVE_EXT Greg Kroah-Hartman
2012-07-26 21:19   ` [ 10/23] mm: fix lost kswapd wakeup in kswapd_stop() Greg Kroah-Hartman
2012-07-26 21:19   ` [ 11/23] HID: add battery quirk for Apple Wireless ANSI Greg Kroah-Hartman
2012-07-26 21:19   ` [ 12/23] HID: add Sennheiser BTD500USB device support Greg Kroah-Hartman
2012-07-26 21:19   ` [ 13/23] HID: multitouch: Add support for Baanto touchscreen Greg Kroah-Hartman
2012-07-26 21:19   ` [ 14/23] MIPS: Properly align the .data..init_task section Greg Kroah-Hartman
2012-07-26 21:19   ` [ 15/23] UBIFS: fix a bug in empty space fix-up Greg Kroah-Hartman
2012-07-26 21:19   ` [ 16/23] ore: Fix NFS crash by supporting any unaligned RAID IO Greg Kroah-Hartman
2012-07-26 21:19   ` [ 17/23] ore: Remove support of partial IO request (NFS crash) Greg Kroah-Hartman
2012-07-26 21:19   ` [ 18/23] pnfs-obj: dont leak objio_state if ore_write/read fails Greg Kroah-Hartman
2012-07-26 21:19   ` [ 19/23] dm thin: do not send discards to shared blocks Greg Kroah-Hartman
2012-07-26 21:19   ` Greg Kroah-Hartman [this message]
2012-07-26 21:20   ` [ 21/23] dm raid1: set discard_zeroes_data_unsupported Greg Kroah-Hartman
2012-07-26 21:20   ` [ 22/23] ARM: SAMSUNG: Update default rate for xusbxti clock Greg Kroah-Hartman
2012-07-26 21:20   ` [ 23/23] cifs: when CONFIG_HIGHMEM is set, serialize the read/write kmaps Greg Kroah-Hartman

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20120726211407.699019627@linuxfoundation.org \
    --to=gregkh@linuxfoundation.org \
    --cc=agk@redhat.com \
    --cc=akpm@linux-foundation.org \
    --cc=alan@lxorguk.ukuu.org.uk \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mpatocka@redhat.com \
    --cc=stable@vger.kernel.org \
    --cc=torvalds@linux-foundation.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox