ShingledFS 2.0
SMR-AwareFUSE-basedFileSystem
|
00001 00009 #include <errno.h> 00010 #include <unistd.h> 00011 #include <stdlib.h> 00012 #include <string.h> 00013 #include <assert.h> 00014 #include <sys/stat.h> 00015 #include <sys/xattr.h> 00016 #include <linux/limits.h> 00017 00018 #include "helper.h" 00019 #include "failstop.h" 00020 #include "emulator.h" 00021 #include "band_log.h" 00022 00023 00024 00025 /* ======================= */ 00026 /* -- Macro Definitions -- */ 00027 /* ======================= */ 00028 00029 00030 00031 /* ====================== */ 00032 /* -- Static Variables -- */ 00033 /* ====================== */ 00034 00035 00036 00037 /* ============================== */ 00038 /* -- Function Implementations -- */ 00039 /* ============================== */ 00040 00049 void 00050 read_edi_parameters(int fd, 00051 uint32_t *blk_size, 00052 band_t *band_count, 00053 rba_t *band_size) { 00054 /* Read the EDI Block Size */ 00055 dod(edi_modesense(SFSDATA.fd_edi, INQ_BLKSIZE, blk_size) == 0); 00056 00057 /* Read the EDI Band Size */ 00058 dod(edi_modesense(SFSDATA.fd_edi, INQ_BNDSIZE, band_size) == 0); 00059 00060 /* Read the EDI Band Count */ 00061 dod(edi_modesense(SFSDATA.fd_edi, INQ_BNDCOUNT, band_count) == 0); 00062 } 00063 00064 00065 00076 void 00077 translate_path(const char *in_path, 00078 const char *prefix, 00079 char *out_path) { 00080 /* Validate the inputs */ 00081 if ((in_path == NULL) || (out_path == NULL)) { 00082 log(LOG_SFS_ERRORS, "Null arguments passed!\n"); 00083 exit(EXIT_FAILURE); 00084 } 00085 00086 /* Ensure that the lengths of the paths will not be an issue */ 00087 if (strlen(in_path) + strlen(prefix) >= PATH_MAX) { 00088 log(LOG_SFS_ERRORS, "Translated path exceeds PATH_MAX!\n"); 00089 exit(EXIT_FAILURE); 00090 } 00091 00092 /* Concatenate the prefix and in_path and store the result in out_path */ 00093 strcpy(out_path, prefix); 00094 strcat(out_path, in_path); 00095 } 00096 00097 00098 00113 void 00114 xattr_path(const char *in_path, 00115 char *out_path) { 00116 char *filename; 00117 int len; 00118 00119 00120 /* Validate the inputs */ 00121 if ((in_path == NULL) || (out_path == NULL)) { 00122 log(LOG_SFS_ERRORS, "Null arguments passed!\n"); 00123 exit(EXIT_FAILURE); 00124 } 00125 00126 /* Ensure that the lengths of the paths will not be an issue */ 00127 if (strlen(in_path) + strlen(FILE_XATTR_PREFIX) >= PATH_MAX) { 00128 log(LOG_SFS_ERRORS, "Translated path exceeds PATH_MAX!\n"); 00129 exit(EXIT_FAILURE); 00130 } 00131 00132 00133 /* Locate the start of the filename in the input path */ 00134 if ((filename = strrchr(in_path, '/')) == NULL) { 00135 log(LOG_SFS_ERRORS, "Received malformed path %s\n", in_path); 00136 exit(EXIT_FAILURE); 00137 } 00138 filename++; 00139 00140 00141 /* Construct the name of the attribute replication file */ 00142 len = (size_t)filename - (size_t)in_path; 00143 strncpy(out_path, in_path, len); 00144 out_path[len] = '\0'; 00145 strcat(out_path, FILE_XATTR_PREFIX); 00146 strcat(out_path, filename); 00147 } 00148 00149 00150 00161 int 00162 xattr_get(const char *path, 00163 const char *name, 00164 void *value, 00165 size_t size) { 00166 char path_xattr[PATH_MAX]; 00167 00168 00169 /* Generate the name of the Attribute Replication file */ 00170 xattr_path(path, path_xattr); 00171 00172 /* Get the attributes */ 00173 return (lgetxattr(path_xattr, name, value, size) > 0) ? 0 : -1; 00174 } 00175 00176 00177 00186 void 00187 xattr_set(const char *path, 00188 const char *name, 00189 void *value, 00190 size_t size, 00191 int flags) { 00192 char path_xattr[PATH_MAX]; 00193 struct stat statbuf; 00194 00195 00196 /* Generate the name of the Attribute Replication file */ 00197 xattr_path(path, path_xattr); 00198 00199 /* Check if the Replicated Attributes are being updated */ 00200 if (!strcmp(name, X_STATS)) { 00201 /* Read the Replicated attributes */ 00202 dod(lgetxattr(path_xattr, X_STATS, &statbuf, sizeof(statbuf)) >= 0); 00203 00204 /* Update the attributes */ 00205 ((struct stat *)value)->st_dev = statbuf.st_dev; 00206 ((struct stat *)value)->st_ino = statbuf.st_ino; 00207 ((struct stat *)value)->st_rdev = statbuf.st_rdev; 00208 log_stats(path, value); 00209 } 00210 00211 /* Set the attributes */ 00212 dod(!lsetxattr(path_xattr, name, value, size, flags)); 00213 } 00214 00215 00216 00224 int 00225 is_valid_dir(const char *path) { 00226 struct stat fstats; 00227 00228 /* Validate the path */ 00229 if (stat(path, &fstats)) 00230 return 0; 00231 00232 if (!S_ISDIR(fstats.st_mode)) 00233 return 0; 00234 00235 return 1; 00236 } 00237 00238 00239 00247 int 00248 is_valid_file(const char *path) { 00249 struct stat fstats; 00250 00251 /* Validate the path */ 00252 if (stat(path, &fstats)) 00253 return 0; 00254 00255 if (!S_ISREG(fstats.st_mode)) 00256 return 0; 00257 00258 return 1; 00259 } 00260 00261 00262 00273 inline void 00274 mark_for_cleaning(inode_t inode) { 00275 int fd_log; 00276 00277 00278 /* Ensure that the file was actually written to the Shingled partition */ 00279 if (inode.entrynumber <= 0) 00280 return; 00281 00282 dod((fd_log = init_deletelog(inode.band_id)) > 0); 00283 append_deletelog(fd_log, inode.band_offset, inode.size, inode.entrynumber); 00284 close(fd_log); 00285 log(LOG_SFS_INFO, "Delete Log entry: Band %ld, RBA %ld, %d blocks, " 00286 "Append Log Entry: %d!\n", inode.band_id, 00287 inode.band_offset, inode.size, inode.entrynumber); 00288 } 00289 00290 00291 00301 inline void 00302 inode_free(int inodeno) { 00303 inode_t inode; 00304 00305 00306 /* Zero out the inode, except for the inode no. */ 00307 memset(&inode, 0, sizeof(inode_t)); 00308 inode.inode_num = inodeno; 00309 00310 /* Write out the inode data */ 00311 if (put_inode(inodeno, &inode)) 00312 exit(EXIT_FAILURE); 00313 00314 /* Mark the inode as free in the inode bitmap */ 00315 put_freeinodenum(inodeno); 00316 } 00317 00318 00319 00328 inline void 00329 inode_update(inode_t *inode, band_t band, rba_t rba, size_t size) { 00330 int fd_log; 00331 00332 00333 /* Update the band no. and offset in the file's inode */ 00334 inode->band_id = band; 00335 inode->band_offset = rba; 00336 inode->size = size; 00337 00338 /* Update the append log for the band */ 00339 dod((fd_log = init_storelog(band)) > 0); 00340 inode->entrynumber = append_storelog(fd_log, rba, size, inode->inode_num, 0); 00341 close(fd_log); 00342 00343 /* Write the updated inode to disk */ 00344 dod(!put_inode(inode->inode_num, inode)); 00345 log(LOG_SFS_INFO, "Append log entry for band %d at %d\n", 00346 band, inode->entrynumber); 00347 } 00348 00349 00350 00359 inline void 00360 inode_unlink(inode_t inode) { 00361 /* Mark the space described by the inode for cleaning */ 00362 mark_for_cleaning(inode); 00363 00364 /* Free the inode */ 00365 inode_free(inode.inode_num); 00366 }