Received: by 10.223.185.111 with SMTP id b44csp1645261wrg; Sat, 10 Mar 2018 10:29:07 -0800 (PST) X-Google-Smtp-Source: AG47ELuI8Q/5ExR1HUI/++Cbn6avf8WrU7Ln8OZU3ig2qNwQL44z7xLN6zm0v1TIOHuq4IwRU1u1 X-Received: by 10.99.3.210 with SMTP id 201mr1328452pgd.5.1520706547810; Sat, 10 Mar 2018 10:29:07 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1520706547; cv=none; d=google.com; s=arc-20160816; b=EVagfjgCWyQVbqv2DIn9Z/3D+oSqkEKvhdfFfYcZjucNwTIHXGFGFIlYv0YJmywZ+j lqR8b2R55EvQ25PhLhnZK5ixTthxMEDWTz96Krtrn3FuwBsq7OKjdwcmTkURJ8wgL5CM lHKzjln/5KeGKO6WcYvg2+kMUHnFNYbQuZXCl7nfo1hCmes6vVa3KCGWCal0yNXg6fwP TuE9v+lhVFeGecUn+nAdMkjx72yCafLege3Tznjj0EOELi+fCuoOKw0I7v8tM2qJPnGk tK25wottDSzhCK3Rr8/ZoYjXAXfT7F4amf4GztvCva9I9EyC11JCGgNaYYEW0R3sha5h Dj4Q== 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=jdhnp9SqZ18A8ybHFznpxQf1J4S+yTe0HFUn4fSTNh4=; b=XiUftVFDo2G+asaBAOOIp4WUGkFPsVCZAmG0KIsw0lbQwpW+YWMxUSXHLwuIbVGp8D OfnpWudB0BoDenBY8r7dbb/9QmF75X0RXdKC1/qZ4hhzEcQp0Ciws/eA+rcH31H4D2dc WHKRbti5wd30ILNQQnF6qG5JSWp+MK/cv3qOWyVAObQRW5DufmLI18ZUUI1LabBpCVtC i/Yn1yUm1zAVYq2tuYvxA5r4olkbSW0v7Vl9xCvjQhw9sQLHyje23A212nzSNiOJYqEs 9BSeSjZbYe7T8PsQiGLlUpTjKOD3zMdntb14aiAxsHOtDKDLng86RtGqwes8vJOGnZ3m uGsg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@eng.ucsd.edu header.s=google header.b=VyY9TmV9; 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 e18si2576641pgv.684.2018.03.10.10.28.52; Sat, 10 Mar 2018 10:29:07 -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=VyY9TmV9; 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 S932847AbeCJSVi (ORCPT + 99 others); Sat, 10 Mar 2018 13:21:38 -0500 Received: from mail-pf0-f196.google.com ([209.85.192.196]:40023 "EHLO mail-pf0-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932670AbeCJSVf (ORCPT ); Sat, 10 Mar 2018 13:21:35 -0500 Received: by mail-pf0-f196.google.com with SMTP id x1so2617889pfh.7 for ; Sat, 10 Mar 2018 10:21:35 -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=jdhnp9SqZ18A8ybHFznpxQf1J4S+yTe0HFUn4fSTNh4=; b=VyY9TmV98sHPEFCb8y0mv3hLjaFimpQ69E7kNB7h0PJnPe3yqRWcWR99O5O0cF7E5r DIfgqHxNaowsll8SFZ/SkU62LviP8KDi+vlWRsMSlPUYUyShdZpwX1rB1ULOgVRbcgVP oz6nGM3TaWkJpDFmjzCSQNyPWiF4N3kvwJMoU= 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=jdhnp9SqZ18A8ybHFznpxQf1J4S+yTe0HFUn4fSTNh4=; b=F8bDOXE4rG6nZTtRw5wyzPX0JenVJ41k7755TuJjgybmXVmhYmR8cLlJYAHiw0EBie xr4JoWkS9msNvgU9yDC5sv/z1/2ZHT3BOiirjeKgjIx/u3xOUus/C6cMHzRk9WW1hDCF xgQvWltJDSqmJjoJ1x6fvw4OK6n6ArjWnhzghotz4IdKys/JDmQxrP7pt8Fb/DSfrk9U jY1iYP3dbykKHFhFnskUjAli31v/dZ2ep2E1zdnL9JZW0PuPZ11nclatAjue5Ri1O95N KrsTQYRrwX+R2535Js9zP9Zzdmuksw2YWgiYE880fLxtRyfoYJ57AkZ9euwJ4yKjSav+ Y9TA== X-Gm-Message-State: AElRT7HcM0zNid6nlxH7ASiXvHd0SuFxF4pBAAzbDhiTinlDzi2kwK7+ BuHFBRfrKRQ4WMhuyw4KqHmGgw== X-Received: by 10.99.126.84 with SMTP id o20mr2220181pgn.188.1520706094722; Sat, 10 Mar 2018 10:21:34 -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.33 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sat, 10 Mar 2018 10:21:34 -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 65/83] File operation: read. Date: Sat, 10 Mar 2018 10:18:46 -0800 Message-Id: <1520705944-6723-66-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 NOVA is a DAX file system and does not use page cache. For read, NOVA looks up the file write entry by searching the radix tree, and copies data from pmem pages to user buffer directly. Signed-off-by: Andiry Xu --- fs/nova/file.c | 144 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) diff --git a/fs/nova/file.c b/fs/nova/file.c index f60fdf3..842da45 100644 --- a/fs/nova/file.c +++ b/fs/nova/file.c @@ -113,9 +113,153 @@ static int nova_open(struct inode *inode, struct file *filp) return generic_file_open(inode, filp); } +static ssize_t +do_dax_mapping_read(struct file *filp, char __user *buf, + size_t len, loff_t *ppos) +{ + struct inode *inode = filp->f_mapping->host; + struct super_block *sb = inode->i_sb; + struct nova_inode_info *si = NOVA_I(inode); + struct nova_inode_info_header *sih = &si->header; + struct nova_file_write_entry *entry; + pgoff_t index, end_index; + unsigned long offset; + loff_t isize, pos; + size_t copied = 0, error = 0; + timing_t memcpy_time; + + pos = *ppos; + index = pos >> PAGE_SHIFT; + offset = pos & ~PAGE_MASK; + + if (!access_ok(VERIFY_WRITE, buf, len)) { + error = -EFAULT; + goto out; + } + + isize = i_size_read(inode); + if (!isize) + goto out; + + nova_dbgv("%s: inode %lu, offset %lld, count %lu, size %lld\n", + __func__, inode->i_ino, pos, len, isize); + + if (len > isize - pos) + len = isize - pos; + + if (len <= 0) + goto out; + + end_index = (isize - 1) >> PAGE_SHIFT; + do { + unsigned long nr, left; + unsigned long nvmm; + void *dax_mem = NULL; + int zero = 0; + + /* nr is the maximum number of bytes to copy from this page */ + if (index >= end_index) { + if (index > end_index) + goto out; + nr = ((isize - 1) & ~PAGE_MASK) + 1; + if (nr <= offset) + goto out; + } + + entry = nova_get_write_entry(sb, sih, index); + if (unlikely(entry == NULL)) { + nova_dbgv("Required extent not found: pgoff %lu, inode size %lld\n", + index, isize); + nr = PAGE_SIZE; + zero = 1; + goto memcpy; + } + + /* Find contiguous blocks */ + if (index < entry->pgoff || + index - entry->pgoff >= entry->num_pages) { + nova_err(sb, "%s ERROR: %lu, entry pgoff %llu, num %u, blocknr %llu\n", + __func__, index, entry->pgoff, + entry->num_pages, entry->block >> PAGE_SHIFT); + return -EINVAL; + } + if (entry->reassigned == 0) { + nr = (entry->num_pages - (index - entry->pgoff)) + * PAGE_SIZE; + } else { + nr = PAGE_SIZE; + } + + nvmm = get_nvmm(sb, sih, entry, index); + dax_mem = nova_get_block(sb, (nvmm << PAGE_SHIFT)); + +memcpy: + nr = nr - offset; + if (nr > len - copied) + nr = len - copied; + + NOVA_START_TIMING(memcpy_r_nvmm_t, memcpy_time); + + if (!zero) + left = __copy_to_user(buf + copied, + dax_mem + offset, nr); + else + left = __clear_user(buf + copied, nr); + + NOVA_END_TIMING(memcpy_r_nvmm_t, memcpy_time); + + if (left) { + nova_dbg("%s ERROR!: bytes %lu, left %lu\n", + __func__, nr, left); + error = -EFAULT; + goto out; + } + + copied += (nr - left); + offset += (nr - left); + index += offset >> PAGE_SHIFT; + offset &= ~PAGE_MASK; + } while (copied < len); + +out: + *ppos = pos + copied; + if (filp) + file_accessed(filp); + + NOVA_STATS_ADD(read_bytes, copied); + + nova_dbgv("%s returned %zu\n", __func__, copied); + return copied ? copied : error; +} + +/* + * Wrappers. We need to use the read lock to avoid + * concurrent truncate operation. No problem for write because we held + * lock. + */ +static ssize_t nova_dax_file_read(struct file *filp, char __user *buf, + size_t len, loff_t *ppos) +{ + struct inode *inode = filp->f_mapping->host; + struct nova_inode_info *si = NOVA_I(inode); + struct nova_inode_info_header *sih = &si->header; + ssize_t res; + timing_t dax_read_time; + + NOVA_START_TIMING(dax_read_t, dax_read_time); + inode_lock_shared(inode); + sih_lock_shared(sih); + res = do_dax_mapping_read(filp, buf, len, ppos); + sih_unlock_shared(sih); + inode_unlock_shared(inode); + NOVA_END_TIMING(dax_read_t, dax_read_time); + return res; +} + const struct file_operations nova_dax_file_operations = { .llseek = nova_llseek, + .read = nova_dax_file_read, .open = nova_open, .fsync = nova_fsync, .flush = nova_flush, -- 2.7.4