aboutsummaryrefslogtreecommitdiffstats
path: root/dbfs.h
blob: 94606ad93639a3e909bde50ec5b0ddb7e2c0b587 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
#ifndef __DBFS_H__
#define __DBFS_H__

/*
 * Maintained by Jeff Garzik <jgarzik@pobox.com>
 *
 * Copyright 2006-2007 Red Hat, Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; see the file COPYING.  If not, write to
 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

#include <glib.h>

#define ALIGN(x,a) (((x)+(a)-1)&~((a)-1))

enum {
	DBFS_BLK_ID_LEN		= 20,		/* block id (sha1 hash) len */

	DBFS_UNLINK_DIR		= (1 << 0),

	DBFS_ROOT_INO		= 1,		/* root inode number */

	DBFS_DIRENT_ALIGN	= 8,	/* struct dbfs_dirent alignment */

	DBFS_FILENAME_MAX	= 256,	/* max filename component size */

	DBFS_XATTR_NAME_LEN	= 256,	/* extended attr limits */
	DBFS_XATTR_MAX_LEN	= (1024 * 1024),

	DBFS_XLIST_ALIGN	= 8,	/* struct dbfs_xlist alignment */

	/* our data items are small, so use the smallest possible page
	 * size.  This is a guess, and should be verified by looking at
	 * overflow pages and other DB statistics.
	 */
	DBFS_PGSZ_METADATA	= 512,

	/* another guess.  must take into account small data items
	 * as well as large ones
	 */
	DBFS_PGSZ_DATA		= 2048,

	DBFS_MAX_EXT_LEN	= (4 * 1024 * 1024),	/* max extent len */

	DBFS_ZERO_CMP_BLK_SZ	= 8192,
};

enum {
	/* dirent magic number */
	DBFS_DE_MAGIC		= 0xd4d4d4d4U,
};

enum dbfs_inode_type {
	IT_REG,
	IT_DIR,
	IT_DEV,
	IT_FIFO,
	IT_SYMLINK,
	IT_SOCKET
};

typedef struct {
	char		buf[DBFS_BLK_ID_LEN];
} dbfs_blk_id_t;

struct dbfs_dirent {
	guint32		magic;
	guint16		res2;
	guint16		namelen;
	guint64		ino;
	char		name[0];
} __attribute__ ((packed));

struct dbfs_xlist {
	guint32		namelen;
	char		name[0];
} __attribute__ ((packed));

struct dbfs_extent {
	guint32			off;		/* offset into block */
	guint32			len;		/* length of fragment */
	dbfs_blk_id_t		id;		/* block id */
} __attribute__ ((packed));

struct dbfs_hashref {
	guint32			refs;
} __attribute__ ((packed));

struct dbfs_raw_inode {
	guint64		ino;
	guint64		version;
	guint32		mode;
	guint32		nlink;
	guint32		uid;
	guint32		gid;
	guint64		rdev;
	guint64		size;
	guint64		ctime;
	guint64		atime;
	guint64		mtime;
	struct dbfs_extent blocks[0];
} __attribute__ ((packed));

struct dbfs_inode {
	enum dbfs_inode_type	type;
	unsigned int		n_extents;
	unsigned int		raw_ino_size;
	struct dbfs_raw_inode	*raw_inode;
};

struct dbfs {
	const char		*home;
	char			*passwd;

	DB_ENV			*env;
	DB			*meta;
	DB			*data;
	DB			*hashref;

	guint64			next_inode;
};

extern int debugging;


typedef int (*dbfs_dir_actor_t) (struct dbfs_dirent *, void *);

/* dbfs-backend.c */
extern int dbmeta_del(DB_TXN *txn, const char *key_str);
extern int dbfs_inode_read(DB_TXN *txn, guint64 ino_n, struct dbfs_inode **ino_out);
extern int dbfs_dir_read(DB_TXN *txn, guint64 ino, DBT *val);
extern int dbfs_symlink_read(DB_TXN *txn, guint64 ino, DBT *val);
extern int dbfs_dir_foreach(void *dir, dbfs_dir_actor_t func, void *userdata);
extern int dbfs_dir_lookup(DB_TXN *txn, guint64 parent, const char *name, guint64 *ino);
extern int dbfs_link(DB_TXN *txn, struct dbfs_inode *ino, guint64 ino_n, guint64 parent, const char *name);
extern int dbfs_unlink(DB_TXN *txn, guint64 parent, const char *name, unsigned long flags);
extern void dbfs_init(void *userdata);
extern void dbfs_exit(void *userdata);
extern int dbfs_mknod(DB_TXN *txn, guint64 parent, const char *name,
		      guint32 mode, guint64 rdev,
		      struct dbfs_inode **ino);
extern int dbfs_symlink_write(DB_TXN *txn, guint64 ino, const char *link);
extern int dbfs_inode_del(DB_TXN *txn, const struct dbfs_inode *ino);
extern int dbfs_xattr_get(DB_TXN *TXN, guint64 ino_n, const char *name,
			  void **buf_out, size_t *buflen_out);
extern int dbfs_xattr_set(DB_TXN *TXN, guint64 ino_n, const char *name,
			  const void *buf, size_t buflen,
			  int flags);
extern int dbfs_xattr_remove(DB_TXN *TXN, guint64, const char *, gboolean);
extern int dbfs_xattr_list(DB_TXN *TXN, guint64 ino, void **buf_out, size_t *buflen_out);
extern int dbfs_read(DB_TXN *, guint64, guint64, size_t, void **);
extern int dbfs_write(DB_TXN *, guint64, guint64, const void *, size_t);
extern int dbfs_inode_resize(DB_TXN *txn, struct dbfs_inode *ino, guint64 new_size);
extern int dbfs_rename(DB_TXN *txn, guint64, const char *, guint64, const char *);

/* libdbfs.c */
extern int dbfs_open(struct dbfs *, unsigned int, unsigned int, const char *,
		     gboolean syslog);
extern void dbfs_close(struct dbfs *fs);
extern struct dbfs *dbfs_new(void);
extern void dbfs_free(struct dbfs *fs);
extern struct dbfs *gfs;
extern int dbfs_inode_write(DB_TXN *txn, struct dbfs_inode *ino);
extern int dbfs_dir_new(DB_TXN *txn, guint64 parent, guint64 ino_n, const struct dbfs_inode *ino);
extern int dbfs_dir_write(DB_TXN *txn, guint64 ino, DBT *val);
extern void dbfs_inode_free(struct dbfs_inode *ino);

static inline size_t dbfs_dirent_next(guint16 namelen)
{
	return ALIGN(sizeof(struct dbfs_dirent) + namelen, DBFS_DIRENT_ALIGN);
}

static inline size_t dbfs_xlist_next(guint16 namelen)
{
	return ALIGN(sizeof(struct dbfs_xlist) + namelen, DBFS_XLIST_ALIGN);
}

#endif /* __DBFS_H__ */