Delivered-To: jwboyer@gmail.com Received: by 10.229.191.66 with SMTP id dl2csp36421qcb; Tue, 26 Jun 2012 07:55:48 -0700 (PDT) Received: by 10.68.228.136 with SMTP id si8mr53042278pbc.159.1340722548310; Tue, 26 Jun 2012 07:55:48 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id qg1si15735731pbc.300.2012.06.26.07.55.47; Tue, 26 Jun 2012 07:55:48 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mail=stable-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757370Ab2FZOzp (ORCPT + 23 others); Tue, 26 Jun 2012 10:55:45 -0400 Received: from mx1.redhat.com ([209.132.183.28]:64097 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757325Ab2FZOzo (ORCPT ); Tue, 26 Jun 2012 10:55:44 -0400 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q5QEtbK2017450 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Tue, 26 Jun 2012 10:55:38 -0400 Received: from segfault.boston.devel.redhat.com (segfault.boston.devel.redhat.com [10.16.60.26]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id q5QEtZV9023431; Tue, 26 Jun 2012 10:55:35 -0400 From: Jeff Moyer To: Jens Axboe , Nick Piggin Cc: LKML List , torsten.hilbrich@secunet.com, Richard Jones , stable@vger.kernel.org, Marcos Mello Subject: [patch] block: fix infinite loop in __getblk_slow X-PGP-KeyID: 1F78E1B4 X-PGP-CertKey: F6FE 280D 8293 F72C 65FD 5A58 1FF8 A7CA 1F78 E1B4 X-PCLoadLetter: What the f**k does that mean? Date: Tue, 26 Jun 2012 10:55:34 -0400 Message-ID: User-Agent: Gnus/5.110011 (No Gnus v0.11) Emacs/23.1 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 Sender: stable-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: stable@vger.kernel.org Hi, This commit: commit 080399aaaf3531f5b8761ec0ac30ff98891e8686 Author: Jeff Moyer Date: Fri May 11 16:34:10 2012 +0200 block: don't mark buffers beyond end of disk as mapped exposed a bug in __getblk_slow that causes mount to hang as it loops infinitely waiting for a buffer that lies beyond the end of the disk to become uptodate. The problem was initially reported by Torsten Hilbrich here: https://lkml.org/lkml/2012/6/18/54, and also reported independently here: http://www.sysresccd.org/forums/viewtopic.php?f=13&t=4511, and then Richard W.M. Jones and Marcos Mello noted a few separate bugzillas also associated with the same issue. The main problem is here, in __getblk_slow: for (;;) { struct buffer_head * bh; int ret; bh = __find_get_block(bdev, block, size); if (bh) return bh; ret = grow_buffers(bdev, block, size); if (ret < 0) return NULL; if (ret == 0) free_more_memory(); } __find_get_block does not find the block, since it will not be marked as mapped, and so grow_buffers is called to fill in the buffers for the associated page. I believe the for (;;) loop is there primarily to retry in the case of memory pressure keeping grow_buffers from succeeding. However, we also continue to loop for other cases, like the block lying beond the end of the disk. So, the fix I came up with is to only loop when grow_buffers fails due to memory allocation issues (return value of 0). The attached patch was tested by myself, Torsten, and Rich, and was found to resolve the problem in call cases. Comments, as always, are appreciated. Signed-off-by: Jeff Moyer Reported-and-Tested-by: Torsten Hilbrich Tested-by: Richard W.M. Jones Cc: Stable -- Stable Notes: this patch requires backport to 3.0, 3.2 and 3.3. diff --git a/fs/buffer.c b/fs/buffer.c index 838a9cf..c7062c8 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -1036,6 +1036,9 @@ grow_buffers(struct block_device *bdev, sector_t block, int size) static struct buffer_head * __getblk_slow(struct block_device *bdev, sector_t block, int size) { + int ret; + struct buffer_head *bh; + /* Size must be multiple of hard sectorsize */ if (unlikely(size & (bdev_logical_block_size(bdev)-1) || (size < 512 || size > PAGE_SIZE))) { @@ -1048,20 +1051,21 @@ __getblk_slow(struct block_device *bdev, sector_t block, int size) return NULL; } - for (;;) { - struct buffer_head * bh; - int ret; +retry: + bh = __find_get_block(bdev, block, size); + if (bh) + return bh; + ret = grow_buffers(bdev, block, size); + if (ret == 0) { + free_more_memory(); + goto retry; + } else if (ret > 0) { bh = __find_get_block(bdev, block, size); if (bh) return bh; - - ret = grow_buffers(bdev, block, size); - if (ret < 0) - return NULL; - if (ret == 0) - free_more_memory(); } + return NULL; } /* -- To unsubscribe from this list: send the line "unsubscribe stable" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html