ShingledFS 2.0
SMR-AwareFUSE-basedFileSystem

band_bitmap.c

Go to the documentation of this file.
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 }