Check that RAM size is enough for ramdisk

Don't try to load ramdisk we don't have enough memory.
This commit is contained in:
Mikhail Efremov 2017-12-06 21:18:26 +03:00
parent a9374f376e
commit 7f50a883ac
7 changed files with 97 additions and 46 deletions

View File

@ -101,7 +101,7 @@ static enum return_type do_with_device(char * dev_name, char * dev_model)
log_message("found %s ISO9660 media, good news!", version);
if (IS_RESCUE) {
load_ramdisk(NULL);
load_ramdisk(NULL, 0);
umount(IMAGE_LOCATION);
}

View File

@ -18,11 +18,11 @@
#define _GNU_SOURCE 1
#include "version.h"
/* If we have more than that amount of memory (in Mbytes), we assume we can load the second stage as a ramdisk */
#define MEM_LIMIT_RAMDISK 124
/* If we have more than that amount of memory (in bytes), we assume we can load the second stage as a ramdisk */
#define MEM_LIMIT_RAMDISK (256 * 1024 * 1024)
/* If we have more than that amount of memory (in Mbytes), we assume we can load the rescue as a ramdisk */
#define MEM_LIMIT_RESCUE 56
/* If we have more than that amount of memory (in bytes), we assume we can load the rescue as a ramdisk */
#define MEM_LIMIT_RESCUE (128 * 1024 * 1024)
#define VERSION_FILE "/.VERSION"
#define RAMDISK_LOCATION "/"

49
disk.c
View File

@ -254,6 +254,8 @@ static enum return_type try_with_partition(char *choice)
struct stat statbuf;
int iso = 0;
char *ramdisk_path = NULL;
unsigned long ramdisk_size;
strcpy(device_fullname, "/dev/");
strcat(device_fullname, choice);
@ -271,8 +273,7 @@ static enum return_type try_with_partition(char *choice)
snprintf(buf, sizeof(buf), "Please enter the directory (or ISO image file) containing %s distribution.", version);
if (ask_from_entries_auto(buf, questions_location, &answers_location, 24, questions_location_auto, NULL) != RETURN_OK) {
umount(IMAGE_LOCATION);
return RETURN_ERROR;
goto err;
}
strcpy(location_full, IMAGE_LOCATION);
@ -283,49 +284,63 @@ static enum return_type try_with_partition(char *choice)
stg1_error_message("Directory or ISO image file could not be found on partition.\n"
"Here's a short extract of the files in the root of the partition:\n"
"%s", disk_extract_list_directory(IMAGE_LOCATION));
umount(IMAGE_LOCATION);
return RETURN_ERROR;
goto err;
}
if (!stat(location_full, &statbuf) && !S_ISDIR(statbuf.st_mode)) {
log_message("%s exists and is not a directory, assuming this is an ISO image", location_full);
if (lomount(location_full, IMAGE_LOCATION)) {
stg1_error_message("Could not mount file %s as an ISO image of the %s Distribution.", answers_location[0], version);
umount(IMAGE_LOCATION);
return RETURN_ERROR;
goto err;
}
iso = 1;
add_to_env("PIGGYBACK", "1");
}
if (access(get_ramdisk_path(iso ? NULL : location_full), R_OK)) {
ramdisk_path = get_ramdisk_path(iso ? NULL : location_full);
if (ramdisk_path == NULL) {
stg1_error_message("Could not get ramdisk path");
goto err;
}
if (access(ramdisk_path, R_OK)) {
stg1_error_message("I can't find the %s Distribution in the specified directory. "
"Here's a short extract of the files in the directory:\n"
"%s", version, disk_extract_list_directory(IMAGE_LOCATION));
loumount();
umount(IMAGE_LOCATION);
return RETURN_ERROR;
goto err;
}
if (stat(ramdisk_path, &statbuf)) {
stg1_error_message("Could not get ramdisk size: %s", strerror(errno));
goto err;
}
ramdisk_size = (unsigned long)statbuf.st_size;
log_message("found the %s Installation, good news!", version);
if (!IS_LOWMEM && ramdisk_possible()) {
if (load_ramdisk(iso ? NULL : location_full) != RETURN_OK) {
if (!IS_LOWMEM && ramdisk_possible(ramdisk_size)) {
if (load_ramdisk(ramdisk_path, ramdisk_size) != RETURN_OK) {
stg1_error_message("Could not load program into memory.");
loumount();
umount(IMAGE_LOCATION);
return RETURN_ERROR;
goto err;
}
} else {
do_losetup(LIVE_DEVICE, get_ramdisk_path(iso ? NULL : location_full));
do_losetup(LIVE_DEVICE, ramdisk_path);
my_mount(LIVE_DEVICE, STAGE2_LOCATION, (IS_LIVE) ? LIVEFS : STAGE2FS, 0);
}
free(ramdisk_path);
add_to_env("DEVICE", choice);
add_to_env("METHOD", strdup("disk"));
add_to_env("PREFIX", answers_location[0]);
return RETURN_OK;
err:
free(ramdisk_path);
loumount();
umount(IMAGE_LOCATION);
return RETURN_ERROR;
}
enum return_type disk_prepare(void)

View File

@ -765,9 +765,9 @@ enum return_type ftp_prepare(void)
enum return_type results;
update_splash("prepare");
if (!ramdisk_possible()) {
stg1_error_message("FTP install needs more than %d Mbytes of memory.",
MEM_LIMIT_RAMDISK);
if (!ramdisk_possible(MEM_LIMIT_RAMDISK)) {
stg1_error_message("FTP install needs more than %d Mbytes of memory (detected %u Mbytes).",
BYTES2MB(MEM_LIMIT_RAMDISK), BYTES2MB(total_memory()));
return RETURN_ERROR;
}
@ -857,9 +857,9 @@ enum return_type http_prepare(void)
update_splash("prepare");
if (!ramdisk_possible()) {
stg1_error_message("HTTP install needs more than %d Mbytes of memory.",
MEM_LIMIT_RAMDISK);
if (!ramdisk_possible(MEM_LIMIT_RAMDISK)) {
stg1_error_message("HTTP install needs more than %d Mbytes of memory (detected %u Mbytes).",
BYTES2MB(MEM_LIMIT_RAMDISK), BYTES2MB(total_memory()));
return RETURN_ERROR;
}

View File

@ -342,6 +342,12 @@ void stage1()
init_frontend(buf);
update_splash("init_frontend");
if (IS_RESCUE && !ramdisk_possible(MEM_LIMIT_RESCUE)) {
stg1_error_message("You are starting the rescue with a low memory configuration. "
"From that point, experience showed us that the program may stop "
"or crash at any point without immediate proper reason. Continue at "
"your own risk. Alternatively, you may reboot your system now.");
}
init = get_param_valued("init");
if (init)

56
tools.c
View File

@ -32,6 +32,7 @@
#include <sys/types.h>
#include <sys/mount.h>
#include <sys/poll.h>
#include <sys/sysinfo.h>
#include "stage1.h"
#include "log.h"
@ -196,11 +197,36 @@ int charstar_to_int(char * s)
return number;
}
int ramdisk_possible(void)
/* Returns total memory in bytes */
unsigned long total_memory(void)
{
struct sysinfo info;
unsigned long value;
if (sysinfo(&info)) {
log_message( "sysinfo: Can't get total memory: %s", strerror(errno));
return 0;
}
value = info.totalram * info.mem_unit;
return value;
}
int ramdisk_possible(unsigned long ramdisk_size)
{
unsigned long tm = total_memory();
log_message("Total Memory: %u Mbytes", BYTES2MB(tm));
/* Assume we need at least twice of ramdisk size */
if (total_memory() >= ramdisk_size * 2)
return 1;
else {
log_message("warning, ramdisk (%u Mb) is not possible due to low mem!", BYTES2MB(ramdisk_size));
return 0;
}
}
@ -234,7 +260,7 @@ static void save_stuff_for_rescue(void)
}
enum return_type load_ramdisk_fd(int source_fd, int size)
enum return_type load_ramdisk_fd(int source_fd, unsigned long size)
{
char * ramdisk = "/dev/ram3"; /* warning, verify that this file exists in the initrd, and that root=/dev/ram3 is actually passed to the kernel at boot time */
int ram_fd;
@ -251,7 +277,7 @@ enum return_type load_ramdisk_fd(int source_fd, int size)
return RETURN_ERROR;
}
init_progression(wait_msg, size);
init_progression(wait_msg, (int)size);
while ((actually = read(source_fd, buffer, sizeof(buffer))) > 0) {
seems_ok = 1;
@ -409,14 +435,12 @@ enum return_type verify_ramdisk_digest(const char *filename, const char *sha256_
return strcmp(computed_hash, sha256_hash) ? RETURN_ERROR : RETURN_OK;
}
enum return_type load_ramdisk(char *mount_path)
enum return_type load_ramdisk(char *ramdisk_path, unsigned long size)
{
int st2_fd;
struct stat statr;
char img_name[500];
char *img_name;
strcpy(img_name, mount_path ? mount_path : IMAGE_LOCATION);
strcat(img_name, get_ramdisk_realname());
img_name = ramdisk_path ?: get_ramdisk_path(NULL);
log_message("trying to load %s as a ramdisk", img_name);
@ -428,10 +452,14 @@ enum return_type load_ramdisk(char *mount_path)
return RETURN_ERROR;
}
if (stat(img_name, &statr))
return RETURN_ERROR;
else
return load_ramdisk_fd(st2_fd, statr.st_size);
if (size == 0) {
struct stat statr;
if (stat(img_name, &statr))
return RETURN_ERROR;
size = (unsigned long)statr.st_size;
}
return load_ramdisk_fd(st2_fd, size);
}
/* pixel's */

10
tools.h
View File

@ -29,11 +29,12 @@ int get_param(int i);
void set_param(int i);
void unset_param(int i);
int charstar_to_int(char * s);
int total_memory(void);
int ramdisk_possible(void);
/* Returns total memory in Kb */
unsigned long total_memory(void);
int ramdisk_possible(unsigned long ramdisk_size);
char * get_ramdisk_realname(void);
enum return_type load_ramdisk(char *);
enum return_type load_ramdisk_fd(int ramdisk_fd, int size);
enum return_type load_ramdisk(char *, unsigned long size);
enum return_type load_ramdisk_fd(int ramdisk_fd, unsigned long size);
void * memdup(void *src, size_t size);
void add_to_env(char * name, char * value);
void handle_env(char ** env);
@ -60,5 +61,6 @@ struct param_elem
#define ptr_begins_static_str(pointer,static_str) (!strncmp(pointer,static_str,sizeof(static_str)-1))
#define streq !strcmp
#define MKDEV(ma,mi) ((ma)<<8 | (mi))
#define BYTES2MB(b) ((unsigned int)(b)/1024/1024)
#endif