xref: /linux/fs/erofs/ishare.c (revision 3ba310f2a3ca70f0497aab5c2e8aa85a12e19406)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (C) 2024, Alibaba Cloud
4  */
5 #include <linux/xxhash.h>
6 #include <linux/mount.h>
7 #include <linux/security.h>
8 #include "internal.h"
9 #include "xattr.h"
10 
11 #include "../internal.h"
12 
13 static struct vfsmount *erofs_ishare_mnt;
14 
15 static inline bool erofs_is_ishare_inode(struct inode *inode)
16 {
17 	/* assumed FS_ONDEMAND is excluded with FS_PAGE_CACHE_SHARE feature */
18 	return inode->i_sb->s_type == &erofs_anon_fs_type;
19 }
20 
21 static int erofs_ishare_iget5_eq(struct inode *inode, void *data)
22 {
23 	struct erofs_inode_fingerprint *fp1 = &EROFS_I(inode)->fingerprint;
24 	struct erofs_inode_fingerprint *fp2 = data;
25 
26 	return fp1->size == fp2->size &&
27 		!memcmp(fp1->opaque, fp2->opaque, fp2->size);
28 }
29 
30 static int erofs_ishare_iget5_set(struct inode *inode, void *data)
31 {
32 	struct erofs_inode *vi = EROFS_I(inode);
33 
34 	vi->fingerprint = *(struct erofs_inode_fingerprint *)data;
35 	INIT_LIST_HEAD(&vi->ishare_list);
36 	spin_lock_init(&vi->ishare_lock);
37 	return 0;
38 }
39 
40 bool erofs_ishare_fill_inode(struct inode *inode)
41 {
42 	struct erofs_sb_info *sbi = EROFS_SB(inode->i_sb);
43 	struct erofs_inode *vi = EROFS_I(inode);
44 	const struct address_space_operations *aops;
45 	struct erofs_inode_fingerprint fp;
46 	struct inode *sharedinode;
47 	unsigned long hash;
48 
49 	aops = erofs_get_aops(inode, true);
50 	if (IS_ERR(aops))
51 		return false;
52 	if (erofs_xattr_fill_inode_fingerprint(&fp, inode, sbi->domain_id))
53 		return false;
54 	hash = xxh32(fp.opaque, fp.size, 0);
55 	sharedinode = iget5_locked(erofs_ishare_mnt->mnt_sb, hash,
56 				   erofs_ishare_iget5_eq, erofs_ishare_iget5_set,
57 				   &fp);
58 	if (!sharedinode) {
59 		kfree(fp.opaque);
60 		return false;
61 	}
62 
63 	if (inode_state_read_once(sharedinode) & I_NEW) {
64 		sharedinode->i_mapping->a_ops = aops;
65 		sharedinode->i_size = vi->vfs_inode.i_size;
66 		unlock_new_inode(sharedinode);
67 	} else {
68 		kfree(fp.opaque);
69 		if (aops != sharedinode->i_mapping->a_ops) {
70 			iput(sharedinode);
71 			return false;
72 		}
73 		if (sharedinode->i_size != vi->vfs_inode.i_size) {
74 			_erofs_printk(inode->i_sb, KERN_WARNING
75 				"size(%lld:%lld) not matches for the same fingerprint\n",
76 				vi->vfs_inode.i_size, sharedinode->i_size);
77 			iput(sharedinode);
78 			return false;
79 		}
80 	}
81 	vi->sharedinode = sharedinode;
82 	INIT_LIST_HEAD(&vi->ishare_list);
83 	spin_lock(&EROFS_I(sharedinode)->ishare_lock);
84 	list_add(&vi->ishare_list, &EROFS_I(sharedinode)->ishare_list);
85 	spin_unlock(&EROFS_I(sharedinode)->ishare_lock);
86 	return true;
87 }
88 
89 void erofs_ishare_free_inode(struct inode *inode)
90 {
91 	struct erofs_inode *vi = EROFS_I(inode);
92 	struct inode *sharedinode = vi->sharedinode;
93 
94 	if (!sharedinode)
95 		return;
96 	spin_lock(&EROFS_I(sharedinode)->ishare_lock);
97 	list_del(&vi->ishare_list);
98 	spin_unlock(&EROFS_I(sharedinode)->ishare_lock);
99 	iput(sharedinode);
100 	vi->sharedinode = NULL;
101 }
102 
103 static int erofs_ishare_file_open(struct inode *inode, struct file *file)
104 {
105 	struct inode *sharedinode = EROFS_I(inode)->sharedinode;
106 	struct file *realfile;
107 
108 	if (file->f_flags & O_DIRECT)
109 		return -EINVAL;
110 	realfile = alloc_empty_backing_file(O_RDONLY|O_NOATIME, current_cred(),
111 					    file);
112 	if (IS_ERR(realfile))
113 		return PTR_ERR(realfile);
114 	ihold(sharedinode);
115 	realfile->f_op = &erofs_file_fops;
116 	realfile->f_inode = sharedinode;
117 	realfile->f_mapping = sharedinode->i_mapping;
118 	path_get(&file->f_path);
119 	backing_file_set_user_path(realfile, &file->f_path);
120 
121 	file_ra_state_init(&realfile->f_ra, file->f_mapping);
122 	realfile->private_data = EROFS_I(inode);
123 	file->private_data = realfile;
124 	return 0;
125 }
126 
127 static int erofs_ishare_file_release(struct inode *inode, struct file *file)
128 {
129 	struct file *realfile = file->private_data;
130 
131 	iput(realfile->f_inode);
132 	fput(realfile);
133 	file->private_data = NULL;
134 	return 0;
135 }
136 
137 static ssize_t erofs_ishare_file_read_iter(struct kiocb *iocb,
138 					   struct iov_iter *to)
139 {
140 	struct file *realfile = iocb->ki_filp->private_data;
141 	struct kiocb dedup_iocb;
142 	ssize_t nread;
143 
144 	if (!iov_iter_count(to))
145 		return 0;
146 	kiocb_clone(&dedup_iocb, iocb, realfile);
147 	nread = filemap_read(&dedup_iocb, to, 0);
148 	iocb->ki_pos = dedup_iocb.ki_pos;
149 	return nread;
150 }
151 
152 static int erofs_ishare_mmap(struct file *file, struct vm_area_struct *vma)
153 {
154 	struct file *realfile = file->private_data;
155 	int err;
156 
157 	vma_set_file(vma, realfile);
158 
159 	err = security_mmap_backing_file(vma, realfile, file);
160 	if (err)
161 		return err;
162 
163 	return generic_file_readonly_mmap(file, vma);
164 }
165 
166 static int erofs_ishare_fadvise(struct file *file, loff_t offset,
167 				loff_t len, int advice)
168 {
169 	return vfs_fadvise(file->private_data, offset, len, advice);
170 }
171 
172 const struct file_operations erofs_ishare_fops = {
173 	.open		= erofs_ishare_file_open,
174 	.llseek		= generic_file_llseek,
175 	.read_iter	= erofs_ishare_file_read_iter,
176 	.mmap		= erofs_ishare_mmap,
177 	.release	= erofs_ishare_file_release,
178 	.get_unmapped_area = thp_get_unmapped_area,
179 	.splice_read	= filemap_splice_read,
180 	.fadvise	= erofs_ishare_fadvise,
181 };
182 
183 struct inode *erofs_real_inode(struct inode *inode, bool *need_iput)
184 {
185 	struct erofs_inode *vi, *vi_share;
186 	struct inode *realinode;
187 
188 	*need_iput = false;
189 	if (!erofs_is_ishare_inode(inode))
190 		return inode;
191 
192 	vi_share = EROFS_I(inode);
193 	spin_lock(&vi_share->ishare_lock);
194 	/* fetch any one as real inode */
195 	DBG_BUGON(list_empty(&vi_share->ishare_list));
196 	list_for_each_entry(vi, &vi_share->ishare_list, ishare_list) {
197 		realinode = igrab(&vi->vfs_inode);
198 		if (realinode) {
199 			*need_iput = true;
200 			break;
201 		}
202 	}
203 	spin_unlock(&vi_share->ishare_lock);
204 
205 	DBG_BUGON(!realinode);
206 	return realinode;
207 }
208 
209 int __init erofs_init_ishare(void)
210 {
211 	struct vfsmount *mnt;
212 	int ret;
213 
214 	mnt = kern_mount(&erofs_anon_fs_type);
215 	if (IS_ERR(mnt))
216 		return PTR_ERR(mnt);
217 	/* generic_fadvise() doesn't work if s_bdi == &noop_backing_dev_info */
218 	ret = super_setup_bdi(mnt->mnt_sb);
219 	if (ret)
220 		kern_unmount(mnt);
221 	else
222 		erofs_ishare_mnt = mnt;
223 	return ret;
224 }
225 
226 void erofs_exit_ishare(void)
227 {
228 	kern_unmount(erofs_ishare_mnt);
229 }
230