Skip to contentSkip to conversation

2.6.23-stable review, filesystem changes

PATCH New Greg Kroah-Hartman 1 participant 4 messages Nov 15, 2007

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

cover 2.6.23-stable review, filesystem changes

This is the start of the stable review cycle for the 2.6.23.X release. There are 3 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let us know. If anyone is a maintainer of the proper subsystem, and wants to add a Signed-off-by: line to the patch, please respond with it.

These patches are sent out with a number of different people on the Cc:
line. If you wish to be a reviewer, please email [email protected] to add your name to the list. If you want to be off the reviewer list, also email us.

Responses should be made by Friday 00:00:00 UTC. Anything received after that time might be too late.

This set of patches focuses on filesystems.

The diffstat of this review series is included below.

thanks,

greg k-h

Signature · 5 lines
 fs/minix/itree_v1.c |    9 +++++++--
 fs/minix/itree_v2.c |    9 +++++++--
 fs/nfs/write.c      |   17 +++++++++++++----
 fs/ocfs2/aops.c     |   22 ++++++++++++++++++++++
 4 files changed, 49 insertions(+), 8 deletions(-)
#1 lore raw

PATCH 1/3 minixfs: limit minixfs printks on corrupted dir i_size (CVE-2006-6058)

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

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

From: Eric Sandeen <[email protected]>

patch f44ec6f3f89889a469773b1fd894f8fcc07c29cf upstream.

This attempts to address CVE-2006-6058
http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2006-6058

first reported at http://projects.info-pull.com/mokb/MOKB-17-11-2006.html

Essentially a corrupted minix dir inode reporting a very large i_size will loop for a very long time in minix_readdir, minix_find_entry, etc, because on EIO they just move on to try the next page. This is under the BKL, printk-storming as well. This can lock up the machine for a very long time. Simply ratelimiting the printks gets things back under control. Make the message a bit more informative while we're here.

---
 fs/minix/itree_v1.c |    9 +++++++--
 fs/minix/itree_v2.c |    9 +++++++--
 2 files changed, 14 insertions(+), 4 deletions(-)
fs/minix/itree_v1.c +7 -2
@@ -23,11 +23,16 @@ static inline block_t *i_data(struct ino
 static int block_to_path(struct inode * inode, long block, int offsets[DEPTH])
 {
 	int n = 0;
+	char b[BDEVNAME_SIZE];
 
 	if (block < 0) {
-		printk("minix_bmap: block<0\n");
+		printk("MINIX-fs: block_to_path: block %ld < 0 on dev %s\n",
+			block, bdevname(inode->i_sb->s_bdev, b));
 	} else if (block >= (minix_sb(inode->i_sb)->s_max_size/BLOCK_SIZE)) {
-		printk("minix_bmap: block>big\n");
+		if (printk_ratelimit())
+			printk("MINIX-fs: block_to_path: "
+			       "block %ld too big on dev %s\n",
+				block, bdevname(inode->i_sb->s_bdev, b));
 	} else if (block < 7) {
 		offsets[n++] = block;
 	} else if ((block -= 7) < 512) {
fs/minix/itree_v2.c +7 -2
@@ -23,12 +23,17 @@ static inline block_t *i_data(struct ino
 static int block_to_path(struct inode * inode, long block, int offsets[DEPTH])
 {
 	int n = 0;
+	char b[BDEVNAME_SIZE];
 	struct super_block *sb = inode->i_sb;
 
 	if (block < 0) {
-		printk("minix_bmap: block<0\n");
+		printk("MINIX-fs: block_to_path: block %ld < 0 on dev %s\n",
+			block, bdevname(sb->s_bdev, b));
 	} else if (block >= (minix_sb(inode->i_sb)->s_max_size/sb->s_blocksize)) {
-		printk("minix_bmap: block>big\n");
+		if (printk_ratelimit())
+			printk("MINIX-fs: block_to_path: "
+			       "block %ld too big on dev %s\n",
+				block, bdevname(sb->s_bdev, b));
 	} else if (block < 7) {
 		offsets[n++] = block;
 	} else if ((block -= 7) < 256) {
#2 lore raw

PATCH 2/3 ocfs2: fix write() performance regression

In reply to Greg Kroah-Hartman

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

------------------
From: Mark Fasheh <[email protected]>

patch 4e9563fd55ff4479f2b118d0757d121dd0cfc39c in mainline.

ocfs2: fix write() performance regression

On file systems which don't support sparse files, Ocfs2_map_page_blocks() was reading blocks on appending writes. This caused write performance to suffer dramatically. Fix this by detecting an appending write on a nonsparse fs and skipping the read.

---
 fs/ocfs2/aops.c |   22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)
fs/ocfs2/aops.c +22 -0
@@ -661,6 +661,27 @@ static void ocfs2_clear_page_regions(str
 }
 
 /*
+ * Nonsparse file systems fully allocate before we get to the write
+ * code. This prevents ocfs2_write() from tagging the write as an
+ * allocating one, which means ocfs2_map_page_blocks() might try to
+ * read-in the blocks at the tail of our file. Avoid reading them by
+ * testing i_size against each block offset.
+ */
+static int ocfs2_should_read_blk(struct inode *inode, struct page *page,
+				 unsigned int block_start)
+{
+	u64 offset = page_offset(page) + block_start;
+
+	if (ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb)))
+		return 1;
+
+	if (i_size_read(inode) > offset)
+		return 1;
+
+	return 0;
+}
+
+/*
  * Some of this taken from block_prepare_write(). We already have our
  * mapping by now though, and the entire write will be allocating or
  * it won't, so not much need to use BH_New.
@@ -713,6 +734,7 @@ int ocfs2_map_page_blocks(struct page *p
 				set_buffer_uptodate(bh);
 		} else if (!buffer_uptodate(bh) && !buffer_delay(bh) &&
 			   !buffer_new(bh) &&
+			   ocfs2_should_read_blk(inode, page, block_start) &&
 			   (block_start < from || block_end > to)) {
 			ll_rw_block(READ, 1, &bh);
 			*wait_bh++=bh;
#3 lore raw

PATCH 3/3 NFS: Fix a writeback race...

In reply to Greg Kroah-Hartman

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

------------------
From: Trond Myklebust <[email protected]>

patch 61e930a904966cc37e0a3404276f0b73037e57ca in mainline

This patch fixes a regression that was introduced by commit 44dd151d5c21234cc534c47d7382f5c28c3143cd

We cannot zero the user page in nfs_mark_uptodate() any more, since

a) We'd be modifying the page without holding the page lock
b) We can race with other updates of the page, most notably because of the call to nfs_wb_page() in nfs_writepage_setup().

Instead, we do the zeroing in nfs_update_request() if we see that we're creating a request that might potentially be marked as up to date.

Thanks to Olivier Paquet for reporting the bug and providing a test-case.

---
 fs/nfs/write.c |   17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)
fs/nfs/write.c +13 -4
@@ -167,8 +167,6 @@ static void nfs_mark_uptodate(struct pag
 		return;
 	if (count != nfs_page_length(page))
 		return;
-	if (count != PAGE_CACHE_SIZE)
-		zero_user_page(page, count, PAGE_CACHE_SIZE - count, KM_USER0);
 	SetPageUptodate(page);
 }
 
@@ -643,7 +641,8 @@ static struct nfs_page * nfs_update_requ
 				return ERR_PTR(error);
 			}
 			spin_unlock(&inode->i_lock);
-			return new;
+			req = new;
+			goto zero_page;
 		}
 		spin_unlock(&inode->i_lock);
 
@@ -671,13 +670,23 @@ static struct nfs_page * nfs_update_requ
 	if (offset < req->wb_offset) {
 		req->wb_offset = offset;
 		req->wb_pgbase = offset;
-		req->wb_bytes = rqend - req->wb_offset;
+		req->wb_bytes = max(end, rqend) - req->wb_offset;
+		goto zero_page;
 	}
 
 	if (end > rqend)
 		req->wb_bytes = end - req->wb_offset;
 
 	return req;
+zero_page:
+	/* If this page might potentially be marked as up to date,
+	 * then we need to zero any uninitalised data. */
+	if (req->wb_pgbase == 0 && req->wb_bytes != PAGE_CACHE_SIZE
+			&& !PageUptodate(req->wb_page))
+		zero_user_page(req->wb_page, req->wb_bytes,
+				PAGE_CACHE_SIZE - req->wb_bytes,
+				KM_USER0);
+	return req;
 }
 
 int nfs_flush_incompatible(struct file *file, struct page *page)