Received: by 2002:ac0:a5a6:0:0:0:0:0 with SMTP id m35-v6csp2061934imm; Thu, 27 Sep 2018 06:53:46 -0700 (PDT) X-Google-Smtp-Source: ACcGV63TqpffQcRahQ5OxMwRqix73p+nj8D3n4VGhA7WjSN6smaPYoPFxn0cyD7Vlr7PHEOnavh1 X-Received: by 2002:a17:902:b7c2:: with SMTP id v2-v6mr11303909plz.238.1538056426418; Thu, 27 Sep 2018 06:53:46 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1538056426; cv=none; d=google.com; s=arc-20160816; b=YvgjA5pHsHvfPw0YZmFC5r97W5U976sG4zVSQei7ov00l5b//gVkqXYYXin7O7p5qQ GreEQHw91s856x0JhFx8r/AQq8fXHiKKP7C8SdqTuFk4sae7vZfzoLer7rmiN6vTzia2 M7fCDqjyMkxguGw8wVTji2bEIGoUWMyMxa3xpUcE79+awDLIrK4BQ5R5bQdUvQrT+KtZ qOILfODt9sEGT3uh3/ZmszJx/AztuP+wtzbfAlYb2ukkpEgsaOqOT67TtMZlCo0wPm75 7Hu8LRpxlHAUdaf6oD/EV6LaGwf9PJhuFgPoVS+6zBCJzB2A6BcpMzEMaZR1rSjeluV+ th4w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:message-id:date:subject :smtp-origin-cluster:cc:to:smtp-origin-hostname:from :smtp-origin-hostprefix:dkim-signature; bh=Yvo0Hdwf7rOZj7He1kTlcXIGqnc0dhTbCmnkInG2boY=; b=p1GXwHf+wfCnTxKPLratWrgIwMFOIPk05ZEBSnnC/VHK/T+RRuIATKppj3R2iU7m8q iUDkZ+sbOrsFu5xRx3KeeZHPwKSCT8Vfg4Vtwmq1tQWANpfHrJYnYn+aAox9QV5NeJHD XKLbI2Yp66A5mrJnzd6AXAitx1UEgWiTC4zQvuDMyxsmccfuSeX0/eKXECZmrafIVvGz mgDlGJ0EJ6Lc4SFQn61wOqxK1ajR+RdufhsJREEf3DAq7U4mLHLfC1Xo0AfRa7d+Xn1c tCDS3YYqnD/8srEZS5xJKJ6MovUpYxlde9R8D5Ks+BM5EyjZGd7dYtuYTFO3IR7AMWb2 3pvA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@fb.com header.s=facebook header.b=mrRBUhg2; 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; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=fb.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id x3-v6si1839891plr.80.2018.09.27.06.53.30; Thu, 27 Sep 2018 06:53:46 -0700 (PDT) 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=@fb.com header.s=facebook header.b=mrRBUhg2; 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; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=fb.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727603AbeI0ULE (ORCPT + 99 others); Thu, 27 Sep 2018 16:11:04 -0400 Received: from mx0b-00082601.pphosted.com ([67.231.153.30]:59760 "EHLO mx0a-00082601.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1727270AbeI0ULD (ORCPT ); Thu, 27 Sep 2018 16:11:03 -0400 Received: from pps.filterd (m0089730.ppops.net [127.0.0.1]) by m0089730.ppops.net (8.16.0.22/8.16.0.22) with SMTP id w8RDiA5l018927 for ; Thu, 27 Sep 2018 06:52:40 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=fb.com; h=from : to : cc : subject : date : message-id : mime-version : content-type; s=facebook; bh=Yvo0Hdwf7rOZj7He1kTlcXIGqnc0dhTbCmnkInG2boY=; b=mrRBUhg2RSA7a7XcIrz/L2TEPtBkhhCBC6wbYjZDHzBA3uVRSxsf/KATg84TWweTZQzP eX1eKnacdxmx+nAr02ddkWYfEjHycrMsWjnDR9NUOzWORIxAnoWIAb+SoaNGeAXPuWfZ MmJv8lW15fC4zs5d0HcglYy9JLxKgY4+2qg= Received: from mail.thefacebook.com ([199.201.64.23]) by m0089730.ppops.net with ESMTP id 2mry1qr9fq-3 (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NOT) for ; Thu, 27 Sep 2018 06:52:40 -0700 Received: from mx-out.facebook.com (192.168.52.123) by mail.thefacebook.com (192.168.16.13) with Microsoft SMTP Server (TLS) id 14.3.361.1; Thu, 27 Sep 2018 06:52:38 -0700 Received: by devvm1658.frc1.facebook.com (Postfix, from userid 119756) id 5F46B10F94A0; Thu, 27 Sep 2018 06:52:30 -0700 (PDT) Smtp-Origin-Hostprefix: devvm From: Dan Schatzberg Smtp-Origin-Hostname: devvm1658.frc1.facebook.com To: Miklos Szeredi CC: , , Dan Schatzberg , , Smtp-Origin-Cluster: frc1c23 Subject: [PATCH] fuse: enable caching of symlinks Date: Thu, 27 Sep 2018 06:52:10 -0700 Message-ID: <20180927135211.31641-1-dschatzberg@fb.com> X-Mailer: git-send-email 2.17.1 X-FB-Internal: Safe MIME-Version: 1.0 Content-Type: text/plain X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:,, definitions=2018-09-27_07:,, signatures=0 X-Proofpoint-Spam-Reason: safe X-FB-Internal: Safe Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org FUSE file reads are cached in the page cache, but symlink reads are not. This patch enables FUSE READLINK operations to be cached which can improve performance of some FUSE workloads. In particular, I'm working on a FUSE filesystem for access to source code and discovered that about a 10% improvement to build times is achieved with this patch (there are a lot of symlinks in the source tree). Please provide feedback, I'm looking to flesh this out more. Signed-off-by: Dan Schatzberg --- fs/fuse/dir.c | 70 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 43 insertions(+), 27 deletions(-) diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 0979609d6eba..3c0a81ef5bca 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -1398,38 +1398,46 @@ static int fuse_readdir(struct file *file, struct dir_context *ctx) return err; } -static const char *fuse_get_link(struct dentry *dentry, - struct inode *inode, - struct delayed_call *done) +static int fuse_symlink_readpage(struct file *file, struct page *page) { + struct inode *inode = page->mapping->host; struct fuse_conn *fc = get_fuse_conn(inode); - FUSE_ARGS(args); - char *link; - ssize_t ret; - - if (!dentry) - return ERR_PTR(-ECHILD); + struct fuse_req *req; + int err; + size_t num_read; - link = kmalloc(PAGE_SIZE, GFP_KERNEL); - if (!link) - return ERR_PTR(-ENOMEM); + err = -EIO; + if (is_bad_inode(inode)) + goto out; - args.in.h.opcode = FUSE_READLINK; - args.in.h.nodeid = get_node_id(inode); - args.out.argvar = 1; - args.out.numargs = 1; - args.out.args[0].size = PAGE_SIZE - 1; - args.out.args[0].value = link; - ret = fuse_simple_request(fc, &args); - if (ret < 0) { - kfree(link); - link = ERR_PTR(ret); - } else { - link[ret] = '\0'; - set_delayed_call(done, kfree_link, link); + req = fuse_get_req(fc, 1); + if (IS_ERR(req)) { + err = PTR_ERR(req); + goto out; } + + req->out.page_zeroing = 1; + req->out.argpages = 1; + req->num_pages = 1; + req->pages[0] = page; + req->page_descs[0].length = PAGE_SIZE - 1; + req->in.h.opcode = FUSE_READLINK; + req->in.h.nodeid = get_node_id(inode); + req->out.argvar = 1; + req->out.numargs = 1; + req->out.args[0].size = PAGE_SIZE - 1; + fuse_request_send(fc, req); + num_read = req->out.args[0].size; + err = req->out.h.error; + + if (!err) + SetPageUptodate(page); + + fuse_put_request(fc, req); fuse_invalidate_atime(inode); - return link; +out: + unlock_page(page); + return err; } static int fuse_dir_open(struct inode *inode, struct file *file) @@ -1855,7 +1863,7 @@ static const struct inode_operations fuse_common_inode_operations = { static const struct inode_operations fuse_symlink_inode_operations = { .setattr = fuse_setattr, - .get_link = fuse_get_link, + .get_link = page_get_link, .getattr = fuse_getattr, .listxattr = fuse_listxattr, }; @@ -1871,7 +1879,15 @@ void fuse_init_dir(struct inode *inode) inode->i_fop = &fuse_dir_operations; } +static const struct address_space_operations fuse_symlink_aops = { + .readpage = fuse_symlink_readpage, +}; + void fuse_init_symlink(struct inode *inode) { inode->i_op = &fuse_symlink_inode_operations; + inode->i_data.a_ops = &fuse_symlink_aops; + mapping_set_gfp_mask(inode->i_mapping, + mapping_gfp_constraint(inode->i_mapping, + ~(__GFP_FS | __GFP_HIGHMEM))); } -- 2.17.1