1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2017-2018 HUAWEI, Inc. 4 * https://www.huawei.com/ 5 * Created by Gao Xiang <gaoxiang25@huawei.com> 6 */ 7 #include "xattr.h" 8 9 #include <trace/events/erofs.h> 10 11 /* 12 * if inode is successfully read, return its inode page (or sometimes 13 * the inode payload page if it's an extended inode) in order to fill 14 * inline data if possible. 15 */ 16 static struct page *erofs_read_inode(struct inode *inode, 17 unsigned int *ofs) 18 { 19 struct super_block *sb = inode->i_sb; 20 struct erofs_sb_info *sbi = EROFS_SB(sb); 21 struct erofs_inode *vi = EROFS_I(inode); 22 const erofs_off_t inode_loc = iloc(sbi, vi->nid); 23 24 erofs_blk_t blkaddr, nblks = 0; 25 struct page *page; 26 struct erofs_inode_compact *dic; 27 struct erofs_inode_extended *die, *copied = NULL; 28 unsigned int ifmt; 29 int err; 30 31 blkaddr = erofs_blknr(inode_loc); 32 *ofs = erofs_blkoff(inode_loc); 33 34 erofs_dbg("%s, reading inode nid %llu at %u of blkaddr %u", 35 __func__, vi->nid, *ofs, blkaddr); 36 37 page = erofs_get_meta_page(sb, blkaddr); 38 if (IS_ERR(page)) { 39 erofs_err(sb, "failed to get inode (nid: %llu) page, err %ld", 40 vi->nid, PTR_ERR(page)); 41 return page; 42 } 43 44 dic = page_address(page) + *ofs; 45 ifmt = le16_to_cpu(dic->i_format); 46 47 if (ifmt & ~EROFS_I_ALL) { 48 erofs_err(inode->i_sb, "unsupported i_format %u of nid %llu", 49 ifmt, vi->nid); 50 err = -EOPNOTSUPP; 51 goto err_out; 52 } 53 54 vi->datalayout = erofs_inode_datalayout(ifmt); 55 if (vi->datalayout >= EROFS_INODE_DATALAYOUT_MAX) { 56 erofs_err(inode->i_sb, "unsupported datalayout %u of nid %llu", 57 vi->datalayout, vi->nid); 58 err = -EOPNOTSUPP; 59 goto err_out; 60 } 61 62 switch (erofs_inode_version(ifmt)) { 63 case EROFS_INODE_LAYOUT_EXTENDED: 64 vi->inode_isize = sizeof(struct erofs_inode_extended); 65 /* check if the inode acrosses page boundary */ 66 if (*ofs + vi->inode_isize <= PAGE_SIZE) { 67 *ofs += vi->inode_isize; 68 die = (struct erofs_inode_extended *)dic; 69 } else { 70 const unsigned int gotten = PAGE_SIZE - *ofs; 71 72 copied = kmalloc(vi->inode_isize, GFP_NOFS); 73 if (!copied) { 74 err = -ENOMEM; 75 goto err_out; 76 } 77 memcpy(copied, dic, gotten); 78 unlock_page(page); 79 put_page(page); 80 81 page = erofs_get_meta_page(sb, blkaddr + 1); 82 if (IS_ERR(page)) { 83 erofs_err(sb, "failed to get inode payload page (nid: %llu), err %ld", 84 vi->nid, PTR_ERR(page)); 85 kfree(copied); 86 return page; 87 } 88 *ofs = vi->inode_isize - gotten; 89 memcpy((u8 *)copied + gotten, page_address(page), *ofs); 90 die = copied; 91 } 92 vi->xattr_isize = erofs_xattr_ibody_size(die->i_xattr_icount); 93 94 inode->i_mode = le16_to_cpu(die->i_mode); 95 switch (inode->i_mode & S_IFMT) { 96 case S_IFREG: 97 case S_IFDIR: 98 case S_IFLNK: 99 vi->raw_blkaddr = le32_to_cpu(die->i_u.raw_blkaddr); 100 break; 101 case S_IFCHR: 102 case S_IFBLK: 103 inode->i_rdev = 104 new_decode_dev(le32_to_cpu(die->i_u.rdev)); 105 break; 106 case S_IFIFO: 107 case S_IFSOCK: 108 inode->i_rdev = 0; 109 break; 110 default: 111 goto bogusimode; 112 } 113 i_uid_write(inode, le32_to_cpu(die->i_uid)); 114 i_gid_write(inode, le32_to_cpu(die->i_gid)); 115 set_nlink(inode, le32_to_cpu(die->i_nlink)); 116 117 /* extended inode has its own timestamp */ 118 inode->i_ctime.tv_sec = le64_to_cpu(die->i_ctime); 119 inode->i_ctime.tv_nsec = le32_to_cpu(die->i_ctime_nsec); 120 121 inode->i_size = le64_to_cpu(die->i_size); 122 123 /* total blocks for compressed files */ 124 if (erofs_inode_is_data_compressed(vi->datalayout)) 125 nblks = le32_to_cpu(die->i_u.compressed_blocks); 126 127 kfree(copied); 128 break; 129 case EROFS_INODE_LAYOUT_COMPACT: 130 vi->inode_isize = sizeof(struct erofs_inode_compact); 131 *ofs += vi->inode_isize; 132 vi->xattr_isize = erofs_xattr_ibody_size(dic->i_xattr_icount); 133 134 inode->i_mode = le16_to_cpu(dic->i_mode); 135 switch (inode->i_mode & S_IFMT) { 136 case S_IFREG: 137 case S_IFDIR: 138 case S_IFLNK: 139 vi->raw_blkaddr = le32_to_cpu(dic->i_u.raw_blkaddr); 140 break; 141 case S_IFCHR: 142 case S_IFBLK: 143 inode->i_rdev = 144 new_decode_dev(le32_to_cpu(dic->i_u.rdev)); 145 break; 146 case S_IFIFO: 147 case S_IFSOCK: 148 inode->i_rdev = 0; 149 break; 150 default: 151 goto bogusimode; 152 } 153 i_uid_write(inode, le16_to_cpu(dic->i_uid)); 154 i_gid_write(inode, le16_to_cpu(dic->i_gid)); 155 set_nlink(inode, le16_to_cpu(dic->i_nlink)); 156 157 /* use build time for compact inodes */ 158 inode->i_ctime.tv_sec = sbi->build_time; 159 inode->i_ctime.tv_nsec = sbi->build_time_nsec; 160 161 inode->i_size = le32_to_cpu(dic->i_size); 162 if (erofs_inode_is_data_compressed(vi->datalayout)) 163 nblks = le32_to_cpu(dic->i_u.compressed_blocks); 164 break; 165 default: 166 erofs_err(inode->i_sb, 167 "unsupported on-disk inode version %u of nid %llu", 168 erofs_inode_version(ifmt), vi->nid); 169 err = -EOPNOTSUPP; 170 goto err_out; 171 } 172 173 inode->i_mtime.tv_sec = inode->i_ctime.tv_sec; 174 inode->i_atime.tv_sec = inode->i_ctime.tv_sec; 175 inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec; 176 inode->i_atime.tv_nsec = inode->i_ctime.tv_nsec; 177 178 if (!nblks) 179 /* measure inode.i_blocks as generic filesystems */ 180 inode->i_blocks = roundup(inode->i_size, EROFS_BLKSIZ) >> 9; 181 else 182 inode->i_blocks = nblks << LOG_SECTORS_PER_BLOCK; 183 return page; 184 185 bogusimode: 186 erofs_err(inode->i_sb, "bogus i_mode (%o) @ nid %llu", 187 inode->i_mode, vi->nid); 188 err = -EFSCORRUPTED; 189 err_out: 190 DBG_BUGON(1); 191 kfree(copied); 192 unlock_page(page); 193 put_page(page); 194 return ERR_PTR(err); 195 } 196 197 static int erofs_fill_symlink(struct inode *inode, void *data, 198 unsigned int m_pofs) 199 { 200 struct erofs_inode *vi = EROFS_I(inode); 201 char *lnk; 202 203 /* if it cannot be handled with fast symlink scheme */ 204 if (vi->datalayout != EROFS_INODE_FLAT_INLINE || 205 inode->i_size >= PAGE_SIZE) { 206 inode->i_op = &erofs_symlink_iops; 207 return 0; 208 } 209 210 lnk = kmalloc(inode->i_size + 1, GFP_KERNEL); 211 if (!lnk) 212 return -ENOMEM; 213 214 m_pofs += vi->xattr_isize; 215 /* inline symlink data shouldn't cross page boundary as well */ 216 if (m_pofs + inode->i_size > PAGE_SIZE) { 217 kfree(lnk); 218 erofs_err(inode->i_sb, 219 "inline data cross block boundary @ nid %llu", 220 vi->nid); 221 DBG_BUGON(1); 222 return -EFSCORRUPTED; 223 } 224 225 memcpy(lnk, data + m_pofs, inode->i_size); 226 lnk[inode->i_size] = '\0'; 227 228 inode->i_link = lnk; 229 inode->i_op = &erofs_fast_symlink_iops; 230 return 0; 231 } 232 233 static int erofs_fill_inode(struct inode *inode, int isdir) 234 { 235 struct erofs_inode *vi = EROFS_I(inode); 236 struct page *page; 237 unsigned int ofs; 238 int err = 0; 239 240 trace_erofs_fill_inode(inode, isdir); 241 242 /* read inode base data from disk */ 243 page = erofs_read_inode(inode, &ofs); 244 if (IS_ERR(page)) 245 return PTR_ERR(page); 246 247 /* setup the new inode */ 248 switch (inode->i_mode & S_IFMT) { 249 case S_IFREG: 250 inode->i_op = &erofs_generic_iops; 251 inode->i_fop = &generic_ro_fops; 252 break; 253 case S_IFDIR: 254 inode->i_op = &erofs_dir_iops; 255 inode->i_fop = &erofs_dir_fops; 256 break; 257 case S_IFLNK: 258 err = erofs_fill_symlink(inode, page_address(page), ofs); 259 if (err) 260 goto out_unlock; 261 inode_nohighmem(inode); 262 break; 263 case S_IFCHR: 264 case S_IFBLK: 265 case S_IFIFO: 266 case S_IFSOCK: 267 inode->i_op = &erofs_generic_iops; 268 init_special_inode(inode, inode->i_mode, inode->i_rdev); 269 goto out_unlock; 270 default: 271 err = -EFSCORRUPTED; 272 goto out_unlock; 273 } 274 275 if (erofs_inode_is_data_compressed(vi->datalayout)) { 276 err = z_erofs_fill_inode(inode); 277 goto out_unlock; 278 } 279 inode->i_mapping->a_ops = &erofs_raw_access_aops; 280 281 out_unlock: 282 unlock_page(page); 283 put_page(page); 284 return err; 285 } 286 287 /* 288 * erofs nid is 64bits, but i_ino is 'unsigned long', therefore 289 * we should do more for 32-bit platform to find the right inode. 290 */ 291 static int erofs_ilookup_test_actor(struct inode *inode, void *opaque) 292 { 293 const erofs_nid_t nid = *(erofs_nid_t *)opaque; 294 295 return EROFS_I(inode)->nid == nid; 296 } 297 298 static int erofs_iget_set_actor(struct inode *inode, void *opaque) 299 { 300 const erofs_nid_t nid = *(erofs_nid_t *)opaque; 301 302 inode->i_ino = erofs_inode_hash(nid); 303 return 0; 304 } 305 306 static inline struct inode *erofs_iget_locked(struct super_block *sb, 307 erofs_nid_t nid) 308 { 309 const unsigned long hashval = erofs_inode_hash(nid); 310 311 return iget5_locked(sb, hashval, erofs_ilookup_test_actor, 312 erofs_iget_set_actor, &nid); 313 } 314 315 struct inode *erofs_iget(struct super_block *sb, 316 erofs_nid_t nid, 317 bool isdir) 318 { 319 struct inode *inode = erofs_iget_locked(sb, nid); 320 321 if (!inode) 322 return ERR_PTR(-ENOMEM); 323 324 if (inode->i_state & I_NEW) { 325 int err; 326 struct erofs_inode *vi = EROFS_I(inode); 327 328 vi->nid = nid; 329 330 err = erofs_fill_inode(inode, isdir); 331 if (!err) 332 unlock_new_inode(inode); 333 else { 334 iget_failed(inode); 335 inode = ERR_PTR(err); 336 } 337 } 338 return inode; 339 } 340 341 int erofs_getattr(struct user_namespace *mnt_userns, const struct path *path, 342 struct kstat *stat, u32 request_mask, 343 unsigned int query_flags) 344 { 345 struct inode *const inode = d_inode(path->dentry); 346 347 if (erofs_inode_is_data_compressed(EROFS_I(inode)->datalayout)) 348 stat->attributes |= STATX_ATTR_COMPRESSED; 349 350 stat->attributes |= STATX_ATTR_IMMUTABLE; 351 stat->attributes_mask |= (STATX_ATTR_COMPRESSED | 352 STATX_ATTR_IMMUTABLE); 353 354 generic_fillattr(&init_user_ns, inode, stat); 355 return 0; 356 } 357 358 const struct inode_operations erofs_generic_iops = { 359 .getattr = erofs_getattr, 360 .listxattr = erofs_listxattr, 361 .get_acl = erofs_get_acl, 362 }; 363 364 const struct inode_operations erofs_symlink_iops = { 365 .get_link = page_get_link, 366 .getattr = erofs_getattr, 367 .listxattr = erofs_listxattr, 368 .get_acl = erofs_get_acl, 369 }; 370 371 const struct inode_operations erofs_fast_symlink_iops = { 372 .get_link = simple_get_link, 373 .getattr = erofs_getattr, 374 .listxattr = erofs_listxattr, 375 .get_acl = erofs_get_acl, 376 }; 377 378