1 /*
2 Copyright 2005-2010 Jakub Kruszona-Zawadzki, Gemius SA, 2013-2014 EditShare, 2013-2015 Skytechnology sp. z o.o..
3
4 This file was part of MooseFS and is part of LizardFS.
5
6 LizardFS is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, version 3.
9
10 LizardFS is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with LizardFS If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "common/platform.h"
20
21 #include <errno.h>
22 #include <fstream>
23 #include <fuse/fuse.h>
24
25 #include "common/crc.h"
26 #include "common/md5.h"
27 #include "protocol/MFSCommunication.h"
28 #include "common/mfserr.h"
29 #include "common/sockets.h"
30 #include "mount/fuse/mfs_fuse.h"
31 #include "mount/fuse/mfs_meta_fuse.h"
32 #include "mount/fuse/mount_config.h"
33 #include "mount/g_io_limiters.h"
34 #include "mount/mastercomm.h"
35 #include "mount/masterproxy.h"
36 #include "mount/readdata.h"
37 #include "mount/stats.h"
38 #include "mount/symlinkcache.h"
39 #include "mount/writedata.h"
40
41 #define STR_AUX(x) #x
42 #define STR(x) STR_AUX(x)
43
44 static void mfs_fsinit (void *userdata, struct fuse_conn_info *conn);
45
46 static struct fuse_lowlevel_ops mfs_meta_oper;
47
48 static struct fuse_lowlevel_ops mfs_oper;
49
init_fuse_lowlevel_ops()50 static void init_fuse_lowlevel_ops() {
51 mfs_meta_oper.init = mfs_fsinit;
52 mfs_meta_oper.statfs = mfs_meta_statfs;
53 mfs_meta_oper.lookup = mfs_meta_lookup;
54 mfs_meta_oper.getattr = mfs_meta_getattr;
55 mfs_meta_oper.setattr = mfs_meta_setattr;
56 mfs_meta_oper.unlink = mfs_meta_unlink;
57 mfs_meta_oper.rename = mfs_meta_rename;
58 mfs_meta_oper.opendir = mfs_meta_opendir;
59 mfs_meta_oper.readdir = mfs_meta_readdir;
60 mfs_meta_oper.releasedir = mfs_meta_releasedir;
61 mfs_meta_oper.open = mfs_meta_open;
62 mfs_meta_oper.release = mfs_meta_release;
63 mfs_meta_oper.read = mfs_meta_read;
64 mfs_meta_oper.write = mfs_meta_write;
65
66 mfs_oper.init = mfs_fsinit;
67 mfs_oper.statfs = mfs_statfs;
68 mfs_oper.lookup = mfs_lookup;
69 mfs_oper.getattr = mfs_getattr;
70 mfs_oper.setattr = mfs_setattr;
71 mfs_oper.mknod = mfs_mknod;
72 mfs_oper.unlink = mfs_unlink;
73 mfs_oper.mkdir = mfs_mkdir;
74 mfs_oper.rmdir = mfs_rmdir;
75 mfs_oper.symlink = mfs_symlink;
76 mfs_oper.readlink = mfs_readlink;
77 mfs_oper.rename = mfs_rename;
78 mfs_oper.link = mfs_link;
79 mfs_oper.opendir = mfs_opendir;
80 mfs_oper.readdir = mfs_readdir;
81 mfs_oper.releasedir = mfs_releasedir;
82 mfs_oper.create = mfs_create;
83 mfs_oper.open = mfs_open;
84 mfs_oper.release = mfs_release;
85 mfs_oper.flush = mfs_flush;
86 mfs_oper.fsync = mfs_fsync;
87 mfs_oper.read = mfs_read;
88 mfs_oper.write = mfs_write;
89 mfs_oper.access = mfs_access;
90 mfs_oper.getxattr = mfs_getxattr;
91 mfs_oper.setxattr = mfs_setxattr;
92 mfs_oper.listxattr = mfs_listxattr;
93 mfs_oper.removexattr = mfs_removexattr;
94 #if FUSE_VERSION >= 26
95 if (gMountOptions.filelocks) {
96 mfs_oper.getlk = lzfs_getlk;
97 mfs_oper.setlk = lzfs_setlk;
98 }
99 #endif
100 #if FUSE_VERSION >= 29
101 if (gMountOptions.filelocks) {
102 mfs_oper.flock = lzfs_flock;
103 }
104 #endif
105 }
106
mfs_fsinit(void * userdata,struct fuse_conn_info * conn)107 static void mfs_fsinit (void *userdata, struct fuse_conn_info *conn) {
108 #if (FUSE_VERSION >= 28)
109 conn->want |= FUSE_CAP_DONT_MASK;
110 #else
111 (void)conn;
112 #endif
113
114 int *piped = (int*)userdata;
115 if (piped[1]>=0) {
116 char s = 0;
117 if (write(piped[1],&s,1)!=1) {
118 lzfs_pretty_syslog(LOG_ERR,"pipe write error: %s",strerr(errno));
119 }
120 close(piped[1]);
121 }
122 }
123
mainloop(struct fuse_args * args,const char * mp,int mt,int fg)124 int mainloop(struct fuse_args *args,const char* mp,int mt,int fg) {
125 struct fuse_session *se;
126 struct fuse_chan *ch;
127 struct rlimit rls;
128 int piped[2];
129 char s;
130 int err;
131 int i;
132 md5ctx ctx;
133 std::vector<uint8_t> md5pass;
134
135 if (gMountOptions.passwordask && gMountOptions.password==NULL
136 && gMountOptions.md5pass==NULL) {
137 gMountOptions.password = getpass("MFS Password:");
138 }
139 if (gMountOptions.password) {
140 md5pass.resize(16);
141 md5_init(&ctx);
142 md5_update(&ctx,(uint8_t*)(gMountOptions.password),
143 strlen(gMountOptions.password));
144 md5_final(md5pass.data(),&ctx);
145 memset(gMountOptions.password,0,strlen(gMountOptions.password));
146 } else if (gMountOptions.md5pass) {
147 int ret = md5_parse(md5pass, gMountOptions.md5pass);
148 if (ret < 0) {
149 fprintf(stderr,"bad md5 definition (md5 should be given as 32 hex digits)\n");
150 return 1;
151 }
152 memset(gMountOptions.md5pass,0,strlen(gMountOptions.md5pass));
153 }
154
155 if (fg==0) {
156 openlog(STR(APPNAME), LOG_PID | LOG_NDELAY , LOG_DAEMON);
157 } else {
158 #if defined(LOG_PERROR)
159 openlog(STR(APPNAME), LOG_PID | LOG_NDELAY | LOG_PERROR, LOG_USER);
160 #else
161 openlog(STR(APPNAME), LOG_PID | LOG_NDELAY, LOG_USER);
162 #endif
163 }
164 lzfs::add_log_syslog();
165
166 rls.rlim_cur = gMountOptions.nofile;
167 rls.rlim_max = gMountOptions.nofile;
168 setrlimit(RLIMIT_NOFILE,&rls);
169
170 setpriority(PRIO_PROCESS,getpid(),gMountOptions.nice);
171 #ifdef MFS_USE_MEMLOCK
172 if (gMountOptions.memlock) {
173 rls.rlim_cur = RLIM_INFINITY;
174 rls.rlim_max = RLIM_INFINITY;
175 if (setrlimit(RLIMIT_MEMLOCK,&rls)<0) {
176 gMountOptions.memlock=0;
177 }
178 }
179 #endif
180
181 piped[0] = piped[1] = -1;
182 if (fg==0) {
183 if (pipe(piped)<0) {
184 fprintf(stderr,"pipe error\n");
185 return 1;
186 }
187 err = fork();
188 if (err<0) {
189 fprintf(stderr,"fork error\n");
190 return 1;
191 } else if (err > 0) {
192 std::fill(md5pass.begin(), md5pass.end(), 0);
193 close(piped[1]);
194 err = read(piped[0],&s,1);
195 if (err==0) {
196 s=1;
197 }
198 return s;
199 }
200 close(piped[0]);
201 s=1;
202 } else {
203 lzfs::add_log_stderr(lzfs::log_level::debug);
204 }
205
206
207 #ifdef MFS_USE_MEMLOCK
208 if (gMountOptions.memlock) {
209 if (mlockall(MCL_CURRENT|MCL_FUTURE)==0) {
210 lzfs_pretty_syslog(LOG_NOTICE,"process memory was successfully locked in RAM");
211 }
212 }
213 #endif
214
215 LizardClient::FsInitParams params(
216 gMountOptions.bindhost ? gMountOptions.bindhost : "",
217 gMountOptions.masterhost, gMountOptions.masterport, mp);
218 params.verbose = true;
219 params.meta = gMountOptions.meta;
220 params.subfolder = gMountOptions.subfolder;
221 params.password_digest = std::move(md5pass);
222 params.do_not_remember_password = gMountOptions.donotrememberpassword;
223 params.delayed_init = gMountOptions.delayedinit;
224 params.report_reserved_period = gMountOptions.reportreservedperiod;
225 params.io_retries = gMountOptions.ioretries;
226 params.io_limits_config_file = gMountOptions.iolimits ? gMountOptions.iolimits : "";
227 params.bandwidth_overuse = gMountOptions.bandwidthoveruse;
228
229 params.chunkserver_round_time_ms = gMountOptions.chunkserverrtt;
230 params.chunkserver_connect_timeout_ms = gMountOptions.chunkserverconnectreadto;
231 params.chunkserver_wave_read_timeout_ms = gMountOptions.chunkserverwavereadto;
232 params.total_read_timeout_ms = gMountOptions.chunkservertotalreadto;
233 params.cache_expiration_time_ms = gMountOptions.cacheexpirationtime;
234 params.readahead_max_window_size_kB = gMountOptions.readaheadmaxwindowsize;
235 params.prefetch_xor_stripes = gMountOptions.prefetchxorstripes;
236 params.bandwidth_overuse = gMountOptions.bandwidthoveruse;
237 params.write_cache_size = gMountOptions.writecachesize;
238 params.write_workers = gMountOptions.writeworkers;
239 params.write_window_size = gMountOptions.writewindowsize;
240 params.chunkserver_write_timeout_ms = gMountOptions.chunkserverwriteto;
241 params.cache_per_inode_percentage = gMountOptions.cachePerInodePercentage;
242
243 params.keep_cache = gMountOptions.keepcache;
244 params.direntry_cache_timeout = gMountOptions.direntrycacheto;
245 params.direntry_cache_size = gMountOptions.direntrycachesize;
246 params.entry_cache_timeout = gMountOptions.entrycacheto;
247 params.attr_cache_timeout = gMountOptions.attrcacheto;
248 params.mkdir_copy_sgid = gMountOptions.mkdircopysgid;
249 params.sugid_clear_mode = gMountOptions.sugidclearmode;
250 params.use_rw_lock = gMountOptions.rwlock;
251 params.acl_cache_timeout = gMountOptions.aclcacheto;
252 params.acl_cache_size = gMountOptions.aclcachesize;
253
254 params.debug_mode = gMountOptions.debug;
255 if (gMountOptions.meta == 0) {
256 try {
257 LizardClient::fs_init(params);
258 } catch (...) {
259 if (piped[1] >= 0) {
260 if (write(piped[1], &s, 1) != 1) {
261 fprintf(stderr,"pipe write error\n");
262 }
263 close(piped[1]);
264 }
265 return 1;
266 }
267 } else {
268 masterproxy_init();
269 symlink_cache_init();
270 if (gMountOptions.delayedinit) {
271 fs_init_master_connection(params);
272 } else {
273 if (fs_init_master_connection(params) < 0) {
274 if (piped[1] >= 0) {
275 if (write(piped[1], &s, 1) != 1) {
276 fprintf(stderr,"pipe write error\n");
277 }
278 close(piped[1]);
279 }
280 return 1;
281 }
282 }
283 fs_init_threads(params.io_retries);
284 }
285
286 ch = fuse_mount(mp, args);
287 if (ch == NULL) {
288 fprintf(stderr,"error in fuse_mount\n");
289 if (piped[1]>=0) {
290 if (write(piped[1], &s, 1) != 1) {
291 fprintf(stderr,"pipe write error\n");
292 }
293 close(piped[1]);
294 }
295 if (gMountOptions.meta == 0) {
296 LizardClient::fs_term();
297 } else {
298 masterproxy_term();
299 fs_term();
300 symlink_cache_term();
301 }
302 return 1;
303 }
304
305 if (gMountOptions.meta) {
306 mfs_meta_init(gMountOptions.debug,
307 gMountOptions.entrycacheto,
308 gMountOptions.attrcacheto);
309 se = fuse_lowlevel_new(args, &mfs_meta_oper, sizeof(mfs_meta_oper), (void*)piped);
310 } else {
311 se = fuse_lowlevel_new(args, &mfs_oper, sizeof(mfs_oper), (void*)piped);
312 }
313 if (se == NULL) {
314 fuse_unmount(mp,ch);
315 fprintf(stderr,"error in fuse_lowlevel_new\n");
316 usleep(100000); // time for print other error messages by FUSE
317 if (piped[1]>=0) {
318 if (write(piped[1],&s,1)!=1) {
319 fprintf(stderr,"pipe write error\n");
320 }
321 close(piped[1]);
322 }
323 if (gMountOptions.meta == 0) {
324 LizardClient::fs_term();
325 } else {
326 masterproxy_term();
327 fs_term();
328 symlink_cache_term();
329 }
330 return 1;
331 }
332
333 fuse_session_add_chan(se, ch);
334
335 if (fuse_set_signal_handlers(se)<0) {
336 fprintf(stderr,"error in fuse_set_signal_handlers\n");
337 fuse_session_remove_chan(ch);
338 fuse_session_destroy(se);
339 fuse_unmount(mp,ch);
340 if (piped[1]>=0) {
341 if (write(piped[1],&s,1)!=1) {
342 fprintf(stderr,"pipe write error\n");
343 }
344 close(piped[1]);
345 }
346 if (gMountOptions.meta == 0) {
347 LizardClient::fs_term();
348 } else {
349 masterproxy_term();
350 fs_term();
351 symlink_cache_term();
352 }
353 return 1;
354 }
355
356 if (gMountOptions.debug==0 && fg==0) {
357 setsid();
358 setpgid(0,getpid());
359 if ((i = open("/dev/null", O_RDWR, 0)) != -1) {
360 (void)dup2(i, STDIN_FILENO);
361 (void)dup2(i, STDOUT_FILENO);
362 (void)dup2(i, STDERR_FILENO);
363 if (i>2) close (i);
364 }
365 }
366
367 if (mt) {
368 err = fuse_session_loop_mt(se);
369 } else {
370 err = fuse_session_loop(se);
371 }
372 if (err) {
373 if (piped[1]>=0) {
374 if (write(piped[1],&s,1)!=1) {
375 lzfs_pretty_syslog(LOG_ERR,"pipe write error: %s",strerr(errno));
376 }
377 close(piped[1]);
378 }
379 }
380 fuse_remove_signal_handlers(se);
381 fuse_session_remove_chan(ch);
382 fuse_session_destroy(se);
383 fuse_unmount(mp,ch);
384 if (gMountOptions.meta == 0) {
385 LizardClient::fs_term();
386 } else {
387 masterproxy_term();
388 fs_term();
389 symlink_cache_term();
390 }
391 return err ? 1 : 0;
392 }
393
394 #if FUSE_VERSION == 25
fuse_opt_insert_arg(struct fuse_args * args,int pos,const char * arg)395 static int fuse_opt_insert_arg(struct fuse_args *args, int pos, const char *arg) {
396 assert(pos <= args->argc);
397 if (fuse_opt_add_arg(args, arg) == -1) {
398 return -1;
399 }
400 if (pos != args->argc - 1) {
401 char *newarg = args->argv[args->argc - 1];
402 memmove(&args->argv[pos + 1], &args->argv[pos], sizeof(char *) * (args->argc - pos - 1));
403 args->argv[pos] = newarg;
404 }
405 return 0;
406 }
407 #endif
408
strncpy_remove_commas(char * dstbuff,unsigned int dstsize,char * src)409 static unsigned int strncpy_remove_commas(char *dstbuff, unsigned int dstsize,char *src) {
410 char c;
411 unsigned int l;
412 l=0;
413 while ((c=*src++) && l+1<dstsize) {
414 if (c!=',') {
415 *dstbuff++ = c;
416 l++;
417 }
418 }
419 *dstbuff=0;
420 return l;
421 }
422
423 #if LIZARDFS_HAVE_FUSE_VERSION
strncpy_escape_commas(char * dstbuff,unsigned int dstsize,char * src)424 static unsigned int strncpy_escape_commas(char *dstbuff, unsigned int dstsize,char *src) {
425 char c;
426 unsigned int l;
427 l=0;
428 while ((c=*src++) && l+1<dstsize) {
429 if (c!=',' && c!='\\') {
430 *dstbuff++ = c;
431 l++;
432 } else {
433 if (l+2<dstsize) {
434 *dstbuff++ = '\\';
435 *dstbuff++ = c;
436 l+=2;
437 } else {
438 *dstbuff=0;
439 return l;
440 }
441 }
442 }
443 *dstbuff=0;
444 return l;
445 }
446 #endif
447
make_fsname(struct fuse_args * args)448 void make_fsname(struct fuse_args *args) {
449 char fsnamearg[256];
450 unsigned int l;
451 #if LIZARDFS_HAVE_FUSE_VERSION
452 int libver;
453 libver = fuse_version();
454 if (libver >= 27) {
455 l = snprintf(fsnamearg,256,"-osubtype=mfs%s,fsname=",(gMountOptions.meta)?"meta":"");
456 if (libver >= 28) {
457 l += strncpy_escape_commas(fsnamearg+l,256-l,gMountOptions.masterhost);
458 if (l<255) {
459 fsnamearg[l++]=':';
460 }
461 l += strncpy_escape_commas(fsnamearg+l,256-l,gMountOptions.masterport);
462 if (gMountOptions.subfolder[0]!='/') {
463 if (l<255) {
464 fsnamearg[l++]='/';
465 }
466 }
467 if (gMountOptions.subfolder[0]!='/' && gMountOptions.subfolder[1]!=0) {
468 l += strncpy_escape_commas(fsnamearg+l,256-l,gMountOptions.subfolder);
469 }
470 if (l>255) {
471 l=255;
472 }
473 fsnamearg[l]=0;
474 } else {
475 l += strncpy_remove_commas(fsnamearg+l,256-l,gMountOptions.masterhost);
476 if (l<255) {
477 fsnamearg[l++]=':';
478 }
479 l += strncpy_remove_commas(fsnamearg+l,256-l,gMountOptions.masterport);
480 if (gMountOptions.subfolder[0]!='/') {
481 if (l<255) {
482 fsnamearg[l++]='/';
483 }
484 }
485 if (gMountOptions.subfolder[0]!='/' && gMountOptions.subfolder[1]!=0) {
486 l += strncpy_remove_commas(fsnamearg+l,256-l,gMountOptions.subfolder);
487 }
488 if (l>255) {
489 l=255;
490 }
491 fsnamearg[l]=0;
492 }
493 } else {
494 #else
495 l = snprintf(fsnamearg,256,"-ofsname=mfs%s#",(gMountOptions.meta)?"meta":"");
496 l += strncpy_remove_commas(fsnamearg+l,256-l,gMountOptions.masterhost);
497 if (l<255) {
498 fsnamearg[l++]=':';
499 }
500 l += strncpy_remove_commas(fsnamearg+l,256-l,gMountOptions.masterport);
501 if (gMountOptions.subfolder[0]!='/') {
502 if (l<255) {
503 fsnamearg[l++]='/';
504 }
505 }
506 if (gMountOptions.subfolder[0]!='/' && gMountOptions.subfolder[1]!=0) {
507 l += strncpy_remove_commas(fsnamearg+l,256-l,gMountOptions.subfolder);
508 }
509 if (l>255) {
510 l=255;
511 }
512 fsnamearg[l]=0;
513 #endif
514 #if LIZARDFS_HAVE_FUSE_VERSION
515 }
516 #endif
517 fuse_opt_insert_arg(args, 1, fsnamearg);
518 }
519
main(int argc,char * argv[])520 int main(int argc, char *argv[]) try {
521 int res;
522 int mt,fg;
523 char *mountpoint;
524 struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
525 struct fuse_args defaultargs = FUSE_ARGS_INIT(0, NULL);
526
527 fuse_opt_add_arg(&defaultargs,"fakeappname");
528
529 if (fuse_opt_parse(&args, &defaultargs, gMfsOptsStage1, mfs_opt_proc_stage1)<0) {
530 exit(1);
531 }
532
533 if (gCustomCfg==0) {
534 mfs_opt_parse_cfg_file(ETC_PATH "/mfsmount.cfg",1,&defaultargs);
535 }
536
537 if (fuse_opt_parse(&defaultargs, &gMountOptions, gMfsOptsStage2, mfs_opt_proc_stage2)<0) {
538 exit(1);
539 }
540
541 if (fuse_opt_parse(&args, &gMountOptions, gMfsOptsStage2, mfs_opt_proc_stage2)<0) {
542 exit(1);
543 }
544
545 init_fuse_lowlevel_ops();
546
547 if (gMountOptions.cachemode!=NULL && gMountOptions.cachefiles) {
548 fprintf(stderr,"mfscachemode and mfscachefiles options are exclusive - use only mfscachemode\nsee: %s -h for help\n",argv[0]);
549 return 1;
550 }
551
552 if (gMountOptions.cachemode==NULL) {
553 gMountOptions.keepcache=(gMountOptions.cachefiles)?1:0;
554 } else if (strcasecmp(gMountOptions.cachemode,"AUTO")==0) {
555 gMountOptions.keepcache=0;
556 } else if (strcasecmp(gMountOptions.cachemode,"YES")==0 || strcasecmp(gMountOptions.cachemode,"ALWAYS")==0) {
557 gMountOptions.keepcache=1;
558 } else if (strcasecmp(gMountOptions.cachemode,"NO")==0
559 || strcasecmp(gMountOptions.cachemode,"NONE")==0
560 || strcasecmp(gMountOptions.cachemode,"NEVER")==0) {
561 gMountOptions.keepcache=2;
562 gMountOptions.cacheexpirationtime=0;
563 } else {
564 fprintf(stderr,"unrecognized cachemode option\nsee: %s -h for help\n",argv[0]);
565 return 1;
566 }
567 if (gMountOptions.sugidclearmodestr==NULL) {
568 gMountOptions.sugidclearmode = LizardClient::FsInitParams::kDefaultSugidClearMode;
569 } else if (strcasecmp(gMountOptions.sugidclearmodestr,"NEVER")==0) {
570 gMountOptions.sugidclearmode = SugidClearMode::kNever;
571 } else if (strcasecmp(gMountOptions.sugidclearmodestr,"ALWAYS")==0) {
572 gMountOptions.sugidclearmode = SugidClearMode::kAlways;
573 } else if (strcasecmp(gMountOptions.sugidclearmodestr,"OSX")==0) {
574 gMountOptions.sugidclearmode = SugidClearMode::kOsx;
575 } else if (strcasecmp(gMountOptions.sugidclearmodestr,"BSD")==0) {
576 gMountOptions.sugidclearmode = SugidClearMode::kBsd;
577 } else if (strcasecmp(gMountOptions.sugidclearmodestr,"EXT")==0) {
578 gMountOptions.sugidclearmode = SugidClearMode::kExt;
579 } else if (strcasecmp(gMountOptions.sugidclearmodestr,"XFS")==0) {
580 gMountOptions.sugidclearmode = SugidClearMode::kXfs;
581 } else {
582 fprintf(stderr,"unrecognized sugidclearmode option\nsee: %s -h for help\n",argv[0]);
583 return 1;
584 }
585 if (gMountOptions.masterhost==NULL) {
586 gMountOptions.masterhost = strdup("mfsmaster");
587 }
588 if (gMountOptions.masterport==NULL) {
589 gMountOptions.masterport = strdup("9421");
590 }
591 if (gMountOptions.subfolder==NULL) {
592 gMountOptions.subfolder = strdup("/");
593 }
594 if (gMountOptions.nofile==0) {
595 gMountOptions.nofile=100000;
596 }
597 if (gMountOptions.writecachesize==0) {
598 gMountOptions.writecachesize=128;
599 }
600 if (gMountOptions.cachePerInodePercentage < 1) {
601 fprintf(stderr, "cache per inode percentage too low (%u %%) - increased to 1%%\n",
602 gMountOptions.cachePerInodePercentage);
603 gMountOptions.cachePerInodePercentage = 1;
604 }
605 if (gMountOptions.cachePerInodePercentage > 100) {
606 fprintf(stderr, "cache per inode percentage too big (%u %%) - decreased to 100%%\n",
607 gMountOptions.cachePerInodePercentage);
608 gMountOptions.cachePerInodePercentage = 100;
609 }
610 if (gMountOptions.writecachesize<16) {
611 fprintf(stderr,"write cache size too low (%u MiB) - increased to 16 MiB\n",
612 gMountOptions.writecachesize);
613 gMountOptions.writecachesize=16;
614 }
615 if (gMountOptions.writecachesize>1024*1024) {
616 fprintf(stderr,"write cache size too big (%u MiB) - decreased to 1 TiB\n",
617 gMountOptions.writecachesize);
618 gMountOptions.writecachesize=1024*1024;
619 }
620 if (gMountOptions.writeworkers<1) {
621 fprintf(stderr,"no write workers - increasing number of workers to 1\n");
622 gMountOptions.writeworkers=1;
623 }
624 if (gMountOptions.writewindowsize < 1) {
625 fprintf(stderr,"write window size is 0 - increasing to 1\n");
626 gMountOptions.writewindowsize = 1;
627 }
628 if (gMountOptions.nostdmountoptions==0) {
629 fuse_opt_add_arg(&args, "-o" DEFAULT_OPTIONS);
630 }
631 if (gMountOptions.aclcachesize > 1000 * 1000) {
632 fprintf(stderr,"acl cache size too big (%u) - decreased to 1000000\n",
633 gMountOptions.aclcachesize);
634 gMountOptions.aclcachesize = 1000 * 1000;
635 }
636 if (gMountOptions.direntrycachesize > 10000000) {
637 fprintf(stderr,"directory entry cache size too big (%u) - decreased to 10000000\n",
638 gMountOptions.direntrycachesize);
639 gMountOptions.direntrycachesize = 10000000;
640 }
641
642 make_fsname(&args);
643
644 if (fuse_parse_cmdline(&args,&mountpoint,&mt,&fg)<0) {
645 fprintf(stderr,"see: %s -h for help\n",argv[0]);
646 return 1;
647 }
648
649 if (!mountpoint) {
650 if (gDefaultMountpoint) {
651 mountpoint = gDefaultMountpoint;
652 } else {
653 fprintf(stderr,"no mount point\nsee: %s -h for help\n",argv[0]);
654 return 1;
655 }
656 }
657
658 res = mainloop(&args,mountpoint,mt,fg);
659 fuse_opt_free_args(&args);
660 fuse_opt_free_args(&defaultargs);
661 free(gMountOptions.masterhost);
662 free(gMountOptions.masterport);
663 if (gMountOptions.bindhost) {
664 free(gMountOptions.bindhost);
665 }
666 free(gMountOptions.subfolder);
667 if (gDefaultMountpoint && gDefaultMountpoint != mountpoint) {
668 free(gDefaultMountpoint);
669 }
670 if (gMountOptions.iolimits) {
671 free(gMountOptions.iolimits);
672 }
673 free(mountpoint);
674 stats_term();
675 return res;
676 } catch (std::bad_alloc ex) {
677 mabort("run out of memory");
678 }
679