1 /*
2 * Copyright (C) 2016 Jakub Kruszona-Zawadzki, Core Technology Sp. z o.o.
3 *
4 * This file is part of MooseFS.
5 *
6 * MooseFS 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 2 (only).
9 *
10 * MooseFS 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 MooseFS; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1301, USA
18 * or visit http://www.gnu.org/licenses/gpl-2.0.html
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <stdio.h>
26 #include <sys/types.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <syslog.h>
32 #include <errno.h>
33 #include <inttypes.h>
34
35 #include "MFSCommunication.h"
36
37 #include "sessions.h"
38 #include "bio.h"
39 #include "filesystem.h"
40 #include "openfiles.h"
41 #include "changelog.h"
42 #include "metadata.h"
43 #include "datapack.h"
44 #include "cfg.h"
45 #include "main.h"
46 #include "slogger.h"
47 #include "massert.h"
48
49 #define SESSION_STATS 16
50
51 #define SESSION_HASHSIZE 256
52 #define SESSION_HASH(sessionid) ((sessionid)%(SESSION_HASHSIZE))
53
54 // opened files
55 /*
56 typedef struct filelist {
57 uint32_t inode;
58 struct filelist *next;
59 } filelist;
60 */
61
62 typedef struct session {
63 uint32_t sessionid;
64 char *info;
65 uint32_t peerip;
66 uint8_t closed;
67 uint8_t sesflags;
68 uint8_t mingoal;
69 uint8_t maxgoal;
70 uint32_t mintrashtime;
71 uint32_t maxtrashtime;
72 uint32_t rootuid;
73 uint32_t rootgid;
74 uint32_t mapalluid;
75 uint32_t mapallgid;
76 uint32_t rootinode;
77 uint32_t disconnected; // 0 = connected ; other = disconnection timestamp
78 uint32_t nsocks; // >0 - connected (number of active connections) ; 0 - not connected
79 uint32_t infopeerip; // peer ip for info
80 uint32_t infoversion; // version for info
81 uint32_t currentopstats[SESSION_STATS];
82 uint32_t lasthouropstats[SESSION_STATS];
83 // filelist *openedfiles;
84 struct session *next;
85 } session;
86
87 static session *sessionshashtab[SESSION_HASHSIZE];
88 // static session *sessionshead=NULL;
89 static uint32_t nextsessionid;
90
91 static uint32_t SessionSustainTime;
92
93 static uint32_t starttime;
94
sessions_attach_session(void * vsesdata,uint32_t peerip,uint32_t version)95 void sessions_attach_session(void* vsesdata,uint32_t peerip,uint32_t version) {
96 session *sesdata = (session*)vsesdata;
97 sesdata->closed = 0;
98 sesdata->nsocks++;
99 sesdata->infopeerip = peerip;
100 sesdata->infoversion = version;
101 sesdata->disconnected = 0;
102 }
103
sessions_close_session(uint32_t sessionid)104 void sessions_close_session(uint32_t sessionid) {
105 session *asesdata;
106 if (sessionid==0) {
107 return;
108 }
109 for (asesdata = sessionshashtab[SESSION_HASH(sessionid)] ; asesdata ; asesdata=asesdata->next) {
110 if (asesdata->sessionid==sessionid) {
111 if (asesdata->nsocks==1) {
112 asesdata->closed = 1;
113 }
114 }
115 }
116 return;
117 }
118
sessions_disconnection(void * vsesdata)119 void sessions_disconnection(void *vsesdata) {
120 session *sesdata = (session*)vsesdata;
121 if (sesdata) {
122 if (sesdata->nsocks>0) {
123 sesdata->nsocks--;
124 }
125 if (sesdata->nsocks==0) {
126 sesdata->disconnected = main_time();
127 changelog("%"PRIu32"|SESDISCONNECTED(%"PRIu32")",main_time(),sesdata->sessionid);
128 }
129 }
130 }
131
sessions_find_session(uint32_t sessionid)132 void* sessions_find_session(uint32_t sessionid) {
133 session *asesdata;
134 if (sessionid==0) {
135 return NULL;
136 }
137 for (asesdata = sessionshashtab[SESSION_HASH(sessionid)] ; asesdata ; asesdata=asesdata->next) {
138 if (asesdata->sessionid==sessionid) {
139 return asesdata;
140 }
141 }
142 return NULL;
143 }
144
sessions_clean_session(session * sesdata)145 static inline void sessions_clean_session(session *sesdata) {
146 // filelist *fl,*afl;
147 of_sessionremoved(sesdata->sessionid);
148 // fl=sesdata->openedfiles;
149 // while (fl) {
150 // afl = fl;
151 // fl=fl->next;
152 // fs_release(afl->inode,sesdata->sessionid);
153 // free(afl);
154 // }
155 // sesdata->openedfiles=NULL;
156 if (sesdata->info) {
157 free(sesdata->info);
158 }
159 }
160
sessions_store(bio * fd)161 uint8_t sessions_store(bio *fd) {
162 session *asesdata;
163 uint32_t ileng;
164 uint8_t fsesrecord[47+SESSION_STATS*8]; // 4+4+4+4+1+1+1+4+4+4+4+4+4+SESSION_STATS*4+SESSION_STATS*4
165 uint8_t *ptr;
166 int i;
167 uint32_t hpos;
168 if (fd==NULL) {
169 return 0x12;
170 }
171 ptr = fsesrecord;
172 put32bit(&ptr,nextsessionid);
173 put16bit(&ptr,SESSION_STATS);
174 if (bio_write(fd,fsesrecord,6)!=6) {
175 return 0xFF;
176 }
177 for (hpos = 0 ; hpos < SESSION_HASHSIZE ; hpos++) {
178 for (asesdata = sessionshashtab[hpos] ; asesdata ; asesdata=asesdata->next) {
179 if (asesdata->closed==0) {
180 ptr = fsesrecord;
181 if (asesdata->info) {
182 ileng = strlen(asesdata->info);
183 } else {
184 ileng = 0;
185 }
186 put32bit(&ptr,asesdata->sessionid);
187 put32bit(&ptr,ileng);
188 put32bit(&ptr,asesdata->peerip);
189 put32bit(&ptr,asesdata->rootinode);
190 put8bit(&ptr,asesdata->sesflags);
191 put8bit(&ptr,asesdata->mingoal);
192 put8bit(&ptr,asesdata->maxgoal);
193 put32bit(&ptr,asesdata->mintrashtime);
194 put32bit(&ptr,asesdata->maxtrashtime);
195 put32bit(&ptr,asesdata->rootuid);
196 put32bit(&ptr,asesdata->rootgid);
197 put32bit(&ptr,asesdata->mapalluid);
198 put32bit(&ptr,asesdata->mapallgid);
199 put32bit(&ptr,asesdata->disconnected);
200 for (i=0 ; i<SESSION_STATS ; i++) {
201 put32bit(&ptr,asesdata->currentopstats[i]);
202 }
203 for (i=0 ; i<SESSION_STATS ; i++) {
204 put32bit(&ptr,asesdata->lasthouropstats[i]);
205 }
206 if (bio_write(fd,fsesrecord,(47+SESSION_STATS*8))!=(47+SESSION_STATS*8)) {
207 return 0xFF;
208 }
209 if (ileng>0) {
210 if (bio_write(fd,asesdata->info,ileng)!=ileng) {
211 return 0xFF;
212 }
213 }
214 }
215 }
216 }
217 memset(fsesrecord,0,(47+SESSION_STATS*8));
218 if (bio_write(fd,fsesrecord,(47+SESSION_STATS*8))!=(47+SESSION_STATS*8)) {
219 return 0xFF;
220 }
221 return 0;
222 }
223
sessions_load(bio * fd,uint8_t mver)224 int sessions_load(bio *fd,uint8_t mver) {
225 session *asesdata;
226 uint32_t ileng;
227 uint8_t hdr[8];
228 uint8_t *fsesrecord;
229 const uint8_t *ptr;
230 uint16_t statsinfile;
231 uint32_t recsize;
232 uint32_t i,sessionid,hpos;
233
234 if (mver<0x12) {
235 if (bio_read(fd,hdr,8)!=8) {
236 return -1;
237 }
238
239 ptr = hdr;
240 switch (get16bit(&ptr)) {
241 case 1:
242 mver = 0x10;
243 break;
244 case 2:
245 mver = 0x11;
246 break;
247 default:
248 return -1;
249 }
250 } else {
251 if (bio_read(fd,hdr,6)!=6) {
252 return -1;
253 }
254
255 ptr = hdr;
256 }
257 nextsessionid = get32bit(&ptr);
258 statsinfile = get16bit(&ptr);
259
260 if (mver<0x11) {
261 recsize = 43+statsinfile*8;
262 } else {
263 recsize = 47+statsinfile*8;
264 }
265 fsesrecord = malloc(recsize);
266 passert(fsesrecord);
267
268 while(1) {
269 if (bio_read(fd,fsesrecord,recsize)==recsize) {
270 ptr = fsesrecord;
271 sessionid = get32bit(&ptr);
272 if (sessionid==0) {
273 free(fsesrecord);
274 return 0;
275 }
276 asesdata = (session*)malloc(sizeof(session));
277 passert(asesdata);
278 asesdata->sessionid = sessionid;
279 ileng = get32bit(&ptr);
280 asesdata->peerip = get32bit(&ptr);
281 asesdata->rootinode = get32bit(&ptr);
282 asesdata->sesflags = get8bit(&ptr);
283 asesdata->mingoal = get8bit(&ptr);
284 asesdata->maxgoal = get8bit(&ptr);
285 asesdata->mintrashtime = get32bit(&ptr);
286 asesdata->maxtrashtime = get32bit(&ptr);
287 asesdata->rootuid = get32bit(&ptr);
288 asesdata->rootgid = get32bit(&ptr);
289 asesdata->mapalluid = get32bit(&ptr);
290 asesdata->mapallgid = get32bit(&ptr);
291 if (mver>=0x11) {
292 asesdata->disconnected = get32bit(&ptr);
293 } else {
294 asesdata->disconnected = main_time();
295 }
296 asesdata->info = NULL;
297 asesdata->closed = 0;
298 // asesdata->openedfiles = NULL;
299 asesdata->nsocks = 0;
300 asesdata->infopeerip = asesdata->peerip;
301 asesdata->infoversion = 0;
302 for (i=0 ; i<SESSION_STATS ; i++) {
303 asesdata->currentopstats[i] = (i<statsinfile)?get32bit(&ptr):0;
304 }
305 if (statsinfile>SESSION_STATS) {
306 ptr+=4*(statsinfile-SESSION_STATS);
307 }
308 for (i=0 ; i<SESSION_STATS ; i++) {
309 asesdata->lasthouropstats[i] = (i<statsinfile)?get32bit(&ptr):0;
310 }
311 if (ileng>0) {
312 asesdata->info = malloc(ileng+1);
313 passert(asesdata->info);
314 if (bio_read(fd,asesdata->info,ileng)!=ileng) {
315 free(asesdata->info);
316 free(asesdata);
317 free(fsesrecord);
318 return -1;
319 }
320 asesdata->info[ileng]=0;
321 }
322 hpos = SESSION_HASH(sessionid);
323 asesdata->next = sessionshashtab[hpos];
324 sessionshashtab[hpos] = asesdata;
325 } else {
326 free(fsesrecord);
327 return -1;
328 }
329 }
330 }
331
332 /* import from old metadata */
sessions_set_nextsessionid(uint32_t nsi)333 void sessions_set_nextsessionid(uint32_t nsi) {
334 nextsessionid = nsi;
335 }
336 /*
337 uint32_t sessions_getnextsessionid(void) {
338 return nextsessionid;
339 }
340 */
sessions_import_data(void)341 int sessions_import_data(void) {
342 session *asesdata;
343 uint32_t ileng;
344 // uint8_t fsesrecord[33+SESSION_STATS*8]; // 4+4+4+4+1+4+4+4+4+SESSION_STATS*4+SESSION_STATS*4
345 uint8_t hdr[8];
346 uint8_t *fsesrecord;
347 const uint8_t *ptr;
348 uint8_t mapalldata;
349 uint8_t goaltrashdata;
350 uint32_t i,statsinfile;
351 uint32_t hpos;
352 int r;
353 FILE *fd;
354
355 fd = fopen("sessions.mfs","r");
356 if (fd==NULL) {
357 mfs_errlog_silent(LOG_WARNING,"can't load sessions, fopen error");
358 if (errno==ENOENT) { // it's ok if file does not exist
359 nextsessionid = 1;
360 return 0;
361 } else {
362 return -1;
363 }
364 }
365 if (fread(hdr,8,1,fd)!=1) {
366 syslog(LOG_WARNING,"can't load sessions, fread error");
367 fclose(fd);
368 return -1;
369 }
370 if (memcmp(hdr,MFSSIGNATURE "S 1.5",8)==0) {
371 mapalldata = 0;
372 goaltrashdata = 0;
373 statsinfile = 16;
374 } else if (memcmp(hdr,MFSSIGNATURE "S \001\006\001",8)==0) {
375 mapalldata = 1;
376 goaltrashdata = 0;
377 statsinfile = 16;
378 } else if (memcmp(hdr,MFSSIGNATURE "S \001\006\002",8)==0) {
379 mapalldata = 1;
380 goaltrashdata = 0;
381 statsinfile = 21;
382 } else if (memcmp(hdr,MFSSIGNATURE "S \001\006\003",8)==0) {
383 mapalldata = 1;
384 goaltrashdata = 0;
385 if (fread(hdr,2,1,fd)!=1) {
386 syslog(LOG_WARNING,"can't load sessions, fread error");
387 fclose(fd);
388 return -1;
389 }
390 ptr = hdr;
391 statsinfile = get16bit(&ptr);
392 } else if (memcmp(hdr,MFSSIGNATURE "S \001\006\004",8)==0) {
393 mapalldata = 1;
394 goaltrashdata = 1;
395 if (fread(hdr,2,1,fd)!=1) {
396 syslog(LOG_WARNING,"can't load sessions, fread error");
397 fclose(fd);
398 return -1;
399 }
400 ptr = hdr;
401 statsinfile = get16bit(&ptr);
402 } else {
403 syslog(LOG_WARNING,"can't load sessions, bad header");
404 fclose(fd);
405 return -1;
406 }
407
408 if (mapalldata==0) {
409 fsesrecord = malloc(25+statsinfile*8);
410 } else if (goaltrashdata==0) {
411 fsesrecord = malloc(33+statsinfile*8);
412 } else {
413 fsesrecord = malloc(43+statsinfile*8);
414 }
415 passert(fsesrecord);
416
417 while (!feof(fd)) {
418 if (mapalldata==0) {
419 r = fread(fsesrecord,25+statsinfile*8,1,fd);
420 } else if (goaltrashdata==0) {
421 r = fread(fsesrecord,33+statsinfile*8,1,fd);
422 } else {
423 r = fread(fsesrecord,43+statsinfile*8,1,fd);
424 }
425 if (r==1) {
426 ptr = fsesrecord;
427 asesdata = (session*)malloc(sizeof(session));
428 passert(asesdata);
429 asesdata->sessionid = get32bit(&ptr);
430 ileng = get32bit(&ptr);
431 asesdata->peerip = get32bit(&ptr);
432 asesdata->rootinode = get32bit(&ptr);
433 asesdata->sesflags = get8bit(&ptr);
434 if (goaltrashdata) {
435 asesdata->mingoal = get8bit(&ptr);
436 asesdata->maxgoal = get8bit(&ptr);
437 asesdata->mintrashtime = get32bit(&ptr);
438 asesdata->maxtrashtime = get32bit(&ptr);
439 } else { // set defaults (no limits)
440 asesdata->mingoal = 1;
441 asesdata->maxgoal = 9;
442 asesdata->mintrashtime = 0;
443 asesdata->maxtrashtime = UINT32_C(0xFFFFFFFF);
444 }
445 asesdata->rootuid = get32bit(&ptr);
446 asesdata->rootgid = get32bit(&ptr);
447 if (mapalldata) {
448 asesdata->mapalluid = get32bit(&ptr);
449 asesdata->mapallgid = get32bit(&ptr);
450 } else {
451 asesdata->mapalluid = 0;
452 asesdata->mapallgid = 0;
453 }
454 asesdata->info = NULL;
455 asesdata->closed = 0;
456 // asesdata->openedfiles = NULL;
457 asesdata->disconnected = main_time();
458 asesdata->nsocks = 0;
459 asesdata->infopeerip = 0;
460 asesdata->infoversion = 0;
461 for (i=0 ; i<SESSION_STATS ; i++) {
462 asesdata->currentopstats[i] = (i<statsinfile)?get32bit(&ptr):0;
463 }
464 if (statsinfile>SESSION_STATS) {
465 ptr+=4*(statsinfile-SESSION_STATS);
466 }
467 for (i=0 ; i<SESSION_STATS ; i++) {
468 asesdata->lasthouropstats[i] = (i<statsinfile)?get32bit(&ptr):0;
469 }
470 if (ileng>0) {
471 asesdata->info = malloc(ileng+1);
472 passert(asesdata->info);
473 if (fread(asesdata->info,ileng,1,fd)!=1) {
474 free(asesdata->info);
475 free(asesdata);
476 free(fsesrecord);
477 syslog(LOG_WARNING,"can't load sessions, fread error");
478 fclose(fd);
479 return -1;
480 }
481 asesdata->info[ileng]=0;
482 }
483 hpos = SESSION_HASH(asesdata->sessionid);
484 asesdata->next = sessionshashtab[hpos];
485 sessionshashtab[hpos] = asesdata;
486 }
487 if (ferror(fd)) {
488 free(fsesrecord);
489 syslog(LOG_WARNING,"can't load sessions, fread error");
490 fclose(fd);
491 return -1;
492 }
493 }
494 free(fsesrecord);
495 syslog(LOG_NOTICE,"sessions have been loaded");
496 fclose(fd);
497 return 1;
498 }
499
sessions_import(void)500 void sessions_import(void) {
501 fprintf(stderr,"loading sessions ... ");
502 fflush(stderr);
503 switch (sessions_import_data()) {
504 case 0: // no file
505 fprintf(stderr,"file not found\n");
506 fprintf(stderr,"if it is not fresh installation then you have to restart all active mounts !!!\n");
507 break;
508 case 1: // file loaded
509 fprintf(stderr,"ok\n");
510 fprintf(stderr,"sessions file has been loaded\n");
511 break;
512 default:
513 fprintf(stderr,"error\n");
514 fprintf(stderr,"due to missing sessions you have to restart all active mounts !!!\n");
515 break;
516 }
517 }
518
519 /*
520 int sessions_open_file(void* vsesdata,uint32_t inode) {
521 session *sesdata = (session*)vsesdata;
522 filelist *ofptr,**ofpptr;
523 int status;
524
525 ofpptr = &(sesdata->openedfiles);
526 while ((ofptr=*ofpptr)) {
527 if (ofptr->inode==inode) {
528 return STATUS_OK; // file already acquired - nothing to do
529 }
530 if (ofptr->inode>inode) {
531 break;
532 }
533 ofpptr = &(ofptr->next);
534 }
535 status = fs_acquire(inode,sesdata->sessionid);
536 if (status==STATUS_OK) {
537 ofptr = (filelist*)malloc(sizeof(filelist));
538 passert(ofptr);
539 ofptr->inode = inode;
540 ofptr->next = *ofpptr;
541 *ofpptr = ofptr;
542 }
543 return status;
544 }
545
546 int sessions_connect_session_with_inode(uint32_t sessionid,uint32_t inode) {
547 session *asesdata;
548 filelist *ofptr,**ofpptr;
549
550 for (asesdata = sessionshead ; asesdata && asesdata->sessionid!=sessionid; asesdata=asesdata->next) ;
551 if (asesdata==NULL) {
552 return 0;
553 }
554
555 ofpptr = &(asesdata->openedfiles);
556 while ((ofptr=*ofpptr)) {
557 if (ofptr->inode==inode) {
558 return 2;
559 }
560 if (ofptr->inode>inode) {
561 break;
562 }
563 ofpptr = &(ofptr->next);
564 }
565 ofptr = (filelist*)malloc(sizeof(filelist));
566 passert(ofptr);
567 ofptr->inode = inode;
568 ofptr->next = *ofpptr;
569 *ofpptr = ofptr;
570 return 1;
571 }
572 */
573
574 //uint32_t sessions_get_statscnt(void) {
575 // return SESSION_STATS;
576 //}
577
sessions_datasize(uint8_t vmode)578 uint32_t sessions_datasize(uint8_t vmode) {
579 session *sesdata;
580 uint32_t hpos;
581 uint32_t size;
582
583 size = 2;
584 for (hpos = 0 ; hpos < SESSION_HASHSIZE ; hpos++) {
585 for (sesdata = sessionshashtab[hpos] ; sesdata ; sesdata=sesdata->next) {
586 if (vmode<2) {
587 if (sesdata->nsocks>0) {
588 size += 37+SESSION_STATS*8+(vmode?10:0);
589 if (sesdata->info) {
590 size += strlen(sesdata->info);
591 }
592 if (sesdata->rootinode==0) {
593 size += 1;
594 } else {
595 size += fs_getdirpath_size(sesdata->rootinode);
596 }
597 }
598 } else {
599 size += 56+SESSION_STATS*8;
600 if (sesdata->info) {
601 size += strlen(sesdata->info);
602 }
603 if (sesdata->rootinode==0) {
604 size += 1;
605 } else {
606 size += fs_getdirpath_size(sesdata->rootinode);
607 }
608 }
609 }
610 }
611 return size;
612 }
613
sessions_datafill(uint8_t * ptr,uint8_t vmode)614 void sessions_datafill(uint8_t *ptr,uint8_t vmode) {
615 session *sesdata;
616 uint32_t now;
617 uint32_t hpos;
618 uint32_t pleng,ileng,i;
619
620 put16bit(&ptr,SESSION_STATS);
621 now = main_time();
622 for (hpos = 0 ; hpos < SESSION_HASHSIZE ; hpos++) {
623 for (sesdata = sessionshashtab[hpos] ; sesdata ; sesdata=sesdata->next) {
624 if (vmode<2) {
625 if (sesdata->nsocks>0) {
626 put32bit(&ptr,sesdata->sessionid);
627 put32bit(&ptr,sesdata->infopeerip);
628 put32bit(&ptr,sesdata->infoversion);
629 if (sesdata->info) {
630 ileng = strlen(sesdata->info);
631 put32bit(&ptr,ileng);
632 memcpy(ptr,sesdata->info,ileng);
633 ptr+=ileng;
634 } else {
635 put32bit(&ptr,0);
636 }
637 if (sesdata->rootinode==0) { // meta
638 pleng = 1;
639 put32bit(&ptr,pleng);
640 put8bit(&ptr,'.');
641 } else {
642 pleng = fs_getdirpath_size(sesdata->rootinode);
643 put32bit(&ptr,pleng);
644 if (pleng>0) {
645 fs_getdirpath_data(sesdata->rootinode,ptr,pleng);
646 ptr+=pleng;
647 }
648 }
649 put8bit(&ptr,sesdata->sesflags);
650 put32bit(&ptr,sesdata->rootuid);
651 put32bit(&ptr,sesdata->rootgid);
652 put32bit(&ptr,sesdata->mapalluid);
653 put32bit(&ptr,sesdata->mapallgid);
654 if (vmode) {
655 put8bit(&ptr,sesdata->mingoal);
656 put8bit(&ptr,sesdata->maxgoal);
657 put32bit(&ptr,sesdata->mintrashtime);
658 put32bit(&ptr,sesdata->maxtrashtime);
659 }
660 for (i=0 ; i<SESSION_STATS ; i++) {
661 put32bit(&ptr,sesdata->currentopstats[i]);
662 }
663 for (i=0 ; i<SESSION_STATS ; i++) {
664 put32bit(&ptr,sesdata->lasthouropstats[i]);
665 }
666 }
667 } else {
668 put32bit(&ptr,sesdata->sessionid);
669 if (sesdata->infopeerip==0 && sesdata->peerip!=0) {
670 put32bit(&ptr,sesdata->peerip);
671 } else {
672 put32bit(&ptr,sesdata->infopeerip);
673 }
674 put32bit(&ptr,sesdata->infoversion);
675 put32bit(&ptr,of_noofopenedfiles(sesdata->sessionid));
676 if (sesdata->nsocks>255) {
677 put8bit(&ptr,255);
678 } else {
679 put8bit(&ptr,sesdata->nsocks);
680 }
681 if (sesdata->nsocks>0) {
682 put32bit(&ptr,UINT32_C(0xFFFFFFFF));
683 } else {
684 if (sesdata->closed || sesdata->disconnected+SessionSustainTime<now) {
685 put32bit(&ptr,0);
686 } else {
687 put32bit(&ptr,sesdata->disconnected+SessionSustainTime-now);
688 }
689 }
690 if (sesdata->info) {
691 ileng = strlen(sesdata->info);
692 put32bit(&ptr,ileng);
693 memcpy(ptr,sesdata->info,ileng);
694 ptr+=ileng;
695 } else {
696 put32bit(&ptr,0);
697 }
698 if (sesdata->rootinode==0) { // meta
699 pleng = 1;
700 put32bit(&ptr,pleng);
701 put8bit(&ptr,'.');
702 } else {
703 pleng = fs_getdirpath_size(sesdata->rootinode);
704 put32bit(&ptr,pleng);
705 if (pleng>0) {
706 fs_getdirpath_data(sesdata->rootinode,ptr,pleng);
707 ptr+=pleng;
708 }
709 }
710 put8bit(&ptr,sesdata->sesflags);
711 put32bit(&ptr,sesdata->rootuid);
712 put32bit(&ptr,sesdata->rootgid);
713 put32bit(&ptr,sesdata->mapalluid);
714 put32bit(&ptr,sesdata->mapallgid);
715 put8bit(&ptr,sesdata->mingoal);
716 put8bit(&ptr,sesdata->maxgoal);
717 put32bit(&ptr,sesdata->mintrashtime);
718 put32bit(&ptr,sesdata->maxtrashtime);
719 for (i=0 ; i<SESSION_STATS ; i++) {
720 put32bit(&ptr,sesdata->currentopstats[i]);
721 }
722 for (i=0 ; i<SESSION_STATS ; i++) {
723 put32bit(&ptr,sesdata->lasthouropstats[i]);
724 }
725 }
726 }
727 }
728 }
729 /*
730 uint32_t sessions_datasize(void *vsesdata,uint8_t vmode) {
731 session *sesdata = (session*)vsesdata;
732 uint32_t size;
733
734 size = 25+SESSION_STATS*8+(vmode?10:0);
735 if (sesdata->info) {
736 size += strlen(sesdata->info);
737 }
738 if (sesdata->rootinode==0) {
739 size += 1;
740 } else {
741 size += fs_getdirpath_size(sesdata->rootinode);
742 }
743 return size;
744 }
745
746 uint32_t sessions_datafill(uint8_t *ptr,void *vsesdata,uint8_t vmode) {
747 session *sesdata = (session*)vsesdata;
748 uint32_t pleng,ileng,i;
749
750 if (sesdata->info) {
751 ileng = strlen(sesdata->info);
752 put32bit(&ptr,ileng);
753 memcpy(ptr,sesdata->info,ileng);
754 ptr+=ileng;
755 } else {
756 put32bit(&ptr,0);
757 ileng = 0;
758 }
759 if (sesdata->rootinode==0) { // meta
760 pleng = 1;
761 put32bit(&ptr,pleng);
762 put8bit(&ptr,'.');
763 } else {
764 pleng = fs_getdirpath_size(sesdata->rootinode);
765 put32bit(&ptr,pleng);
766 if (pleng>0) {
767 fs_getdirpath_data(sesdata->rootinode,ptr,pleng);
768 ptr+=pleng;
769 }
770 }
771 put8bit(&ptr,sesdata->sesflags);
772 put32bit(&ptr,sesdata->rootuid);
773 put32bit(&ptr,sesdata->rootgid);
774 put32bit(&ptr,sesdata->mapalluid);
775 put32bit(&ptr,sesdata->mapallgid);
776 if (vmode) {
777 put8bit(&ptr,sesdata->mingoal);
778 put8bit(&ptr,sesdata->maxgoal);
779 put32bit(&ptr,sesdata->mintrashtime);
780 put32bit(&ptr,sesdata->maxtrashtime);
781 }
782 for (i=0 ; i<SESSION_STATS ; i++) {
783 put32bit(&ptr,sesdata->currentopstats[i]);
784 }
785 for (i=0 ; i<SESSION_STATS ; i++) {
786 put32bit(&ptr,sesdata->lasthouropstats[i]);
787 }
788 return 25+SESSION_STATS*8+(vmode?10:0)+ileng+pleng;
789 }
790 */
sessions_create_session(uint32_t rootinode,uint8_t sesflags,uint32_t rootuid,uint32_t rootgid,uint32_t mapalluid,uint32_t mapallgid,uint8_t mingoal,uint8_t maxgoal,uint32_t mintrashtime,uint32_t maxtrashtime,uint32_t peerip,const char * info,uint32_t ileng)791 static inline void* sessions_create_session(uint32_t rootinode,uint8_t sesflags,uint32_t rootuid,uint32_t rootgid,uint32_t mapalluid,uint32_t mapallgid,uint8_t mingoal,uint8_t maxgoal,uint32_t mintrashtime,uint32_t maxtrashtime,uint32_t peerip,const char *info,uint32_t ileng) {
792 session *sesdata;
793 uint32_t hpos;
794
795 sesdata = (session*)malloc(sizeof(session));
796 passert(sesdata);
797 sesdata->sessionid = nextsessionid++;
798 sesdata->rootinode = rootinode;
799 sesdata->sesflags = (sesflags&(~SESFLAG_METARESTORE));
800 sesdata->rootuid = rootuid;
801 sesdata->rootgid = rootgid;
802 sesdata->mapalluid = mapalluid;
803 sesdata->mapallgid = mapallgid;
804 sesdata->mingoal = mingoal;
805 sesdata->maxgoal = maxgoal;
806 sesdata->mintrashtime = mintrashtime;
807 sesdata->maxtrashtime = maxtrashtime;
808 sesdata->peerip = peerip;
809 if (ileng>0) {
810 if (info[ileng-1]==0) {
811 sesdata->info = strdup(info);
812 passert(sesdata->info);
813 } else {
814 sesdata->info = malloc(ileng+1);
815 passert(sesdata->info);
816 memcpy(sesdata->info,info,ileng);
817 sesdata->info[ileng]=0;
818 }
819 }
820 sesdata->closed = 0;
821 // sesdata->openedfiles = NULL;
822 sesdata->disconnected = 0;
823 sesdata->nsocks = 0;
824 sesdata->infopeerip = 0;
825 sesdata->infoversion = 0;
826 memset(sesdata->currentopstats,0,4*SESSION_STATS);
827 memset(sesdata->lasthouropstats,0,4*SESSION_STATS);
828 hpos = SESSION_HASH(sesdata->sessionid);
829 sesdata->next = sessionshashtab[hpos];
830 sessionshashtab[hpos] = sesdata;
831 if ((sesflags&SESFLAG_METARESTORE)==0) {
832 changelog("%" PRIu32 "|SESADD(%"PRIu32",%"PRIu8",%"PRIu32",%"PRIu32",%"PRIu32",%"PRIu32",%"PRIu8",%"PRIu8",%"PRIu32",%"PRIu32",%"PRIu32",%s):%"PRIu32,main_time(),rootinode,sesflags,rootuid,rootgid,mapalluid,mapallgid,mingoal,maxgoal,mintrashtime,maxtrashtime,peerip,changelog_escape_name(ileng,(uint8_t*)info),sesdata->sessionid);
833 } else {
834 meta_version_inc();
835 }
836 return sesdata;
837 }
838
sessions_new_session(uint32_t rootinode,uint8_t sesflags,uint32_t rootuid,uint32_t rootgid,uint32_t mapalluid,uint32_t mapallgid,uint8_t mingoal,uint8_t maxgoal,uint32_t mintrashtime,uint32_t maxtrashtime,uint32_t peerip,const char * info,uint32_t ileng)839 void* sessions_new_session(uint32_t rootinode,uint8_t sesflags,uint32_t rootuid,uint32_t rootgid,uint32_t mapalluid,uint32_t mapallgid,uint8_t mingoal,uint8_t maxgoal,uint32_t mintrashtime,uint32_t maxtrashtime,uint32_t peerip,const char *info,uint32_t ileng) {
840 session *sesdata;
841 sesdata = sessions_create_session(rootinode,sesflags&(~SESFLAG_METARESTORE),rootuid,rootgid,mapalluid,mapallgid,mingoal,maxgoal,mintrashtime,maxtrashtime,peerip,info,ileng);
842 return sesdata;
843 }
844
sessions_mr_sesadd(uint32_t rootinode,uint8_t sesflags,uint32_t rootuid,uint32_t rootgid,uint32_t mapalluid,uint32_t mapallgid,uint8_t mingoal,uint8_t maxgoal,uint32_t mintrashtime,uint32_t maxtrashtime,uint32_t peerip,const uint8_t * info,uint32_t ileng,uint32_t sessionid)845 uint8_t sessions_mr_sesadd(uint32_t rootinode,uint8_t sesflags,uint32_t rootuid,uint32_t rootgid,uint32_t mapalluid,uint32_t mapallgid,uint8_t mingoal,uint8_t maxgoal,uint32_t mintrashtime,uint32_t maxtrashtime,uint32_t peerip,const uint8_t *info,uint32_t ileng,uint32_t sessionid) {
846 session *sesdata;
847 sesdata = sessions_create_session(rootinode,sesflags|SESFLAG_METARESTORE,rootuid,rootgid,mapalluid,mapallgid,mingoal,maxgoal,mintrashtime,maxtrashtime,peerip,(const char*)info,ileng);
848 if (sesdata->sessionid!=sessionid) {
849 return ERROR_MISMATCH;
850 }
851 return STATUS_OK;
852 }
853
sessions_mr_sesdel(uint32_t sessionid)854 uint8_t sessions_mr_sesdel(uint32_t sessionid) {
855 session **sesdata,*asesdata;
856 uint8_t status = ERROR_BADSESSIONID;
857 uint32_t hpos;
858
859 hpos = SESSION_HASH(sessionid);
860 sesdata = sessionshashtab + hpos;
861 while ((asesdata=*sesdata)) {
862 if (asesdata->sessionid==sessionid) {
863 sessions_clean_session(asesdata);
864 *sesdata = asesdata->next;
865 free(asesdata);
866 status = STATUS_OK;
867 } else {
868 sesdata = &(asesdata->next);
869 }
870 }
871 if (status==STATUS_OK) {
872 meta_version_inc();
873 }
874 return status;
875 }
876
sessions_mr_disconnected(uint32_t sessionid,uint32_t disctime)877 uint8_t sessions_mr_disconnected(uint32_t sessionid,uint32_t disctime) {
878 session *sesdata;
879
880 for (sesdata = sessionshashtab[SESSION_HASH(sessionid)] ; sesdata ; sesdata = sesdata->next) {
881 if (sesdata->sessionid == sessionid) {
882 sesdata->disconnected = disctime;
883 meta_version_inc();
884 return STATUS_OK;
885 }
886 }
887 return ERROR_NOTFOUND;
888 }
889
sessions_mr_session(uint32_t sessionid)890 uint8_t sessions_mr_session(uint32_t sessionid) {
891 if (sessionid!=nextsessionid) {
892 return ERROR_MISMATCH;
893 }
894 nextsessionid++;
895 meta_version_inc();
896 return STATUS_OK;
897 }
898
sessions_new(void)899 void sessions_new(void) {
900 nextsessionid=1;
901 }
902
903 /*
904 void sessions_sync_open_files(void *vsesdata,const uint8_t *ptr,uint32_t inodecnt) {
905 session *sesdata = (session*)vsesdata;
906
907
908 filelist *ofptr,**ofpptr;
909 uint32_t inode;
910
911 ofpptr = &(sesdata->openedfiles);
912 if (inodecnt) {
913 inodecnt--;
914 inode = get32bit(&ptr);
915 } else {
916 inode = 0;
917 }
918
919 while ((ofptr=*ofpptr) && inodecnt>0) {
920 if (ofptr->inode<inode) {
921 fs_release(ofptr->inode,sesdata->sessionid);
922 *ofpptr = ofptr->next;
923 free(ofptr);
924 } else {
925 if (ofptr->inode>inode) {
926 if (fs_acquire(inode,sesdata->sessionid)==STATUS_OK) {
927 ofptr = (filelist*)malloc(sizeof(filelist));
928 passert(ofptr);
929 ofptr->next = *ofpptr;
930 ofptr->inode = inode;
931 *ofpptr = ofptr;
932 ofpptr = &(ofptr->next);
933 }
934 } else {
935 ofpptr = &(ofptr->next);
936 }
937 if (inodecnt) {
938 inodecnt--;
939 inode = get32bit(&ptr);
940 } else {
941 inode = 0;
942 }
943 }
944 }
945 while (inode>0) {
946 if (fs_acquire(inode,sesdata->sessionid)==STATUS_OK) {
947 ofptr = (filelist*)malloc(sizeof(filelist));
948 passert(ofptr);
949 ofptr->next = *ofpptr;
950 ofptr->inode = inode;
951 *ofpptr = ofptr;
952 ofpptr = &(ofptr->next);
953 }
954 if (inodecnt) {
955 inodecnt--;
956 inode = get32bit(&ptr);
957 } else {
958 inode = 0;
959 }
960 }
961 while ((ofptr=*ofpptr)) {
962 fs_release(ofptr->inode,sesdata->sessionid);
963 *ofpptr = ofptr->next;
964 free(ofptr);
965 }
966 }
967 */
sessions_get_id(void * vsesdata)968 uint32_t sessions_get_id(void *vsesdata) {
969 session *sesdata = (session*)vsesdata;
970 return sesdata->sessionid;
971 }
972
sessions_get_peerip(void * vsesdata)973 uint32_t sessions_get_peerip(void *vsesdata) {
974 session *sesdata = (session*)vsesdata;
975 return sesdata->peerip;
976 }
977
sessions_get_rootinode(void * vsesdata)978 uint32_t sessions_get_rootinode(void *vsesdata) {
979 session *sesdata = (session*)vsesdata;
980 return sesdata->rootinode;
981 }
982
sessions_get_sesflags(void * vsesdata)983 uint32_t sessions_get_sesflags(void *vsesdata) {
984 session *sesdata = (session*)vsesdata;
985 return sesdata->sesflags | ((sesdata->infoversion>=VERSION2INT(1,7,32))?SESFLAG_ATTRBIT:0);
986 }
987
sessions_is_root_remapped(void * vsesdata)988 uint8_t sessions_is_root_remapped(void *vsesdata) {
989 session *sesdata = (session*)vsesdata;
990 return (sesdata->rootuid!=0)?1:0;
991 }
992
sessions_check_goal(void * vsesdata,uint8_t smode,uint8_t goal)993 uint8_t sessions_check_goal(void *vsesdata,uint8_t smode,uint8_t goal) {
994 session *sesdata = (session*)vsesdata;
995 switch (smode) {
996 case SMODE_SET:
997 if (goal<sesdata->mingoal || goal>sesdata->maxgoal) {
998 return ERROR_EPERM;
999 }
1000 case SMODE_INCREASE:
1001 if (goal>sesdata->maxgoal) {
1002 return ERROR_EPERM;
1003 }
1004 case SMODE_DECREASE:
1005 if (goal<sesdata->mingoal) {
1006 return ERROR_EPERM;
1007 }
1008 }
1009 return STATUS_OK;
1010 }
1011
sessions_check_trashtime(void * vsesdata,uint8_t smode,uint32_t trashtime)1012 uint8_t sessions_check_trashtime(void *vsesdata,uint8_t smode,uint32_t trashtime) {
1013 session *sesdata = (session*)vsesdata;
1014 switch (smode) {
1015 case SMODE_SET:
1016 if (trashtime<sesdata->mintrashtime || trashtime>sesdata->maxtrashtime) {
1017 return ERROR_EPERM;
1018 }
1019 case SMODE_INCREASE:
1020 if (trashtime>sesdata->maxtrashtime) {
1021 return ERROR_EPERM;
1022 }
1023 case SMODE_DECREASE:
1024 if (trashtime<sesdata->mintrashtime) {
1025 return ERROR_EPERM;
1026 }
1027 }
1028 return STATUS_OK;
1029 }
1030
sessions_inc_stats(void * vsesdata,uint8_t statid)1031 void sessions_inc_stats(void *vsesdata,uint8_t statid) {
1032 session *sesdata = (session*)vsesdata;
1033 if (sesdata && statid<SESSION_STATS) {
1034 sesdata->currentopstats[statid]++;
1035 }
1036 }
1037
sessions_ugid_remap(void * vsesdata,uint32_t * auid,uint32_t * agid)1038 void sessions_ugid_remap(void *vsesdata,uint32_t *auid,uint32_t *agid) {
1039 session *sesdata = (session*)vsesdata;
1040 if (*auid==0) {
1041 *auid = sesdata->rootuid;
1042 if (agid) {
1043 *agid = sesdata->rootgid;
1044 }
1045 } else if (sesdata->sesflags&SESFLAG_MAPALL) {
1046 *auid = sesdata->mapalluid;
1047 if (agid) {
1048 *agid = sesdata->mapallgid;
1049 }
1050 }
1051 }
1052
sessions_check(void)1053 void sessions_check(void) {
1054 session **sesdata,*asesdata;
1055 uint32_t now;
1056 uint32_t hpos;
1057
1058 now = main_time();
1059 if (starttime+120>now) {
1060 return;
1061 }
1062 for (hpos = 0 ; hpos < SESSION_HASHSIZE ; hpos++) {
1063 sesdata = sessionshashtab + hpos;
1064 while ((asesdata=*sesdata)) {
1065 if (asesdata->nsocks==0 && (asesdata->closed || asesdata->disconnected+SessionSustainTime<now)) {
1066 changelog("%"PRIu32"|SESDEL(%"PRIu32")",main_time(),asesdata->sessionid);
1067 syslog(LOG_NOTICE,"remove session: %u",asesdata->sessionid);
1068 sessions_clean_session(asesdata);
1069 *sesdata = asesdata->next;
1070 free(asesdata);
1071 } else {
1072 sesdata = &(asesdata->next);
1073 }
1074 }
1075 }
1076 }
1077
sessions_force_remove(uint32_t sessionid)1078 uint8_t sessions_force_remove(uint32_t sessionid) {
1079 session **sesdata,*asesdata;
1080 uint32_t hpos;
1081
1082 hpos = SESSION_HASH(sessionid);
1083 sesdata = sessionshashtab + hpos;
1084 while ((asesdata=*sesdata)) {
1085 if (asesdata->sessionid==sessionid) {
1086 if (asesdata->nsocks==0) {
1087 changelog("%"PRIu32"|SESDEL(%"PRIu32")",main_time(),asesdata->sessionid);
1088 syslog(LOG_NOTICE,"remove session: %u",asesdata->sessionid);
1089 sessions_clean_session(asesdata);
1090 *sesdata = asesdata->next;
1091 free(asesdata);
1092 return STATUS_OK;
1093 } else {
1094 return ERROR_ACTIVE;
1095 }
1096 } else {
1097 sesdata = &(asesdata->next);
1098 }
1099 }
1100 return ERROR_NOTFOUND;
1101 }
1102
sessions_statsmove(void)1103 void sessions_statsmove(void) {
1104 session *sesdata;
1105 uint32_t hpos;
1106 for (hpos = 0 ; hpos < SESSION_HASHSIZE ; hpos++) {
1107 for (sesdata = sessionshashtab[hpos] ; sesdata ; sesdata=sesdata->next) {
1108 memcpy(sesdata->lasthouropstats,sesdata->currentopstats,4*SESSION_STATS);
1109 memset(sesdata->currentopstats,0,4*SESSION_STATS);
1110 }
1111 }
1112 }
1113
sessions_cleanup(void)1114 void sessions_cleanup(void) {
1115 session *ss,*ssn;
1116 uint32_t hpos;
1117 // filelist *of,*ofn;
1118
1119 for (hpos = 0 ; hpos < SESSION_HASHSIZE ; hpos++) {
1120 for (ss = sessionshashtab[hpos] ; ss ; ss = ssn) {
1121 ssn = ss->next;
1122 // for (of = ss->openedfiles ; of ; of = ofn) {
1123 // ofn = of->next;
1124 // free(of);
1125 // }
1126 if (ss->info) {
1127 free(ss->info);
1128 }
1129 free(ss);
1130 }
1131 sessionshashtab[hpos] = NULL;
1132 }
1133 }
1134
sessions_reload(void)1135 void sessions_reload(void) {
1136 SessionSustainTime = cfg_getuint32("SESSION_SUSTAIN_TIME",86400);
1137 if (SessionSustainTime>7*86400) {
1138 SessionSustainTime=7*86400;
1139 mfs_syslog(LOG_WARNING,"SESSION_SUSTAIN_TIME too big (more than week) - setting this value to one week");
1140 }
1141 if (SessionSustainTime<60) {
1142 SessionSustainTime=60;
1143 mfs_syslog(LOG_WARNING,"SESSION_SUSTAIN_TIME too low (less than minute) - setting this value to one minute");
1144 }
1145 }
1146
sessions_init(void)1147 int sessions_init(void) {
1148 uint32_t hpos;
1149
1150 starttime = main_time();
1151 for (hpos = 0 ; hpos < SESSION_HASHSIZE ; hpos++) {
1152 sessionshashtab[hpos] = NULL;
1153 }
1154 sessions_reload();
1155 main_time_register(10,0,sessions_check);
1156 main_time_register(3600,0,sessions_statsmove);
1157 main_reload_register(sessions_reload);
1158 return 0;
1159 }
1160