"Fossies" - the Fresh Open Source Software Archive

Member "fuse-3.10.4/doc/html/fuse-3_810_83_2test_2test__write__cache_8c_source.html" (9 Jun 2021, 47508 Bytes) of package /linux/misc/fuse-3.10.4.tar.xz:


Caution: In this restricted "Fossies" environment the current HTML page may not be correctly presentated and may have some non-functional links. You can here alternatively try to browse the pure source code or just view or download the uninterpreted raw source code. If the rendering is insufficient you may try to find and view the page on the project site itself.

libfuse
test_write_cache.c
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 GPLv2.
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),
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);
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  free(buf);
179  close(fd);
180 }
181 
182 int main(int argc, char *argv[]) {
183  struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
184  struct fuse_session *se;
185  struct fuse_cmdline_opts fuse_opts;
186  pthread_t fs_thread;
187 
188  assert(fuse_opt_parse(&args, &options, option_spec, NULL) == 0);
189  assert(fuse_parse_cmdline(&args, &fuse_opts) == 0);
190 #ifndef __FreeBSD__
191  assert(fuse_opt_add_arg(&args, "-oauto_unmount") == 0);
192 #endif
193  se = fuse_session_new(&args, &tfs_oper,
194  sizeof(tfs_oper), NULL);
195  fuse_opt_free_args(&args);
196  assert (se != NULL);
197  assert(fuse_set_signal_handlers(se) == 0);
198  assert(fuse_session_mount(se, fuse_opts.mountpoint) == 0);
199 
200  /* Start file-system thread */
201  assert(pthread_create(&fs_thread, NULL, run_fs, (void *)se) == 0);
202 
203  /* Write test data */
204  test_fs(fuse_opts.mountpoint);
205  free(fuse_opts.mountpoint);
206 
207  /* Stop file system */
208  fuse_session_exit(se);
210  assert(pthread_join(fs_thread, NULL) == 0);
211 
212  assert(got_write == 1);
215 
216  printf("Test completed successfully.\n");
217  return 0;
218 }
219 
220 
unsigned capable
Definition: fuse_common.h:459
struct fuse_session * fuse_session_new(struct fuse_args *args, const struct fuse_lowlevel_ops *op, size_t op_size, void *userdata)
int fuse_reply_open(fuse_req_t req, const struct fuse_file_info *fi)
int fuse_reply_entry(fuse_req_t req, const struct fuse_entry_param *e)
void fuse_session_destroy(struct fuse_session *se)
int fuse_session_loop(struct fuse_session *se)
Definition: fuse_loop.c:19
Definition: fuse_lowlevel.h:59
struct fuse_req * fuse_req_t
Definition: fuse_lowlevel.h:49
void fuse_session_exit(struct fuse_session *se)
int fuse_set_signal_handlers(struct fuse_session *se)
Definition: fuse_signals.c:62
int fuse_session_mount(struct fuse_session *se, const char *mountpoint)
void fuse_opt_free_args(struct fuse_args *args)
Definition: fuse_opt.c:34
#define FUSE_CAP_WRITEBACK_CACHE
Definition: fuse_common.h:296
#define FUSE_OPT_END
Definition: fuse_opt.h:104
int fuse_opt_add_arg(struct fuse_args *args, const char *arg)
Definition: fuse_opt.c:55
int fuse_reply_err(fuse_req_t req, int err)
int fuse_reply_attr(fuse_req_t req, const struct stat *attr, double attr_timeout)
int fuse_parse_cmdline(struct fuse_args *args, struct fuse_cmdline_opts *opts)
Definition: helper.c:202
uint64_t fuse_ino_t
Definition: fuse_lowlevel.h:46
#define FUSE_ROOT_ID
Definition: fuse_lowlevel.h:43
int fuse_opt_parse(struct fuse_args *args, void *data, const struct fuse_opt opts[], fuse_opt_proc_t proc)
Definition: fuse_opt.c:398
void fuse_session_unmount(struct fuse_session *se)
unsigned want
Definition: fuse_common.h:467
int fuse_reply_write(fuse_req_t req, size_t count)
#define FUSE_ARGS_INIT(argc, argv)
Definition: fuse_opt.h:123
void fuse_remove_signal_handlers(struct fuse_session *se)
Definition: fuse_signals.c:79
void(* init)(void *userdata, struct fuse_conn_info *conn)