From patchwork Thu Oct 24 14:05:21 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 13849281 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id B4793CE8E7A for ; Thu, 24 Oct 2024 14:08:58 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 4EC6C8D0009; Thu, 24 Oct 2024 10:08:58 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 49BCE8D0003; Thu, 24 Oct 2024 10:08:58 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 316508D0009; Thu, 24 Oct 2024 10:08:58 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0017.hostedemail.com [216.40.44.17]) by kanga.kvack.org (Postfix) with ESMTP id 0C3368D0003 for ; Thu, 24 Oct 2024 10:08:58 -0400 (EDT) Received: from smtpin22.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay08.hostedemail.com (Postfix) with ESMTP id 52E6F14137F for ; Thu, 24 Oct 2024 14:08:38 +0000 (UTC) X-FDA: 82708676610.22.A32BD7F Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by imf30.hostedemail.com (Postfix) with ESMTP id E6D7880021 for ; Thu, 24 Oct 2024 14:08:20 +0000 (UTC) Authentication-Results: imf30.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=ZRbHw5+d; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf30.hostedemail.com: domain of dhowells@redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1729778767; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=W7zYjNvXTa+DouJa38s/xpWc0NJHXd1mJpy+zTMcLyQ=; b=A4Sr5Gg5sNE/I/XBA6FONReMnN3CAP/K4flZb4dvpPgva+jLVDU1krDwGzRi98pVhsAlBO YNdpqdrF6pT1osVLCmTI6Sm0qSme9xlpPjD72qCnpD4/8ck+gRoFy0BGSn5GvFld3WLgQB 8YHSS8/kBnmypwZzXJSJvqLADzIFTn0= ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1729778767; a=rsa-sha256; cv=none; b=SpAYKY7IL5fafDJwTEq2XD7m4ysbu33X/qYcMHyj3+KLXCmdIOYBzfl0KIHJZmrdgY7MCE Ie8NiGqB/fm9rUUaCWa5JoSyHHXljrcxyA0qOwdHkDZLoSGSef0v4lcAk9agFM4rkqcv57 iQYorP1xrCdmmT5nEeljHBL/p+SQ+F0= ARC-Authentication-Results: i=1; imf30.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=ZRbHw5+d; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf30.hostedemail.com: domain of dhowells@redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1729778935; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=W7zYjNvXTa+DouJa38s/xpWc0NJHXd1mJpy+zTMcLyQ=; b=ZRbHw5+dnpnZt0MYwN2j6BQSI9TFyJ5VKHKU7FeAX4sTN4bd9+g0ZsTeMMqYpAQcfX3XS9 2zpjeOA4Fz2CGIVyXJB1uA+5HUWe/dOYdzZY188NTTUTnmatJT5MLsLlFic+50+gVwb+yI JYqorSVg9OZSbM4/7+T9DOYhQG8OWcQ= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-499-QLcN7krUM66cKfwR--SXiQ-1; Thu, 24 Oct 2024 10:08:49 -0400 X-MC-Unique: QLcN7krUM66cKfwR--SXiQ-1 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 14CBA19560A6; Thu, 24 Oct 2024 14:08:47 +0000 (UTC) Received: from warthog.procyon.org.uk.com (unknown [10.42.28.231]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 87DCC1956046; Thu, 24 Oct 2024 14:08:41 +0000 (UTC) From: David Howells To: Christian Brauner , Steve French , Matthew Wilcox Cc: David Howells , Jeff Layton , Gao Xiang , Dominique Martinet , Marc Dionne , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Eric Van Hensbergen , Ilya Dryomov , netfs@lists.linux.dev, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, linux-nfs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs@lists.linux.dev, linux-erofs@lists.ozlabs.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 23/27] afs: Use netfslib for symlinks, allowing them to be cached Date: Thu, 24 Oct 2024 15:05:21 +0100 Message-ID: <20241024140539.3828093-24-dhowells@redhat.com> In-Reply-To: <20241024140539.3828093-1-dhowells@redhat.com> References: <20241024140539.3828093-1-dhowells@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 X-Rspamd-Server: rspam07 X-Rspamd-Queue-Id: E6D7880021 X-Stat-Signature: ab7shec3qyjxwgdz9h4r6sg5omchgrji X-Rspam-User: X-HE-Tag: 1729778900-658926 X-HE-Meta: U2FsdGVkX1+u4xKW9kdY/as7GhCDt57WGzX2Y/k4nyMXvwHpLIX8B/hiaY/oPB+95hIduHN0UnI60bgcUHPgYAfUsVXsnul6IrGgXKmSioxoyuCJpQPmiK8j/uW7+WjMg8khX4omyoaFpG012XTbCCnc9JeLW3z5YaZZiO0dPvcwIDtPeMRFmFez4c061d9Z+G8Ooupbnw+yI6HI3q/81SLMnAo4TFSrUa6JFymiz+Yo79pcWgxcUx+5aEQISO7Y+40jOo4Xd7jOT93rRVitnNgvgJnfyvAEfi2METVhf5DBIm9RtP5k0J6hMMSENSBfcyXNH5NgGusxdd3YqXYhGNZGBFUYAGbmSKNpKHmp7FGHO9USKi3+Y78QZni4pae876rtn8FaR3Ut+h8xZmHPCqwD6IzigNwtdNI7DHSM/y/g9jI4ewx7j6gTR8ufTDrrbKR3DY5y07x8kFddz2waObx4JH1OzIq83snuUUO8ttBvLUBJx5FqULkpW31WHTGYooCvzXoArOfbtNWQ+IODW3sq5s/CrqHUaksfklMFBZ9uN6ddeUhbHKKoA9BWEoBfOMWhcbwk72nqIBsFwvCmPhBtsu3ggQh39b2UdtYw7w5Bza2X/9fT7Xpp2Jc8mXopOKcsJe1/3Zp7sHe9GCPEJZ427926H1JtPPquBvIPNXYGA8Kx5oXGjSE0DUrnUAVAaCYBUqtsb/XdceqpXG2+YYxbetwrmUwl8Ax4w7HRfC8ydCBTPU2M2iqnQgJ/ZACPNKJP7faRD78gahTLJ4cDiAFUUW2C/73C4U6Y6yQIWO48WPCz3rd7sLPhqEmrOHVC/Xq07dnWm39pHp0Ajt9RQHvrg4HECtJJUhplySa0Jm04vn7YgawT3gVJ6Mp8IKUmxZWoniaFJaFe7srBh+Cooo2Xs2uh0YGIV7ZD0E+glgu5HrX9cIm+Ezb7ePqzE6pPYFV+9SYXOjo0rwS1sle jjw71LGQ MtNbTGJn5YW9T7MOW2RzH7UnaVSLNODZBtJfCkNENxB83ZsrVIOxUYFMDxsZhcJMPmFZ7xpDpzRIdF9lMpHxlK17gXUToJUIu5dkgVEAFM7Crwu4EnYOoIdXGBz6quf61i633uVSmZjx6R2IBlIOaOli/MQ29byVvkARDs5OX/eTCFPeti4Pr6tm8s1d7SD5KEPja48+EtFa9gvZEzJJ19VJe/nMGG00aJOTdpow9266we3ZANPb5m21cIoqk79PP+af/r3m3HeLkQlgYIwlOgN5gEJll4PSn1P+DThvZy6p4cvokRyuB2sHF+Im1gTXDLZDA3aPHxyX/FbhDRtes2NlJf2usf3LGfeU9XX2tTkPefooiwE3T6qhYT3xWfE7pGoSAPfTiT3VjyNdO7bUsOHjGnPwrmLjalwEcoGiNC3T3Z65LSkB/PtHhIkuEKN8YhvuXD0HQeTtHQ/6x0/7n4FwZ3Q== X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Use netfslib to read symlinks, thereby allowing them to be cached by fscache and cachefiles. Signed-off-by: David Howells cc: Marc Dionne cc: Jeff Layton cc: linux-afs@lists.infradead.org cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/afs/file.c | 32 -------------------- fs/afs/inode.c | 62 +++++++++++++++++++++++++++++++++++--- fs/afs/internal.h | 4 ++- fs/afs/mntpt.c | 22 +++++++------- include/trace/events/afs.h | 1 + 5 files changed, 72 insertions(+), 49 deletions(-) diff --git a/fs/afs/file.c b/fs/afs/file.c index 5bc36bfaa173..48695a50d2f9 100644 --- a/fs/afs/file.c +++ b/fs/afs/file.c @@ -20,7 +20,6 @@ #include "internal.h" static int afs_file_mmap(struct file *file, struct vm_area_struct *vma); -static int afs_symlink_read_folio(struct file *file, struct folio *folio); static ssize_t afs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter); static ssize_t afs_file_splice_read(struct file *in, loff_t *ppos, @@ -61,13 +60,6 @@ const struct address_space_operations afs_file_aops = { .writepages = afs_writepages, }; -const struct address_space_operations afs_symlink_aops = { - .read_folio = afs_symlink_read_folio, - .release_folio = netfs_release_folio, - .invalidate_folio = netfs_invalidate_folio, - .migrate_folio = filemap_migrate_folio, -}; - static const struct vm_operations_struct afs_vm_ops = { .open = afs_vm_open, .close = afs_vm_close, @@ -346,30 +338,6 @@ static void afs_issue_read(struct netfs_io_subrequest *subreq) queue_work(system_long_wq, &subreq->work); } -static int afs_symlink_read_folio(struct file *file, struct folio *folio) -{ - struct afs_vnode *vnode = AFS_FS_I(folio->mapping->host); - struct afs_read *fsreq; - int ret; - - fsreq = afs_alloc_read(GFP_NOFS); - if (!fsreq) - return -ENOMEM; - - fsreq->pos = folio_pos(folio); - fsreq->len = folio_size(folio); - fsreq->vnode = vnode; - fsreq->iter = &fsreq->def_iter; - iov_iter_xarray(&fsreq->def_iter, ITER_DEST, &folio->mapping->i_pages, - fsreq->pos, fsreq->len); - - ret = afs_fetch_data(fsreq->vnode, fsreq); - if (ret == 0) - folio_mark_uptodate(folio); - folio_unlock(folio); - return ret; -} - static int afs_init_request(struct netfs_io_request *rreq, struct file *file) { struct afs_vnode *vnode = AFS_FS_I(rreq->inode); diff --git a/fs/afs/inode.c b/fs/afs/inode.c index 0ed1e5c35fef..8c7aa759ad1b 100644 --- a/fs/afs/inode.c +++ b/fs/afs/inode.c @@ -25,8 +25,58 @@ #include "internal.h" #include "afs_fs.h" +static void afs_put_link(void *arg) +{ + struct folio *folio = virt_to_folio(arg); + + kunmap_local(arg); + folio_put(folio); +} + +const char *afs_get_link(struct dentry *dentry, struct inode *inode, + struct delayed_call *callback) +{ + struct afs_vnode *vnode = AFS_FS_I(inode); + struct folio *folio; + char *content; + ssize_t ret; + + if (atomic64_read(&vnode->cb_expires_at) == AFS_NO_CB_PROMISE || + !vnode->directory) { + ret = afs_read_single(vnode, NULL); + if (ret < 0) + return ERR_PTR(ret); + } + + folio = folioq_folio(vnode->directory, 0); + folio_get(folio); + content = kmap_local_folio(folio, 0); + set_delayed_call(callback, afs_put_link, content); + return content; +} + +int afs_readlink(struct dentry *dentry, char __user *buffer, int buflen) +{ + DEFINE_DELAYED_CALL(done); + const char *content; + int len; + + content = afs_get_link(dentry, d_inode(dentry), &done); + if (IS_ERR(content)) { + do_delayed_call(&done); + return PTR_ERR(content); + } + + len = umin(strlen(content), buflen); + if (copy_to_user(buffer, content, len)) + len = -EFAULT; + do_delayed_call(&done); + return len; +} + static const struct inode_operations afs_symlink_inode_operations = { - .get_link = page_get_link, + .get_link = afs_get_link, + .readlink = afs_readlink, }; static noinline void dump_vnode(struct afs_vnode *vnode, struct afs_vnode *parent_vnode) @@ -124,13 +174,13 @@ static int afs_inode_init_from_status(struct afs_operation *op, inode->i_mode = S_IFDIR | 0555; inode->i_op = &afs_mntpt_inode_operations; inode->i_fop = &afs_mntpt_file_operations; - inode->i_mapping->a_ops = &afs_symlink_aops; } else { inode->i_mode = S_IFLNK | status->mode; inode->i_op = &afs_symlink_inode_operations; - inode->i_mapping->a_ops = &afs_symlink_aops; } + inode->i_mapping->a_ops = &afs_dir_aops; inode_nohighmem(inode); + mapping_set_release_always(inode->i_mapping); break; default: dump_vnode(vnode, op->file[0].vnode != vnode ? op->file[0].vnode : NULL); @@ -443,7 +493,8 @@ static void afs_get_inode_cache(struct afs_vnode *vnode) struct afs_vnode_cache_aux aux; if (vnode->status.type != AFS_FTYPE_FILE && - vnode->status.type != AFS_FTYPE_DIR) { + vnode->status.type != AFS_FTYPE_DIR && + vnode->status.type != AFS_FTYPE_SYMLINK) { vnode->netfs.cache = NULL; return; } @@ -657,7 +708,8 @@ void afs_evict_inode(struct inode *inode) ASSERTCMP(inode->i_ino, ==, vnode->fid.vnode); - if ((S_ISDIR(inode->i_mode)) && + if ((S_ISDIR(inode->i_mode) || + S_ISLNK(inode->i_mode)) && (inode->i_state & I_DIRTY) && !sbi->dyn_root) { struct writeback_control wbc = { diff --git a/fs/afs/internal.h b/fs/afs/internal.h index ecf5df9ca12c..6fa3b1dd4c98 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h @@ -1115,7 +1115,6 @@ extern void afs_dynroot_depopulate(struct super_block *); * file.c */ extern const struct address_space_operations afs_file_aops; -extern const struct address_space_operations afs_symlink_aops; extern const struct inode_operations afs_file_inode_operations; extern const struct file_operations afs_file_operations; extern const struct netfs_request_ops afs_req_ops; @@ -1221,6 +1220,9 @@ extern void afs_fs_probe_cleanup(struct afs_net *); */ extern const struct afs_operation_ops afs_fetch_status_operation; +const char *afs_get_link(struct dentry *dentry, struct inode *inode, + struct delayed_call *callback); +int afs_readlink(struct dentry *dentry, char __user *buffer, int buflen); extern void afs_vnode_commit_status(struct afs_operation *, struct afs_vnode_param *); extern int afs_fetch_status(struct afs_vnode *, struct key *, bool, afs_access_t *); extern int afs_ilookup5_test_by_fid(struct inode *, void *); diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c index 297487ee8323..507c25a5b2cb 100644 --- a/fs/afs/mntpt.c +++ b/fs/afs/mntpt.c @@ -30,7 +30,7 @@ const struct file_operations afs_mntpt_file_operations = { const struct inode_operations afs_mntpt_inode_operations = { .lookup = afs_mntpt_lookup, - .readlink = page_readlink, + .readlink = afs_readlink, .getattr = afs_getattr, }; @@ -118,9 +118,9 @@ static int afs_mntpt_set_params(struct fs_context *fc, struct dentry *mntpt) ctx->volnamesz = sizeof(afs_root_volume) - 1; } else { /* read the contents of the AFS special symlink */ - struct page *page; + DEFINE_DELAYED_CALL(cleanup); + const char *content; loff_t size = i_size_read(d_inode(mntpt)); - char *buf; if (src_as->cell) ctx->cell = afs_use_cell(src_as->cell, afs_cell_trace_use_mntpt); @@ -128,16 +128,16 @@ static int afs_mntpt_set_params(struct fs_context *fc, struct dentry *mntpt) if (size < 2 || size > PAGE_SIZE - 1) return -EINVAL; - page = read_mapping_page(d_inode(mntpt)->i_mapping, 0, NULL); - if (IS_ERR(page)) - return PTR_ERR(page); + content = afs_get_link(mntpt, d_inode(mntpt), &cleanup); + if (IS_ERR(content)) { + do_delayed_call(&cleanup); + return PTR_ERR(content); + } - buf = kmap(page); ret = -EINVAL; - if (buf[size - 1] == '.') - ret = vfs_parse_fs_string(fc, "source", buf, size - 1); - kunmap(page); - put_page(page); + if (content[size - 1] == '.') + ret = vfs_parse_fs_string(fc, "source", content, size - 1); + do_delayed_call(&cleanup); if (ret < 0) return ret; diff --git a/include/trace/events/afs.h b/include/trace/events/afs.h index d05f2c09efe3..49a749672e38 100644 --- a/include/trace/events/afs.h +++ b/include/trace/events/afs.h @@ -422,6 +422,7 @@ enum yfs_cm_operation { EM(afs_file_error_dir_over_end, "DIR_ENT_OVER_END") \ EM(afs_file_error_dir_small, "DIR_SMALL") \ EM(afs_file_error_dir_unmarked_ext, "DIR_UNMARKED_EXT") \ + EM(afs_file_error_symlink_big, "SYM_BIG") \ EM(afs_file_error_mntpt, "MNTPT_READ_FAILED") \ E_(afs_file_error_writeback_fail, "WRITEBACK_FAILED")