When sending start offset to readdir, get . and .. into account
[pohmelfs.git] / fs / pohmelfs / packet.h
blobf432987581302a9de578b3fa07360c11a6ab7a92
1 /*
2 * 2008+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
3 * All rights reserved.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program 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.
16 #ifndef __DNET_PACKET_H
17 #define __DNET_PACKET_H
19 #ifndef __KERNEL__
20 #include <sys/time.h>
21 #include <arpa/inet.h>
22 #include <sys/stat.h>
24 #include <string.h>
25 #include <stdint.h>
27 #include <elliptics/typedefs.h>
28 #include <elliptics/core.h>
29 #endif
31 #ifdef __cplusplus
32 extern "C" {
33 #endif
35 enum dnet_commands {
36 DNET_CMD_LOOKUP = 1, /* Lookup address by ID and per-object info: size, permissions and so on*/
37 DNET_CMD_REVERSE_LOOKUP, /* Lookup ID by address */
38 DNET_CMD_JOIN, /* Join the network - force remote nodes to update
39 * their route tables to include given node with given
40 * address
42 DNET_CMD_WRITE,
43 DNET_CMD_READ, /* IO commands. They have to follow by the
44 * IO attribute which will have offset and size
45 * parameters.
47 DNET_CMD_LIST, /* List all objects for given node ID */
48 DNET_CMD_EXEC, /* Execute given command on the remote node */
49 DNET_CMD_ROUTE_LIST, /* Receive route table from given node */
50 DNET_CMD_STAT, /* Gather remote VM, LA and FS statistics */
51 DNET_CMD_NOTIFY, /* Notify when object in question was modified */
52 DNET_CMD_DEL, /* Remove given object from the storage */
53 DNET_CMD_STAT_COUNT, /* Gather remote per-cmd statistics */
54 DNET_CMD_STATUS, /* Change elliptics node status */
55 DNET_CMD_READ_RANGE, /* Read range of objects */
56 DNET_CMD_DEL_RANGE, /* Remove range of objects */
57 DNET_CMD_AUTH, /* Authentification cookie check */
58 DNET_CMD_BULK_READ, /* Read a number of ids at one time */
60 DNET_CMD_UNKNOWN, /* This slot is allocated for statistics gathered for unknown commands */
61 __DNET_CMD_MAX,
64 enum dnet_counters {
65 DNET_CNTR_LA1 = __DNET_CMD_MAX*2, /* Load average for 1 min */
66 DNET_CNTR_LA5, /* Load average for 5 min */
67 DNET_CNTR_LA15, /* Load average for 15 min */
68 DNET_CNTR_BSIZE, /* Block size */
69 DNET_CNTR_FRSIZE, /* Fragment size */
70 DNET_CNTR_BLOCKS, /* Filesystem size in frsize units */
71 DNET_CNTR_BFREE, /* # free blocks */
72 DNET_CNTR_BAVAIL, /* # free blocks for non-root */
73 DNET_CNTR_FILES, /* # inodes */
74 DNET_CNTR_FFREE, /* # free inodes */
75 DNET_CNTR_FAVAIL, /* # free inodes for non-root */
76 DNET_CNTR_FSID, /* File system ID */
77 DNET_CNTR_VM_ACTIVE, /* Active memory */
78 DNET_CNTR_VM_INACTIVE, /* Inactive memory */
79 DNET_CNTR_VM_TOTAL, /* Total memory */
80 DNET_CNTR_VM_FREE, /* Free memory */
81 DNET_CNTR_VM_CACHED, /* Used for cache */
82 DNET_CNTR_VM_BUFFERS, /* Used for buffers */
83 DNET_CNTR_NODE_FILES, /* # files in meta */
84 DNET_CNTR_NODE_LAST_MERGE, /* Result of the last merge */
85 DNET_CNTR_NODE_CHECK_COPY, /* Result of the last check copies */
86 DNET_CNTR_DBR_NOREC, /* Kyoto Cabinet DB read error KCENOREC */
87 DNET_CNTR_DBR_SYSTEM, /* Kyoto Cabinet DB read error KCESYSTEM */
88 DNET_CNTR_DBR_ERROR, /* Kyoto Cabinet DB read error */
89 DNET_CNTR_DBW_SYSTEM, /* Kyoto Cabinet DB write error KCESYSTEM */
90 DNET_CNTR_DBW_ERROR, /* Kyoto Cabinet DB write error */
91 DNET_CNTR_UNKNOWN, /* This slot is allocated for statistics gathered for unknown counters */
92 __DNET_CNTR_MAX,
96 * Transaction ID direction bit.
97 * When set, data is a reply for the given transaction.
99 #define DNET_TRANS_REPLY 0x8000000000000000ULL
102 * Command flags.
106 * When set, node will generate a reply when transaction
107 * is completed and put completion status into cmd.status
108 * field.
110 #define DNET_FLAGS_NEED_ACK (1<<0)
112 /* There will be more commands with the same parameters (transaction number and id) */
113 #define DNET_FLAGS_MORE (1<<1)
115 /* Transaction is about to be destroyed */
116 #define DNET_FLAGS_DESTROY (1<<2)
118 /* Do not forward requst to antoher node even if given ID does not belong to our range */
119 #define DNET_FLAGS_DIRECT (1<<3)
121 /* Do not locks operations - must be set for script callers or recursive operations */
122 #define DNET_FLAGS_NOLOCK (1<<4)
124 struct dnet_id {
125 uint8_t id[DNET_ID_SIZE];
126 uint32_t group_id;
127 int type;
128 } __attribute__ ((packed));
130 struct dnet_raw_id {
131 uint8_t id[DNET_ID_SIZE];
132 } __attribute__ ((packed));
134 static inline void dnet_convert_raw_id(struct dnet_raw_id *id __attribute__ ((unused)))
138 static inline void dnet_setup_id(struct dnet_id *id, unsigned int group_id, unsigned char *raw)
140 memcpy(id->id, raw, DNET_ID_SIZE);
141 id->group_id = group_id;
144 struct dnet_cmd
146 struct dnet_id id;
147 uint32_t flags;
148 int status;
149 uint64_t trans;
150 uint64_t size;
151 uint8_t data[0];
152 } __attribute__ ((packed));
154 /* kernel (pohmelfs) provides own defines for byteorder changes */
155 #ifndef __KERNEL__
156 #ifdef WORDS_BIGENDIAN
158 #define dnet_bswap16(x) ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8))
160 #define dnet_bswap32(x) \
161 ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
162 (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
164 #define dnet_bswap64(x) \
165 ((((x) & 0xff00000000000000ull) >> 56) \
166 | (((x) & 0x00ff000000000000ull) >> 40) \
167 | (((x) & 0x0000ff0000000000ull) >> 24) \
168 | (((x) & 0x000000ff00000000ull) >> 8) \
169 | (((x) & 0x00000000ff000000ull) << 8) \
170 | (((x) & 0x0000000000ff0000ull) << 24) \
171 | (((x) & 0x000000000000ff00ull) << 40) \
172 | (((x) & 0x00000000000000ffull) << 56))
173 #else
174 #define dnet_bswap16(x) (x)
175 #define dnet_bswap32(x) (x)
176 #define dnet_bswap64(x) (x)
177 #endif
178 #endif
180 static inline void dnet_convert_id(struct dnet_id *id)
182 id->group_id = dnet_bswap32(id->group_id);
183 id->type = dnet_bswap32(id->type);
186 static inline void dnet_convert_cmd(struct dnet_cmd *cmd)
188 dnet_convert_id(&cmd->id);
189 cmd->flags = dnet_bswap32(cmd->flags);
190 cmd->status = dnet_bswap32(cmd->status);
191 cmd->size = dnet_bswap64(cmd->size);
192 cmd->trans = dnet_bswap64(cmd->trans);
195 /* Completely remove object history and metadata */
196 #define DNET_ATTR_DELETE_HISTORY (1<<0)
198 /* What type of counters to fetch */
199 #define DNET_ATTR_CNTR_GLOBAL (1<<0)
201 /* Bulk request for checking files */
202 #define DNET_ATTR_BULK_CHECK (1<<0)
204 /* Fill ctime/mtime from metadata when processing DNET_CMD_LOOKUP */
205 #define DNET_ATTR_META_TIMES (1<<1)
207 /* Do not verify checksum */
208 #define DNET_ATTR_NOCSUM (1<<2)
211 * ascending sort data before returning range request to user
212 * c++ bindings only
214 #define DNET_ATTR_SORT (1<<3)
217 * This flag will force its parent CMD not to lock operation
218 * Flag will be propagated to cmd->flags
220 #define DNET_ATTR_NOLOCK (1<<4)
222 struct dnet_attr
224 uint64_t size;
225 uint32_t cmd;
226 uint32_t flags;
227 uint32_t unused[2];
228 } __attribute__ ((packed));
230 static inline void dnet_convert_attr(struct dnet_attr *a)
232 a->size = dnet_bswap64(a->size);
233 a->cmd = dnet_bswap32(a->cmd);
234 a->flags = dnet_bswap32(a->flags);
237 #define DNET_ADDR_SIZE 28
239 struct dnet_addr
241 uint8_t addr[DNET_ADDR_SIZE];
242 uint32_t addr_len;
243 } __attribute__ ((packed));
245 struct dnet_list
247 struct dnet_id id;
248 uint32_t size;
249 uint8_t data[0];
250 } __attribute__ ((packed));
252 static inline void dnet_convert_list(struct dnet_list *l)
254 dnet_convert_id(&l->id);
255 l->size = dnet_bswap32(l->size);
258 struct dnet_addr_attr
260 uint16_t sock_type;
261 uint16_t family;
262 uint32_t proto;
263 struct dnet_addr addr;
264 } __attribute__ ((packed));
266 static inline void dnet_convert_addr_attr(struct dnet_addr_attr *a)
268 a->addr.addr_len = dnet_bswap32(a->addr.addr_len);
269 a->proto = dnet_bswap32(a->proto);
270 a->sock_type = dnet_bswap16(a->sock_type);
271 a->family = dnet_bswap16(a->family);
274 struct dnet_addr_cmd
276 struct dnet_cmd cmd;
277 struct dnet_attr a;
278 struct dnet_addr_attr addr;
279 } __attribute__ ((packed));
281 static inline void dnet_convert_addr_cmd(struct dnet_addr_cmd *l)
283 dnet_convert_cmd(&l->cmd);
284 dnet_convert_attr(&l->a);
285 dnet_convert_addr_attr(&l->addr);
288 /* Do not update history for given transaction */
289 #define DNET_IO_FLAGS_SKIP_SENDING (1<<0)
291 /* Append given data at the end of the object */
292 #define DNET_IO_FLAGS_APPEND (1<<1)
294 #define DNET_IO_FLAGS_COMPRESS (1<<2)
296 /* Metada IO request */
297 #define DNET_IO_FLAGS_META (1<<3)
299 /* eblob prepare/commit phase */
300 #define DNET_IO_FLAGS_PREPARE (1<<4)
301 #define DNET_IO_FLAGS_COMMIT (1<<5)
303 /* Object was removed */
304 #define DNET_IO_FLAGS_REMOVED (1<<6)
306 /* Overwrite data */
307 #define DNET_IO_FLAGS_OVERWRITE (1<<7)
309 /* Do not checksum data */
310 #define DNET_IO_FLAGS_NOCSUM (1<<8)
313 * this flag is used when we want backend not to perform any additional actions
314 * except than write data at given offset. This is no-op in filesystem backend,
315 * but eblob one should disable prepare/commit operations.
317 #define DNET_IO_FLAGS_PLAIN_WRITE (1<<9)
319 /* Do not really send data in range request.
320 * Send only statistics instead.
322 * -- we do not care if it matches above DNET_IO_FLAGS_PLAIN_WRITE,
323 * since using plain write and nodata (read) is useless anyway
325 #define DNET_IO_FLAGS_NODATA (1<<9)
327 struct dnet_io_attr
329 uint8_t parent[DNET_ID_SIZE];
330 uint8_t id[DNET_ID_SIZE];
333 * used in range request as start and number for LIMIT(start, num)
335 * write prepare request uses @num is used as a placeholder
336 * for number of bytes to reserve on disk
338 uint64_t start, num;
339 int type;
340 uint32_t flags;
341 uint64_t offset;
342 uint64_t size;
343 } __attribute__ ((packed));
345 static inline void dnet_convert_io_attr(struct dnet_io_attr *a)
347 a->start = dnet_bswap64(a->start);
348 a->num = dnet_bswap64(a->num);
350 a->flags = dnet_bswap32(a->flags);
351 a->offset = dnet_bswap64(a->offset);
352 a->size = dnet_bswap64(a->size);
355 struct dnet_history_entry
357 uint8_t id[DNET_ID_SIZE];
358 uint32_t flags;
359 uint64_t reserved;
360 uint64_t tsec, tnsec;
361 uint64_t offset;
362 uint64_t size;
363 } __attribute__ ((packed));
366 * Helper structure and set of functions to map history file and perform basic checks.
368 struct dnet_history_map
370 struct dnet_history_entry *ent;
371 long num;
372 ssize_t size;
373 int fd;
376 static inline void dnet_convert_history_entry(struct dnet_history_entry *a)
378 a->flags = dnet_bswap32(a->flags);
379 a->offset = dnet_bswap64(a->offset);
380 a->size = dnet_bswap64(a->size);
381 a->tsec = dnet_bswap64(a->tsec);
382 a->tnsec = dnet_bswap64(a->tnsec);
385 static inline void dnet_setup_history_entry(struct dnet_history_entry *e,
386 unsigned char *id, uint64_t size, uint64_t offset,
387 struct timespec *ts, uint32_t flags)
389 if (!ts) {
390 struct timeval tv;
392 gettimeofday(&tv, NULL);
394 e->tsec = tv.tv_sec;
395 e->tnsec = tv.tv_usec * 1000;
396 } else {
397 e->tsec = ts->tv_sec;
398 e->tnsec = ts->tv_nsec;
401 memcpy(e->id, id, DNET_ID_SIZE);
403 e->size = size;
404 e->offset = offset;
405 e->flags = flags;
406 e->reserved = 0;
408 dnet_convert_history_entry(e);
411 struct dnet_stat
413 /* Load average from the target system multiplied by 100 */
414 uint16_t la[3];
416 uint16_t namemax; /* maximum filename length */
418 uint64_t bsize; /* Block size */
419 uint64_t frsize; /* Fragment size */
420 uint64_t blocks; /* Filesystem size in frsize units */
421 uint64_t bfree; /* # free blocks */
422 uint64_t bavail; /* # free blocks for non-root */
423 uint64_t files; /* # inodes */
424 uint64_t ffree; /* # free inodes */
425 uint64_t favail; /* # free inodes for non-root */
426 uint64_t fsid; /* file system ID */
427 uint64_t flag; /* mount flags */
430 * VM counters in KB (1024) units.
431 * On FreeBSD vm_buffers is used for wire counter.
433 uint64_t vm_active;
434 uint64_t vm_inactive;
435 uint64_t vm_total;
436 uint64_t vm_free;
437 uint64_t vm_cached;
438 uint64_t vm_buffers;
441 * Per node IO statistics will live here.
442 * Reserved for future use.
444 uint64_t reserved[32];
447 static inline void dnet_convert_stat(struct dnet_stat *st)
449 int i;
451 for (i=0; i<3; ++i)
452 st->la[i] = dnet_bswap16(st->la[i]);
454 st->bsize = dnet_bswap64(st->bsize);
455 st->frsize = dnet_bswap64(st->frsize);
456 st->blocks = dnet_bswap64(st->blocks);
457 st->bfree = dnet_bswap64(st->bfree);
458 st->bavail = dnet_bswap64(st->bavail);
459 st->files = dnet_bswap64(st->files);
460 st->ffree = dnet_bswap64(st->ffree);
461 st->favail = dnet_bswap64(st->favail);
462 st->fsid = dnet_bswap64(st->fsid);
463 st->namemax = dnet_bswap16(st->namemax);
465 st->vm_active = dnet_bswap64(st->vm_active);
466 st->vm_inactive = dnet_bswap64(st->vm_inactive);
467 st->vm_total = dnet_bswap64(st->vm_total);
468 st->vm_free = dnet_bswap64(st->vm_free);
469 st->vm_buffers = dnet_bswap64(st->vm_buffers);
470 st->vm_cached = dnet_bswap64(st->vm_cached);
473 struct dnet_io_notification
475 struct dnet_addr_attr addr;
476 struct dnet_io_attr io;
479 static inline void dnet_convert_io_notification(struct dnet_io_notification *n)
481 dnet_convert_addr_attr(&n->addr);
482 dnet_convert_io_attr(&n->io);
485 struct dnet_stat_count
487 uint64_t count;
488 uint64_t err;
491 static inline void dnet_convert_stat_count(struct dnet_stat_count *st, int num)
493 int i;
495 for (i=0; i<num; ++i) {
496 st[i].count = dnet_bswap64(st[i].count);
497 st[i].err = dnet_bswap64(st[i].err);
501 struct dnet_addr_stat
503 struct dnet_addr addr;
504 int num;
505 int cmd_num;
506 struct dnet_stat_count count[0];
507 } __attribute__ ((packed));
509 static inline void dnet_convert_addr_stat(struct dnet_addr_stat *st, int num)
511 st->addr.addr_len = dnet_bswap32(st->addr.addr_len);
512 st->num = dnet_bswap32(st->num);
513 if (!num)
514 num = st->num;
515 st->cmd_num = dnet_bswap32(st->cmd_num);
517 dnet_convert_stat_count(st->count, num);
520 static inline void dnet_stat_inc(struct dnet_stat_count *st, int cmd, int err)
522 if (cmd >= __DNET_CMD_MAX)
523 cmd = DNET_CMD_UNKNOWN;
525 if (!err)
526 st[cmd].count++;
527 else
528 st[cmd].err++;
531 struct dnet_time {
532 uint64_t tsec, tnsec;
535 static inline void dnet_convert_time(struct dnet_time *tm)
537 tm->tsec = dnet_bswap64(tm->tsec);
538 tm->tnsec = dnet_bswap64(tm->tnsec);
541 static inline void dnet_current_time(struct dnet_time *t)
543 struct timeval tv;
545 gettimeofday(&tv, NULL);
547 t->tsec = tv.tv_sec;
548 t->tnsec = tv.tv_usec * 1000;
551 struct dnet_file_info {
552 int flen; /* filename length, which goes after this structure */
553 unsigned char checksum[DNET_CSUM_SIZE];
555 unsigned int nlink;
557 uint64_t mode;
559 uint64_t dev;
560 uint64_t rdev;
562 uint64_t ino;
564 uint64_t uid;
565 uint64_t gid;
567 uint64_t blksize;
568 uint64_t blocks;
570 uint64_t size;
571 uint64_t offset; /* offset within eblob */
573 struct dnet_time atime;
574 struct dnet_time ctime;
575 struct dnet_time mtime;
578 static inline void dnet_convert_file_info(struct dnet_file_info *info)
580 info->flen = dnet_bswap32(info->flen);
581 info->nlink = dnet_bswap32(info->nlink);
583 info->mode = dnet_bswap64(info->mode);
584 info->dev = dnet_bswap64(info->dev);
585 info->ino = dnet_bswap64(info->ino);
586 info->uid = dnet_bswap64(info->uid);
587 info->gid = dnet_bswap64(info->gid);
588 info->blksize = dnet_bswap64(info->blksize);
589 info->blocks = dnet_bswap64(info->blocks);
590 info->rdev = dnet_bswap64(info->rdev);
591 info->size = dnet_bswap64(info->size);
592 info->offset = dnet_bswap64(info->offset);
594 dnet_convert_time(&info->atime);
595 dnet_convert_time(&info->ctime);
596 dnet_convert_time(&info->mtime);
599 static inline void dnet_info_from_stat(struct dnet_file_info *info, struct stat *st)
601 info->nlink = st->st_nlink;
602 info->mode = st->st_mode;
603 info->dev = st->st_dev;
604 info->ino = st->st_ino;
605 info->uid = st->st_uid;
606 info->gid = st->st_gid;
607 info->blksize = st->st_blksize;
608 info->blocks = st->st_blocks;
609 info->rdev = st->st_rdev;
610 info->size = st->st_size;
611 info->offset = 0;
613 info->atime.tsec = st->st_atime;
614 info->ctime.tsec = st->st_ctime;
615 info->mtime.tsec = st->st_mtime;
617 info->atime.tnsec = 0;
618 info->ctime.tnsec = 0;
619 info->mtime.tnsec = 0;
622 /* Elliptics node status - if set, status will be changed */
623 #define DNET_ATTR_STATUS_CHANGE (1<<0)
625 /* Elliptics node should exit */
626 #define DNET_STATUS_EXIT (1<<0)
628 /* Ellipitcs node goes ro/rw */
629 #define DNET_STATUS_RO (1<<1)
631 struct dnet_node_status {
632 int nflags;
633 int status_flags; /* DNET_STATUS_EXIT, DNET_STATUS_RO should be specified here */
634 uint32_t log_mask;
637 static inline void dnet_convert_node_status(struct dnet_node_status *st)
639 st->nflags = dnet_bswap32(st->nflags);
640 st->status_flags = dnet_bswap32(st->status_flags);
641 st->log_mask = dnet_bswap32(st->log_mask);
644 enum cmd_type {
645 DNET_EXEC_SHELL = 0,
646 DNET_EXEC_PYTHON_SCRIPT_NAME,
647 DNET_EXEC_PYTHON,
650 struct dnet_exec {
651 int type;
652 int flags;
653 uint64_t script_size, name_size, binary_size;
654 uint64_t reserved[2];
657 * we pack script name first, then user's script content and then binary data,
658 * which will be pushed into server's object
660 char data[0];
661 } __attribute__((packed));
663 static inline void dnet_convert_exec(struct dnet_exec *e)
665 e->type = dnet_bswap32(e->type);
666 e->script_size = dnet_bswap64(e->script_size);
667 e->name_size = dnet_bswap64(e->name_size);
668 e->binary_size = dnet_bswap64(e->binary_size);
669 e->flags = dnet_bswap32(e->flags);
672 #define DNET_AUTH_COOKIE_SIZE 32
674 struct dnet_auth {
675 char cookie[DNET_AUTH_COOKIE_SIZE];
676 uint64_t flags;
677 uint64_t unused[3];
680 static inline void dnet_convert_auth(struct dnet_auth *a)
682 a->flags = dnet_bswap64(a->flags);
685 enum dnet_meta_types {
686 DNET_META_PARENT_OBJECT = 1, /* parent object name */
687 DNET_META_GROUPS, /* this object has copies in given groups */
688 DNET_META_CHECK_STATUS, /* last checking status: timestamp and so on */
689 DNET_META_NAMESPACE, /* namespace where given object lives */
690 DNET_META_UPDATE, /* last update information (timestamp, flags) */
691 DNET_META_CHECKSUM, /* checksum (sha512) of the whole data object calculated on server */
692 __DNET_META_MAX,
695 struct dnet_meta
697 uint32_t type;
698 uint32_t size;
699 uint64_t common;
700 uint8_t tmp[16];
701 uint8_t data[0];
702 } __attribute__ ((packed));
704 static inline void dnet_convert_meta(struct dnet_meta *m)
706 m->type = dnet_bswap32(m->type);
707 m->size = dnet_bswap32(m->size);
708 m->common = dnet_bswap64(m->common);
711 struct dnet_meta_update {
712 int unused_gap;
713 int group_id;
714 uint64_t flags;
715 struct dnet_time tm;
716 uint64_t reserved[4];
717 } __attribute__((packed));
719 static inline void dnet_convert_meta_update(struct dnet_meta_update *m)
721 dnet_convert_time(&m->tm);
722 m->flags = dnet_bswap64(m->flags);
725 struct dnet_meta_check_status {
726 int status;
727 int pad;
728 struct dnet_time tm;
729 uint64_t reserved[4];
730 } __attribute__ ((packed));
732 static inline void dnet_convert_meta_check_status(struct dnet_meta_check_status *c)
734 c->status = dnet_bswap32(c->status);
735 dnet_convert_time(&c->tm);
738 struct dnet_meta_checksum {
739 uint8_t checksum[DNET_CSUM_SIZE];
740 struct dnet_time tm;
741 } __attribute__ ((packed));
743 static inline void dnet_convert_meta_checksum(struct dnet_meta_checksum *c)
745 dnet_convert_time(&c->tm);
748 #ifdef __cplusplus
750 #endif
752 #endif /* __DNET_PACKET_H */