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