📄 init.c
字号:
/* * iSCSI driver for Linux * Copyright (C) 2002 Cisco Systems, Inc. * maintained by linux-iscsi-devel@lists.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * See the file COPYING included with this distribution for more details. * * $Id: init.c,v 1.12 2005/01/11 03:47:11 mikenc Exp $ * */#include <stdint.h>#include <unistd.h>#include <sys/stat.h>#include <sys/fcntl.h>#include <sys/mount.h>#include <scsi/scsi.h>#include <linux/unistd.h>#include <errno.h>#include <dirent.h>#include "iscsi-sfnet.h"#include "iscsi-ioctl.h"#include "iscsi-network-boot.h"#define ISCSI_SYS_PATH(hostnum, val) \ sprintf(sysfs_file, "/sys/class/scsi_host/host%d/%s", hostnum, val)static inline _syscall2(int, pivot_root, const char *, one, const char *, two);static int varpart = 0, rootpart = 0; /* default value 0 indicate complete * disk instead of a partition. */int hostnum = -1;char sysfs_file[PATH_MAX];struct scsi_idlun { int dev_id; int host_unique_id;};struct device_info { int lun; int part;};static intscan_cmdline(void){ FILE *f; char line[512], buf[256], *res, *rbuf, *cp, *tmp = NULL; f = fopen("/proc/cmdline", "r"); if (!f) { printf("Cannot open control path to the driver"); exit(1); } rbuf = fgets(line, sizeof (buf), f); cp = strtok(rbuf, " "); do { sscanf(cp, "%s", buf); res = strchr(buf, '='); if (res) { *res = '\0'; tmp = res + 1; } if (strcasecmp(buf, "varpart") == 0) { varpart = atoi(tmp); } if (strcasecmp(buf, "rootpart") == 0) { rootpart = atoi(tmp); } cp = strtok(NULL, " "); } while (cp); fclose(f); return 0;}static intread_sysfs_file(char *sysfs_file){ int fd; char buf[20]; fd = open(sysfs_file, O_RDONLY); if (fd < 0) { printf("error in opening %s file\n", sysfs_file); return -1; } memset(buf, 0, sizeof(buf)); read(fd, buf, sizeof(buf)); if (!strncmp(buf, "iscsi-sfnet", 11)) { close(fd); return 1; } close(fd); return -1;}static voidwrite_sysfs_file(char *sysfs_file, char *cmd){ int fd; fd = open(sysfs_file, O_WRONLY); if (fd < 0) printf("error in opening %s file\n", sysfs_file); write(fd, cmd, strlen(cmd)); write(fd, "\n", 1); close(fd);}static voidgenerate_rootdev(int *rdev_id, struct device_info *info, char *devname){ struct scsi_idlun idlun; struct stat s; char fname[64], buf[8], ebuf[256]; int fd, in, i; memset(buf, 0, sizeof (buf)); for (i = 0; i <= 26; i++) { strcpy(fname, "/dev/sd"); if (info->part != 0) sprintf(buf, "%c%d", ('a' + (char) i), info->part); else sprintf(buf, "%c", ('a' + (char) i)); strcat(fname, buf); fd = open(fname, O_RDWR); if (fd < 0) { if (errno == EBUSY) { printf("%s : device busy\n", fname); continue; } else break; } if (ioctl(fd, SCSI_IOCTL_GET_IDLUN, &idlun) < 0) { sprintf(ebuf, "device %s failed on scsi ioctl, skip", fname); perror(ebuf); continue; } hostnum = idlun.dev_id >> 24 & 0xff; ISCSI_SYS_PATH(hostnum, "proc_name"); if ((read_sysfs_file(sysfs_file) > 0) && ((idlun.dev_id >> 8 & 0xff) == info->lun)) { in = open(fname, O_RDONLY); fstat(in, &s); *rdev_id = s.st_rdev; if (devname) strcpy(devname, fname); close(in); break; } } if (fd) close(fd);}static intmkdevices(char *prefix){ int fd, i, major, minor; char buf[32768], devName[128]; char old, *start, *chptr; if ((fd = open("/proc/partitions", O_RDONLY)) < 0) { printf("failed to open /proc/partitions: %d\n", errno); return 1; } i = read(fd, buf, sizeof (buf)); if (i < 1) { close(fd); printf("failed to read /proc/partitions: %d\n", errno); return 1; } buf[i] = '\0'; close(fd); start = strchr(buf, '\n'); if (start) { start++; start = strchr(buf, '\n'); } if (!start) return 1; start = start + 1; while (*start) { while (*start && isspace(*start)) start++; major = strtol(start, &chptr, 10); if (start != chptr) { start = chptr; while (*start && isspace(*start)) start++; minor = strtol(start, &chptr, 10); if (start != chptr) { start = chptr; while (*start && isspace(*start)) start++; while (*start && !isspace(*start)) start++; while (*start && isspace(*start)) start++; if (*start) { char *ptr, *deviceDir; int i; chptr = start; while (!isspace(*chptr)) chptr++; old = *chptr; *chptr = '\0'; sprintf(devName, "%s/%s", prefix, start); unlink(devName); ptr = devName; i = 0; while (*ptr) if (*ptr++ == '/') i++; if (i > 2) { deviceDir = alloca(strlen(devName) + 1); strcpy(deviceDir, devName); ptr = deviceDir + (strlen(devName) - 1); while (*ptr != '/') *ptr-- = '\0'; if (access(deviceDir, X_OK) && mkdir(deviceDir, 0644)) { printf("cannot create " "directory %s: " "%d\n", deviceDir, errno); } } if (mknod(devName, S_IFBLK | 0600, makedev(major, minor))) { printf("failed to create %s\n", devName); } *chptr = old; start = chptr; } } } start = strchr(start, '\n'); if (!*start) return 1; start = start + 1; } return 0;}static intwrite_device_number(int rdev){ FILE *f = NULL; char buf[10]; f = fopen("/proc/sys/kernel/real-root-dev", "w"); if (!f) { printf("Cannot open /proc/sys/kernel/real-root-dev\n"); return -1; } sprintf(buf, "0x%x", rdev); fprintf(f, buf, strlen(buf)); fclose(f); return 1;}static voidcreate_symlink(char *devname, int rootpart){ char *c, buf1[64], buf2[256], diskname[256]; int i, len; unlink("/sysroot/dev/inbpdisk"); if (rootpart != 0) { len = strlen(devname); c = devname; c += strlen(devname); c--; i = atoi(c); for (;;) { if (i == rootpart) { memset(diskname, 0, sizeof(diskname)); strncpy(diskname, devname, c-devname); break; } else { c--; i = atoi(c); } } } else { memset(diskname, 0, sizeof(diskname)); strcpy(diskname, devname); } symlink(diskname, "/sysroot/dev/inbpdisk"); for (i = 1; i < 16; i++) { sprintf(buf1, "/sysroot/dev/inbpdisk%d", i); unlink(buf1); sprintf(buf2, "%s%d", diskname, i); symlink(buf2, buf1); }}static voidgenerate_rootrc(char *rootfs, int lun){ int rdev_id = 0; unsigned long mf; char buf[256], devname[64]; struct device_info info = { lun: lun, part: rootpart, }; memset(devname, 0, sizeof (devname)); generate_rootdev(&rdev_id, &info, devname); if (rdev_id) { write_device_number(rdev_id); } if (mknod("/dev/root", S_IFBLK | 0700, rdev_id)) printf("mknod failed: %d\n", errno); write_device_number(256); mf = 0; mount("/dev/root", "/sysroot", rootfs, mf, NULL); sprintf(buf, "- - -"); ISCSI_SYS_PATH(hostnum, "scan"); write_sysfs_file(sysfs_file, buf); create_symlink(devname, rootpart); umount("/sysroot"); mf = 0; mf |= MS_RDONLY; mount("/dev/root", "/sysroot", rootfs, mf, NULL); if (pivot_root("/sysroot", "/sysroot/initrd")) printf("pivotroot: pivot_root(/sysroot, /sysroot/initrd) " "failed: %d\n", errno); umount("/initrd/proc"); umount("/initrd/sys");}intmain(int argc, char *argv[]){ char *rootfs = NULL; char *varfs = NULL; struct sapiNBP nbp; if (argc > 1) rootfs = argv[1]; if (argc > 2) varfs = argv[2]; scan_cmdline(); get_inbp_info(&nbp); while (!bring_up_network(&nbp)) { printf("iSCSI: Error in bringing up the network interface\n"); } establish_iscsi_network_boot_session(&nbp); mkdevices("/dev"); generate_rootrc(rootfs, nbp.slun); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -