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  * info.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 #include <string.h>
     39 
     40 #include "squashfs_fs.h"
     41 #include "mksquashfs.h"
     42 #include "error.h"
     43 #include "progressbar.h"
     44 #include "caches-queues-lists.h"
     45 
     46 static int silent = 0;
     47 static struct dir_ent *ent = NULL;
     48 
     49 pthread_t info_thread;
     50 
     51 
     52 void disable_info()
     53 {
     54 	ent = NULL;
     55 }
     56 
     57 
     58 void update_info(struct dir_ent *dir_ent)
     59 {
     60 	ent = dir_ent;
     61 }
     62 
     63 
     64 void print_filename()
     65 {
     66 	struct dir_ent *dir_ent = ent;
     67 
     68 	if(dir_ent == NULL)
     69 		return;
     70 
     71 	if(dir_ent->our_dir->subpath[0] != '\0')
     72 		INFO("%s/%s\n", dir_ent->our_dir->subpath, dir_ent->name);
     73 	else
     74 		INFO("/%s\n", dir_ent->name);
     75 }
     76 
     77 
     78 void dump_state()
     79 {
     80 	disable_progress_bar();
     81 
     82 	printf("Queue and Cache status dump\n");
     83 	printf("===========================\n");
     84 
     85 	printf("file buffer queue (reader thread -> deflate thread(s))\n");
     86 	dump_queue(to_deflate);
     87 
     88 	printf("uncompressed fragment queue (reader thread -> fragment"
     89 						" thread(s))\n");
     90 	dump_queue(to_process_frag);
     91 
     92 	printf("processed fragment queue (fragment thread(s) -> main"
     93 						" thread)\n");
     94 	dump_seq_queue(to_main, 1);
     95 
     96 	printf("compressed block queue (deflate thread(s) -> main thread)\n");
     97 	dump_seq_queue(to_main, 0);
     98 
     99 	printf("uncompressed packed fragment queue (main thread -> fragment"
    100 						" deflate thread(s))\n");
    101 	dump_queue(to_frag);
    102 
    103 
    104 	printf("locked frag queue (compressed frags waiting while multi-block"
    105 						" file is written)\n");
    106 	dump_queue(locked_fragment);
    107 
    108 	printf("compressed block queue (main & fragment deflate threads(s) ->"
    109 						" writer thread)\n");
    110 	dump_queue(to_writer);
    111 
    112 	printf("read cache (uncompressed blocks read by reader thread)\n");
    113 	dump_cache(reader_buffer);
    114 
    115 	printf("block write cache (compressed blocks waiting for the writer"
    116 						" thread)\n");
    117 	dump_cache(bwriter_buffer);
    118 	printf("fragment write cache (compressed fragments waiting for the"
    119 						" writer thread)\n");
    120 	dump_cache(fwriter_buffer);
    121 
    122 	printf("fragment cache (frags waiting to be compressed by fragment"
    123 						" deflate thread(s))\n");
    124 	dump_cache(fragment_buffer);
    125 
    126 	printf("fragment reserve cache (avoids pipeline stall if frag cache"
    127 						" full in dup check)\n");
    128 	dump_cache(reserve_cache);
    129 
    130 	enable_progress_bar();
    131 }
    132 
    133 
    134 void *info_thrd(void *arg)
    135 {
    136 	sigset_t sigmask;
    137 	int sig, err, waiting = 0;
    138 
    139 	sigemptyset(&sigmask);
    140 	sigaddset(&sigmask, SIGQUIT);
    141 	sigaddset(&sigmask, SIGHUP);
    142 	sigaddset(&sigmask, SIGALRM);
    143 
    144 	while(1) {
    145 		err = sigwait(&sigmask, &sig);
    146 
    147 		if(err == -1) {
    148 			switch(errno) {
    149 			case EINTR:
    150 				continue;
    151 			default:
    152 				BAD_ERROR("sigwait failed "
    153 					"because %s\n", strerror(errno));
    154 			}
    155 		}
    156 
    157 		if(sig == SIGQUIT && !waiting) {
    158 			print_filename();
    159 
    160 			/* set one second interval period, if ^\ received
    161 			   within then, dump queue and cache status */
    162 			waiting = 1;
    163 			alarm(1);
    164 		} else if (sig == SIGQUIT) {
    165 			dump_state();
    166 		} else if (sig == SIGALRM) {
    167 			waiting = 0;
    168 		}
    169 	}
    170 }
    171 
    172 
    173 void init_info()
    174 {
    175 	pthread_create(&info_thread, NULL, info_thrd, NULL);
    176 }
    177