Home | History | Annotate | Download | only in squashfs-tools
      1 /*
      2  * Create a squashfs filesystem.  This is a highly compressed read only
      3  * filesystem.
      4  *
      5  * Copyright (c) 2013, 2014
      6  * Phillip Lougher <phillip (at) squashfs.org.uk>
      7  *
      8  * This program is free software; you can redistribute it and/or
      9  * modify it under the terms of the GNU General Public License
     10  * as published by the Free Software Foundation; either version 2,
     11  * or (at your option) any later version.
     12  *
     13  * This program is distributed in the hope that it will be useful,
     14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16  * GNU General Public License for more details.
     17  *
     18  * You should have received a copy of the GNU General Public License
     19  * along with this program; if not, write to the Free Software
     20  * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
     21  *
     22  * restore.c
     23  */
     24 
     25 #include <pthread.h>
     26 #include <sys/ioctl.h>
     27 #include <unistd.h>
     28 #include <signal.h>
     29 #include <sys/time.h>
     30 #include <stdio.h>
     31 #include <math.h>
     32 #include <stdarg.h>
     33 #include <errno.h>
     34 #include <stdlib.h>
     35 #include <dirent.h>
     36 #include <sys/types.h>
     37 #include <sys/stat.h>
     38 
     39 #include "caches-queues-lists.h"
     40 #include "squashfs_fs.h"
     41 #include "mksquashfs.h"
     42 #include "error.h"
     43 #include "progressbar.h"
     44 #include "info.h"
     45 
     46 #define FALSE 0
     47 #define TRUE 1
     48 
     49 extern pthread_t reader_thread, writer_thread, main_thread;
     50 extern pthread_t *deflator_thread, *frag_deflator_thread, *frag_thread;
     51 extern struct queue *to_deflate, *to_writer, *to_frag, *to_process_frag;
     52 extern struct seq_queue *to_main;
     53 extern void restorefs();
     54 extern int processors;
     55 
     56 static int interrupted = 0;
     57 static pthread_t restore_thread;
     58 
     59 void *restore_thrd(void *arg)
     60 {
     61 	sigset_t sigmask, old_mask;
     62 	int i, sig;
     63 
     64 	sigemptyset(&sigmask);
     65 	sigaddset(&sigmask, SIGINT);
     66 	sigaddset(&sigmask, SIGTERM);
     67 	sigaddset(&sigmask, SIGUSR1);
     68 	pthread_sigmask(SIG_BLOCK, &sigmask, &old_mask);
     69 
     70 	while(1) {
     71 		sigwait(&sigmask, &sig);
     72 
     73 		if((sig == SIGINT || sig == SIGTERM) && !interrupted) {
     74 			ERROR("Interrupting will restore original "
     75 				"filesystem!\n");
     76                 	ERROR("Interrupt again to quit\n");
     77 			interrupted = TRUE;
     78 			continue;
     79 		}
     80 
     81 		/* kill main thread/worker threads and restore */
     82 		set_progressbar_state(FALSE);
     83 		disable_info();
     84 
     85 		/* first kill the reader thread */
     86 		pthread_cancel(reader_thread);
     87 		pthread_join(reader_thread, NULL);
     88 
     89 		/*
     90 		 * then flush the reader to deflator thread(s) output queue.
     91 		 * The deflator thread(s) will idle
     92 		 */
     93 		queue_flush(to_deflate);
     94 
     95 		/* now kill the deflator thread(s) */
     96 		for(i = 0; i < processors; i++)
     97 			pthread_cancel(deflator_thread[i]);
     98 		for(i = 0; i < processors; i++)
     99 			pthread_join(deflator_thread[i], NULL);
    100 
    101 		/*
    102 		 * then flush the reader to process fragment thread(s) output
    103 		 * queue.  The process fragment thread(s) will idle
    104 		 */
    105 		queue_flush(to_process_frag);
    106 
    107 		/* now kill the process fragment thread(s) */
    108 		for(i = 0; i < processors; i++)
    109 			pthread_cancel(frag_thread[i]);
    110 		for(i = 0; i < processors; i++)
    111 			pthread_join(frag_thread[i], NULL);
    112 
    113 		/*
    114 		 * then flush the reader/deflator/process fragment to main
    115 		 * thread output queue.  The main thread will idle
    116 		 */
    117 		seq_queue_flush(to_main);
    118 
    119 		/* now kill the main thread */
    120 		pthread_cancel(main_thread);
    121 		pthread_join(main_thread, NULL);
    122 
    123 		/* then flush the main thread to fragment deflator thread(s)
    124 		 * queue.  The fragment deflator thread(s) will idle
    125 		 */
    126 		queue_flush(to_frag);
    127 
    128 		/* now kill the fragment deflator thread(s) */
    129 		for(i = 0; i < processors; i++)
    130 			pthread_cancel(frag_deflator_thread[i]);
    131 		for(i = 0; i < processors; i++)
    132 			pthread_join(frag_deflator_thread[i], NULL);
    133 
    134 		/*
    135 		 * then flush the main thread/fragment deflator thread(s)
    136 		 * to writer thread queue.  The writer thread will idle
    137 		 */
    138 		queue_flush(to_writer);
    139 
    140 		/* now kill the writer thread */
    141 		pthread_cancel(writer_thread);
    142 		pthread_join(writer_thread, NULL);
    143 
    144 		TRACE("All threads cancelled\n");
    145 
    146 		restorefs();
    147 	}
    148 }
    149 
    150 
    151 pthread_t *init_restore_thread()
    152 {
    153 	pthread_create(&restore_thread, NULL, restore_thrd, NULL);
    154 	return &restore_thread;
    155 }
    156