ShingledFS 2.0
SMR-AwareFUSE-basedFileSystem
|
00001 00009 #define FUSE_USE_VERSION 26 00010 00011 00012 #include <fuse.h> 00013 #include <errno.h> 00014 #include <stdio.h> 00015 #include <string.h> 00016 #include <stdlib.h> 00017 #include <unistd.h> 00018 #include <sys/types.h> 00019 #include <sys/xattr.h> 00020 #include <limits.h> 00021 00022 #include "helper.h" 00023 #include "shingledfs.h" 00024 00025 00026 00027 /* ======================= */ 00028 /* -- Macro Definitions -- */ 00029 /* ======================= */ 00030 00031 #define ARG_COUNT_MIN 4 00032 00033 #define ARG_PATH_UNSHINGLED 1 00034 #define ARG_PATH_TMPFS 2 00035 #define ARG_PATH_EDI 3 00036 00037 #define ARG_SINGLE_THREADED "-s" 00038 #define ARG_FOREGROUND_EXEC "-f" 00039 //#define ARG_FSNAME "-ofsname=ShingledFS" 00040 00041 00042 00043 /* ====================== */ 00044 /* -- Static Variables -- */ 00045 /* ====================== */ 00046 00050 struct fuse_operations shingledfs_ops = { 00051 .init = shingledfs_init, 00052 // .destroy = shingledfs_destroy, 00053 00054 .mkdir = shingledfs_mkdir, 00055 .rmdir = shingledfs_rmdir, 00056 .opendir = shingledfs_opendir, 00057 .readdir = shingledfs_readdir, 00058 .releasedir = shingledfs_releasedir, 00059 00060 .mknod = shingledfs_mknod, 00061 .open = shingledfs_open, 00062 .read = shingledfs_read, 00063 .write = shingledfs_write, 00064 .flush = shingledfs_flush, 00065 .release = shingledfs_release, 00066 .rename = shingledfs_rename, 00067 .unlink = shingledfs_unlink, 00068 .truncate = shingledfs_truncate, 00069 00070 .getattr = shingledfs_getattr, 00071 .fgetattr = shingledfs_fgetattr, 00072 .setxattr = shingledfs_setxattr, 00073 .getxattr = shingledfs_getxattr, 00074 .listxattr = shingledfs_listxattr, 00075 .removexattr = shingledfs_removexattr, 00076 00077 .access = shingledfs_access, 00078 .utime = shingledfs_utime, 00079 .chmod = shingledfs_chmod, 00080 .chown = shingledfs_chown, 00081 00082 .symlink = shingledfs_symlink, 00083 .readlink = shingledfs_readlink, 00084 .link = shingledfs_link, 00085 .statfs = shingledfs_statfs, 00086 00087 // .ftruncate = shingledfs_ftruncate, 00088 // .fsync = shingledfs_fsync, 00089 // .fsyncdir = NULL, 00090 }; 00091 00092 00093 00094 /* ================================================= */ 00095 /* -- Usage and Command-line Arguments Processing -- */ 00096 /* ================================================= */ 00097 00101 static void 00102 usage(const char *program_name) 00103 { 00104 fprintf(stderr, 00105 "USAGE: %s <Unshingled path> <tmpFS path> <EDI path> <FUSE mount path>\n", 00106 program_name); 00107 abort(); 00108 } 00109 00110 00111 00127 static void 00128 process_args(int *argc, 00129 char *argv[]) { 00130 int i, arg_error = 0; 00131 int is_singled_threaded = 0; 00132 00133 00134 /* Ensure that the arguments are available */ 00135 if (*argc < ARG_COUNT_MIN) 00136 usage(argv[0]); 00137 00138 00139 /* Strip out any terminating /'s in the path to the directories */ 00140 i = strlen(argv[ARG_PATH_UNSHINGLED]) - 1; 00141 if (argv[ARG_PATH_UNSHINGLED][i] == '/') 00142 argv[ARG_PATH_UNSHINGLED][i] = '\0'; 00143 00144 i = strlen(argv[ARG_PATH_TMPFS]) - 1; 00145 if (argv[ARG_PATH_TMPFS][i] == '/') 00146 argv[ARG_PATH_TMPFS][i] = '\0'; 00147 00148 00149 /* Validate the path to the Unshingled partition */ 00150 if (!is_valid_dir(argv[ARG_PATH_UNSHINGLED])) { 00151 arg_error = 1; 00152 fprintf(stderr, 00153 "Error accessing %s. Please ensure it is a valid directory!\n", 00154 argv[ARG_PATH_UNSHINGLED]); 00155 } 00156 00157 /* Validate the path to the tmpFS partition */ 00158 if (!is_valid_dir(argv[ARG_PATH_TMPFS])) { 00159 arg_error = 1; 00160 fprintf(stderr, 00161 "Error accessing %s. Please ensure it is a valid directory!\n", 00162 argv[ARG_PATH_TMPFS]); 00163 } 00164 00165 /* Validate the path to the Emulated Disk Image */ 00166 if (!is_valid_file(argv[ARG_PATH_EDI])) { 00167 arg_error = 1; 00168 fprintf(stderr, 00169 "Error accessing %s. Please ensure it is a valid file!\n", 00170 argv[ARG_PATH_EDI]); 00171 } 00172 00173 00174 /* Check if there are any errors */ 00175 if (arg_error) 00176 usage(argv[0]); 00177 00178 00179 /* Store the arguments */ 00180 strcpy(shingledfs_data.path_unshingled, argv[ARG_PATH_UNSHINGLED]); 00181 strcpy(shingledfs_data.path_tmpfs, argv[ARG_PATH_TMPFS]); 00182 strcpy(shingledfs_data.path_edi, argv[ARG_PATH_EDI]); 00183 00184 dbg("Unshingled path: %s\n", shingledfs_data.path_unshingled); 00185 dbg("tmpFS path: %s\n", shingledfs_data.path_tmpfs); 00186 dbg("EDI path: %s\n", shingledfs_data.path_edi); 00187 00188 00189 /* Adjust the argument count and remove the Shingled FS arguments */ 00190 *argc -= ARG_COUNT_MIN - 1; 00191 for(i=0; i<(*argc); i++) { 00192 /* Move the argument forward */ 00193 argv[i] = argv[i + ARG_COUNT_MIN - 1]; 00194 00195 /* Check if the argument is the -s flag for single-threaded execution */ 00196 if (strcasecmp(argv[i], ARG_SINGLE_THREADED) == 0) 00197 is_singled_threaded = 1; 00198 } 00199 00200 /* @todo Ensure that the File System Name is passed */ 00201 // argv[(*argc)++] = ARG_FSNAME; 00202 00203 /* Ensure that the process is running in single-threaded mode */ 00204 if (!is_singled_threaded) 00205 argv[(*argc)++] = ARG_SINGLE_THREADED; 00206 00207 #ifdef DEBUG 00208 /* When running in debug mode, ensure that FUSE runs in the foreground */ 00209 argv[(*argc)++] = ARG_FOREGROUND_EXEC; 00210 #endif 00211 00212 00213 /* Null-terminate the arguments array */ 00214 argv[*argc] = NULL; 00215 } 00216 00217 00218 00219 /* =================== */ 00220 /* -- Main Function -- */ 00221 /* =================== */ 00222 00223 int 00224 main(int argc, 00225 char *argv[]) { 00226 /* Process the arguments */ 00227 process_args(&argc, argv); 00228 00229 /* Reset the umask to ensure all permissions get set exactly as specified */ 00230 umask(0); 00231 00232 /* Kick start FUSE */ 00233 return fuse_main(argc, argv, &shingledfs_ops, &shingledfs_data); 00234 }