ShingledFS 2.0
SMR-AwareFUSE-basedFileSystem
|
00001 00002 00003 00004 #include <stdio.h> 00005 #include <sys/types.h> 00006 #include <sys/stat.h> 00007 #include <fcntl.h> 00008 #include <unistd.h> 00009 #include <signal.h> 00010 #include <string.h> 00011 #include <assert.h> 00012 00013 #include "band_log.h" 00014 00015 #define _XOPEN_SOURCE 500 00016 #include <unistd.h> 00017 #include <semaphore.h> 00018 #include <pthread.h> 00019 #include <stdlib.h> 00020 00021 #include "band_bitmap.h" 00022 #include "cleaning_thread.h" 00023 #include "common.h" 00024 #include "inode.h" 00025 #include "emulator.h" 00026 00027 00028 static sem_t cleaner_sem; 00029 00030 00031 static void sig_handler(int signal); 00032 00033 00034 00035 /* 00036 * @brief : Spawns a cleaning thread and intializes the cleaning parameters. 00037 * 00038 * @param : None. 00039 * 00040 * @return 0 : on Success. 00041 * -1 : on Error. 00042 * 00043 */ 00044 00045 int cleaner_init(void) 00046 { 00047 int err; 00048 pthread_t tid; 00049 00050 if ((err = pthread_create(&tid, NULL, band_cleaner, NULL)) != 0) { 00051 log(LOG_CLN_ERRORS, "Error creating thread: %s\n", strerror(err)); 00052 return -1; 00053 } 00054 00055 00056 // Install the signal handler 00057 signal(SIGUSR1, sig_handler); 00058 00059 return 0; 00060 } 00061 00062 00063 00064 /* 00065 * @brief : Cleaning thread created by the cleaner_init function. It waits on 00066 * a semaphore to be signalled by the signal handler to start 00067 * cleaning. Currently ascynchronus cleaning is supported. It will 00068 * clean all bands one by one and then will again wait on the semaphore 00069 * once all the bands are cleaned. It also intializes the log 00070 * functions for the cleaning thread. 00071 * 00072 * @param sfs : Pointer to fuse context data. 00073 * 00074 * @return : None. 00075 * 00076 */ 00077 00078 void * band_cleaner() 00079 { 00080 //Initialize the log file creation. 00081 #ifdef GENERATE_LOGS 00082 char filename[50]; 00083 int len; 00084 time_t curtime = time(NULL); 00085 00086 00087 /* Initialize the logging interface */ 00088 len = strftime(filename, 50, "/tmp/smr%Y%m%d%H%M%S_cleaner.log", 00089 localtime(&curtime)); 00090 if (!len) { 00091 fprintf(stderr, "Error generating log file name: %s\n", filename); 00092 assert(0); 00093 } 00094 log_open(filename); 00095 #endif 00096 00097 00098 00099 init_semcleaner(); 00100 00101 00102 while(1) { 00103 wait_cleaner(); 00104 00105 //Fucntion will clean all the bands on the disk. 00106 band_cleanall(); 00107 00108 } 00109 } 00110 00111 00112 /* 00113 * @brief : Fucntion will clean all the band on the disk. Will return once all 00114 * the bands are cleaned. When this fucntion is running no other 00115 * activity should be running on the file system. 00116 * 00117 * @param sfs : Pointer to fuse context. 00118 * 00119 * @return : None. 00120 * 00121 */ 00122 00123 void band_cleanall() 00124 { 00125 int i; 00126 00127 while (1) { 00128 i = band_cleaning(); 00129 if (i == -1) { 00130 break; 00131 } 00132 } 00133 } 00134 00135 00136 /* 00137 * @breif : Cleans one band at a time. 00138 * Selects one band for cleaning and one band to clean to. 00139 * Once the band are selected according to the policies then they 00140 * are cleaned. The updates of the data and inode takes place in 00141 * a particular order to avaoid inconsistencies during failure. 00142 * 00143 * @param 00144 * 00145 * @return 0 : on Success. 00146 * -1 : no band left to clean. 00147 * 00148 */ 00149 00150 int band_cleaning() 00151 { 00152 int band_frag; 00153 int band_clean; 00154 struct store_entry *live; 00155 int livedata; 00156 int length; 00157 int frag_storefd; 00158 int frag_deletefd; 00159 int write_pointer = 0; 00160 00161 00162 //TODO: Acquire locks before writing to the band. In the functions select 00163 //the locks should be acaquired. Thus one the band is selected, no one uses 00164 //it for writing. 00165 00166 band_frag = select_fragband(); 00167 if (band_frag == 0) { 00168 return -1; 00169 } 00170 00171 //Get the fd's for store log and append log. 00172 frag_storefd = init_storelog(band_frag); 00173 if (frag_storefd == -1) { 00174 exit(EXIT_FAILURE); 00175 } 00176 00177 frag_deletefd = init_deletelog(band_frag); 00178 if (frag_deletefd == -1) { 00179 exit(EXIT_FAILURE); 00180 } 00181 00182 live = get_livelog(band_frag, frag_storefd, frag_deletefd, &length, 00183 &livedata); 00184 00185 close(frag_storefd); 00186 close(frag_deletefd); 00187 00188 band_clean = select_cleanband(livedata); 00189 00190 if (band_clean == 0) { 00191 exit(EXIT_FAILURE); 00192 } 00193 00194 migrate_data(band_frag, band_clean, live, length); 00195 00196 clear_storelog(band_frag); 00197 clear_deletelog(band_frag); 00198 00199 //TODO:Update the locks of both the bands. 00200 00201 if (edi_managebands(SFSDATA.fd_edi, SVC_SETPTR, &band_frag, &write_pointer, 00202 sizeof(rba_t))) { 00203 exit(EXIT_FAILURE); 00204 } 00205 00206 free(live); 00207 return 0; 00208 00209 } 00210 00211 00212 /* 00213 * @brief : The function migrates data from one band to another band. 00214 * 00215 * @param band_frag : Band id of the band to be cleaned. 00216 * @param band_clean : Band id of the band to clean to. 00217 * @param live : Array of store entries i.e. live data's metadata for the band. 00218 * @param length : Length of the array live. 00219 * 00220 * @return : None. 00221 * 00222 */ 00223 00224 void migrate_data(int band_frag, int band_clean, 00225 struct store_entry *live, int length) 00226 { 00227 int i; 00228 int write_pointer; 00229 inode_t temp_inode; 00230 int index; 00231 int clean_storefd; 00232 int err; 00233 00234 if (edi_managebands(SFSDATA.fd_edi, SVC_GETPTR, &band_clean, &write_pointer, 00235 sizeof(rba_t))) { 00236 exit(EXIT_FAILURE); 00237 } 00238 00239 clean_storefd = init_storelog(band_clean); 00240 if (clean_storefd == -1) { 00241 exit(EXIT_FAILURE); 00242 } 00243 00244 for(i = 0; i < length; i++) { 00245 00246 err = get_inode(live[i].inode_num, &temp_inode); 00247 if (err == -1) { 00248 exit(EXIT_FAILURE); 00249 } 00250 00251 copy_data(band_frag, band_clean, live[i].offset, live[i].size, 00252 write_pointer); 00253 00254 //TODO: Update the age correctly. 00255 index = append_storelog(clean_storefd, write_pointer, live[i].size, 00256 live[i].inode_num, 0); 00257 00258 temp_inode.entrynumber = index; 00259 temp_inode.band_id = band_clean; 00260 temp_inode.band_offset = write_pointer; 00261 00262 err = put_inode(live[i].inode_num, &temp_inode); 00263 if (err == -1) { 00264 exit(EXIT_FAILURE); 00265 } 00266 00267 write_pointer = write_pointer + live[i].size; 00268 00269 } 00270 00271 close(clean_storefd); 00272 } 00273 00274 00275 /* 00276 * @brief : Called by the cleaner thread to wait for the signal/ 00277 * 00278 * @param : None. 00279 * 00280 * @return : None. 00281 * 00282 */ 00283 00284 void wait_cleaner(void) 00285 { 00286 sem_wait(&cleaner_sem); 00287 } 00288 00289 00290 /* 00291 * @brief : Called by the signal handler to woka up the cleaning thread. 00292 * 00293 * @param : None. 00294 * 00295 * @return : None. 00296 * 00297 */ 00298 00299 void signal_cleaner(void) 00300 { 00301 sem_post(&cleaner_sem); 00302 } 00303 00304 00305 /* 00306 * @brief : Initialize the cleaner semaphore. 00307 * 00308 * @param : None. 00309 * 00310 * @return : None. 00311 * 00312 */ 00313 00314 void init_semcleaner(void) 00315 { 00316 int error; 00317 error = sem_init(&cleaner_sem, 0, 0); 00318 if (error != 0) { 00319 log(LOG_CLN_ERRORS, "Error initializing semaphore for the cleaner. \n"); 00320 } 00321 } 00322 00323 00324 /* 00325 * @brief : Copy data from one band to another band with the given band offset 00326 * and size. 00327 * 00328 * @param band_src : Source band number. 00329 * @param band_dst : Destination band number. 00330 * @param offset_src : Sorce band rba. 00331 * @param len_src : Length of copy. 00332 * @param offset_dst : Destination band rba. 00333 * 00334 * @return None. 00335 * 00336 */ 00337 00338 void copy_data(int band_src, int band_dst, int offset_src, int len_src, 00339 int offset_dst) 00340 { 00341 char *buf; 00342 00343 buf = (char *) malloc (len_src * SFSDATA.edi_blksize); 00344 if (buf == NULL) { 00345 exit(EXIT_FAILURE); 00346 } 00347 00348 if (edi_read(SFSDATA.fd_edi, band_src, offset_src, buf, len_src)) { 00349 exit(EXIT_FAILURE); 00350 } 00351 00352 if (edi_write(SFSDATA.fd_edi, band_dst, offset_dst, buf, len_src)) { 00353 exit(EXIT_FAILURE); 00354 } 00355 00356 } 00357 00358 00359 00360 static void sig_handler(int signal) { 00361 /* Check the signal received */ 00362 if (signal == SIGUSR1) 00363 signal_cleaner(); 00364 }