[klibc] [PATCH] kinit
Volker Dormeyer
volker at ixolution.de
Fri Mar 12 22:04:01 PST 2004
Hello,
On Wed, Mar 10, 2004 at 10:28:30AM -0800,
H. Peter Anvin <hpa at zytor.com> wrote:
> Volker Dormeyer wrote:
> >try_name () determined "part" with minor 3 and "res" contained major 3.
> >Now, try_name () returned "6" and mknod () created /dev/root with
> >major 0 and minor 6. I did a left shift of 8 bits, to give mknod () an
> >appropriate 16 bit value of type dev_t.
>
> NO NO NO NO NO NO NO NO NO NO NO NO NO...
>
> First of all, dev_t is 32 bits not 16. Use makedev() to create one.
using makedev() works fine.
Here is another patch, which should solve the problem. This code was
mostly derived from a recent 2.6 kernel. The older code seemed to be
derived from an 2.5 kernel some time ago.
The patch changes the following:
* Determine the root device (major, minor) from sysfs
of recent 2.6.x kernels.
* It removes the pivot_root call, because it doesn't work
anymore in recent 2.6 kernels. It mounts the real root
over the ramfs root. But it does not contain a cleanup
of the ramfs.
Regards,
Volker
-------------- next part --------------
diff -upr klibc-0.115/kinit/do_mounts.c klibc-0.115_dev/kinit/do_mounts.c
--- klibc-0.115/kinit/do_mounts.c 2003-06-01 08:21:09.000000000 +0200
+++ klibc-0.115_dev/kinit/do_mounts.c 2004-03-12 21:31:34.000000000 +0100
@@ -17,8 +17,7 @@ static const char *progname = "VFS";
static const int do_devfs; // FIXME
/* Find dev_t for e.g. "hda,NULL" or "hdb,2" */
-static dev_t
-try_name(char *name, int part)
+static dev_t try_name(char *name, int part)
{
char path[BUF_SZ];
char buf[BUF_SZ];
@@ -27,34 +26,46 @@ try_name(char *name, int part)
char *s;
int len;
int fd;
+ int maj, min;
/* read device number from /sys/block/.../dev */
- snprintf(path, sizeof(path), "/sys/block/%s/dev", name);
+ sprintf(path, "/sys/block/%s/dev", name);
fd = open(path, 0, 0);
if (fd < 0)
goto fail;
len = read(fd, buf, BUF_SZ);
close(fd);
-
if (len <= 0 || len == BUF_SZ || buf[len - 1] != '\n')
goto fail;
buf[len - 1] = '\0';
- res = (dev_t) strtoul(buf, &s, 16);
- if (*s)
- goto fail;
+ if (sscanf(buf, "%u:%u", &maj, &min) == 2) {
+ /*
+ * Try the %u:%u format -- see print_dev_t()
+ */
+ res = makedev(maj, min);
+ if (maj != major(res) || min != minor(res))
+ goto fail;
+ } else {
+ /*
+ * Try old-style "0321"
+ */
+ res = (dev_t) strtoul(buf, &s, 16);
+ if (*s)
+ goto fail;
+ }
/* if it's there and we are not looking for a partition - that's it */
if (!part)
return res;
/* otherwise read range from .../range */
- snprintf(path, sizeof(path), "/sys/block/%s/range", name);
+ sprintf(path, "/sys/block/%s/range", name);
fd = open(path, 0, 0);
if (fd < 0)
goto fail;
- len = read(fd, buf, 32);
+ len = read(fd, buf, BUF_SZ);
close(fd);
- if (len <= 0 || len == 32 || buf[len - 1] != '\n')
+ if (len <= 0 || len == BUF_SZ || buf[len - 1] != '\n')
goto fail;
buf[len - 1] = '\0';
range = strtoul(buf, &s, 10);
@@ -73,7 +84,7 @@ fail:
* Convert a name into device number. We accept the following variants:
*
* 1) device number in hexadecimal represents itself
- * 2) /dev/nfs represents Root_NFS
+ * 2) /dev/nfs represents Root_NFS (0xff)
* 3) /dev/<disk_name> represents the device number of disk
* 4) /dev/<disk_name><decimal> represents the device number
* of partition - device number of disk plus the partition number
@@ -84,12 +95,11 @@ fail:
* Driverfs is used to check if something is a disk name - it has
* all known disks under bus/block/devices. If the disk name
* contains slashes, name of driverfs node has them replaced with
- * dots. try_name() does the actual checks, assuming that driverfs
+ * bangs. try_name() does the actual checks, assuming that driverfs
* is mounted on rootfs /sys.
*/
-static dev_t
-name_to_dev_t(const char *name)
+static dev_t name_to_dev_t(const char *name)
{
char *p;
dev_t res = 0;
@@ -97,9 +107,17 @@ name_to_dev_t(const char *name)
int part;
if (strncmp(name, "/dev/", 5) != 0) {
- res = (dev_t) strtoul(name, &p, 16);
- if (*p)
- goto fail;
+ int maj, min;
+
+ if (sscanf(name, "%u:%u", &maj, &min) == 2) {
+ res = makedev(maj, min);
+ if (maj != major(res) || min != minor(res))
+ goto fail;
+ } else {
+ res = (dev_t) strtoul(name, &p, 16);
+ if (*p)
+ goto fail;
+ }
goto done;
}
name += 5;
@@ -113,7 +131,7 @@ name_to_dev_t(const char *name)
for (p = s; *p; p++)
if (*p == '/')
- *p = '.';
+ *p = '!';
res = try_name(s, 0);
if (res)
goto done;
@@ -132,15 +150,14 @@ name_to_dev_t(const char *name)
goto fail;
p[-1] = '\0';
res = try_name(s, part);
- done:
+done:
return res;
- fail:
+fail:
res = (dev_t) 0;
goto done;
}
-static int
-find_in_devfs(char *path, dev_t dev)
+static int find_in_devfs(char *path, dev_t dev)
{
(void) path;
(void) dev;
@@ -190,8 +207,7 @@ find_in_devfs(char *path, dev_t dev)
}
/* Create the device node "name" */
-static int
-create_dev(const char *name, dev_t dev, const char *devfs_name)
+static int create_dev(const char *name, dev_t dev, const char *devfs_name)
{
char path[BUF_SZ];
@@ -217,8 +233,7 @@ create_dev(const char *name, dev_t dev,
}
/* get a list of all filesystems to try to mount root with */
-static void
-get_fs_names(int argc, char *argv[], char *buf)
+static void get_fs_names(int argc, char *argv[], char *buf)
{
char *s, *p;
char line[BUF_SZ];
@@ -255,8 +270,7 @@ get_fs_names(int argc, char *argv[], cha
}
/* mount the root filesystem from a block device */
-static int
-mount_block_root(int argc, char *argv[],
+static int mount_block_root(int argc, char *argv[],
dev_t root_dev, const char *root_dev_name, int flags)
{
char fs_names[BUF_SZ];
@@ -298,8 +312,7 @@ out:
return 0;
}
-int
-do_mounts(int argc, char *argv[])
+int do_mounts(int argc, char *argv[])
{
const char *root_dev_name = get_arg(argc, argv, "root=");
int flags = MS_RDONLY | MS_VERBOSE;
diff -upr klibc-0.115/kinit/kinit.c klibc-0.115_dev/kinit/kinit.c
--- klibc-0.115/kinit/kinit.c 2003-06-01 08:18:41.000000000 +0200
+++ klibc-0.115_dev/kinit/kinit.c 2004-03-12 21:26:26.000000000 +0100
@@ -182,7 +182,7 @@ char *get_arg(int argc, char *argv[], co
for (i = 1; i < argc; i++) {
if (argv[i] && strncmp(argv[i], name, len) == 0 &&
- (argv[i][len] == '\0')) {
+ (argv[i][len] != '\0')) {
ret = argv[i] + len;
break;
}
@@ -260,22 +260,18 @@ int main(int argc, char *argv[])
restore_cmdline(saved, cmdc, cmdv);
check_path("/root");
- check_path("/old_root");
do_mounts(cmdc, cmdv);
#ifndef INI_DEBUG
- if (pivot_root(".", "old_root") == -1) {
- perror("pivot_root");
- ret = 2;
- goto bail;
- }
-
if (mnt_procfs == 1)
umount2("/proc", 0);
if (mnt_sysfs == 1)
umount2("/sys", 0);
+ mount(".", "/", NULL, MS_MOVE, NULL);
+ chroot(".");
+
for (i = 1; i < cmdc; i++) {
if (strncmp(cmdv[i], "kinit=", 6) == 0) {
kinit = cmdv[i] + 6;
@@ -298,7 +294,7 @@ int main(int argc, char *argv[])
ret = 2;
goto done;
#else
- printf("%s: imagine pivot_root and exec\n", progname);
+ printf("%s: imagine mount, chroot and exec\n", progname);
#endif
bail:
More information about the klibc
mailing list