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