summaryrefslogtreecommitdiff
path: root/kernel/power
diff options
context:
space:
mode:
authorAndré Fabian Silva Delgado <emulatorman@parabola.nu>2016-04-23 04:02:05 -0300
committerAndré Fabian Silva Delgado <emulatorman@parabola.nu>2016-04-23 04:02:05 -0300
commit394569928e2f17dff4ae367ac700048138e318c7 (patch)
treec789d2a2d107284e78f6c6558267b6984f518581 /kernel/power
parentbdcfd44fb5b5fb8fd660e7f93f1095c507481024 (diff)
Linux-libre 4.5.2-gnupck-4.5.2-gnu
Diffstat (limited to 'kernel/power')
-rw-r--r--kernel/power/power.h3
-rw-r--r--kernel/power/tuxonice_bio.h2
-rw-r--r--kernel/power/tuxonice_bio_chains.c17
-rw-r--r--kernel/power/tuxonice_bio_core.c79
-rw-r--r--kernel/power/tuxonice_highlevel.c7
-rw-r--r--kernel/power/tuxonice_io.c28
-rw-r--r--kernel/power/tuxonice_io.h2
-rw-r--r--kernel/power/tuxonice_prepare_image.c15
-rw-r--r--kernel/power/tuxonice_prepare_image.h2
9 files changed, 86 insertions, 69 deletions
diff --git a/kernel/power/power.h b/kernel/power/power.h
index 2577c6d01..bf4d922b2 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -81,6 +81,7 @@ static struct kobj_attribute _name##_attr = { \
.store = _name##_store, \
}
+extern struct pbe *restore_pblist;
#define power_attr_ro(_name) \
static struct kobj_attribute _name##_attr = { \
.attr = { \
@@ -90,8 +91,6 @@ static struct kobj_attribute _name##_attr = { \
.show = _name##_show, \
}
-extern struct pbe *restore_pblist;
-
/* Preferred image size in bytes (default 500 MB) */
extern unsigned long image_size;
/* Size of memory reserved for drivers (default SPARE_PAGES x PAGE_SIZE) */
diff --git a/kernel/power/tuxonice_bio.h b/kernel/power/tuxonice_bio.h
index 9d52a3b69..2f717f5c5 100644
--- a/kernel/power/tuxonice_bio.h
+++ b/kernel/power/tuxonice_bio.h
@@ -76,3 +76,5 @@ struct toi_bio_allocator_ops {
void (*free_storage) (struct toi_bdev_info *);
unsigned long (*free_unused_storage) (struct toi_bdev_info *, unsigned long used);
};
+
+extern int toi_bio_register_storage(void);
diff --git a/kernel/power/tuxonice_bio_chains.c b/kernel/power/tuxonice_bio_chains.c
index 086a5527d..11cd37f77 100644
--- a/kernel/power/tuxonice_bio_chains.c
+++ b/kernel/power/tuxonice_bio_chains.c
@@ -924,11 +924,14 @@ static int apply_header_reservation(void)
return 0;
}
-static int toi_bio_register_storage(void)
+int toi_bio_register_storage(void)
{
int result = 0;
struct toi_module_ops *this_module;
+ toi_message(TOI_BIO, TOI_VERBOSE, 0, "toi_bio_allocate_storage: "
+ "Registering storage.");
+
list_for_each_entry(this_module, &toi_modules, module_list) {
if (!this_module->enabled ||
this_module->type != BIO_ALLOCATOR_MODULE)
@@ -962,16 +965,8 @@ int toi_bio_allocate_storage(unsigned long request)
int no_free = 0;
if (!chain) {
- int result = toi_bio_register_storage();
- toi_message(TOI_BIO, TOI_VERBOSE, 0, "toi_bio_allocate_storage: "
- "Registering storage.");
- if (result)
- return 0;
- chain = prio_chain_head;
- if (!chain) {
- printk("TuxOnIce: No storage was registered.\n");
- return 0;
- }
+ printk("TuxOnIce: No storage was registered.\n");
+ return 0;
}
toi_message(TOI_BIO, TOI_VERBOSE, 0, "toi_bio_allocate_storage: "
diff --git a/kernel/power/tuxonice_bio_core.c b/kernel/power/tuxonice_bio_core.c
index 87aa4c96e..bc27662d7 100644
--- a/kernel/power/tuxonice_bio_core.c
+++ b/kernel/power/tuxonice_bio_core.c
@@ -565,7 +565,7 @@ void debug_broken_header(void)
printk(KERN_DEBUG "Total used : %d (%ld pages).\n", total_header_bytes,
DIV_ROUND_UP(total_header_bytes, PAGE_SIZE));
printk(KERN_DEBUG "Space needed now : %ld.\n",
- get_header_storage_needed());
+ get_header_storage_needed(0));
dump_block_chains();
abort_hibernate(TOI_HEADER_TOO_BIG, "Header reservation too small.");
}
@@ -1389,6 +1389,11 @@ static int toi_bio_initialise(int starting_cycle)
if (result)
return result;
+ result = toi_bio_register_storage();
+
+ if (result)
+ return result;
+
return get_signature_page();
}
@@ -1875,47 +1880,47 @@ static struct toi_sysfs_data sysfs_params[] = {
};
struct toi_module_ops toi_blockwriter_ops = {
- .type = WRITER_MODULE,
- .name = "block i/o",
- .directory = "block_io",
- .module = THIS_MODULE,
- .memory_needed = toi_bio_memory_needed,
- .print_debug_info = toi_bio_print_debug_stats,
- .storage_needed = toi_bio_storage_needed,
- .save_config_info = toi_bio_save_config_info,
- .load_config_info = toi_bio_load_config_info,
- .initialise = toi_bio_initialise,
+ .type = WRITER_MODULE,
+ .name = "block i/o",
+ .directory = "block_io",
+ .module = THIS_MODULE,
+ .memory_needed = toi_bio_memory_needed,
+ .print_debug_info = toi_bio_print_debug_stats,
+ .storage_needed = toi_bio_storage_needed,
+ .save_config_info = toi_bio_save_config_info,
+ .load_config_info = toi_bio_load_config_info,
+ .initialise = toi_bio_initialise,
.cleanup = toi_bio_cleanup,
- .post_atomic_restore = toi_bio_chains_post_atomic,
+ .post_atomic_restore = toi_bio_chains_post_atomic,
.rw_init = toi_rw_init,
- .rw_cleanup = toi_rw_cleanup,
- .read_page = toi_bio_read_page,
- .write_page = toi_bio_write_page,
+ .rw_cleanup = toi_rw_cleanup,
+ .read_page = toi_bio_read_page,
+ .write_page = toi_bio_write_page,
.rw_header_chunk = toi_rw_header_chunk,
- .rw_header_chunk_noreadahead = toi_rw_header_chunk_noreadahead,
- .io_flusher = bio_io_flusher,
- .update_throughput_throttle = update_throughput_throttle,
- .finish_all_io = toi_finish_all_io,
-
- .noresume_reset = toi_bio_noresume_reset,
- .storage_available = toi_bio_storage_available,
- .storage_allocated = toi_bio_storage_allocated,
- .reserve_header_space = toi_bio_reserve_header_space,
- .allocate_storage = toi_bio_allocate_storage,
+ .rw_header_chunk_noreadahead = toi_rw_header_chunk_noreadahead,
+ .io_flusher = bio_io_flusher,
+ .update_throughput_throttle = update_throughput_throttle,
+ .finish_all_io = toi_finish_all_io,
+
+ .noresume_reset = toi_bio_noresume_reset,
+ .storage_available = toi_bio_storage_available,
+ .storage_allocated = toi_bio_storage_allocated,
+ .reserve_header_space = toi_bio_reserve_header_space,
+ .allocate_storage = toi_bio_allocate_storage,
.free_unused_storage = toi_bio_free_unused_storage,
- .image_exists = toi_bio_image_exists,
- .mark_resume_attempted = toi_bio_mark_resume_attempted,
- .write_header_init = toi_bio_write_header_init,
- .write_header_cleanup = toi_bio_write_header_cleanup,
- .read_header_init = toi_bio_read_header_init,
- .read_header_cleanup = toi_bio_read_header_cleanup,
- .get_header_version = toi_bio_get_header_version,
- .remove_image = toi_bio_remove_image,
- .parse_sig_location = toi_bio_parse_sig_location,
-
- .sysfs_data = sysfs_params,
- .num_sysfs_entries = sizeof(sysfs_params) /
+ .image_exists = toi_bio_image_exists,
+ .mark_resume_attempted = toi_bio_mark_resume_attempted,
+ .write_header_init = toi_bio_write_header_init,
+ .write_header_cleanup = toi_bio_write_header_cleanup,
+ .read_header_init = toi_bio_read_header_init,
+ .read_header_cleanup = toi_bio_read_header_cleanup,
+ .get_header_version = toi_bio_get_header_version,
+ .remove_image = toi_bio_remove_image,
+ .parse_sig_location = toi_bio_parse_sig_location,
+
+ .sysfs_data = sysfs_params,
+ .num_sysfs_entries = sizeof(sysfs_params) /
sizeof(struct toi_sysfs_data),
};
diff --git a/kernel/power/tuxonice_highlevel.c b/kernel/power/tuxonice_highlevel.c
index 16cf14cbc..1ef1f22b7 100644
--- a/kernel/power/tuxonice_highlevel.c
+++ b/kernel/power/tuxonice_highlevel.c
@@ -160,7 +160,8 @@ void toi_finish_anything(int hibernate_or_resume)
set_cpus_allowed_ptr(current, cpu_all_mask);
toi_alloc_print_debug_stats();
atomic_inc(&snapshot_device_available);
- unlock_system_sleep();
+ unlock_system_sleep();
+ release_super_lock();
}
set_fs(oldfs);
@@ -185,7 +186,8 @@ int toi_start_anything(int hibernate_or_resume)
toi_trace_index = 0;
if (hibernate_or_resume) {
- lock_system_sleep();
+ take_super_lock();
+ lock_system_sleep();
if (!atomic_add_unless(&snapshot_device_available, -1, 0))
goto snapshotdevice_unavailable;
@@ -230,6 +232,7 @@ prehibernate_err:
snapshotdevice_unavailable:
if (hibernate_or_resume)
mutex_unlock(&pm_mutex);
+ release_super_lock();
set_fs(oldfs);
mutex_unlock(&tuxonice_in_use);
return -EBUSY;
diff --git a/kernel/power/tuxonice_io.c b/kernel/power/tuxonice_io.c
index 3c62c2682..2db934350 100644
--- a/kernel/power/tuxonice_io.c
+++ b/kernel/power/tuxonice_io.c
@@ -1232,24 +1232,28 @@ static inline int save_fs_info(struct fs_info *fs, struct block_device *bdev)
return (!fs || IS_ERR(fs) || !fs->last_mount_size) ? 0 : 1;
}
-int fs_info_space_needed(void)
+int fs_info_space_needed(int reset)
{
- const struct super_block *sb;
- int result = sizeof(int);
+ static int last_result = 0;
+ const struct super_block *sb;
+ int result = sizeof(int);
+ if (!last_result || reset) {
list_for_each_entry(sb, &super_blocks, s_list) {
- struct fs_info *fs;
+ struct fs_info *fs;
- if (!sb->s_bdev)
- continue;
+ if (!sb->s_bdev)
+ continue;
- fs = fs_info_from_block_dev(sb->s_bdev);
- if (save_fs_info(fs, sb->s_bdev))
- result += 16 + sizeof(dev_t) + sizeof(int) +
- fs->last_mount_size;
- free_fs_info(fs);
+ fs = fs_info_from_block_dev(sb->s_bdev);
+ if (save_fs_info(fs, sb->s_bdev))
+ result += 16 + sizeof(dev_t) + sizeof(int) +
+ fs->last_mount_size;
+ free_fs_info(fs);
}
- return result;
+ last_result = result;
+ }
+ return result;
}
static int fs_info_num_to_save(void)
diff --git a/kernel/power/tuxonice_io.h b/kernel/power/tuxonice_io.h
index 683eab7a0..7d4d83f40 100644
--- a/kernel/power/tuxonice_io.h
+++ b/kernel/power/tuxonice_io.h
@@ -67,6 +67,6 @@ extern atomic_t toi_io_workers;
extern wait_queue_head_t toi_io_queue_flusher;
extern int toi_bio_queue_flusher_should_finish;
-int fs_info_space_needed(void);
+int fs_info_space_needed(int reset);
extern int toi_max_workers;
diff --git a/kernel/power/tuxonice_prepare_image.c b/kernel/power/tuxonice_prepare_image.c
index a10d62080..df37cc805 100644
--- a/kernel/power/tuxonice_prepare_image.c
+++ b/kernel/power/tuxonice_prepare_image.c
@@ -428,13 +428,18 @@ static unsigned long main_storage_needed(int use_ecr,
/*
* Storage needed for the image header, in bytes until the return.
+ *
+ * fs_info_space_needed is saved in a static variable unless we
+ * explicitly want to reset the value (done at the start of a cycle)
+ * as it requires memory allocation that may result in a hang if we're
+ * also trying to free memory.
*/
-unsigned long get_header_storage_needed(void)
+unsigned long get_header_storage_needed(int reset)
{
unsigned long bytes = sizeof(struct toi_header) +
toi_header_storage_for_modules() +
toi_pageflags_space_needed() +
- fs_info_space_needed();
+ fs_info_space_needed(0);
return DIV_ROUND_UP(bytes, PAGE_SIZE);
}
@@ -858,7 +863,7 @@ static void update_image(int ps2_recalc)
toiActiveAllocator->storage_allocated();
/* Need more header because more storage allocated? */
- header_storage_needed = get_header_storage_needed();
+ header_storage_needed = get_header_storage_needed(0);
} while (header_storage_needed > old_header_req);
@@ -1007,6 +1012,10 @@ int toi_prepare_image(void)
int result = 1, tries = 1;
main_storage_allocated = 0;
+
+ // Force recalculation of the amount of header storage needed for fs info.
+ fs_info_space_needed(1);
+
no_ps2_needed = 0;
if (attempt_to_freeze())
diff --git a/kernel/power/tuxonice_prepare_image.h b/kernel/power/tuxonice_prepare_image.h
index c1508975c..f7f2b695c 100644
--- a/kernel/power/tuxonice_prepare_image.h
+++ b/kernel/power/tuxonice_prepare_image.h
@@ -33,6 +33,6 @@ extern void free_attention_list(void);
#define ZONE_HIGHMEM (MAX_NR_ZONES + 1)
#endif
-unsigned long get_header_storage_needed(void);
+unsigned long get_header_storage_needed(int reset);
unsigned long any_to_free(int use_image_size_limit);
int try_allocate_extra_memory(void);