fs/erofs/inode.c

Source file repositories/reference/linux-study-clean/fs/erofs/inode.c

File Facts

System
Linux kernel
Corpus path
fs/erofs/inode.c
Extension
.c
Size
11046 bytes
Lines
399
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: implementation source
Status
source implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

if (unlikely(!inode->i_size || strlen(link) != inode->i_size)) {
			erofs_err(inode->i_sb, "invalid fast symlink size %llu @ nid %llu",
				  inode->i_size | 0ULL, vi->nid);
			kfree(link);
			return -EFSCORRUPTED;
		}
		inode_set_cached_link(inode, link, inode->i_size);
	}
	return 0;
}

static int erofs_read_inode(struct inode *inode)
{
	struct super_block *sb = inode->i_sb;
	erofs_blk_t blkaddr = erofs_blknr(sb, erofs_iloc(inode));
	unsigned int ofs = erofs_blkoff(sb, erofs_iloc(inode));
	bool in_mbox = erofs_inode_in_metabox(inode);
	struct erofs_buf buf = __EROFS_BUF_INITIALIZER;
	struct erofs_sb_info *sbi = EROFS_SB(sb);
	erofs_blk_t addrmask = BIT_ULL(48) - 1;
	struct erofs_inode *vi = EROFS_I(inode);
	struct erofs_inode_extended *die, copied;
	struct erofs_inode_compact *dic;
	unsigned int ifmt;
	void *ptr;
	int err = 0;

	ptr = erofs_read_metabuf(&buf, sb, erofs_pos(sb, blkaddr), in_mbox);
	if (IS_ERR(ptr)) {
		err = PTR_ERR(ptr);
		erofs_err(sb, "failed to read inode meta block (nid: %llu): %d",
			  vi->nid, err);
		goto err_out;
	}

	dic = ptr + ofs;
	ifmt = le16_to_cpu(dic->i_format);
	if (ifmt & ~EROFS_I_ALL) {
		erofs_err(sb, "unsupported i_format %u of nid %llu",
			  ifmt, vi->nid);
		err = -EOPNOTSUPP;
		goto err_out;
	}

	vi->datalayout = erofs_inode_datalayout(ifmt);
	if (vi->datalayout >= EROFS_INODE_DATALAYOUT_MAX) {
		erofs_err(sb, "unsupported datalayout %u of nid %llu",
			  vi->datalayout, vi->nid);
		err = -EOPNOTSUPP;
		goto err_out;
	}

	switch (erofs_inode_version(ifmt)) {
	case EROFS_INODE_LAYOUT_EXTENDED:
		vi->inode_isize = sizeof(struct erofs_inode_extended);
		/* check if the extended inode acrosses block boundary */
		if (ofs + vi->inode_isize <= sb->s_blocksize) {
			ofs += vi->inode_isize;
			die = (struct erofs_inode_extended *)dic;
			copied.i_u = die->i_u;
			copied.i_nb = die->i_nb;
		} else {
			const unsigned int gotten = sb->s_blocksize - ofs;

			memcpy(&copied, dic, gotten);
			ptr = erofs_read_metabuf(&buf, sb,
					erofs_pos(sb, blkaddr + 1), in_mbox);
			if (IS_ERR(ptr)) {
				err = PTR_ERR(ptr);
				erofs_err(sb, "failed to read inode payload block (nid: %llu): %d",
					  vi->nid, err);
				goto err_out;
			}
			ofs = vi->inode_isize - gotten;
			memcpy((u8 *)&copied + gotten, ptr, ofs);
			die = &copied;
		}
		vi->xattr_isize = erofs_xattr_ibody_size(die->i_xattr_icount);

		inode->i_mode = le16_to_cpu(die->i_mode);
		i_uid_write(inode, le32_to_cpu(die->i_uid));
		i_gid_write(inode, le32_to_cpu(die->i_gid));
		set_nlink(inode, le32_to_cpu(die->i_nlink));
		inode_set_mtime(inode, le64_to_cpu(die->i_mtime),
				le32_to_cpu(die->i_mtime_nsec));

		inode->i_size = le64_to_cpu(die->i_size);
		break;
	case EROFS_INODE_LAYOUT_COMPACT:
		vi->inode_isize = sizeof(struct erofs_inode_compact);

Annotation

Implementation Notes