"Fossies" - the Fresh Open Source Software Archive

Member "fuse-3.2.3/test/test_write_cache.c" (11 May 2018, 5216 Bytes) of package /linux/misc/fuse-3.2.3.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the last Fossies "Diffs" side-by-side code changes report for "test_write_cache.c": 3.1.1_vs_3.2.0.

    1 /*
    2   FUSE: Filesystem in Userspace
    3   Copyright (C) 2016 Nikolaus Rath <Nikolaus@rath.org>
    4 
    5   This program can be distributed under the terms of the GNU GPL.
    6   See the file COPYING.
    7 */
    8 
    9 
   10 #define FUSE_USE_VERSION 30
   11 
   12 #include <config.h>
   13 #include <fuse_lowlevel.h>
   14 #include <stdio.h>
   15 #include <stdlib.h>
   16 #include <string.h>
   17 #include <errno.h>
   18 #include <fcntl.h>
   19 #include <assert.h>
   20 #include <stddef.h>
   21 #include <unistd.h>
   22 #include <pthread.h>
   23 
   24 #ifndef __linux__
   25 #include <limits.h>
   26 #else
   27 #include <linux/limits.h>
   28 #endif
   29 
   30 #define FILE_INO 2
   31 #define FILE_NAME "write_me"
   32 
   33 /* Command line parsing */
   34 struct options {
   35     int writeback;
   36     int data_size;
   37 } options = {
   38     .writeback = 0,
   39     .data_size = 4096,
   40 };
   41 
   42 #define OPTION(t, p)                           \
   43     { t, offsetof(struct options, p), 1 }
   44 static const struct fuse_opt option_spec[] = {
   45     OPTION("writeback_cache", writeback),
   46     OPTION("--data-size=%d", data_size),
   47     FUSE_OPT_END
   48 };
   49 static int got_write;
   50 
   51 static void tfs_init (void *userdata, struct fuse_conn_info *conn)
   52 {
   53     (void) userdata;
   54 
   55     if(options.writeback) {
   56         assert(conn->capable & FUSE_CAP_WRITEBACK_CACHE);
   57         conn->want |= FUSE_CAP_WRITEBACK_CACHE;
   58     }
   59 }
   60 
   61 static int tfs_stat(fuse_ino_t ino, struct stat *stbuf) {
   62     stbuf->st_ino = ino;
   63     if (ino == FUSE_ROOT_ID) {
   64         stbuf->st_mode = S_IFDIR | 0755;
   65         stbuf->st_nlink = 1;
   66     }
   67 
   68     else if (ino == FILE_INO) {
   69         stbuf->st_mode = S_IFREG | 0222;
   70         stbuf->st_nlink = 1;
   71         stbuf->st_size = 0;
   72     }
   73 
   74     else
   75         return -1;
   76 
   77     return 0;
   78 }
   79 
   80 static void tfs_lookup(fuse_req_t req, fuse_ino_t parent,
   81                        const char *name) {
   82     struct fuse_entry_param e;
   83     memset(&e, 0, sizeof(e));
   84 
   85     if (parent != FUSE_ROOT_ID)
   86         goto err_out;
   87     else if (strcmp(name, FILE_NAME) == 0)
   88         e.ino = FILE_INO;
   89     else
   90         goto err_out;
   91 
   92     if (tfs_stat(e.ino, &e.attr) != 0)
   93         goto err_out;
   94     fuse_reply_entry(req, &e);
   95     return;
   96 
   97 err_out:
   98     fuse_reply_err(req, ENOENT);
   99 }
  100 
  101 static void tfs_getattr(fuse_req_t req, fuse_ino_t ino,
  102                         struct fuse_file_info *fi) {
  103     struct stat stbuf;
  104 
  105     (void) fi;
  106 
  107     memset(&stbuf, 0, sizeof(stbuf));
  108     if (tfs_stat(ino, &stbuf) != 0)
  109         fuse_reply_err(req, ENOENT);
  110     else
  111         fuse_reply_attr(req, &stbuf, 5);
  112 }
  113 
  114 static void tfs_open(fuse_req_t req, fuse_ino_t ino,
  115                      struct fuse_file_info *fi) {
  116     if (ino == FUSE_ROOT_ID)
  117         fuse_reply_err(req, EISDIR);
  118     else {
  119         assert(ino == FILE_INO);
  120         fuse_reply_open(req, fi);
  121     }
  122 }
  123 
  124 static void tfs_write(fuse_req_t req, fuse_ino_t ino, const char *buf,
  125                       size_t size, off_t off, struct fuse_file_info *fi) {
  126     (void) fi; (void) buf; (void) off;
  127     size_t expected;
  128 
  129     assert(ino == FILE_INO);
  130     expected = options.data_size;
  131     if(options.writeback)
  132         expected *= 2;
  133 
  134     if(size != expected)
  135         fprintf(stderr, "ERROR: Expected %zd bytes, got %zd\n!",
  136                 expected, size);
  137     else
  138         got_write = 1;
  139     fuse_reply_write(req, size);
  140 }
  141 
  142 static struct fuse_lowlevel_ops tfs_oper = {
  143     .init       = tfs_init,
  144     .lookup = tfs_lookup,
  145     .getattr    = tfs_getattr,
  146     .open   = tfs_open,
  147     .write  = tfs_write,
  148 };
  149 
  150 static void* run_fs(void *data) {
  151     struct fuse_session *se = (struct fuse_session*) data;
  152     assert(fuse_session_loop(se) == 0);
  153     return NULL;
  154 }
  155 
  156 static void test_fs(char *mountpoint) {
  157     char fname[PATH_MAX];
  158     char *buf;
  159     size_t dsize = options.data_size;
  160     int fd;
  161 
  162     buf = malloc(dsize);
  163     assert(buf != NULL);
  164     assert((fd = open("/dev/urandom", O_RDONLY)) != -1);
  165     assert(read(fd, buf, dsize) == dsize);
  166     close(fd);
  167 
  168     assert(snprintf(fname, PATH_MAX, "%s/" FILE_NAME,
  169                      mountpoint) > 0);
  170     fd = open(fname, O_WRONLY);
  171     if (fd == -1) {
  172         perror(fname);
  173         assert(0);
  174     }
  175 
  176     assert(write(fd, buf, dsize) == dsize);
  177     assert(write(fd, buf, dsize) == dsize);
  178     close(fd);
  179 }
  180 
  181 int main(int argc, char *argv[]) {
  182     struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
  183     struct fuse_session *se;
  184     struct fuse_cmdline_opts fuse_opts;
  185     pthread_t fs_thread;
  186 
  187     assert(fuse_opt_parse(&args, &options, option_spec, NULL) == 0);
  188     assert(fuse_parse_cmdline(&args, &fuse_opts) == 0);
  189 #ifndef __FreeBSD__    
  190     assert(fuse_opt_add_arg(&args, "-oauto_unmount") == 0);
  191 #endif
  192     se = fuse_session_new(&args, &tfs_oper,
  193                           sizeof(tfs_oper), NULL);
  194     assert (se != NULL);
  195     assert(fuse_set_signal_handlers(se) == 0);
  196     assert(fuse_session_mount(se, fuse_opts.mountpoint) == 0);
  197 
  198     /* Start file-system thread */
  199     assert(pthread_create(&fs_thread, NULL, run_fs, (void *)se) == 0);
  200 
  201     /* Write test data */
  202     test_fs(fuse_opts.mountpoint);
  203 
  204     /* Stop file system */
  205     assert(pthread_cancel(fs_thread) == 0);
  206 
  207     fuse_session_unmount(se);
  208     assert(got_write == 1);
  209     fuse_remove_signal_handlers(se);
  210     fuse_session_destroy(se);
  211 
  212     printf("Test completed successfully.\n");
  213     return 0;
  214 }
  215 
  216 
  217 /**
  218  * Local Variables:
  219  * mode: c
  220  * indent-tabs-mode: nil
  221  * c-basic-offset: 4
  222  * End:
  223  */