ShingledFS 2.0
SMR-AwareFUSE-basedFileSystem
|
00001 00010 #define _XOPEN_SOURCE 500 00011 #include <fcntl.h> 00012 #include <errno.h> 00013 #include <stdio.h> 00014 #include <unistd.h> 00015 #include <stdlib.h> 00016 #include <string.h> 00017 #include <sys/stat.h> 00018 #include <sys/types.h> 00019 00020 #include "log.h" 00021 #include "failstop.h" 00022 #include "common.h" 00023 #include "helper.h" 00024 #include "emulator.h" 00025 #include "band_bitmap.h" 00026 00027 00028 #define FILE_BAND_BITMAP "/.smr_band_bitmap" 00029 00030 static int fd; 00031 00032 00033 00034 /* 00035 * @brief Initializes the band bitmap. 00036 * 00037 * If the band bitmap file exists, then it will open the bitmap file. 00038 * 00039 * @return 0 on success; -1 on failure 00040 */ 00041 00042 int init_band_bitmap(void) 00043 { 00044 int i; 00045 char path[PATH_MAX]; 00046 char bit = 0; 00047 int band_modulocount; //Assumption : Band count is a multiple of 8. 00048 00049 00050 /* Identify the no. of bands on the emulated disk */ 00051 band_modulocount = SFSDATA.edi_bandcount / 8; 00052 00053 00054 /* Initialize the last open band */ 00055 open_band.band = 0; 00056 open_band.rba = 0; 00057 open_band.total_blocks = 0; 00058 00059 00060 /* Open the Band Bitmap file */ 00061 translate_path(FILE_BAND_BITMAP, SFSDATA.path_unshingled, path); 00062 fd = open(path, O_RDWR | O_CREAT | O_EXCL, 0644); 00063 if (fd < 0) { 00064 // Band bitmap file already exists. 00065 dod((fd = open(path, O_RDWR)) > 0); 00066 return 0; 00067 } 00068 00069 00070 /* If the file is created then initialize the bitmap */ 00071 for (i = 0; i < band_modulocount; i++) { 00072 dod(pwrite(fd, &bit, 1, i) == 1); 00073 } 00074 00075 return 0; 00076 } 00077 00078 00079 /* 00080 * @brief Get next free band and update the band bitmap. 00081 * 00082 * @return Free band number 00083 */ 00084 00085 int get_freebandnum() 00086 { 00087 int i, j; 00088 int max_bands; 00089 int band_num = 0; 00090 char bit; 00091 00092 00093 max_bands = SFSDATA.edi_bandcount / 8; 00094 00095 for (i = 0; i < max_bands; i++) { 00096 dod(pread(fd, &bit, 1, i) == 1); 00097 00098 if(bit == 0xFF) { 00099 continue; 00100 } 00101 00102 for (j = 0; j < 8; j++) { 00103 if ((bit & (1 << j)) == 0) { 00104 bit = bit | (1 << j); 00105 dod(pwrite(fd, &bit, 1, i) == 1); 00106 band_num = i * 8 + j + 1; 00107 break; 00108 } 00109 } 00110 if (band_num != 0) { 00111 break; 00112 } 00113 } 00114 00115 return band_num; 00116 } 00117 00118 00119 /* 00120 * @brief Set the band by updating the band bitmap. 00121 * 00122 * @param band_num: Band number of the band to be set in the bitmap. 00123 */ 00124 00125 void put_setbandnum(int band_num) 00126 { 00127 int i, j; 00128 char bit; 00129 00130 if (band_num <= 0) { 00131 return; 00132 } 00133 00134 i = (band_num - 1) / 8; 00135 j = (band_num - 1) % 8; 00136 00137 dod(pread(fd, &bit, 1, i) == 1); 00138 00139 bit = bit | (1 << j); 00140 00141 dod(pwrite(fd, &bit, 1, i) == 1); 00142 } 00143 00144 00145 /* 00146 * @brief Free the band by updating the band bitmap 00147 * 00148 * @param band_num: Band number of the band to be freed 00149 */ 00150 00151 void put_freebandnum(int band_num) 00152 { 00153 int i, j; 00154 char bit; 00155 00156 if (band_num <= 0) { 00157 return; 00158 } 00159 00160 i = (band_num - 1) / 8; 00161 j = (band_num - 1) % 8; 00162 00163 dod(pread(fd, &bit, 1, i) == 1); 00164 00165 bit = bit & (~(1 << j)); 00166 00167 dod(pwrite(fd, &bit, 1, i) == 1); 00168 } 00169 00170 00171 /* 00172 * @brief Test if the band is free or occupied. 00173 * 00174 * @param band_num : Band number. 00175 * 00176 * @return 0 : if Band is free. 00177 * 1 : if Band is occupied. 00178 * -1 : on Error. 00179 */ 00180 00181 int test_bandusage(int band_num) 00182 { 00183 int i, j; 00184 char bit; 00185 int usage = 0; 00186 00187 if (band_num <= 0) { 00188 return -1; 00189 } 00190 00191 i = (band_num - 1) / 8; 00192 j = (band_num - 1) % 8; 00193 00194 dod(pread(fd, &bit, 1, i) == 1); 00195 00196 usage = bit & (1 << j); 00197 if (usage == 0) { 00198 return 0; 00199 } 00200 00201 return 1; 00202 } 00203 00204 00205 /* 00206 * @brief Retrieves the next band that has at least block_count free blocks. 00207 * 00208 * @param edi_fd File descriptor to EDI file 00209 * @param band Pointer to open_band_t structure 00210 * @param block_count Min. no. of blocks required in the band 00211 * 00212 * @return 0 on success; -1 on failure 00213 */ 00214 00215 int get_openband(int edi_fd, open_band_t *band, int block_count) 00216 { 00217 /* Read the no. of blocks for a band */ 00218 if (band->total_blocks == 0) { 00219 band->total_blocks = SFSDATA.edi_bandsize; 00220 } 00221 00222 if (band->band != 0) { 00223 dod(!edi_managebands(edi_fd, SVC_GETPTR, &band->band, &band->rba, 1)); 00224 00225 /* Check if the band has enough blocks */ 00226 if (band->total_blocks - band->rba >= block_count) { 00227 return 0; 00228 } 00229 } 00230 00231 band->band = get_freebandnum(); 00232 band->rba = 0; 00233 00234 if (band->band != 0) { 00235 return 0; 00236 } 00237 00238 for (band->band = 1; band->band <= SFSDATA.edi_bandcount; (band->band)++) { 00239 /* Get the write pointer for the current band */ 00240 dod(!edi_managebands(edi_fd, SVC_GETPTR, &band->band, &band->rba, 1)); 00241 00242 /* Check if the current band has enough space */ 00243 if (band->total_blocks - band->rba >= block_count) { 00244 return 0; 00245 } 00246 } 00247 00248 return -1; 00249 }