ShingledFS 2.0
SMR-AwareFUSE-basedFileSystem

profiler.c

Go to the documentation of this file.
00001 
00012 #define FUSE_USE_VERSION 26
00013 
00014 #define _XOPEN_SOURCE 500
00015 
00016 #include <fuse.h>
00017 #include <fcntl.h>
00018 #include <stdio.h>
00019 #include <errno.h>
00020 #include <dirent.h>
00021 #include <limits.h>
00022 #include <string.h>
00023 #include <stdlib.h>
00024 #include <unistd.h>
00025 #include <sys/xattr.h>
00026 #include <sys/types.h>
00027 
00028 #include <semaphore.h>
00029 #include <pthread.h>
00030 #include <signal.h>
00031 
00032 
00033 
00034 /* ======================= */
00035 /* -- Macro Definitions -- */
00036 /* ======================= */
00037 
00038 #define GETATTR      0
00039 #define READLINK     1
00040 #define MKNOD        2
00041 #define MKDIR        3
00042 #define UNLINK       4
00043 #define RMDIR        5
00044 #define SYMLINK      6
00045 #define RENAME       7
00046 #define LINK         8
00047 #define CHMOD        9
00048 #define CHOWN       10
00049 #define TRUNCATE    11
00050 #define UTIME       12
00051 #define OPEN        13
00052 #define READ        14
00053 #define WRITE       15
00054 #define STATFS      16
00055 #define RELEASE     17
00056 #define FSYNC       18
00057 #define SETXATTR    19
00058 #define GETXATTR    20
00059 #define LISTXATTR   21
00060 #define REMOVEXATTR 22
00061 #define OPENDIR     23
00062 #define READDIR     24
00063 #define RELEASEDIR  25
00064 #define ACCESS      26
00065 
00066 static int counters[27] = {0};
00067 static FILE *file;
00068 
00069 
00070 
00071 /* ====================== */
00072 /* -- Static Variables -- */
00073 /* ====================== */
00074 
00075 static char base[PATH_MAX];
00076 static sem_t sem_profiler;
00077 
00078 
00079 
00080 /* ============================== */
00081 /* -- Function Implementations -- */
00082 /* ============================== */
00083 
00084 
00085 void *profiler() {
00086         while(1) {
00087                 /* Wait for a profiling signal */
00088                 sem_wait(&sem_profiler);
00089 
00090 
00091             /* Open the file to write the application's profile */
00092             file = fopen("/tmp/profile.out", "a+");
00093             fprintf(file, "Profile:\n");
00094             fprintf(file, "getattr()\t%d\n", counters[GETATTR]);
00095             fprintf(file, "readlink()\t%d\n", counters[READLINK]);
00096             fprintf(file, "mknod()\t%d\n", counters[MKNOD]);
00097             fprintf(file, "mkdir()\t%d\n", counters[MKDIR]);
00098             fprintf(file, "unlink()\t%d\n", counters[UNLINK]);
00099             fprintf(file, "rmdir()\t%d\n", counters[RMDIR]);
00100             fprintf(file, "symlink()\t%d\n", counters[SYMLINK]);
00101             fprintf(file, "rename()\t%d\n", counters[RENAME]);
00102             fprintf(file, "link()\t%d\n", counters[LINK]);
00103             fprintf(file, "chmod()\t%d\n", counters[CHMOD]);
00104             fprintf(file, "chown()\t%d\n", counters[CHOWN]);
00105             fprintf(file, "truncate()\t%d\n", counters[TRUNCATE]);
00106             fprintf(file, "utime()\t%d\n", counters[UTIME]);
00107             fprintf(file, "open()\t%d\n", counters[OPEN]);
00108             fprintf(file, "read()\t%d\n", counters[READ]);
00109             fprintf(file, "write()\t%d\n", counters[WRITE]);
00110             fprintf(file, "statfs()\t%d\n", counters[STATFS]);
00111             fprintf(file, "release()\t%d\n", counters[RELEASE]);
00112             fprintf(file, "fsync()\t%d\n", counters[FSYNC]);
00113             fprintf(file, "setxattr()\t%d\n", counters[SETXATTR]);
00114             fprintf(file, "getxattr()\t%d\n", counters[GETXATTR]);
00115             fprintf(file, "listxattr()\t%d\n", counters[LISTXATTR]);
00116             fprintf(file, "removexattr()\t%d\n", counters[REMOVEXATTR]);
00117             fprintf(file, "opendir()\t%d\n", counters[OPENDIR]);
00118             fprintf(file, "readdir()\t%d\n", counters[READDIR]);
00119             fprintf(file, "releasedir()\t%d\n", counters[RELEASEDIR]);
00120             fprintf(file, "access()\t%d\n", counters[ACCESS]);
00121             fprintf(file, "\n\n");
00122             fclose(file);
00123         }
00124 
00125         return NULL;
00126 }
00127 
00128 
00129 
00130 void sig_handler(int sig) {
00131     /* Check the signal received */
00132     if (sig == SIGUSR1) {
00133         fprintf(stderr, "Signaling...\n");
00134         sem_post(&sem_profiler);
00135         signal(sig, sig_handler);
00136     }
00137 
00138 }
00139 
00140 
00141 
00146 void
00147 fullpath (const char *path, char *buf)
00148 {
00149         char *basedir = (char *) fuse_get_context ()->private_data;
00150 
00151         strcpy (buf, basedir);
00152         strcat (buf, path);
00153 }
00154 
00155 
00156 /* The following functions describe FUSE operations. Each operation appends
00157    the path of the root filesystem to the given path in order to give the
00158    mirrored path. All quota checking takes place in fuse_write. */
00159 
00160 int
00161 fuse_getattr (const char *path, struct stat *buf)
00162 {
00163         char fpath[PATH_MAX];
00164         int retval;
00165         fullpath (path, fpath);
00166 
00167     counters[GETATTR]++;
00168         retval = lstat (fpath, buf) ? -errno : 0;
00169         return retval;
00170 }
00171 
00172 int
00173 fuse_readlink (const char *path, char *target, size_t size)
00174 {
00175         char fpath[PATH_MAX];
00176         int retval;
00177         fullpath (path, fpath);
00178 
00179     counters[READLINK]++;
00180         retval = readlink (fpath, target, size);
00181         if (retval > 0) {
00182             if (retval == size)
00183                 retval--;
00184             target[retval] = '\0';
00185             retval = 0;
00186         }
00187         return retval;
00188 }
00189 
00190 int
00191 fuse_mknod (const char *path, mode_t mode, dev_t dev)
00192 {
00193         char fpath[PATH_MAX];
00194         int retval;
00195         fullpath (path, fpath);
00196 
00197     counters[MKNOD]++;
00198         retval = mknod (fpath, mode | S_IRUSR | S_IWUSR, dev) ? -errno : 0;
00199         return retval;
00200 }
00201 
00202 int
00203 fuse_mkdir (const char *path, mode_t mode)
00204 {
00205         char fpath[PATH_MAX];
00206         int retval;
00207         fullpath (path, fpath);
00208 
00209     counters[MKDIR]++;
00210         retval = mkdir (fpath, mode | S_IFDIR) ? -errno : 0;
00211         return retval;
00212 }
00213 
00214 int
00215 fuse_unlink (const char *path)
00216 {
00217         char fpath[PATH_MAX];
00218         int retval;
00219         fullpath (path, fpath);
00220 
00221     counters[UNLINK]++;
00222         retval = unlink (fpath) ? -errno : 0;
00223         return retval;
00224 }
00225 
00226 int
00227 fuse_rmdir (const char *path)
00228 {
00229         char fpath[PATH_MAX];
00230         int retval;
00231         fullpath (path, fpath);
00232 
00233     counters[RMDIR]++;
00234         retval = rmdir (fpath) ? -errno : 0;
00235         return retval;
00236 }
00237 
00238 int
00239 fuse_symlink (const char *path, const char *link)
00240 {
00241         char flink[PATH_MAX];
00242         int retval;
00243         fullpath (link, flink);
00244 
00245     counters[SYMLINK]++;
00246         retval = symlink (path, flink) ? -errno : 0;
00247         return retval;
00248 }
00249 
00250 int
00251 fuse_rename (const char *src, const char *dst)
00252 {
00253         char fsrc[PATH_MAX];
00254         char fdst[PATH_MAX];
00255         int retval;
00256         fullpath (src, fsrc);
00257         fullpath (dst, fdst);
00258 
00259     counters[RENAME]++;
00260         retval = rename (fsrc, fdst) ? -errno : 0;
00261         return retval;
00262 }
00263 
00264 int
00265 fuse_link (const char *src, const char *dst)
00266 {
00267         char fsrc[PATH_MAX];
00268         char fdst[PATH_MAX];
00269         int retval;
00270         fullpath (src, fsrc);
00271         fullpath (dst, fdst);
00272 
00273     counters[LINK]++;
00274         retval = link (fsrc, fdst) ? -errno : 0;
00275         return retval;
00276 }
00277 
00278 int
00279 fuse_chmod (const char *path, mode_t mode)
00280 {
00281         char fpath[PATH_MAX];
00282         int retval;
00283         fullpath (path, fpath);
00284 
00285     counters[CHMOD]++;
00286         retval = chmod (fpath, mode) ? -errno : 0;
00287         return retval;
00288 }
00289 
00290 int
00291 fuse_chown (const char *path, uid_t uid, gid_t gid)
00292 {
00293         char fpath[PATH_MAX];
00294         int retval;
00295         fullpath (path, fpath);
00296 
00297     counters[CHOWN]++;
00298         retval = chown (fpath, uid, gid) ? -errno : 0;
00299         return retval;
00300 }
00301 
00302 int
00303 fuse_truncate (const char *path, off_t off)
00304 {
00305         char fpath[PATH_MAX];
00306         int retval;
00307         fullpath (path, fpath);
00308 
00309     counters[TRUNCATE]++;
00310         retval = truncate (fpath, off) ? -errno : 0;
00311         return retval;
00312 }
00313 
00314 int
00315 fuse_utime (const char *path, struct utimbuf *buf)
00316 {
00317         char fpath[PATH_MAX];
00318         int retval;
00319         fullpath (path, fpath);
00320 
00321     counters[UTIME]++;
00322         retval = utime (fpath, buf) ? -errno : 0;
00323         return retval;
00324 }
00325 
00326 int
00327 fuse_open (const char *path, struct fuse_file_info *fi)
00328 {
00329         char fpath[PATH_MAX];
00330         int retval;
00331         fullpath (path, fpath);
00332 
00333     counters[OPEN]++;
00334         int fh = open (fpath, fi->flags);
00335         if (fh < 0)
00336                 retval = -errno;
00337         else {
00338                 fi->fh = fh;
00339                 retval = 0;
00340         }
00341 
00342         return retval;
00343 }
00344 
00345 int
00346 fuse_read (const char *path, char *buf, size_t size, off_t off,
00347                 struct fuse_file_info *fi)
00348 {
00349         int retval;
00350 
00351     counters[READ]++;
00352         retval = pread (fi->fh, buf, size, off) < 0 ? -errno : size;
00353         return retval;
00354 }
00355 
00356 int
00357 fuse_write (const char *path, const char *buf, size_t size, off_t off,
00358                 struct fuse_file_info *fi)
00359 {
00360         int retval;
00361 
00362     counters[WRITE]++;
00363         retval = pwrite (fi->fh, buf, size, off) < 0 ? -errno : size;
00364         return retval;
00365 }
00366 
00367 int
00368 fuse_statfs (const char *path, struct statvfs *buf)
00369 {
00370         char fpath[PATH_MAX];
00371         int retval;
00372         fullpath (path, fpath);
00373 
00374     counters[STATFS]++;
00375         retval = statvfs (fpath, buf) ? -errno : 0;
00376         return retval;
00377 }
00378 
00379 int
00380 fuse_release (const char *path, struct fuse_file_info *fi)
00381 {
00382         int retval;
00383 
00384     counters[RELEASE]++;
00385         retval = close (fi->fh) ? -errno : 0;
00386         return retval;
00387 }
00388 
00389 int
00390 fuse_fsync (const char *path, int datasync, struct fuse_file_info *fi)
00391 {
00392         int retval;
00393 
00394     counters[FSYNC]++;
00395         if (datasync)
00396                 retval = fdatasync (fi->fh) ? -errno : 0;
00397         else
00398                 retval = fsync (fi->fh) ? -errno : 0;
00399 
00400         return retval;
00401 }
00402 
00403 int
00404 fuse_setxattr (const char *path, const char *name, const char *value,
00405                 size_t size, int flags)
00406 {
00407         char fpath[PATH_MAX];
00408         int retval;
00409         fullpath (path, fpath);
00410 
00411     counters[SETXATTR]++;
00412         retval = lsetxattr (fpath, name, value, size, flags) ? -errno : 0;
00413         return retval;
00414 }
00415 
00416 int
00417 fuse_getxattr (const char *path, const char *name, char *value, size_t size)
00418 {
00419         char fpath[PATH_MAX];
00420         int retval;
00421         fullpath (path, fpath);
00422 
00423     counters[GETXATTR]++;
00424         ssize_t s = lgetxattr (fpath, name, value, size);
00425         retval = s < 0 ? -errno : s;
00426         return retval;
00427 }
00428 
00429 int
00430 fuse_listxattr (const char *path, char *list, size_t size)
00431 {
00432         char fpath[PATH_MAX];
00433         int retval;
00434         fullpath (path, fpath);
00435 
00436     counters[LISTXATTR]++;
00437         retval = llistxattr (fpath, list, size) < 0 ? -errno : 0;
00438         return retval;
00439 }
00440 
00441 int
00442 fuse_removexattr (const char *path, const char *name)
00443 {
00444         char fpath[PATH_MAX];
00445         int retval;
00446         fullpath (path, fpath);
00447 
00448     counters[GETATTR]++;
00449         retval = lremovexattr (fpath, name) ? -errno : 0;
00450         return retval;
00451 }
00452 
00453 int
00454 fuse_opendir (const char *path, struct fuse_file_info *fi)
00455 {
00456         char fpath[PATH_MAX];
00457         int retval;
00458         fullpath (path, fpath);
00459 
00460     counters[OPENDIR]++;
00461         DIR *dir = opendir (fpath);
00462         if (dir == NULL)
00463                 retval = -errno;
00464         else {
00465                 fi->fh = (uint64_t) dir;
00466                 retval = 0;
00467         }
00468 
00469         return retval;
00470 }
00471 
00472 int
00473 fuse_readdir (const char *path, void *buf, fuse_fill_dir_t fill, off_t off,
00474                 struct fuse_file_info *fi)
00475 {
00476         struct dirent *de = NULL;
00477 
00478     counters[READDIR]++;
00479         while ((de = readdir ((DIR *) fi->fh)) != NULL)
00480         {
00481                 struct stat st;
00482                 memset (&st, 0, sizeof (struct stat));
00483                 st.st_ino = de->d_ino;
00484                 st.st_mode = de->d_type << 12;
00485 
00486                 if (fill (buf, de->d_name, &st, 0))
00487                         break;
00488         }
00489 
00490         return 0;
00491 }
00492 
00493 int
00494 fuse_releasedir (const char *path, struct fuse_file_info *fi)
00495 {
00496         int retval;
00497 
00498     counters[RELEASEDIR]++;
00499         retval = closedir ((DIR *) fi->fh) ? -errno : 0;
00500         return retval;
00501 }
00502 
00503 int
00504 fuse_access (const char *path, int mode)
00505 {
00506         char fpath[PATH_MAX];
00507         int retval;
00508         fullpath (path, fpath);
00509 
00510     counters[ACCESS]++;
00511         retval = access (fpath, mode) ? -errno : 0;
00512         return retval;
00513 }
00514 
00515 void *
00516 fuse_init (struct fuse_conn_info *conn)
00517 {
00518         pthread_t tid;
00519         int err;
00520 
00521     /* Initialize the semaphore */
00522         if ((err = sem_init(&sem_profiler, 0, 0)) != 0)
00523                 exit(EXIT_FAILURE);
00524 
00525         /* Install the signal handler */
00526     signal(SIGUSR1, sig_handler);
00527 
00528     /* Spawn a thread to profile the application */
00529         if ((err = pthread_create(&tid, NULL, profiler, NULL)) != 0)
00530                 exit(EXIT_FAILURE);
00531 
00532         return (fuse_get_context())->private_data;
00533 }
00534 
00535 
00536 
00537 struct fuse_operations fuse_ops = {
00538                 .getattr = fuse_getattr,
00539                 .readlink = fuse_readlink,
00540                 .mknod = fuse_mknod,
00541                 .mkdir = fuse_mkdir,
00542                 .unlink = fuse_unlink,
00543                 .rmdir = fuse_rmdir,
00544                 .symlink = fuse_symlink,
00545                 .rename = fuse_rename,
00546                 .link = fuse_link,
00547                 .chmod = fuse_chmod,
00548                 .chown = fuse_chown,
00549                 .truncate = fuse_truncate,
00550                 .utime = fuse_utime,
00551                 .open = fuse_open,
00552                 .read = fuse_read,
00553                 .write = fuse_write,
00554                 .statfs = fuse_statfs,
00555                 .release = fuse_release,
00556                 .fsync = fuse_fsync,
00557                 .setxattr = fuse_setxattr,
00558                 .getxattr = fuse_getxattr,
00559                 .listxattr = fuse_listxattr,
00560                 .removexattr = fuse_removexattr,
00561                 .opendir = fuse_opendir,
00562                 .readdir = fuse_readdir,
00563                 .releasedir = fuse_releasedir,
00564                 .access = fuse_access,
00565                 .init = fuse_init,
00566 };
00567 
00568 
00569 
00570 void
00571 usage ()
00572 {
00573         printf ("transparency <basedir> <mountpoint>\n");
00574         exit (0);
00575 }
00576 
00577 
00578 
00579 int
00580 main (int argc, char *argv[])
00581 {
00582         if (argc < 3)
00583                 usage ();
00584 
00585         if (realpath(argv[1], base) == NULL)
00586                 printf("The base directory path %s is invalid!\n", argv[1]);
00587 
00588         int i = 1;
00589         for (; i < argc; i++)
00590                 argv[i] = argv[i + 1];
00591         argc -= 1;
00592 
00593         umask(0);
00594         int ret = fuse_main (argc, argv, &fuse_ops, base);
00595         if (ret < 0)
00596                 printf("Error in FUSE main()\n");
00597     else
00598         printf("Output will be found in /tmp/profile.out\n");
00599 
00600         return ret;
00601 }