ShingledFS 2.0
SMR-AwareFUSE-basedFileSystem
|
00001 00002 00003 #define _XOPEN_SOURCE 500 00004 #include <unistd.h> 00005 #include <stdio.h> 00006 #include <sys/types.h> 00007 #include <sys/stat.h> 00008 #include <fcntl.h> 00009 #include <limits.h> 00010 00011 00012 #include "helper.h" 00013 #include "common.h" 00014 #include "errno.h" 00015 #include "string.h" 00016 00017 #include <stdlib.h> 00018 00019 00020 #include "band_log.h" 00021 00022 00023 00024 #define FILE_BANDLOG_APPEND_PREFIX "/.smr_append_log_" 00025 #define FILE_BANDLOG_DELETE_PREFIX "/.smr_delete_log_" 00026 00027 00028 /* 00029 * @brief : Initialize the store log for the given band number. 00030 * 00031 * @param band_num : Band number. 00032 * 00033 * @return fd : File descriptor. 00034 * -ve number : on Error. 00035 * 00036 */ 00037 00038 int init_storelog(int band_num) 00039 { 00040 int fd; 00041 char band_name[PATH_MAX]; 00042 char path[PATH_MAX]; 00043 00044 sprintf(band_name, "%s%d", FILE_BANDLOG_APPEND_PREFIX, band_num); 00045 translate_path(band_name, SFSDATA.path_unshingled, path); 00046 00047 fd = open(path, O_RDWR | O_APPEND | O_CREAT | O_EXCL, 0644); 00048 00049 if (fd < 0) { 00050 //append log file already exist. 00051 fd = open(path, O_RDWR | O_APPEND); 00052 if (fd < 0) { 00053 dbg("Error opening store log: %s \n", strerror(errno)); 00054 return -1; 00055 } 00056 return fd; 00057 } 00058 00059 return fd; 00060 } 00061 00062 00063 /* 00064 * @brief : Initialize the delete log for a band. 00065 * 00066 * @param band_num : Band number. 00067 * 00068 * @return fd : File descriptor. 00069 * -ve number : on Error. 00070 * 00071 */ 00072 00073 int init_deletelog(int band_num) 00074 { 00075 int fd; 00076 char band_name[PATH_MAX]; 00077 char path[PATH_MAX]; 00078 00079 sprintf(band_name, "%s%d", FILE_BANDLOG_DELETE_PREFIX, band_num); 00080 translate_path(band_name, SFSDATA.path_unshingled, path); 00081 00082 fd = open(path, O_RDWR | O_APPEND | O_CREAT | O_EXCL, 0644); 00083 00084 if (fd < 0) { 00085 //delete log file already exist. 00086 fd = open(path, O_RDWR | O_APPEND); 00087 if (fd < 0) { 00088 dbg("Error opening delete log \n"); 00089 return -1; 00090 } 00091 return fd; 00092 } 00093 00094 return fd; 00095 } 00096 00097 00098 /* 00099 * @brief : Deletes the store log for given band. 00100 * 00101 * @param band_num : Band number. 00102 * 00103 * @return : None. 00104 * 00105 */ 00106 00107 void clear_storelog(int band_num) 00108 { 00109 char band_name[PATH_MAX]; 00110 char path[PATH_MAX]; 00111 00112 sprintf(band_name, "%s%d", FILE_BANDLOG_APPEND_PREFIX, band_num); 00113 translate_path(band_name, SFSDATA.path_unshingled, path); 00114 00115 unlink(path); 00116 } 00117 00118 00119 /* 00120 * @brief : Deletes the delete log for given band. Is called when a band is 00121 * cleaned. 00122 * 00123 * @param band_num : Band number. 00124 * @param path_unshingled : Path to the unshingled drive. 00125 * 00126 * @return : None. 00127 * 00128 */ 00129 00130 void clear_deletelog(int band_num) 00131 { 00132 char band_name[PATH_MAX]; 00133 char path[PATH_MAX]; 00134 00135 sprintf(band_name, "%s%d", FILE_BANDLOG_DELETE_PREFIX, band_num); 00136 translate_path(band_name, SFSDATA.path_unshingled, path); 00137 00138 unlink(path); 00139 } 00140 00141 00142 /* 00143 * @brief : Appends an entry to the store log. 00144 * 00145 * @param fd : File descriptor. 00146 * @param offset : Offset in the band where the file is stored. 00147 * @param size : Size of the file. 00148 * @param inode_num : inode number of the file. 00149 * 00150 * @return : Index of the appended entry. 00151 * 00152 */ 00153 00154 int append_storelog(int fd, int offset, int size, int inode_num, long int age) 00155 { 00156 struct store_entry entry; 00157 struct stat filestat; 00158 int entrynumber; 00159 00160 entry.offset = offset; 00161 entry.size = size; 00162 entry.inode_num = inode_num; 00163 entry.age = age; 00164 00165 if (write(fd, &entry, sizeof(struct store_entry)) < 0) { 00166 dbg("Error writing to the append log in append_storelog \n"); 00167 exit(1); 00168 } 00169 00170 //Calculate the index of the insertion using the file size. 00171 fstat(fd, &filestat); 00172 entrynumber = filestat.st_size / (sizeof(struct store_entry)); 00173 00174 return entrynumber; 00175 } 00176 00177 00178 /* 00179 * @brief : Appends an entry to the delete log. 00180 * 00181 * @param fd : File descriptor. 00182 * @param offset : Offset in the band where the file was stored. 00183 * @param size : Size of the file. 00184 * @param entrynumber : Index in the append log. 00185 * 00186 * @return : None. 00187 */ 00188 00189 void append_deletelog(int fd, int offset, int size, int entrynumber) 00190 { 00191 struct delete_entry entry;; 00192 00193 entry.offset = offset; 00194 entry.size = size; 00195 entry.entrynumber = entrynumber; 00196 00197 if (write(fd, &entry, sizeof(struct delete_entry)) < 0) { 00198 dbg("Error writing delete log in append_deletelog\n"); 00199 exit(1); 00200 } 00201 } 00202 00203 00204 /* 00205 * @brief : List the entries of the band where the data is live on the band. 00206 * 00207 * @param band_num : Band number. 00208 * @param store_fd : File Descriptor for append log. 00209 * @param delete_fd : File Descriptor for delete log. 00210 * @param length : Pointer to store the number of entries returned. 00211 * @param livedatasize : Number of live block in the band. 00212 * 00213 * @return : List of struct containing append log entries not present in delete 00214 * log. The list of structure is malloced here and needs tobe freed 00215 * by the user afterwards. 00216 * 00217 */ 00218 00219 struct store_entry* get_livelog(int band_num, int store_fd, int delete_fd, 00220 int *length, int *livedatablocks) 00221 { 00222 struct store_entry *live; 00223 struct delete_entry del; 00224 struct store_entry entry; 00225 int *deleted; 00226 int numentries; 00227 int delentries; 00228 int i; 00229 int livecount = 0; 00230 int liveblock = 0; 00231 00232 struct stat filestat; 00233 00234 fstat(store_fd, &filestat); 00235 numentries = filestat.st_size / sizeof(struct store_entry); 00236 00237 fstat(delete_fd, &filestat); 00238 delentries = filestat.st_size / sizeof(struct delete_entry); 00239 00240 deleted = (int *) calloc (numentries, sizeof(int)); 00241 if (deleted == NULL) { 00242 dbg("Memory allocation failed in get_livelog\n"); 00243 exit(1); 00244 } 00245 00246 //Read the delete log and mark the entires which are deleted in a array. 00247 for (i = 0; i < delentries; i++) { 00248 pread(delete_fd, &del, sizeof(struct delete_entry), 00249 i * sizeof(struct delete_entry)); 00250 00251 if (del.entrynumber > numentries) { 00252 dbg("wrong value of delete entry \n"); 00253 exit(1); 00254 } 00255 00256 deleted[del.entrynumber - 1] = 1; 00257 } 00258 00259 live = (struct store_entry *) calloc((numentries - delentries), 00260 sizeof(struct store_entry)); 00261 if (live == NULL) { 00262 dbg("Malloc failed \n"); 00263 exit(1); 00264 } 00265 00266 //Now using the array, read only those entries which are not present in the 00267 //delete log. 00268 for (i = 0; i < numentries; i++) { 00269 if (deleted[i] == 0) { 00270 if (pread(store_fd, &entry, sizeof(struct store_entry), 00271 i * sizeof(struct store_entry)) < 0) { 00272 dbg("Error reading the store log in get_livelog \n"); 00273 } 00274 00275 live[livecount] = entry; 00276 liveblock = liveblock + entry.size; 00277 livecount++; 00278 } 00279 } 00280 00281 *length = livecount; 00282 *livedatablocks = liveblock; 00283 free(deleted); 00284 return live; 00285 00286 } 00287 00288 00289 /* 00290 * @brief : Returns the size of the band currently used. 00291 * 00292 * @param band_num : Band number. 00293 * 00294 * @return size : Size of the band used. 00295 * -1 : on Error. 00296 * 00297 */ 00298 00299 int band_occupancy(int band_num) 00300 { 00301 int fd; 00302 char band_name[PATH_MAX]; 00303 char path[PATH_MAX]; 00304 struct store_entry lastentry; 00305 int error; 00306 00307 sprintf(band_name, "%s%d", FILE_BANDLOG_APPEND_PREFIX, band_num); 00308 translate_path(band_name, SFSDATA.path_unshingled, path); 00309 00310 fd = open(path, O_RDWR); 00311 if (fd < 0) { 00312 dbg("Error opening store log file in band_occupancy \n"); 00313 return -1; 00314 } 00315 00316 lseek(fd, -1 * (sizeof(struct store_entry)), SEEK_END); 00317 error = read(fd, &lastentry, sizeof(struct store_entry)); 00318 00319 close(fd); 00320 if (error < 0) { 00321 dbg("Error reading the store log in band_occupancy \n"); 00322 return -1; 00323 } 00324 00325 if (error == 0) { 00326 return 0; 00327 } 00328 00329 return lastentry.offset + lastentry.size; 00330 } 00331 00332 00333 /* 00334 * @brief : Returns the age of the band currently used. 00335 * 00336 * @param band_num : Band number. 00337 * 00338 * @return age : Age of the band. 00339 * -1 : on Error. 00340 * 00341 */ 00342 00343 int band_age(int band_num) 00344 { 00345 int fd; 00346 char band_name[PATH_MAX]; 00347 char path[PATH_MAX]; 00348 struct store_entry firstentry; 00349 int error; 00350 00351 //TODO: Currently returns the age of the first file. 00352 //Needs to parse the entire log to get the age of the band. 00353 00354 sprintf(band_name, "%s%d", FILE_BANDLOG_APPEND_PREFIX, band_num); 00355 translate_path(band_name, SFSDATA.path_unshingled, path); 00356 00357 fd = open(path, O_RDWR); 00358 if (fd < 0) { 00359 dbg("Error opening store log in band_age \n"); 00360 return -1; 00361 } 00362 00363 error = read(fd, &firstentry, sizeof(struct store_entry)); 00364 00365 close(fd); 00366 if (error < 0) { 00367 dbg("Error reading append log in band_age \n"); 00368 return -1; 00369 } 00370 00371 if (error == 0) { 00372 return 0; 00373 } 00374 00375 return firstentry.age; 00376 } 00377 00378 00379 /* 00380 * @brief : Return the number of entries in the delete log. 00381 * Function currently used in cleaning for the base line 00382 * cleaning thread. 00383 * 00384 * @param band_num : Band number. 00385 * 00386 * @return num_entries : Number of entries in delete log. 00387 * 00388 */ 00389 00390 int band_delentries(int band_num) 00391 { 00392 char band_name[PATH_MAX]; 00393 char path[PATH_MAX]; 00394 struct stat filestat; 00395 int error; 00396 int num_entries; 00397 00398 sprintf(band_name, "%s%d", FILE_BANDLOG_DELETE_PREFIX, band_num); 00399 translate_path(band_name, SFSDATA.path_unshingled, path); 00400 00401 error = stat(path, &filestat); 00402 if (error == -1) { 00403 if (errno == ENOENT) { 00404 //delete log does not exist for file 00405 return 0; 00406 } 00407 return 0; 00408 } 00409 00410 num_entries = filestat.st_size / sizeof (struct delete_entry); 00411 return num_entries; 00412 }