From owner-dev-commits-src-main@freebsd.org Fri May 7 07:09:48 2021 Return-Path: Delivered-To: dev-commits-src-main@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 1292B5F9EF3; Fri, 7 May 2021 07:09:48 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4Fc1mD00gVz3mdJ; Fri, 7 May 2021 07:09:48 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id E573026FB1; Fri, 7 May 2021 07:09:47 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 14779lRv058772; Fri, 7 May 2021 07:09:47 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 14779lLg058771; Fri, 7 May 2021 07:09:47 GMT (envelope-from git) Date: Fri, 7 May 2021 07:09:47 GMT Message-Id: <202105070709.14779lLg058771@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Fedor Uporov Subject: git: 1ed5f62d61ac - main - Add chr/blk devices support. MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: fsu X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 1ed5f62d61accf8c7a4d45e2e701a0179ff2fe1b Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-main@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commit messages for the main branch of the src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 07 May 2021 07:09:48 -0000 The branch main has been updated by fsu: URL: https://cgit.FreeBSD.org/src/commit/?id=1ed5f62d61accf8c7a4d45e2e701a0179ff2fe1b commit 1ed5f62d61accf8c7a4d45e2e701a0179ff2fe1b Author: Fedor Uporov AuthorDate: 2021-02-18 08:26:50 +0000 Commit: Fedor Uporov CommitDate: 2021-05-07 07:08:31 +0000 Add chr/blk devices support. The dev field is placed into the inode structure. The major/minor numbers conversion to/from linux compatile format happen during on-disk inodes writing/reading. Reviewed by: pfg MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D29930 --- sys/fs/ext2fs/ext2_inode.c | 3 +-- sys/fs/ext2fs/ext2_inode_cnv.c | 54 ++++++++++++++++++++++++++++++++++++++++-- sys/fs/ext2fs/ext2_vnops.c | 32 ++++++++++++++++--------- sys/fs/ext2fs/ext2fs.h | 7 ++++++ sys/fs/ext2fs/inode.h | 2 +- 5 files changed, 82 insertions(+), 16 deletions(-) diff --git a/sys/fs/ext2fs/ext2_inode.c b/sys/fs/ext2fs/ext2_inode.c index 34c32f2f113d..1412017b4b3c 100644 --- a/sys/fs/ext2fs/ext2_inode.c +++ b/sys/fs/ext2fs/ext2_inode.c @@ -605,8 +605,7 @@ ext2_inactive(struct vop_inactive_args *ap) if (ip->i_nlink <= 0) { ext2_extattr_free(ip); error = ext2_truncate(vp, (off_t)0, 0, NOCRED, td); - if (!(ip->i_flag & IN_E4EXTENTS)) - ip->i_rdev = 0; + ip->i_rdev = 0; mode = ip->i_mode; ip->i_mode = 0; ip->i_flag |= IN_CHANGE | IN_UPDATE; diff --git a/sys/fs/ext2fs/ext2_inode_cnv.c b/sys/fs/ext2fs/ext2_inode_cnv.c index bfa505896637..a71d5cef21aa 100644 --- a/sys/fs/ext2fs/ext2_inode_cnv.c +++ b/sys/fs/ext2fs/ext2_inode_cnv.c @@ -96,6 +96,42 @@ ext2_print_inode(struct inode *in) #define XTIME_TO_NSEC(x) ((le32toh(x) & EXT3_NSEC_MASK) >> 2) +static inline bool +ext2_old_valid_dev(dev_t dev) +{ + return (major(dev) < 256 && minor(dev) < 256); +} + +static inline uint16_t +ext2_old_encode_dev(dev_t dev) +{ + return ((major(dev) << 8) | minor(dev)); +} + +static inline dev_t +ext2_old_decode_dev(uint16_t val) +{ + return (makedev((val >> 8) & 255, val & 255)); +} + +static inline uint32_t +ext2_new_encode_dev(dev_t dev) +{ + unsigned maj = major(dev); + unsigned min = minor(dev); + + return ((min & 0xff) | (maj << 8) | ((min & ~0xff) << 12)); +} + +static inline dev_t +ext2_new_decode_dev(uint32_t dev) +{ + unsigned maj = (dev & 0xfff00) >> 8; + unsigned min = (dev & 0xff) | ((dev >> 12) & 0xfff00); + + return (makedev(maj, min)); +} + /* * raw ext2 inode LE to host inode conversion */ @@ -172,7 +208,12 @@ ext2_ei2i(struct ext2fs_dinode *ei, struct inode *ip) ip->i_uid |= (uint32_t)le16toh(ei->e2di_uid_high) << 16; ip->i_gid |= (uint32_t)le16toh(ei->e2di_gid_high) << 16; - if ((ip->i_flag & IN_E4EXTENTS)) { + if (S_ISCHR(ip->i_mode) || S_ISBLK(ip->i_mode)) { + if (ei->e2di_blocks[0]) + ip->i_rdev = ext2_old_decode_dev(le32toh(ei->e2di_blocks[0])); + else + ip->i_rdev = ext2_new_decode_dev(le32toh(ei->e2di_blocks[1])); + } else if ((ip->i_flag & IN_E4EXTENTS)) { memcpy(ip->i_data, ei->e2di_blocks, sizeof(ei->e2di_blocks)); } else { for (i = 0; i < EXT2_NDADDR; i++) @@ -247,7 +288,16 @@ ext2_i2ei(struct inode *ip, struct ext2fs_dinode *ei) ei->e2di_gid = htole16(ip->i_gid & 0xffff); ei->e2di_gid_high = htole16(ip->i_gid >> 16 & 0xffff); - if ((ip->i_flag & IN_E4EXTENTS)) { + if (S_ISCHR(ip->i_mode) || S_ISBLK(ip->i_mode)) { + if (ext2_old_valid_dev(ip->i_rdev)) { + ei->e2di_blocks[0] = htole32(ext2_old_encode_dev(ip->i_rdev)); + ei->e2di_blocks[1] = 0; + } else { + ei->e2di_blocks[0] = 0; + ei->e2di_blocks[1] = htole32(ext2_new_encode_dev(ip->i_rdev)); + ei->e2di_blocks[2] = 0; + } + } else if ((ip->i_flag & IN_E4EXTENTS)) { memcpy(ei->e2di_blocks, ip->i_data, sizeof(ei->e2di_blocks)); } else { for (i = 0; i < EXT2_NDADDR; i++) diff --git a/sys/fs/ext2fs/ext2_vnops.c b/sys/fs/ext2fs/ext2_vnops.c index 1ab360a7ad87..2721aa535b40 100644 --- a/sys/fs/ext2fs/ext2_vnops.c +++ b/sys/fs/ext2fs/ext2_vnops.c @@ -322,9 +322,6 @@ ext2_access(struct vop_access_args *ap) accmode_t accmode = ap->a_accmode; int error; - if (vp->v_type == VBLK || vp->v_type == VCHR) - return (EOPNOTSUPP); - /* * Disallow write attempts on read-only file systems; * unless the file is a socket, fifo, or a block or @@ -622,6 +619,18 @@ ext2_fsync(struct vop_fsync_args *ap) return (ext2_update(ap->a_vp, ap->a_waitfor == MNT_WAIT)); } +static int +ext2_check_mknod_limits(dev_t dev) +{ + unsigned maj = major(dev); + unsigned min = minor(dev); + + if (maj > EXT2_MAJOR_MAX || min > EXT2_MINOR_MAX) + return (EINVAL); + + return (0); +} + /* * Mknod vnode call */ @@ -635,20 +644,21 @@ ext2_mknod(struct vop_mknod_args *ap) ino_t ino; int error; + if (vap->va_rdev != VNOVAL) { + error = ext2_check_mknod_limits(vap->va_rdev); + if (error) + return (error); + } + error = ext2_makeinode(MAKEIMODE(vap->va_type, vap->va_mode), ap->a_dvp, vpp, ap->a_cnp); if (error) return (error); ip = VTOI(*vpp); ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE; - if (vap->va_rdev != VNOVAL) { - /* - * Want to be able to use this to make badblock - * inodes, so don't truncate the dev number. - */ - if (!(ip->i_flag & IN_E4EXTENTS)) - ip->i_rdev = vap->va_rdev; - } + if (vap->va_rdev != VNOVAL) + ip->i_rdev = vap->va_rdev; + /* * Remove inode, then reload it through VFS_VGET so it is * checked to see if it is an alias of an existing entry in diff --git a/sys/fs/ext2fs/ext2fs.h b/sys/fs/ext2fs/ext2fs.h index 81ff6838f16f..b11ccc0b5b5a 100644 --- a/sys/fs/ext2fs/ext2fs.h +++ b/sys/fs/ext2fs/ext2fs.h @@ -429,4 +429,11 @@ struct ext2_gd { #define EXT2_FIRST_INO(s) (le32toh((EXT2_SB(s)->e2fs->e2fs_rev) == \ E2FS_REV0) ? EXT2_FIRSTINO : le32toh(EXT2_SB(s)->e2fs->e2fs_first_ino)) +/* + * Linux major/minor values limits + */ +#define EXT2_MINORBITS (20) +#define EXT2_MAJOR_MAX (0xffffffff >> EXT2_MINORBITS) +#define EXT2_MINOR_MAX ((1 << EXT2_MINORBITS) - 1) + #endif /* !_FS_EXT2FS_EXT2FS_H_ */ diff --git a/sys/fs/ext2fs/inode.h b/sys/fs/ext2fs/inode.h index 2b9ec687a75c..e6af6ef8d5b6 100644 --- a/sys/fs/ext2fs/inode.h +++ b/sys/fs/ext2fs/inode.h @@ -110,6 +110,7 @@ struct inode { uint32_t i_gen; /* Generation number. */ uint64_t i_facl; /* EA block number. */ uint32_t i_flags; /* Status flags (chflags). */ + dev_t i_rdev; /* Major/minor inode values. */ union { struct { uint32_t i_db[EXT2_NDADDR]; /* Direct disk blocks. */ @@ -131,7 +132,6 @@ struct inode { * di_db area. */ #define i_shortlink i_db -#define i_rdev i_db[0] /* File permissions. */ #define IEXEC 0000100 /* Executable. */