From patchwork Tue Jun 7 15:07:34 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Amir G." X-Patchwork-Id: 99229 X-Patchwork-Delegate: tytso@mit.edu Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3C123B6F91 for ; Wed, 8 Jun 2011 01:09:17 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756525Ab1FGPJO (ORCPT ); Tue, 7 Jun 2011 11:09:14 -0400 Received: from mail-ww0-f44.google.com ([74.125.82.44]:41767 "EHLO mail-ww0-f44.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755729Ab1FGPJN (ORCPT ); Tue, 7 Jun 2011 11:09:13 -0400 Received: by mail-ww0-f44.google.com with SMTP id 36so5035787wwa.1 for ; Tue, 07 Jun 2011 08:09:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:sender:from:to:cc:subject:date:message-id :x-mailer:in-reply-to:references; bh=MZn8pTGsRyJHehXb3XKWs9mVe/gyVsfSMnwJ5BOGX54=; b=l4ESwUBLOuF/5oP5qfBQvy0M37NYB/oBco9VI4GwrdJGi4JFOe//6brBKgqE0togk9 Q+fNDxpsofIm0uVVwJiEVhjQZxS6oDpns+XlHBpzOxvJ8r3oF2uCQ7dGmXzAgd/z74Kk 5jJz/TzxgB3dMZ2xpw3NydiuSpLXb22wJpH7g= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=sender:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references; b=pTaVmJGMDiz/C/Mx7h7nWA506uVBWVDXOP8tblPAmW+pOXSDilVt8pfn/q8/ZNjtqA nVK9HeiXNHORraARCGKe7oIH7/MwsthQvp5rwV2hBHEc9CVRivDM3TZp9E4hYeQXty8D 7D5590PMxHOdFztJ0RBsErnui0MrsdaTjffEI= Received: by 10.227.201.16 with SMTP id ey16mr4888811wbb.30.1307459352813; Tue, 07 Jun 2011 08:09:12 -0700 (PDT) Received: from localhost.localdomain (bzq-218-153-66.cablep.bezeqint.net [81.218.153.66]) by mx.google.com with ESMTPS id en1sm3622645wbb.52.2011.06.07.08.09.10 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 07 Jun 2011 08:09:12 -0700 (PDT) From: amir73il@users.sourceforge.net To: linux-ext4@vger.kernel.org Cc: tytso@mit.edu, lczerner@redhat.com, Amir Goldstein , Yongqiang Yang Subject: [PATCH v1 07/36] ext4: snapshot hooks - direct I/O Date: Tue, 7 Jun 2011 18:07:34 +0300 Message-Id: <1307459283-22130-8-git-send-email-amir73il@users.sourceforge.net> X-Mailer: git-send-email 1.7.4.1 In-Reply-To: <1307459283-22130-1-git-send-email-amir73il@users.sourceforge.net> References: <1307459283-22130-1-git-send-email-amir73il@users.sourceforge.net> Sender: linux-ext4-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-ext4@vger.kernel.org From: Amir Goldstein With indirect mapped files, direct I/O write is not allowed to initialize holes, so stale data won't be exposed. With snapshots, direct I/O write is not allowed to do move-on-write, for the exact same reason. Signed-off-by: Amir Goldstein Signed-off-by: Yongqiang Yang --- fs/ext4/inode.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 48 insertions(+), 2 deletions(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 2d7e540..1cb94d2 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -1373,6 +1373,16 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode, return ret; } + if (retval > 0 && (map->m_flags & EXT4_MAP_REMAP) && + (flags & EXT4_GET_BLOCKS_PRE_IO)) { + /* + * If mow is needed on the requested block and + * request comes from async-direct-io-write path, + * we return an unmapped buffer to fall back to buffered I/O. + */ + map->m_flags &= ~EXT4_MAP_MAPPED; + return 0; + } /* If it is only a block(s) look up */ if ((flags & EXT4_GET_BLOCKS_CREATE) == 0) return retval; @@ -3654,6 +3664,29 @@ static int ext4_releasepage(struct page *page, gfp_t wait) } /* + * ext4_get_block_dio used when preparing for a DIO write + * to indirect mapped files with snapshots. + */ +int ext4_get_block_dio_write(struct inode *inode, sector_t iblock, + struct buffer_head *bh, int create) +{ + int flags = EXT4_GET_BLOCKS_CREATE; + + /* + * DIO_SKIP_HOLES may ask to map direct I/O write with create=0, + * but we know this is a write, so we need to check if block + * needs to be moved to snapshot and fall back to buffered I/O. + * ext4_map_blocks() will return an unmapped buffer if block + * is not allocated or if it needs to be moved to snapshot. + */ + if (ext4_snapshot_should_move_data(inode)) + flags |= EXT4_GET_BLOCKS_MOVE_ON_WRITE| + EXT4_GET_BLOCKS_PRE_IO; + + return _ext4_get_block(inode, iblock, bh, flags); +} + +/* * O_DIRECT for ext3 (or indirect map) based files * * If the O_DIRECT write will extend the file then add this inode to the @@ -3708,6 +3741,16 @@ retry: ret = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, offset, nr_segs, + /* + * snapshots code gets here for DIO write + * to ind mapped files or outside i_size + * of extent mapped files and for DIO read + * to all files. + * XXX: isn't it possible to expose stale data + * on DIO read to newly allocated ind map + * blocks or newly MOWed blocks? + */ + (rw == WRITE) ? ext4_get_block_dio_write : ext4_get_block, NULL); if (unlikely((rw & WRITE) && ret < 0)) { @@ -3769,10 +3812,13 @@ out: static int ext4_get_block_write(struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create) { + int flags = EXT4_GET_BLOCKS_IO_CREATE_EXT; + ext4_debug("ext4_get_block_write: inode %lu, create flag %d\n", inode->i_ino, create); - return _ext4_get_block(inode, iblock, bh_result, - EXT4_GET_BLOCKS_IO_CREATE_EXT); + if (ext4_snapshot_should_move_data(inode)) + flags |= EXT4_GET_BLOCKS_MOVE_ON_WRITE; + return _ext4_get_block(inode, iblock, bh_result, flags); } static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset,