ShingledFS 2.0
SMR-AwareFUSE-basedFileSystem

helper.c

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