Received: by 2002:a05:6a10:413:0:0:0:0 with SMTP id 19csp956546pxp; Wed, 16 Mar 2022 22:35:29 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwhyLZDceJuBJPQS0iERY3DA/lc4evinW7XdBtYv3pAIZMD1lq+ac5QMS9fKlZkyp7y3GgD X-Received: by 2002:a17:902:f605:b0:14d:9e11:c864 with SMTP id n5-20020a170902f60500b0014d9e11c864mr3099276plg.54.1647495329222; Wed, 16 Mar 2022 22:35:29 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1647495329; cv=none; d=google.com; s=arc-20160816; b=ouTmI81ZC0oymTNIijfSvnBGvHXH3egu3d3KI+FSgeUTpayh3yw7gMeBalwO+l6U/i XkstPunuwuLFfmcw71OjtXIrRNFeO1f/nm5Azp8WXaDrGbzc3VVNT5lWfqdenDiNr2J9 N2BzrDj333Gs02rlhRcCOBZ3IUXa2nGi3jjrtGye0R+e5STRIG+UtGYzYmxUTNXYoRxr t0EE5VbqliP2UKzpcqBYaTZl/n79phffbjKflXAvY3DbeMExiRd+dJaC1IOGFRvLoNwI Xe7Zp2axG1meUE/TUYVW2YeVYyGdaSeXcqdMUePYqDP/i8SLglpbghJIAmbxtbRWOghJ HKGg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=ZbLiCgpFz73G5LP8BHOv8GIivW/zWGvOX46AnFZW95U=; b=Ak+VQ0z6DaDMAIEwB33iEXkJk+tVgPMoaLb6CrJuIbmWqQ55F7AHEsIfKEP6ZPDguc dV6BG97G8ctx57wCUCcrfmHhYRc4IeE5/afyXG20casLg3jonJi68Zw0HxLEbkBxxxN/ d7Wfj/iqZKxdRtkUxKJ7yqIQzLHpi+6Jz72jKuX2ZEme2SjxqHD3RZT+QzMyJLTCi4RX py231w42YcH4sjUjhRVJi3UNq1Es5xA4+iDlCF5l4kdmuEKqJEFEwz29gSQuJaGNKsdf eTIh0RK78hHdVnMoa5oY7B1Dq++lTsk0lkKKmFVgh54fYf/382TfmYYUeedXB2RUt5GA 8dow== ARC-Authentication-Results: i=1; mx.google.com; spf=softfail (google.com: domain of transitioning linux-kernel-owner@vger.kernel.org does not designate 23.128.96.19 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=alibaba.com Return-Path: Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net. [23.128.96.19]) by mx.google.com with ESMTPS id x8-20020a656aa8000000b003816043f0d0si1188723pgu.709.2022.03.16.22.35.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 16 Mar 2022 22:35:29 -0700 (PDT) Received-SPF: softfail (google.com: domain of transitioning linux-kernel-owner@vger.kernel.org does not designate 23.128.96.19 as permitted sender) client-ip=23.128.96.19; Authentication-Results: mx.google.com; spf=softfail (google.com: domain of transitioning linux-kernel-owner@vger.kernel.org does not designate 23.128.96.19 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=alibaba.com Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 3CA071B9FC5; Wed, 16 Mar 2022 21:36:46 -0700 (PDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236573AbiCPNTA (ORCPT + 99 others); Wed, 16 Mar 2022 09:19:00 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52508 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1356193AbiCPNSr (ORCPT ); Wed, 16 Mar 2022 09:18:47 -0400 Received: from out30-56.freemail.mail.aliyun.com (out30-56.freemail.mail.aliyun.com [115.124.30.56]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E6C1D66ADE; Wed, 16 Mar 2022 06:17:31 -0700 (PDT) X-Alimail-AntiSpam: AC=PASS;BC=-1|-1;BR=01201311R241e4;CH=green;DM=||false|;DS=||;FP=0|-1|-1|-1|0|-1|-1|-1;HT=e01e04423;MF=jefflexu@linux.alibaba.com;NM=1;PH=DS;RN=16;SR=0;TI=SMTPD_---0V7NDH9X_1647436648; Received: from localhost(mailfrom:jefflexu@linux.alibaba.com fp:SMTPD_---0V7NDH9X_1647436648) by smtp.aliyun-inc.com(127.0.0.1); Wed, 16 Mar 2022 21:17:29 +0800 From: Jeffle Xu To: dhowells@redhat.com, linux-cachefs@redhat.com, xiang@kernel.org, chao@kernel.org, linux-erofs@lists.ozlabs.org Cc: torvalds@linux-foundation.org, gregkh@linuxfoundation.org, willy@infradead.org, linux-fsdevel@vger.kernel.org, joseph.qi@linux.alibaba.com, bo.liu@linux.alibaba.com, tao.peng@linux.alibaba.com, gerry@linux.alibaba.com, eguan@linux.alibaba.com, linux-kernel@vger.kernel.org, luodaowen.backend@bytedance.com Subject: [PATCH v5 03/22] cachefiles: introduce on-demand read mode Date: Wed, 16 Mar 2022 21:17:04 +0800 Message-Id: <20220316131723.111553-4-jefflexu@linux.alibaba.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20220316131723.111553-1-jefflexu@linux.alibaba.com> References: <20220316131723.111553-1-jefflexu@linux.alibaba.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,RDNS_NONE, SPF_HELO_NONE,T_SCC_BODY_TEXT_LINE,UNPARSEABLE_RELAY autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Fscache/cachefiles used to serve as a local cache for remote fs. This patch, along with the following patches, introduces a new on-demand read mode for cachefiles, which can boost the scenario where on-demand read semantics is needed, e.g. container image distribution. The essential difference between the original mode and on-demand read mode is that, in the original mode, when cache miss, netfs itself will fetch data from remote, and then write the fetched data into cache file. While in on-demand read mode, a user daemon is responsible for fetching data and then writing to the cache file. This patch only adds the command to enable on-demand read mode. An optional parameter to "bind" command is added. On-demand mode will be turned on when this optional argument matches "ondemand" exactly, i.e. "bind ondemand". Otherwise cachefiles will keep working in the original mode. The following patches will implement the data plane of on-demand read mode. Signed-off-by: Jeffle Xu --- fs/cachefiles/Kconfig | 11 ++++ fs/cachefiles/daemon.c | 132 +++++++++++++++++++++++++++++++-------- fs/cachefiles/internal.h | 6 ++ 3 files changed, 124 insertions(+), 25 deletions(-) diff --git a/fs/cachefiles/Kconfig b/fs/cachefiles/Kconfig index 719faeeda168..58aad1fb4c5c 100644 --- a/fs/cachefiles/Kconfig +++ b/fs/cachefiles/Kconfig @@ -26,3 +26,14 @@ config CACHEFILES_ERROR_INJECTION help This permits error injection to be enabled in cachefiles whilst a cache is in service. + +config CACHEFILES_ONDEMAND + bool "Support for on-demand read" + depends on CACHEFILES + default n + help + This permits on-demand read mode of cachefiles. In this mode, when + cache miss, the cachefiles backend instead of netfs, is responsible + for fetching data, e.g. through user daemon. + + If unsure, say N. diff --git a/fs/cachefiles/daemon.c b/fs/cachefiles/daemon.c index 7ac04ee2c0a0..c0c3a3cbee28 100644 --- a/fs/cachefiles/daemon.c +++ b/fs/cachefiles/daemon.c @@ -78,6 +78,65 @@ static const struct cachefiles_daemon_cmd cachefiles_daemon_cmds[] = { { "", NULL } }; +#ifdef CONFIG_CACHEFILES_ONDEMAND +static inline void cachefiles_ondemand_open(struct cachefiles_cache *cache) +{ + xa_init_flags(&cache->reqs, XA_FLAGS_ALLOC); + rwlock_init(&cache->reqs_lock); +} + +static inline void cachefiles_ondemand_release(struct cachefiles_cache *cache) +{ + xa_destroy(&cache->reqs); +} + +static inline __poll_t cachefiles_ondemand_mask(struct cachefiles_cache *cache) +{ + __poll_t mask = 0; + + if (!xa_empty(&cache->reqs)) + mask |= EPOLLIN; + + if (test_bit(CACHEFILES_CULLING, &cache->flags)) + mask |= EPOLLOUT; + + return mask; +} + +static inline +bool cachefiles_ondemand_daemon_bind(struct cachefiles_cache *cache, char *args) +{ + if (!strcmp(args, "ondemand")) { + set_bit(CACHEFILES_ONDEMAND_MODE, &cache->flags); + return true; + } + + return false; +} + +#else +static inline void cachefiles_ondemand_open(struct cachefiles_cache *cache) {} +static inline void cachefiles_ondemand_release(struct cachefiles_cache *cache) {} + +static inline +__poll_t cachefiles_ondemand_mask(struct cachefiles_cache *cache) +{ + return 0; +} + +static inline +bool cachefiles_ondemand_daemon_bind(struct cachefiles_cache *cache, char *args) +{ + return false; +} +#endif + +static inline +ssize_t cachefiles_ondemand_daemon_read(struct cachefiles_cache *cache, + char __user *_buffer, size_t buflen) +{ + return -EOPNOTSUPP; +} /* * Prepare a cache for caching. @@ -108,6 +167,7 @@ static int cachefiles_daemon_open(struct inode *inode, struct file *file) INIT_LIST_HEAD(&cache->volumes); INIT_LIST_HEAD(&cache->object_list); spin_lock_init(&cache->object_list_lock); + cachefiles_ondemand_open(cache); /* set default caching limits * - limit at 1% free space and/or free files @@ -139,6 +199,7 @@ static int cachefiles_daemon_release(struct inode *inode, struct file *file) set_bit(CACHEFILES_DEAD, &cache->flags); + cachefiles_ondemand_release(cache); cachefiles_daemon_unbind(cache); /* clean up the control file interface */ @@ -152,23 +213,15 @@ static int cachefiles_daemon_release(struct inode *inode, struct file *file) return 0; } -/* - * Read the cache state. - */ -static ssize_t cachefiles_daemon_read(struct file *file, char __user *_buffer, - size_t buflen, loff_t *pos) +static ssize_t cachefiles_do_daemon_read(struct cachefiles_cache *cache, + char __user *_buffer, + size_t buflen) { - struct cachefiles_cache *cache = file->private_data; unsigned long long b_released; unsigned f_released; char buffer[256]; int n; - //_enter(",,%zu,", buflen); - - if (!test_bit(CACHEFILES_READY, &cache->flags)) - return 0; - /* check how much space the cache has */ cachefiles_has_space(cache, 0, 0, cachefiles_has_space_check); @@ -206,6 +259,25 @@ static ssize_t cachefiles_daemon_read(struct file *file, char __user *_buffer, return n; } +/* + * Read the cache state. + */ +static ssize_t cachefiles_daemon_read(struct file *file, char __user *_buffer, + size_t buflen, loff_t *pos) +{ + struct cachefiles_cache *cache = file->private_data; + + //_enter(",,%zu,", buflen); + + if (!test_bit(CACHEFILES_READY, &cache->flags)) + return 0; + + if (likely(!test_bit(CACHEFILES_ONDEMAND_MODE, &cache->flags))) + return cachefiles_do_daemon_read(cache, _buffer, buflen); + else + return cachefiles_ondemand_daemon_read(cache, _buffer, buflen); +} + /* * Take a command from cachefilesd, parse it and act on it. */ @@ -284,6 +356,21 @@ static ssize_t cachefiles_daemon_write(struct file *file, goto error; } + +static inline +__poll_t cachefiles_daemon_mask(struct cachefiles_cache *cache) +{ + __poll_t mask = 0; + + if (test_bit(CACHEFILES_STATE_CHANGED, &cache->flags)) + mask |= EPOLLIN; + + if (test_bit(CACHEFILES_CULLING, &cache->flags)) + mask |= EPOLLOUT; + + return mask; +} + /* * Poll for culling state * - use EPOLLOUT to indicate culling state @@ -292,18 +379,13 @@ static __poll_t cachefiles_daemon_poll(struct file *file, struct poll_table_struct *poll) { struct cachefiles_cache *cache = file->private_data; - __poll_t mask; poll_wait(file, &cache->daemon_pollwq, poll); - mask = 0; - - if (test_bit(CACHEFILES_STATE_CHANGED, &cache->flags)) - mask |= EPOLLIN; - - if (test_bit(CACHEFILES_CULLING, &cache->flags)) - mask |= EPOLLOUT; - return mask; + if (likely(!test_bit(CACHEFILES_ONDEMAND_MODE, &cache->flags))) + return cachefiles_daemon_mask(cache); + else + return cachefiles_ondemand_mask(cache); } /* @@ -687,11 +769,6 @@ static int cachefiles_daemon_bind(struct cachefiles_cache *cache, char *args) cache->brun_percent >= 100) return -ERANGE; - if (*args) { - pr_err("'bind' command doesn't take an argument\n"); - return -EINVAL; - } - if (!cache->rootdirname) { pr_err("No cache directory specified\n"); return -EINVAL; @@ -703,6 +780,11 @@ static int cachefiles_daemon_bind(struct cachefiles_cache *cache, char *args) return -EBUSY; } + if (!cachefiles_ondemand_daemon_bind(cache, args) && *args) { + pr_err("'bind' command doesn't take an argument\n"); + return -EINVAL; + } + /* Make sure we have copies of the tag string */ if (!cache->tag) { /* diff --git a/fs/cachefiles/internal.h b/fs/cachefiles/internal.h index e80673d0ab97..3f791882fa3f 100644 --- a/fs/cachefiles/internal.h +++ b/fs/cachefiles/internal.h @@ -15,6 +15,7 @@ #include #include #include +#include #define CACHEFILES_DIO_BLOCK_SIZE 4096 @@ -98,9 +99,14 @@ struct cachefiles_cache { #define CACHEFILES_DEAD 1 /* T if cache dead */ #define CACHEFILES_CULLING 2 /* T if cull engaged */ #define CACHEFILES_STATE_CHANGED 3 /* T if state changed (poll trigger) */ +#define CACHEFILES_ONDEMAND_MODE 4 /* T if in on-demand read mode */ char *rootdirname; /* name of cache root directory */ char *secctx; /* LSM security context */ char *tag; /* cache binding tag */ +#ifdef CONFIG_CACHEFILES_ONDEMAND + struct xarray reqs; /* xarray of pending on-demand requests */ + rwlock_t reqs_lock; /* Lock for reqs xarray */ +#endif }; #include -- 2.27.0