From nobody Sun Feb 8 02:30:13 2026 Received: from out30-119.freemail.mail.aliyun.com (out30-119.freemail.mail.aliyun.com [115.124.30.119]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EE9AA450E2 for ; Wed, 31 Jul 2024 08:07:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=115.124.30.119 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722413253; cv=none; b=alNIuAdwhBWSl8191fZklrzx7deI8EhG/WumQvL0UjNYIPAjzYoTCZaXbZU+S4i6RIulStWZhcgOX5DQGNPpjMJHxRzShP1Vu+6TW0hDiVts1Wf4knHuBM5VqGPi4A1kNZoMqy5UqPNRWc5kfE2rRAPhL4YaBts13cLlNu2DPzw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722413253; c=relaxed/simple; bh=UP59hoySUxTOQWRjvpXN0tg1HDwfSZ1aixRrwcBqzAc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KArq/MMMaE/t5ZSxt2eHa/ZphdIjcM/RKugkFP8FaKok7MYyaxrN0EQciabS96KhlWrSYb6HJ5l9m+2rkRxgj6HJ4VtsTaPXpcKWPsmmoRnPUTntdsy7uF9Nv77fHdO2Lvoz+SL8EPaap4bMLROOcBSatdO6Zpy208mZTqOvXTk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.alibaba.com; spf=pass smtp.mailfrom=linux.alibaba.com; dkim=pass (1024-bit key) header.d=linux.alibaba.com header.i=@linux.alibaba.com header.b=P0/MiyCh; arc=none smtp.client-ip=115.124.30.119 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.alibaba.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.alibaba.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.alibaba.com header.i=@linux.alibaba.com header.b="P0/MiyCh" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.alibaba.com; s=default; t=1722413247; h=From:To:Subject:Date:Message-ID:MIME-Version; bh=1vychGnx9JkHG1URHFL9M2pGgd4sXlxVdgTpdcpkQHk=; b=P0/MiyChnboFFrXyu62CSFWb/pXaE9K8UkKc3yOq3oEARoFVY3FsDOUmBGc+xseaTno0uWCpMOPBAJ8jxoRe7xtexwb8ppKs2IFlGWPtgZ/rXf9uUa6VPPW+XxdSCTDTfX0eD8o6YuWW8DaLOn1Byd+LWc86fOIto1pHuSkVcp0= X-Alimail-AntiSpam: AC=PASS;BC=-1|-1;BR=01201311R301e4;CH=green;DM=||false|;DS=||;FP=0|-1|-1|-1|0|-1|-1|-1;HT=maildocker-contentspam033037067111;MF=hongzhen@linux.alibaba.com;NM=1;PH=DS;RN=4;SR=0;TI=SMTPD_---0WBiiDRy_1722413246; Received: from localhost(mailfrom:hongzhen@linux.alibaba.com fp:SMTPD_---0WBiiDRy_1722413246) by smtp.aliyun-inc.com; Wed, 31 Jul 2024 16:07:26 +0800 From: Hongzhen Luo To: linux-erofs@lists.ozlabs.org, lihongbo22@huawei.com Cc: linux-kernel@vger.kernel.org, Hongzhen Luo Subject: [PATCH RFC v2 1/2] erofs: introduce page cache share feature Date: Wed, 31 Jul 2024 16:07:03 +0800 Message-ID: <20240731080704.678259-2-hongzhen@linux.alibaba.com> X-Mailer: git-send-email 2.43.5 In-Reply-To: <20240731080704.678259-1-hongzhen@linux.alibaba.com> References: <20240731080704.678259-1-hongzhen@linux.alibaba.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Currently, reading files with different paths (or names) but the same content will consume multiple copies of the page cache, even if the content of these page caches is the same. For example, reading identical files (e.g., *.so files) from two different minor versions of container images will cost multiple copies of the same page cache, since different containers have different mount points. Therefore, sharing the page cache for files with the same content can save memory. This introduces the page cache share feature in erofs. During the mkfs phase, file content is hashed and the hash value is stored in the `trusted.erofs.fingerprint` extended attribute. Inodes of files with the same `trusted.erofs.fingerprint` are mapped to a list. One of these inodes that in the list (the first inode in this implementation) is used to store the actual content. In this way, a single copy of the selected inode's page cache can serve read requests from several files mapped to it. Below is the memory usage for reading all files in two different minor versions of container images: +-------------------+------------------+-------------+---------------+ | Image | Page Cache Share | Memory (MB) | Memory | | | | | Reduction (%) | +-------------------+------------------+-------------+---------------+ | | No | 241 | - | | redis +------------------+-------------+---------------+ | 7.2.4 & 7.2.5 | Yes | 163 | 33% | +-------------------+------------------+-------------+---------------+ | | No | 872 | - | | postgres +------------------+-------------+---------------+ | 16.1 & 16.2 | Yes | 630 | 28% | +-------------------+------------------+-------------+---------------+ | | No | 2771 | - | | tensorflow +------------------+-------------+---------------+ | 1.11.0 & 2.11.1 | Yes | 2340 | 16% | +-------------------+------------------+-------------+---------------+ | | No | 926 | - | | mysql +------------------+-------------+---------------+ | 8.0.11 & 8.0.12 | Yes | 735 | 21% | +-------------------+------------------+-------------+---------------+ | | No | 390 | - | | nginx +------------------+-------------+---------------+ | 7.2.4 & 7.2.5 | Yes | 219 | 44% | +-------------------+------------------+-------------+---------------+ | tomcat | No | 924 | - | | 10.1.25 & 10.1.26 +------------------+-------------+---------------+ | | Yes | 474 | 49% | +-------------------+------------------+-------------+---------------+ Additionally, the table below shows the runtime memory usage of the container: +-------------------+------------------+-------------+---------------+ | Image | Page Cache Share | Memory (MB) | Memory | | | | | Reduction (%) | +-------------------+------------------+-------------+---------------+ | | No | 35 | - | | redis +------------------+-------------+---------------+ | 7.2.4 & 7.2.5 | Yes | 28 | 20% | +-------------------+------------------+-------------+---------------+ | | No | 149 | - | | postgres +------------------+-------------+---------------+ | 16.1 & 16.2 | Yes | 95 | 37% | +-------------------+------------------+-------------+---------------+ | | No | 1028 | - | | tensorflow +------------------+-------------+---------------+ | 1.11.0 & 2.11.1 | Yes | 941 | 9% | +-------------------+------------------+-------------+---------------+ | | No | 155 | - | | mysql +------------------+-------------+---------------+ | 8.0.11 & 8.0.12 | Yes | 139 | 11% | +-------------------+------------------+-------------+---------------+ | | No | 25 | - | | nginx +------------------+-------------+---------------+ | 7.2.4 & 7.2.5 | Yes | 20 | 23% | +-------------------+------------------+-------------+---------------+ | tomcat | No | 186 | - | | 10.1.25 & 10.1.26 +------------------+-------------+---------------+ | | Yes | 98 | 48% | +-------------------+------------------+-------------+---------------+ Signed-off-by: Hongzhen Luo --- v2: Refactored the implementation. v1: https://lore.kernel.org/all/20240722065355.1396365-4-hongzhen@linux.ali= baba.com/ --- fs/erofs/Kconfig | 10 ++ fs/erofs/Makefile | 1 + fs/erofs/internal.h | 8 ++ fs/erofs/pagecache_share.c | 189 +++++++++++++++++++++++++++++++++++++ fs/erofs/pagecache_share.h | 15 +++ 5 files changed, 223 insertions(+) create mode 100644 fs/erofs/pagecache_share.c create mode 100644 fs/erofs/pagecache_share.h diff --git a/fs/erofs/Kconfig b/fs/erofs/Kconfig index 7dcdce660cac..756a74de623c 100644 --- a/fs/erofs/Kconfig +++ b/fs/erofs/Kconfig @@ -158,3 +158,13 @@ config EROFS_FS_PCPU_KTHREAD_HIPRI at higher priority. =20 If unsure, say N. + +config EROFS_FS_PAGE_CACHE_SHARE + bool "EROFS page cache share support" + depends on EROFS_FS + default n + help + This permits EROFS to share page cache for files with same + fingerprints. + + If unsure, say N. diff --git a/fs/erofs/Makefile b/fs/erofs/Makefile index 097d672e6b14..f14a2ac0e561 100644 --- a/fs/erofs/Makefile +++ b/fs/erofs/Makefile @@ -8,3 +8,4 @@ erofs-$(CONFIG_EROFS_FS_ZIP_LZMA) +=3D decompressor_lzma.o erofs-$(CONFIG_EROFS_FS_ZIP_DEFLATE) +=3D decompressor_deflate.o erofs-$(CONFIG_EROFS_FS_ZIP_ZSTD) +=3D decompressor_zstd.o erofs-$(CONFIG_EROFS_FS_ONDEMAND) +=3D fscache.o +erofs-$(CONFIG_EROFS_FS_PAGE_CACHE_SHARE) +=3D pagecache_share.o diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h index 736607675396..e3c17b28d1c5 100644 --- a/fs/erofs/internal.h +++ b/fs/erofs/internal.h @@ -288,6 +288,13 @@ struct erofs_inode { }; #endif /* CONFIG_EROFS_FS_ZIP */ }; +#ifdef CONFIG_EROFS_FS_PAGE_CACHE_SHARE + struct list_head pcs_list; + struct rw_semaphore pcs_rwsem; + char *fprt; + int fprt_len; + unsigned long fprt_hash; +#endif /* the corresponding vfs inode */ struct inode vfs_inode; }; @@ -383,6 +390,7 @@ extern const struct inode_operations erofs_fast_symlink= _iops; extern const struct inode_operations erofs_dir_iops; =20 extern const struct file_operations erofs_file_fops; +extern const struct file_operations erofs_pcs_file_fops; extern const struct file_operations erofs_dir_fops; =20 extern const struct iomap_ops z_erofs_iomap_report_ops; diff --git a/fs/erofs/pagecache_share.c b/fs/erofs/pagecache_share.c new file mode 100644 index 000000000000..985dd2a38b5e --- /dev/null +++ b/fs/erofs/pagecache_share.c @@ -0,0 +1,189 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2024, Alibaba Cloud + */ +#include +#include +#include +#include "internal.h" +#include "xattr.h" +#include "pagecache_share.h" + +struct erofs_pcs_lhead { + struct mutex lmutex; + struct list_head list; +}; + +#define PCS_FPRT_IDX 4 +#define PCS_FPRT_NAME "erofs.fingerprint" +#define PCS_FPRT_MAXLEN 1024 + +DEFINE_XARRAY(pcs_xarray); + +void erofs_pcs_fill_inode(struct inode *inode) +{ + struct erofs_inode *vi =3D EROFS_I(inode); + char fprt[PCS_FPRT_MAXLEN]; + + vi->fprt_len =3D erofs_getxattr(inode, PCS_FPRT_IDX, PCS_FPRT_NAME, fprt, + PCS_FPRT_MAXLEN); + if (vi->fprt_len > 0 && vi->fprt_len <=3D PCS_FPRT_MAXLEN) { + vi->fprt =3D kmalloc(vi->fprt_len, GFP_KERNEL); + if (IS_ERR(vi->fprt)) { + vi->fprt_len =3D -1; + return; + } + memcpy(vi->fprt, fprt, vi->fprt_len); + vi->fprt_hash =3D xxh32(vi->fprt, vi->fprt_len, 0); + } +} + +int erofs_pcs_add(struct inode *inode) +{ + struct erofs_inode *vi =3D EROFS_I(inode); + struct erofs_pcs_lhead *lst; + + xa_lock(&pcs_xarray); + lst =3D xa_load(&pcs_xarray, vi->fprt_hash); + if (!lst) { + lst =3D kmalloc(sizeof(struct erofs_pcs_lhead), GFP_KERNEL); + if (!lst) { + xa_unlock(&pcs_xarray); + return -ENOMEM; + } + mutex_init(&lst->lmutex); + INIT_LIST_HEAD(&lst->list); + /* we have already held the xa_lock here */ + __xa_store(&pcs_xarray, vi->fprt_hash, lst, GFP_KERNEL); + } + xa_unlock(&pcs_xarray); + + mutex_lock(&lst->lmutex); + list_add_tail(&vi->pcs_list, &lst->list); + mutex_unlock(&lst->lmutex); + return 0; +} + +int erofs_pcs_remove(struct inode *inode) +{ + struct erofs_inode *vi =3D EROFS_I(inode); + struct erofs_pcs_lhead *lst =3D xa_load(&pcs_xarray, vi->fprt_hash); + + if (!lst || list_empty(&lst->list)) + return -EINVAL; + + mutex_lock(&lst->lmutex); + down_write(&vi->pcs_rwsem); + list_del(&vi->pcs_list); + up_write(&vi->pcs_rwsem); + mutex_unlock(&lst->lmutex); + + xa_lock(&pcs_xarray); + if (list_empty(&lst->list)) { + __xa_erase(&pcs_xarray, vi->fprt_hash); + kfree(lst); + } + xa_unlock(&pcs_xarray); + return 0; +} + +static struct inode *erofs_pcs_get4read(struct inode *inode) +{ + struct erofs_inode *vi =3D EROFS_I(inode), *pcs_inode =3D NULL, *p, *tmp; + struct erofs_pcs_lhead *lst =3D xa_load(&pcs_xarray, vi->fprt_hash); + + if (!lst || list_empty(&lst->list)) + return ERR_PTR(-EINVAL); + + mutex_lock(&lst->lmutex); + list_for_each_entry_safe(p, tmp, &lst->list, pcs_list) { + if (vi->fprt_len =3D=3D p->fprt_len && + !memcmp(vi->fprt, p->fprt, p->fprt_len)) { + pcs_inode =3D p; + break; + } + } + if (pcs_inode) + down_read(&pcs_inode->pcs_rwsem); + mutex_unlock(&lst->lmutex); + + return pcs_inode ? &pcs_inode->vfs_inode : ERR_PTR(-EINVAL); +} + +static int erofs_pcs_file_open(struct inode *inode, struct file *file) +{ + struct inode *pcs_inode; + struct file *ano_file; + + pcs_inode =3D erofs_pcs_get4read(inode); + if (IS_ERR(pcs_inode)) + return PTR_ERR(pcs_inode); + + ano_file =3D alloc_file_pseudo(pcs_inode, file->f_path.mnt, "[erofs_pcs_f= ]", + O_RDONLY, &erofs_file_fops); + file_ra_state_init(&ano_file->f_ra, file->f_mapping); + ihold(pcs_inode); + file->private_data =3D (void *)ano_file; + return 0; +} + +static int erofs_pcs_file_release(struct inode *inode, struct file *file) +{ + struct inode *pcs_inode; + + if (!file->private_data) + return -EINVAL; + pcs_inode =3D ((struct file *)file->private_data)->f_inode; + up_read(&EROFS_I(pcs_inode)->pcs_rwsem); + fput((struct file *)file->private_data); + file->private_data =3D NULL; + return 0; +} + +static ssize_t erofs_pcs_file_read_iter(struct kiocb *iocb, + struct iov_iter *to) +{ + struct file *file, *ano_file; + struct kiocb ano_iocb; + ssize_t res; + + memcpy(&ano_iocb, iocb, sizeof(struct kiocb)); + file =3D iocb->ki_filp; + ano_file =3D file->private_data; + if (!ano_file) + return -EINVAL; + ano_iocb.ki_filp =3D ano_file; + res =3D filemap_read(&ano_iocb, to, 0); + memcpy(iocb, &ano_iocb, sizeof(struct kiocb)); + iocb->ki_filp =3D file; + file_accessed(file); + return res; +} + +static vm_fault_t erofs_pcs_fault(struct vm_fault *vmf) +{ + return filemap_fault(vmf); +} + +static const struct vm_operations_struct erofs_pcs_file_vm_ops =3D { + .fault =3D erofs_pcs_fault, +}; + +static int erofs_pcs_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct file *ano_file =3D file->private_data; + + vma_set_file(vma, ano_file); + vma->vm_ops =3D &erofs_pcs_file_vm_ops; + return 0; +} + +const struct file_operations erofs_pcs_file_fops =3D { + .open =3D erofs_pcs_file_open, + .llseek =3D generic_file_llseek, + .read_iter =3D erofs_pcs_file_read_iter, + .mmap =3D erofs_pcs_mmap, + .release =3D erofs_pcs_file_release, + .get_unmapped_area =3D thp_get_unmapped_area, + .splice_read =3D filemap_splice_read, +}; diff --git a/fs/erofs/pagecache_share.h b/fs/erofs/pagecache_share.h new file mode 100644 index 000000000000..fb75ae3abd8a --- /dev/null +++ b/fs/erofs/pagecache_share.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2024, Alibaba Cloud + */ +#ifndef __EROFS_PAGECACHE_SHARE_H +#define __EROFS_PAGECACHE_SHARE_H + +#include +#include "internal.h" + +void erofs_pcs_fill_inode(struct inode *inode); +int erofs_pcs_add(struct inode *inode); +int erofs_pcs_remove(struct inode *inode); + +#endif --=20 2.43.5 From nobody Sun Feb 8 02:30:13 2026 Received: from out30-99.freemail.mail.aliyun.com (out30-99.freemail.mail.aliyun.com [115.124.30.99]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2E4531A7F83 for ; Wed, 31 Jul 2024 08:07:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=115.124.30.99 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722413259; cv=none; b=tUFRevHObpDIkkF0pN44DrC8yaGifiyToeQCwaI7Uju3Nts5SxstR2QL+fIIHI5/dKSiOza3AKdTl8/dBg/dCA3UNS7hL7/SZhET3Wjks3yX9JS/gYNUYOelTDBKzdV9mWZ+kSz9gRnSPBYVWPNZ8loIVh3AfWfIKpvf2vYzGRk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722413259; c=relaxed/simple; bh=sJSne7FvUaCGqRE++yqsmdYIUgUzrbYV/gqTygAMAkY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KS0Loq4N1mOrRakplcx7K7wZuIA+MLJuJPIUS0nkF5h69zR6L2Alciu3AxBvNexppZmTVa8wmxhp+rbHDKra0ILl+UT4idNC7fw02LVIOA9UN5bbOpJ0KXRWVkU/tArs/8dXlsCMZI4z/VPHrZSu9f01aDUybtpSsHQHx91CFaM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.alibaba.com; spf=pass smtp.mailfrom=linux.alibaba.com; dkim=pass (1024-bit key) header.d=linux.alibaba.com header.i=@linux.alibaba.com header.b=t/RxFkd0; arc=none smtp.client-ip=115.124.30.99 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.alibaba.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.alibaba.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.alibaba.com header.i=@linux.alibaba.com header.b="t/RxFkd0" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.alibaba.com; s=default; t=1722413248; h=From:To:Subject:Date:Message-ID:MIME-Version; bh=DSxArOXpMYYo5QvLWFHxWEb/Rcp06yq06zBpX4yplY0=; b=t/RxFkd03KWda9R0qUqgPt4yADXslPTVVdoZOFPnK0cTaZbbLP34T5qevcybkov1b7wCYAvXMfgpMUkFfy6aeJ5/hrzgasw/R8bLq5Va0LfveAXUYeNht4uLC0vJTAxjAFuxDLMhMa9DFrsLzLojNyM+KFwrgQCg0jgqxliuY44= X-Alimail-AntiSpam: AC=PASS;BC=-1|-1;BR=01201311R741e4;CH=green;DM=||false|;DS=||;FP=0|-1|-1|-1|0|-1|-1|-1;HT=maildocker-contentspam033045046011;MF=hongzhen@linux.alibaba.com;NM=1;PH=DS;RN=4;SR=0;TI=SMTPD_---0WBikPVL_1722413247; Received: from localhost(mailfrom:hongzhen@linux.alibaba.com fp:SMTPD_---0WBikPVL_1722413247) by smtp.aliyun-inc.com; Wed, 31 Jul 2024 16:07:28 +0800 From: Hongzhen Luo To: linux-erofs@lists.ozlabs.org, lihongbo22@huawei.com Cc: linux-kernel@vger.kernel.org, Hongzhen Luo Subject: [PATCH RFC v2 2/2] erofs: apply the page cache share feature Date: Wed, 31 Jul 2024 16:07:04 +0800 Message-ID: <20240731080704.678259-3-hongzhen@linux.alibaba.com> X-Mailer: git-send-email 2.43.5 In-Reply-To: <20240731080704.678259-1-hongzhen@linux.alibaba.com> References: <20240731080704.678259-1-hongzhen@linux.alibaba.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" This modifies relevant functions to apply the page cache share feature. Signed-off-by: Hongzhen Luo --- v2: Make adjustments based on the latest implementation. v1: https://lore.kernel.org/all/20240722065355.1396365-5-hongzhen@linux.ali= baba.com/ --- fs/erofs/inode.c | 23 +++++++++++++++++++++++ fs/erofs/super.c | 23 +++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/fs/erofs/inode.c b/fs/erofs/inode.c index 5f6439a63af7..9f1e7332cff9 100644 --- a/fs/erofs/inode.c +++ b/fs/erofs/inode.c @@ -5,6 +5,7 @@ * Copyright (C) 2021, Alibaba Cloud */ #include "xattr.h" +#include "pagecache_share.h" =20 #include =20 @@ -229,10 +230,22 @@ static int erofs_fill_inode(struct inode *inode) switch (inode->i_mode & S_IFMT) { case S_IFREG: inode->i_op =3D &erofs_generic_iops; +#ifdef CONFIG_EROFS_FS_PAGE_CACHE_SHARE + erofs_pcs_fill_inode(inode); +#endif if (erofs_inode_is_data_compressed(vi->datalayout)) inode->i_fop =3D &generic_ro_fops; +#ifdef CONFIG_EROFS_FS_PAGE_CACHE_SHARE + else { + if (vi->fprt_len > 0) + inode->i_fop =3D &erofs_pcs_file_fops; + else + inode->i_fop =3D &erofs_file_fops; + } +#else else inode->i_fop =3D &erofs_file_fops; +#endif break; case S_IFDIR: inode->i_op =3D &erofs_dir_iops; @@ -325,6 +338,16 @@ struct inode *erofs_iget(struct super_block *sb, erofs= _nid_t nid) return ERR_PTR(err); } unlock_new_inode(inode); +#ifdef CONFIG_EROFS_FS_PAGE_CACHE_SHARE + if ((inode->i_mode & S_IFMT) =3D=3D S_IFREG && + EROFS_I(inode)->fprt_len > 0) { + err =3D erofs_pcs_add(inode); + if (err) { + iget_failed(inode); + return ERR_PTR(err); + } + } +#endif } return inode; } diff --git a/fs/erofs/super.c b/fs/erofs/super.c index 35268263aaed..a42e65ef7fc7 100644 --- a/fs/erofs/super.c +++ b/fs/erofs/super.c @@ -11,6 +11,7 @@ #include #include #include "xattr.h" +#include "pagecache_share.h" =20 #define CREATE_TRACE_POINTS #include @@ -95,6 +96,10 @@ static struct inode *erofs_alloc_inode(struct super_bloc= k *sb) =20 /* zero out everything except vfs_inode */ memset(vi, 0, offsetof(struct erofs_inode, vfs_inode)); +#ifdef CONFIG_EROFS_FS_PAGE_CACHE_SHARE + INIT_LIST_HEAD(&vi->pcs_list); + init_rwsem(&vi->pcs_rwsem); +#endif return &vi->vfs_inode; } =20 @@ -108,6 +113,21 @@ static void erofs_free_inode(struct inode *inode) kmem_cache_free(erofs_inode_cachep, vi); } =20 +#ifdef CONFIG_EROFS_FS_PAGE_CACHE_SHARE +static void erofs_destroy_inode(struct inode *inode) +{ + struct erofs_inode *vi =3D EROFS_I(inode); + + if ((inode->i_mode & S_IFMT) =3D=3D S_IFREG && + EROFS_I(inode)->fprt_len > 0) { + if (erofs_pcs_remove(inode)) + erofs_err(inode->i_sb, "pcs: fail to remove inode."); + kfree(vi->fprt); + vi->fprt =3D NULL; + } +} +#endif + static bool check_layout_compatibility(struct super_block *sb, struct erofs_super_block *dsb) { @@ -937,6 +957,9 @@ static int erofs_show_options(struct seq_file *seq, str= uct dentry *root) const struct super_operations erofs_sops =3D { .put_super =3D erofs_put_super, .alloc_inode =3D erofs_alloc_inode, +#ifdef CONFIG_EROFS_FS_PAGE_CACHE_SHARE + .destroy_inode =3D erofs_destroy_inode, +#endif .free_inode =3D erofs_free_inode, .statfs =3D erofs_statfs, .show_options =3D erofs_show_options, --=20 2.43.5