Commit 6b655223 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'erofs-for-6.7-rc3-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs

Pull erofs fixes from Gao Xiang:

 - Tidy up erofs_read_inode() for simplicity

 - Fix broken fscache mode due to NULL dereference of dif->bdev_handle

 - Add the EROFS webpage to MAINTAINERS, documentation, and Kconfig

* tag 'erofs-for-6.7-rc3-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs:
  MAINTAINERS: erofs: add EROFS webpage
  erofs: fix NULL dereference of dif->bdev_handle in fscache mode
  erofs: simplify erofs_read_inode()
parents 98b1cc82 62b241ef
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -91,6 +91,10 @@ compatibility checking tool (fsck.erofs), and a debugging tool (dump.erofs):

- git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs-utils.git

For more information, please also refer to the documentation site:

- https://erofs.docs.kernel.org

Bugs and patches are welcome, please kindly help us and send to the following
linux-erofs mailing list:

+1 −0
Original line number Diff line number Diff line
@@ -7855,6 +7855,7 @@ R: Yue Hu <huyue2@coolpad.com>
R:	Jeffle Xu <jefflexu@linux.alibaba.com>
L:	linux-erofs@lists.ozlabs.org
S:	Maintained
W:	https://erofs.docs.kernel.org
T:	git git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs.git
F:	Documentation/ABI/testing/sysfs-fs-erofs
F:	Documentation/filesystems/erofs.rst
+1 −1
Original line number Diff line number Diff line
@@ -21,7 +21,7 @@ config EROFS_FS
	  performance under extremely memory pressure without extra cost.

	  See the documentation at <file:Documentation/filesystems/erofs.rst>
	  for more details.
	  and the web pages at <https://erofs.docs.kernel.org> for more details.

	  If unsure, say N.

+3 −2
Original line number Diff line number Diff line
@@ -220,7 +220,7 @@ int erofs_map_dev(struct super_block *sb, struct erofs_map_dev *map)
			up_read(&devs->rwsem);
			return 0;
		}
		map->m_bdev = dif->bdev_handle->bdev;
		map->m_bdev = dif->bdev_handle ? dif->bdev_handle->bdev : NULL;
		map->m_daxdev = dif->dax_dev;
		map->m_dax_part_off = dif->dax_part_off;
		map->m_fscache = dif->fscache;
@@ -238,7 +238,8 @@ int erofs_map_dev(struct super_block *sb, struct erofs_map_dev *map)
			if (map->m_pa >= startoff &&
			    map->m_pa < startoff + length) {
				map->m_pa -= startoff;
				map->m_bdev = dif->bdev_handle->bdev;
				map->m_bdev = dif->bdev_handle ?
					      dif->bdev_handle->bdev : NULL;
				map->m_daxdev = dif->dax_dev;
				map->m_dax_part_off = dif->dax_part_off;
				map->m_fscache = dif->fscache;
+35 −63
Original line number Diff line number Diff line
@@ -15,11 +15,11 @@ static void *erofs_read_inode(struct erofs_buf *buf,
	struct erofs_sb_info *sbi = EROFS_SB(sb);
	struct erofs_inode *vi = EROFS_I(inode);
	const erofs_off_t inode_loc = erofs_iloc(inode);

	erofs_blk_t blkaddr, nblks = 0;
	void *kaddr;
	struct erofs_inode_compact *dic;
	struct erofs_inode_extended *die, *copied = NULL;
	union erofs_inode_i_u iu;
	unsigned int ifmt;
	int err;

@@ -35,9 +35,8 @@ static void *erofs_read_inode(struct erofs_buf *buf,

	dic = kaddr + *ofs;
	ifmt = le16_to_cpu(dic->i_format);

	if (ifmt & ~EROFS_I_ALL) {
		erofs_err(inode->i_sb, "unsupported i_format %u of nid %llu",
		erofs_err(sb, "unsupported i_format %u of nid %llu",
			  ifmt, vi->nid);
		err = -EOPNOTSUPP;
		goto err_out;
@@ -45,7 +44,7 @@ static void *erofs_read_inode(struct erofs_buf *buf,

	vi->datalayout = erofs_inode_datalayout(ifmt);
	if (vi->datalayout >= EROFS_INODE_DATALAYOUT_MAX) {
		erofs_err(inode->i_sb, "unsupported datalayout %u of nid %llu",
		erofs_err(sb, "unsupported datalayout %u of nid %llu",
			  vi->datalayout, vi->nid);
		err = -EOPNOTSUPP;
		goto err_out;
@@ -82,40 +81,15 @@ static void *erofs_read_inode(struct erofs_buf *buf,
		vi->xattr_isize = erofs_xattr_ibody_size(die->i_xattr_icount);

		inode->i_mode = le16_to_cpu(die->i_mode);
		switch (inode->i_mode & S_IFMT) {
		case S_IFREG:
		case S_IFDIR:
		case S_IFLNK:
			vi->raw_blkaddr = le32_to_cpu(die->i_u.raw_blkaddr);
			break;
		case S_IFCHR:
		case S_IFBLK:
			inode->i_rdev =
				new_decode_dev(le32_to_cpu(die->i_u.rdev));
			break;
		case S_IFIFO:
		case S_IFSOCK:
			inode->i_rdev = 0;
			break;
		default:
			goto bogusimode;
		}
		iu = die->i_u;
		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));

		/* extended inode has its own timestamp */
		/* each extended inode has its own timestamp */
		inode_set_ctime(inode, le64_to_cpu(die->i_mtime),
				le32_to_cpu(die->i_mtime_nsec));

		inode->i_size = le64_to_cpu(die->i_size);

		/* total blocks for compressed files */
		if (erofs_inode_is_data_compressed(vi->datalayout))
			nblks = le32_to_cpu(die->i_u.compressed_blocks);
		else if (vi->datalayout == EROFS_INODE_CHUNK_BASED)
			/* fill chunked inode summary info */
			vi->chunkformat = le16_to_cpu(die->i_u.c.format);
		kfree(copied);
		copied = NULL;
		break;
@@ -125,49 +99,51 @@ static void *erofs_read_inode(struct erofs_buf *buf,
		vi->xattr_isize = erofs_xattr_ibody_size(dic->i_xattr_icount);

		inode->i_mode = le16_to_cpu(dic->i_mode);
		iu = dic->i_u;
		i_uid_write(inode, le16_to_cpu(dic->i_uid));
		i_gid_write(inode, le16_to_cpu(dic->i_gid));
		set_nlink(inode, le16_to_cpu(dic->i_nlink));
		/* use build time for compact inodes */
		inode_set_ctime(inode, sbi->build_time, sbi->build_time_nsec);

		inode->i_size = le32_to_cpu(dic->i_size);
		break;
	default:
		erofs_err(sb, "unsupported on-disk inode version %u of nid %llu",
			  erofs_inode_version(ifmt), vi->nid);
		err = -EOPNOTSUPP;
		goto err_out;
	}

	switch (inode->i_mode & S_IFMT) {
	case S_IFREG:
	case S_IFDIR:
	case S_IFLNK:
			vi->raw_blkaddr = le32_to_cpu(dic->i_u.raw_blkaddr);
		vi->raw_blkaddr = le32_to_cpu(iu.raw_blkaddr);
		break;
	case S_IFCHR:
	case S_IFBLK:
			inode->i_rdev =
				new_decode_dev(le32_to_cpu(dic->i_u.rdev));
		inode->i_rdev = new_decode_dev(le32_to_cpu(iu.rdev));
		break;
	case S_IFIFO:
	case S_IFSOCK:
		inode->i_rdev = 0;
		break;
	default:
			goto bogusimode;
		}
		i_uid_write(inode, le16_to_cpu(dic->i_uid));
		i_gid_write(inode, le16_to_cpu(dic->i_gid));
		set_nlink(inode, le16_to_cpu(dic->i_nlink));

		/* use build time for compact inodes */
		inode_set_ctime(inode, sbi->build_time, sbi->build_time_nsec);

		inode->i_size = le32_to_cpu(dic->i_size);
		if (erofs_inode_is_data_compressed(vi->datalayout))
			nblks = le32_to_cpu(dic->i_u.compressed_blocks);
		else if (vi->datalayout == EROFS_INODE_CHUNK_BASED)
			vi->chunkformat = le16_to_cpu(dic->i_u.c.format);
		break;
	default:
		erofs_err(inode->i_sb,
			  "unsupported on-disk inode version %u of nid %llu",
			  erofs_inode_version(ifmt), vi->nid);
		err = -EOPNOTSUPP;
		erofs_err(sb, "bogus i_mode (%o) @ nid %llu", inode->i_mode,
			  vi->nid);
		err = -EFSCORRUPTED;
		goto err_out;
	}

	if (vi->datalayout == EROFS_INODE_CHUNK_BASED) {
	/* total blocks for compressed files */
	if (erofs_inode_is_data_compressed(vi->datalayout)) {
		nblks = le32_to_cpu(iu.compressed_blocks);
	} else if (vi->datalayout == EROFS_INODE_CHUNK_BASED) {
		/* fill chunked inode summary info */
		vi->chunkformat = le16_to_cpu(iu.c.format);
		if (vi->chunkformat & ~EROFS_CHUNK_FORMAT_ALL) {
			erofs_err(inode->i_sb,
				  "unsupported chunk format %x of nid %llu",
			erofs_err(sb, "unsupported chunk format %x of nid %llu",
				  vi->chunkformat, vi->nid);
			err = -EOPNOTSUPP;
			goto err_out;
@@ -191,10 +167,6 @@ static void *erofs_read_inode(struct erofs_buf *buf,
		inode->i_blocks = nblks << (sb->s_blocksize_bits - 9);
	return kaddr;

bogusimode:
	erofs_err(inode->i_sb, "bogus i_mode (%o) @ nid %llu",
		  inode->i_mode, vi->nid);
	err = -EFSCORRUPTED;
err_out:
	DBG_BUGON(1);
	kfree(copied);