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