Received: by 10.223.185.111 with SMTP id b44csp1643974wrg; Sat, 10 Mar 2018 10:27:13 -0800 (PST) X-Google-Smtp-Source: AG47ELtMRsENFTsA/PAcA3evNhZGIg0eYD/daAmtDOgFSsvw0uaYg7FvZqp4w0HWZhormCxLSAb5 X-Received: by 10.98.61.73 with SMTP id k70mr2697745pfa.10.1520706433494; Sat, 10 Mar 2018 10:27:13 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1520706433; cv=none; d=google.com; s=arc-20160816; b=y7z4aEMXbipI0bILYTT5rtG7w1sPrME6616hzRMnu5UbewL7i0IBViuteZ2UfkaKdm vAh1Y2q3x3RSKA+8VHMYWHFHb9Iool/EL37ssU+c8vizVp57KMMzGrOludcaJBHvnbDy pZjxBYOtjoFg30RKDG/UGWGP1pwNjOgo0ey0EDxqjUTmtRN/LWFpuJYG46CSXfpXycdx S+O7Bujx+VuB7Lw9fRXrSFh61DO6Tg/97OIeDb4lbHcBAbuvLVici9cgxyW0pf48PYfY Jfy3DraPrvLI9GS9Yb2l7fM0fgbY/CWBuSpamwNL1JJdYSb9W7clo3ZHHB4oBE7KsWTz o2Uw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=JTpozIbz8Bqk8jMH6bZzbqmuwgVBJmbVyoi9nDkoamo=; b=Fl8jxJqyoQd4iMDL+GQ5MPO6L+YpDxV7TYB/O1CPN4r2UBSH9oER02EBiTdnoyBu4t gJJKMUhf290O/Vm6h2DR76ihOD0NcZNfdDpAQBk7z6Hxvm4400rnKAsJxGEla6wrO87N 9eMv/HDYs+4XnmOy91FreHZ6l7UhSc3Em3LKzHkOEJS/g4g/evb2zO50qtFvQP8qWOKC 9iBbQ6E53uKmmtWbLmVoms1t0yRE+19Oz0GuoINmltIU+Rk3Qrn0LQgLiGzAJsFPUAEv +cpiY2z6e+JursqRzCeSAZTxzpfsZGxV/kfrK4N2aiQf9AVnS+ohjbvTdN4xuJoBtXf4 vn2A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@eng.ucsd.edu header.s=google header.b=PRByxTUb; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id d70si3017935pfj.238.2018.03.10.10.26.59; Sat, 10 Mar 2018 10:27:13 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@eng.ucsd.edu header.s=google header.b=PRByxTUb; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751392AbeCJSZY (ORCPT + 99 others); Sat, 10 Mar 2018 13:25:24 -0500 Received: from mail-pf0-f195.google.com ([209.85.192.195]:43578 "EHLO mail-pf0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932894AbeCJSVp (ORCPT ); Sat, 10 Mar 2018 13:21:45 -0500 Received: by mail-pf0-f195.google.com with SMTP id j2so2614405pff.10 for ; Sat, 10 Mar 2018 10:21:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=eng.ucsd.edu; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=JTpozIbz8Bqk8jMH6bZzbqmuwgVBJmbVyoi9nDkoamo=; b=PRByxTUbLVlQ673XUZIUT7mSuVQMpxpjST/9reuetrOXpGd+E5blt3P1Oxf1NdQI9M LWJaA/2v2iB/wQ/+9B2dJ3rsd9XQ7HK++gJvV3uup5DLGeo95ijOPVbdYXogNvBgyD1/ Rwp96e3jeokwqtzE+YNqPq5XzOlhku4TUqfXw= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=JTpozIbz8Bqk8jMH6bZzbqmuwgVBJmbVyoi9nDkoamo=; b=Senutc81qdAHSPzTWRnyNA7xEijmI8IZOztuN2rVUyZncBbzc6+wkiIRmnpmAZ0zr3 A0t/o2vx9YXXXCiRpg5tUSgO/egFcOqcyP2QHfQkIYmGqG7FyWxBrsdl2d8823a3ng7M vnk3hDQx4hR1NNSxlL2qF+3KdmF1KYOJIXf02BCUTBpBaqztOJtTkMLiVYSe+jJM1PHG w4j2sw6xoUDS8TntQT6zLbMGPiJLLR2qY958eO4wgrkkzOfNP3IaKcRd2UmEsspVfphd K7Rcw3xaubh48S1IV/bLLzl3xhvjaXQkz8tJPWSNmwPk5dtUqU6lm3YdD3o7xoMl+SSw 13eA== X-Gm-Message-State: AElRT7H5IaGZ95SAV02CwRDbnx5eyLWPRWYnukclWWXj5kVP3dJW/M1t stt0laN8RtF75J5+X2ziDRC1kA== X-Received: by 10.101.87.199 with SMTP id q7mr2242250pgr.215.1520706104617; Sat, 10 Mar 2018 10:21:44 -0800 (PST) Received: from brienza-desktop.8.8.4.4 (andxu.ucsd.edu. [132.239.17.134]) by smtp.gmail.com with ESMTPSA id h80sm9210167pfj.181.2018.03.10.10.21.43 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sat, 10 Mar 2018 10:21:44 -0800 (PST) From: Andiry Xu To: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-nvdimm@lists.01.org Cc: dan.j.williams@intel.com, andy.rudoff@intel.com, coughlan@redhat.com, swanson@cs.ucsd.edu, david@fromorbit.com, jack@suse.com, swhiteho@redhat.com, miklos@szeredi.hu, andiry.xu@gmail.com, Andiry Xu Subject: [RFC v2 73/83] Dax: Add iomap operations. Date: Sat, 10 Mar 2018 10:18:54 -0800 Message-Id: <1520705944-6723-74-git-send-email-jix024@eng.ucsd.edu> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1520705944-6723-1-git-send-email-jix024@eng.ucsd.edu> References: <1520705944-6723-1-git-send-email-jix024@eng.ucsd.edu> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Andiry Xu The key of iomap is dax_get_blocks(). It first takes the read lock and lookup the block; if the block is missing, it takes write lock, check again and allocate the new block if needed. Signed-off-by: Andiry Xu --- fs/nova/dax.c | 184 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ fs/nova/nova.h | 3 + 2 files changed, 187 insertions(+) diff --git a/fs/nova/dax.c b/fs/nova/dax.c index 8624ce4..e639b23 100644 --- a/fs/nova/dax.c +++ b/fs/nova/dax.c @@ -731,3 +731,187 @@ ssize_t nova_inplace_file_write(struct file *filp, return ret; } + +/* + * return > 0, # of blocks mapped or allocated. + * return = 0, if plain lookup failed. + * return < 0, error case. + */ +static int nova_dax_get_blocks(struct inode *inode, sector_t iblock, + unsigned long max_blocks, u32 *bno, bool *new, bool *boundary, + int create) +{ + struct super_block *sb = inode->i_sb; + struct nova_inode *pi; + struct nova_inode_info *si = NOVA_I(inode); + struct nova_inode_info_header *sih = &si->header; + struct nova_file_write_entry *entry = NULL; + struct nova_file_write_item entry_item; + struct list_head item_head; + struct nova_inode_update update; + u32 time; + unsigned long nvmm = 0; + unsigned long blocknr = 0; + u64 epoch_id; + int num_blocks = 0; + int inplace = 0; + int allocated = 0; + int locked = 0; + int check_next; + int ret = 0; + timing_t get_block_time; + + + if (max_blocks == 0) + return 0; + + NOVA_START_TIMING(dax_get_block_t, get_block_time); + INIT_LIST_HEAD(&item_head); + + nova_dbgv("%s: pgoff %lu, num %lu, create %d\n", + __func__, iblock, max_blocks, create); + + epoch_id = nova_get_epoch_id(sb); + + check_next = 0; + sih_lock_shared(sih); + +again: + num_blocks = nova_check_existing_entry(sb, inode, max_blocks, + iblock, &entry, check_next, + epoch_id, &inplace); + + if (entry) { + if (create == 0 || inplace) { + nvmm = get_nvmm(sb, sih, entry, iblock); + nova_dbgv("%s: found pgoff %lu, block %lu\n", + __func__, iblock, nvmm); + goto out; + } + } + + if (create == 0) { + num_blocks = 0; + goto out1; + } + + if (locked == 0) { + sih_unlock_shared(sih); + sih_lock(sih); + locked = 1; + /* Check again incase someone has done it for us */ + check_next = 1; + goto again; + } + + pi = nova_get_inode(sb, inode); + inode->i_ctime = inode->i_mtime = current_time(inode); + time = current_time(inode).tv_sec; + update.tail = sih->log_tail; + + /* Return initialized blocks to the user */ + allocated = nova_new_data_blocks(sb, sih, &blocknr, iblock, + num_blocks, ALLOC_INIT_ZERO, ANY_CPU, + ALLOC_FROM_HEAD); + if (allocated <= 0) { + nova_dbgv("%s alloc blocks failed %d\n", __func__, + allocated); + ret = allocated; + goto out; + } + + num_blocks = allocated; + /* FIXME: how to handle file size? */ + nova_init_file_write_item(sb, sih, &entry_item, + epoch_id, iblock, num_blocks, + blocknr, time, inode->i_size); + + list_add_tail(&entry_item.list, &item_head); + + nvmm = blocknr; + + ret = nova_commit_writes_to_log(sb, pi, inode, + &item_head, num_blocks, 0); + if (ret < 0) { + nova_err(sb, "commit to log failed\n"); + goto out; + } + + NOVA_STATS_ADD(dax_new_blocks, 1); + + *new = true; +// set_buffer_new(bh); +out: + if (ret < 0) { + nova_cleanup_incomplete_write(sb, sih, &item_head, 0); + num_blocks = ret; + goto out1; + } + + *bno = nvmm; +// if (num_blocks > 1) +// bh->b_size = sb->s_blocksize * num_blocks; + +out1: + if (locked) + sih_unlock(sih); + else + sih_unlock_shared(sih); + + NOVA_END_TIMING(dax_get_block_t, get_block_time); + return num_blocks; +} + +static int nova_iomap_begin(struct inode *inode, loff_t offset, loff_t length, + unsigned int flags, struct iomap *iomap) +{ + struct nova_sb_info *sbi = NOVA_SB(inode->i_sb); + unsigned int blkbits = inode->i_blkbits; + unsigned long first_block = offset >> blkbits; + unsigned long max_blocks = (length + (1 << blkbits) - 1) >> blkbits; + bool new = false, boundary = false; + u32 bno; + int ret; + + ret = nova_dax_get_blocks(inode, first_block, max_blocks, &bno, &new, + &boundary, flags & IOMAP_WRITE); + if (ret < 0) { + nova_dbgv("%s: nova_dax_get_blocks failed %d", __func__, ret); + return ret; + } + + iomap->flags = 0; + iomap->bdev = inode->i_sb->s_bdev; + iomap->dax_dev = sbi->s_dax_dev; + iomap->offset = (u64)first_block << blkbits; + + if (ret == 0) { + iomap->type = IOMAP_HOLE; + iomap->addr = IOMAP_NULL_ADDR; + iomap->length = 1 << blkbits; + } else { + iomap->type = IOMAP_MAPPED; + iomap->addr = (u64)bno << blkbits; + iomap->length = (u64)ret << blkbits; + iomap->flags |= IOMAP_F_MERGED; + } + + if (new) + iomap->flags |= IOMAP_F_NEW; + return 0; +} + +static int nova_iomap_end(struct inode *inode, loff_t offset, loff_t length, + ssize_t written, unsigned int flags, struct iomap *iomap) +{ + if (iomap->type == IOMAP_MAPPED && + written < length && + (flags & IOMAP_WRITE)) + truncate_pagecache(inode, inode->i_size); + return 0; +} + +const struct iomap_ops nova_iomap_ops = { + .iomap_begin = nova_iomap_begin, + .iomap_end = nova_iomap_end, +}; diff --git a/fs/nova/nova.h b/fs/nova/nova.h index ab9e8f3..0d62c47 100644 --- a/fs/nova/nova.h +++ b/fs/nova/nova.h @@ -487,6 +487,9 @@ ssize_t nova_inplace_file_write(struct file *filp, const char __user *buf, ssize_t do_nova_inplace_file_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos); +extern const struct iomap_ops nova_iomap_ops; + + /* dir.c */ extern const struct file_operations nova_dir_operations; int nova_insert_dir_radix_tree(struct super_block *sb, -- 2.7.4