ShingledFS 2.0
SMR-AwareFUSE-basedFileSystem
|
00001 00010 #include <errno.h> 00011 #include <stdio.h> 00012 #include <string.h> 00013 #include <stdlib.h> 00014 #include <unistd.h> 00015 #include <limits.h> 00016 00017 #include "debug.h" 00018 #include "common.h" 00019 #include "helper.h" 00020 #include "emulator.h" 00021 #include "band_bitmap.h" 00022 #include "band_log.h" 00023 00024 00025 00026 /* ======================= */ 00027 /* -- Macro Definitions -- */ 00028 /* ======================= */ 00029 00030 #define ARG_COUNT_MIN 4 00031 00032 #define ARG_PATH_EDI 1 00033 #define ARG_PATH_USHNG 2 00034 #define ARG_PATH_OUTPUT 3 00035 00036 00037 00038 /* ====================== */ 00039 /* -- Type Definitions -- */ 00040 /* ====================== */ 00041 00042 00043 00044 /* ============================= */ 00045 /* -- Global/Static Variables -- */ 00046 /* ============================= */ 00047 00048 FILE *file_stats; 00049 00050 00051 00052 /* ========================= */ 00053 /* -- Function Prototypes -- */ 00054 /* ========================= */ 00055 00056 static void initialize(); 00057 static void process_band(band_t band); 00058 00059 00060 00061 /* ============================== */ 00062 /* -- Function Implementations -- */ 00063 /* ============================== */ 00064 00068 static void usage(const char *program_name) 00069 { 00070 fprintf(stderr, 00071 "USAGE: %s <EDI path> <Unshingled path> <Output path>\n", 00072 program_name); 00073 abort(); 00074 } 00075 00076 00077 00090 static void process_args(int *argc, char *argv[]) { 00091 int i, arg_error = 0; 00092 00093 00094 /* Ensure that the arguments are available */ 00095 if (*argc < ARG_COUNT_MIN) 00096 usage(argv[0]); 00097 00098 00099 /* Strip out any terminating /'s in the path to the directories */ 00100 i = strlen(argv[ARG_PATH_USHNG]) - 1; 00101 if (argv[ARG_PATH_USHNG][i] == '/') 00102 argv[ARG_PATH_USHNG][i] = '\0'; 00103 00104 00105 /* Validate the path to the Emulated Disk Image */ 00106 if (!is_valid_file(argv[ARG_PATH_EDI])) { 00107 arg_error = 1; 00108 fprintf(stderr, "%s is not a valid file!\n", argv[ARG_PATH_EDI]); 00109 } 00110 00111 /* Validate the path to the Unshingled partition */ 00112 if (!is_valid_dir(argv[ARG_PATH_USHNG])) { 00113 arg_error = 1; 00114 fprintf(stderr, "%s is not a valid directory!\n", argv[ARG_PATH_USHNG]); 00115 } 00116 00117 00118 /* Check if there are any errors */ 00119 if (arg_error) 00120 usage(argv[0]); 00121 00122 00123 /* Store the arguments */ 00124 strcpy(SFSDATA.path_edi, argv[ARG_PATH_EDI]); 00125 strcpy(SFSDATA.path_unshingled, argv[ARG_PATH_USHNG]); 00126 strcpy(SFSDATA.path_tmpfs, argv[ARG_PATH_OUTPUT]); 00127 dbg("EDI path: %s\n", SFSDATA.path_edi); 00128 dbg("Unshingled path: %s\n", SFSDATA.path_unshingled); 00129 dbg("Output path: %s\n", SFSDATA.path_tmpfs); 00130 } 00131 00132 00133 00140 static void initialize() { 00141 /* Load the Emulated Disk Image */ 00142 if (edi_init()) { 00143 fprintf(stderr, "Error initializing Emulator interface!\n"); 00144 exit(EXIT_FAILURE); 00145 } 00146 00147 if ((SFSDATA.fd_edi = edi_open(SFSDATA.path_edi)) < 0) { 00148 fprintf(stderr, "edi_open(%s): %s!\n", SFSDATA.path_edi, strerror(errno)); 00149 exit(EXIT_FAILURE); 00150 } 00151 00152 /* Open the output file */ 00153 if ((file_stats = fopen(SFSDATA.path_tmpfs, "w+")) == NULL) { 00154 fprintf(stderr, "fopen(%s): %s\n", SFSDATA.path_tmpfs, strerror(errno)); 00155 exit(EXIT_FAILURE); 00156 } 00157 00158 00159 /* Read the EDI Parameters */ 00160 read_edi_parameters(SFSDATA.fd_edi, &SFSDATA.edi_blksize, 00161 &SFSDATA.edi_bandcount, &SFSDATA.edi_bandsize); 00162 00163 /* Initialize the Band Bitmap */ 00164 if (init_band_bitmap() < 0) { 00165 fprintf(stderr, "Error opening band bitmap!\n"); 00166 exit(EXIT_FAILURE); 00167 } 00168 } 00169 00170 00171 00179 static void process_band(band_t band) { 00180 char error[PATH_MAX]; 00181 int i, band_used, fd_append, fd_delete, num_append, num_delete; 00182 rba_t band_ptr = 0, band_live = 0, band_dead = 0; 00183 struct stat statbuf; 00184 int *deleted; 00185 struct delete_entry rec_delete; 00186 struct store_entry rec_append; 00187 00188 00189 /* Read the write pointer for the band */ 00190 if (edi_managebands(SFSDATA.fd_edi, SVC_GETPTR, &band, &band_ptr, 0)) { 00191 sprintf(error, "edi_managebands() failed!"); 00192 goto error; 00193 } 00194 00195 /* Check if the band is free or occupied */ 00196 if ((band_used = test_bandusage(band)) < 0) { 00197 sprintf(error, "test_bandusage() failed!"); 00198 goto error; 00199 } 00200 dbg("Band State: %s\n", band_used ? "Used" : "Free"); 00201 00202 00203 /* Open the Append Log and the Delete Log for the band */ 00204 if ((fd_append = init_storelog(band)) < 0) { 00205 sprintf(error, "Error opening Append Log!"); 00206 goto error; 00207 } 00208 00209 if ((fd_delete = init_deletelog(band)) < 0) { 00210 sprintf(error, "Error opening Delete Log!"); 00211 goto error; 00212 } 00213 00214 00215 /* Generate statistics for the band if it is used */ 00216 if (band_used) { 00217 /* Read the no. of append and delete log entries */ 00218 fstat(fd_append, &statbuf); 00219 num_append = statbuf.st_size / sizeof(struct store_entry); 00220 dbg("Append Log Entries:%d\n",num_append); 00221 00222 fstat(fd_delete, &statbuf); 00223 num_delete = statbuf.st_size / sizeof(struct delete_entry); 00224 dbg("Delete Log Entries:%d\n",num_delete); 00225 00226 00227 /* Identify deleted append log entries from the delete log */ 00228 deleted = calloc(num_append, sizeof(int)); 00229 for (i=0; i<num_delete; i++) { 00230 dbg("Processing Delete Entry %d\n", i); 00231 pread(fd_delete, &rec_delete, sizeof(struct delete_entry), 00232 i * sizeof(struct delete_entry)); 00233 00234 if (rec_delete.entrynumber > num_append) { 00235 sprintf(error, "Delete Log entry %d refers to %d of %d Append" 00236 "Log entries!", i, rec_delete.entrynumber, num_append); 00237 goto error; 00238 } 00239 00240 deleted[rec_delete.entrynumber - 1] = 1; 00241 band_dead += rec_delete.size; 00242 } 00243 00244 00245 /* Identify the live data in the band */ 00246 for (i=0; i<num_append; i++) { 00247 if (deleted[i]) 00248 continue; 00249 00250 dbg("Processing Append Entry %d\n", i); 00251 pread(fd_append, &rec_append, sizeof(struct store_entry), 00252 i * sizeof(struct store_entry)); 00253 00254 band_live += rec_append.size; 00255 } 00256 } 00257 00258 00259 /* Close the open files */ 00260 close(fd_append); 00261 close(fd_delete); 00262 00263 00264 /* Write the band statistics to the output file */ 00265 fprintf(file_stats, "Band %3d\t%s\t%8d\t%8d\t%8d\t%8d\n", 00266 band, (band_used ? "Used" : "Free"), SFSDATA.edi_bandsize, 00267 band_ptr, band_live, band_dead); 00268 00269 return; 00270 00271 error: 00272 fprintf(file_stats, "Band %3d: %s\n", band, error); 00273 } 00274 00275 00276 00277 /* =================== */ 00278 /* -- Main Function -- */ 00279 /* =================== */ 00280 00281 int main(int argc, char *argv[]) { 00282 int i; 00283 time_t curtime = time(NULL); 00284 00285 00286 /* Process the arguments */ 00287 process_args(&argc, argv); 00288 00289 /* Initialize the program */ 00290 initialize(); 00291 00292 00293 /* Output the basic EDI parameters */ 00294 fprintf(file_stats, "EDI Image: %s\n", SFSDATA.path_edi); 00295 fprintf(file_stats, "Unshingled Partition: %s\n", SFSDATA.path_unshingled); 00296 fprintf(file_stats, "Report Time: %s\n", ctime(&curtime)); 00297 fprintf(file_stats, "Sector Size: %d bytes\n", SFSDATA.edi_blksize); 00298 fprintf(file_stats, "Bands: %d bytes\n", SFSDATA.edi_bandcount); 00299 fprintf(file_stats, "Band Size: %d blocks (%d bytes)\n", 00300 SFSDATA.edi_bandsize, SFSDATA.edi_bandsize * SFSDATA.edi_blksize); 00301 00302 00303 /* Iterate over the bands in the EDI */ 00304 fprintf(file_stats, "Band No.\tState\tBand Size\tCursor Position\t" 00305 "Live Blocks\tDead Blocks\n"); 00306 for (i=1; i<SFSDATA.edi_bandcount; i++) { 00307 dbg("Processing band %d\n", i); 00308 process_band(i); 00309 } 00310 00311 00312 /* Close the output file */ 00313 fclose(file_stats); 00314 return (EXIT_SUCCESS); 00315 }