2 Copyright (C) 2010 Proxmox Server Solutions GmbH
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU Affero General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Affero General Public License for more details.
14 You should have received a copy of the GNU Affero General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 Author: Dietmar Maurer <dietmar@proxmox.com>
21 #define G_LOG_DOMAIN "dcdb"
25 #endif /* HAVE_CONFIG_H */
33 #include <sys/types.h>
35 #include <arpa/inet.h>
36 #include <sys/epoll.h>
40 #include "cfs-utils.h"
46 memdb_index_t
*master
;
55 const guchar csum
[32],
58 g_return_if_fail(dfsm
!= NULL
);
59 g_return_if_fail(path
!= NULL
);
60 g_return_if_fail(csum
!= NULL
);
64 iov
[0].iov_base
= (char *)csum
;
67 iov
[1].iov_base
= (char *)path
;
68 iov
[1].iov_len
= strlen(path
) + 1;
70 if (!cfs_is_quorate())
73 dcdb_message_t msg_type
= request
?
74 DCDB_MESSAGE_CFS_UNLOCK_REQUEST
: DCDB_MESSAGE_CFS_UNLOCK
;
76 dfsm_send_message_sync(dfsm
, msg_type
, iov
, 2, NULL
);
80 dcdb_parse_unlock_request(
87 g_return_val_if_fail(msg
!= NULL
, FALSE
);
88 g_return_val_if_fail(path
!= NULL
, FALSE
);
89 g_return_val_if_fail(csum
!= NULL
, FALSE
);
92 cfs_critical("received short unlock message (%zu < 33)", msg_len
);
97 msg
+= 32; msg_len
-= 32;
100 if ((*path
)[msg_len
- 1] != 0) {
101 cfs_critical("received mailformed unlock message - 'path' not terminated");
110 dcdb_send_fuse_message(
112 dcdb_message_t msg_type
,
122 iov
[0].iov_base
= (char *)&size
;
123 iov
[0].iov_len
= sizeof(size
);
125 iov
[1].iov_base
= (char *)&offset
;
126 iov
[1].iov_len
= sizeof(offset
);
128 guint32 pathlen
= path
? strlen(path
) + 1 : 0;
129 iov
[2].iov_base
= (char *)&pathlen
;
130 iov
[2].iov_len
= sizeof(pathlen
);
132 guint32 tolen
= to
? strlen(to
) + 1 : 0;
133 iov
[3].iov_base
= (char *)&tolen
;
134 iov
[3].iov_len
= sizeof(tolen
);
136 iov
[4].iov_base
= (char *)&flags
;
137 iov
[4].iov_len
= sizeof(flags
);
139 iov
[5].iov_base
= (char *)path
;
140 iov
[5].iov_len
= pathlen
;
142 iov
[6].iov_base
= (char *)to
;
143 iov
[6].iov_len
= tolen
;
145 iov
[7].iov_base
= (char *)buf
;
146 iov
[7].iov_len
= size
;
149 memset(&rc
, 0, sizeof(rc
));
152 if (!cfs_is_quorate())
155 if (dfsm_send_message_sync(dfsm
, msg_type
, iov
, 8, &rc
))
162 dcdb_parse_fuse_message(
173 g_return_val_if_fail(msg
!= NULL
, FALSE
);
174 g_return_val_if_fail(path
!= NULL
, FALSE
);
175 g_return_val_if_fail(to
!= NULL
, FALSE
);
176 g_return_val_if_fail(buf
!= NULL
, FALSE
);
177 g_return_val_if_fail(size
!= NULL
, FALSE
);
178 g_return_val_if_fail(offset
!= NULL
, FALSE
);
179 g_return_val_if_fail(flags
!= NULL
, FALSE
);
182 cfs_critical("received short fuse message (%zu < 20)", msg_len
);
186 *size
= *((guint32
*)msg
);
187 msg
+= 4; msg_len
-= 4;
189 *offset
= *((guint32
*)msg
);
190 msg
+= 4; msg_len
-= 4;
192 guint32 pathlen
= *((guint32
*)msg
);
193 msg
+= 4; msg_len
-= 4;
195 guint32 tolen
= *((guint32
*)msg
);
196 msg
+= 4; msg_len
-= 4;
198 *flags
= *((guint32
*)msg
);
199 msg
+= 4; msg_len
-= 4;
201 if (msg_len
!= ((*size
) + pathlen
+ tolen
)) {
202 cfs_critical("received mailformed fuse message");
207 msg
+= pathlen
; msg_len
-= pathlen
;
210 if ((*path
)[pathlen
- 1] != 0) {
211 cfs_critical("received mailformed fuse message - 'path' not terminated");
220 msg
+= tolen
; msg_len
-= tolen
;
223 if ((*to
)[tolen
- 1] != 0) {
224 cfs_critical("received mailformed fuse message - 'to' not terminated");
232 *buf
= (*size
) ? msg
: NULL
;
238 dcdb_send_update_inode(
240 memdb_tree_entry_t
*te
)
242 g_return_val_if_fail(dfsm
!= NULL
, FALSE
);
243 g_return_val_if_fail(te
!= NULL
, FALSE
);
246 struct iovec iov
[20];
248 uint32_t namelen
= strlen(te
->name
) + 1;
250 iov
[0].iov_base
= (char *)&te
->parent
;
251 iov
[0].iov_len
= sizeof(te
->parent
);
252 iov
[1].iov_base
= (char *)&te
->inode
;
253 iov
[1].iov_len
= sizeof(te
->inode
);
254 iov
[2].iov_base
= (char *)&te
->version
;
255 iov
[2].iov_len
= sizeof(te
->version
);
256 iov
[3].iov_base
= (char *)&te
->writer
;
257 iov
[3].iov_len
= sizeof(te
->writer
);
258 iov
[4].iov_base
= (char *)&te
->mtime
;
259 iov
[4].iov_len
= sizeof(te
->mtime
);
260 iov
[5].iov_base
= (char *)&te
->size
;
261 iov
[5].iov_len
= sizeof(te
->size
);
262 iov
[6].iov_base
= (char *)&namelen
;
263 iov
[6].iov_len
= sizeof(namelen
);
264 iov
[7].iov_base
= (char *)&te
->type
;
265 iov
[7].iov_len
= sizeof(te
->type
);
266 iov
[8].iov_base
= (char *)te
->name
;
267 iov
[8].iov_len
= namelen
;
270 if (te
->type
== DT_REG
&& te
->size
) {
271 iov
[9].iov_base
= (char *)te
->data
.value
;
272 iov
[9].iov_len
= te
->size
;
276 if (dfsm_send_update(dfsm
, iov
, len
) != CS_OK
)
283 dcdb_parse_update_inode(
288 cfs_critical("received short message (msg_len < 40)");
292 guint64 parent
= *((guint64
*)msg
);
293 msg
+= 8; msg_len
-= 8;
294 guint64 inode
= *((guint64
*)msg
);
295 msg
+= 8; msg_len
-= 8;
296 guint64 version
= *((guint64
*)msg
);
297 msg
+= 8; msg_len
-= 8;
299 guint32 writer
= *((guint32
*)msg
);
300 msg
+= 4; msg_len
-= 4;
301 guint32 mtime
= *((guint32
*)msg
);
302 msg
+= 4; msg_len
-= 4;
303 guint32 size
= *((guint32
*)msg
);
304 msg
+= 4; msg_len
-= 4;
305 guint32 namelen
= *((guint32
*)msg
);
306 msg
+= 4; msg_len
-= 4;
308 char type
= *((char *)msg
);
309 msg
+= 1; msg_len
-= 1;
311 if (!(type
== DT_REG
|| type
== DT_DIR
)) {
312 cfs_critical("received mailformed message (unknown inode type %d)", type
);
316 if (msg_len
!= (size
+ namelen
)) {
317 cfs_critical("received mailformed message (msg_len != (size + namelen))");
321 char *name
= (char *)msg
;
322 msg
+= namelen
; msg_len
-= namelen
;
324 const void *data
= msg
;
326 if (name
[namelen
- 1] != 0) {
327 cfs_critical("received mailformed message (name[namelen-1] != 0)");
331 memdb_tree_entry_t
*te
= memdb_tree_entry_new(name
);
336 te
->version
= version
;
343 if (te
->type
== DT_REG
&& te
->size
) {
344 te
->data
.value
= g_memdup(data
, te
->size
);
345 if (!te
->data
.value
) {
346 memdb_tree_entry_free(te
);
355 dcdb_sync_corosync_conf(
357 gboolean notify_corosync
)
359 g_return_if_fail(memdb
!= NULL
);
362 gpointer data
= NULL
;
364 len
= memdb_read(memdb
, "corosync.conf", &data
);
368 guint64 new_version
= cluster_config_version(data
, len
);
370 cfs_critical("unable to parse cluster config_version");
374 char *old_data
= NULL
;
375 gsize old_length
= 0;
376 guint64 old_version
= 0;
379 if (!g_file_get_contents(HOST_CLUSTER_CONF_FN
, &old_data
, &old_length
, &err
)) {
380 if (!g_error_matches(err
, G_FILE_ERROR
, G_FILE_ERROR_NOENT
)) {
381 cfs_critical("unable to read cluster config file '%s' - %s",
382 HOST_CLUSTER_CONF_FN
, err
->message
);
387 old_version
= cluster_config_version(old_data
, old_length
);
390 /* test if something changed - return if no changes */
391 if (data
&& old_data
&& (old_length
== len
) &&
392 !memcmp(data
, old_data
, len
))
395 if (new_version
< old_version
) {
396 cfs_critical("local corosync.conf is newer");
400 if (!atomic_write_file(HOST_CLUSTER_CONF_FN
, data
, len
, 0644, 0))
403 cfs_message("wrote new corosync config '%s' (version = %" G_GUINT64_FORMAT
")",
404 HOST_CLUSTER_CONF_FN
, new_version
);
406 if (notify_corosync
&& old_version
) {
407 /* tell corosync that there is a new config file */
408 cfs_debug ("run corosync-cfgtool -R");
409 int status
= system("corosync-cfgtool -R >/dev/null 2>&1");
410 if (WIFEXITED(status
) && WEXITSTATUS(status
) != 0) {
411 cfs_critical("corosync-cfgtool -R failed with exit code %d\n", WEXITSTATUS(status
));
413 cfs_debug ("end corosync-cfgtool -R");
429 unsigned int *res_len
)
431 g_return_val_if_fail(dfsm
!= NULL
, FALSE
);
432 g_return_val_if_fail(data
!= NULL
, FALSE
);
434 memdb_t
*memdb
= (memdb_t
*)data
;
436 g_return_val_if_fail(memdb
->root
!= NULL
, FALSE
);
438 cfs_debug("enter %s %016" PRIX64
" %08X", __func__
, (uint64_t) memdb
->root
->version
, memdb
->root
->mtime
);
440 g_mutex_lock (&memdb
->mutex
);
441 memdb_index_t
*idx
= memdb_encode_index(memdb
->index
, memdb
->root
);
442 g_mutex_unlock (&memdb
->mutex
);
445 *res_len
= idx
->bytes
;
454 memdb_index_t
*idx
[])
456 g_return_val_if_fail(idx
!= NULL
, -1);
458 cfs_debug("enter %s", __func__
);
462 /* try select most actual data - compare 'version' an 'time of last write'
463 * NOTE: syncinfo members are sorted
465 for (int i
= 0; i
< node_count
; i
++) {
469 memdb_index_t
*leaderidx
= idx
[leader
];
471 if (idx
[i
]->version
== leaderidx
->version
&&
472 idx
[i
]->mtime
> leaderidx
->mtime
) {
474 } else if (idx
[i
]->version
> leaderidx
->version
) {
480 cfs_debug ("leave %s (%d)", __func__
, leader
);
486 dcdb_create_and_send_updates(
489 memdb_index_t
*master
,
491 memdb_index_t
*idx
[])
493 g_return_val_if_fail(dfsm
!= NULL
, FALSE
);
494 g_return_val_if_fail(memdb
!= NULL
, FALSE
);
495 g_return_val_if_fail(master
!= NULL
, FALSE
);
497 cfs_debug("enter %s", __func__
);
499 gboolean res
= FALSE
;
501 GHashTable
*updates
= g_hash_table_new(g_int64_hash
, g_int64_equal
);
505 g_mutex_lock (&memdb
->mutex
);
507 for (int n
= 0; n
< node_count
; n
++) {
508 memdb_index_t
*slave
= idx
[n
];
515 for (int i
= 0; i
< master
->size
; i
++) {
516 guint64 inode
= master
->entries
[i
].inode
;
517 while (j
< slave
->size
&& slave
->entries
[j
].inode
< inode
)
520 if (memcmp(&slave
->entries
[j
], &master
->entries
[i
],
521 sizeof(memdb_index_extry_t
)) == 0) {
525 if (g_hash_table_lookup(updates
, &inode
))
528 cfs_debug("found different inode %d %016" PRIX64
, i
, (uint64_t) inode
);
530 memdb_tree_entry_t
*te
, *cpy
;
532 if (!(te
= g_hash_table_lookup(memdb
->index
, &inode
))) {
533 cfs_critical("can get inode data for inode %016" PRIX64
, (uint64_t) inode
);
537 cpy
= memdb_tree_entry_copy(te
, 1);
538 g_hash_table_replace(updates
, &cpy
->inode
, cpy
);
542 g_mutex_unlock (&memdb
->mutex
);
550 cfs_message("start sending inode updates");
552 g_hash_table_iter_init (&iter
, updates
);
553 while (g_hash_table_iter_next (&iter
, &key
, &value
)) {
554 memdb_tree_entry_t
*te
= (memdb_tree_entry_t
*)value
;
557 if (!dcdb_send_update_inode(dfsm
, te
)) {
558 /* tolerate error here */
559 cfs_critical("sending update inode failed %016" PRIX64
, (uint64_t) te
->inode
);
561 cfs_debug("sent update inode %016" PRIX64
, (uint64_t) te
->inode
);
564 memdb_tree_entry_free(te
);
567 cfs_message("sent all (%d) updates", count
);
569 if (dfsm_send_update_complete(dfsm
) != CS_OK
) {
570 cfs_critical("failed to send UPDATE_COMPLETE message");
578 g_hash_table_destroy(updates
);
580 cfs_debug("leave %s (%d)", __func__
, res
);
586 dcdb_process_state_update(
589 dfsm_sync_info_t
*syncinfo
)
591 g_return_val_if_fail(dfsm
!= NULL
, -1);
592 g_return_val_if_fail(data
!= NULL
, -1);
593 g_return_val_if_fail(syncinfo
!= NULL
, -1);
595 memdb_t
*memdb
= (memdb_t
*)data
;
597 cfs_debug("enter %s", __func__
);
599 dcdb_sync_info_t
*localsi
= g_new0(dcdb_sync_info_t
, 1);
603 syncinfo
->data
= localsi
;
605 memdb_index_t
*idx
[syncinfo
->node_count
];
607 for (int i
= 0; i
< syncinfo
->node_count
; i
++) {
608 dfsm_node_info_t
*ni
= &syncinfo
->nodes
[i
];
610 if (ni
->state_len
< sizeof(memdb_index_t
)) {
611 cfs_critical("received short memdb index (len < sizeof(memdb_index_t))");
615 idx
[i
] = (memdb_index_t
*)ni
->state
;
617 if (ni
->state_len
!= idx
[i
]->bytes
) {
618 cfs_critical("received mailformed memdb index (len != idx->bytes)");
623 /* select leader - set mode */
624 int leader
= dcdb_select_leader(syncinfo
->node_count
, idx
);
626 cfs_critical("unable to select leader failed");
630 cfs_message("leader is %d/%d", syncinfo
->nodes
[leader
].nodeid
, syncinfo
->nodes
[leader
].pid
);
632 memdb_index_t
*leaderidx
= idx
[leader
];
633 localsi
->master
= leaderidx
;
635 GString
*str
= g_string_new("synced members:");
636 g_string_append_printf(str
, " %d/%d", syncinfo
->nodes
[leader
].nodeid
, syncinfo
->nodes
[leader
].pid
);
638 for (int i
= 0; i
< syncinfo
->node_count
; i
++) {
639 dfsm_node_info_t
*ni
= &syncinfo
->nodes
[i
];
643 if (leaderidx
->bytes
== idx
[i
]->bytes
&&
644 memcmp(leaderidx
, idx
[i
], leaderidx
->bytes
) == 0) {
646 g_string_append_printf(str
, ", %d/%d", ni
->nodeid
, ni
->pid
);
649 if (dfsm_nodeid_is_local(dfsm
, ni
->nodeid
, ni
->pid
))
650 localsi
->idx
= idx
[i
];
652 cfs_message(str
->str
);
653 g_string_free(str
, 1);
656 if (dfsm_nodeid_is_local(dfsm
, syncinfo
->nodes
[leader
].nodeid
, syncinfo
->nodes
[leader
].pid
)) {
657 if (!dcdb_create_and_send_updates(dfsm
, memdb
, leaderidx
, syncinfo
->node_count
, idx
))
668 dfsm_sync_info_t
*syncinfo
,
674 g_return_val_if_fail(dfsm
!= NULL
, -1);
675 g_return_val_if_fail(data
!= NULL
, -1);
676 g_return_val_if_fail(msg
!= NULL
, -1);
677 g_return_val_if_fail(syncinfo
!= NULL
, -1);
678 g_return_val_if_fail(syncinfo
->data
!= NULL
, -1);
680 cfs_debug("enter %s", __func__
);
682 memdb_tree_entry_t
*te
;
684 if (!(te
= dcdb_parse_update_inode(msg
, msg_len
)))
687 cfs_debug("received inode update %016" PRIX64
" from node %d",
688 (uint64_t) te
->inode
, nodeid
);
690 dcdb_sync_info_t
*localsi
= (dcdb_sync_info_t
*)syncinfo
->data
;
692 localsi
->updates
= g_list_append(localsi
->updates
, te
);
701 dfsm_sync_info_t
*syncinfo
)
703 g_return_val_if_fail(dfsm
!= NULL
, -1);
704 g_return_val_if_fail(data
!= NULL
, -1);
705 g_return_val_if_fail(syncinfo
!= NULL
, -1);
706 g_return_val_if_fail(syncinfo
->data
!= NULL
, -1);
708 memdb_t
*memdb
= (memdb_t
*)data
;
710 cfs_debug("enter %s", __func__
);
712 dcdb_sync_info_t
*localsi
= (dcdb_sync_info_t
*)syncinfo
->data
;
714 guint count
= g_list_length(localsi
->updates
);
716 cfs_message("update complete - trying to commit (got %u inode updates)", count
);
718 if (!bdb_backend_commit_update(memdb
, localsi
->master
, localsi
->idx
, localsi
->updates
))
721 dcdb_sync_corosync_conf(memdb
, FALSE
);
730 dfsm_sync_info_t
*syncinfo
)
732 g_return_val_if_fail(dfsm
!= NULL
, -1);
733 g_return_val_if_fail(data
!= NULL
, -1);
734 g_return_val_if_fail(syncinfo
!= NULL
, -1);
735 g_return_val_if_fail(syncinfo
->data
!= NULL
, -1);
737 cfs_debug("enter %s", __func__
);
739 dcdb_sync_info_t
*localsi
= (dcdb_sync_info_t
*)syncinfo
->data
;
741 GList
*iter
= localsi
->updates
;
743 memdb_tree_entry_t
*te
= (memdb_tree_entry_t
*)iter
->data
;
744 memdb_tree_entry_free(te
);
745 iter
= g_list_next(iter
);
747 g_list_free(localsi
->updates
);
761 g_return_val_if_fail(dfsm
!= NULL
, FALSE
);
762 g_return_val_if_fail(csum
!= NULL
, FALSE
);
764 memdb_t
*memdb
= (memdb_t
*)data
;
766 g_return_val_if_fail(memdb
!= NULL
, FALSE
);
768 cfs_debug("enter %s %016" PRIX64
" %08X", __func__
, memdb
->root
->version
, memdb
->root
->mtime
);
770 g_mutex_lock (&memdb
->mutex
);
771 gboolean res
= memdb_compute_checksum(memdb
->index
, memdb
->root
, csum
, csum_len
);
772 g_mutex_unlock (&memdb
->mutex
);
774 cfs_debug("leave %s %016" PRIX64
" (%d)", __func__
, *( (uint64_t *) csum
), res
);
791 g_return_val_if_fail(dfsm
!= NULL
, -1);
792 g_return_val_if_fail(msg
!= NULL
, -1);
794 memdb_t
*memdb
= (memdb_t
*)data
;
796 g_return_val_if_fail(memdb
!= NULL
, -1);
797 g_return_val_if_fail(res_ptr
!= NULL
, -1);
801 int msg_result
= -ENOTSUP
;
803 if (!DCDB_VALID_MESSAGE_TYPE(msg_type
))
806 cfs_debug("process message %u (length = %zd)", msg_type
, msg_len
);
808 if (!cfs_is_quorate()) {
809 cfs_critical("received write while not quorate - trigger resync");
810 msg_result
= -EACCES
;
814 const char *path
, *to
, *buf
;
815 guint32 size
, offset
, flags
;
818 if (msg_type
== DCDB_MESSAGE_CFS_UNLOCK_REQUEST
||
819 msg_type
== DCDB_MESSAGE_CFS_UNLOCK
) {
820 msg_result
= 0; /* ignored anyways */
822 if (!dcdb_parse_unlock_request(msg
, msg_len
, &path
, &csum
))
826 memdb_tree_entry_t
*te
= memdb_getattr(memdb
, path
);
828 if (te
&& te
->type
== DT_DIR
&&
829 path_is_lockdir(path
) && memdb_tree_entry_csum(te
, cur_csum
) &&
830 (memcmp(csum
, cur_csum
, 32) == 0)) {
832 if (msg_type
== DCDB_MESSAGE_CFS_UNLOCK
) {
834 cfs_debug("got valid unlock message");
836 msg_result
= memdb_delete(memdb
, path
, nodeid
, msg_time
);
838 } else if (dfsm_lowest_nodeid(dfsm
)) {
840 cfs_debug("got valid unlock request message");
842 if (memdb_lock_expired(memdb
, path
, csum
)) {
843 cfs_debug("sending unlock message");
844 dcdb_send_unlock(dfsm
, path
, csum
, FALSE
);
849 } else if (msg_type
== DCDB_MESSAGE_CFS_WRITE
) {
851 if (!dcdb_parse_fuse_message(msg
, msg_len
, &path
, &to
, &buf
,
852 &size
, &offset
, &flags
))
855 msg_result
= memdb_write(memdb
, path
, nodeid
, msg_time
,
856 buf
, size
, offset
, flags
);
858 if ((msg_result
>= 0) && !strcmp(path
, "corosync.conf"))
859 dcdb_sync_corosync_conf(memdb
, dfsm_nodeid_is_local(dfsm
, nodeid
, pid
));
861 } else if (msg_type
== DCDB_MESSAGE_CFS_CREATE
) {
863 if (!dcdb_parse_fuse_message(msg
, msg_len
, &path
, &to
, &buf
,
864 &size
, &offset
, &flags
))
867 msg_result
= memdb_create(memdb
, path
, nodeid
, msg_time
);
869 if ((msg_result
>= 0) && !strcmp(path
, "corosync.conf"))
870 dcdb_sync_corosync_conf(memdb
, dfsm_nodeid_is_local(dfsm
, nodeid
, pid
));
872 } else if (msg_type
== DCDB_MESSAGE_CFS_MKDIR
) {
874 if (!dcdb_parse_fuse_message(msg
, msg_len
, &path
, &to
, &buf
,
875 &size
, &offset
, &flags
))
878 msg_result
= memdb_mkdir(memdb
, path
, nodeid
, msg_time
);
880 } else if (msg_type
== DCDB_MESSAGE_CFS_DELETE
) {
882 if (!dcdb_parse_fuse_message(msg
, msg_len
, &path
, &to
, &buf
,
883 &size
, &offset
, &flags
))
886 msg_result
= memdb_delete(memdb
, path
, nodeid
, msg_time
);
888 } else if (msg_type
== DCDB_MESSAGE_CFS_RENAME
) {
890 if (!dcdb_parse_fuse_message(msg
, msg_len
, &path
, &to
, &buf
,
891 &size
, &offset
, &flags
))
894 msg_result
= memdb_rename(memdb
, path
, to
, nodeid
, msg_time
);
896 if ((msg_result
>= 0) && !strcmp(to
, "corosync.conf"))
897 dcdb_sync_corosync_conf(memdb
, dfsm_nodeid_is_local(dfsm
, nodeid
, pid
));
899 } else if (msg_type
== DCDB_MESSAGE_CFS_MTIME
) {
901 if (!dcdb_parse_fuse_message(msg
, msg_len
, &path
, &to
, &buf
,
902 &size
, &offset
, &flags
))
905 /* Note: mtime is sent via offset field */
906 msg_result
= memdb_mtime(memdb
, path
, nodeid
, offset
);
912 *res_ptr
= msg_result
;
915 dfsm_set_errormode(dfsm
);
919 cfs_debug("leave %s (%d)", __func__
, res
);
924 cfs_critical("received unknown message type (msg_type == %u)", msg_type
);
931 static dfsm_callbacks_t dcdb_dfsm_callbacks
= {
932 .dfsm_deliver_fn
= dcdb_deliver
,
933 .dfsm_get_state_fn
= dcdb_get_state
,
934 .dfsm_process_state_update_fn
= dcdb_process_state_update
,
935 .dfsm_process_update_fn
= dcdb_process_update
,
936 .dfsm_commit_fn
= dcdb_commit
,
937 .dfsm_cleanup_fn
= dcdb_cleanup
,
938 .dfsm_checksum_fn
= dcdb_checksum
,
941 dfsm_t
*dcdb_new(memdb_t
*memdb
)
943 g_return_val_if_fail(memdb
!= NULL
, NULL
);
945 return dfsm_new(memdb
, DCDB_CPG_GROUP_NAME
, G_LOG_DOMAIN
,
946 DCDB_PROTOCOL_VERSION
, &dcdb_dfsm_callbacks
);