Work to add inode serialization/deserialization routines.
[bluesky.git] / bluesky / bluesky.h
1 /* Blue Sky: File Systems in the Cloud
2  *
3  * Copyright (C) 2009  The Regents of the University of California
4  * Written by Michael Vrable <mvrable@cs.ucsd.edu>
5  *
6  * TODO: Licensing
7  */
8
9 #ifndef _BLUESKY_H
10 #define _BLUESKY_H
11
12 #include <stdint.h>
13 #include <glib.h>
14
15 #ifdef __cplusplus
16 extern "C" {
17 #endif
18
19 struct S3Store;
20
21 /* Reference-counted blocks of memory, used for passing data in and out of
22  * storage backends and in other places. */
23 typedef struct {
24     gint refcount;
25     gchar *data;
26     gsize len;
27 } BlueSkyRCStr;
28
29 BlueSkyRCStr *bluesky_string_new(gpointer data, gsize len);
30 void bluesky_string_ref(BlueSkyRCStr *string);
31 void bluesky_string_unref(BlueSkyRCStr *string);
32 BlueSkyRCStr *bluesky_string_dup(BlueSkyRCStr *string);
33
34 /* Cryptographic operations. */
35 #define CRYPTO_BLOCK_SIZE 16        /* 128-bit AES */
36 #define CRYPTO_KEY_SIZE   16
37
38 void bluesky_crypt_init();
39 void bluesky_crypt_random_bytes(guchar *buf, gint len);
40 BlueSkyRCStr *bluesky_crypt_encrypt(BlueSkyRCStr *in, const uint8_t *key);
41 BlueSkyRCStr *bluesky_crypt_decrypt(BlueSkyRCStr *in, const uint8_t *key);
42
43 /* File types.  The numeric values are chosen to match with those used in
44  * NFSv3. */
45 typedef enum {
46     BLUESKY_REGULAR = 1,
47     BLUESKY_DIRECTORY = 2,
48     BLUESKY_BLOCK = 3,
49     BLUESKY_CHARACTER = 4,
50     BLUESKY_SYMLINK = 5,
51     BLUESKY_SOCKET = 6,
52     BLUESKY_FIFO = 7,
53 } BlueSkyFileType;
54
55 /* Filesystem state.  Each filesystem which is exported is represented by a
56  * single bluesky_fs structure in memory. */
57 typedef struct {
58     GMutex *lock;
59
60     gchar *name;                /* Descriptive name for the filesystem */
61     GHashTable *inodes;         /* Cached inodes */
62     uint64_t next_inum;         /* Next available inode for allocation */
63
64     struct S3Store *store;
65
66     uint8_t *encryption_key;
67 } BlueSkyFS;
68
69 /* Inode number of the root directory. */
70 #define BLUESKY_ROOT_INUM 1
71
72 /* Timestamp, measured in microseconds since the Unix epoch. */
73 typedef int64_t bluesky_time;
74
75 /* In-memory representation of an inode within a Blue Sky server.  This
76  * corresponds roughly with information that is committed to persistent
77  * storage.  Locking/refcounting rules:
78  *   - To access or modify any data fields, the lock must be held.  This
79  *     includes file blocks.
80  *   - One reference is held by the BlueSkyFS inode hash table.  If that is the
81  *     only reference (and the inode is unlocked), the inode is subject to
82  *     dropping from the cache.
83  *   - Any pending operations should hold extra references to the inode as
84  *     appropriate to keep it available until the operation completes.
85  * */
86 typedef struct {
87     GMutex *lock;
88     gint refcount;
89
90     BlueSkyFS *fs;
91
92     BlueSkyFileType type;
93     uint32_t mode;
94     uint32_t uid, gid;
95     uint32_t nlink;
96
97     /* Rather than track an inode number and generation number, we will simply
98      * never re-use a fileid after a file is deleted.  64 bits should be enough
99      * that we don't exhaust the identifier space. */
100     uint64_t inum;
101
102     uint64_t change_count;      /* Incremented each with each change made */
103     int64_t atime;              /* Microseconds since the Unix epoch */
104     int64_t ctime;
105     int64_t mtime;
106     int64_t ntime;              /* "new time": time object was created */
107
108     /* File-specific fields */
109     uint64_t size;
110     GArray *blocks;
111
112     /* Directory-specific fields */
113     GSequence *dirents;         /* List of entries for READDIR */
114     GHashTable *dirhash;        /* Hash table by name for LOOKUP */
115     uint64_t parent_inum;       /* inode for ".."; 0 if the root directory */
116 } BlueSkyInode;
117
118 /* A directory entry.  The name is UTF-8 and is a freshly-allocated string.
119  * Each directory entry is listed in two indices: dirents is indexed by cookie
120  * and dirhash by name.  The cookie is a randomly-assigned 32-bit value, unique
121  * within the directory, that remains unchanged until the entry is deleted.  It
122  * is used to provide a stable key for restarting a READDIR call. */
123 typedef struct {
124     gchar *name;
125     uint32_t cookie;
126     uint64_t inum;
127 } BlueSkyDirent;
128
129 /* File data is divided into fixed-size blocks (except the last block which may
130  * be short?).  These blocks are backed by storage in a key/value store, but
131  * may also be dirty if modifications have been made in-memory that have not
132  * been committed. */
133 #define BLUESKY_BLOCK_SIZE 32768ULL
134 #define BLUESKY_MAX_FILE_SIZE (BLUESKY_BLOCK_SIZE << 24)
135 typedef enum {
136     BLUESKY_BLOCK_ZERO = 0,     /* Data is all zeroes, not explicitly stored */
137     BLUESKY_BLOCK_REF = 1,      /* Reference to key/value store, not cached */
138     BLUESKY_BLOCK_CACHED = 2,   /* Data is cached in memory, clean */
139     BLUESKY_BLOCK_DIRTY = 3,    /* Data needs to be committed to store */
140 } BlueSkyBlockType;
141
142 typedef struct {
143     BlueSkyBlockType type;
144     gchar *ref;                 /* Name of data block in the backing store */
145     BlueSkyRCStr *data;         /* Pointer to data in memory if cached */
146 } BlueSkyBlock;
147
148 BlueSkyFS *bluesky_new_fs(gchar *name);
149 int64_t bluesky_get_current_time();
150 void bluesky_inode_update_ctime(BlueSkyInode *inode, gboolean update_mtime);
151 uint64_t bluesky_fs_alloc_inode(BlueSkyFS *fs);
152 BlueSkyInode *bluesky_new_inode(uint64_t inum, BlueSkyFS *fs, BlueSkyFileType type);
153
154 BlueSkyInode *bluesky_get_inode(BlueSkyFS *fs, uint64_t inum);
155 void bluesky_insert_inode(BlueSkyFS *fs, BlueSkyInode *inode);
156
157 void bluesky_dirent_destroy(gpointer dirent);
158 uint64_t bluesky_directory_hash(gchar *name);
159 uint64_t bluesky_directory_lookup(BlueSkyInode *inode, gchar *name);
160 gboolean bluesky_directory_insert(BlueSkyInode *dir, gchar *name,
161                                   uint64_t inum);
162 void bluesky_directory_dump(BlueSkyInode *dir);
163
164 void bluesky_block_touch(BlueSkyInode *inode, uint64_t i);
165 void bluesky_block_fetch(BlueSkyFS *fs, BlueSkyBlock *block);
166 void bluesky_block_flush(BlueSkyFS *fs, BlueSkyBlock *block);
167 void bluesky_file_truncate(BlueSkyInode *inode, uint64_t size);
168 void bluesky_file_write(BlueSkyInode *inode, uint64_t offset,
169                         const char *data, gint len);
170 void bluesky_file_read(BlueSkyInode *inode, uint64_t offset,
171                        char *buf, gint len);
172
173 struct S3Store *s3store_new();
174 BlueSkyRCStr *s3store_get(struct S3Store *store, const gchar *key);
175 void s3store_put(struct S3Store *store, const gchar *key, BlueSkyRCStr *val);
176
177 #ifdef __cplusplus
178 }
179 #endif
180
181 #endif