Received: by 2002:ac0:a5a6:0:0:0:0:0 with SMTP id m35-v6csp2069213imm; Thu, 27 Sep 2018 07:00:47 -0700 (PDT) X-Google-Smtp-Source: ACcGV63roYWgegHe8h/ltZQqiYDqW3cOH7RAIJSW2nBihtjfg4zfwjqwL69Ug1D9livu/yW+TUD4 X-Received: by 2002:a63:6c89:: with SMTP id h131-v6mr10323491pgc.237.1538056847036; Thu, 27 Sep 2018 07:00:47 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1538056847; cv=none; d=google.com; s=arc-20160816; b=JtHdzrPi/L73RXOmbthM+7tcHEB0B8ojXCyH6/d1Oso4ydbN1cCpKB9SfvTiOXvsRz /7At8ZDp/TT/THPbdsR4FfvIckH9ZU3Jaxz3wRviRbvWeEWHhwbtt+ru/2BF5iNFz0Ys 0yrgj3EKPMnsJfckBdlvCnglnkVLUo5z6Phv1LzNPcV8tD4ZkPnYZn+G2EztCLIuaMx0 4HLJ69Vk64lQGr8WhCYQUesEhogNk0AZVo+CTuH2E4IYguh9QPY06HHJqL3mxLiPKVTJ FSyToCYazCkFEeCBnn3fXdYGdl/2hfpD213Aylyq0OZzFsXiBSMCkiCd8OtpGxaGe70c b6hA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:cc:to:subject:message-id:date:from :references:in-reply-to:mime-version:dkim-signature; bh=gvpP0lbBoycAsX+Pfl/y1ATalMn2lcO+jpRaS6p3u+A=; b=Vx7lNzmNqk7LAi77dpQV6hEU5AIvLEjuu3t8jtAsfmQCaLI7e9+awBK58DHBJjoJAp ary4tNAElE2OvNYAq5qKygCioh7ePC6L6wGr4mVTugtmwaK+FsjS7qu+28JGeXDnh5A+ gyZEcdFMYEt+gmJAouICvKFy9DvQBF13ZJddzUK5XOzzYaX6/P/34qqPi8I8SPSlLcXf KILJkB380MYrrfBxijcQuWhCTZdBfZuyXg+gZeq/hZ6xP9osz072qQpFgg7T4A6ffEV0 wm6Nk033ccH7UGpD0DVEC5upk106AMHwybnsZKdZ5I1vKNBpvk9BQ9oThu/rTTvV8s2p oSOw== ARC-Authentication-Results: i=1; mx.google.com; dkim=temperror (no key for signature) header.i=@szeredi.hu header.s=google header.b=nQC0llW3; 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 o67-v6si2074552pga.597.2018.09.27.07.00.29; Thu, 27 Sep 2018 07:00:47 -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=temperror (no key for signature) header.i=@szeredi.hu header.s=google header.b=nQC0llW3; 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 S1727335AbeI0URV (ORCPT + 99 others); Thu, 27 Sep 2018 16:17:21 -0400 Received: from mail-io1-f65.google.com ([209.85.166.65]:45476 "EHLO mail-io1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727175AbeI0URU (ORCPT ); Thu, 27 Sep 2018 16:17:20 -0400 Received: by mail-io1-f65.google.com with SMTP id e12-v6so1976969iok.12 for ; Thu, 27 Sep 2018 06:58:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=szeredi.hu; s=google; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=gvpP0lbBoycAsX+Pfl/y1ATalMn2lcO+jpRaS6p3u+A=; b=nQC0llW3yeNprNQPhdObv+8RUx0BE8yaTRAT+rCh19EeQJr8PUahDaeqd1UigJNBHM 2RNKM2LU0PgS5XcLPeYbS+xAqnA2+PBZRHT1AEQNM3rLsD1l3btuVimbkGy+MQ0h/gvy dJdYn1BRDjHzL/TBg8K0aY7ZGkpyyWiRYLPTI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=gvpP0lbBoycAsX+Pfl/y1ATalMn2lcO+jpRaS6p3u+A=; b=QerWZeKWX3lRsf8DxTOFbPSpuocZQRINIuxm9MtbaGnsTsKcV0+Md9J6DR3YDkUdHq 2i/mGHaIoZLWgx6JjCZmd9oY+QXkpdM8Bxqw6JqTTtRzQDLEZAE17spnxj/Oi7fl+7t9 s8sV1E2N7cDSDDfqtfz5NqGSUl5WEtO+lD/pTSzgSgohlToFQrSb9oNfTZ6xh14ZqvQc L227gktLz+3FHzQCccFmVK44efBuL4GCqb0Cu4H/qJWB9HnuAd9LxwMYsrdeplGKakPn ziUDgPXQc9dZ4cPqQYMWc/i5Zg8Bsq5qgGEZMXZC5LRN/59Yvi8OwzBaF1XRYblz4iD2 OTbQ== X-Gm-Message-State: ABuFfoiwpcsiGYfQj5XxdoekJH2yFzkrm0aabn35GcgRC3lDSfFYIpBR 5kiwtzrQq+DywF7+jKQMs+hTtXNIv0eS41JftX+F2A== X-Received: by 2002:a6b:acc4:: with SMTP id v187-v6mr8855692ioe.246.1538056736208; Thu, 27 Sep 2018 06:58:56 -0700 (PDT) MIME-Version: 1.0 Received: by 2002:a6b:bf41:0:0:0:0:0 with HTTP; Thu, 27 Sep 2018 06:58:55 -0700 (PDT) X-Originating-IP: [212.96.48.140] In-Reply-To: <20180927135211.31641-1-dschatzberg@fb.com> References: <20180927135211.31641-1-dschatzberg@fb.com> From: Miklos Szeredi Date: Thu, 27 Sep 2018 15:58:55 +0200 Message-ID: Subject: Re: [PATCH] fuse: enable caching of symlinks To: Dan Schatzberg Cc: Tejun Heo , kernel-team , linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Content-Type: text/plain; charset="UTF-8" Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Thu, Sep 27, 2018 at 3:52 PM, Dan Schatzberg wrote: > 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. Need to think about how/when to invalidate the cached symlink contents. I think treating it like metadata (i.e. look at attr_timeout for validity) would be the simplest. Thanks, Miklos > > 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 >