From nobody Thu Jun 29 08:20:28 2023 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4QsBGP2vHLz4knXb; Thu, 29 Jun 2023 08:20:29 +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 4QsBGP1DRFz3vHW; Thu, 29 Jun 2023 08:20:29 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1688026829; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=1iv7gju3PTNTunH5ntJuhLEqftnG0tlaQ3NWr5bpD+U=; b=poi8CMRGpJ4UNZU+Q6NH5cXN+F1YQW55XPy2pnGuRbKZq4euW8iaqMkdFZqfpg3u8dsBGv nC8u9jISm6g4JCU5weUqguVtpy3O3mcwl60ru69S0Wpw3HnO6F9fIdGfGyLkAhS1Ou1oMS uZtJe4OR6y0wRVztLh4e4nlxb0knixNtQLQ11pem0R4ppguf9xHQhcj55NVHgRx8tjRAEa hu+KCuPTe+b2qyE/yqi3tJ7HzE3k+jAwRQQmuq++gmHVplPbtKSVYaDmOH6sXl1MzQiURZ DoxWC5dKXV7+eazuC6LKA8ANn9wfjuBiy70mQ5zn7eoqDVRMaAExSuTu0H2Ysg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1688026829; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=1iv7gju3PTNTunH5ntJuhLEqftnG0tlaQ3NWr5bpD+U=; b=RRswWdh1YiqFvKrNItyRlgH/HWu2jcRN1Qwxmr76q8zY/9xtC4yoMWEl1SVHbV/I2zgF4t Dlf9EdofmxyxPXuObCxKBtix0dLuyDWehAMxNsNjsDr+LHLcS2lGXCsx5cHK2THBz0bdPT jy2XIRwF/+I/kKSrqJV0UcTHc9RdFW45ZmIpObhxGgYGOjxeKtTMrybbRzKUzxWQbK6oY7 PaTsfD3vM//HIaZH3Flxwx5ghkHTOW+Ut0zodlkcUxbtRE6Iy3NlUB/SQ9J6/hvtLGdVVs n1s/Q1KVHItRFGgksWtT1sFUYv7KxwGWwX/q7LUJsEi/CasXw3QgOMLiTo88wQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1688026829; a=rsa-sha256; cv=none; b=Q0SCy0o3sTvTjhJAPnpNNy88kzYMpD5GoRBGQ+G0liaxGvAvBAkMLjOJ3FaHTPdQNd0jW9 Unc/ZJs97m/V7ri1ViFKE4uWpK16V3/NewKPhpmryXa1ErUcnCoIHndb8IeMdT7UhVIGym oILmtdK8cJrWw7543j5APfXurFsA4p88FCtE44uaI7bppW9/0XyQc+IKh0BlOy5KdLVN7m L47Y7t5ofJZAwwBt35KLeD9TU8MV0MOE4EUbeD0PKhftrt0JKgQ4dJM0o264hg8Zw+nZtj cC94Xq8pPfEUlZfX4ibE96GVS0J1tx3N4k5RdOYGnaTlTJdcHg/mW9v9sbaWTg== 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 4QsBGN6fYvz17gj; Thu, 29 Jun 2023 08:20:28 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.17.1/8.17.1) with ESMTP id 35T8KS9J083497; Thu, 29 Jun 2023 08:20:28 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.17.1/8.17.1/Submit) id 35T8KSEh083496; Thu, 29 Jun 2023 08:20:28 GMT (envelope-from git) Date: Thu, 29 Jun 2023 08:20:28 GMT Message-Id: <202306290820.35T8KSEh083496@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Dmitry Chagin Subject: git: 5e424fec72aa - stable/13 - linux(4): Uniformly dev_t arguments translation List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: dchagin X-Git-Repository: src X-Git-Refname: refs/heads/stable/13 X-Git-Reftype: branch X-Git-Commit: 5e424fec72aafe1154ae23cd0674193e757a4d2a Auto-Submitted: auto-generated X-ThisMailContainsUnwantedMimeParts: N The branch stable/13 has been updated by dchagin: URL: https://cgit.FreeBSD.org/src/commit/?id=5e424fec72aafe1154ae23cd0674193e757a4d2a commit 5e424fec72aafe1154ae23cd0674193e757a4d2a Author: Dmitry Chagin AuthorDate: 2023-04-28 08:55:05 +0000 Commit: Dmitry Chagin CommitDate: 2023-06-29 08:15:49 +0000 linux(4): Uniformly dev_t arguments translation The two main uses of dev_t are in struct stat and as a parameter of the mknod system calls. As of version 2.6.0 of the Linux kernel, dev_t is a 32-bit quantity with 12 bits set asaid for the major number and 20 for the minor number. The in-kernel dev_t encoded as MMMmmmmm, where M is a hex digit of the major number and m is a hex digit of the minor number. The user-space dev_t encoded as mmmM MMmm, where M and m is the major and minor numbers accordingly. This is downward compatible with legacy systems where dev_t is 16 bits wide, encoded as MMmm. In glibc dev_t is a 64-bit quantity, with 32-bit major and minor numbers, encoded as MMMM Mmmm mmmM MMmm. This is downward compatible with the Linux kernel and with legacy systems where dev_t is 16 bits wide. In the FreeBSD dev_t is a 64-bit quantity. The major and minor numbers are encoded as MMMmmmMm, therefore conversion of the device numbers between Linux user-space and FreeBSD kernel required. (cherry picked from commit 166e2e5a9e87d32dbfc7838903904673873f1e71) --- sys/compat/linux/linux.h | 68 ++++++++++++++++++++++++++++++++++++++++++ sys/compat/linux/linux_misc.c | 4 +-- sys/compat/linux/linux_stats.c | 49 ++++++++++++------------------ sys/compat/linux/linux_util.c | 3 +- 4 files changed, 91 insertions(+), 33 deletions(-) diff --git a/sys/compat/linux/linux.h b/sys/compat/linux/linux.h index 9061548399e4..bb70007cfc5b 100644 --- a/sys/compat/linux/linux.h +++ b/sys/compat/linux/linux.h @@ -33,6 +33,74 @@ */ typedef uint32_t l_dev_t; +/* + * Linux dev_t conversion routines. + * + * As of version 2.6.0 of the Linux kernel, dev_t is a 32-bit quantity + * with 12 bits set asaid for the major number and 20 for the minor number. + * The in-kernel dev_t encoded as MMMmmmmm, where M is a hex digit of the + * major number and m is a hex digit of the minor number. + * The user-space dev_t encoded as mmmM MMmm, where M and m is the major + * and minor numbers accordingly. This is downward compatible with legacy + * systems where dev_t is 16 bits wide, encoded as MMmm. + * In glibc dev_t is a 64-bit quantity, with 32-bit major and minor numbers, + * encoded as MMMM Mmmm mmmM MMmm. This is downward compatible with the Linux + * kernel and with legacy systems where dev_t is 16 bits wide. + * + * In the FreeBSD dev_t is a 64-bit quantity. The major and minor numbers + * are encoded as MMMmmmMm, therefore conversion of the device numbers between + * Linux user-space and FreeBSD kernel required. + */ +static __inline l_dev_t +linux_encode_dev(int _major, int _minor) +{ + + return ((_minor & 0xff) | ((_major & 0xfff) << 8) | + (((_minor & ~0xff) << 12) & 0xfff00000)); +} + +static __inline l_dev_t +linux_new_encode_dev(dev_t _dev) +{ + + return (_dev == NODEV ? 0 : linux_encode_dev(major(_dev), minor(_dev))); +} + +static __inline int +linux_encode_major(dev_t _dev) +{ + + return (_dev == NODEV ? 0 : major(_dev) & 0xfff); +} + +static __inline int +linux_encode_minor(dev_t _dev) +{ + + return (_dev == NODEV ? 0 : minor(_dev) & 0xfffff); +} + +static __inline int +linux_decode_major(l_dev_t _dev) +{ + + return ((_dev & 0xfff00) >> 8); +} + +static __inline int +linux_decode_minor(l_dev_t _dev) +{ + + return ((_dev & 0xff) | ((_dev & 0xfff00000) >> 12)); +} + +static __inline dev_t +linux_decode_dev(l_dev_t _dev) +{ + + return (makedev(linux_decode_major(_dev), linux_decode_minor(_dev))); +} + /* * Private Brandinfo flags */ diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c index ba0ac190a946..bc6ff9559493 100644 --- a/sys/compat/linux/linux_misc.c +++ b/sys/compat/linux/linux_misc.c @@ -901,7 +901,7 @@ linux_mknod(struct thread *td, struct linux_mknod_args *args) case S_IFCHR: case S_IFBLK: error = kern_mknodat(td, AT_FDCWD, path, seg, - args->mode, args->dev); + args->mode, linux_decode_dev(args->dev)); break; case S_IFDIR: @@ -956,7 +956,7 @@ linux_mknodat(struct thread *td, struct linux_mknodat_args *args) case S_IFCHR: case S_IFBLK: error = kern_mknodat(td, dfd, path, seg, args->mode, - args->dev); + linux_decode_dev(args->dev)); break; case S_IFDIR: diff --git a/sys/compat/linux/linux_stats.c b/sys/compat/linux/linux_stats.c index 07ef72706d75..a5c1949a4d28 100644 --- a/sys/compat/linux/linux_stats.c +++ b/sys/compat/linux/linux_stats.c @@ -57,6 +57,7 @@ __FBSDID("$FreeBSD$"); #include #endif +#include #include #include @@ -139,38 +140,19 @@ linux_kern_lstat(struct thread *td, const char *path, enum uio_seg pathseg, } #endif -/* - * l_dev_t has the same encoding as dev_t in the latter's low 16 bits, so - * truncation of a dev_t to 16 bits gives the same result as unpacking - * using major() and minor() and repacking in the l_dev_t format. This - * detail is hidden in dev_to_ldev(). Overflow in conversions of dev_t's - * are not checked for, as for other fields. - * - * dev_to_ldev() is only used for translating st_dev. When we convert - * st_rdev for copying it out, it isn't really a dev_t, but has already - * been translated to an l_dev_t in a nontrivial way. Translating it - * again would be illogical but would have no effect since the low 16 - * bits have the same encoding. - * - * The nontrivial translation for st_rdev renumbers some devices, but not - * ones that can be mounted on, so it is consistent with the translation - * for st_dev except when the renumbering or truncation causes conflicts. - */ -#define dev_to_ldev(d) ((uint16_t)(d)) - static int newstat_copyout(struct stat *buf, void *ubuf) { struct l_newstat tbuf; bzero(&tbuf, sizeof(tbuf)); - tbuf.st_dev = dev_to_ldev(buf->st_dev); + tbuf.st_dev = linux_new_encode_dev(buf->st_dev); tbuf.st_ino = buf->st_ino; tbuf.st_mode = buf->st_mode; tbuf.st_nlink = buf->st_nlink; tbuf.st_uid = buf->st_uid; tbuf.st_gid = buf->st_gid; - tbuf.st_rdev = buf->st_rdev; + tbuf.st_rdev = linux_new_encode_dev(buf->st_rdev); tbuf.st_size = buf->st_size; tbuf.st_atim.tv_sec = buf->st_atim.tv_sec; tbuf.st_atim.tv_nsec = buf->st_atim.tv_nsec; @@ -239,19 +221,27 @@ linux_newfstat(struct thread *td, struct linux_newfstat_args *args) } #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) + +static __inline uint16_t +linux_old_encode_dev(dev_t _dev) +{ + + return (_dev == NODEV ? 0 : linux_encode_dev(major(_dev), minor(_dev))); +} + static int old_stat_copyout(struct stat *buf, void *ubuf) { struct l_old_stat lbuf; bzero(&lbuf, sizeof(lbuf)); - lbuf.st_dev = dev_to_ldev(buf->st_dev); + lbuf.st_dev = linux_old_encode_dev(buf->st_dev); lbuf.st_ino = buf->st_ino; lbuf.st_mode = buf->st_mode; lbuf.st_nlink = buf->st_nlink; lbuf.st_uid = buf->st_uid; lbuf.st_gid = buf->st_gid; - lbuf.st_rdev = buf->st_rdev; + lbuf.st_rdev = linux_old_encode_dev(buf->st_rdev); lbuf.st_size = MIN(buf->st_size, INT32_MAX); lbuf.st_atim.tv_sec = buf->st_atim.tv_sec; lbuf.st_atim.tv_nsec = buf->st_atim.tv_nsec; @@ -550,13 +540,13 @@ stat64_copyout(struct stat *buf, void *ubuf) struct l_stat64 lbuf; bzero(&lbuf, sizeof(lbuf)); - lbuf.st_dev = dev_to_ldev(buf->st_dev); + lbuf.st_dev = linux_new_encode_dev(buf->st_dev); lbuf.st_ino = buf->st_ino; lbuf.st_mode = buf->st_mode; lbuf.st_nlink = buf->st_nlink; lbuf.st_uid = buf->st_uid; lbuf.st_gid = buf->st_gid; - lbuf.st_rdev = buf->st_rdev; + lbuf.st_rdev = linux_new_encode_dev(buf->st_rdev); lbuf.st_size = buf->st_size; lbuf.st_atim.tv_sec = buf->st_atim.tv_sec; lbuf.st_atim.tv_nsec = buf->st_atim.tv_nsec; @@ -762,11 +752,10 @@ statx_copyout(struct stat *buf, void *ubuf) tbuf.stx_ctime.tv_nsec = buf->st_ctim.tv_nsec; tbuf.stx_mtime.tv_sec = buf->st_mtim.tv_sec; tbuf.stx_mtime.tv_nsec = buf->st_mtim.tv_nsec; - - tbuf.stx_rdev_major = buf->st_rdev >> 8; - tbuf.stx_rdev_minor = buf->st_rdev & 0xff; - tbuf.stx_dev_major = buf->st_dev >> 8; - tbuf.stx_dev_minor = buf->st_dev & 0xff; + tbuf.stx_rdev_major = linux_encode_major(buf->st_rdev); + tbuf.stx_rdev_minor = linux_encode_minor(buf->st_rdev); + tbuf.stx_dev_major = linux_encode_major(buf->st_dev); + tbuf.stx_dev_minor = linux_encode_minor(buf->st_dev); return (copyout(&tbuf, ubuf, sizeof(tbuf))); } diff --git a/sys/compat/linux/linux_util.c b/sys/compat/linux/linux_util.c index 5995ac5e18af..498320937fd3 100644 --- a/sys/compat/linux/linux_util.c +++ b/sys/compat/linux/linux_util.c @@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$"); #include +#include #include #include #include @@ -248,7 +249,7 @@ translate_vnhook_major_minor(struct vnode *vp, struct stat *sb) sb->st_dev = rootdevmp->mnt_stat.f_fsid.val[0]; if (linux_vn_get_major_minor(vp, &major, &minor) == 0) - sb->st_rdev = (major << 8 | minor); + sb->st_rdev = makedev(major, minor); } char *