From patchwork Mon May 9 16:41:25 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Amir G." X-Patchwork-Id: 94799 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 B48BDB6F1E for ; Tue, 10 May 2011 02:43:21 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752808Ab1EIQnU (ORCPT ); Mon, 9 May 2011 12:43:20 -0400 Received: from mail-wy0-f174.google.com ([74.125.82.174]:33538 "EHLO mail-wy0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752701Ab1EIQnU (ORCPT ); Mon, 9 May 2011 12:43:20 -0400 Received: by mail-wy0-f174.google.com with SMTP id 21so4026020wya.19 for ; Mon, 09 May 2011 09:43:19 -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=C42Q7q491VXJhQI7Fb98OA5W/Thc5FYnWjkylkx4RJI=; b=osG2LGFhOt2x92/vG3PDePDzFf3e+1oqpRoY6a95jdLBWv5xzjpAn4qTuiH/0JVqCS UD5tey5JyxYwv8NbX4QJT5moUCx+Lra9a1xowXy4MzdRqnfB8LmdKQyTqkBgR3u/+iXs a/EP+wA0Me2mbZUZ+D8y3S7tKwysjMYJugl6s= 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=OfDLRt3QiGm7Uts5Glu17s4cuGri7Z06YtbkO/NI701QFkiQ8NcwvSCR8Q8rv3cPQt 8iAePy85YhECfRumrJWFm7sSTmd3tQi9R0lYKAAg+igffH4rlkNZerukZVpE+YrRwJHw CDbpbRLmZSLuVWT28j9LbUMDzD19Y4ePBhfGQ= Received: by 10.227.55.134 with SMTP id u6mr328181wbg.62.1304959399718; Mon, 09 May 2011 09:43:19 -0700 (PDT) Received: from localhost.localdomain (bzq-79-179-43-50.red.bezeqint.net [79.179.43.50]) by mx.google.com with ESMTPS id o23sm2034877wbc.27.2011.05.09.09.43.08 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 09 May 2011 09:43:12 -0700 (PDT) From: amir73il@users.sourceforge.net To: linux-ext4@vger.kernel.org Cc: tytso@mit.edu, Amir Goldstein , Yongqiang Yang Subject: [PATCH RFC 07/30] ext4: snapshot hooks - direct I/O Date: Mon, 9 May 2011 19:41:25 +0300 Message-Id: <1304959308-11122-8-git-send-email-amir73il@users.sourceforge.net> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: <1304959308-11122-1-git-send-email-amir73il@users.sourceforge.net> References: <1304959308-11122-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 3ed64bb..476606b 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -1370,6 +1370,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; @@ -3678,6 +3688,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 @@ -3732,6 +3765,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)) { @@ -3793,10 +3836,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,