Skip to content

Commit

Permalink
Moved temporary file hardlinking to the shutdown phase, but it does n…
Browse files Browse the repository at this point in the history
…ot work there yet.

It seems that the hardlink file is getting deleted once the journal log is replayed, or the fsck runs and etc, so the code does not actually work.
  • Loading branch information
msiniavine committed Mar 23, 2012
1 parent e77a578 commit 4b3032a
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 31 deletions.
89 changes: 86 additions & 3 deletions arch/x86/kernel/save_state.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include <net/af_unix.h>
#include <linux/kprobes.h>
#include <linux/kallsyms.h>
#include <linux/hash.h>

#include <linux/set_state.h>

Expand Down Expand Up @@ -873,6 +874,81 @@ static void save_fs(struct fs_struct* fs, struct saved_task_struct* task, struct

}

#define TMP_FILE_MAP_SIZE 64
#define TMP_FILE_MAP_BITS 6
struct tmp_file_chain
{
struct hlist_node chain;
struct file* file;
};
static struct hlist_head tmp_file_map[TMP_FILE_MAP_SIZE];
static int saving_temp_files = 0;

void hardlink_temp_file(const char* name, unsigned long ino);

static void save_temp_files(struct task_struct* task)
{
unsigned int fd;
struct fdtable* fdt;
char name[PATH_LENGTH];
struct task_struct* child;

// spin_lock(&task->files->file_lock);
fdt = files_fdtable(task->files);

for(fd=0; fd<fdt->max_fds; fd++)
{
struct tmp_file_chain* chain;
struct file* f = fcheck_files(task->files, fd);

if(f == NULL)
continue;

if(f->f_dentry->d_inode->i_nlink != 0) continue;

get_path_absolute(f, name);
hardlink_temp_file(name, f->f_dentry->d_inode->i_ino);

chain = kmalloc(sizeof(*chain), GFP_KERNEL);
INIT_HLIST_NODE(&chain->chain);
chain->file = f;

hlist_add_head(&chain->chain, &tmp_file_map[hash_ptr(f, TMP_FILE_MAP_BITS)]);
}

// spin_unlock(&task->files->file_lock);

list_for_each_entry(child, &task->children, sibling)
{
save_temp_files(child);
}
}

void hardlink_temp_files(void)
{
struct task_struct* task;
int i;

for(i=0; i<TMP_FILE_MAP_SIZE; i++)
{
INIT_HLIST_HEAD(&tmp_file_map[i]);
}
saving_temp_files = 1;

read_lock(&tasklist_lock);

for_each_process(task)
{
if(!is_save_enabled(task)) continue;

save_temp_files(task);

}

read_unlock(&tasklist_lock);
}


int save_state_mutex_debug = 0;
int do_path_lookup(int dfd, const char *name,
unsigned int flags, struct nameidata *nd);
Expand Down Expand Up @@ -910,6 +986,8 @@ static void save_files(struct files_struct* files, struct saved_task_struct* tas
struct saved_file* file;
struct file* f = fcheck_files(files, fd);
struct shared_resource* file_res;
struct tmp_file_chain* chain;
struct hlist_node* pos;

// sprint("Bit set: %s\n", FD_ISSET(fd, fdt->open_fds) ? "yes" : "no");

Expand All @@ -936,9 +1014,13 @@ static void save_files(struct files_struct* files, struct saved_task_struct* tas
file->count = file_count(f);
file->ino = f->f_dentry->d_inode->i_ino;
sprint("link count %d\n", f->f_dentry->d_inode->i_nlink);
if(f->f_dentry->d_inode->i_nlink == 0)

hlist_for_each_entry(chain, pos, &tmp_file_map[hash_ptr(f, TMP_FILE_MAP_BITS)], chain)
{
file->temporary = 1;
if(chain->file == f)
{
file->temporary = 1;
}
}

if(f->f_mode & FMODE_READ)
Expand Down Expand Up @@ -1231,6 +1313,7 @@ void save_running_processes(void)
read_unlock(&tasklist_lock);
}


static char* task_states(int state)
{
static char* states[] = {"Running", "Interruptible", "Uninterruptible", "Other"};
Expand Down Expand Up @@ -1538,7 +1621,7 @@ int set_state_present()
{
struct saved_state* state;
state = (struct saved_state*)get_reserved_region();
return !list_empty(&state->processes);
return !list_empty(&state->processes) || saving_temp_files;
}

void test_restore_sockets(void);
Expand Down
13 changes: 5 additions & 8 deletions arch/x86/kernel/set_state.c
Original file line number Diff line number Diff line change
Expand Up @@ -1026,7 +1026,7 @@ struct file* restore_vc_terminal(struct saved_file* f)
#include <linux/ext3_fs.h>

struct inode *ext3_iget(struct super_block *sb, unsigned long ino);
static void restore_temp_file(struct saved_file* file)
void hardlink_temp_file(const char* name, unsigned long ino)
{
struct nameidata nd;
int err;
Expand All @@ -1035,8 +1035,8 @@ static void restore_temp_file(struct saved_file* file)
struct super_block *sb;
struct inode* inode;

sprint("Hardlinking to %s\n", file->name);
err = path_lookup(file->name, LOOKUP_PARENT, &nd);
sprint("Hardlinking to %s\n", name);
err = path_lookup(name, LOOKUP_PARENT, &nd);
if(err)
panic("Failed to lookup path for new file");

Expand All @@ -1056,11 +1056,11 @@ static void restore_temp_file(struct saved_file* file)

sb = nd.path.dentry->d_sb;
EXT3_SB(sb)->s_mount_state |= EXT3_ORPHAN_FS;
inode = ext3_iget(sb, file->ino);
inode = ext3_iget(sb, ino);
EXT3_SB(sb)->s_mount_state &= ~EXT3_ORPHAN_FS;

if(IS_ERR(inode))
panic("Could not get inode = %lu err %ld", file->ino, PTR_ERR(inode));
panic("Could not get inode = %lu err %ld", ino, PTR_ERR(inode));
fake_dentry.d_inode = inode;

sprint("Getting write access\n");
Expand Down Expand Up @@ -1120,9 +1120,6 @@ void restore_file(int fd, struct saved_file* f, struct state_info* info)
file = restore_vc_terminal(f);
break;
default:
if(f->temporary)
restore_temp_file(f);

file = do_filp_open(AT_FDCWD, f->name, f->flags, 0);

if(IS_ERR(file))
Expand Down
6 changes: 0 additions & 6 deletions fs/ext3/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -1373,12 +1373,6 @@ static void ext3_orphan_cleanup (struct super_block * sb,
#endif


if(set_state_present())
{
printk(KERN_INFO "Skipping orphan clean up because of save state\n");
return;
}

if (!es->s_last_orphan) {
jbd_debug(4, "no orphan inodes to clean up\n");
return;
Expand Down
1 change: 1 addition & 0 deletions include/linux/set_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ int are_user_tasks_ready(void);
int are_all_tasks_ready(void);
void install_syscall_blocker(void);
void activate_syscall_blocker(void);
void hardlink_temp_files(void);

// timing specific functions
void time_start_quiesence(void);
Expand Down
1 change: 1 addition & 0 deletions kernel/kexec.c
Original file line number Diff line number Diff line change
Expand Up @@ -1569,6 +1569,7 @@ static int do_kernel_kexec(unsigned int flags)
stop_user_tasks();
sprint("Shutting down devices\n");
system_state = SYSTEM_RESTART;
hardlink_temp_files();
do_sync(1);
device_shutdown();
sysdev_shutdown();
Expand Down
4 changes: 2 additions & 2 deletions load_kernel.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ cd test

#./launcher `pidof mysqld`

#./test_runner
./test_mmap 7
./test_runner
#./test_mmap 7

#kexec -l /boot/vmlinuz-`uname -r` --initrd=/boot/initrd.img-`uname -r` --append="root=/dev/sda1 1 irqpoll maxcpus=4 reset_devices load_state debug early_printk bootmem_debug"
#kexec -l /boot/vmlinuz-`uname -r` --append="root=/dev/sda1 1 irqpoll maxcpus=4 reset_devices load_state debug early_printk"
Expand Down
24 changes: 12 additions & 12 deletions test/test_runner.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,18 @@
#include "test.h"

char* tests[] = {
"test_loop",
"test_altstack",
"test_bind",
"test_pending_signals",
"test_pid",
"test_restore_signal",
"test_sighandler",
"test_sighandler_call",
"test_sigsuspend",
"test_stack",
"test_wait",
"test_fork",
/* "test_loop", */
/* "test_altstack", */
/* "test_bind", */
/* "test_pending_signals", */
/* "test_pid", */
/* "test_restore_signal", */
/* "test_sighandler", */
/* "test_sighandler_call", */
/* "test_sigsuspend", */
/* "test_stack", */
/* "test_wait", */
/* "test_fork", */
"test_tempfile",
NULL
};
Expand Down

0 comments on commit 4b3032a

Please sign in to comment.