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 #include "mount/mastercomm.h"
21 
22 #include <limits.h>
23 #include <pthread.h>
24 #include <signal.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <time.h>
29 #include <unistd.h>
30 #include <atomic>
31 #include <condition_variable>
32 #include <mutex>
33 #include <unordered_map>
34 #include <vector>
35 
36 #ifndef _WIN32
37   #include <arpa/inet.h>
38   #include <grp.h>
39   #include <pwd.h>
40 #endif
41 
42 #include "common/datapack.h"
43 #include "common/exception.h"
44 #include "common/exit_status.h"
45 #include "common/goal.h"
46 #include "common/lizardfs_version.h"
47 #include "common/md5.h"
48 #include "common/mfserr.h"
49 #include "common/sockets.h"
50 #include "common/slogger.h"
51 #include "mount/exports.h"
52 #include "mount/stats.h"
53 #include "protocol/cltoma.h"
54 #include "protocol/matocl.h"
55 #include "protocol/MFSCommunication.h"
56 #include "protocol/packet.h"
57 
58 struct threc {
59 	pthread_t thid;
60 	std::mutex mutex;
61 	std::condition_variable condition;
62 	MessageBuffer outputBuffer;
63 	MessageBuffer inputBuffer;
64 	uint8_t status;         // receive status
65 	bool sent;              // packet was sent
66 	bool received;          // packet was received
67 	bool waiting;           // thread is waiting for answer
68 
69 	uint32_t receivedType;
70 
71 	uint32_t packetId;      // thread number
72 	threc *next;
73 };
74 
75 typedef struct _acquired_file {
76 	uint32_t inode;
77 	uint32_t cnt;
78 	struct _acquired_file *next;
79 } acquired_file;
80 
81 
82 #define DEFAULT_OUTPUT_BUFFSIZE 0x1000
83 #define DEFAULT_INPUT_BUFFSIZE 0x10000
84 
85 #define RECEIVE_TIMEOUT 10
86 
87 static threc *threchead=NULL;
88 
89 static acquired_file *afhead=NULL;
90 
91 static int fd;
92 static bool disconnect;
93 static time_t lastwrite;
94 static int sessionlost;
95 
96 static uint32_t maxretries;
97 
98 static pthread_t rpthid,npthid;
99 static std::mutex fdMutex, recMutex, acquiredFileMutex;
100 
101 static uint32_t sessionid;
102 static uint32_t masterversion;
103 
104 static char masterstrip[17];
105 static uint32_t masterip=0;
106 static uint16_t masterport=0;
107 static char srcstrip[17];
108 static uint32_t srcip=0;
109 
110 static uint8_t fterm;
111 static std::atomic<bool> gIsKilled(false);
112 
113 typedef std::unordered_map<PacketHeader::Type, PacketHandler*> PerTypePacketHandlers;
114 static PerTypePacketHandlers perTypePacketHandlers;
115 static std::mutex perTypePacketHandlersLock;
116 
fs_getmasterlocation(uint8_t loc[14])117 void fs_getmasterlocation(uint8_t loc[14]) {
118 	put32bit(&loc,masterip);
119 	put16bit(&loc,masterport);
120 	put32bit(&loc,sessionid);
121 	put32bit(&loc,masterversion);
122 }
123 
fs_getsrcip()124 uint32_t fs_getsrcip() {
125 	return srcip;
126 }
127 
128 enum {
129 	MASTER_CONNECTS = 0,
130 	MASTER_BYTESSENT,
131 	MASTER_BYTESRCVD,
132 	MASTER_PACKETSSENT,
133 	MASTER_PACKETSRCVD,
134 	STATNODES
135 };
136 
137 static uint64_t *statsptr[STATNODES];
138 
139 struct InitParams {
140 	std::string bind_host;
141 	std::string host;
142 	std::string port;
143 	bool meta;
144 	bool do_not_remember_password;
145 	std::string mountpoint;
146 	std::string subfolder;
147 	std::vector<uint8_t> password_digest;
148 	unsigned report_reserved_period;
149 
operator =InitParams150 	InitParams &operator=(const LizardClient::FsInitParams &params) {
151 		bind_host = params.bind_host;
152 		host = params.host;
153 		port = params.port;
154 		meta = params.meta;
155 		do_not_remember_password = params.do_not_remember_password;
156 		mountpoint = params.mountpoint;
157 		subfolder = params.subfolder;
158 		password_digest = params.password_digest;
159 		report_reserved_period = params.report_reserved_period;
160 		return *this;
161 	}
162 };
163 
164 static InitParams gInitParams;
165 
master_statsptr_init(void)166 void master_statsptr_init(void) {
167 	void *s;
168 	s = stats_get_subnode(NULL,"master",0);
169 	statsptr[MASTER_PACKETSRCVD] = stats_get_counterptr(stats_get_subnode(s,"packets_received",0));
170 	statsptr[MASTER_PACKETSSENT] = stats_get_counterptr(stats_get_subnode(s,"packets_sent",0));
171 	statsptr[MASTER_BYTESRCVD] = stats_get_counterptr(stats_get_subnode(s,"bytes_received",0));
172 	statsptr[MASTER_BYTESSENT] = stats_get_counterptr(stats_get_subnode(s,"bytes_sent",0));
173 	statsptr[MASTER_CONNECTS] = stats_get_counterptr(stats_get_subnode(s,"reconnects",0));
174 }
175 
master_stats_inc(uint8_t id)176 void master_stats_inc(uint8_t id) {
177 	if (id<STATNODES) {
178 		stats_lock();
179 		(*statsptr[id])++;
180 		stats_unlock();
181 	}
182 }
183 
master_stats_add(uint8_t id,uint64_t s)184 void master_stats_add(uint8_t id,uint64_t s) {
185 	if (id<STATNODES) {
186 		stats_lock();
187 		(*statsptr[id])+=s;
188 		stats_unlock();
189 	}
190 }
191 
setDisconnect(bool value)192 static inline void setDisconnect(bool value) {
193 	std::unique_lock<std::mutex> fdLock(fdMutex);
194 	disconnect = value;
195 }
196 
fs_inc_acnt(uint32_t inode)197 void fs_inc_acnt(uint32_t inode) {
198 	acquired_file *afptr,**afpptr;
199 	std::unique_lock<std::mutex> acquiredFileLock(acquiredFileMutex);
200 	afpptr = &afhead;
201 	while ((afptr=*afpptr)) {
202 		if (afptr->inode==inode) {
203 			afptr->cnt++;
204 			return;
205 		}
206 		if (afptr->inode>inode) {
207 			break;
208 		}
209 		afpptr = &(afptr->next);
210 	}
211 	afptr = (acquired_file*)malloc(sizeof(acquired_file));
212 	afptr->inode = inode;
213 	afptr->cnt = 1;
214 	afptr->next = *afpptr;
215 	*afpptr = afptr;
216 }
217 
fs_dec_acnt(uint32_t inode)218 void fs_dec_acnt(uint32_t inode) {
219 	acquired_file *afptr,**afpptr;
220 	std::unique_lock<std::mutex> afLock(acquiredFileMutex);
221 	afpptr = &afhead;
222 	while ((afptr=*afpptr)) {
223 		if (afptr->inode == inode) {
224 			if (afptr->cnt<=1) {
225 				*afpptr = afptr->next;
226 				free(afptr);
227 			} else {
228 				afptr->cnt--;
229 			}
230 			return;
231 		}
232 		afpptr = &(afptr->next);
233 	}
234 }
235 
fs_get_my_threc()236 threc* fs_get_my_threc() {
237 	pthread_t mythid = pthread_self();
238 	threc *rec;
239 	std::unique_lock<std::mutex> recLock(recMutex);
240 	for (rec = threchead ; rec ; rec = rec->next) {
241 		if (pthread_equal(rec->thid, mythid)) {
242 			return rec;
243 		}
244 	}
245 	rec = new threc;
246 	rec->thid = mythid;
247 	rec->sent = false;
248 	rec->status = 0;
249 	rec->received = false;
250 	rec->waiting = 0;
251 	rec->receivedType = 0;
252 	if (threchead==NULL) {
253 		rec->packetId = 1;
254 	} else {
255 		rec->packetId = threchead->packetId + 1;
256 	}
257 	rec->next = threchead;
258 	threchead = rec;
259 	return rec;
260 }
261 
fs_get_threc_by_id(uint32_t packetId)262 threc* fs_get_threc_by_id(uint32_t packetId) {
263 	threc *rec;
264 	std::unique_lock<std::mutex> recLock(recMutex);
265 	for (rec = threchead ; rec ; rec=rec->next) {
266 		if (rec->packetId==packetId) {
267 			return rec;
268 		}
269 	}
270 	return NULL;
271 }
272 
fs_createpacket(threc * rec,uint32_t cmd,uint32_t size)273 uint8_t* fs_createpacket(threc *rec,uint32_t cmd,uint32_t size) {
274 	uint8_t *ptr;
275 	uint32_t hdrsize = size+4;
276 	std::unique_lock<std::mutex> lock(rec->mutex);
277 	rec->outputBuffer.resize(size+12);
278 	ptr = rec->outputBuffer.data();
279 	put32bit(&ptr,cmd);
280 	put32bit(&ptr,hdrsize);
281 	put32bit(&ptr,rec->packetId);
282 	return ptr;
283 }
284 
fs_lizcreatepacket(threc * rec,MessageBuffer message)285 bool fs_lizcreatepacket(threc *rec, MessageBuffer message) {
286 	std::unique_lock<std::mutex> lock(rec->mutex);
287 	rec->outputBuffer = std::move(message);
288 	return true;
289 }
290 
291 LIZARDFS_CREATE_EXCEPTION_CLASS_MSG(LostSessionException, Exception, "session lost");
292 
fs_threc_flush(threc * rec)293 static bool fs_threc_flush(threc *rec) {
294 	std::unique_lock<std::mutex> fdLock(fdMutex);
295 	if (sessionlost) {
296 		throw LostSessionException();
297 	}
298 	if (fd==-1) {
299 		return false;
300 	}
301 	std::unique_lock<std::mutex> lock(rec->mutex);
302 	const int32_t size = rec->outputBuffer.size();
303 	if (tcptowrite(fd, rec->outputBuffer.data(), size, 1000) != size) {
304 		lzfs_pretty_syslog(LOG_WARNING, "tcp send error: %s", strerr(tcpgetlasterror()));
305 		disconnect = true;
306 		return false;
307 	}
308 	rec->received = false;
309 	rec->sent = true;
310 	lock.unlock();
311 	master_stats_add(MASTER_BYTESSENT, size);
312 	master_stats_inc(MASTER_PACKETSSENT);
313 	lastwrite = time(NULL);
314 	return true;
315 }
316 
fs_threc_wait(threc * rec,std::unique_lock<std::mutex> & lock)317 static bool fs_threc_wait(threc *rec, std::unique_lock<std::mutex>& lock) {
318 	while (!rec->received) {
319 		rec->waiting = 1;
320 		rec->condition.wait(lock);
321 		rec->waiting = 0;
322 	}
323 	return rec->status == LIZARDFS_STATUS_OK;
324 }
325 
sleep_time(uint32_t tryNo)326 static inline uint32_t sleep_time(uint32_t tryNo) {
327 	if (tryNo < 30) {
328 		return 1 + (tryNo) / 3;
329 	} else {
330 		return 10;
331 	}
332 }
333 
334 // TODO(jotek): not every request should be retransmitted if recv failed (e.g. snapshot)
fs_threc_send_receive(threc * rec,bool filter,PacketHeader::Type expected_type)335 static bool fs_threc_send_receive(threc *rec, bool filter, PacketHeader::Type expected_type) {
336 	try {
337 		for (uint32_t cnt = 0 ; cnt < maxretries ; cnt++) {
338 			if (fs_threc_flush(rec)) {
339 				std::unique_lock<std::mutex> lock(rec->mutex);
340 				if (fs_threc_wait(rec, lock)) {
341 					if (!filter || rec->receivedType == expected_type) {
342 						return true;
343 					} else {
344 						lock.unlock();
345 						setDisconnect(true);
346 					}
347 				}
348 			}
349 			sleep(sleep_time(cnt));
350 			continue;
351 		}
352 	} catch (LostSessionException&) {
353 	}
354 	return false;
355 }
356 
fs_sendandreceive(threc * rec,uint32_t expected_cmd,uint32_t * answer_leng)357 const uint8_t* fs_sendandreceive(threc *rec, uint32_t expected_cmd, uint32_t *answer_leng) {
358 	// this function is only for compatibility with MooseFS code
359 	sassert(expected_cmd <= PacketHeader::kMaxOldPacketType);
360 	if (fs_threc_send_receive(rec, true, expected_cmd)) {
361 		const uint8_t *answer;
362 		answer = rec->inputBuffer.data();
363 		*answer_leng = rec->inputBuffer.size();
364 
365 		// MooseFS code doesn't expect message id, skip it
366 		answer += 4;
367 		*answer_leng -= 4;
368 
369 		return answer;
370 	}
371 	return NULL;
372 }
373 
fs_lizsendandreceive(threc * rec,uint32_t expectedCommand,MessageBuffer & messageData)374 bool fs_lizsendandreceive(threc *rec, uint32_t expectedCommand, MessageBuffer& messageData) {
375 	if (fs_threc_send_receive(rec, true, expectedCommand)) {
376 		std::unique_lock<std::mutex> lock(rec->mutex);
377 		rec->received = false;  // we steal ownership of the received buffer
378 		messageData = std::move(rec->inputBuffer);
379 		return true;
380 	}
381 	return false;
382 }
383 
fs_lizsend(threc * rec)384 bool fs_lizsend(threc *rec) {
385 	try {
386 		for (uint32_t cnt = 0; cnt < maxretries; cnt++) {
387 			if (fs_threc_flush(rec)) {
388 				return true;
389 			}
390 			sleep(sleep_time(cnt));
391 		}
392 	} catch (LostSessionException&) {
393 	}
394 	return false;
395 }
396 
fs_lizrecv(threc * rec,uint32_t expectedCommand,MessageBuffer & messageData)397 bool fs_lizrecv(threc *rec, uint32_t expectedCommand, MessageBuffer& messageData) {
398 	try {
399 		std::unique_lock<std::mutex> lock(rec->mutex);
400 		if (fs_threc_wait(rec, lock)) {
401 			if (rec->receivedType == expectedCommand) {
402 				rec->received = false;  // we steal ownership of the received buffer
403 				messageData = std::move(rec->inputBuffer);
404 				return true;
405 			} else {
406 				lock.unlock();
407 				setDisconnect(true);
408 			}
409 		}
410 	} catch (LostSessionException&) {
411 	}
412 	return false;
413 }
414 
fs_lizsendandreceive_any(threc * rec,MessageBuffer & messageData)415 bool fs_lizsendandreceive_any(threc *rec, MessageBuffer& messageData) {
416 	if (fs_threc_send_receive(rec, false, 0)) {
417 		std::unique_lock<std::mutex> lock(rec->mutex);
418 		const MessageBuffer& payload = rec->inputBuffer;
419 		const PacketHeader header(rec->receivedType, payload.size());
420 		messageData.clear();
421 		serialize(messageData, header);
422 		messageData.insert(messageData.end(), payload.begin(), payload.end());
423 		return true;
424 	}
425 	return false;
426 }
427 
fs_resolve(bool verbose,const std::string & bindhostname,const std::string & masterhostname,const std::string & masterportname)428 int fs_resolve(bool verbose, const std::string &bindhostname, const std::string &masterhostname, const std::string &masterportname) {
429 	if (!bindhostname.empty()) {
430 		if (tcpresolve(bindhostname.c_str(), nullptr, &srcip, nullptr, 1) < 0) {
431 			if (verbose) {
432 				fprintf(stderr,"can't resolve source hostname (%s)\n", bindhostname.c_str());
433 			} else {
434 				lzfs_pretty_syslog(LOG_WARNING,"can't resolve source hostname (%s)", bindhostname.c_str());
435 			}
436 			return -1;
437 		}
438 	} else {
439 		srcip = 0;
440 	}
441 	snprintf(srcstrip, 17, "%" PRIu32 ".%" PRIu32 ".%" PRIu32 ".%" PRIu32,
442 	         (srcip>>24)&0xFF, (srcip>>16)&0xFF, (srcip>>8)&0xFF, srcip&0xFF);
443 	srcstrip[16] = 0;
444 
445 	if (tcpresolve(masterhostname.c_str(), masterportname.c_str(), &masterip, &masterport, 0) < 0) {
446 		if (verbose) {
447 			fprintf(stderr, "can't resolve master hostname and/or portname (%s:%s)\n",
448 			        masterhostname.c_str(), masterportname.c_str());
449 		} else {
450 			lzfs_pretty_syslog(LOG_WARNING,"can't resolve master hostname and/or portname (%s:%s)",
451 			                   masterhostname.c_str(), masterportname.c_str());
452 		}
453 		return -1;
454 	}
455 	snprintf(masterstrip, 17, "%" PRIu32 ".%" PRIu32 ".%" PRIu32 ".%" PRIu32,
456 	        (masterip>>24)&0xFF, (masterip>>16)&0xFF, (masterip>>8)&0xFF, masterip&0xFF);
457 	masterstrip[16] = 0;
458 
459 	return 0;
460 }
461 
fs_connect(bool verbose)462 int fs_connect(bool verbose) {
463 	uint32_t i,j;
464 	uint8_t *wptr,*regbuff;
465 	md5ctx ctx;
466 	uint8_t digest[16];
467 	const uint8_t *rptr;
468 	uint8_t havepassword;
469 	uint32_t pleng,ileng;
470 	uint8_t sesflags;
471 	uint32_t rootuid,rootgid,mapalluid,mapallgid;
472 	uint8_t mingoal,maxgoal;
473 	uint32_t mintrashtime,maxtrashtime;
474 	const char *sesflagposstrtab[]={SESFLAG_POS_STRINGS};
475 	const char *sesflagnegstrtab[]={SESFLAG_NEG_STRINGS};
476 
477 	if (fs_resolve(verbose ,gInitParams.bind_host, gInitParams.host, gInitParams.port) < 0) {
478 		return -1;
479 	}
480 
481 	havepassword = !gInitParams.password_digest.empty();
482 	ileng=gInitParams.mountpoint.size() + 1;
483 	if (gInitParams.meta) {
484 		pleng=0;
485 		regbuff = (uint8_t*) malloc(8+64+9+ileng+16);
486 	} else {
487 		pleng=gInitParams.subfolder.size() + 1;
488 		regbuff = (uint8_t*) malloc(8+64+13+pleng+ileng+16);
489 	}
490 
491 	fd = tcpsocket();
492 	if (fd<0) {
493 		free(regbuff);
494 		return -1;
495 	}
496 	if (tcpnodelay(fd)<0) {
497 		if (verbose) {
498 			fprintf(stderr,"can't set TCP_NODELAY\n");
499 		} else {
500 			lzfs_pretty_syslog(LOG_WARNING,"can't set TCP_NODELAY");
501 		}
502 	}
503 	if (srcip>0) {
504 		if (tcpnumbind(fd,srcip,0)<0) {
505 			if (verbose) {
506 				fprintf(stderr,"can't bind socket to given ip (\"%s\")\n",srcstrip);
507 			} else {
508 				lzfs_pretty_syslog(LOG_WARNING,"can't bind socket to given ip (\"%s\")",srcstrip);
509 			}
510 			tcpclose(fd);
511 			fd=-1;
512 			free(regbuff);
513 			return -1;
514 		}
515 	}
516 	if (tcpnumconnect(fd,masterip,masterport)<0) {
517 		if (verbose) {
518 			fprintf(stderr,"can't connect to mfsmaster (\"%s\":\"%" PRIu16 "\")\n",masterstrip,masterport);
519 		} else {
520 			lzfs_pretty_syslog(LOG_WARNING,"can't connect to mfsmaster (\"%s\":\"%" PRIu16 "\")",masterstrip,masterport);
521 		}
522 		tcpclose(fd);
523 		fd=-1;
524 		free(regbuff);
525 		return -1;
526 	}
527 	if (havepassword) {
528 		wptr = regbuff;
529 		put32bit(&wptr,CLTOMA_FUSE_REGISTER);
530 		put32bit(&wptr,65);
531 		memcpy(wptr,FUSE_REGISTER_BLOB_ACL,64);
532 		wptr+=64;
533 		put8bit(&wptr,REGISTER_GETRANDOM);
534 		if (tcptowrite(fd,regbuff,8+65,1000)!=8+65) {
535 			if (verbose) {
536 				fprintf(stderr,"error sending data to mfsmaster\n");
537 			} else {
538 				lzfs_pretty_syslog(LOG_WARNING,"error sending data to mfsmaster");
539 			}
540 			tcpclose(fd);
541 			fd=-1;
542 			free(regbuff);
543 			return -1;
544 		}
545 		if (tcptoread(fd,regbuff,8,1000)!=8) {
546 			if (verbose) {
547 				fprintf(stderr,"error receiving data from mfsmaster\n");
548 			} else {
549 				lzfs_pretty_syslog(LOG_WARNING,"error receiving data from mfsmaster");
550 			}
551 			tcpclose(fd);
552 			fd=-1;
553 			free(regbuff);
554 			return -1;
555 		}
556 		rptr = regbuff;
557 		i = get32bit(&rptr);
558 		if (i!=MATOCL_FUSE_REGISTER) {
559 			if (verbose) {
560 				fprintf(stderr,"got incorrect answer from mfsmaster\n");
561 			} else {
562 				lzfs_pretty_syslog(LOG_WARNING,"got incorrect answer from mfsmaster");
563 			}
564 			tcpclose(fd);
565 			fd=-1;
566 			free(regbuff);
567 			return -1;
568 		}
569 		i = get32bit(&rptr);
570 		if (i!=32) {
571 			if (verbose) {
572 				fprintf(stderr,"got incorrect answer from mfsmaster\n");
573 			} else {
574 				lzfs_pretty_syslog(LOG_WARNING,"got incorrect answer from mfsmaster");
575 			}
576 			tcpclose(fd);
577 			fd=-1;
578 			free(regbuff);
579 			return -1;
580 		}
581 		if (tcptoread(fd,regbuff,32,1000)!=32) {
582 			if (verbose) {
583 				fprintf(stderr,"error receiving data from mfsmaster\n");
584 			} else {
585 				lzfs_pretty_syslog(LOG_WARNING,"error receiving data from mfsmaster");
586 			}
587 			tcpclose(fd);
588 			fd=-1;
589 			free(regbuff);
590 			return -1;
591 		}
592 		md5_init(&ctx);
593 		md5_update(&ctx,regbuff,16);
594 		md5_update(&ctx, gInitParams.password_digest.data(), gInitParams.password_digest.size());
595 		md5_update(&ctx,regbuff+16,16);
596 		md5_final(digest,&ctx);
597 	}
598 	wptr = regbuff;
599 	put32bit(&wptr,CLTOMA_FUSE_REGISTER);
600 	if (gInitParams.meta) {
601 		if (havepassword) {
602 			put32bit(&wptr,64+9+ileng+16);
603 		} else {
604 			put32bit(&wptr,64+9+ileng);
605 		}
606 	} else {
607 		if (havepassword) {
608 			put32bit(&wptr,64+13+ileng+pleng+16);
609 		} else {
610 			put32bit(&wptr,64+13+ileng+pleng);
611 		}
612 	}
613 	memcpy(wptr,FUSE_REGISTER_BLOB_ACL,64);
614 	wptr+=64;
615 	put8bit(&wptr,(gInitParams.meta)?REGISTER_NEWMETASESSION:REGISTER_NEWSESSION);
616 	put16bit(&wptr,LIZARDFS_PACKAGE_VERSION_MAJOR);
617 	put8bit(&wptr,LIZARDFS_PACKAGE_VERSION_MINOR);
618 	put8bit(&wptr,LIZARDFS_PACKAGE_VERSION_MICRO);
619 	put32bit(&wptr,ileng);
620 	memcpy(wptr,gInitParams.mountpoint.c_str(),ileng);
621 	wptr+=ileng;
622 	if (!gInitParams.meta) {
623 		put32bit(&wptr,pleng);
624 		memcpy(wptr,gInitParams.subfolder.c_str(),pleng);
625 	}
626 	if (havepassword) {
627 		memcpy(wptr+pleng,digest,16);
628 	}
629 	if (tcptowrite(fd,regbuff,8+64+(gInitParams.meta?9:13)+ileng+pleng+(havepassword?16:0),1000)!=(int32_t)(8+64+(gInitParams.meta?9:13)+ileng+pleng+(havepassword?16:0))) {
630 		if (verbose) {
631 			fprintf(stderr,"error sending data to mfsmaster: %s\n",strerr(tcpgetlasterror()));
632 		} else {
633 			lzfs_pretty_syslog(LOG_WARNING,"error sending data to mfsmaster: %s",strerr(tcpgetlasterror()));
634 		}
635 		tcpclose(fd);
636 		fd=-1;
637 		free(regbuff);
638 		return -1;
639 	}
640 	if (tcptoread(fd,regbuff,8,1000)!=8) {
641 		if (verbose) {
642 			fprintf(stderr,"error receiving data from mfsmaster: %s\n",strerr(tcpgetlasterror()));
643 		} else {
644 			lzfs_pretty_syslog(LOG_WARNING,"error receiving data from mfsmaster: %s",strerr(tcpgetlasterror()));
645 		}
646 		tcpclose(fd);
647 		fd=-1;
648 		free(regbuff);
649 		return -1;
650 	}
651 	rptr = regbuff;
652 	i = get32bit(&rptr);
653 	if (i!=MATOCL_FUSE_REGISTER) {
654 		if (verbose) {
655 			fprintf(stderr,"got incorrect answer from mfsmaster\n");
656 		} else {
657 			lzfs_pretty_syslog(LOG_WARNING,"got incorrect answer from mfsmaster");
658 		}
659 		tcpclose(fd);
660 		fd=-1;
661 		free(regbuff);
662 		return -1;
663 	}
664 	i = get32bit(&rptr);
665 	if (!(i==1 || (gInitParams.meta && (i==5 || i==9 || i==19)) || (gInitParams.meta==0 && (i==13 || i==21 || i==25 || i==35)))) {
666 		if (verbose) {
667 			fprintf(stderr,"got incorrect answer from mfsmaster\n");
668 		} else {
669 			lzfs_pretty_syslog(LOG_WARNING,"got incorrect answer from mfsmaster");
670 		}
671 		tcpclose(fd);
672 		fd=-1;
673 		free(regbuff);
674 		return -1;
675 	}
676 	if (tcptoread(fd,regbuff,i,1000)!=(int32_t)i) {
677 		if (verbose) {
678 			fprintf(stderr,"error receiving data from mfsmaster: %s\n",strerr(tcpgetlasterror()));
679 		} else {
680 			lzfs_pretty_syslog(LOG_WARNING,"error receiving data from mfsmaster: %s",strerr(tcpgetlasterror()));
681 		}
682 		tcpclose(fd);
683 		fd=-1;
684 		free(regbuff);
685 		return -1;
686 	}
687 	rptr = regbuff;
688 	if (i==1) {
689 		if (verbose) {
690 			fprintf(stderr,"mfsmaster register error: %s\n",lizardfs_error_string(rptr[0]));
691 		} else {
692 			lzfs_pretty_syslog(LOG_WARNING,"mfsmaster register error: %s",lizardfs_error_string(rptr[0]));
693 		}
694 		tcpclose(fd);
695 		fd=-1;
696 		free(regbuff);
697 		return -1;
698 	}
699 	if (i==9 || i==19 || i==25 || i==35) {
700 		masterversion = get32bit(&rptr);
701 	} else {
702 		masterversion = 0;
703 	}
704 	sessionid = get32bit(&rptr);
705 	sesflags = get8bit(&rptr);
706 	if (!gInitParams.meta) {
707 		rootuid = get32bit(&rptr);
708 		rootgid = get32bit(&rptr);
709 		if (i==21 || i==25 || i==35) {
710 			mapalluid = get32bit(&rptr);
711 			mapallgid = get32bit(&rptr);
712 		} else {
713 			mapalluid = 0;
714 			mapallgid = 0;
715 		}
716 	} else {
717 		rootuid = 0;
718 		rootgid = 0;
719 		mapalluid = 0;
720 		mapallgid = 0;
721 	}
722 	if (i==19 || i==35) {
723 		mingoal = get8bit(&rptr);
724 		maxgoal = get8bit(&rptr);
725 		mintrashtime = get32bit(&rptr);
726 		maxtrashtime = get32bit(&rptr);
727 	} else {
728 		mingoal = 0;
729 		maxgoal = 0;
730 		mintrashtime = 0;
731 		maxtrashtime = 0;
732 	}
733 	free(regbuff);
734 	lastwrite=time(NULL);
735 	if (!verbose) {
736 		lzfs_pretty_syslog(LOG_NOTICE,"registered to master with new session (id #%" PRIu32 ")", sessionid);
737 	}
738 	if (gInitParams.do_not_remember_password) {
739 		std::fill(gInitParams.password_digest.begin(), gInitParams.password_digest.end(), 0);
740 	}
741 	if (verbose) {
742 		fprintf(stderr,"mfsmaster accepted connection with parameters: ");
743 		j=0;
744 		for (i=0 ; i<8 ; i++) {
745 			if (sesflags&(1<<i)) {
746 				fprintf(stderr,"%s%s",j?",":"",sesflagposstrtab[i]);
747 				j=1;
748 			} else if (sesflagnegstrtab[i]) {
749 				fprintf(stderr,"%s%s",j?",":"",sesflagnegstrtab[i]);
750 				j=1;
751 			}
752 		}
753 		if (j==0) {
754 			fprintf(stderr,"-");
755 		}
756 		if (!gInitParams.meta) {
757 #ifndef _WIN32
758 			struct passwd pwd,*pw;
759 			struct group grp,*gr;
760 			char pwdgrpbuff[16384];
761 
762 			fprintf(stderr," ; root mapped to ");
763 			getpwuid_r(rootuid,&pwd,pwdgrpbuff,16384,&pw);
764 			if (pw) {
765 				fprintf(stderr,"%s:",pw->pw_name);
766 			} else {
767 				fprintf(stderr,"%" PRIu32 ":",rootuid);
768 			}
769 			getgrgid_r(rootgid,&grp,pwdgrpbuff,16384,&gr);
770 			if (gr) {
771 				fprintf(stderr,"%s",gr->gr_name);
772 			} else {
773 				fprintf(stderr,"%" PRIu32,rootgid);
774 			}
775 			if (sesflags&SESFLAG_MAPALL) {
776 				fprintf(stderr," ; users mapped to ");
777 				pw = getpwuid(mapalluid);
778 				if (pw) {
779 					fprintf(stderr,"%s:",pw->pw_name);
780 				} else {
781 					fprintf(stderr,"%" PRIu32 ":",mapalluid);
782 				}
783 				gr = getgrgid(mapallgid);
784 				if (gr) {
785 					fprintf(stderr,"%s",gr->gr_name);
786 				} else {
787 					fprintf(stderr,"%" PRIu32,mapallgid);
788 				}
789 			}
790 #else
791 			fprintf(stderr, " ; root mapped to %" PRIu32 ":%" PRIu32, rootuid, rootgid);
792 			fprintf(stderr, " ; users mapped to %" PRIu32 ":%" PRIu32, mapalluid, mapallgid);
793 #endif
794 		} else {
795 			// meta
796 			if (sesflags & SESFLAG_NONROOTMETA) {
797 				nonRootAllowedToUseMeta() = true;
798 			} else {
799 				nonRootAllowedToUseMeta() = false;
800 			}
801 		}
802 		if (mingoal>0 && maxgoal>0) {
803 			if (mingoal > GoalId::kMin || maxgoal < GoalId::kMax) {
804 				fprintf(stderr," ; setgoal limited to (%u:%u)",mingoal,maxgoal);
805 			}
806 			if (mintrashtime>0 || maxtrashtime<UINT32_C(0xFFFFFFFF)) {
807 				fprintf(stderr," ; settrashtime limited to (");
808 				if (mintrashtime>0) {
809 					if (mintrashtime>604800) {
810 						fprintf(stderr,"%uw",mintrashtime/604800);
811 						mintrashtime %= 604800;
812 					}
813 					if (mintrashtime>86400) {
814 						fprintf(stderr,"%ud",mintrashtime/86400);
815 						mintrashtime %= 86400;
816 					}
817 					if (mintrashtime>3600) {
818 						fprintf(stderr,"%uh",mintrashtime/3600);
819 						mintrashtime %= 3600;
820 					}
821 					if (mintrashtime>60) {
822 						fprintf(stderr,"%um",mintrashtime/60);
823 						mintrashtime %= 60;
824 					}
825 					if (mintrashtime>0) {
826 						fprintf(stderr,"%us",mintrashtime);
827 					}
828 				} else {
829 					fprintf(stderr,"0s");
830 				}
831 				fprintf(stderr,":");
832 				if (maxtrashtime>0) {
833 					if (maxtrashtime>604800) {
834 						fprintf(stderr,"%uw",maxtrashtime/604800);
835 						maxtrashtime %= 604800;
836 					}
837 					if (maxtrashtime>86400) {
838 						fprintf(stderr,"%ud",maxtrashtime/86400);
839 						maxtrashtime %= 86400;
840 					}
841 					if (maxtrashtime>3600) {
842 						fprintf(stderr,"%uh",maxtrashtime/3600);
843 						maxtrashtime %= 3600;
844 					}
845 					if (maxtrashtime>60) {
846 						fprintf(stderr,"%um",maxtrashtime/60);
847 						maxtrashtime %= 60;
848 					}
849 					if (maxtrashtime>0) {
850 						fprintf(stderr,"%us",maxtrashtime);
851 					}
852 				} else {
853 					fprintf(stderr,"0s");
854 				}
855 				fprintf(stderr,")");
856 			}
857 		}
858 		fprintf(stderr,"\n");
859 	}
860 	return 0;
861 }
862 
fs_reconnect()863 void fs_reconnect() {
864 	uint32_t i;
865 	uint8_t *wptr,regbuff[8+64+9];
866 	const uint8_t *rptr;
867 
868 	if (sessionid==0) {
869 		lzfs_pretty_syslog(LOG_WARNING,"can't register: session not created");
870 		return;
871 	}
872 
873 	fd = tcpsocket();
874 	if (fd<0) {
875 		return;
876 	}
877 	if (tcpnodelay(fd)<0) {
878 		lzfs_pretty_syslog(LOG_WARNING,"can't set TCP_NODELAY: %s",strerr(tcpgetlasterror()));
879 	}
880 	if (srcip>0) {
881 		if (tcpnumbind(fd,srcip,0)<0) {
882 			lzfs_pretty_syslog(LOG_WARNING,"can't bind socket to given ip (\"%s\")",srcstrip);
883 			tcpclose(fd);
884 			fd=-1;
885 			return;
886 		}
887 	}
888 	if (tcpnumconnect(fd,masterip,masterport)<0) {
889 		lzfs_pretty_syslog(LOG_WARNING,"can't connect to master (\"%s\":\"%" PRIu16 "\")",masterstrip,masterport);
890 		tcpclose(fd);
891 		fd=-1;
892 		return;
893 	}
894 	master_stats_inc(MASTER_CONNECTS);
895 	wptr = regbuff;
896 	put32bit(&wptr,CLTOMA_FUSE_REGISTER);
897 	put32bit(&wptr,73);
898 	memcpy(wptr,FUSE_REGISTER_BLOB_ACL,64);
899 	wptr+=64;
900 	put8bit(&wptr,REGISTER_RECONNECT);
901 	put32bit(&wptr,sessionid);
902 	put16bit(&wptr,LIZARDFS_PACKAGE_VERSION_MAJOR);
903 	put8bit(&wptr,LIZARDFS_PACKAGE_VERSION_MINOR);
904 	put8bit(&wptr,LIZARDFS_PACKAGE_VERSION_MICRO);
905 	if (tcptowrite(fd,regbuff,8+64+9,1000)!=8+64+9) {
906 		lzfs_pretty_syslog(LOG_WARNING,"master: register error (write: %s)",strerr(tcpgetlasterror()));
907 		tcpclose(fd);
908 		fd=-1;
909 		return;
910 	}
911 	master_stats_add(MASTER_BYTESSENT,16+64);
912 	master_stats_inc(MASTER_PACKETSSENT);
913 	if (tcptoread(fd,regbuff,8,1000)!=8) {
914 		lzfs_pretty_syslog(LOG_WARNING,"master: register error (read header: %s)",strerr(tcpgetlasterror()));
915 		tcpclose(fd);
916 		fd=-1;
917 		return;
918 	}
919 	master_stats_add(MASTER_BYTESRCVD,8);
920 	rptr = regbuff;
921 	i = get32bit(&rptr);
922 	if (i!=MATOCL_FUSE_REGISTER) {
923 		lzfs_pretty_syslog(LOG_WARNING,"master: register error (bad answer: %" PRIu32 ")",i);
924 		tcpclose(fd);
925 		fd=-1;
926 		return;
927 	}
928 	i = get32bit(&rptr);
929 	if (i!=1) {
930 		lzfs_pretty_syslog(LOG_WARNING,"master: register error (bad length: %" PRIu32 ")",i);
931 		tcpclose(fd);
932 		fd=-1;
933 		return;
934 	}
935 	if (tcptoread(fd,regbuff,i,1000)!=(int32_t)i) {
936 		lzfs_pretty_syslog(LOG_WARNING,"master: register error (read data: %s)",strerr(tcpgetlasterror()));
937 		tcpclose(fd);
938 		fd=-1;
939 		return;
940 	}
941 	master_stats_add(MASTER_BYTESRCVD,i);
942 	master_stats_inc(MASTER_PACKETSRCVD);
943 	rptr = regbuff;
944 	if (rptr[0]!=0) {
945 		sessionlost=1;
946 		lzfs_pretty_syslog(LOG_WARNING,"master: register status: %s",lizardfs_error_string(rptr[0]));
947 		tcpclose(fd);
948 		fd=-1;
949 		return;
950 	}
951 	lastwrite=time(NULL);
952 	lzfs_pretty_syslog(LOG_NOTICE,"registered to master (session id #%" PRIu32 ")", sessionid);
953 }
954 
fs_close_session(void)955 void fs_close_session(void) {
956 	uint8_t *wptr,regbuff[8+64+5];
957 
958 	if (sessionid==0) {
959 		return;
960 	}
961 
962 	wptr = regbuff;
963 	put32bit(&wptr,CLTOMA_FUSE_REGISTER);
964 	put32bit(&wptr,69);
965 	memcpy(wptr,FUSE_REGISTER_BLOB_ACL,64);
966 	wptr+=64;
967 	put8bit(&wptr,REGISTER_CLOSESESSION);
968 	put32bit(&wptr,sessionid);
969 	if (tcptowrite(fd,regbuff,8+64+5,1000)!=8+64+5) {
970 		lzfs_pretty_syslog(LOG_WARNING,"master: close session error (write: %s)",strerr(tcpgetlasterror()));
971 	}
972 }
973 
974 #ifdef ENABLE_EXIT_ON_USR1
usr1_handler(int)975 static void usr1_handler(int) {
976 	gIsKilled = true;
977 }
978 #endif
979 
fs_nop_thread(void * arg)980 void* fs_nop_thread(void *arg) {
981 	uint8_t *ptr,hdr[12],*inodespacket;
982 	int32_t inodesleng;
983 	acquired_file *afptr;
984 	int now;
985 	uint32_t inodeswritecnt=0;
986 	(void)arg;
987 
988 #ifdef ENABLE_EXIT_ON_USR1
989 	if (signal(SIGUSR1, usr1_handler) == SIG_ERR) {
990 		mabort("Can't set handler for SIGUSR1");
991 	}
992 #endif
993 	for (;;) {
994 		now = time(NULL);
995 		std::unique_lock<std::mutex> fdLock(fdMutex);
996 		if (fterm) {
997 			if (fd>=0) {
998 				fs_close_session();
999 			}
1000 			return NULL;
1001 		}
1002 		if (gIsKilled) {
1003 			lzfs_pretty_syslog(LOG_NOTICE, "Received SIGUSR1, killing gently...");
1004 			exit(LIZARDFS_EXIT_STATUS_GENTLY_KILL);
1005 		}
1006 		if (disconnect == false && fd >= 0) {
1007 			if (lastwrite+2<now) {  // NOP
1008 				ptr = hdr;
1009 				put32bit(&ptr,ANTOAN_NOP);
1010 				put32bit(&ptr,4);
1011 				put32bit(&ptr,0);
1012 				if (tcptowrite(fd,hdr,12,1000)!=12) {
1013 					disconnect = true;
1014 				} else {
1015 					master_stats_add(MASTER_BYTESSENT,12);
1016 					master_stats_inc(MASTER_PACKETSSENT);
1017 				}
1018 				lastwrite=now;
1019 			}
1020 			if (++inodeswritecnt >= gInitParams.report_reserved_period) {
1021 				inodeswritecnt = 0;
1022 				std::unique_lock<std::mutex> asLock(acquiredFileMutex);
1023 				inodesleng=8;
1024 				for (afptr=afhead ; afptr ; afptr=afptr->next) {
1025 					//lzfs_pretty_syslog(LOG_NOTICE,"reserved inode: %" PRIu32,afptr->inode);
1026 					inodesleng+=4;
1027 				}
1028 				inodespacket = (uint8_t*) malloc(inodesleng);
1029 				ptr = inodespacket;
1030 				put32bit(&ptr,CLTOMA_FUSE_RESERVED_INODES);
1031 				put32bit(&ptr,inodesleng-8);
1032 				for (afptr=afhead ; afptr ; afptr=afptr->next) {
1033 					put32bit(&ptr,afptr->inode);
1034 				}
1035 				if (tcptowrite(fd,inodespacket,inodesleng,1000)!=inodesleng) {
1036 					disconnect = true;
1037 				} else {
1038 					master_stats_add(MASTER_BYTESSENT,inodesleng);
1039 					master_stats_inc(MASTER_PACKETSSENT);
1040 				}
1041 				free(inodespacket);
1042 			}
1043 		}
1044 		fdLock.unlock();
1045 		sleep(1);
1046 	}
1047 }
1048 
fs_append_from_master(MessageBuffer & buffer,uint32_t size)1049 bool fs_append_from_master(MessageBuffer& buffer, uint32_t size) {
1050 	if (size == 0) {
1051 		return true;
1052 	}
1053 	const uint32_t oldSize = buffer.size();
1054 	buffer.resize(oldSize + size);
1055 	uint8_t *appendPointer = buffer.data() + oldSize;
1056 	int r = tcptoread(fd, appendPointer, size, RECEIVE_TIMEOUT * 1000);
1057 	if (r == 0) {
1058 		lzfs_pretty_syslog(LOG_WARNING,"master: connection lost");
1059 		setDisconnect(true);
1060 		return false;
1061 	}
1062 	if (r != (int)size) {
1063 		lzfs_pretty_syslog(LOG_WARNING,"master: tcp recv error: %s",strerr(tcpgetlasterror()));
1064 		setDisconnect(true);
1065 		return false;
1066 	}
1067 	master_stats_add(MASTER_BYTESRCVD, size);
1068 	return true;
1069 }
1070 
1071 template<class... Args>
fs_deserialize_from_master(uint32_t & remainingBytes,Args &...destination)1072 bool fs_deserialize_from_master(uint32_t& remainingBytes, Args&... destination) {
1073 	const uint32_t size = serializedSize(destination...);
1074 	if (size > remainingBytes) {
1075 		lzfs_pretty_syslog(LOG_WARNING,"master: packet too short");
1076 		setDisconnect(true);
1077 		return false;
1078 	}
1079 	MessageBuffer buffer;
1080 	if (!fs_append_from_master(buffer, size)) {
1081 		return false;
1082 	}
1083 	try {
1084 		deserialize(buffer, destination...);
1085 	} catch (IncorrectDeserializationException& e) {
1086 		lzfs_pretty_syslog(LOG_WARNING,"master: deserialization error: %s", e.what());
1087 		setDisconnect(true);
1088 		return false;
1089 	}
1090 	remainingBytes -= size;
1091 	return true;
1092 }
1093 
fs_receive_thread(void *)1094 void* fs_receive_thread(void *) {
1095 	uint32_t initialReconnectSleep_ms = 100;
1096 	uint32_t reconnectSleep_ms = initialReconnectSleep_ms;
1097 	for (;;) {
1098 		std::unique_lock<std::mutex>fdLock(fdMutex);
1099 		if (fterm) {
1100 			return NULL;
1101 		}
1102 		if (disconnect) {
1103 			tcpclose(fd);
1104 			fd=-1;
1105 			disconnect = false;
1106 			// send to any threc status error and unlock them
1107 			std::unique_lock<std::mutex>recLock(recMutex);
1108 			for (threc *rec=threchead ; rec ; rec=rec->next) {
1109 				std::unique_lock<std::mutex> lock(rec->mutex);
1110 				if (rec->sent) {
1111 					rec->status = 1;
1112 					rec->received = true;
1113 					if (rec->waiting) {
1114 						rec->condition.notify_one();
1115 					}
1116 				}
1117 			}
1118 		}
1119 		if (fd==-1 && sessionid!=0) {
1120 			fs_reconnect();         // try to register using the same session id
1121 		}
1122 		if (fd==-1) {   // still not connected
1123 			if (sessionlost) {      // if previous session is lost then try to register as a new session
1124 				if (fs_connect(false)==0) {
1125 					sessionlost=0;
1126 				}
1127 			} else {        // if other problem occurred then try to resolve hostname and portname then try to reconnect using the same session id
1128 				if (fs_resolve(false, gInitParams.bind_host, gInitParams.host, gInitParams.port) == 0) {
1129 					fs_reconnect();
1130 				}
1131 			}
1132 		}
1133 		if (fd==-1) {
1134 			fdLock.unlock();
1135 			usleep(reconnectSleep_ms * 1000);
1136 			// slowly increase timeout before each retry
1137 			if (reconnectSleep_ms < 5 * initialReconnectSleep_ms) {
1138 				reconnectSleep_ms += initialReconnectSleep_ms / 2;
1139 			} else if (reconnectSleep_ms < 10 * initialReconnectSleep_ms) {
1140 				reconnectSleep_ms += initialReconnectSleep_ms;
1141 			} else {
1142 				reconnectSleep_ms = 20 * initialReconnectSleep_ms;
1143 			}
1144 			continue;
1145 		} else {
1146 			// connecection succeeded -- reset timeout the initial value
1147 			reconnectSleep_ms = initialReconnectSleep_ms;
1148 		}
1149 		fdLock.unlock();
1150 
1151 		PacketHeader packetHeader;
1152 		PacketVersion packetVersion;
1153 		uint32_t messageId = 0;
1154 		uint32_t remainingBytes = serializedSize(packetHeader);
1155 		if (!fs_deserialize_from_master(remainingBytes, packetHeader)) {
1156 			continue;
1157 		}
1158 		master_stats_inc(MASTER_PACKETSRCVD);
1159 		remainingBytes = packetHeader.length;
1160 
1161 		{
1162 			std::unique_lock<std::mutex> lock(perTypePacketHandlersLock);
1163 			const PerTypePacketHandlers::iterator handler =
1164 					perTypePacketHandlers.find(packetHeader.type);
1165 			if (handler != perTypePacketHandlers.end()) {
1166 				MessageBuffer buffer;
1167 				if (fs_append_from_master(buffer, remainingBytes)) {
1168 					handler->second->handle(std::move(buffer));
1169 				}
1170 				continue;
1171 			}
1172 		}
1173 
1174 		if (packetHeader.isLizPacketType()) {
1175 			if (remainingBytes < serializedSize(packetVersion, messageId)) {
1176 				lzfs_pretty_syslog(LOG_WARNING,"master: packet too short: no msgid");
1177 				setDisconnect(true);
1178 				continue;
1179 			}
1180 			if (!fs_deserialize_from_master(remainingBytes, packetVersion, messageId)) {
1181 				continue;
1182 			}
1183 		} else {
1184 			if (remainingBytes < serializedSize(messageId)) {
1185 				lzfs_pretty_syslog(LOG_WARNING,"master: packet too short: no msgid");
1186 				setDisconnect(true);
1187 				continue;
1188 			}
1189 			if (!fs_deserialize_from_master(remainingBytes, messageId)) {
1190 				continue;
1191 			}
1192 		}
1193 
1194 		if (messageId == 0) {
1195 			if (packetHeader.type == ANTOAN_NOP && remainingBytes == 0) {
1196 				continue;
1197 			}
1198 			if (packetHeader.type == ANTOAN_UNKNOWN_COMMAND ||
1199 					packetHeader.type == ANTOAN_BAD_COMMAND_SIZE) {
1200 				// just ignore these packets with packetId==0
1201 				continue;
1202 			}
1203 		}
1204 		threc *rec = fs_get_threc_by_id(messageId);
1205 		if (rec == NULL) {
1206 			lzfs_pretty_syslog(LOG_WARNING,"master: got unexpected queryid");
1207 			setDisconnect(true);
1208 			continue;
1209 		}
1210 		std::unique_lock<std::mutex> lock(rec->mutex);
1211 		rec->inputBuffer.clear();
1212 		if (packetHeader.isLizPacketType()) {
1213 			serialize(rec->inputBuffer, packetVersion, messageId);
1214 		} else {
1215 			serialize(rec->inputBuffer, messageId);
1216 		}
1217 		if (!fs_append_from_master(rec->inputBuffer, remainingBytes)) {
1218 			lock.unlock();
1219 			continue;
1220 		}
1221 		rec->sent = false;
1222 		rec->status = 0;
1223 		rec->receivedType = packetHeader.type;
1224 		rec->received = true;
1225 		if (rec->waiting) {
1226 			rec->condition.notify_one();
1227 		}
1228 	}
1229 }
1230 
1231 // called before fork
fs_init_master_connection(LizardClient::FsInitParams & params)1232 int fs_init_master_connection(LizardClient::FsInitParams &params) {
1233 	master_statsptr_init();
1234 
1235 	gInitParams = params;
1236 	std::fill(params.password_digest.begin(), params.password_digest.end(), 0);
1237 
1238 	fd = -1;
1239 	sessionlost = params.delayed_init;
1240 	sessionid = 0;
1241 	disconnect = false;
1242 
1243 	if (params.delayed_init) {
1244 		return 1;
1245 	}
1246 	return fs_connect(params.verbose);
1247 }
1248 
1249 // called after fork
fs_init_threads(uint32_t retries)1250 void fs_init_threads(uint32_t retries) {
1251 	pthread_attr_t thattr;
1252 	maxretries = retries;
1253 	fterm = 0;
1254 
1255 	pthread_attr_init(&thattr);
1256 	pthread_attr_setstacksize(&thattr,0x100000);
1257 	pthread_create(&rpthid,&thattr,fs_receive_thread,NULL);
1258 	pthread_create(&npthid,&thattr,fs_nop_thread,NULL);
1259 	pthread_attr_destroy(&thattr);
1260 }
1261 
fs_term(void)1262 void fs_term(void) {
1263 	threc *tr,*trn;
1264 	acquired_file *af,*afn;
1265 	std::unique_lock<std::mutex> fd_lock(fdMutex);
1266 	fterm = 1;
1267 	fd_lock.unlock();
1268 	pthread_join(npthid,NULL);
1269 	pthread_join(rpthid,NULL);
1270 	std::unique_lock<std::mutex> rec_lock(recMutex);
1271 	for (tr = threchead ; tr ; tr = trn) {
1272 		trn = tr->next;
1273 		tr->outputBuffer.clear();
1274 		tr->inputBuffer.clear();
1275 		delete tr;
1276 	}
1277 	threchead = nullptr;
1278 	rec_lock.unlock();
1279 	std::unique_lock<std::mutex> af_lock(acquiredFileMutex);
1280 	for (af = afhead ; af ; af = afn) {
1281 		afn = af->next;
1282 		free(af);
1283 	}
1284 	afhead = nullptr;
1285 	af_lock.unlock();
1286 	fd_lock.lock();
1287 	if (fd>=0) {
1288 		tcpclose(fd);
1289 	}
1290 }
1291 
fs_got_inconsistent(const std::string & type,uint32_t size,const std::string & what)1292 static void fs_got_inconsistent(const std::string& type, uint32_t size, const std::string& what) {
1293 	lzfs_pretty_syslog(LOG_NOTICE,
1294 			"Got inconsistent %s message from master (length:%" PRIu32 "): %s",
1295 			type.c_str(), size, what.c_str());
1296 	setDisconnect(true);
1297 }
1298 
fs_statfs(uint64_t * totalspace,uint64_t * availspace,uint64_t * trashspace,uint64_t * reservedspace,uint32_t * inodes)1299 void fs_statfs(uint64_t *totalspace,uint64_t *availspace,uint64_t *trashspace,uint64_t *reservedspace,uint32_t *inodes) {
1300 	uint8_t *wptr;
1301 	const uint8_t *rptr;
1302 	uint32_t i;
1303 	threc *rec = fs_get_my_threc();
1304 	wptr = fs_createpacket(rec,CLTOMA_FUSE_STATFS,0);
1305 	if (wptr==NULL) {
1306 		*totalspace = 0;
1307 		*availspace = 0;
1308 		*trashspace = 0;
1309 		*reservedspace = 0;
1310 		*inodes = 0;
1311 		return;
1312 	}
1313 	rptr = fs_sendandreceive(rec,MATOCL_FUSE_STATFS,&i);
1314 	if (rptr==NULL || i!=36) {
1315 		*totalspace = 0;
1316 		*availspace = 0;
1317 		*trashspace = 0;
1318 		*reservedspace = 0;
1319 		*inodes = 0;
1320 	} else {
1321 		*totalspace = get64bit(&rptr);
1322 		*availspace = get64bit(&rptr);
1323 		*trashspace = get64bit(&rptr);
1324 		*reservedspace = get64bit(&rptr);
1325 		*inodes = get32bit(&rptr);
1326 	}
1327 }
1328 
fs_access(uint32_t inode,uint32_t uid,uint32_t gid,uint8_t modemask)1329 uint8_t fs_access(uint32_t inode,uint32_t uid,uint32_t gid,uint8_t modemask) {
1330 	uint8_t *wptr;
1331 	const uint8_t *rptr;
1332 	uint32_t i;
1333 	uint8_t ret;
1334 	threc *rec = fs_get_my_threc();
1335 	wptr = fs_createpacket(rec,CLTOMA_FUSE_ACCESS,13);
1336 	if (wptr==NULL) {
1337 		return LIZARDFS_ERROR_IO;
1338 	}
1339 	put32bit(&wptr,inode);
1340 	put32bit(&wptr,uid);
1341 	put32bit(&wptr,gid);
1342 	put8bit(&wptr,modemask);
1343 	rptr = fs_sendandreceive(rec,MATOCL_FUSE_ACCESS,&i);
1344 	if (!rptr || i!=1) {
1345 		ret = LIZARDFS_ERROR_IO;
1346 	} else {
1347 		ret = rptr[0];
1348 	}
1349 	return ret;
1350 }
1351 
fs_lookup(uint32_t parent,const std::string & path,uint32_t uid,uint32_t gid,uint32_t * inode,Attributes & attr)1352 uint8_t fs_lookup(uint32_t parent, const std::string &path, uint32_t uid, uint32_t gid, uint32_t *inode, Attributes &attr) {
1353 	threc *rec = fs_get_my_threc();
1354 	auto message = cltoma::wholePathLookup::build(rec->packetId, parent, path, uid, gid);
1355 	if (!fs_lizcreatepacket(rec, message)) {
1356 		return LIZARDFS_ERROR_IO;
1357 	}
1358 	if (!fs_lizsendandreceive(rec, LIZ_MATOCL_WHOLE_PATH_LOOKUP, message)) {
1359 		return LIZARDFS_ERROR_IO;
1360 	}
1361 	try {
1362 		uint32_t msgid;
1363 		PacketVersion packet_version;
1364 		deserializePacketVersionNoHeader(message, packet_version);
1365 		if (packet_version == matocl::wholePathLookup::kStatusPacketVersion) {
1366 			uint8_t status;
1367 			matocl::wholePathLookup::deserialize(message, msgid, status);
1368 			if (status == LIZARDFS_STATUS_OK) {
1369 				fs_got_inconsistent("LIZ_MATOCL_WHOLE_PATH_LOOKUP", message.size(),
1370 				                    "version 0 and LIZARDFS_STATUS_OK");
1371 				return LIZARDFS_ERROR_IO;
1372 			}
1373 			return status;
1374 		} else if (packet_version == matocl::wholePathLookup::kResponsePacketVersion) {
1375 			matocl::wholePathLookup::deserialize(message, msgid, *inode, attr);
1376 			return LIZARDFS_STATUS_OK;
1377 		} else {
1378 			fs_got_inconsistent("LIZ_MATOCL_WHOLE_PATH_LOOKUP", message.size(),
1379 					"unknown version " + std::to_string(packet_version));
1380 			return LIZARDFS_ERROR_IO;
1381 		}
1382 	} catch (Exception& ex) {
1383 		fs_got_inconsistent("LIZ_MATOCL_WHOLE_PATH_LOOKUP", message.size(), ex.what());
1384 		return LIZARDFS_ERROR_IO;
1385 	}
1386 }
1387 
fs_getattr(uint32_t inode,uint32_t uid,uint32_t gid,Attributes & attr)1388 uint8_t fs_getattr(uint32_t inode, uint32_t uid, uint32_t gid, Attributes &attr) {
1389 	uint8_t *wptr;
1390 	const uint8_t *rptr;
1391 	uint32_t i;
1392 	uint8_t ret;
1393 	threc *rec = fs_get_my_threc();
1394 	wptr = fs_createpacket(rec,CLTOMA_FUSE_GETATTR,12);
1395 	if (wptr==NULL) {
1396 		return LIZARDFS_ERROR_IO;
1397 	}
1398 	put32bit(&wptr,inode);
1399 	put32bit(&wptr,uid);
1400 	put32bit(&wptr,gid);
1401 	rptr = fs_sendandreceive(rec,MATOCL_FUSE_GETATTR,&i);
1402 	if (rptr==NULL) {
1403 		ret = LIZARDFS_ERROR_IO;
1404 	} else if (i==1) {
1405 		ret = rptr[0];
1406 	} else if (i != attr.size()) {
1407 		setDisconnect(true);
1408 		ret = LIZARDFS_ERROR_IO;
1409 	} else {
1410 		memcpy(attr.data(), rptr, attr.size());
1411 		ret = LIZARDFS_STATUS_OK;
1412 	}
1413 	return ret;
1414 }
1415 
fs_setattr(uint32_t inode,uint32_t uid,uint32_t gid,uint8_t setmask,uint16_t attrmode,uint32_t attruid,uint32_t attrgid,uint32_t attratime,uint32_t attrmtime,uint8_t sugidclearmode,Attributes & attr)1416 uint8_t fs_setattr(uint32_t inode, uint32_t uid, uint32_t gid, uint8_t setmask, uint16_t attrmode, uint32_t attruid, uint32_t attrgid, uint32_t attratime, uint32_t attrmtime, uint8_t sugidclearmode, Attributes &attr) {
1417 	uint8_t *wptr;
1418 	const uint8_t *rptr;
1419 	uint32_t i;
1420 	uint8_t ret;
1421 	threc *rec = fs_get_my_threc();
1422 	if (masterversion<0x010619) {
1423 		wptr = fs_createpacket(rec,CLTOMA_FUSE_SETATTR,31);
1424 	} else {
1425 		wptr = fs_createpacket(rec,CLTOMA_FUSE_SETATTR,32);
1426 	}
1427 	if (wptr==NULL) {
1428 		return LIZARDFS_ERROR_IO;
1429 	}
1430 	put32bit(&wptr,inode);
1431 	put32bit(&wptr,uid);
1432 	put32bit(&wptr,gid);
1433 	put8bit(&wptr,setmask);
1434 	put16bit(&wptr,attrmode);
1435 	put32bit(&wptr,attruid);
1436 	put32bit(&wptr,attrgid);
1437 	put32bit(&wptr,attratime);
1438 	put32bit(&wptr,attrmtime);
1439 	if (masterversion>=0x010619) {
1440 		put8bit(&wptr,sugidclearmode);
1441 	}
1442 	rptr = fs_sendandreceive(rec,MATOCL_FUSE_SETATTR,&i);
1443 	if (rptr==NULL) {
1444 		ret = LIZARDFS_ERROR_IO;
1445 	} else if (i==1) {
1446 		ret = rptr[0];
1447 	} else if (i != attr.size()) {
1448 		setDisconnect(true);
1449 		ret = LIZARDFS_ERROR_IO;
1450 	} else {
1451 		memcpy(attr.data(), rptr, attr.size());
1452 		ret = LIZARDFS_STATUS_OK;
1453 	}
1454 	return ret;
1455 }
1456 
fs_truncate(uint32_t inode,bool opened,uint32_t uid,uint32_t gid,uint64_t length,bool & clientPerforms,Attributes & attr,uint64_t & oldLength,uint32_t & lockId)1457 uint8_t fs_truncate(uint32_t inode, bool opened, uint32_t uid, uint32_t gid, uint64_t length,
1458 		bool& clientPerforms, Attributes& attr, uint64_t& oldLength, uint32_t& lockId) {
1459 	threc *rec = fs_get_my_threc();
1460 	std::vector<uint8_t> message;
1461 	cltoma::fuseTruncate::serialize(message, rec->packetId, inode, opened, uid, gid, length);
1462 	if (!fs_lizcreatepacket(rec, message)) {
1463 		return LIZARDFS_ERROR_IO;
1464 	}
1465 
1466 	try {
1467 		if (!fs_lizsendandreceive(rec, LIZ_MATOCL_FUSE_TRUNCATE, message)) {
1468 			return LIZARDFS_ERROR_IO;
1469 		}
1470 
1471 		clientPerforms = false;
1472 		uint32_t messageId;
1473 		PacketVersion packetVersion;
1474 		deserializePacketVersionNoHeader(message, packetVersion);
1475 		if (packetVersion == matocl::fuseTruncate::kStatusPacketVersion) {
1476 			uint8_t status;
1477 			matocl::fuseTruncate::deserialize(message, messageId, status);
1478 			if (status == LIZARDFS_STATUS_OK) {
1479 				lzfs_pretty_syslog (LOG_NOTICE,
1480 						"Received LIZARDFS_STATUS_OK in message LIZ_MATOCL_FUSE_TRUNCATE with version"
1481 						" %d" PRIu32, matocl::fuseTruncate::kStatusPacketVersion);
1482 				setDisconnect(true);
1483 				return LIZARDFS_ERROR_IO;
1484 			}
1485 			return status;
1486 		} else if (packetVersion == matocl::fuseTruncate::kFinishedPacketVersion) {
1487 			matocl::fuseTruncate::deserialize(message, messageId, attr);
1488 		} else if (packetVersion == matocl::fuseTruncate::kInProgressPacketVersion) {
1489 			clientPerforms = true;
1490 			matocl::fuseTruncate::deserialize(message, messageId, oldLength, lockId);
1491 		} else {
1492 			lzfs_pretty_syslog(LOG_NOTICE, "LIZ_MATOCL_FUSE_TRUNCATE - wrong packet version");
1493 			setDisconnect(true);
1494 			return LIZARDFS_ERROR_IO;
1495 		}
1496 	} catch (IncorrectDeserializationException& ex) {
1497 		lzfs_pretty_syslog(LOG_NOTICE,
1498 				"got inconsistent LIZ_MATOCL_FUSE_TRUNCATE message from master "
1499 				"(length:%" PRIu64"), %s", message.size(), ex.what());
1500 		setDisconnect(true);
1501 		return LIZARDFS_ERROR_IO;
1502 	}
1503 
1504 	return LIZARDFS_STATUS_OK;
1505 }
1506 
fs_truncateend(uint32_t inode,uint32_t uid,uint32_t gid,uint64_t length,uint32_t lockId,Attributes & attr)1507 uint8_t fs_truncateend(uint32_t inode, uint32_t uid, uint32_t gid, uint64_t length, uint32_t lockId,
1508 		Attributes& attr) {
1509 	threc *rec = fs_get_my_threc();
1510 	std::vector<uint8_t> message;
1511 	cltoma::fuseTruncateEnd::serialize(message, rec->packetId, inode, uid, gid, length, lockId);
1512 	if (!fs_lizcreatepacket(rec, message)) {
1513 		return LIZARDFS_ERROR_IO;
1514 	}
1515 
1516 	try {
1517 		if (!fs_lizsendandreceive(rec, LIZ_MATOCL_FUSE_TRUNCATE_END, message)) {
1518 			return LIZARDFS_ERROR_IO;
1519 		}
1520 
1521 		PacketVersion packetVersion;
1522 		deserializePacketVersionNoHeader(message, packetVersion);
1523 		uint32_t messageId;
1524 		if (packetVersion == matocl::fuseTruncateEnd::kStatusPacketVersion) {
1525 			uint8_t status;
1526 			matocl::fuseTruncateEnd::deserialize(message, messageId, status);
1527 			if (status == LIZARDFS_STATUS_OK) {
1528 				lzfs_pretty_syslog (LOG_NOTICE,
1529 						"Received LIZARDFS_STATUS_OK in message LIZ_MATOCL_FUSE_TRUNCATE_END with version"
1530 						" %d" PRIu32, matocl::fuseTruncateEnd::kStatusPacketVersion);
1531 				setDisconnect(true);
1532 				return LIZARDFS_ERROR_IO;
1533 			}
1534 			return status;
1535 		} else if (packetVersion == matocl::fuseTruncateEnd::kResponsePacketVersion) {
1536 			matocl::fuseTruncateEnd::deserialize(message, messageId, attr);
1537 		} else {
1538 			lzfs_pretty_syslog(LOG_NOTICE, "LIZ_MATOCL_FUSE_TRUNCATE_END - wrong packet version");
1539 			setDisconnect(true);
1540 			return LIZARDFS_ERROR_IO;
1541 		}
1542 	} catch (IncorrectDeserializationException& ex) {
1543 		lzfs_pretty_syslog(LOG_NOTICE,
1544 				"got inconsistent LIZ_MATOCL_FUSE_TRUNCATE_END message from master "
1545 				"(length:%" PRIu64"), %s", message.size(), ex.what());
1546 		setDisconnect(true);
1547 		return LIZARDFS_ERROR_IO;
1548 	}
1549 
1550 	return LIZARDFS_STATUS_OK;
1551 }
1552 
1553 
fs_readlink(uint32_t inode,const uint8_t ** path)1554 uint8_t fs_readlink(uint32_t inode,const uint8_t **path) {
1555 	uint8_t *wptr;
1556 	const uint8_t *rptr;
1557 	uint32_t i;
1558 	uint32_t pleng;
1559 	uint8_t ret;
1560 	threc *rec = fs_get_my_threc();
1561 	wptr = fs_createpacket(rec,CLTOMA_FUSE_READLINK,4);
1562 	if (wptr==NULL) {
1563 		return LIZARDFS_ERROR_IO;
1564 	}
1565 	put32bit(&wptr,inode);
1566 	rptr = fs_sendandreceive(rec,MATOCL_FUSE_READLINK,&i);
1567 	if (rptr==NULL) {
1568 		ret = LIZARDFS_ERROR_IO;
1569 	} else if (i==1) {
1570 		ret = rptr[0];
1571 	} else if (i<4) {
1572 		setDisconnect(true);
1573 		ret = LIZARDFS_ERROR_IO;
1574 	} else {
1575 		pleng = get32bit(&rptr);
1576 		if (i!=4+pleng || pleng==0 || rptr[pleng-1]!=0) {
1577 			setDisconnect(true);
1578 			ret = LIZARDFS_ERROR_IO;
1579 		} else {
1580 			*path = rptr;
1581 			ret = LIZARDFS_STATUS_OK;
1582 		}
1583 	}
1584 	return ret;
1585 }
1586 
fs_symlink(uint32_t parent,uint8_t nleng,const uint8_t * name,const uint8_t * path,uint32_t uid,uint32_t gid,uint32_t * inode,Attributes & attr)1587 uint8_t fs_symlink(uint32_t parent, uint8_t nleng, const uint8_t *name, const uint8_t *path, uint32_t uid, uint32_t gid, uint32_t *inode, Attributes &attr) {
1588 	uint8_t *wptr;
1589 	const uint8_t *rptr;
1590 	uint32_t i;
1591 	uint32_t t32;
1592 	uint8_t ret;
1593 	threc *rec = fs_get_my_threc();
1594 	t32 = strlen((const char *)path)+1;
1595 	wptr = fs_createpacket(rec,CLTOMA_FUSE_SYMLINK,t32+nleng+17);
1596 	if (wptr==NULL) {
1597 		return LIZARDFS_ERROR_IO;
1598 	}
1599 	put32bit(&wptr,parent);
1600 	put8bit(&wptr,nleng);
1601 	memcpy(wptr,name,nleng);
1602 	wptr+=nleng;
1603 	put32bit(&wptr,t32);
1604 	memcpy(wptr,path,t32);
1605 	wptr+=t32;
1606 	put32bit(&wptr,uid);
1607 	put32bit(&wptr,gid);
1608 	rptr = fs_sendandreceive(rec,MATOCL_FUSE_SYMLINK,&i);
1609 	if (rptr==NULL) {
1610 		ret = LIZARDFS_ERROR_IO;
1611 	} else if (i==1) {
1612 		ret = rptr[0];
1613 	} else if (i != (attr.size() + 4)) {
1614 		setDisconnect(true);
1615 		ret = LIZARDFS_ERROR_IO;
1616 	} else {
1617 		t32 = get32bit(&rptr);
1618 		*inode = t32;
1619 		memcpy(attr.data(), rptr, attr.size());
1620 		ret = LIZARDFS_STATUS_OK;
1621 	}
1622 	return ret;
1623 }
1624 
fs_mknod(uint32_t parent,uint8_t nleng,const uint8_t * name,uint8_t type,uint16_t mode,uint16_t umask,uint32_t uid,uint32_t gid,uint32_t rdev,uint32_t & inode,Attributes & attr)1625 uint8_t fs_mknod(uint32_t parent, uint8_t nleng, const uint8_t *name, uint8_t type,
1626 		uint16_t mode, uint16_t umask, uint32_t uid, uint32_t gid, uint32_t rdev,
1627 		uint32_t &inode, Attributes& attr) {
1628 	threc* rec = fs_get_my_threc();
1629 	auto message = cltoma::fuseMknod::build(rec->packetId, parent,
1630 			MooseFsString<uint8_t>(reinterpret_cast<const char*>(name), nleng),
1631 			type, mode, umask, uid, gid, rdev);
1632 	if (!fs_lizcreatepacket(rec, message)) {
1633 		return LIZARDFS_ERROR_IO;
1634 	}
1635 	if (!fs_lizsendandreceive(rec, LIZ_MATOCL_FUSE_MKNOD, message)) {
1636 		return LIZARDFS_ERROR_IO;
1637 	}
1638 	try {
1639 		uint32_t messageId;
1640 		PacketVersion packetVersion;
1641 		deserializePacketVersionNoHeader(message, packetVersion);
1642 		if (packetVersion == matocl::fuseMkdir::kStatusPacketVersion) {
1643 			uint8_t status;
1644 			matocl::fuseMknod::deserialize(message, messageId, status);
1645 			if (status == LIZARDFS_STATUS_OK) {
1646 				fs_got_inconsistent("LIZ_MATOCL_FUSE_MKNOD", message.size(),
1647 						"version 0 and LIZARDFS_STATUS_OK");
1648 				return LIZARDFS_ERROR_IO;
1649 			}
1650 			return status;
1651 		} else if (packetVersion == matocl::fuseMkdir::kResponsePacketVersion) {
1652 			matocl::fuseMknod::deserialize(message, messageId, inode, attr);
1653 			return LIZARDFS_STATUS_OK;
1654 		} else {
1655 			fs_got_inconsistent("LIZ_MATOCL_FUSE_MKNOD", message.size(),
1656 					"unknown version " + std::to_string(packetVersion));
1657 			return LIZARDFS_ERROR_IO;
1658 		}
1659 		return LIZARDFS_ERROR_ENOTSUP;
1660 	} catch (Exception& ex) {
1661 		fs_got_inconsistent("LIZ_MATOCL_FUSE_MKNOD", message.size(), ex.what());
1662 		return LIZARDFS_ERROR_IO;
1663 	}
1664 }
1665 
fs_mkdir(uint32_t parent,uint8_t nleng,const uint8_t * name,uint16_t mode,uint16_t umask,uint32_t uid,uint32_t gid,uint8_t copysgid,uint32_t & inode,Attributes & attr)1666 uint8_t fs_mkdir(uint32_t parent, uint8_t nleng, const uint8_t *name,
1667 		uint16_t mode, uint16_t umask, uint32_t uid, uint32_t gid,
1668 		uint8_t copysgid,uint32_t &inode, Attributes& attr) {
1669 	threc* rec = fs_get_my_threc();
1670 	auto message = cltoma::fuseMkdir::build(rec->packetId, parent,
1671 			MooseFsString<uint8_t>(reinterpret_cast<const char*>(name), nleng),
1672 			mode, umask, uid, gid, copysgid);
1673 	if (!fs_lizcreatepacket(rec, message)) {
1674 		return LIZARDFS_ERROR_IO;
1675 	}
1676 	if (!fs_lizsendandreceive(rec, LIZ_MATOCL_FUSE_MKDIR, message)) {
1677 		return LIZARDFS_ERROR_IO;
1678 	}
1679 	try {
1680 		uint32_t messageId;
1681 		PacketVersion packetVersion;
1682 		deserializePacketVersionNoHeader(message, packetVersion);
1683 		if (packetVersion == matocl::fuseMkdir::kStatusPacketVersion) {
1684 			uint8_t status;
1685 			matocl::fuseMkdir::deserialize(message, messageId, status);
1686 			if (status == LIZARDFS_STATUS_OK) {
1687 				fs_got_inconsistent("LIZ_MATOCL_FUSE_MKDIR", message.size(),
1688 						"version 0 and LIZARDFS_STATUS_OK");
1689 				return LIZARDFS_ERROR_IO;
1690 			}
1691 			return status;
1692 		} else if (packetVersion == matocl::fuseMkdir::kResponsePacketVersion) {
1693 			matocl::fuseMkdir::deserialize(message, messageId, inode, attr);
1694 			return LIZARDFS_STATUS_OK;
1695 		} else {
1696 			fs_got_inconsistent("LIZ_MATOCL_FUSE_MKDIR", message.size(),
1697 					"unknown version " + std::to_string(packetVersion));
1698 			return LIZARDFS_ERROR_IO;
1699 		}
1700 		return LIZARDFS_ERROR_ENOTSUP;
1701 	} catch (Exception& ex) {
1702 		fs_got_inconsistent("LIZ_MATOCL_FUSE_MKDIR", message.size(), ex.what());
1703 		return LIZARDFS_ERROR_IO;
1704 	}
1705 }
1706 
fs_unlink(uint32_t parent,uint8_t nleng,const uint8_t * name,uint32_t uid,uint32_t gid)1707 uint8_t fs_unlink(uint32_t parent,uint8_t nleng,const uint8_t *name,uint32_t uid,uint32_t gid) {
1708 	uint8_t *wptr;
1709 	const uint8_t *rptr;
1710 	uint32_t i;
1711 	uint8_t ret;
1712 	threc *rec = fs_get_my_threc();
1713 	wptr = fs_createpacket(rec,CLTOMA_FUSE_UNLINK,13+nleng);
1714 	if (wptr==NULL) {
1715 		return LIZARDFS_ERROR_IO;
1716 	}
1717 	put32bit(&wptr,parent);
1718 	put8bit(&wptr,nleng);
1719 	memcpy(wptr,name,nleng);
1720 	wptr+=nleng;
1721 	put32bit(&wptr,uid);
1722 	put32bit(&wptr,gid);
1723 	rptr = fs_sendandreceive(rec,MATOCL_FUSE_UNLINK,&i);
1724 	if (rptr==NULL) {
1725 		ret = LIZARDFS_ERROR_IO;
1726 	} else if (i==1) {
1727 		ret = rptr[0];
1728 	} else {
1729 		setDisconnect(true);
1730 		ret = LIZARDFS_ERROR_IO;
1731 	}
1732 	return ret;
1733 }
1734 
fs_rmdir(uint32_t parent,uint8_t nleng,const uint8_t * name,uint32_t uid,uint32_t gid)1735 uint8_t fs_rmdir(uint32_t parent,uint8_t nleng,const uint8_t *name,uint32_t uid,uint32_t gid) {
1736 	uint8_t *wptr;
1737 	const uint8_t *rptr;
1738 	uint32_t i;
1739 	uint8_t ret;
1740 	threc *rec = fs_get_my_threc();
1741 	wptr = fs_createpacket(rec,CLTOMA_FUSE_RMDIR,13+nleng);
1742 	if (wptr==NULL) {
1743 		return LIZARDFS_ERROR_IO;
1744 	}
1745 	put32bit(&wptr,parent);
1746 	put8bit(&wptr,nleng);
1747 	memcpy(wptr,name,nleng);
1748 	wptr+=nleng;
1749 	put32bit(&wptr,uid);
1750 	put32bit(&wptr,gid);
1751 	rptr = fs_sendandreceive(rec,MATOCL_FUSE_RMDIR,&i);
1752 	if (rptr==NULL) {
1753 		ret = LIZARDFS_ERROR_IO;
1754 	} else if (i==1) {
1755 		ret = rptr[0];
1756 	} else {
1757 		setDisconnect(true);
1758 		ret = LIZARDFS_ERROR_IO;
1759 	}
1760 	return ret;
1761 }
1762 
fs_rename(uint32_t parent_src,uint8_t nleng_src,const uint8_t * name_src,uint32_t parent_dst,uint8_t nleng_dst,const uint8_t * name_dst,uint32_t uid,uint32_t gid,uint32_t * inode,Attributes & attr)1763 uint8_t fs_rename(uint32_t parent_src, uint8_t nleng_src, const uint8_t *name_src, uint32_t parent_dst, uint8_t nleng_dst, const uint8_t *name_dst, uint32_t uid, uint32_t gid, uint32_t *inode, Attributes &attr) {
1764 	uint8_t *wptr;
1765 	const uint8_t *rptr;
1766 	uint32_t i;
1767 	uint32_t t32;
1768 	uint8_t ret;
1769 	threc *rec = fs_get_my_threc();
1770 	wptr = fs_createpacket(rec,CLTOMA_FUSE_RENAME,18+nleng_src+nleng_dst);
1771 	if (wptr==NULL) {
1772 		return LIZARDFS_ERROR_IO;
1773 	}
1774 	put32bit(&wptr,parent_src);
1775 	put8bit(&wptr,nleng_src);
1776 	memcpy(wptr,name_src,nleng_src);
1777 	wptr+=nleng_src;
1778 	put32bit(&wptr,parent_dst);
1779 	put8bit(&wptr,nleng_dst);
1780 	memcpy(wptr,name_dst,nleng_dst);
1781 	wptr+=nleng_dst;
1782 	put32bit(&wptr,uid);
1783 	put32bit(&wptr,gid);
1784 	rptr = fs_sendandreceive(rec,MATOCL_FUSE_RENAME,&i);
1785 	if (rptr==NULL) {
1786 		ret = LIZARDFS_ERROR_IO;
1787 	} else if (i==1) {
1788 		ret = rptr[0];
1789 		*inode = 0;
1790 		attr.fill(0);
1791 	} else if (i != (attr.size() + 4)) {
1792 		setDisconnect(true);
1793 		ret = LIZARDFS_ERROR_IO;
1794 	} else {
1795 		t32 = get32bit(&rptr);
1796 		*inode = t32;
1797 		memcpy(attr.data(), rptr, attr.size());
1798 		ret = LIZARDFS_STATUS_OK;
1799 	}
1800 	return ret;
1801 }
1802 
fs_link(uint32_t inode_src,uint32_t parent_dst,uint8_t nleng_dst,const uint8_t * name_dst,uint32_t uid,uint32_t gid,uint32_t * inode,Attributes & attr)1803 uint8_t fs_link(uint32_t inode_src, uint32_t parent_dst, uint8_t nleng_dst, const uint8_t *name_dst, uint32_t uid, uint32_t gid, uint32_t *inode, Attributes &attr) {
1804 	uint8_t *wptr;
1805 	const uint8_t *rptr;
1806 	uint32_t i;
1807 	uint32_t t32;
1808 	uint8_t ret;
1809 	threc *rec = fs_get_my_threc();
1810 	wptr = fs_createpacket(rec,CLTOMA_FUSE_LINK,17+nleng_dst);
1811 	if (wptr==NULL) {
1812 		return LIZARDFS_ERROR_IO;
1813 	}
1814 	put32bit(&wptr,inode_src);
1815 	put32bit(&wptr,parent_dst);
1816 	put8bit(&wptr,nleng_dst);
1817 	memcpy(wptr,name_dst,nleng_dst);
1818 	wptr+=nleng_dst;
1819 	put32bit(&wptr,uid);
1820 	put32bit(&wptr,gid);
1821 	rptr = fs_sendandreceive(rec,MATOCL_FUSE_LINK,&i);
1822 	if (rptr==NULL) {
1823 		ret = LIZARDFS_ERROR_IO;
1824 	} else if (i==1) {
1825 		ret = rptr[0];
1826 	} else if (i != (attr.size() + 4)) {
1827 		setDisconnect(true);
1828 		ret = LIZARDFS_ERROR_IO;
1829 	} else {
1830 		t32 = get32bit(&rptr);
1831 		*inode = t32;
1832 		memcpy(attr.data(), rptr, attr.size());
1833 		ret = LIZARDFS_STATUS_OK;
1834 	}
1835 	return ret;
1836 }
1837 
fs_getdir(uint32_t inode,uint32_t uid,uint32_t gid,const uint8_t ** dbuff,uint32_t * dbuffsize)1838 uint8_t fs_getdir(uint32_t inode,uint32_t uid,uint32_t gid,const uint8_t **dbuff,uint32_t *dbuffsize) {
1839 	uint8_t *wptr;
1840 	const uint8_t *rptr;
1841 	uint32_t i;
1842 	uint8_t ret;
1843 	threc *rec = fs_get_my_threc();
1844 	wptr = fs_createpacket(rec,CLTOMA_FUSE_GETDIR,12);
1845 	if (wptr==NULL) {
1846 		return LIZARDFS_ERROR_IO;
1847 	}
1848 	put32bit(&wptr,inode);
1849 	put32bit(&wptr,uid);
1850 	put32bit(&wptr,gid);
1851 	rptr = fs_sendandreceive(rec,MATOCL_FUSE_GETDIR,&i);
1852 	if (rptr==NULL) {
1853 		ret = LIZARDFS_ERROR_IO;
1854 	} else if (i==1) {
1855 		ret = rptr[0];
1856 	} else {
1857 		*dbuff = rptr;
1858 		*dbuffsize = i;
1859 		ret = LIZARDFS_STATUS_OK;
1860 	}
1861 	return ret;
1862 }
1863 
fs_getdir_plus(uint32_t inode,uint32_t uid,uint32_t gid,uint8_t addtocache,const uint8_t ** dbuff,uint32_t * dbuffsize)1864 uint8_t fs_getdir_plus(uint32_t inode,uint32_t uid,uint32_t gid,uint8_t addtocache,const uint8_t **dbuff,uint32_t *dbuffsize) {
1865 	uint8_t *wptr;
1866 	const uint8_t *rptr;
1867 	uint32_t i;
1868 	uint8_t ret;
1869 	uint8_t flags;
1870 	threc *rec = fs_get_my_threc();
1871 	wptr = fs_createpacket(rec,CLTOMA_FUSE_GETDIR,13);
1872 	if (wptr==NULL) {
1873 		return LIZARDFS_ERROR_IO;
1874 	}
1875 	put32bit(&wptr,inode);
1876 	put32bit(&wptr,uid);
1877 	put32bit(&wptr,gid);
1878 	flags = GETDIR_FLAG_WITHATTR;
1879 	if (addtocache) {
1880 		flags |= GETDIR_FLAG_ADDTOCACHE;
1881 	}
1882 	put8bit(&wptr,flags);
1883 	rptr = fs_sendandreceive(rec,MATOCL_FUSE_GETDIR,&i);
1884 	if (rptr==NULL) {
1885 		ret = LIZARDFS_ERROR_IO;
1886 	} else if (i==1) {
1887 		ret = rptr[0];
1888 	} else {
1889 		*dbuff = rptr;
1890 		*dbuffsize = i;
1891 		ret = LIZARDFS_STATUS_OK;
1892 	}
1893 	return ret;
1894 }
1895 
fs_getdir(uint32_t inode,uint32_t uid,uint32_t gid,uint64_t first_entry,uint64_t max_entries,std::vector<DirectoryEntry> & dir_entries)1896 uint8_t fs_getdir(uint32_t inode, uint32_t uid, uint32_t gid, uint64_t first_entry,
1897 		uint64_t max_entries, std::vector<DirectoryEntry> &dir_entries) {
1898 	threc *rec = fs_get_my_threc();
1899 	auto message =
1900 	        cltoma::fuseGetDir::build(rec->packetId, inode, uid, gid, first_entry, max_entries);
1901 	if (!fs_lizcreatepacket(rec, message)) {
1902 		return LIZARDFS_ERROR_IO;
1903 	}
1904 	if (!fs_lizsendandreceive(rec, LIZ_MATOCL_FUSE_GETDIR, message)) {
1905 		return LIZARDFS_ERROR_IO;
1906 	}
1907 	try {
1908 		uint32_t message_id;
1909 		PacketVersion packet_version;
1910 		deserializePacketVersionNoHeader(message, packet_version);
1911 		if (packet_version == matocl::fuseGetDir::kStatus) {
1912 			uint8_t status;
1913 			matocl::fuseGetDir::deserialize(message, message_id, status);
1914 			if (status == LIZARDFS_STATUS_OK) {
1915 				fs_got_inconsistent("LIZ_MATOCL_FUSE_GETDIR", message.size(),
1916 				                    "version 0 and LIZARDFS_STATUS_OK");
1917 				return LIZARDFS_ERROR_IO;
1918 			}
1919 			return status;
1920 		} else if (packet_version == matocl::fuseGetDir::kResponse) {
1921 			matocl::fuseGetDir::deserialize(message, message_id, first_entry,
1922 			                                dir_entries);
1923 			return LIZARDFS_STATUS_OK;
1924 		} else {
1925 			fs_got_inconsistent("LIZ_MATOCL_FUSE_GETDIR", message.size(),
1926 			                    "unknown version " + std::to_string(packet_version));
1927 			return LIZARDFS_ERROR_IO;
1928 		}
1929 	} catch (Exception &ex) {
1930 		fs_got_inconsistent("LIZ_MATOCL_FUSE_GETDIR", message.size(), ex.what());
1931 		return LIZARDFS_ERROR_IO;
1932 	}
1933 }
1934 
1935 // FUSE - I/O
1936 
fs_opencheck(uint32_t inode,uint32_t uid,uint32_t gid,uint8_t flags,Attributes & attr)1937 uint8_t fs_opencheck(uint32_t inode, uint32_t uid, uint32_t gid, uint8_t flags, Attributes &attr) {
1938 	uint8_t *wptr;
1939 	const uint8_t *rptr;
1940 	uint32_t i;
1941 	uint8_t ret;
1942 	threc *rec = fs_get_my_threc();
1943 	wptr = fs_createpacket(rec,CLTOMA_FUSE_OPEN,13);
1944 	if (wptr==NULL) {
1945 		return LIZARDFS_ERROR_IO;
1946 	}
1947 	put32bit(&wptr,inode);
1948 	put32bit(&wptr,uid);
1949 	put32bit(&wptr,gid);
1950 	put8bit(&wptr,flags);
1951 	fs_inc_acnt(inode);
1952 	rptr = fs_sendandreceive(rec,MATOCL_FUSE_OPEN,&i);
1953 	if (rptr==NULL) {
1954 		ret = LIZARDFS_ERROR_IO;
1955 	} else if (i==1) {
1956 		attr.fill(0);
1957 		ret = rptr[0];
1958 	} else if (i == attr.size()) {
1959 		memcpy(attr.data(), rptr, attr.size());
1960 		ret = LIZARDFS_STATUS_OK;
1961 	} else {
1962 		setDisconnect(true);
1963 		ret = LIZARDFS_ERROR_IO;
1964 	}
1965 	if (ret) {      // release on error
1966 		fs_dec_acnt(inode);
1967 	}
1968 	return ret;
1969 }
1970 
fs_update_credentials(uint32_t key,const GroupCache::Groups & gids)1971 uint8_t fs_update_credentials(uint32_t key, const GroupCache::Groups &gids) {
1972 	threc* rec = fs_get_my_threc();
1973 	std::vector<uint8_t> message;
1974 	cltoma::updateCredentials::serialize(message, rec->packetId, key, gids);
1975 	if (!fs_lizcreatepacket(rec, message)) {
1976 		return LIZARDFS_ERROR_IO;
1977 	}
1978 	if (!fs_lizsendandreceive(rec, LIZ_MATOCL_UPDATE_CREDENTIALS, message)) {
1979 		return LIZARDFS_ERROR_IO;
1980 	}
1981 	try {
1982 		uint8_t status;
1983 		uint32_t msgid;
1984 		matocl::updateCredentials::deserialize(message, msgid, status);
1985 		return status;
1986 	} catch (Exception& ex) {
1987 		setDisconnect(true);
1988 		return LIZARDFS_ERROR_IO;
1989 	}
1990 }
1991 
fs_release(uint32_t inode)1992 void fs_release(uint32_t inode) {
1993 	fs_dec_acnt(inode);
1994 }
1995 
fs_readchunk(uint32_t inode,uint32_t indx,uint64_t * length,uint64_t * chunkid,uint32_t * version,const uint8_t ** csdata,uint32_t * csdatasize)1996 uint8_t fs_readchunk(uint32_t inode,uint32_t indx,uint64_t *length,uint64_t *chunkid,uint32_t *version,const uint8_t **csdata,uint32_t *csdatasize) {
1997 	uint8_t *wptr;
1998 	const uint8_t *rptr;
1999 	uint32_t i;
2000 	uint8_t ret;
2001 	uint64_t t64;
2002 	uint32_t t32;
2003 	threc *rec = fs_get_my_threc();
2004 	*csdata=NULL;
2005 	*csdatasize=0;
2006 	wptr = fs_createpacket(rec,CLTOMA_FUSE_READ_CHUNK,8);
2007 	if (wptr==NULL) {
2008 		return LIZARDFS_ERROR_IO;
2009 	}
2010 
2011 	put32bit(&wptr,inode);
2012 	put32bit(&wptr,indx);
2013 	rptr = fs_sendandreceive(rec,MATOCL_FUSE_READ_CHUNK,&i);
2014 	if (rptr==NULL) {
2015 		ret = LIZARDFS_ERROR_IO;
2016 	} else if (i==1) {
2017 		ret = rptr[0];
2018 	} else if (i<20 || ((i-20)%6)!=0) {
2019 		setDisconnect(true);
2020 		ret = LIZARDFS_ERROR_IO;
2021 	} else {
2022 		t64 = get64bit(&rptr);
2023 		*length = t64;
2024 		t64 = get64bit(&rptr);
2025 		*chunkid = t64;
2026 		t32 = get32bit(&rptr);
2027 		*version = t32;
2028 		if (i>20) {
2029 			*csdata = rptr;
2030 			*csdatasize = i-20;
2031 		}
2032 		ret = LIZARDFS_STATUS_OK;
2033 	}
2034 	return ret;
2035 }
2036 
fs_lizreadchunk(std::vector<ChunkTypeWithAddress> & chunkservers,uint64_t & chunkId,uint32_t & chunkVersion,uint64_t & fileLength,uint32_t inode,uint32_t chunkIndex)2037 uint8_t fs_lizreadchunk(std::vector<ChunkTypeWithAddress> &chunkservers, uint64_t &chunkId,
2038 		uint32_t &chunkVersion, uint64_t &fileLength, uint32_t inode, uint32_t chunkIndex) {
2039 	threc *rec = fs_get_my_threc();
2040 
2041 	std::vector<uint8_t> message;
2042 	cltoma::fuseReadChunk::serialize(message, rec->packetId, inode, chunkIndex);
2043 	if (!fs_lizcreatepacket(rec, message)) {
2044 		return LIZARDFS_ERROR_IO;
2045 	}
2046 
2047 	try {
2048 		if (!fs_lizsendandreceive(rec, LIZ_MATOCL_FUSE_READ_CHUNK, message)) {
2049 			return LIZARDFS_ERROR_IO;
2050 		}
2051 		PacketVersion packetVersion;
2052 		deserializePacketVersionNoHeader(message, packetVersion);
2053 
2054 		if (packetVersion == matocl::fuseReadChunk::kStatusPacketVersion) {
2055 			uint8_t status;
2056 			matocl::fuseReadChunk::deserialize(message, status);
2057 			return status;
2058 		} else if (packetVersion == matocl::fuseReadChunk::kECChunks_ResponsePacketVersion) {
2059 			matocl::fuseReadChunk::deserialize(message, fileLength,
2060 					chunkId, chunkVersion, chunkservers);
2061 		} else if (packetVersion == matocl::fuseReadChunk::kResponsePacketVersion) {
2062 			std::vector<legacy::ChunkTypeWithAddress> legacy_chunkservers;
2063 			matocl::fuseReadChunk::deserialize(message, fileLength,
2064 					chunkId, chunkVersion, legacy_chunkservers);
2065 			chunkservers.clear();
2066 			for (const auto &part : legacy_chunkservers) {
2067 				chunkservers.push_back(ChunkTypeWithAddress(part.address, ChunkPartType(part.chunkType), kFirstXorVersion));
2068 			}
2069 		} else {
2070 			lzfs_pretty_syslog(LOG_NOTICE, "LIZ_MATOCL_FUSE_READ_CHUNK - wrong packet version");
2071 			setDisconnect(true);
2072 			return LIZARDFS_ERROR_IO;
2073 		}
2074 	} catch (IncorrectDeserializationException&) {
2075 		setDisconnect(true);
2076 		return LIZARDFS_ERROR_IO;
2077 	}
2078 	return LIZARDFS_STATUS_OK;
2079 }
2080 
fs_writechunk(uint32_t inode,uint32_t indx,uint64_t * length,uint64_t * chunkid,uint32_t * version,const uint8_t ** csdata,uint32_t * csdatasize)2081 uint8_t fs_writechunk(uint32_t inode,uint32_t indx,uint64_t *length,uint64_t *chunkid,uint32_t *version,const uint8_t **csdata,uint32_t *csdatasize) {
2082 	uint8_t *wptr;
2083 	const uint8_t *rptr;
2084 	uint32_t i;
2085 	uint8_t ret;
2086 	uint64_t t64;
2087 	uint32_t t32;
2088 	threc *rec = fs_get_my_threc();
2089 	*csdata=NULL;
2090 	*csdatasize=0;
2091 	wptr = fs_createpacket(rec,CLTOMA_FUSE_WRITE_CHUNK,8);
2092 	if (wptr==NULL) {
2093 		return LIZARDFS_ERROR_IO;
2094 	}
2095 	put32bit(&wptr,inode);
2096 	put32bit(&wptr,indx);
2097 	rptr = fs_sendandreceive(rec,MATOCL_FUSE_WRITE_CHUNK,&i);
2098 	if (rptr==NULL) {
2099 		ret = LIZARDFS_ERROR_IO;
2100 	} else if (i==1) {
2101 		ret = rptr[0];
2102 	} else if (i<20 || ((i-20)%6)!=0) {
2103 		setDisconnect(true);
2104 		ret = LIZARDFS_ERROR_IO;
2105 	} else {
2106 		t64 = get64bit(&rptr);
2107 		*length = t64;
2108 		t64 = get64bit(&rptr);
2109 		*chunkid = t64;
2110 		t32 = get32bit(&rptr);
2111 		*version = t32;
2112 		if (i>20) {
2113 			*csdata = rptr;
2114 			*csdatasize = i-20;
2115 		}
2116 		ret = LIZARDFS_STATUS_OK;
2117 	}
2118 	return ret;
2119 }
2120 
fs_lizwritechunk(uint32_t inode,uint32_t chunkIndex,uint32_t & lockId,uint64_t & fileLength,uint64_t & chunkId,uint32_t & chunkVersion,std::vector<ChunkTypeWithAddress> & chunkservers)2121 uint8_t fs_lizwritechunk(uint32_t inode, uint32_t chunkIndex, uint32_t &lockId,
2122 		uint64_t &fileLength, uint64_t &chunkId, uint32_t &chunkVersion,
2123 		std::vector<ChunkTypeWithAddress> &chunkservers) {
2124 	threc *rec = fs_get_my_threc();
2125 
2126 	std::vector<uint8_t> message;
2127 	cltoma::fuseWriteChunk::serialize(message, rec->packetId, inode, chunkIndex, lockId);
2128 	if (!fs_lizcreatepacket(rec, message)) {
2129 		return LIZARDFS_ERROR_IO;
2130 	}
2131 
2132 	try {
2133 		if (!fs_lizsendandreceive(rec, LIZ_MATOCL_FUSE_WRITE_CHUNK, message)) {
2134 			return LIZARDFS_ERROR_IO;
2135 		}
2136 
2137 		PacketVersion packetVersion;
2138 		deserializePacketVersionNoHeader(message, packetVersion);
2139 		if (packetVersion == matocl::fuseWriteChunk::kStatusPacketVersion) {
2140 			uint8_t status;
2141 			matocl::fuseWriteChunk::deserialize(message, status);
2142 			if (status == LIZARDFS_STATUS_OK) {
2143 				lzfs_pretty_syslog (LOG_NOTICE,
2144 						"Received LIZARDFS_STATUS_OK in message LIZ_MATOCL_FUSE_WRITE_CHUNK with version"
2145 						" %d" PRIu32, matocl::fuseWriteChunk::kStatusPacketVersion);
2146 				setDisconnect(true);
2147 				return LIZARDFS_ERROR_IO;
2148 			}
2149 			return status;
2150 		} else if (packetVersion == matocl::fuseWriteChunk::kECChunks_ResponsePacketVersion) {
2151 			matocl::fuseWriteChunk::deserialize(message,
2152 					fileLength, chunkId, chunkVersion, lockId, chunkservers);
2153 		} else if (packetVersion == matocl::fuseWriteChunk::kResponsePacketVersion) {
2154 			std::vector<legacy::ChunkTypeWithAddress> legacy_chunkservers;
2155 			matocl::fuseWriteChunk::deserialize(message,
2156 					fileLength, chunkId, chunkVersion, lockId, legacy_chunkservers);
2157 			chunkservers.clear();
2158 			for (const auto &part : legacy_chunkservers) {
2159 				chunkservers.push_back(ChunkTypeWithAddress(part.address, ChunkPartType(part.chunkType), kFirstXorVersion));
2160 			}
2161 		} else {
2162 			lzfs_pretty_syslog(LOG_NOTICE, "LIZ_MATOCL_FUSE_WRITE_CHUNK - wrong packet version");
2163 			setDisconnect(true);
2164 			return LIZARDFS_ERROR_IO;
2165 		}
2166 	} catch (IncorrectDeserializationException& ex) {
2167 		lzfs_pretty_syslog(LOG_NOTICE,
2168 				"got inconsistent LIZ_MATOCL_FUSE_WRITE_CHUNK message from master "
2169 				"(length:%" PRIu64"), %s", message.size(), ex.what());
2170 		setDisconnect(true);
2171 		return LIZARDFS_ERROR_IO;
2172 	}
2173 
2174 	return LIZARDFS_STATUS_OK;
2175 }
2176 
fs_lizwriteend(uint64_t chunkId,uint32_t lockId,uint32_t inode,uint64_t length)2177 uint8_t fs_lizwriteend(uint64_t chunkId, uint32_t lockId, uint32_t inode, uint64_t length) {
2178 	threc* rec = fs_get_my_threc();
2179 	std::vector<uint8_t> message;
2180 	cltoma::fuseWriteChunkEnd::serialize(message, rec->packetId, chunkId, lockId, inode, length);
2181 	if (!fs_lizcreatepacket(rec, message)) {
2182 		return LIZARDFS_ERROR_IO;
2183 	}
2184 	if (!fs_lizsendandreceive(rec, LIZ_MATOCL_FUSE_WRITE_CHUNK_END, message)) {
2185 		return LIZARDFS_ERROR_IO;
2186 	}
2187 	try {
2188 		uint8_t status;
2189 		matocl::fuseWriteChunkEnd::deserialize(message, status);
2190 		return status;
2191 	} catch (Exception& ex) {
2192 		lzfs_pretty_syslog(LOG_NOTICE,
2193 				"got inconsistent LIZ_MATOCL_FUSE_WRITE_CHUNK_END message from master "
2194 				"(length:%" PRIu64"), %s", message.size(), ex.what());
2195 		setDisconnect(true);
2196 		return LIZARDFS_ERROR_IO;
2197 	}
2198 }
2199 
fs_writeend(uint64_t chunkid,uint32_t inode,uint64_t length)2200 uint8_t fs_writeend(uint64_t chunkid, uint32_t inode, uint64_t length) {
2201 	uint8_t *wptr;
2202 	const uint8_t *rptr;
2203 	uint32_t i;
2204 	uint8_t ret;
2205 	threc *rec = fs_get_my_threc();
2206 	wptr = fs_createpacket(rec,CLTOMA_FUSE_WRITE_CHUNK_END,20);
2207 	if (wptr==NULL) {
2208 		return LIZARDFS_ERROR_IO;
2209 	}
2210 	put64bit(&wptr,chunkid);
2211 	put32bit(&wptr,inode);
2212 	put64bit(&wptr,length);
2213 	rptr = fs_sendandreceive(rec,MATOCL_FUSE_WRITE_CHUNK_END,&i);
2214 	if (rptr==NULL) {
2215 		ret = LIZARDFS_ERROR_IO;
2216 	} else if (i==1) {
2217 		ret = rptr[0];
2218 	} else {
2219 		setDisconnect(true);
2220 		ret = LIZARDFS_ERROR_IO;
2221 	}
2222 	return ret;
2223 }
2224 
2225 
2226 // FUSE - META
2227 
2228 
fs_getreserved(const uint8_t ** dbuff,uint32_t * dbuffsize)2229 uint8_t fs_getreserved(const uint8_t **dbuff,uint32_t *dbuffsize) {
2230 	uint8_t *wptr;
2231 	const uint8_t *rptr;
2232 	uint32_t i;
2233 	uint8_t ret;
2234 	threc *rec = fs_get_my_threc();
2235 	wptr = fs_createpacket(rec,CLTOMA_FUSE_GETRESERVED,0);
2236 	if (wptr==NULL) {
2237 		return LIZARDFS_ERROR_IO;
2238 	}
2239 	rptr = fs_sendandreceive(rec,MATOCL_FUSE_GETRESERVED,&i);
2240 	if (rptr==NULL) {
2241 		ret = LIZARDFS_ERROR_IO;
2242 	} else if (i==1) {
2243 		ret = rptr[0];
2244 	} else {
2245 		*dbuff = rptr;
2246 		*dbuffsize = i;
2247 		ret = LIZARDFS_STATUS_OK;
2248 	}
2249 	return ret;
2250 }
2251 
fs_gettrash(const uint8_t ** dbuff,uint32_t * dbuffsize)2252 uint8_t fs_gettrash(const uint8_t **dbuff,uint32_t *dbuffsize) {
2253 	uint8_t *wptr;
2254 	const uint8_t *rptr;
2255 	uint32_t i;
2256 	uint8_t ret;
2257 	threc *rec = fs_get_my_threc();
2258 	wptr = fs_createpacket(rec,CLTOMA_FUSE_GETTRASH,0);
2259 	if (wptr==NULL) {
2260 		return LIZARDFS_ERROR_IO;
2261 	}
2262 	rptr = fs_sendandreceive(rec,MATOCL_FUSE_GETTRASH,&i);
2263 	if (rptr==NULL) {
2264 		ret = LIZARDFS_ERROR_IO;
2265 	} else if (i==1) {
2266 		ret = rptr[0];
2267 	} else {
2268 		*dbuff = rptr;
2269 		*dbuffsize = i;
2270 		ret = LIZARDFS_STATUS_OK;
2271 	}
2272 	return ret;
2273 }
2274 
fs_getreserved(LizardClient::NamedInodeOffset off,LizardClient::NamedInodeOffset max_entries,std::vector<NamedInodeEntry> & entries)2275 uint8_t fs_getreserved(LizardClient::NamedInodeOffset off, LizardClient::NamedInodeOffset max_entries,
2276 	               std::vector<NamedInodeEntry> &entries) {
2277 	threc *rec = fs_get_my_threc();
2278 	auto message = cltoma::fuseGetReserved::build(rec->packetId, off, max_entries);
2279 	if (!fs_lizcreatepacket(rec, message)) {
2280 		return LIZARDFS_ERROR_IO;
2281 	}
2282 	if (!fs_lizsendandreceive(rec, LIZ_MATOCL_FUSE_GETRESERVED, message)) {
2283 		return LIZARDFS_ERROR_IO;
2284 	}
2285 	try {
2286 		PacketVersion dummy_packet_version;
2287 		uint32_t dummy_message_id;
2288 		deserializePacketVersionNoHeader(message, dummy_packet_version);
2289 		matocl::fuseGetReserved::deserialize(message, dummy_message_id, entries);
2290 		return LIZARDFS_STATUS_OK;
2291 	} catch (Exception &ex) {
2292 		fs_got_inconsistent("LIZ_MATOCL_FUSE_GETRESERVED", message.size(), ex.what());
2293 		return LIZARDFS_ERROR_IO;
2294 	}
2295 }
2296 
fs_gettrash(LizardClient::NamedInodeOffset off,LizardClient::NamedInodeOffset max_entries,std::vector<NamedInodeEntry> & entries)2297 uint8_t fs_gettrash(LizardClient::NamedInodeOffset off, LizardClient::NamedInodeOffset max_entries,
2298 	            std::vector<NamedInodeEntry> &entries) {
2299 	threc *rec = fs_get_my_threc();
2300 	auto message = cltoma::fuseGetTrash::build(rec->packetId, off, max_entries);
2301 	if (!fs_lizcreatepacket(rec, message)) {
2302 		return LIZARDFS_ERROR_IO;
2303 	}
2304 	if (!fs_lizsendandreceive(rec, LIZ_MATOCL_FUSE_GETTRASH, message)) {
2305 		return LIZARDFS_ERROR_IO;
2306 	}
2307 	try {
2308 		PacketVersion dummy_packet_version;
2309 		uint32_t dummy_message_id;
2310 		deserializePacketVersionNoHeader(message, dummy_packet_version);
2311 		matocl::fuseGetTrash::deserialize(message, dummy_message_id, entries);
2312 		return LIZARDFS_STATUS_OK;
2313 	} catch (Exception &ex) {
2314 		fs_got_inconsistent("LIZ_MATOCL_FUSE_GETTRASH", message.size(), ex.what());
2315 		return LIZARDFS_ERROR_IO;
2316 	}
2317 }
2318 
fs_getdetachedattr(uint32_t inode,Attributes & attr)2319 uint8_t fs_getdetachedattr(uint32_t inode, Attributes &attr) {
2320 	uint8_t *wptr;
2321 	const uint8_t *rptr;
2322 	uint32_t i;
2323 	uint8_t ret;
2324 	threc *rec = fs_get_my_threc();
2325 	wptr = fs_createpacket(rec,CLTOMA_FUSE_GETDETACHEDATTR,4);
2326 	if (wptr==NULL) {
2327 		return LIZARDFS_ERROR_IO;
2328 	}
2329 	put32bit(&wptr,inode);
2330 	rptr = fs_sendandreceive(rec,MATOCL_FUSE_GETDETACHEDATTR,&i);
2331 	if (rptr==NULL) {
2332 		ret = LIZARDFS_ERROR_IO;
2333 	} else if (i==1) {
2334 		ret = rptr[0];
2335 	} else if (i != attr.size()) {
2336 		setDisconnect(true);
2337 		ret = LIZARDFS_ERROR_IO;
2338 	} else {
2339 		memcpy(attr.data(), rptr, attr.size());
2340 		ret = LIZARDFS_STATUS_OK;
2341 	}
2342 	return ret;
2343 }
2344 
fs_gettrashpath(uint32_t inode,const uint8_t ** path)2345 uint8_t fs_gettrashpath(uint32_t inode,const uint8_t **path) {
2346 	uint8_t *wptr;
2347 	const uint8_t *rptr;
2348 	uint32_t i;
2349 	uint32_t pleng;
2350 	uint8_t ret;
2351 	threc *rec = fs_get_my_threc();
2352 	wptr = fs_createpacket(rec,CLTOMA_FUSE_GETTRASHPATH,4);
2353 	if (wptr==NULL) {
2354 		return LIZARDFS_ERROR_IO;
2355 	}
2356 	put32bit(&wptr,inode);
2357 	rptr = fs_sendandreceive(rec,MATOCL_FUSE_GETTRASHPATH,&i);
2358 	if (rptr==NULL) {
2359 		ret = LIZARDFS_ERROR_IO;
2360 	} else if (i==1) {
2361 		ret = rptr[0];
2362 	} else if (i<4) {
2363 		setDisconnect(true);
2364 		ret = LIZARDFS_ERROR_IO;
2365 	} else {
2366 		pleng = get32bit(&rptr);
2367 		if (i!=4+pleng || pleng==0 || rptr[pleng-1]!=0) {
2368 			setDisconnect(true);
2369 			ret = LIZARDFS_ERROR_IO;
2370 		} else {
2371 			*path = rptr;
2372 			ret = LIZARDFS_STATUS_OK;
2373 		}
2374 	}
2375 	return ret;
2376 }
2377 
fs_settrashpath(uint32_t inode,const uint8_t * path)2378 uint8_t fs_settrashpath(uint32_t inode,const uint8_t *path) {
2379 	uint8_t *wptr;
2380 	const uint8_t *rptr;
2381 	uint32_t i;
2382 	uint32_t t32;
2383 	uint8_t ret;
2384 	threc *rec = fs_get_my_threc();
2385 	t32 = strlen((const char *)path)+1;
2386 	wptr = fs_createpacket(rec,CLTOMA_FUSE_SETTRASHPATH,t32+8);
2387 	if (wptr==NULL) {
2388 		return LIZARDFS_ERROR_IO;
2389 	}
2390 	put32bit(&wptr,inode);
2391 	put32bit(&wptr,t32);
2392 	memcpy(wptr,path,t32);
2393 	rptr = fs_sendandreceive(rec,MATOCL_FUSE_SETTRASHPATH,&i);
2394 	if (rptr==NULL) {
2395 		ret = LIZARDFS_ERROR_IO;
2396 	} else if (i==1) {
2397 		ret = rptr[0];
2398 	} else {
2399 		setDisconnect(true);
2400 		ret = LIZARDFS_ERROR_IO;
2401 	}
2402 	return ret;
2403 }
2404 
fs_undel(uint32_t inode)2405 uint8_t fs_undel(uint32_t inode) {
2406 	uint8_t *wptr;
2407 	const uint8_t *rptr;
2408 	uint32_t i;
2409 	uint8_t ret;
2410 	threc *rec = fs_get_my_threc();
2411 	wptr = fs_createpacket(rec,CLTOMA_FUSE_UNDEL,4);
2412 	if (wptr==NULL) {
2413 		return LIZARDFS_ERROR_IO;
2414 	}
2415 	put32bit(&wptr,inode);
2416 	rptr = fs_sendandreceive(rec,MATOCL_FUSE_UNDEL,&i);
2417 	if (rptr==NULL) {
2418 		ret = LIZARDFS_ERROR_IO;
2419 	} else if (i==1) {
2420 		ret = rptr[0];
2421 	} else {
2422 		setDisconnect(true);
2423 		ret = LIZARDFS_ERROR_IO;
2424 	}
2425 	return ret;
2426 }
2427 
fs_purge(uint32_t inode)2428 uint8_t fs_purge(uint32_t inode) {
2429 	uint8_t *wptr;
2430 	const uint8_t *rptr;
2431 	uint32_t i;
2432 	uint8_t ret;
2433 	threc *rec = fs_get_my_threc();
2434 	wptr = fs_createpacket(rec,CLTOMA_FUSE_PURGE,4);
2435 	if (wptr==NULL) {
2436 		return LIZARDFS_ERROR_IO;
2437 	}
2438 	put32bit(&wptr,inode);
2439 	rptr = fs_sendandreceive(rec,MATOCL_FUSE_PURGE,&i);
2440 	if (rptr==NULL) {
2441 		ret = LIZARDFS_ERROR_IO;
2442 	} else if (i==1) {
2443 		ret = rptr[0];
2444 	} else {
2445 		setDisconnect(true);
2446 		ret = LIZARDFS_ERROR_IO;
2447 	}
2448 	return ret;
2449 }
2450 
fs_getxattr(uint32_t inode,uint8_t opened,uint32_t uid,uint32_t gid,uint8_t nleng,const uint8_t * name,uint8_t mode,const uint8_t ** vbuff,uint32_t * vleng)2451 uint8_t fs_getxattr(uint32_t inode,uint8_t opened,uint32_t uid,uint32_t gid,uint8_t nleng,const uint8_t *name,uint8_t mode,const uint8_t **vbuff,uint32_t *vleng) {
2452 	uint8_t *wptr;
2453 	const uint8_t *rptr;
2454 	uint32_t i;
2455 	uint8_t ret;
2456 	threc *rec = fs_get_my_threc();
2457 	if (masterversion < lizardfsVersion(1, 6, 29)) {
2458 		return LIZARDFS_ERROR_ENOTSUP;
2459 	}
2460 	wptr = fs_createpacket(rec,CLTOMA_FUSE_GETXATTR,15+nleng);
2461 	if (wptr==NULL) {
2462 		return LIZARDFS_ERROR_IO;
2463 	}
2464 	put32bit(&wptr,inode);
2465 	put8bit(&wptr,opened);
2466 	put32bit(&wptr,uid);
2467 	put32bit(&wptr,gid);
2468 	put8bit(&wptr,nleng);
2469 	memcpy(wptr,name,nleng);
2470 	wptr+=nleng;
2471 	put8bit(&wptr,mode);
2472 	rptr = fs_sendandreceive(rec,MATOCL_FUSE_GETXATTR,&i);
2473 	if (rptr==NULL) {
2474 		ret = LIZARDFS_ERROR_IO;
2475 	} else if (i==1) {
2476 		ret = rptr[0];
2477 	} else if (i<4) {
2478 		setDisconnect(true);
2479 		ret = LIZARDFS_ERROR_IO;
2480 	} else {
2481 		*vleng = get32bit(&rptr);
2482 		*vbuff = (mode==XATTR_GMODE_GET_DATA)?rptr:NULL;
2483 		if ((mode==XATTR_GMODE_GET_DATA && i!=(*vleng)+4) || (mode==XATTR_GMODE_LENGTH_ONLY && i!=4)) {
2484 			setDisconnect(true);
2485 			ret = LIZARDFS_ERROR_IO;
2486 		} else {
2487 			ret = LIZARDFS_STATUS_OK;
2488 		}
2489 	}
2490 	return ret;
2491 }
2492 
fs_listxattr(uint32_t inode,uint8_t opened,uint32_t uid,uint32_t gid,uint8_t mode,const uint8_t ** dbuff,uint32_t * dleng)2493 uint8_t fs_listxattr(uint32_t inode,uint8_t opened,uint32_t uid,uint32_t gid,uint8_t mode,const uint8_t **dbuff,uint32_t *dleng) {
2494 	uint8_t *wptr;
2495 	const uint8_t *rptr;
2496 	uint32_t i;
2497 	uint8_t ret;
2498 	threc *rec = fs_get_my_threc();
2499 	if (masterversion < lizardfsVersion(1, 6, 29)) {
2500 		return LIZARDFS_ERROR_ENOTSUP;
2501 	}
2502 	wptr = fs_createpacket(rec,CLTOMA_FUSE_GETXATTR,15);
2503 	if (wptr==NULL) {
2504 		return LIZARDFS_ERROR_IO;
2505 	}
2506 	put32bit(&wptr,inode);
2507 	put8bit(&wptr,opened);
2508 	put32bit(&wptr,uid);
2509 	put32bit(&wptr,gid);
2510 	put8bit(&wptr,0);
2511 	put8bit(&wptr,mode);
2512 	rptr = fs_sendandreceive(rec,MATOCL_FUSE_GETXATTR,&i);
2513 	if (rptr==NULL) {
2514 		ret = LIZARDFS_ERROR_IO;
2515 	} else if (i==1) {
2516 		ret = rptr[0];
2517 	} else if (i<4) {
2518 		setDisconnect(true);
2519 		ret = LIZARDFS_ERROR_IO;
2520 	} else {
2521 		*dleng = get32bit(&rptr);
2522 		*dbuff = (mode==XATTR_GMODE_GET_DATA)?rptr:NULL;
2523 		if ((mode==XATTR_GMODE_GET_DATA && i!=(*dleng)+4) || (mode==XATTR_GMODE_LENGTH_ONLY && i!=4)) {
2524 			setDisconnect(true);
2525 			ret = LIZARDFS_ERROR_IO;
2526 		} else {
2527 			ret = LIZARDFS_STATUS_OK;
2528 		}
2529 	}
2530 	return ret;
2531 }
2532 
fs_setxattr(uint32_t inode,uint8_t opened,uint32_t uid,uint32_t gid,uint8_t nleng,const uint8_t * name,uint32_t vleng,const uint8_t * value,uint8_t mode)2533 uint8_t fs_setxattr(uint32_t inode,uint8_t opened,uint32_t uid,uint32_t gid,uint8_t nleng,const uint8_t *name,uint32_t vleng,const uint8_t *value,uint8_t mode) {
2534 	uint8_t *wptr;
2535 	const uint8_t *rptr;
2536 	uint32_t i;
2537 	uint8_t ret;
2538 	threc *rec = fs_get_my_threc();
2539 	if (masterversion < lizardfsVersion(1, 6, 29)) {
2540 		return LIZARDFS_ERROR_ENOTSUP;
2541 	}
2542 	if (mode>=XATTR_SMODE_REMOVE) {
2543 		return LIZARDFS_ERROR_EINVAL;
2544 	}
2545 	wptr = fs_createpacket(rec,CLTOMA_FUSE_SETXATTR,19+nleng+vleng);
2546 	if (wptr==NULL) {
2547 		return LIZARDFS_ERROR_IO;
2548 	}
2549 	put32bit(&wptr,inode);
2550 	put8bit(&wptr,opened);
2551 	put32bit(&wptr,uid);
2552 	put32bit(&wptr,gid);
2553 	put8bit(&wptr,nleng);
2554 	memcpy(wptr,name,nleng);
2555 	wptr+=nleng;
2556 	put32bit(&wptr,vleng);
2557 	memcpy(wptr,value,vleng);
2558 	wptr+=vleng;
2559 	put8bit(&wptr,mode);
2560 	rptr = fs_sendandreceive(rec,MATOCL_FUSE_SETXATTR,&i);
2561 	if (rptr==NULL) {
2562 		ret = LIZARDFS_ERROR_IO;
2563 	} else if (i==1) {
2564 		ret = rptr[0];
2565 	} else {
2566 		setDisconnect(true);
2567 		ret = LIZARDFS_ERROR_IO;
2568 	}
2569 	return ret;
2570 }
2571 
fs_removexattr(uint32_t inode,uint8_t opened,uint32_t uid,uint32_t gid,uint8_t nleng,const uint8_t * name)2572 uint8_t fs_removexattr(uint32_t inode,uint8_t opened,uint32_t uid,uint32_t gid,uint8_t nleng,const uint8_t *name) {
2573 	uint8_t *wptr;
2574 	const uint8_t *rptr;
2575 	uint32_t i;
2576 	uint8_t ret;
2577 	threc *rec = fs_get_my_threc();
2578 	if (masterversion < lizardfsVersion(1, 6, 29)) {
2579 		return LIZARDFS_ERROR_ENOTSUP;
2580 	}
2581 	wptr = fs_createpacket(rec,CLTOMA_FUSE_SETXATTR,19+nleng);
2582 	if (wptr==NULL) {
2583 		return LIZARDFS_ERROR_IO;
2584 	}
2585 	put32bit(&wptr,inode);
2586 	put8bit(&wptr,opened);
2587 	put32bit(&wptr,uid);
2588 	put32bit(&wptr,gid);
2589 	put8bit(&wptr,nleng);
2590 	memcpy(wptr,name,nleng);
2591 	wptr+=nleng;
2592 	put32bit(&wptr,0);
2593 	put8bit(&wptr,XATTR_SMODE_REMOVE);
2594 	rptr = fs_sendandreceive(rec,MATOCL_FUSE_SETXATTR,&i);
2595 	if (rptr==NULL) {
2596 		ret = LIZARDFS_ERROR_IO;
2597 	} else if (i==1) {
2598 		ret = rptr[0];
2599 	} else {
2600 		setDisconnect(true);
2601 		ret = LIZARDFS_ERROR_IO;
2602 	}
2603 	return ret;
2604 }
2605 
fs_deletacl(uint32_t inode,uint32_t uid,uint32_t gid,AclType type)2606 uint8_t fs_deletacl(uint32_t inode, uint32_t uid, uint32_t gid, AclType type) {
2607 	threc* rec = fs_get_my_threc();
2608 	auto message = cltoma::fuseDeleteAcl::build(rec->packetId, inode, uid, gid, type);
2609 	if (!fs_lizcreatepacket(rec, message)) {
2610 		return LIZARDFS_ERROR_IO;
2611 	}
2612 	if (!fs_lizsendandreceive(rec, LIZ_MATOCL_FUSE_DELETE_ACL, message)) {
2613 		return LIZARDFS_ERROR_IO;
2614 	}
2615 	try {
2616 		uint8_t status;
2617 		uint32_t dummyMessageId;
2618 		matocl::fuseDeleteAcl::deserialize(message.data(), message.size(), dummyMessageId, status);
2619 		return status;
2620 	} catch (Exception& ex) {
2621 		fs_got_inconsistent("LIZ_MATOCL_DELETE_ACL", message.size(), ex.what());
2622 		return LIZARDFS_ERROR_IO;
2623 	}
2624 }
2625 
fs_getacl(uint32_t inode,uint32_t uid,uint32_t gid,RichACL & acl,uint32_t & owner_id)2626 uint8_t fs_getacl(uint32_t inode, uint32_t uid, uint32_t gid, RichACL& acl, uint32_t &owner_id) {
2627 	threc* rec = fs_get_my_threc();
2628 	auto message = cltoma::fuseGetAcl::build(rec->packetId, inode, uid, gid, AclType::kRichACL);
2629 	if (!fs_lizcreatepacket(rec, message)) {
2630 		return LIZARDFS_ERROR_IO;
2631 	}
2632 	if (!fs_lizsendandreceive(rec, LIZ_MATOCL_FUSE_GET_ACL, message)) {
2633 		return LIZARDFS_ERROR_IO;
2634 	}
2635 	try {
2636 		PacketVersion packetVersion;
2637 		deserializePacketVersionNoHeader(message, packetVersion);
2638 		if (packetVersion == matocl::fuseGetAcl::kStatusPacketVersion) {
2639 			uint8_t status;
2640 			uint32_t dummy_msg_id;
2641 			matocl::fuseGetAcl::deserialize(message.data(), message.size(), dummy_msg_id,
2642 					status);
2643 			if (status == LIZARDFS_STATUS_OK) {
2644 				fs_got_inconsistent("LIZ_MATOCL_GET_ACL", message.size(),
2645 						"version 0 and LIZARDFS_STATUS_OK");
2646 				return LIZARDFS_ERROR_IO;
2647 			}
2648 			return status;
2649 		} else if (packetVersion == matocl::fuseGetAcl::kRichACLResponsePacketVersion) {
2650 			uint32_t dummy_msg_id;
2651 			matocl::fuseGetAcl::deserialize(message.data(), message.size(), dummy_msg_id, owner_id, acl);
2652 			return LIZARDFS_STATUS_OK;
2653 		} else {
2654 			fs_got_inconsistent("LIZ_MATOCL_GET_ACL", message.size(),
2655 					"unknown version " + std::to_string(packetVersion));
2656 			return LIZARDFS_ERROR_IO;
2657 		}
2658 	} catch (Exception& ex) {
2659 		fs_got_inconsistent("LIZ_MATOCL_GET_ACL", message.size(), ex.what());
2660 		return LIZARDFS_ERROR_IO;
2661 	}
2662 }
2663 
fs_setacl(uint32_t inode,uint32_t uid,uint32_t gid,const RichACL & acl)2664 uint8_t fs_setacl(uint32_t inode, uint32_t uid, uint32_t gid, const RichACL& acl) {
2665 	threc* rec = fs_get_my_threc();
2666 	auto message = cltoma::fuseSetAcl::build(rec->packetId, inode, uid, gid, acl);
2667 	if (!fs_lizcreatepacket(rec, message)) {
2668 		return LIZARDFS_ERROR_IO;
2669 	}
2670 	if (!fs_lizsendandreceive(rec, LIZ_MATOCL_FUSE_SET_ACL, message)) {
2671 		return LIZARDFS_ERROR_IO;
2672 	}
2673 	try {
2674 		uint8_t status;
2675 		uint32_t dummy_msg_id;
2676 		matocl::fuseSetAcl::deserialize(message.data(), message.size(), dummy_msg_id, status);
2677 		return status;
2678 	} catch (Exception& ex) {
2679 		fs_got_inconsistent("LIZ_MATOCL_SET_ACL", message.size(), ex.what());
2680 		return LIZARDFS_ERROR_IO;
2681 	}
2682 }
2683 
fs_setacl(uint32_t inode,uint32_t uid,uint32_t gid,AclType type,const AccessControlList & acl)2684 uint8_t fs_setacl(uint32_t inode, uint32_t uid, uint32_t gid, AclType type, const AccessControlList& acl) {
2685 	threc* rec = fs_get_my_threc();
2686 	auto message = cltoma::fuseSetAcl::build(rec->packetId, inode, uid, gid, type, acl);
2687 	if (!fs_lizcreatepacket(rec, message)) {
2688 		return LIZARDFS_ERROR_IO;
2689 	}
2690 	if (!fs_lizsendandreceive(rec, LIZ_MATOCL_FUSE_SET_ACL, message)) {
2691 		return LIZARDFS_ERROR_IO;
2692 	}
2693 	try {
2694 		uint8_t status;
2695 		uint32_t dummy_msg_id;
2696 		matocl::fuseSetAcl::deserialize(message.data(), message.size(), dummy_msg_id, status);
2697 		return status;
2698 	} catch (Exception& ex) {
2699 		fs_got_inconsistent("LIZ_MATOCL_SET_ACL", message.size(), ex.what());
2700 		return LIZARDFS_ERROR_IO;
2701 	}
2702 }
2703 
msgIdPtr(const MessageBuffer & buffer)2704 static uint32_t* msgIdPtr(const MessageBuffer& buffer) {
2705 	PacketHeader header;
2706 	deserializePacketHeader(buffer, header);
2707 	uint32_t msgIdOffset = 0;
2708 	if (header.isOldPacketType()) {
2709 		msgIdOffset = serializedSize(PacketHeader());
2710 	} else if (header.isLizPacketType()) {
2711 		msgIdOffset = serializedSize(PacketHeader(), PacketVersion());
2712 	} else {
2713 		sassert(!"unrecognized packet header");
2714 	}
2715 	if (msgIdOffset + serializedSize(uint32_t()) > buffer.size()) {
2716 		return nullptr;
2717 	}
2718 	return (uint32_t*) (buffer.data() + msgIdOffset);
2719 }
2720 
fs_custom(MessageBuffer & buffer)2721 uint8_t fs_custom(MessageBuffer& buffer) {
2722 	threc *rec = fs_get_my_threc();
2723 	uint32_t *ptr = nullptr;
2724 	ptr = msgIdPtr(buffer);
2725 	if (!ptr) {
2726 		// packet too short
2727 		return LIZARDFS_ERROR_EINVAL;
2728 	}
2729 	const uint32_t origMsgIdBigEndian = *ptr;
2730 	*ptr = htonl(rec->packetId);
2731 	if (!fs_lizcreatepacket(rec, std::move(buffer))) {
2732 		return LIZARDFS_ERROR_IO;
2733 	}
2734 	if (!fs_lizsendandreceive_any(rec, buffer)) {
2735 		return LIZARDFS_ERROR_IO;
2736 	}
2737 	ptr = msgIdPtr(buffer);
2738 	if (!ptr) {
2739 		// reply too short
2740 		return LIZARDFS_ERROR_EINVAL;
2741 	}
2742 	*ptr = origMsgIdBigEndian;
2743 	return LIZARDFS_STATUS_OK;
2744 }
2745 
fs_raw_sendandreceive(MessageBuffer & buffer,PacketHeader::Type expectedType)2746 uint8_t fs_raw_sendandreceive(MessageBuffer& buffer, PacketHeader::Type expectedType) {
2747 	threc *rec = fs_get_my_threc();
2748 	uint32_t *ptr = nullptr;
2749 	ptr = msgIdPtr(buffer);
2750 	if (!ptr) {
2751 		// packet too short
2752 		return LIZARDFS_ERROR_EINVAL;
2753 	}
2754 	*ptr = htonl(rec->packetId);
2755 	if (!fs_lizcreatepacket(rec, std::move(buffer))) {
2756 		return LIZARDFS_ERROR_IO;
2757 	}
2758 	if (!fs_lizsendandreceive(rec, expectedType, buffer)) {
2759 		return LIZARDFS_ERROR_IO;
2760 	}
2761 	return LIZARDFS_STATUS_OK;
2762 }
2763 
fs_send_custom(MessageBuffer buffer)2764 uint8_t fs_send_custom(MessageBuffer buffer) {
2765 	threc *rec = fs_get_my_threc();
2766 	if (!fs_lizcreatepacket(rec, std::move(buffer))) {
2767 		return LIZARDFS_ERROR_IO;
2768 	}
2769 	if (!fs_threc_flush(rec)) {
2770 		return LIZARDFS_ERROR_IO;
2771 	}
2772 	return LIZARDFS_STATUS_OK;
2773 }
2774 
fs_register_packet_type_handler(PacketHeader::Type type,PacketHandler * handler)2775 bool fs_register_packet_type_handler(PacketHeader::Type type, PacketHandler *handler) {
2776 	std::unique_lock<std::mutex> lock(perTypePacketHandlersLock);
2777 	if (perTypePacketHandlers.count(type) > 0) {
2778 		return false;
2779 	}
2780 	perTypePacketHandlers[type] = handler;
2781 	return true;
2782 }
2783 
fs_unregister_packet_type_handler(PacketHeader::Type type,PacketHandler * handler)2784 bool fs_unregister_packet_type_handler(PacketHeader::Type type, PacketHandler *handler) {
2785 	std::unique_lock<std::mutex> lock(perTypePacketHandlersLock);
2786 	PerTypePacketHandlers::iterator it = perTypePacketHandlers.find(type);
2787 	if (it == perTypePacketHandlers.end()) {
2788 		return false;
2789 	}
2790 	if (it->second != handler) {
2791 		return false;
2792 	}
2793 	perTypePacketHandlers.erase(it);
2794 	return true;
2795 }
2796 
fs_flock_interrupt(const lzfs_locks::InterruptData & data)2797 void fs_flock_interrupt(const lzfs_locks::InterruptData &data) {
2798 	threc *rec = fs_get_my_threc();
2799 	auto message = cltoma::fuseFlock::build(rec->packetId, data);
2800 	// is there anything we can do if send fails?
2801 	fs_lizcreatepacket(rec, message);
2802 	fs_lizsend(rec);
2803 }
2804 
fs_setlk_interrupt(const lzfs_locks::InterruptData & data)2805 void fs_setlk_interrupt(const lzfs_locks::InterruptData &data) {
2806 	threc *rec = fs_get_my_threc();
2807 	auto message = cltoma::fuseSetlk::build(rec->packetId, data);
2808 	// is there anything we can do if send fails?
2809 	fs_lizcreatepacket(rec, message);
2810 	fs_lizsend(rec);
2811 }
2812 
fs_getlk(uint32_t inode,uint64_t owner,lzfs_locks::FlockWrapper & lock)2813 uint8_t fs_getlk(uint32_t inode, uint64_t owner, lzfs_locks::FlockWrapper &lock) {
2814 	threc *rec = fs_get_my_threc();
2815 
2816 	auto message = cltoma::fuseGetlk::build(rec->packetId, inode, owner, lock);
2817 
2818 	if (!fs_lizcreatepacket(rec, message)) {
2819 		return LIZARDFS_ERROR_IO;
2820 	}
2821 
2822 	if (!fs_lizsendandreceive(rec, LIZ_MATOCL_FUSE_GETLK, message)) {
2823 		return LIZARDFS_ERROR_IO;
2824 	}
2825 
2826 	try {
2827 		PacketVersion packet_version;
2828 		deserializePacketVersionNoHeader(message, packet_version);
2829 		if (packet_version == matocl::fuseGetlk::kStatusPacketVersion) {
2830 			uint8_t status;
2831 			uint32_t message_id;
2832 			matocl::fuseGetlk::deserialize(message, message_id, status);
2833 			return status;
2834 		} else if (packet_version == matocl::fuseGetlk::kResponsePacketVersion) {
2835 			uint32_t message_id;
2836 			matocl::fuseGetlk::deserialize(message, message_id, lock);
2837 			return LIZARDFS_STATUS_OK;
2838 		} else {
2839 			fs_got_inconsistent(
2840 				"LIZ_MATOCL_GETLK",
2841 				message.size(),
2842 				"unknown version " + std::to_string(packet_version));
2843 			return LIZARDFS_ERROR_IO;
2844 		}
2845 	} catch (Exception& ex) {
2846 		fs_got_inconsistent("LIZ_MATOCL_GETLK", message.size(), ex.what());
2847 		return LIZARDFS_ERROR_IO;
2848 	}
2849 }
2850 
fs_setlk_send(uint32_t inode,uint64_t owner,uint32_t reqid,const lzfs_locks::FlockWrapper & lock)2851 uint8_t fs_setlk_send(uint32_t inode, uint64_t owner, uint32_t reqid, const lzfs_locks::FlockWrapper &lock) {
2852 	threc *rec = fs_get_my_threc();
2853 
2854 	auto message = cltoma::fuseSetlk::build(rec->packetId, inode, owner, reqid, lock);
2855 
2856 	if (!fs_lizcreatepacket(rec, message)) {
2857 		return LIZARDFS_ERROR_IO;
2858 	}
2859 
2860 	if (!fs_lizsend(rec)) {
2861 		return LIZARDFS_ERROR_IO;
2862 	}
2863 
2864 	return LIZARDFS_STATUS_OK;
2865 }
2866 
fs_setlk_recv()2867 uint8_t fs_setlk_recv() {
2868 	MessageBuffer message;
2869 	threc* rec = fs_get_my_threc();
2870 
2871 	if (!fs_lizrecv(rec, LIZ_MATOCL_FUSE_SETLK, message)) {
2872 		return LIZARDFS_ERROR_IO;
2873 	}
2874 
2875 	try {
2876 		PacketVersion packetVersion;
2877 		deserializePacketVersionNoHeader(message, packetVersion);
2878 		if (packetVersion == 0) {
2879 			uint8_t status;
2880 			uint32_t dummyMessageId;
2881 			matocl::fuseSetlk::deserialize(message, dummyMessageId, status);
2882 			return status;
2883 		} else {
2884 			fs_got_inconsistent(
2885 				"LIZ_MATOCL_SETLK",
2886 				message.size(),
2887 				"unknown version " + std::to_string(packetVersion));
2888 			return LIZARDFS_ERROR_IO;
2889 		}
2890 	} catch (Exception& ex) {
2891 		fs_got_inconsistent("LIZ_MATOCL_SETLK", message.size(), ex.what());
2892 		return LIZARDFS_ERROR_IO;
2893 	}
2894 }
2895 
fs_flock_send(uint32_t inode,uint64_t owner,uint32_t reqid,uint16_t op)2896 uint8_t fs_flock_send(uint32_t inode, uint64_t owner, uint32_t reqid, uint16_t op) {
2897 	threc *rec = fs_get_my_threc();
2898 
2899 	auto message = cltoma::fuseFlock::build(rec->packetId, inode, owner, reqid, op);
2900 
2901 	if (!fs_lizcreatepacket(rec, message)) {
2902 		return LIZARDFS_ERROR_IO;
2903 	}
2904 
2905 	if (!fs_lizsend(rec)) {
2906 		return LIZARDFS_ERROR_IO;
2907 	}
2908 
2909 	return LIZARDFS_STATUS_OK;
2910 }
2911 
fs_flock_recv()2912 uint8_t fs_flock_recv() {
2913 	MessageBuffer message;
2914 	threc* rec = fs_get_my_threc();
2915 
2916 	if (!fs_lizrecv(rec, LIZ_MATOCL_FUSE_FLOCK, message)) {
2917 		return LIZARDFS_ERROR_IO;
2918 	}
2919 
2920 	try {
2921 		PacketVersion packetVersion;
2922 		deserializePacketVersionNoHeader(message, packetVersion);
2923 		if (packetVersion == 0) {
2924 			uint8_t status;
2925 			uint32_t dummyMessageId;
2926 			matocl::fuseFlock::deserialize(message, dummyMessageId, status);
2927 			return status;
2928 		} else {
2929 			fs_got_inconsistent(
2930 				"LIZ_MATOCL_FLOCK",
2931 				message.size(),
2932 				"unknown version " + std::to_string(packetVersion));
2933 			return LIZARDFS_ERROR_IO;
2934 		}
2935 	} catch (Exception& ex) {
2936 		fs_got_inconsistent("LIZ_MATOCL_FLOCK", message.size(), ex.what());
2937 		return LIZARDFS_ERROR_IO;
2938 	}
2939 }
2940 
fs_makesnapshot(uint32_t src_inode,uint32_t dst_inode,const std::string & dst_parent,uint32_t uid,uint32_t gid,uint8_t can_overwrite,LizardClient::JobId & job_id)2941 uint8_t fs_makesnapshot(uint32_t src_inode, uint32_t dst_inode, const std::string &dst_parent,
2942 	                uint32_t uid, uint32_t gid, uint8_t can_overwrite, LizardClient::JobId &job_id) {
2943 	static const int kBatchSize = 1024;
2944 	threc *rec = fs_get_my_threc();
2945 	job_id = 0;
2946 
2947 	uint32_t msg_id;
2948 	MessageBuffer response;
2949 	auto request = cltoma::requestTaskId::build(rec->packetId);
2950 	if (!fs_lizcreatepacket(rec, request)) {
2951 		return LIZARDFS_ERROR_IO;
2952 	}
2953 	if (!fs_lizsendandreceive(rec, LIZ_MATOCL_REQUEST_TASK_ID, response)) {
2954 		return LIZARDFS_ERROR_IO;
2955 	}
2956 
2957 	try {
2958 		matocl::requestTaskId::deserialize(response, msg_id, job_id);
2959 	} catch (Exception& ex) {
2960 		fs_got_inconsistent("LIZ_MATOCL_FUSE_REQUEST_TASK_ID", request.size(), ex.what());
2961 		job_id = 0;
2962 		return LIZARDFS_ERROR_IO;
2963 	}
2964 
2965 	request = cltoma::snapshot::build(rec->packetId, job_id, src_inode, dst_inode, dst_parent,
2966 	                                  uid, gid, can_overwrite, true, kBatchSize);
2967 
2968 	if (!fs_lizcreatepacket(rec, request)) {
2969 		job_id = 0;
2970 		return LIZARDFS_ERROR_IO;
2971 	}
2972 
2973 	response.clear();
2974 	if (!fs_lizsendandreceive(rec, LIZ_MATOCL_FUSE_SNAPSHOT, response)) {
2975 		job_id = 0;
2976 		return LIZARDFS_ERROR_IO;
2977 	}
2978 
2979 	try {
2980 		uint8_t status;
2981 		matocl::snapshot::deserialize(response, msg_id, status);
2982 		return status;
2983 	} catch (Exception& ex) {
2984 		fs_got_inconsistent("LIZ_MATOCL_FUSE_SNAPSHOT", request.size(), ex.what());
2985 		job_id = 0;
2986 		return LIZARDFS_ERROR_IO;
2987 	}
2988 }
2989 
fs_getgoal(uint32_t inode,std::string & goal)2990 uint8_t fs_getgoal(uint32_t inode, std::string &goal) {
2991 	threc *rec = fs_get_my_threc();
2992 
2993 	goal.clear();
2994 	auto message = cltoma::fuseGetGoal::build(rec->packetId, inode, GMODE_NORMAL);
2995 
2996 	if (!fs_lizcreatepacket(rec, message)) {
2997 		return LIZARDFS_ERROR_IO;
2998 	}
2999 
3000 	if (!fs_lizsendandreceive(rec, LIZ_MATOCL_FUSE_GETGOAL, message)) {
3001 		return LIZARDFS_ERROR_IO;
3002 	}
3003 
3004 	try {
3005 		PacketVersion packet_version;
3006 		deserializePacketVersionNoHeader(message, packet_version);
3007 		if (packet_version == matocl::fuseGetGoal::kStatusPacketVersion) {
3008 			uint8_t status;
3009 			uint32_t dummy_message_id;
3010 			matocl::fuseGetGoal::deserialize(message, dummy_message_id, status);
3011 			return status;
3012 		} else if (packet_version == matocl::fuseGetGoal::kResponsePacketVersion) {
3013 			std::vector<FuseGetGoalStats> goalsStats;
3014 			uint32_t messageId;
3015 			matocl::fuseGetGoal::deserialize(message, messageId, goalsStats);
3016 			if (goalsStats.size() != 1) {
3017 				return LIZARDFS_ERROR_EINVAL;
3018 			}
3019 			goal = goalsStats[0].goalName;
3020 			return LIZARDFS_STATUS_OK;
3021 		} else {
3022 			return LIZARDFS_ERROR_EINVAL;
3023 		}
3024 	} catch (Exception& ex) {
3025 		fs_got_inconsistent("LIZ_MATOCL_FUSE_GETGOAL", message.size(), ex.what());
3026 		return LIZARDFS_ERROR_IO;
3027 	}
3028 }
3029 
fs_setgoal(uint32_t inode,uint32_t uid,const std::string & goal_name,uint8_t smode)3030 uint8_t fs_setgoal(uint32_t inode, uint32_t uid, const std::string &goal_name, uint8_t smode) {
3031 	threc *rec = fs_get_my_threc();
3032 
3033 	auto message = cltoma::fuseSetGoal::build(rec->packetId, inode, uid, goal_name, smode);
3034 
3035 	if (!fs_lizcreatepacket(rec, message)) {
3036 		return LIZARDFS_ERROR_IO;
3037 	}
3038 
3039 	if (!fs_lizsendandreceive(rec, LIZ_MATOCL_FUSE_SETGOAL, message)) {
3040 		return LIZARDFS_ERROR_IO;
3041 	}
3042 
3043 	try {
3044 		PacketVersion packet_version;
3045 		deserializePacketVersionNoHeader(message, packet_version);
3046 		if (packet_version == matocl::fuseSetGoal::kStatusPacketVersion) {
3047 			uint8_t status;
3048 			uint32_t dummy_message_id;
3049 			matocl::fuseSetGoal::deserialize(message, dummy_message_id, status);
3050 			return status;
3051 		} else if (packet_version == matocl::fuseSetGoal::kResponsePacketVersion) {
3052 			return LIZARDFS_STATUS_OK;
3053 		} else {
3054 			return LIZARDFS_ERROR_EINVAL;
3055 		}
3056 	} catch (Exception& ex) {
3057 		fs_got_inconsistent("LIZ_MATOCL_FUSE_SETGOAL", message.size(), ex.what());
3058 		return LIZARDFS_ERROR_IO;
3059 	}
3060 }
3061 
fs_getchunksinfo(uint32_t uid,uint32_t gid,uint32_t inode,uint32_t chunk_index,uint32_t chunk_count,std::vector<ChunkWithAddressAndLabel> & chunks)3062 uint8_t fs_getchunksinfo(uint32_t uid, uint32_t gid, uint32_t inode, uint32_t chunk_index,
3063 		uint32_t chunk_count, std::vector<ChunkWithAddressAndLabel> &chunks) {
3064 	threc *rec = fs_get_my_threc();
3065 
3066 	auto message = cltoma::chunksInfo::build(rec->packetId, uid, gid, inode, chunk_index, chunk_count);
3067 
3068 	if (!fs_lizcreatepacket(rec, message)) {
3069 		return LIZARDFS_ERROR_IO;
3070 	}
3071 
3072 	if (!fs_lizsendandreceive(rec, LIZ_MATOCL_CHUNKS_INFO, message)) {
3073 		return LIZARDFS_ERROR_IO;
3074 	}
3075 
3076 	try {
3077 		PacketVersion packet_version;
3078 		deserializePacketVersionNoHeader(message, packet_version);
3079 		if (packet_version == matocl::fuseSetGoal::kStatusPacketVersion) {
3080 			uint8_t status;
3081 			uint32_t message_id;
3082 			matocl::chunksInfo::deserialize(message, message_id, status);
3083 			return status;
3084 		} else if (packet_version == matocl::fuseSetGoal::kResponsePacketVersion) {
3085 			uint32_t message_id;
3086 			matocl::chunksInfo::deserialize(message, message_id, chunks);
3087 			return LIZARDFS_STATUS_OK;
3088 		} else {
3089 			return LIZARDFS_ERROR_EINVAL;
3090 		}
3091 	} catch (Exception& ex) {
3092 		fs_got_inconsistent("LIZ_MATOCL_CHUNKS_INFO", message.size(), ex.what());
3093 		return LIZARDFS_ERROR_IO;
3094 	}
3095 }
3096 
fs_getchunkservers(std::vector<ChunkserverListEntry> & chunkservers)3097 uint8_t fs_getchunkservers(std::vector<ChunkserverListEntry> &chunkservers) {
3098 	threc *rec = fs_get_my_threc();
3099 	uint32_t message_id;
3100 
3101 	auto message = cltoma::cservList::build(rec->packetId, true);
3102 
3103 	if (!fs_lizcreatepacket(rec, message)) {
3104 		return LIZARDFS_ERROR_IO;
3105 	}
3106 
3107 	if (!fs_lizsendandreceive(rec, LIZ_MATOCL_CSERV_LIST, message)) {
3108 		return LIZARDFS_ERROR_IO;
3109 	}
3110 
3111 	chunkservers.clear();
3112 	matocl::cservList::deserialize(message, message_id, chunkservers);
3113 	return LIZARDFS_STATUS_OK;
3114 }
3115