├── .gitignore ├── Makefile ├── README.md ├── dmap-connection.c ├── dmap-connection.h ├── dmap-const.h ├── dmap-core.c ├── dmap-handler.c ├── dmap-handler.h ├── dmap-hash.c ├── dmap-hash.h ├── dmap-helpers.c ├── dmap-helpers.h ├── dmap-malloc.h ├── dmap-neighbor.c ├── dmap-neighbor.h ├── dmap-server.c ├── dmap-server.h ├── dmap-sha256.c ├── dmap-sha256.h ├── dmap-sysfs.c ├── dmap-sysfs.h ├── dmap-trace-helpers.h ├── dmap-trace.c ├── dmap-trace.h ├── dmap.h ├── ksocket.c ├── ksocket.h ├── malloc-checker.c ├── malloc-checker.h └── scripts ├── cluster.py ├── cmd.py ├── cmp_files.sh ├── ssh.py ├── start.sh ├── stop.sh └── test.sh /.gitignore: -------------------------------------------------------------------------------- 1 | temp/ 2 | .tmp_versions/ 3 | *.ko 4 | *.cmd 5 | *.o 6 | *.mod.c 7 | *.symvers 8 | *.order 9 | *.patch 10 | *.swp 11 | *.out 12 | *.pyc 13 | tags 14 | dmap-client 15 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CURRDIR = $(shell pwd) 2 | KERNEL_BUILD_PATH=/lib/modules/$(shell uname -r)/build 3 | 4 | DMAP_MOD = dmap 5 | DMAP_MOD_KO = $(DMAP_MOD).ko 6 | 7 | dmap-y += dmap-core.o dmap-sysfs.o dmap-connection.o ksocket.o \ 8 | dmap-trace.o malloc-checker.o dmap-helpers.o \ 9 | dmap-server.o dmap-neighbor.o dmap-sha256.o \ 10 | dmap-handler.o dmap-hash.o 11 | 12 | obj-m = $(DMAP_MOD).o 13 | 14 | KBUILD_EXTRA_SYMBOLS = $(KERNEL_BUILD_PATH)/Module.symvers 15 | 16 | ccflags-y := -I$(src) -g3 \ 17 | -D __MALLOC_CHECKER__ \ 18 | -D __MALLOC_CHECKER_STACK_TRACE__ \ 19 | -D __MALLOC_CHECKER_FILL_CC__ \ 20 | 21 | all: 22 | $(MAKE) -C $(KERNEL_BUILD_PATH) M=$(CURRDIR) modules 23 | clean: 24 | $(MAKE) -C $(KERNEL_BUILD_PATH) M=$(CURRDIR) clean 25 | rm -f *.o 26 | rm -rf temp/ 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### dmap - distributed key-value memory cache 2 | 3 | #### Client: 4 | [go client](https://github.com/irqlevel/dmap-client-go) 5 | 6 | #### Build: 7 | ```sh 8 | $ make 9 | ``` 10 | 11 | #### Install: 12 | ```sh 13 | $ sudo insmod dmap.ko #load kernel module on each node in cluster 14 | 15 | $ echo hostname port | sudo tee /sys/fs/dmap/start_server #start server on each node in cluster 16 | 17 | $ echo hostname port | sudo tee /sys/fs/dmap/add_neighbor #add node into cluster 18 | 19 | $ cat /sys/fs/dmap/id #query node UID 20 | 21 | $ cat /sys/fs/dmap/neighbors #query nodes in cluster 22 | ``` 23 | 24 | #### Usage: 25 | ```sh 26 | $ ./dmap-client hostname:port set key value #add key-value 27 | 28 | $ ./dmap-client hostname:port get key #query value by key 29 | 30 | $ ./dmap-client hostname:port upd key value #update key value 31 | 32 | $ ./dmap-client hostname:port cmpxchg key exchange comparand #compare exchange key value 33 | 34 | $ ./dmap-client hostname:port del key #delete key 35 | ``` 36 | 37 | #### Uninstall: 38 | ```sh 39 | $ rmmod dmap #unload dmap on each node in cluster 40 | ``` 41 | -------------------------------------------------------------------------------- /dmap-connection.c: -------------------------------------------------------------------------------- 1 | #include "dmap-connection.h" 2 | #include "ksocket.h" 3 | #include "dmap-trace-helpers.h" 4 | #include "dmap-malloc.h" 5 | 6 | #include 7 | 8 | int dmap_con_init(struct dmap_connection *con) 9 | { 10 | memset(con, 0, sizeof(*con)); 11 | mutex_init(&con->mutex); 12 | 13 | return 0; 14 | } 15 | 16 | void dmap_con_deinit(struct dmap_connection *con) 17 | { 18 | dmap_con_close(con); 19 | } 20 | 21 | int dmap_con_connect(struct dmap_connection *con, char *host, u16 port) 22 | { 23 | int r; 24 | struct socket *sock; 25 | 26 | mutex_lock(&con->mutex); 27 | if (con->sock) { 28 | r = -EEXIST; 29 | goto unlock; 30 | } 31 | 32 | r = ksock_connect_host(&sock, host, port); 33 | if (r) { 34 | TRACE_ERR(r, "connect failed"); 35 | goto unlock; 36 | } 37 | 38 | r = ksock_set_nodelay(sock, true); 39 | if (r) { 40 | TRACE_ERR(r, "set no delay failed"); 41 | goto release_sock; 42 | } 43 | 44 | snprintf(con->host, ARRAY_SIZE(con->host), "%s", host); 45 | con->port = port; 46 | con->sock = sock; 47 | 48 | r = 0; 49 | goto unlock; 50 | 51 | release_sock: 52 | ksock_release(sock); 53 | unlock: 54 | mutex_unlock(&con->mutex); 55 | return r; 56 | } 57 | 58 | int dmap_con_set_socket(struct dmap_connection *con, struct socket *sock) 59 | { 60 | int r; 61 | 62 | mutex_lock(&con->mutex); 63 | if (con->sock) { 64 | r = -EEXIST; 65 | goto unlock; 66 | } 67 | 68 | con->sock = sock; 69 | r = 0; 70 | unlock: 71 | mutex_unlock(&con->mutex); 72 | return r; 73 | } 74 | 75 | int dmap_con_close(struct dmap_connection *con) 76 | { 77 | mutex_lock(&con->mutex); 78 | if (con->sock) { 79 | ksock_release(con->sock); 80 | con->sock = NULL; 81 | con->host[0] = '\0'; 82 | con->port = 0; 83 | } 84 | mutex_unlock(&con->mutex); 85 | return 0; 86 | } 87 | 88 | int dmap_con_send(struct dmap_connection *con, u32 type, u32 len, 89 | u32 result, struct dmap_packet *packet) 90 | { 91 | int r; 92 | 93 | mutex_lock(&con->mutex); 94 | if (!con->sock) { 95 | r = -EBADF; 96 | goto unlock; 97 | } 98 | 99 | if (len > sizeof(packet->body)) { 100 | r = -EINVAL; 101 | goto unlock; 102 | } 103 | 104 | packet->header.magic = cpu_to_le32(DMAP_PACKET_MAGIC); 105 | packet->header.len = cpu_to_le32(len); 106 | packet->header.type = cpu_to_le32(type); 107 | packet->header.result = cpu_to_le32(result); 108 | 109 | r = ksock_send(con->sock, packet, sizeof(packet->header) + len); 110 | if (r < 0) 111 | goto unlock; 112 | 113 | if (r != (sizeof(packet->header) + len)) { 114 | r = -EIO; 115 | goto unlock; 116 | } 117 | 118 | r = 0; 119 | 120 | unlock: 121 | mutex_unlock(&con->mutex); 122 | return r; 123 | } 124 | 125 | int dmap_con_recv(struct dmap_connection *con, struct dmap_packet *packet, 126 | u32 *type, u32 *len, u32 *result) 127 | { 128 | int r; 129 | u32 magic, ltype, llen, lresult; 130 | 131 | mutex_lock(&con->mutex); 132 | if (!con->sock) { 133 | r = -EBADF; 134 | goto unlock; 135 | } 136 | 137 | r = ksock_recv(con->sock, &packet->header, sizeof(packet->header)); 138 | if (r < 0) 139 | goto unlock; 140 | 141 | if (r != sizeof(packet->header)) { 142 | r = -EIO; 143 | goto unlock; 144 | } 145 | 146 | magic = le32_to_cpu(packet->header.magic); 147 | ltype = le32_to_cpu(packet->header.type); 148 | llen = le32_to_cpu(packet->header.len); 149 | lresult = le32_to_cpu(packet->header.result); 150 | 151 | if (magic != DMAP_PACKET_MAGIC) { 152 | r = -EBADF; 153 | goto unlock; 154 | } 155 | 156 | if (llen > sizeof(packet->body)) { 157 | r = -EBADF; 158 | goto unlock; 159 | } 160 | 161 | r = ksock_recv(con->sock, packet->body, llen); 162 | if (r < 0) 163 | goto unlock; 164 | 165 | if (r != llen) { 166 | r = -EIO; 167 | goto unlock; 168 | } 169 | 170 | *type = ltype; 171 | *len = llen; 172 | *result = lresult; 173 | r = 0; 174 | 175 | unlock: 176 | mutex_unlock(&con->mutex); 177 | return r; 178 | } 179 | 180 | int dmap_con_recv_check(struct dmap_connection *con, struct dmap_packet *packet, 181 | u32 type, u32 len) 182 | { 183 | u32 ltype, llen, lresult; 184 | int r; 185 | 186 | r = dmap_con_recv(con, packet, <ype, &llen, &lresult); 187 | if (r) 188 | return r; 189 | 190 | if (llen != len) 191 | return -EBADF; 192 | 193 | if (ltype != type) 194 | return -EBADF; 195 | 196 | return lresult; 197 | } 198 | -------------------------------------------------------------------------------- /dmap-connection.h: -------------------------------------------------------------------------------- 1 | #ifndef __DMAP_CONNECTION_H__ 2 | #define __DMAP_CONNECTION_H__ 3 | 4 | #include "dmap-const.h" 5 | #include 6 | 7 | #define DMAP_PACKET_MAGIC 0xCBEECBEE 8 | 9 | #define DMAP_PACKET_BODY_SIZE 65520 10 | 11 | #define DMAP_PACKET_HELLO 1 12 | #define DMAP_PACKET_PING 2 13 | #define DMAP_PACKET_BYE 3 14 | #define DMAP_PACKET_SET_KEY 4 15 | #define DMAP_PACKET_GET_KEY 5 16 | #define DMAP_PACKET_DEL_KEY 6 17 | #define DMAP_PACKET_UPD_KEY 7 18 | #define DMAP_PACKET_CMPXCHG_KEY 8 19 | 20 | struct dmap_packet_header { 21 | __le32 magic; 22 | __le32 type; 23 | __le32 len; 24 | __le32 result; 25 | }; 26 | 27 | struct dmap_packet { 28 | struct dmap_packet_header header; 29 | unsigned char body[DMAP_PACKET_BODY_SIZE]; 30 | }; 31 | 32 | struct dmap_req_set_key { 33 | unsigned char key[DMAP_KEY_SIZE]; 34 | unsigned char value[DMAP_VALUE_SIZE]; 35 | }; 36 | 37 | struct dmap_resp_set_key { 38 | __le64 padding; 39 | }; 40 | 41 | struct dmap_req_get_key { 42 | unsigned char key[DMAP_KEY_SIZE]; 43 | }; 44 | 45 | struct dmap_resp_get_key { 46 | unsigned char value[DMAP_VALUE_SIZE]; 47 | }; 48 | 49 | struct dmap_req_del_key { 50 | unsigned char key[DMAP_KEY_SIZE]; 51 | }; 52 | 53 | struct dmap_resp_del_key { 54 | __le64 padding; 55 | }; 56 | 57 | struct dmap_req_upd_key { 58 | unsigned char key[DMAP_KEY_SIZE]; 59 | unsigned char value[DMAP_VALUE_SIZE]; 60 | }; 61 | 62 | struct dmap_resp_upd_key { 63 | __le64 padding; 64 | }; 65 | 66 | struct dmap_req_cmpxchg_key { 67 | unsigned char key[DMAP_KEY_SIZE]; 68 | unsigned char exchange[DMAP_VALUE_SIZE]; 69 | unsigned char comparand[DMAP_VALUE_SIZE]; 70 | }; 71 | 72 | struct dmap_resp_cmpxchg_key { 73 | unsigned char value[DMAP_VALUE_SIZE]; 74 | }; 75 | 76 | struct dmap_req_hello { 77 | struct dmap_address source; 78 | }; 79 | 80 | struct dmap_resp_hello { 81 | struct dmap_address addr; 82 | }; 83 | 84 | struct dmap_req_ping { 85 | struct dmap_address source; 86 | }; 87 | 88 | struct dmap_resp_ping { 89 | __le64 padding; 90 | }; 91 | 92 | struct dmap_req_bye { 93 | struct dmap_address source; 94 | }; 95 | 96 | struct dmap_resp_bye { 97 | __le64 padding; 98 | }; 99 | 100 | struct dmap_connection { 101 | struct mutex mutex; 102 | struct socket *sock; 103 | char host[DMAP_HOST_SIZE]; 104 | int port; 105 | }; 106 | 107 | int dmap_con_init(struct dmap_connection *con); 108 | 109 | void dmap_con_deinit(struct dmap_connection *con); 110 | 111 | int dmap_con_connect(struct dmap_connection *con, char *host, u16 port); 112 | 113 | int dmap_con_set_socket(struct dmap_connection *con, struct socket *sock); 114 | 115 | int dmap_con_close(struct dmap_connection *con); 116 | 117 | int dmap_con_send(struct dmap_connection *con, u32 type, u32 len, 118 | u32 result, struct dmap_packet *packet); 119 | 120 | int dmap_con_recv(struct dmap_connection *con, struct dmap_packet *packet, 121 | u32 *type, u32 *len, u32 *result); 122 | 123 | int dmap_con_recv_check(struct dmap_connection *con, struct dmap_packet *packet, 124 | u32 type, u32 len); 125 | 126 | #endif 127 | -------------------------------------------------------------------------------- /dmap-const.h: -------------------------------------------------------------------------------- 1 | #ifndef __DMAP_CONST_H__ 2 | #define __DMAP_CONST_H__ 3 | 4 | #include 5 | 6 | #define DMAP_TIMER_MS 100 7 | 8 | #define DMAP_KEY_SIZE 16 9 | #define DMAP_KEY_HEX_SIZE (2 * DMAP_KEY_SIZE + 1) 10 | 11 | #define DMAP_ID_SIZE 32 12 | #define DMAP_VALUE_SIZE 4096 13 | #define DMAP_HOST_SIZE 64 14 | 15 | #define DMAP_PARAM_SIZE 64 16 | #define DMAP_PARAM_FMT "%63s" 17 | 18 | struct dmap_address { 19 | char host[DMAP_HOST_SIZE]; 20 | unsigned char id[DMAP_ID_SIZE]; 21 | char id_str[2 * DMAP_ID_SIZE + 1]; 22 | int port; 23 | }; 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /dmap-core.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "malloc-checker.h" 20 | #include "dmap.h" 21 | #include "dmap-sysfs.h" 22 | #include "dmap-connection.h" 23 | #include "dmap-trace-helpers.h" 24 | #include "dmap-helpers.h" 25 | #include "dmap-malloc.h" 26 | #include "dmap-neighbor.h" 27 | 28 | static struct dmap global_dmap; 29 | 30 | static void dmap_ping_worker(struct work_struct *work) 31 | { 32 | struct dmap_neighbor *curr; 33 | struct dmap *map; 34 | 35 | map = container_of(work, struct dmap, ping_work); 36 | 37 | down_read(&map->rw_sem); 38 | list_for_each_entry(curr, &map->neighbor_list, list) { 39 | dmap_neighbor_ping(curr); 40 | } 41 | up_read(&map->rw_sem); 42 | } 43 | 44 | static enum hrtimer_restart dmap_timer_callback(struct hrtimer *timer) 45 | { 46 | struct dmap *map; 47 | 48 | map = container_of(timer, struct dmap, timer); 49 | queue_work(map->wq, &map->ping_work); 50 | 51 | hrtimer_start(&map->timer, ktime_add_ms(ktime_get(), DMAP_TIMER_MS), 52 | HRTIMER_MODE_ABS); 53 | 54 | return HRTIMER_NORESTART; 55 | } 56 | 57 | static int dmap_init(struct dmap *map) 58 | { 59 | int r; 60 | 61 | init_rwsem(&map->rw_sem); 62 | INIT_LIST_HEAD(&map->neighbor_list); 63 | map->neighbor_tree = RB_ROOT; 64 | 65 | dmap_hash_init(&map->hash); 66 | 67 | get_random_bytes(map->id, sizeof(map->id)); 68 | 69 | dmap_bytes_to_hex(map->id, ARRAY_SIZE(map->id), 70 | map->id_str, ARRAY_SIZE(map->id_str)); 71 | 72 | hrtimer_init(&map->timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); 73 | map->timer.function = dmap_timer_callback; 74 | 75 | INIT_WORK(&map->ping_work, dmap_ping_worker); 76 | map->wq = alloc_workqueue("dmap-wq", WQ_MEM_RECLAIM, 0); 77 | if (!map->wq) { 78 | r = -ENOMEM; 79 | goto out; 80 | } 81 | 82 | r = dmap_server_init(&map->server); 83 | if (r) 84 | goto del_wq; 85 | 86 | r = dmap_sysfs_init(&map->kobj_holder, fs_kobj, &dmap_ktype, 87 | "%s", "dmap"); 88 | if (r) 89 | goto deinit_server; 90 | 91 | hrtimer_start(&map->timer, ktime_add_ms(ktime_get(), DMAP_TIMER_MS), 92 | HRTIMER_MODE_ABS); 93 | 94 | return 0; 95 | 96 | deinit_server: 97 | dmap_server_deinit(&map->server); 98 | del_wq: 99 | destroy_workqueue(map->wq); 100 | out: 101 | return r; 102 | } 103 | 104 | static void dmap_deinit(struct dmap *map) 105 | { 106 | struct dmap_neighbor *curr, *tmp; 107 | 108 | hrtimer_cancel(&map->timer); 109 | destroy_workqueue(map->wq); 110 | 111 | dmap_sysfs_deinit(&map->kobj_holder); 112 | dmap_server_deinit(&map->server); 113 | 114 | down_write(&map->rw_sem); 115 | list_for_each_entry_safe(curr, tmp, &map->neighbor_list, list) { 116 | list_del_init(&curr->list); 117 | rb_erase(&curr->rb_link, &map->neighbor_tree); 118 | dmap_neighbor_bye(curr); 119 | dmap_neighbor_put(curr); 120 | } 121 | up_write(&map->rw_sem); 122 | 123 | dmap_hash_deinit(&map->hash); 124 | } 125 | 126 | static struct dmap *get_dmap(void) 127 | { 128 | return &global_dmap; 129 | } 130 | 131 | static bool __dmap_insert_neighbor(struct dmap *map, 132 | struct dmap_neighbor *neighbor) 133 | { 134 | struct dmap_neighbor *curr; 135 | struct rb_node **p; 136 | struct rb_node *parent; 137 | int cmp; 138 | bool exist; 139 | 140 | exist = false; 141 | parent = NULL; 142 | p = &map->neighbor_tree.rb_node; 143 | while (*p) { 144 | parent = *p; 145 | curr = rb_entry(parent, struct dmap_neighbor, rb_link); 146 | cmp = memcmp(neighbor->addr.id, curr->addr.id, 147 | sizeof(neighbor->addr.id)); 148 | if (cmp < 0) 149 | p = &(*p)->rb_left; 150 | else if (cmp > 0) 151 | p = &(*p)->rb_right; 152 | else { 153 | exist = true; 154 | break; 155 | } 156 | } 157 | if (!exist) { 158 | rb_link_node(&neighbor->rb_link, parent, p); 159 | rb_insert_color(&neighbor->rb_link, &map->neighbor_tree); 160 | } 161 | 162 | return (exist) ? false : true; 163 | } 164 | 165 | int dmap_add_neighbor(struct dmap *map, struct dmap_address *addr, bool hello) 166 | { 167 | struct dmap_neighbor *new, *curr; 168 | int r; 169 | 170 | new = dmap_neighbor_create(map, addr->host, addr->port); 171 | if (!new) 172 | return -ENOMEM; 173 | 174 | if (hello) { 175 | memcpy(new->addr.id, addr->id, sizeof(new->addr.id)); 176 | memcpy(new->addr.id_str, addr->id_str, 177 | sizeof(new->addr.id_str)); 178 | } 179 | 180 | down_write(&map->rw_sem); 181 | r = 0; 182 | list_for_each_entry(curr, &map->neighbor_list, list) { 183 | if (strncmp(curr->addr.host, new->addr.host, 184 | strlen(curr->addr.host) + 1) == 0) { 185 | r = -EEXIST; 186 | goto unlock; 187 | } 188 | if (hello && memcmp(curr->addr.id, new->addr.id, 189 | sizeof(curr->addr.id)) == 0) { 190 | r = -EEXIST; 191 | goto unlock; 192 | } 193 | } 194 | 195 | if (!hello) 196 | r = dmap_neighbor_hello(new); 197 | else { 198 | mutex_lock(&new->mutex); 199 | dmap_neighbor_set_state(new, DMAP_NEIGHBOR_S_HELLO); 200 | mutex_unlock(&new->mutex); 201 | } 202 | 203 | if (!r) { 204 | if (__dmap_insert_neighbor(map, new)) { 205 | dmap_neighbor_get(new); 206 | list_add_tail(&new->list, &map->neighbor_list); 207 | } else 208 | r = -EEXIST; 209 | } 210 | 211 | unlock: 212 | up_write(&map->rw_sem); 213 | dmap_neighbor_put(new); 214 | 215 | return r; 216 | } 217 | 218 | struct dmap_neighbor *dmap_lookup_neighbor(struct dmap *map, 219 | struct dmap_address *addr) 220 | { 221 | struct dmap_neighbor *curr; 222 | struct dmap_neighbor *found = NULL; 223 | struct rb_node *n; 224 | int cmp; 225 | 226 | down_read(&map->rw_sem); 227 | n = map->neighbor_tree.rb_node; 228 | while (n) { 229 | curr = rb_entry(n, struct dmap_neighbor, rb_link); 230 | cmp = memcmp(addr->id, curr->addr.id, sizeof(addr->id)); 231 | if (cmp < 0) 232 | n = n->rb_left; 233 | else if (cmp > 0) 234 | n = n->rb_right; 235 | else { 236 | found = curr; 237 | dmap_neighbor_get(found); 238 | break; 239 | } 240 | } 241 | up_read(&map->rw_sem); 242 | return found; 243 | } 244 | 245 | struct dmap_neighbor *dmap_select_neighbor(struct dmap *map, 246 | unsigned char id[DMAP_ID_SIZE]) 247 | { 248 | struct dmap_neighbor *curr; 249 | struct dmap_neighbor *found = NULL; 250 | struct rb_node *n; 251 | 252 | down_read(&map->rw_sem); 253 | for (n = rb_first(&map->neighbor_tree); n != NULL; n = rb_next(n)) { 254 | curr = rb_entry(n, struct dmap_neighbor, rb_link); 255 | if (memcmp(id, curr->addr.id, sizeof(*id)) < 0) { 256 | found = curr; 257 | break; 258 | } 259 | } 260 | 261 | if (found == NULL) { 262 | n = rb_first(&map->neighbor_tree); 263 | if (n) 264 | found = rb_entry(n, struct dmap_neighbor, rb_link); 265 | } 266 | 267 | up_read(&map->rw_sem); 268 | return found; 269 | } 270 | 271 | bool dmap_is_self_neighbor(struct dmap *map, struct dmap_neighbor *neighbor) 272 | { 273 | if (memcmp(map->id, neighbor->addr.id, sizeof(map->id)) == 0) 274 | return true; 275 | return false; 276 | } 277 | 278 | int dmap_remove_neighbor(struct dmap *map, char *host) 279 | { 280 | struct dmap_neighbor *found, *curr, *tmp; 281 | 282 | found = NULL; 283 | down_write(&map->rw_sem); 284 | list_for_each_entry_safe(curr, tmp, &map->neighbor_list, list) { 285 | if (strncmp(curr->addr.host, host, 286 | strlen(curr->addr.host) + 1) == 0) { 287 | found = curr; 288 | rb_erase(&found->rb_link, &map->neighbor_tree); 289 | list_del_init(&found->list); 290 | break; 291 | } 292 | } 293 | up_write(&map->rw_sem); 294 | 295 | if (found) { 296 | dmap_neighbor_bye(found); 297 | dmap_neighbor_put(found); 298 | } 299 | 300 | return (found) ? 0 : -ENOTTY; 301 | } 302 | 303 | int dmap_erase_neighbor(struct dmap *map, struct dmap_neighbor *victim) 304 | { 305 | struct dmap_neighbor *curr, *tmp, *found; 306 | 307 | found = NULL; 308 | down_write(&map->rw_sem); 309 | list_for_each_entry_safe(curr, tmp, &map->neighbor_list, list) { 310 | if (curr == victim) { 311 | rb_erase(&curr->rb_link, &map->neighbor_tree); 312 | list_del_init(&curr->list); 313 | found = curr; 314 | break; 315 | } 316 | } 317 | up_write(&map->rw_sem); 318 | 319 | if (found) 320 | dmap_neighbor_put(found); 321 | 322 | return (found) ? 0 : -ENOTTY; 323 | } 324 | 325 | void dmap_addr_init(struct dmap_address *addr, char *host, int port, 326 | unsigned char id[DMAP_ID_SIZE]) 327 | { 328 | snprintf(addr->host, ARRAY_SIZE(addr->host), "%s", host); 329 | addr->port = port; 330 | 331 | memcpy(addr->id, id, sizeof(addr->id)); 332 | 333 | dmap_bytes_to_hex(addr->id, ARRAY_SIZE(addr->id), 334 | addr->id_str, ARRAY_SIZE(addr->id_str)); 335 | } 336 | 337 | void dmap_get_address(struct dmap *map, struct dmap_address *addr) 338 | { 339 | dmap_addr_init(addr, map->server.host, map->server.port, map->id); 340 | } 341 | 342 | int dmap_check_address(struct dmap_address *addr) 343 | { 344 | if (addr->host[ARRAY_SIZE(addr->host) - 1] != '\0') 345 | return -EINVAL; 346 | if (addr->id_str[ARRAY_SIZE(addr->id_str) - 1] != '\0') 347 | return -EINVAL; 348 | 349 | return 0; 350 | } 351 | 352 | void *dmap_kzalloc(size_t size, gfp_t flags) 353 | { 354 | #ifdef __MALLOC_CHECKER__ 355 | void *ptr; 356 | 357 | ptr = dmap_kmalloc(size, flags); 358 | if (ptr) 359 | memset(ptr, 0, size); 360 | 361 | return ptr; 362 | #else 363 | return kzalloc(size, flags); 364 | #endif 365 | } 366 | 367 | void *dmap_kcalloc(size_t n, size_t size, gfp_t flags) 368 | { 369 | #ifdef __MALLOC_CHECKER__ 370 | void *ptr; 371 | 372 | ptr = dmap_kmalloc(n * size, flags); 373 | if (ptr) 374 | memset(ptr, 0, n * size); 375 | 376 | return ptr; 377 | #else 378 | return kcalloc(n, size, flags); 379 | #endif 380 | } 381 | 382 | void *dmap_kmalloc(size_t size, gfp_t flags) 383 | { 384 | #ifdef __MALLOC_CHECKER__ 385 | return malloc_checker_kmalloc(size, flags); 386 | #else 387 | return kmalloc(size, flags); 388 | #endif 389 | } 390 | 391 | void dmap_kfree(void *ptr) 392 | { 393 | #ifdef __MALLOC_CHECKER__ 394 | malloc_checker_kfree(ptr); 395 | #else 396 | kfree(ptr); 397 | #endif 398 | } 399 | 400 | static int __init dmap_module_init(void) 401 | { 402 | struct dmap *map = get_dmap(); 403 | int r; 404 | 405 | #ifdef __MALLOC_CHECKER__ 406 | r = malloc_checker_init(); 407 | if (r) { 408 | PRINTK("malloc checker init r %d", r); 409 | return r; 410 | } 411 | #endif 412 | 413 | r = dmap_init(map); 414 | if (r) { 415 | #ifdef __MALLOC_CHECKER__ 416 | malloc_checker_deinit(); 417 | #endif 418 | PRINTKE("cant init global, r %d", r); 419 | return r; 420 | } 421 | 422 | PRINTK("inited, dmap_module_init=0x%p global=0x%p", 423 | dmap_module_init, map); 424 | return 0; 425 | } 426 | 427 | static void __exit dmap_module_exit(void) 428 | { 429 | struct dmap *map = get_dmap(); 430 | 431 | dmap_deinit(map); 432 | 433 | #ifdef __MALLOC_CHECKER__ 434 | malloc_checker_deinit(); 435 | #endif 436 | 437 | PRINTK("exited"); 438 | } 439 | 440 | module_init(dmap_module_init) 441 | module_exit(dmap_module_exit) 442 | 443 | MODULE_AUTHOR("Andrey Smetanin "); 444 | MODULE_DESCRIPTION("Virtual disk"); 445 | MODULE_LICENSE("GPL"); 446 | -------------------------------------------------------------------------------- /dmap-handler.c: -------------------------------------------------------------------------------- 1 | #include "dmap-handler.h" 2 | #include "dmap-neighbor.h" 3 | #include "dmap-trace-helpers.h" 4 | #include "dmap-hash.h" 5 | #include "dmap-sha256.h" 6 | 7 | static int dmap_handle_hello(struct dmap *map, struct dmap_req_hello *req, 8 | struct dmap_resp_hello *resp) 9 | { 10 | int r; 11 | 12 | r = dmap_check_address(&req->source); 13 | if (r) 14 | return r; 15 | 16 | TRACE("hello %s:%d %s", 17 | req->source.host, req->source.port, req->source.id_str); 18 | 19 | r = dmap_add_neighbor(map, &req->source, true); 20 | if (r) { 21 | if (r == -EEXIST) 22 | r = 0; 23 | else 24 | return r; 25 | } 26 | 27 | dmap_get_address(map, &resp->addr); 28 | return 0; 29 | } 30 | 31 | static int dmap_handle_ping(struct dmap *map, struct dmap_req_ping *req, 32 | struct dmap_resp_ping *resp) 33 | { 34 | struct dmap_neighbor *neighbor; 35 | int r; 36 | 37 | r = dmap_check_address(&req->source); 38 | if (r) 39 | return r; 40 | 41 | 42 | TRACE("ping %s:%d %s", 43 | req->source.host, req->source.port, req->source.id_str); 44 | 45 | neighbor = dmap_lookup_neighbor(map, &req->source); 46 | if (!neighbor) 47 | return -ENOTTY; 48 | 49 | dmap_neighbor_put(neighbor); 50 | return 0; 51 | } 52 | 53 | static int dmap_handle_bye(struct dmap *map, struct dmap_req_bye *req, 54 | struct dmap_resp_bye *resp) 55 | { 56 | struct dmap_neighbor *neighbor; 57 | int r; 58 | 59 | r = dmap_check_address(&req->source); 60 | if (r) 61 | return r; 62 | 63 | TRACE("bye %s:%d %s", 64 | req->source.host, req->source.port, req->source.id_str); 65 | 66 | neighbor = dmap_lookup_neighbor(map, &req->source); 67 | if (!neighbor) 68 | return -ENOTTY; 69 | 70 | r = dmap_erase_neighbor(map, neighbor); 71 | 72 | dmap_neighbor_put(neighbor); 73 | return r; 74 | } 75 | 76 | static int dmap_handle_set_key(struct dmap *map, struct dmap_req_set_key *req, 77 | struct dmap_resp_set_key *resp) 78 | { 79 | unsigned char hash[32]; 80 | struct dmap_neighbor *neighbor; 81 | int r; 82 | 83 | sha256(req->key, sizeof(req->key), hash); 84 | 85 | neighbor = dmap_select_neighbor(map, hash); 86 | if (WARN_ON(neighbor == NULL)) 87 | return -ENOTTY; 88 | 89 | if (dmap_is_self_neighbor(map, neighbor)) 90 | r = dmap_hash_insert(&map->hash, req->key, sizeof(req->key), 91 | req->value, sizeof(req->value)); 92 | else 93 | r = dmap_neighbor_set_key(neighbor, req, resp); 94 | 95 | TRACE("set key: %16phN r: %d", req->key, hash, r); 96 | 97 | return r; 98 | } 99 | 100 | static int dmap_handle_get_key(struct dmap *map, struct dmap_req_get_key *req, 101 | struct dmap_resp_get_key *resp) 102 | { 103 | struct dmap_neighbor *neighbor; 104 | unsigned char hash[32]; 105 | int r; 106 | size_t value_len; 107 | 108 | sha256(req->key, sizeof(req->key), hash); 109 | 110 | neighbor = dmap_select_neighbor(map, hash); 111 | if (WARN_ON(neighbor == NULL)) 112 | return -ENOTTY; 113 | 114 | if (dmap_is_self_neighbor(map, neighbor)) 115 | r = dmap_hash_get(&map->hash, req->key, sizeof(req->key), 116 | resp->value, sizeof(resp->value), &value_len); 117 | else 118 | r = dmap_neighbor_get_key(neighbor, req, resp); 119 | 120 | TRACE("get key: %16phN value: %16phN r: %d", req->key, resp->value); 121 | 122 | 123 | return r; 124 | } 125 | 126 | static int dmap_handle_del_key(struct dmap *map, struct dmap_req_del_key *req, 127 | struct dmap_resp_del_key *resp) 128 | { 129 | struct dmap_neighbor *neighbor; 130 | unsigned char hash[32]; 131 | int r; 132 | 133 | sha256(req->key, sizeof(req->key), hash); 134 | 135 | neighbor = dmap_select_neighbor(map, hash); 136 | if (WARN_ON(neighbor == NULL)) 137 | return -ENOTTY; 138 | 139 | if (dmap_is_self_neighbor(map, neighbor)) 140 | r = dmap_hash_delete(&map->hash, req->key, sizeof(req->key)); 141 | else 142 | r = dmap_neighbor_del_key(neighbor, req, resp); 143 | 144 | TRACE("del key: %16phN r: %d", req->key, r); 145 | 146 | return r; 147 | } 148 | 149 | static int dmap_handle_upd_key(struct dmap *map, struct dmap_req_upd_key *req, 150 | struct dmap_resp_upd_key *resp) 151 | { 152 | unsigned char hash[32]; 153 | struct dmap_neighbor *neighbor; 154 | int r; 155 | 156 | sha256(req->key, sizeof(req->key), hash); 157 | 158 | neighbor = dmap_select_neighbor(map, hash); 159 | if (WARN_ON(neighbor == NULL)) 160 | return -ENOTTY; 161 | 162 | if (dmap_is_self_neighbor(map, neighbor)) 163 | r = dmap_hash_update(&map->hash, req->key, sizeof(req->key), 164 | req->value, sizeof(req->value)); 165 | else 166 | r = dmap_neighbor_upd_key(neighbor, req, resp); 167 | 168 | TRACE("update key: %16phN r: %d", req->key, hash, r); 169 | 170 | return r; 171 | } 172 | 173 | static int dmap_handle_cmpxchg_key(struct dmap *map, 174 | struct dmap_req_cmpxchg_key *req, 175 | struct dmap_resp_cmpxchg_key *resp) 176 | { 177 | unsigned char hash[32]; 178 | struct dmap_neighbor *neighbor; 179 | size_t value_len; 180 | int r; 181 | 182 | sha256(req->key, sizeof(req->key), hash); 183 | 184 | neighbor = dmap_select_neighbor(map, hash); 185 | if (WARN_ON(neighbor == NULL)) 186 | return -ENOTTY; 187 | 188 | if (dmap_is_self_neighbor(map, neighbor)) 189 | r = dmap_hash_cmpxchg(&map->hash, req->key, sizeof(req->key), 190 | req->exchange, sizeof(req->exchange), 191 | req->comparand, sizeof(req->comparand), 192 | resp->value, sizeof(resp->value), &value_len); 193 | else 194 | r = dmap_neighbor_cmpxchg_key(neighbor, req, resp); 195 | 196 | TRACE("cmpxchg key: %16phN r: %d", req->key, hash, r); 197 | 198 | return r; 199 | } 200 | 201 | int dmap_handle_request(struct dmap *map, u32 type, void *req_body, u32 req_len, 202 | void *resp_body, u32 *resp_len) 203 | { 204 | int r; 205 | 206 | switch (type) { 207 | case DMAP_PACKET_HELLO: { 208 | struct dmap_req_hello *req = req_body; 209 | struct dmap_resp_hello *resp = resp_body; 210 | 211 | if (req_len != sizeof(*req)) { 212 | r = -EINVAL; 213 | break; 214 | } 215 | 216 | r = dmap_handle_hello(map, req, resp); 217 | 218 | *resp_len = sizeof(*resp); 219 | break; 220 | } 221 | case DMAP_PACKET_PING: { 222 | struct dmap_req_ping *req = req_body; 223 | struct dmap_resp_ping *resp = resp_body; 224 | 225 | if (req_len != sizeof(*req)) { 226 | r = -EINVAL; 227 | break; 228 | } 229 | 230 | r = dmap_handle_ping(map, req, resp); 231 | 232 | *resp_len = sizeof(*resp); 233 | break; 234 | } 235 | case DMAP_PACKET_BYE: { 236 | struct dmap_req_bye *req = req_body; 237 | struct dmap_resp_bye *resp = resp_body; 238 | 239 | if (req_len != sizeof(*req)) { 240 | r = -EINVAL; 241 | break; 242 | } 243 | 244 | r = dmap_handle_bye(map, req, resp); 245 | 246 | *resp_len = sizeof(*resp); 247 | break; 248 | } 249 | case DMAP_PACKET_SET_KEY: { 250 | struct dmap_req_set_key *req = req_body; 251 | struct dmap_resp_set_key *resp = resp_body; 252 | 253 | if (req_len != sizeof(*req)) { 254 | r = -EINVAL; 255 | break; 256 | } 257 | 258 | r = dmap_handle_set_key(map, req, resp); 259 | 260 | *resp_len = sizeof(*resp); 261 | break; 262 | } 263 | case DMAP_PACKET_GET_KEY: { 264 | struct dmap_req_get_key *req = req_body; 265 | struct dmap_resp_get_key *resp = resp_body; 266 | 267 | if (req_len != sizeof(*req)) { 268 | r = -EINVAL; 269 | break; 270 | } 271 | 272 | r = dmap_handle_get_key(map, req, resp); 273 | 274 | *resp_len = sizeof(*resp); 275 | break; 276 | } 277 | case DMAP_PACKET_DEL_KEY: { 278 | struct dmap_req_del_key *req = req_body; 279 | struct dmap_resp_del_key *resp = resp_body; 280 | 281 | if (req_len != sizeof(*req)) { 282 | r = -EINVAL; 283 | break; 284 | } 285 | 286 | r = dmap_handle_del_key(map, req, resp); 287 | 288 | *resp_len = sizeof(*resp); 289 | break; 290 | } 291 | case DMAP_PACKET_UPD_KEY: { 292 | struct dmap_req_upd_key *req = req_body; 293 | struct dmap_resp_upd_key *resp = resp_body; 294 | 295 | if (req_len != sizeof(*req)) { 296 | r = -EINVAL; 297 | break; 298 | } 299 | 300 | r = dmap_handle_upd_key(map, req, resp); 301 | 302 | *resp_len = sizeof(*resp); 303 | break; 304 | } 305 | case DMAP_PACKET_CMPXCHG_KEY: { 306 | struct dmap_req_cmpxchg_key *req = req_body; 307 | struct dmap_resp_cmpxchg_key *resp = resp_body; 308 | 309 | if (req_len != sizeof(*req)) { 310 | r = -EINVAL; 311 | break; 312 | } 313 | 314 | r = dmap_handle_cmpxchg_key(map, req, resp); 315 | 316 | *resp_len = sizeof(*resp); 317 | break; 318 | } 319 | default: 320 | r = -EINVAL; 321 | TRACE_ERR(r, "unsupported request type %d", type); 322 | break; 323 | } 324 | 325 | if (r) 326 | *resp_len = 0; 327 | 328 | return r; 329 | } 330 | -------------------------------------------------------------------------------- /dmap-handler.h: -------------------------------------------------------------------------------- 1 | #ifndef __DMAP_HANDLER_H__ 2 | #define __DMAP_HANDLER_H__ 3 | 4 | #include "dmap.h" 5 | 6 | int dmap_handle_request(struct dmap *map, u32 type, void *req_body, u32 req_len, 7 | void *resp_body, u32 *resp_len); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /dmap-hash.c: -------------------------------------------------------------------------------- 1 | #include "dmap-hash.h" 2 | #include "dmap-malloc.h" 3 | 4 | void dmap_hash_init(struct dmap_hash *hash) 5 | { 6 | struct dmap_hash_bucket *bucket; 7 | int i; 8 | 9 | atomic64_set(&hash->nr_keys, 0); 10 | for (i = 0; i < ARRAY_SIZE(hash->bucket); i++) { 11 | bucket = &hash->bucket[i]; 12 | rwlock_init(&bucket->lock); 13 | bucket->tree = RB_ROOT; 14 | } 15 | } 16 | 17 | static void dmap_hash_node_put(struct dmap_hash_node *node) 18 | { 19 | if (atomic_dec_and_test(&node->ref_count)) { 20 | WARN_ON(node->in_tree); 21 | dmap_kfree(node->key); 22 | dmap_kfree(node->value); 23 | dmap_kfree(node); 24 | } 25 | } 26 | 27 | void dmap_hash_deinit(struct dmap_hash *hash) 28 | { 29 | struct dmap_hash_bucket *bucket; 30 | struct dmap_hash_node *node, *tmp; 31 | int i; 32 | 33 | for (i = 0; i < ARRAY_SIZE(hash->bucket); i++) { 34 | bucket = &hash->bucket[i]; 35 | rbtree_postorder_for_each_entry_safe(node, tmp, 36 | &bucket->tree, link) { 37 | node->in_tree = false; 38 | dmap_hash_node_put(node); 39 | } 40 | } 41 | } 42 | 43 | static void dmap_hash_node_get(struct dmap_hash_node *node) 44 | { 45 | atomic_inc(&node->ref_count); 46 | } 47 | 48 | static struct dmap_hash_node *dmap_hash_node_create( 49 | unsigned char *key, size_t key_len, 50 | unsigned char *value, size_t value_len) 51 | { 52 | struct dmap_hash_node *node; 53 | 54 | if (WARN_ON(key_len == 0 || key_len > DMAP_KEY_SIZE)) 55 | return NULL; 56 | if (WARN_ON(value_len == 0 || value_len > DMAP_VALUE_SIZE)) 57 | return NULL; 58 | 59 | node = dmap_kmalloc(sizeof(*node), GFP_KERNEL); 60 | if (!node) 61 | return NULL; 62 | 63 | atomic_set(&node->ref_count, 1); 64 | rwlock_init(&node->lock); 65 | 66 | node->key = dmap_kmalloc(key_len, GFP_KERNEL); 67 | if (!node->key) 68 | goto free_node; 69 | 70 | node->value = dmap_kmalloc(value_len, GFP_KERNEL); 71 | if (!node->value) 72 | goto free_key; 73 | 74 | node->in_tree = false; 75 | node->key_len = key_len; 76 | memcpy(node->key, key, node->key_len); 77 | node->value_len = value_len; 78 | memcpy(node->value, value, node->value_len); 79 | 80 | return node; 81 | 82 | free_key: 83 | dmap_kfree(node->key); 84 | free_node: 85 | dmap_kfree(node); 86 | return NULL; 87 | } 88 | 89 | static unsigned long dmap_hash_get_hash(unsigned char *key, size_t key_len) 90 | { 91 | unsigned long hash = 5381; 92 | size_t i; 93 | int c; 94 | 95 | for (i = 0; i < key_len; i++) { 96 | c = key[i]; 97 | hash = ((hash << 5) + hash) + c; 98 | } 99 | 100 | return hash; 101 | } 102 | 103 | static int dmap_hash_compare_key(unsigned char *key1, size_t key1_len, 104 | unsigned char *key2, size_t key2_len) 105 | { 106 | if (key1_len < key2_len) 107 | return -1; 108 | if (key1_len > key2_len) 109 | return 1; 110 | 111 | return memcmp(key1, key2, key1_len); 112 | } 113 | 114 | static int dmap_hash_insert_node(struct dmap_hash *hash, 115 | struct dmap_hash_node *node) 116 | { 117 | struct dmap_hash_bucket *bucket; 118 | struct dmap_hash_node *curr; 119 | struct rb_node **p; 120 | struct rb_node *parent; 121 | int i, cmp; 122 | bool exist; 123 | 124 | i = dmap_hash_get_hash(node->key, node->key_len); 125 | bucket = &hash->bucket[i % ARRAY_SIZE(hash->bucket)]; 126 | exist = false; 127 | parent = NULL; 128 | write_lock(&bucket->lock); 129 | p = &bucket->tree.rb_node; 130 | while (*p) { 131 | parent = *p; 132 | curr = rb_entry(parent, struct dmap_hash_node, link); 133 | cmp = dmap_hash_compare_key(node->key, node->key_len, 134 | curr->key, curr->key_len); 135 | if (cmp < 0) 136 | p = &(*p)->rb_left; 137 | else if (cmp > 0) 138 | p = &(*p)->rb_right; 139 | else { 140 | exist = true; 141 | break; 142 | } 143 | } 144 | if (!exist) { 145 | rb_link_node(&node->link, parent, p); 146 | rb_insert_color(&node->link, &bucket->tree); 147 | node->in_tree = true; 148 | dmap_hash_node_get(node); 149 | atomic64_inc(&hash->nr_keys); 150 | } 151 | write_unlock(&bucket->lock); 152 | 153 | return (exist) ? -EEXIST : 0; 154 | } 155 | 156 | static struct dmap_hash_node *dmap_hash_lookup_node(struct dmap_hash *hash, 157 | unsigned char *key, size_t key_len) 158 | { 159 | struct dmap_hash_bucket *bucket; 160 | struct dmap_hash_node *node, *found; 161 | struct rb_node *n; 162 | int i, cmp; 163 | 164 | found = NULL; 165 | i = dmap_hash_get_hash(key, key_len); 166 | bucket = &hash->bucket[i % ARRAY_SIZE(hash->bucket)]; 167 | 168 | read_lock(&bucket->lock); 169 | n = bucket->tree.rb_node; 170 | while (n) { 171 | node = rb_entry(n, struct dmap_hash_node, link); 172 | cmp = dmap_hash_compare_key(key, key_len, node->key, 173 | node->key_len); 174 | if (cmp < 0) 175 | n = n->rb_left; 176 | else if (cmp > 0) 177 | n = n->rb_right; 178 | else { 179 | found = node; 180 | dmap_hash_node_get(found); 181 | break; 182 | } 183 | } 184 | read_unlock(&bucket->lock); 185 | 186 | return found; 187 | } 188 | 189 | static int dmap_hash_delete_node(struct dmap_hash *hash, 190 | struct dmap_hash_node *node) 191 | { 192 | struct dmap_hash_bucket *bucket; 193 | int i, r; 194 | 195 | r = -ENOTTY; 196 | i = dmap_hash_get_hash(node->key, node->key_len); 197 | bucket = &hash->bucket[i % ARRAY_SIZE(hash->bucket)]; 198 | 199 | write_lock(&bucket->lock); 200 | if (node->in_tree) { 201 | rb_erase(&node->link, &bucket->tree); 202 | atomic64_dec(&hash->nr_keys); 203 | node->in_tree = false; 204 | r = 0; 205 | } 206 | write_unlock(&bucket->lock); 207 | 208 | if (!r) 209 | dmap_hash_node_put(node); 210 | 211 | return r; 212 | } 213 | 214 | int dmap_hash_insert(struct dmap_hash *hash, unsigned char *key, size_t key_len, 215 | unsigned char *value, size_t value_len) 216 | { 217 | struct dmap_hash_node *node; 218 | int r; 219 | 220 | if (key_len == 0 || key_len > DMAP_KEY_SIZE) 221 | return -EINVAL; 222 | if (value_len == 0 || value_len > DMAP_VALUE_SIZE) 223 | return -EINVAL; 224 | 225 | node = dmap_hash_node_create(key, key_len, value, value_len); 226 | if (!node) 227 | return -ENOMEM; 228 | 229 | r = dmap_hash_insert_node(hash, node); 230 | 231 | dmap_hash_node_put(node); 232 | return r; 233 | } 234 | 235 | int dmap_hash_update(struct dmap_hash *hash, unsigned char *key, size_t key_len, 236 | unsigned char *value, size_t value_len) 237 | { 238 | struct dmap_hash_node *node; 239 | void *new_value, *old_value; 240 | int r; 241 | 242 | if (key_len == 0 || key_len > DMAP_KEY_SIZE) 243 | return -EINVAL; 244 | if (value_len == 0 || value_len > DMAP_VALUE_SIZE) 245 | return -EINVAL; 246 | 247 | node = dmap_hash_lookup_node(hash, key, key_len); 248 | if (!node) 249 | return -ENOTTY; 250 | 251 | new_value = dmap_kmalloc(value_len, GFP_KERNEL); 252 | if (!new_value) { 253 | r = -ENOMEM; 254 | goto put_node; 255 | } 256 | 257 | memcpy(new_value, value, value_len); 258 | 259 | write_lock(&node->lock); 260 | old_value = node->value; 261 | node->value = new_value; 262 | node->value_len = value_len; 263 | write_unlock(&node->lock); 264 | 265 | dmap_kfree(old_value); 266 | r = 0; 267 | 268 | put_node: 269 | dmap_hash_node_put(node); 270 | return r; 271 | } 272 | 273 | int dmap_hash_cmpxchg(struct dmap_hash *hash, unsigned char *key, 274 | size_t key_len, unsigned char *exchange, size_t exchange_len, 275 | unsigned char *comparand, size_t comparand_len, 276 | unsigned char *value, size_t value_len, size_t *pvalue_len) 277 | { 278 | struct dmap_hash_node *node; 279 | int r; 280 | 281 | if (key_len == 0 || key_len > DMAP_KEY_SIZE) 282 | return -EINVAL; 283 | if (value_len == 0 || value_len > DMAP_VALUE_SIZE) 284 | return -EINVAL; 285 | if (exchange_len == 0 || exchange_len > DMAP_VALUE_SIZE) 286 | return -EINVAL; 287 | if (comparand_len == 0 || comparand_len > DMAP_VALUE_SIZE) 288 | return -EINVAL; 289 | 290 | node = dmap_hash_lookup_node(hash, key, key_len); 291 | if (!node) 292 | return -ENOTTY; 293 | 294 | write_lock(&node->lock); 295 | if (comparand_len != node->value_len) { 296 | r = -EINVAL; 297 | goto unlock; 298 | } 299 | 300 | if (value_len < node->value_len) { 301 | r = -EINVAL; 302 | goto unlock; 303 | } 304 | 305 | memcpy(value, node->value, node->value_len); 306 | *pvalue_len = node->value_len; 307 | 308 | if (memcmp(node->value, comparand, node->value_len) == 0) { 309 | memcpy(node->value, exchange, exchange_len); 310 | node->value_len = exchange_len; 311 | } 312 | r = 0; 313 | 314 | unlock: 315 | write_unlock(&node->lock); 316 | dmap_hash_node_put(node); 317 | return r; 318 | 319 | } 320 | 321 | int dmap_hash_get(struct dmap_hash *hash, unsigned char *key, size_t key_len, 322 | unsigned char *value, size_t value_len, size_t *pvalue_len) 323 | { 324 | struct dmap_hash_node *node; 325 | int r; 326 | 327 | if (key_len == 0 || key_len > DMAP_KEY_SIZE) 328 | return -EINVAL; 329 | if (value_len == 0 || value_len > DMAP_VALUE_SIZE) 330 | return -EINVAL; 331 | 332 | node = dmap_hash_lookup_node(hash, key, key_len); 333 | if (!node) 334 | return -ENOTTY; 335 | 336 | read_lock(&node->lock); 337 | if (node->value_len > value_len) { 338 | r = -E2BIG; 339 | goto unlock_node; 340 | } 341 | 342 | memcpy(value, node->value, node->value_len); 343 | *pvalue_len = node->value_len; 344 | r = 0; 345 | 346 | unlock_node: 347 | read_unlock(&node->lock); 348 | dmap_hash_node_put(node); 349 | return r; 350 | } 351 | 352 | int dmap_hash_delete(struct dmap_hash *hash, unsigned char *key, 353 | size_t key_len) 354 | { 355 | struct dmap_hash_node *node; 356 | int r; 357 | 358 | if (key_len == 0 || key_len > DMAP_KEY_SIZE) 359 | return -EINVAL; 360 | 361 | node = dmap_hash_lookup_node(hash, key, key_len); 362 | if (!node) 363 | return -ENOTTY; 364 | 365 | r = dmap_hash_delete_node(hash, node); 366 | 367 | dmap_hash_node_put(node); 368 | return r; 369 | } 370 | -------------------------------------------------------------------------------- /dmap-hash.h: -------------------------------------------------------------------------------- 1 | #ifndef __DMAP_HASH_H__ 2 | #define __DMAP_HASH_H__ 3 | 4 | #include "dmap-const.h" 5 | 6 | #include 7 | #include 8 | 9 | #define DMAP_HASH_SIZE 32768 10 | 11 | struct dmap_hash_node { 12 | struct rb_node link; 13 | unsigned char *key; 14 | size_t key_len; 15 | unsigned char *value; 16 | size_t value_len; 17 | atomic_t ref_count; 18 | bool in_tree; 19 | rwlock_t lock; 20 | }; 21 | 22 | struct dmap_hash_bucket { 23 | struct rb_root tree; 24 | rwlock_t lock; 25 | }; 26 | 27 | struct dmap_hash { 28 | struct dmap_hash_bucket bucket[DMAP_HASH_SIZE]; 29 | atomic64_t nr_keys; 30 | }; 31 | 32 | void dmap_hash_init(struct dmap_hash *hash); 33 | 34 | void dmap_hash_deinit(struct dmap_hash *hash); 35 | 36 | int dmap_hash_insert(struct dmap_hash *hash, unsigned char *key, size_t key_len, 37 | unsigned char *value, size_t value_len); 38 | 39 | int dmap_hash_update(struct dmap_hash *hash, unsigned char *key, size_t key_len, 40 | unsigned char *value, size_t value_len); 41 | 42 | int dmap_hash_cmpxchg(struct dmap_hash *hash, unsigned char *key, 43 | size_t key_len, unsigned char *exchange, size_t exchange_len, 44 | unsigned char *comparand, size_t comparand_len, 45 | unsigned char *value, size_t value_len, size_t *pvalue_len); 46 | 47 | int dmap_hash_get(struct dmap_hash *hash, unsigned char *key, size_t key_len, 48 | unsigned char *value, size_t value_len, size_t *pvalue_len); 49 | 50 | int dmap_hash_delete(struct dmap_hash *hash, unsigned char *key, 51 | size_t key_len); 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /dmap-helpers.c: -------------------------------------------------------------------------------- 1 | #include "dmap-helpers.h" 2 | 3 | unsigned long dmap_hash_pointer(void *ptr) 4 | { 5 | unsigned long val = (unsigned long)ptr; 6 | unsigned long hash, i, c; 7 | 8 | hash = 5381; 9 | val = val >> 3; 10 | for (i = 0; i < sizeof(val); i++) { 11 | c = (unsigned char)val & 0xFF; 12 | hash = ((hash << 5) + hash) + c; 13 | val = val >> 8; 14 | } 15 | 16 | return hash; 17 | } 18 | 19 | const char *dmap_truncate_file_name(const char *file_name) 20 | { 21 | char *base; 22 | 23 | base = strrchr(file_name, '/'); 24 | if (base) 25 | return ++base; 26 | else 27 | return file_name; 28 | } 29 | 30 | char dmap_byte_to_hex(unsigned char c) 31 | { 32 | if (WARN_ON(c > 15)) 33 | return '0'; 34 | 35 | if (c < 10) 36 | return '0' + c; 37 | else 38 | return 'a' + c - 10; 39 | } 40 | 41 | void dmap_bytes_to_hex(unsigned char *src, int slen, char *dst, int dlen) 42 | { 43 | int i; 44 | 45 | if (WARN_ON(dlen < (2 * slen + 1))) 46 | return; 47 | 48 | for (i = 0; i < slen; i++) { 49 | dst[2 * i] = dmap_byte_to_hex((src[i] >> 4) & 0xF); 50 | dst[2 * i + 1] = dmap_byte_to_hex(src[i] & 0xF); 51 | } 52 | 53 | dst[2 * slen] = '\0'; 54 | } 55 | 56 | unsigned char dmap_hex_to_byte(char c) 57 | { 58 | if (c >= '0' && c <= '9') 59 | return c - '0'; 60 | if (c >= 'a' && c <= 'f') 61 | return c - 'a' + 10; 62 | if (c >= 'A' && c <= 'F') 63 | return c - 'A' + 10; 64 | else 65 | return -1; 66 | } 67 | 68 | int dmap_hex_to_bytes(char *hex, int hex_len, unsigned char *dst, 69 | int dst_len) 70 | { 71 | int i, pos; 72 | int low, high; 73 | 74 | if (hex_len <= 0 || dst_len <= 0) 75 | return -EINVAL; 76 | 77 | if (hex_len & 1) 78 | return -EINVAL; 79 | 80 | if (dst_len != hex_len/2) 81 | return -EINVAL; 82 | 83 | for (i = 0, pos = 0; i < hex_len; i += 2, pos += 1) { 84 | high = dmap_hex_to_byte(hex[i]); 85 | low = dmap_hex_to_byte(hex[i + 1]); 86 | if (high == -1 || low == -1) 87 | return -EINVAL; 88 | dst[pos] = (high << 4) + low; 89 | } 90 | 91 | return 0; 92 | } 93 | -------------------------------------------------------------------------------- /dmap-helpers.h: -------------------------------------------------------------------------------- 1 | #ifndef __DMAP_HELPERS_H__ 2 | #define __DMAP_HELPERS_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define PRINTK(fmt, ...) \ 10 | pr_info("dmap: " fmt, ##__VA_ARGS__) 11 | 12 | #define PRINTKE(fmt, ...) \ 13 | pr_err("dmap: " fmt, ##__VA_ARGS__) 14 | 15 | unsigned long dmap_hash_pointer(void *ptr); 16 | 17 | const char *dmap_truncate_file_name(const char *file_name); 18 | 19 | char dmap_byte_to_hex(unsigned char c); 20 | 21 | void dmap_bytes_to_hex(unsigned char *src, int slen, char *dst, int dlen); 22 | 23 | unsigned char dmap_hex_to_byte(char c); 24 | 25 | int dmap_hex_to_bytes(char *hex, int hex_len, unsigned char *dst, 26 | int dst_len); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /dmap-malloc.h: -------------------------------------------------------------------------------- 1 | #ifndef __DMAP_MALLOC_H__ 2 | #define __DMAP_MALLOC_H__ 3 | 4 | void *dmap_kzalloc(size_t size, gfp_t flags); 5 | 6 | void *dmap_kcalloc(size_t n, size_t size, gfp_t flags); 7 | 8 | void *dmap_kmalloc(size_t size, gfp_t flags); 9 | 10 | void dmap_kfree(void *ptr); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /dmap-neighbor.c: -------------------------------------------------------------------------------- 1 | #include "dmap-neighbor.h" 2 | #include "dmap-malloc.h" 3 | #include "dmap.h" 4 | #include "dmap-trace-helpers.h" 5 | 6 | static void dmap_neighbor_free(struct dmap_neighbor *neighbor) 7 | { 8 | dmap_con_deinit(&neighbor->con); 9 | dmap_kfree(neighbor); 10 | } 11 | 12 | void dmap_neighbor_put(struct dmap_neighbor *neighbor) 13 | { 14 | if (atomic_dec_and_test(&neighbor->ref_count)) 15 | dmap_neighbor_free(neighbor); 16 | } 17 | 18 | void dmap_neighbor_get(struct dmap_neighbor *neighbor) 19 | { 20 | atomic_inc(&neighbor->ref_count); 21 | } 22 | 23 | void dmap_neighbor_set_state(struct dmap_neighbor *neighbor, int state) 24 | { 25 | neighbor->state = state; 26 | } 27 | 28 | static int dmap_neighbor_connect(struct dmap_neighbor *neighbor) 29 | { 30 | int r; 31 | 32 | r = dmap_con_connect(&neighbor->con, neighbor->addr.host, 33 | neighbor->addr.port); 34 | if (r) { 35 | if (r == -EEXIST) 36 | return 0; 37 | 38 | TRACE_ERR(r, "connect %s:%d failed", neighbor->addr.host, 39 | neighbor->addr.port); 40 | 41 | dmap_neighbor_set_state(neighbor, DMAP_NEIGHBOR_S_BROKEN); 42 | return r; 43 | } 44 | 45 | return 0; 46 | } 47 | 48 | int dmap_neighbor_hello(struct dmap_neighbor *neighbor) 49 | { 50 | struct dmap_req_hello *req = 51 | (struct dmap_req_hello *)neighbor->request.body; 52 | struct dmap_resp_hello *resp = 53 | (struct dmap_resp_hello *)neighbor->response.body; 54 | int r; 55 | 56 | mutex_lock(&neighbor->mutex); 57 | r = dmap_neighbor_connect(neighbor); 58 | if (r) 59 | goto unlock; 60 | 61 | dmap_get_address(neighbor->map, &req->source); 62 | 63 | r = dmap_con_send(&neighbor->con, DMAP_PACKET_HELLO, sizeof(*req), 0, 64 | &neighbor->request); 65 | if (r) 66 | goto unlock; 67 | 68 | r = dmap_con_recv_check(&neighbor->con, &neighbor->response, 69 | DMAP_PACKET_HELLO, sizeof(*resp)); 70 | if (r) 71 | dmap_neighbor_set_state(neighbor, DMAP_NEIGHBOR_S_BROKEN); 72 | else { 73 | memcpy(neighbor->addr.id, resp->addr.id, 74 | sizeof(neighbor->addr.id)); 75 | memcpy(neighbor->addr.id_str, resp->addr.id_str, 76 | sizeof(neighbor->addr.id_str)); 77 | dmap_neighbor_set_state(neighbor, DMAP_NEIGHBOR_S_HELLO); 78 | } 79 | 80 | unlock: 81 | mutex_unlock(&neighbor->mutex); 82 | return r; 83 | } 84 | 85 | int dmap_neighbor_bye(struct dmap_neighbor *neighbor) 86 | { 87 | struct dmap_req_bye *req = 88 | (struct dmap_req_bye *)neighbor->request.body; 89 | struct dmap_resp_bye *resp = 90 | (struct dmap_resp_bye *)neighbor->response.body; 91 | int r; 92 | 93 | mutex_lock(&neighbor->mutex); 94 | r = dmap_neighbor_connect(neighbor); 95 | if (r) 96 | goto unlock; 97 | 98 | dmap_get_address(neighbor->map, &req->source); 99 | 100 | r = dmap_con_send(&neighbor->con, DMAP_PACKET_BYE, sizeof(*req), 0, 101 | &neighbor->request); 102 | if (r) 103 | goto unlock; 104 | 105 | r = dmap_con_recv_check(&neighbor->con, &neighbor->response, 106 | DMAP_PACKET_BYE, sizeof(*resp)); 107 | if (r) 108 | dmap_neighbor_set_state(neighbor, DMAP_NEIGHBOR_S_BROKEN); 109 | 110 | unlock: 111 | mutex_unlock(&neighbor->mutex); 112 | return r; 113 | } 114 | 115 | int dmap_neighbor_ping(struct dmap_neighbor *neighbor) 116 | { 117 | struct dmap_req_ping *req = 118 | (struct dmap_req_ping *)neighbor->request.body; 119 | struct dmap_resp_ping *resp = 120 | (struct dmap_resp_ping *)neighbor->response.body; 121 | int r; 122 | ktime_t start; 123 | 124 | mutex_lock(&neighbor->mutex); 125 | if (neighbor->state != DMAP_NEIGHBOR_S_HELLO) { 126 | r = -ENOTTY; 127 | goto unlock; 128 | } 129 | 130 | r = dmap_neighbor_connect(neighbor); 131 | if (r) 132 | goto unlock; 133 | 134 | dmap_get_address(neighbor->map, &req->source); 135 | start = ktime_get(); 136 | r = dmap_con_send(&neighbor->con, DMAP_PACKET_PING, sizeof(*req), 0, 137 | &neighbor->request); 138 | if (r) 139 | goto unlock; 140 | 141 | r = dmap_con_recv_check(&neighbor->con, &neighbor->response, 142 | DMAP_PACKET_PING, sizeof(*resp)); 143 | if (r) 144 | dmap_neighbor_set_state(neighbor, DMAP_NEIGHBOR_S_BROKEN); 145 | else 146 | neighbor->ping_us = ktime_us_delta(ktime_get(), start); 147 | 148 | unlock: 149 | mutex_unlock(&neighbor->mutex); 150 | return r; 151 | } 152 | 153 | struct dmap_neighbor *dmap_neighbor_create(struct dmap *map, 154 | char *host, int port) 155 | { 156 | struct dmap_neighbor *neighbor; 157 | int r; 158 | 159 | neighbor = dmap_kzalloc(sizeof(*neighbor), GFP_KERNEL); 160 | if (!neighbor) 161 | return NULL; 162 | 163 | neighbor->map = map; 164 | mutex_init(&neighbor->mutex); 165 | INIT_LIST_HEAD(&neighbor->list); 166 | atomic_set(&neighbor->ref_count, 1); 167 | snprintf(neighbor->addr.host, ARRAY_SIZE(neighbor->addr.host), 168 | "%s", host); 169 | neighbor->addr.port = port; 170 | neighbor->state = DMAP_NEIGHBOR_S_INIT; 171 | 172 | r = dmap_con_init(&neighbor->con); 173 | if (r) 174 | goto free_neighbor; 175 | 176 | return neighbor; 177 | 178 | free_neighbor: 179 | dmap_kfree(neighbor); 180 | return NULL; 181 | } 182 | 183 | int dmap_neighbor_set_key(struct dmap_neighbor *neighbor, 184 | struct dmap_req_set_key *req, 185 | struct dmap_resp_set_key *resp) 186 | { 187 | struct dmap_req_set_key *lreq = 188 | (struct dmap_req_set_key *)neighbor->request.body; 189 | struct dmap_resp_set_key *lresp = 190 | (struct dmap_resp_set_key *)neighbor->response.body; 191 | int r; 192 | 193 | mutex_lock(&neighbor->mutex); 194 | if (neighbor->state != DMAP_NEIGHBOR_S_HELLO) { 195 | r = -ENOTTY; 196 | goto unlock; 197 | } 198 | 199 | r = dmap_neighbor_connect(neighbor); 200 | if (r) 201 | goto unlock; 202 | 203 | memcpy(lreq, req, sizeof(*lreq)); 204 | 205 | r = dmap_con_send(&neighbor->con, DMAP_PACKET_SET_KEY, sizeof(*lreq), 0, 206 | &neighbor->request); 207 | if (r) 208 | goto unlock; 209 | 210 | r = dmap_con_recv_check(&neighbor->con, &neighbor->response, 211 | DMAP_PACKET_SET_KEY, sizeof(*lresp)); 212 | if (r) 213 | goto unlock; 214 | 215 | memcpy(resp, lresp, sizeof(*resp)); 216 | 217 | unlock: 218 | mutex_unlock(&neighbor->mutex); 219 | return r; 220 | } 221 | 222 | int dmap_neighbor_get_key(struct dmap_neighbor *neighbor, 223 | struct dmap_req_get_key *req, 224 | struct dmap_resp_get_key *resp) 225 | { 226 | struct dmap_req_get_key *lreq = 227 | (struct dmap_req_get_key *)neighbor->request.body; 228 | struct dmap_resp_get_key *lresp = 229 | (struct dmap_resp_get_key *)neighbor->response.body; 230 | int r; 231 | 232 | mutex_lock(&neighbor->mutex); 233 | if (neighbor->state != DMAP_NEIGHBOR_S_HELLO) { 234 | r = -ENOTTY; 235 | goto unlock; 236 | } 237 | 238 | r = dmap_neighbor_connect(neighbor); 239 | if (r) 240 | goto unlock; 241 | 242 | memcpy(lreq, req, sizeof(*lreq)); 243 | 244 | r = dmap_con_send(&neighbor->con, DMAP_PACKET_GET_KEY, sizeof(*lreq), 0, 245 | &neighbor->request); 246 | if (r) 247 | goto unlock; 248 | 249 | r = dmap_con_recv_check(&neighbor->con, &neighbor->response, 250 | DMAP_PACKET_GET_KEY, sizeof(*lresp)); 251 | if (r) 252 | goto unlock; 253 | 254 | memcpy(resp, lresp, sizeof(*resp)); 255 | 256 | unlock: 257 | mutex_unlock(&neighbor->mutex); 258 | return r; 259 | } 260 | 261 | int dmap_neighbor_del_key(struct dmap_neighbor *neighbor, 262 | struct dmap_req_del_key *req, 263 | struct dmap_resp_del_key *resp) 264 | { 265 | struct dmap_req_del_key *lreq = 266 | (struct dmap_req_del_key *)neighbor->request.body; 267 | struct dmap_resp_del_key *lresp = 268 | (struct dmap_resp_del_key *)neighbor->response.body; 269 | int r; 270 | 271 | mutex_lock(&neighbor->mutex); 272 | if (neighbor->state != DMAP_NEIGHBOR_S_HELLO) { 273 | r = -ENOTTY; 274 | goto unlock; 275 | } 276 | 277 | r = dmap_neighbor_connect(neighbor); 278 | if (r) 279 | goto unlock; 280 | 281 | memcpy(lreq, req, sizeof(*lreq)); 282 | 283 | r = dmap_con_send(&neighbor->con, DMAP_PACKET_DEL_KEY, sizeof(*lreq), 0, 284 | &neighbor->request); 285 | if (r) 286 | goto unlock; 287 | 288 | r = dmap_con_recv_check(&neighbor->con, &neighbor->response, 289 | DMAP_PACKET_DEL_KEY, sizeof(*lresp)); 290 | if (r) 291 | goto unlock; 292 | 293 | memcpy(resp, lresp, sizeof(*resp)); 294 | 295 | unlock: 296 | mutex_unlock(&neighbor->mutex); 297 | return r; 298 | } 299 | 300 | int dmap_neighbor_upd_key(struct dmap_neighbor *neighbor, 301 | struct dmap_req_upd_key *req, 302 | struct dmap_resp_upd_key *resp) 303 | { 304 | struct dmap_req_upd_key *lreq = 305 | (struct dmap_req_upd_key *)neighbor->request.body; 306 | struct dmap_resp_upd_key *lresp = 307 | (struct dmap_resp_upd_key *)neighbor->response.body; 308 | int r; 309 | 310 | mutex_lock(&neighbor->mutex); 311 | if (neighbor->state != DMAP_NEIGHBOR_S_HELLO) { 312 | r = -ENOTTY; 313 | goto unlock; 314 | } 315 | 316 | r = dmap_neighbor_connect(neighbor); 317 | if (r) 318 | goto unlock; 319 | 320 | memcpy(lreq, req, sizeof(*lreq)); 321 | 322 | r = dmap_con_send(&neighbor->con, DMAP_PACKET_UPD_KEY, sizeof(*lreq), 0, 323 | &neighbor->request); 324 | if (r) 325 | goto unlock; 326 | 327 | r = dmap_con_recv_check(&neighbor->con, &neighbor->response, 328 | DMAP_PACKET_UPD_KEY, sizeof(*lresp)); 329 | if (r) 330 | goto unlock; 331 | 332 | memcpy(resp, lresp, sizeof(*resp)); 333 | 334 | unlock: 335 | mutex_unlock(&neighbor->mutex); 336 | return r; 337 | 338 | } 339 | 340 | int dmap_neighbor_cmpxchg_key(struct dmap_neighbor *neighbor, 341 | struct dmap_req_cmpxchg_key *req, 342 | struct dmap_resp_cmpxchg_key *resp) 343 | { 344 | struct dmap_req_cmpxchg_key *lreq = 345 | (struct dmap_req_cmpxchg_key *)neighbor->request.body; 346 | struct dmap_resp_cmpxchg_key *lresp = 347 | (struct dmap_resp_cmpxchg_key *)neighbor->response.body; 348 | int r; 349 | 350 | mutex_lock(&neighbor->mutex); 351 | if (neighbor->state != DMAP_NEIGHBOR_S_HELLO) { 352 | r = -ENOTTY; 353 | goto unlock; 354 | } 355 | 356 | r = dmap_neighbor_connect(neighbor); 357 | if (r) 358 | goto unlock; 359 | 360 | memcpy(lreq, req, sizeof(*lreq)); 361 | 362 | r = dmap_con_send(&neighbor->con, DMAP_PACKET_CMPXCHG_KEY, 363 | sizeof(*lreq), 0, &neighbor->request); 364 | if (r) 365 | goto unlock; 366 | 367 | r = dmap_con_recv_check(&neighbor->con, &neighbor->response, 368 | DMAP_PACKET_CMPXCHG_KEY, sizeof(*lresp)); 369 | if (r) 370 | goto unlock; 371 | 372 | memcpy(resp, lresp, sizeof(*resp)); 373 | 374 | unlock: 375 | mutex_unlock(&neighbor->mutex); 376 | return r; 377 | 378 | } 379 | -------------------------------------------------------------------------------- /dmap-neighbor.h: -------------------------------------------------------------------------------- 1 | #ifndef __DMAP_NEIGHBOR_H__ 2 | #define __DMAP_NEIGHBOR_H__ 3 | 4 | #include "dmap-const.h" 5 | #include "dmap-connection.h" 6 | 7 | enum { 8 | DMAP_NEIGHBOR_S_INIT = 1, 9 | DMAP_NEIGHBOR_S_HELLO = 3, 10 | DMAP_NEIGHBOR_S_BROKEN = 4, 11 | }; 12 | 13 | struct dmap; 14 | 15 | struct dmap_neighbor { 16 | struct dmap *map; 17 | struct mutex mutex; 18 | struct list_head list; 19 | struct dmap_address addr; 20 | int state; 21 | atomic_t ref_count; 22 | struct dmap_connection con; 23 | struct dmap_packet request; 24 | struct dmap_packet response; 25 | struct rb_node rb_link; 26 | u64 ping_us; 27 | }; 28 | 29 | void dmap_neighbor_put(struct dmap_neighbor *neighbor); 30 | 31 | void dmap_neighbor_get(struct dmap_neighbor *neighbor); 32 | 33 | struct dmap_neighbor *dmap_neighbor_create(struct dmap *map, 34 | char *host, int port); 35 | 36 | int dmap_neighbor_hello(struct dmap_neighbor *neighbor); 37 | 38 | int dmap_neighbor_bye(struct dmap_neighbor *neighbor); 39 | 40 | int dmap_neighbor_ping(struct dmap_neighbor *neighbor); 41 | 42 | void dmap_neighbor_set_state(struct dmap_neighbor *neighbor, int state); 43 | 44 | int dmap_neighbor_set_key(struct dmap_neighbor *neighbor, 45 | struct dmap_req_set_key *req, 46 | struct dmap_resp_set_key *resp); 47 | 48 | int dmap_neighbor_get_key(struct dmap_neighbor *neighbor, 49 | struct dmap_req_get_key *req, 50 | struct dmap_resp_get_key *resp); 51 | 52 | int dmap_neighbor_del_key(struct dmap_neighbor *neighbor, 53 | struct dmap_req_del_key *req, 54 | struct dmap_resp_del_key *resp); 55 | 56 | int dmap_neighbor_upd_key(struct dmap_neighbor *neighbor, 57 | struct dmap_req_upd_key *req, 58 | struct dmap_resp_upd_key *resp); 59 | 60 | int dmap_neighbor_cmpxchg_key(struct dmap_neighbor *neighbor, 61 | struct dmap_req_cmpxchg_key *req, 62 | struct dmap_resp_cmpxchg_key *resp); 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /dmap-server.c: -------------------------------------------------------------------------------- 1 | #include "dmap-server.h" 2 | #include "dmap-trace-helpers.h" 3 | #include "dmap-malloc.h" 4 | #include "dmap.h" 5 | #include "dmap-handler.h" 6 | #include "dmap-neighbor.h" 7 | 8 | #include 9 | #include 10 | 11 | int dmap_server_init(struct dmap_server *srv) 12 | { 13 | memset(srv, 0, sizeof(*srv)); 14 | mutex_init(&srv->mutex); 15 | atomic64_set(&srv->next_con_id, 0); 16 | INIT_LIST_HEAD(&srv->con_list); 17 | return 0; 18 | } 19 | 20 | static int dmap_server_con_thread(void *data) 21 | { 22 | struct dmap_server_con *con; 23 | struct dmap_server *srv; 24 | struct dmap *map; 25 | u32 type, len, result; 26 | int r; 27 | 28 | con = (struct dmap_server_con *)data; 29 | srv = con->srv; 30 | map = container_of(srv, struct dmap, server); 31 | 32 | while (!kthread_should_stop() && !con->stopping) { 33 | r = dmap_con_recv(&con->con, &con->request, 34 | &type, &len, &result); 35 | if (r) { 36 | if (r == -EAGAIN) { 37 | r = 0; 38 | continue; 39 | } 40 | 41 | if (r != -ECONNRESET) { 42 | TRACE_ERR(r, "con 0x%p id %llu recv failed", 43 | con, con->id); 44 | } 45 | break; 46 | } 47 | 48 | if (kthread_should_stop() || con->stopping) 49 | break; 50 | 51 | result = dmap_handle_request(map, type, con->request.body, len, 52 | con->response.body, &len); 53 | 54 | r = dmap_con_send(&con->con, type, len, result, 55 | &con->response); 56 | if (r) { 57 | if (r != -ECONNRESET) { 58 | TRACE_ERR(r, "con 0x%p id %llu send failed", 59 | con, con->id); 60 | } 61 | break; 62 | } 63 | } 64 | 65 | return 0; 66 | } 67 | 68 | static int dmap_server_con_start(struct dmap_server *srv, struct socket *sock) 69 | { 70 | struct dmap_server_con *con; 71 | struct task_struct *thread; 72 | int r; 73 | 74 | con = dmap_kzalloc(sizeof(*con), GFP_KERNEL); 75 | if (!con) 76 | return -ENOMEM; 77 | 78 | r = dmap_con_init(&con->con); 79 | if (r) 80 | goto free_con; 81 | 82 | con->id = atomic64_inc_return(&srv->next_con_id); 83 | mutex_init(&con->mutex); 84 | INIT_LIST_HEAD(&con->list); 85 | 86 | thread = kthread_create(dmap_server_con_thread, con, "dmap-con-%llu", 87 | con->id); 88 | if (IS_ERR(thread)) { 89 | r = PTR_ERR(thread); 90 | goto deinit_con; 91 | } 92 | 93 | r = dmap_con_set_socket(&con->con, sock); 94 | if (r) 95 | goto del_thread; 96 | 97 | get_task_struct(thread); 98 | con->thread = thread; 99 | con->srv = srv; 100 | 101 | mutex_lock(&srv->mutex); 102 | list_add_tail(&con->list, &srv->con_list); 103 | mutex_unlock(&srv->mutex); 104 | 105 | wake_up_process(thread); 106 | 107 | return 0; 108 | 109 | del_thread: 110 | kthread_stop(thread); 111 | deinit_con: 112 | dmap_con_deinit(&con->con); 113 | free_con: 114 | dmap_kfree(con); 115 | return r; 116 | } 117 | 118 | static void dmap_server_con_release(struct dmap_server_con *con) 119 | { 120 | mutex_lock(&con->mutex); 121 | if (con->thread) { 122 | con->stopping = true; 123 | PRINTK("going to stop connection thread 0x%p", con->thread); 124 | kthread_stop(con->thread); 125 | put_task_struct(con->thread); 126 | con->thread = NULL; 127 | dmap_con_deinit(&con->con); 128 | con->stopping = false; 129 | } 130 | mutex_unlock(&con->mutex); 131 | dmap_kfree(con); 132 | } 133 | 134 | static int dmap_server_thread(void *data) 135 | { 136 | struct dmap_server *srv; 137 | struct socket *sock; 138 | int r; 139 | 140 | srv = (struct dmap_server *)data; 141 | PRINTK("server 0x%p running, thread 0x%p", srv, current); 142 | 143 | while (!kthread_should_stop() && !srv->stopping) { 144 | 145 | r = ksock_accept(&sock, srv->sock); 146 | if (r) { 147 | TRACE_ERR(r, "accept failed"); 148 | continue; 149 | } 150 | 151 | r = dmap_server_con_start(srv, sock); 152 | if (r) { 153 | TRACE_ERR(r, "connection start failed"); 154 | ksock_release(sock); 155 | } 156 | } 157 | 158 | PRINTK("server 0x%p stopped, thread 0x%p", srv, current); 159 | 160 | return 0; 161 | } 162 | 163 | int dmap_server_start(struct dmap_server *srv, char *host, int port) 164 | { 165 | struct dmap_address addr; 166 | struct dmap *map; 167 | struct task_struct *thread; 168 | struct socket *sock; 169 | int r; 170 | int i; 171 | 172 | mutex_lock(&srv->mutex); 173 | if (srv->thread) { 174 | r = -EEXIST; 175 | goto unlock; 176 | } 177 | 178 | map = container_of(srv, struct dmap, server); 179 | 180 | dmap_addr_init(&addr, host, port, map->id); 181 | 182 | r = dmap_add_neighbor(map, &addr, true); 183 | if (r) 184 | goto unlock; 185 | 186 | snprintf(srv->host, ARRAY_SIZE(srv->host), "%s", host); 187 | srv->port = port; 188 | 189 | for (i = 0; i < 5; i++) { 190 | r = ksock_listen_host(&sock, host, port, 5); 191 | if (r) { 192 | TRACE_ERR(r, "listen failed"); 193 | if (r == -EADDRINUSE) { 194 | msleep_interruptible(100); 195 | continue; 196 | } 197 | goto remove_neighbor; 198 | } else 199 | break; 200 | } 201 | 202 | if (r) 203 | goto remove_neighbor; 204 | 205 | thread = kthread_create(dmap_server_thread, srv, "dmap-server"); 206 | if (IS_ERR(thread)) { 207 | r = PTR_ERR(thread); 208 | goto release_sock; 209 | } 210 | 211 | get_task_struct(thread); 212 | srv->thread = thread; 213 | srv->sock = sock; 214 | INIT_LIST_HEAD(&srv->con_list); 215 | 216 | wake_up_process(thread); 217 | r = 0; 218 | goto unlock; 219 | 220 | release_sock: 221 | ksock_release(sock); 222 | remove_neighbor: 223 | dmap_remove_neighbor(map, addr.host); 224 | unlock: 225 | mutex_unlock(&srv->mutex); 226 | return r; 227 | } 228 | 229 | int dmap_server_stop(struct dmap_server *srv) 230 | { 231 | struct dmap_server_con *con, *tmp; 232 | int r; 233 | 234 | mutex_lock(&srv->mutex); 235 | if (srv->thread) { 236 | srv->stopping = true; 237 | ksock_abort_accept(srv->sock); 238 | PRINTK("going to stop server thread 0x%p", srv->thread); 239 | kthread_stop(srv->thread); 240 | put_task_struct(srv->thread); 241 | srv->thread = NULL; 242 | ksock_release(srv->sock); 243 | srv->sock = NULL; 244 | 245 | list_for_each_entry_safe(con, tmp, &srv->con_list, list) { 246 | list_del_init(&con->list); 247 | dmap_server_con_release(con); 248 | } 249 | 250 | srv->stopping = false; 251 | r = 0; 252 | } else 253 | r = -ENOTTY; 254 | mutex_unlock(&srv->mutex); 255 | return r; 256 | } 257 | 258 | void dmap_server_deinit(struct dmap_server *srv) 259 | { 260 | dmap_server_stop(srv); 261 | } 262 | -------------------------------------------------------------------------------- /dmap-server.h: -------------------------------------------------------------------------------- 1 | #ifndef __DMAP_SERVER_H__ 2 | #define __DMAP_SERVER_H__ 3 | 4 | #include "dmap-const.h" 5 | #include "dmap-connection.h" 6 | 7 | #include "ksocket.h" 8 | 9 | #include 10 | 11 | struct dmap_server; 12 | 13 | struct dmap_server_con { 14 | struct dmap_server *srv; 15 | struct mutex mutex; 16 | struct list_head list; 17 | struct task_struct *thread; 18 | struct dmap_connection con; 19 | struct dmap_packet request; 20 | struct dmap_packet response; 21 | bool stopping; 22 | u64 id; 23 | }; 24 | 25 | struct dmap_server { 26 | struct mutex mutex; 27 | char host[DMAP_HOST_SIZE]; 28 | int port; 29 | 30 | struct task_struct *thread; 31 | struct socket *sock; 32 | bool stopping; 33 | 34 | struct list_head con_list; 35 | atomic64_t next_con_id; 36 | }; 37 | 38 | int dmap_server_init(struct dmap_server *srv); 39 | 40 | int dmap_server_start(struct dmap_server *srv, char *host, int port); 41 | 42 | int dmap_server_stop(struct dmap_server *srv); 43 | 44 | void dmap_server_deinit(struct dmap_server *srv); 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /dmap-sha256.c: -------------------------------------------------------------------------------- 1 | #include "dmap-sha256.h" 2 | 3 | #ifndef PUT_UINT32_BE 4 | #define PUT_UINT32_BE(n, b, i) \ 5 | { \ 6 | (b)[(i)] = (unsigned char)((n) >> 24); \ 7 | (b)[(i) + 1] = (unsigned char)((n) >> 16); \ 8 | (b)[(i) + 2] = (unsigned char)((n) >> 8); \ 9 | (b)[(i) + 3] = (unsigned char)((n)); \ 10 | } 11 | #endif 12 | 13 | #ifndef GET_UINT32_BE 14 | #define GET_UINT32_BE(n, b, i) \ 15 | { \ 16 | (n) = ((u32)(b)[(i)] << 24) \ 17 | | ((u32)(b)[(i) + 1] << 16) \ 18 | | ((u32)(b)[(i) + 2] << 8) \ 19 | | ((u32)(b)[(i) + 3]); \ 20 | } 21 | #endif 22 | 23 | static unsigned char sha256_padding[64] = { 24 | 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 28 | }; 29 | 30 | static void sha256_process(struct sha256_context *ctx, 31 | const unsigned char data[64]) 32 | { 33 | u32 temp1, temp2, W[64]; 34 | u32 A, B, C, D, E, F, G, H; 35 | 36 | GET_UINT32_BE(W[0], data, 0); 37 | GET_UINT32_BE(W[1], data, 4); 38 | GET_UINT32_BE(W[2], data, 8); 39 | GET_UINT32_BE(W[3], data, 12); 40 | GET_UINT32_BE(W[4], data, 16); 41 | GET_UINT32_BE(W[5], data, 20); 42 | GET_UINT32_BE(W[6], data, 24); 43 | GET_UINT32_BE(W[7], data, 28); 44 | GET_UINT32_BE(W[8], data, 32); 45 | GET_UINT32_BE(W[9], data, 36); 46 | GET_UINT32_BE(W[10], data, 40); 47 | GET_UINT32_BE(W[11], data, 44); 48 | GET_UINT32_BE(W[12], data, 48); 49 | GET_UINT32_BE(W[13], data, 52); 50 | GET_UINT32_BE(W[14], data, 56); 51 | GET_UINT32_BE(W[15], data, 60); 52 | 53 | #define SHR(x, n) ((x & 0xFFFFFFFF) >> n) 54 | #define ROTR(x, n) (SHR(x, n) | (x << (32 - n))) 55 | 56 | #define S0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3)) 57 | #define S1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10)) 58 | 59 | #define S2(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22)) 60 | #define S3(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25)) 61 | 62 | #define F0(x, y, z) ((x & y) | (z & (x | y))) 63 | #define F1(x, y, z) (z ^ (x & (y ^ z))) 64 | 65 | #define R(t) \ 66 | ( \ 67 | W[t] = S1(W[t - 2]) + W[t - 7] + \ 68 | S0(W[t - 15]) + W[t - 16] \ 69 | ) 70 | 71 | #define P(a, b, c, d, e, f, g, h, x, K) \ 72 | { \ 73 | temp1 = h + S3(e) + F1(e, f, g) + K + x; \ 74 | temp2 = S2(a) + F0(a, b, c); \ 75 | d += temp1; h = temp1 + temp2; \ 76 | } 77 | 78 | A = ctx->state[0]; 79 | B = ctx->state[1]; 80 | C = ctx->state[2]; 81 | D = ctx->state[3]; 82 | E = ctx->state[4]; 83 | F = ctx->state[5]; 84 | G = ctx->state[6]; 85 | H = ctx->state[7]; 86 | 87 | P(A, B, C, D, E, F, G, H, W[0], 0x428A2F98); 88 | P(H, A, B, C, D, E, F, G, W[1], 0x71374491); 89 | P(G, H, A, B, C, D, E, F, W[2], 0xB5C0FBCF); 90 | P(F, G, H, A, B, C, D, E, W[3], 0xE9B5DBA5); 91 | P(E, F, G, H, A, B, C, D, W[4], 0x3956C25B); 92 | P(D, E, F, G, H, A, B, C, W[5], 0x59F111F1); 93 | P(C, D, E, F, G, H, A, B, W[6], 0x923F82A4); 94 | P(B, C, D, E, F, G, H, A, W[7], 0xAB1C5ED5); 95 | P(A, B, C, D, E, F, G, H, W[8], 0xD807AA98); 96 | P(H, A, B, C, D, E, F, G, W[9], 0x12835B01); 97 | P(G, H, A, B, C, D, E, F, W[10], 0x243185BE); 98 | P(F, G, H, A, B, C, D, E, W[11], 0x550C7DC3); 99 | P(E, F, G, H, A, B, C, D, W[12], 0x72BE5D74); 100 | P(D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE); 101 | P(C, D, E, F, G, H, A, B, W[14], 0x9BDC06A7); 102 | P(B, C, D, E, F, G, H, A, W[15], 0xC19BF174); 103 | P(A, B, C, D, E, F, G, H, R(16), 0xE49B69C1); 104 | P(H, A, B, C, D, E, F, G, R(17), 0xEFBE4786); 105 | P(G, H, A, B, C, D, E, F, R(18), 0x0FC19DC6); 106 | P(F, G, H, A, B, C, D, E, R(19), 0x240CA1CC); 107 | P(E, F, G, H, A, B, C, D, R(20), 0x2DE92C6F); 108 | P(D, E, F, G, H, A, B, C, R(21), 0x4A7484AA); 109 | P(C, D, E, F, G, H, A, B, R(22), 0x5CB0A9DC); 110 | P(B, C, D, E, F, G, H, A, R(23), 0x76F988DA); 111 | P(A, B, C, D, E, F, G, H, R(24), 0x983E5152); 112 | P(H, A, B, C, D, E, F, G, R(25), 0xA831C66D); 113 | P(G, H, A, B, C, D, E, F, R(26), 0xB00327C8); 114 | P(F, G, H, A, B, C, D, E, R(27), 0xBF597FC7); 115 | P(E, F, G, H, A, B, C, D, R(28), 0xC6E00BF3); 116 | P(D, E, F, G, H, A, B, C, R(29), 0xD5A79147); 117 | P(C, D, E, F, G, H, A, B, R(30), 0x06CA6351); 118 | P(B, C, D, E, F, G, H, A, R(31), 0x14292967); 119 | P(A, B, C, D, E, F, G, H, R(32), 0x27B70A85); 120 | P(H, A, B, C, D, E, F, G, R(33), 0x2E1B2138); 121 | P(G, H, A, B, C, D, E, F, R(34), 0x4D2C6DFC); 122 | P(F, G, H, A, B, C, D, E, R(35), 0x53380D13); 123 | P(E, F, G, H, A, B, C, D, R(36), 0x650A7354); 124 | P(D, E, F, G, H, A, B, C, R(37), 0x766A0ABB); 125 | P(C, D, E, F, G, H, A, B, R(38), 0x81C2C92E); 126 | P(B, C, D, E, F, G, H, A, R(39), 0x92722C85); 127 | P(A, B, C, D, E, F, G, H, R(40), 0xA2BFE8A1); 128 | P(H, A, B, C, D, E, F, G, R(41), 0xA81A664B); 129 | P(G, H, A, B, C, D, E, F, R(42), 0xC24B8B70); 130 | P(F, G, H, A, B, C, D, E, R(43), 0xC76C51A3); 131 | P(E, F, G, H, A, B, C, D, R(44), 0xD192E819); 132 | P(D, E, F, G, H, A, B, C, R(45), 0xD6990624); 133 | P(C, D, E, F, G, H, A, B, R(46), 0xF40E3585); 134 | P(B, C, D, E, F, G, H, A, R(47), 0x106AA070); 135 | P(A, B, C, D, E, F, G, H, R(48), 0x19A4C116); 136 | P(H, A, B, C, D, E, F, G, R(49), 0x1E376C08); 137 | P(G, H, A, B, C, D, E, F, R(50), 0x2748774C); 138 | P(F, G, H, A, B, C, D, E, R(51), 0x34B0BCB5); 139 | P(E, F, G, H, A, B, C, D, R(52), 0x391C0CB3); 140 | P(D, E, F, G, H, A, B, C, R(53), 0x4ED8AA4A); 141 | P(C, D, E, F, G, H, A, B, R(54), 0x5B9CCA4F); 142 | P(B, C, D, E, F, G, H, A, R(55), 0x682E6FF3); 143 | P(A, B, C, D, E, F, G, H, R(56), 0x748F82EE); 144 | P(H, A, B, C, D, E, F, G, R(57), 0x78A5636F); 145 | P(G, H, A, B, C, D, E, F, R(58), 0x84C87814); 146 | P(F, G, H, A, B, C, D, E, R(59), 0x8CC70208); 147 | P(E, F, G, H, A, B, C, D, R(60), 0x90BEFFFA); 148 | P(D, E, F, G, H, A, B, C, R(61), 0xA4506CEB); 149 | P(C, D, E, F, G, H, A, B, R(62), 0xBEF9A3F7); 150 | P(B, C, D, E, F, G, H, A, R(63), 0xC67178F2); 151 | 152 | ctx->state[0] += A; 153 | ctx->state[1] += B; 154 | ctx->state[2] += C; 155 | ctx->state[3] += D; 156 | ctx->state[4] += E; 157 | ctx->state[5] += F; 158 | ctx->state[6] += G; 159 | ctx->state[7] += H; 160 | } 161 | 162 | void sha256_init(struct sha256_context *ctx) 163 | { 164 | memset(ctx, 0, sizeof(*ctx)); 165 | } 166 | 167 | void sha256_starts(struct sha256_context *ctx) 168 | { 169 | ctx->total[0] = 0; 170 | ctx->total[1] = 0; 171 | 172 | ctx->state[0] = 0x6A09E667; 173 | ctx->state[1] = 0xBB67AE85; 174 | ctx->state[2] = 0x3C6EF372; 175 | ctx->state[3] = 0xA54FF53A; 176 | ctx->state[4] = 0x510E527F; 177 | ctx->state[5] = 0x9B05688C; 178 | ctx->state[6] = 0x1F83D9AB; 179 | ctx->state[7] = 0x5BE0CD19; 180 | } 181 | 182 | void sha256_update(struct sha256_context *ctx, void *ibuf, size_t ilen) 183 | { 184 | size_t fill; 185 | const unsigned char *input = (const unsigned char *)ibuf; 186 | u32 left; 187 | 188 | if (ilen == 0) 189 | return; 190 | 191 | left = ctx->total[0] & 0x3F; 192 | fill = 64 - left; 193 | ctx->total[0] += (u32) ilen; 194 | ctx->total[0] &= 0xFFFFFFFF; 195 | if (ctx->total[0] < (u32) ilen) 196 | ctx->total[1]++; 197 | 198 | if (left && ilen >= fill) { 199 | memcpy((void *)(ctx->buffer + left), input, fill); 200 | sha256_process(ctx, ctx->buffer); 201 | input += fill; 202 | ilen -= fill; 203 | left = 0; 204 | } 205 | 206 | while (ilen >= 64) { 207 | sha256_process(ctx, input); 208 | input += 64; 209 | ilen -= 64; 210 | } 211 | 212 | if (ilen > 0) 213 | memcpy((void *)(ctx->buffer + left), input, ilen); 214 | } 215 | 216 | void sha256_finish(struct sha256_context *ctx, unsigned char output[32]) 217 | { 218 | u32 last, padn; 219 | u32 high, low; 220 | unsigned char msglen[8]; 221 | 222 | high = (ctx->total[0] >> 29) | (ctx->total[1] << 3); 223 | low = (ctx->total[0] << 3); 224 | 225 | PUT_UINT32_BE(high, msglen, 0); 226 | PUT_UINT32_BE(low, msglen, 4); 227 | 228 | last = ctx->total[0] & 0x3F; 229 | padn = (last < 56) ? (56 - last) : (120 - last); 230 | 231 | sha256_update(ctx, sha256_padding, padn); 232 | sha256_update(ctx, msglen, 8); 233 | 234 | PUT_UINT32_BE(ctx->state[0], output, 0); 235 | PUT_UINT32_BE(ctx->state[1], output, 4); 236 | PUT_UINT32_BE(ctx->state[2], output, 8); 237 | PUT_UINT32_BE(ctx->state[3], output, 12); 238 | PUT_UINT32_BE(ctx->state[4], output, 16); 239 | PUT_UINT32_BE(ctx->state[5], output, 20); 240 | PUT_UINT32_BE(ctx->state[6], output, 24); 241 | 242 | PUT_UINT32_BE(ctx->state[7], output, 28); 243 | } 244 | 245 | void sha256_free(struct sha256_context *ctx) 246 | { 247 | } 248 | 249 | void sha256(void *input, size_t ilen, unsigned char output[32]) 250 | { 251 | struct sha256_context ctx; 252 | 253 | sha256_init(&ctx); 254 | sha256_starts(&ctx); 255 | sha256_update(&ctx, input, ilen); 256 | sha256_finish(&ctx, output); 257 | sha256_free(&ctx); 258 | } 259 | -------------------------------------------------------------------------------- /dmap-sha256.h: -------------------------------------------------------------------------------- 1 | #ifndef __DMAP_SHA256_H__ 2 | #define __DMAP_SHA256_H__ 3 | 4 | #include 5 | #include 6 | 7 | struct sha256_context { 8 | u32 total[2]; 9 | u32 state[8]; 10 | unsigned char buffer[64]; 11 | 12 | unsigned char ipad[64]; 13 | unsigned char opad[64]; 14 | }; 15 | 16 | void sha256_init(struct sha256_context *ctx); 17 | 18 | void sha256_starts(struct sha256_context *ctx); 19 | 20 | void sha256_update(struct sha256_context *ctx, void *ibuf, size_t ilen); 21 | 22 | void sha256_finish(struct sha256_context *ctx, unsigned char output[32]); 23 | 24 | void sha256_free(struct sha256_context *ctx); 25 | 26 | void sha256(void *input, size_t ilen, unsigned char output[32]); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /dmap-sysfs.c: -------------------------------------------------------------------------------- 1 | #include "dmap-sysfs.h" 2 | #include "dmap.h" 3 | #include "dmap-server.h" 4 | #include "dmap-neighbor.h" 5 | 6 | #include 7 | 8 | #define DMAP_ATTR_RO(_name) \ 9 | struct dmap_sysfs_attr dmap_attr_##_name = \ 10 | __ATTR(_name, S_IRUGO, dmap_attr_##_name##_show, NULL) 11 | 12 | #define DMAP_ATTR_RW(_name) \ 13 | struct dmap_sysfs_attr dmap_attr_##_name = \ 14 | __ATTR(_name, S_IRUGO | S_IWUSR, dmap_attr_##_name##_show, \ 15 | dmap_attr_##_name##_store) 16 | 17 | struct dmap_sysfs_attr { 18 | struct attribute attr; 19 | ssize_t (*show)(struct dmap *, char *); 20 | ssize_t (*store)(struct dmap *, const char *, size_t count); 21 | }; 22 | 23 | static struct completion *dmap_get_completion_from_kobject(struct kobject *kobj) 24 | { 25 | return &container_of(kobj, 26 | struct dmap_kobject_holder, kobj)->completion; 27 | } 28 | 29 | static void dmap_kobject_release(struct kobject *kobj) 30 | { 31 | complete(dmap_get_completion_from_kobject(kobj)); 32 | } 33 | 34 | static struct dmap *dmap_from_kobject(struct kobject *kobj) 35 | { 36 | return container_of(kobj, struct dmap, kobj_holder.kobj); 37 | } 38 | 39 | int dmap_sysfs_init(struct dmap_kobject_holder *holder, struct kobject *root, 40 | struct kobj_type *ktype, const char *fmt, ...) 41 | { 42 | char name[256]; 43 | va_list args; 44 | 45 | ktype->release = dmap_kobject_release; 46 | 47 | init_completion(&holder->completion); 48 | 49 | va_start(args, fmt); 50 | vsnprintf(name, ARRAY_SIZE(name), fmt, args); 51 | va_end(args); 52 | 53 | return kobject_init_and_add(&holder->kobj, ktype, root, "%s", name); 54 | } 55 | 56 | void dmap_sysfs_deinit(struct dmap_kobject_holder *holder) 57 | { 58 | struct kobject *kobj = &holder->kobj; 59 | 60 | if (atomic_cmpxchg(&holder->deiniting, 0, 1) == 0) { 61 | kobject_put(kobj); 62 | wait_for_completion(dmap_get_completion_from_kobject(kobj)); 63 | } 64 | } 65 | 66 | static ssize_t dmap_attr_start_server_store(struct dmap *map, 67 | const char *buf, size_t count) 68 | { 69 | char host[DMAP_PARAM_SIZE]; 70 | int r, port; 71 | 72 | r = sscanf(buf, DMAP_PARAM_FMT" %d", host, &port); 73 | if (r != 2) 74 | return -EINVAL; 75 | 76 | r = dmap_server_start(&map->server, host, port); 77 | if (r) 78 | return r; 79 | 80 | return count; 81 | } 82 | 83 | static ssize_t dmap_attr_start_server_show(struct dmap *map, 84 | char *buf) 85 | { 86 | snprintf(buf, PAGE_SIZE, "\n"); 87 | return strlen(buf); 88 | } 89 | 90 | static ssize_t dmap_attr_stop_server_store(struct dmap *map, 91 | const char *buf, size_t count) 92 | { 93 | int r; 94 | 95 | r = dmap_server_stop(&map->server); 96 | if (r) 97 | return r; 98 | 99 | return count; 100 | } 101 | 102 | static ssize_t dmap_attr_stop_server_show(struct dmap *map, 103 | char *buf) 104 | { 105 | snprintf(buf, PAGE_SIZE, "\n"); 106 | return strlen(buf); 107 | } 108 | 109 | static ssize_t dmap_attr_server_show(struct dmap *map, 110 | char *buf) 111 | { 112 | snprintf(buf, PAGE_SIZE, "%s:%d\n", map->server.host, map->server.port); 113 | return strlen(buf); 114 | } 115 | 116 | static ssize_t dmap_attr_add_neighbor_store(struct dmap *map, 117 | const char *buf, size_t count) 118 | { 119 | char host[DMAP_PARAM_SIZE]; 120 | struct dmap_address addr = {0}; 121 | int r, port; 122 | 123 | r = sscanf(buf, DMAP_PARAM_FMT" %d", host, &port); 124 | if (r != 2) 125 | return -EINVAL; 126 | 127 | snprintf(addr.host, ARRAY_SIZE(addr.host), "%s", host); 128 | addr.port = port; 129 | r = dmap_add_neighbor(map, &addr, false); 130 | if (r) 131 | return r; 132 | 133 | return count; 134 | } 135 | 136 | static ssize_t dmap_attr_add_neighbor_show(struct dmap *map, 137 | char *buf) 138 | { 139 | snprintf(buf, PAGE_SIZE, "\n"); 140 | return strlen(buf); 141 | } 142 | 143 | static ssize_t dmap_attr_remove_neighbor_store(struct dmap *map, 144 | const char *buf, size_t count) 145 | { 146 | char host[DMAP_PARAM_SIZE]; 147 | int r; 148 | 149 | r = sscanf(buf, DMAP_PARAM_FMT, host); 150 | if (r != 1) 151 | return -EINVAL; 152 | 153 | r = dmap_remove_neighbor(map, host); 154 | if (r) 155 | return r; 156 | 157 | return count; 158 | } 159 | 160 | static ssize_t dmap_attr_remove_neighbor_show(struct dmap *map, 161 | char *buf) 162 | { 163 | snprintf(buf, PAGE_SIZE, "\n"); 164 | return strlen(buf); 165 | } 166 | 167 | static ssize_t dmap_attr_neighbors_show(struct dmap *map, 168 | char *buf) 169 | { 170 | struct dmap_neighbor *curr; 171 | int n, off, r; 172 | 173 | r = 0; 174 | off = 0; 175 | down_read(&map->rw_sem); 176 | list_for_each_entry(curr, &map->neighbor_list, list) { 177 | if (off >= PAGE_SIZE) { 178 | r = -ENOMEM; 179 | break; 180 | } 181 | n = snprintf((char *)buf + off, PAGE_SIZE - off, 182 | "%s:%d %s %llu %d\n", curr->addr.host, curr->addr.port, 183 | curr->addr.id_str, curr->ping_us, curr->state); 184 | if (n <= 0) { 185 | r = -ENOMEM; 186 | break; 187 | } 188 | off += n; 189 | } 190 | up_read(&map->rw_sem); 191 | 192 | if (r) 193 | return r; 194 | 195 | return strlen(buf); 196 | } 197 | 198 | static ssize_t dmap_attr_id_show(struct dmap *map, 199 | char *buf) 200 | { 201 | snprintf(buf, PAGE_SIZE, "%s\n", map->id_str); 202 | return strlen(buf); 203 | } 204 | 205 | static ssize_t dmap_attr_nr_keys_show(struct dmap *map, 206 | char *buf) 207 | { 208 | snprintf(buf, PAGE_SIZE, "%lu\n", atomic64_read(&map->hash.nr_keys)); 209 | return strlen(buf); 210 | } 211 | 212 | static ssize_t dmap_attr_show(struct kobject *kobj, 213 | struct attribute *attr, 214 | char *page) 215 | { 216 | struct dmap_sysfs_attr *vattr; 217 | struct dmap *map; 218 | 219 | vattr = container_of(attr, struct dmap_sysfs_attr, attr); 220 | if (!vattr->show) 221 | return -EIO; 222 | 223 | map = dmap_from_kobject(kobj); 224 | if (!map) 225 | return -EIO; 226 | 227 | return vattr->show(map, page); 228 | } 229 | 230 | static ssize_t dmap_attr_store(struct kobject *kobj, 231 | struct attribute *attr, 232 | const char *page, size_t count) 233 | { 234 | struct dmap_sysfs_attr *vattr; 235 | struct dmap *map; 236 | 237 | vattr = container_of(attr, struct dmap_sysfs_attr, attr); 238 | if (!vattr->store) 239 | return -EIO; 240 | 241 | map = dmap_from_kobject(kobj); 242 | if (!map) 243 | return -EIO; 244 | 245 | return vattr->store(map, page, count); 246 | } 247 | 248 | static DMAP_ATTR_RW(start_server); 249 | static DMAP_ATTR_RW(stop_server); 250 | static DMAP_ATTR_RO(server); 251 | static DMAP_ATTR_RW(add_neighbor); 252 | static DMAP_ATTR_RW(remove_neighbor); 253 | static DMAP_ATTR_RO(neighbors); 254 | static DMAP_ATTR_RO(id); 255 | static DMAP_ATTR_RO(nr_keys); 256 | 257 | static struct attribute *dmap_attrs[] = { 258 | &dmap_attr_start_server.attr, 259 | &dmap_attr_stop_server.attr, 260 | &dmap_attr_server.attr, 261 | &dmap_attr_add_neighbor.attr, 262 | &dmap_attr_remove_neighbor.attr, 263 | &dmap_attr_neighbors.attr, 264 | &dmap_attr_id.attr, 265 | &dmap_attr_nr_keys.attr, 266 | NULL, 267 | }; 268 | 269 | static const struct sysfs_ops dmap_sysfs_ops = { 270 | .show = dmap_attr_show, 271 | .store = dmap_attr_store, 272 | }; 273 | 274 | struct kobj_type dmap_ktype = { 275 | .sysfs_ops = &dmap_sysfs_ops, 276 | .default_attrs = dmap_attrs, 277 | }; 278 | -------------------------------------------------------------------------------- /dmap-sysfs.h: -------------------------------------------------------------------------------- 1 | #ifndef __DMAP_SYSFS_H__ 2 | #define __DMAP_SYSFS_H__ 3 | 4 | #include 5 | #include 6 | 7 | struct dmap_kobject_holder { 8 | struct kobject kobj; 9 | struct completion completion; 10 | atomic_t deiniting; 11 | }; 12 | 13 | extern struct kobj_type dmap_ktype; 14 | 15 | int dmap_sysfs_init(struct dmap_kobject_holder *holder, struct kobject *root, 16 | struct kobj_type *ktype, const char *fmt, ...); 17 | 18 | void dmap_sysfs_deinit(struct dmap_kobject_holder *holder); 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /dmap-trace-helpers.h: -------------------------------------------------------------------------------- 1 | #ifndef __DMAP_TRACE_HELPERS_H__ 2 | #define __DMAP_TRACE_HELPERS_H__ 3 | 4 | void dmap_trace_printf(const char *fmt, ...); 5 | 6 | void dmap_trace_error(int err, const char *fmt, ...); 7 | 8 | #define TRACE(fmt, ...) \ 9 | do { \ 10 | dmap_trace_printf("%s: " fmt, \ 11 | __func__, ##__VA_ARGS__); \ 12 | } while (false) 13 | 14 | #define TRACE_ERR(err, fmt, ...) \ 15 | do { \ 16 | dmap_trace_error(err, "%s: " fmt, \ 17 | __func__, ##__VA_ARGS__); \ 18 | } while (false) 19 | 20 | #define TRACE_VERBOSE(fmt, ...) 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /dmap-trace.c: -------------------------------------------------------------------------------- 1 | #define CREATE_TRACE_POINTS 2 | #include "dmap-trace.h" 3 | 4 | void dmap_trace_printf(const char *fmt, ...) 5 | { 6 | va_list args; 7 | 8 | va_start(args, fmt); 9 | trace_printf(fmt, args); 10 | va_end(args); 11 | } 12 | 13 | void dmap_trace_error(int err, const char *fmt, ...) 14 | { 15 | va_list args; 16 | 17 | va_start(args, fmt); 18 | trace_error(err, fmt, args); 19 | va_end(args); 20 | } 21 | -------------------------------------------------------------------------------- /dmap-trace.h: -------------------------------------------------------------------------------- 1 | #if !defined(_TRACE_DMAP_H) || defined(TRACE_HEADER_MULTI_READ) 2 | #define _TRACE_DMAP_H 3 | 4 | #include 5 | 6 | #undef TRACE_SYSTEM 7 | #define TRACE_SYSTEM dmap 8 | 9 | #define DMAP_MSG_CHARS 256 10 | 11 | TRACE_EVENT(printf, 12 | TP_PROTO(const char *fmt, va_list args), 13 | TP_ARGS(fmt, args), 14 | 15 | TP_STRUCT__entry( 16 | __dynamic_array(char, message, DMAP_MSG_CHARS) 17 | ), 18 | 19 | TP_fast_assign( 20 | vsnprintf((char *)__get_str(message), 21 | DMAP_MSG_CHARS - 1, fmt, args); 22 | ((char *)__get_str(message))[DMAP_MSG_CHARS - 1] = '\0'; 23 | ), 24 | 25 | TP_printk("%s", __get_str(message)) 26 | ); 27 | 28 | TRACE_EVENT(error, 29 | TP_PROTO(int err, const char *fmt, va_list args), 30 | TP_ARGS(err, fmt, args), 31 | 32 | TP_STRUCT__entry( 33 | __dynamic_array(char, message, DMAP_MSG_CHARS) 34 | __field(int, err) 35 | ), 36 | 37 | TP_fast_assign( 38 | vsnprintf((char *)__get_str(message), 39 | DMAP_MSG_CHARS - 1, fmt, args); 40 | ((char *)__get_str(message))[DMAP_MSG_CHARS - 1] = '\0'; 41 | __entry->err = err; 42 | ), 43 | 44 | TP_printk("%d: %s", __entry->err, __get_str(message)) 45 | ); 46 | 47 | #endif /* _TRACE_DMAP_H */ 48 | 49 | #undef TRACE_INCLUDE_PATH 50 | #define TRACE_INCLUDE_PATH . 51 | #undef TRACE_INCLUDE_FILE 52 | #define TRACE_INCLUDE_FILE dmap-trace 53 | 54 | /* This part must be outside protection */ 55 | #include 56 | -------------------------------------------------------------------------------- /dmap.h: -------------------------------------------------------------------------------- 1 | #ifndef __DMAP_H__ 2 | #define __DMAP_H__ 3 | 4 | #include "dmap-const.h" 5 | #include "dmap-helpers.h" 6 | #include "dmap-sysfs.h" 7 | #include "dmap-connection.h" 8 | #include "dmap-server.h" 9 | #include "dmap-hash.h" 10 | #include "dmap-neighbor.h" 11 | 12 | #include 13 | 14 | struct dmap { 15 | struct rw_semaphore rw_sem; 16 | struct dmap_kobject_holder kobj_holder; 17 | struct dmap_server server; 18 | unsigned char id[DMAP_ID_SIZE]; 19 | char id_str[2 * DMAP_ID_SIZE + 1]; 20 | struct list_head neighbor_list; 21 | struct work_struct ping_work; 22 | struct workqueue_struct *wq; 23 | struct hrtimer timer; 24 | struct dmap_hash hash; 25 | struct rb_root neighbor_tree; 26 | }; 27 | 28 | int dmap_add_neighbor(struct dmap *map, struct dmap_address *addr, bool hello); 29 | 30 | int dmap_remove_neighbor(struct dmap *map, char *host); 31 | 32 | struct dmap_neighbor *dmap_lookup_neighbor(struct dmap *map, 33 | struct dmap_address *addr); 34 | 35 | int dmap_erase_neighbor(struct dmap *map, struct dmap_neighbor *victim); 36 | 37 | void dmap_addr_init(struct dmap_address *addr, char *host, int port, 38 | unsigned char id[DMAP_ID_SIZE]); 39 | 40 | void dmap_get_address(struct dmap *map, struct dmap_address *addr); 41 | 42 | int dmap_check_address(struct dmap_address *addr); 43 | 44 | struct dmap_neighbor *dmap_select_neighbor(struct dmap *map, 45 | unsigned char id[DMAP_ID_SIZE]); 46 | 47 | bool dmap_is_self_neighbor(struct dmap *map, struct dmap_neighbor *neighbor); 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /ksocket.c: -------------------------------------------------------------------------------- 1 | #include "ksocket.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "dmap-trace-helpers.h" 13 | 14 | u16 ksock_peer_port(struct socket *sock) 15 | { 16 | return be16_to_cpu(sock->sk->sk_dport); 17 | } 18 | 19 | u16 ksock_self_port(struct socket *sock) 20 | { 21 | return sock->sk->sk_num; 22 | } 23 | 24 | u32 ksock_peer_addr(struct socket *sock) 25 | { 26 | return be32_to_cpu(sock->sk->sk_daddr); 27 | } 28 | 29 | u32 ksock_self_addr(struct socket *sock) 30 | { 31 | return be32_to_cpu(sock->sk->sk_rcv_saddr); 32 | } 33 | 34 | int ksock_create(struct socket **sockp, 35 | __u32 local_ip, int local_port) 36 | { 37 | struct sockaddr_in localaddr; 38 | struct socket *sock = NULL; 39 | int error; 40 | int option; 41 | mm_segment_t oldmm = get_fs(); 42 | 43 | error = sock_create(PF_INET, SOCK_STREAM, 0, &sock); 44 | if (error) 45 | goto out; 46 | 47 | 48 | set_fs(KERNEL_DS); 49 | option = 1; 50 | error = sock_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, 51 | (char *)&option, sizeof(option)); 52 | set_fs(oldmm); 53 | 54 | if (error) 55 | goto out_sock_release; 56 | 57 | if (local_ip != 0 || local_port != 0) { 58 | memset(&localaddr, 0, sizeof(localaddr)); 59 | localaddr.sin_family = AF_INET; 60 | localaddr.sin_port = htons(local_port); 61 | localaddr.sin_addr.s_addr = (local_ip == 0) ? 62 | INADDR_ANY : htonl(local_ip); 63 | error = sock->ops->bind(sock, (struct sockaddr *)&localaddr, 64 | sizeof(localaddr)); 65 | if (error == -EADDRINUSE) 66 | goto out_sock_release; 67 | 68 | if (error) 69 | goto out_sock_release; 70 | 71 | } 72 | *sockp = sock; 73 | return 0; 74 | 75 | out_sock_release: 76 | sock_release(sock); 77 | out: 78 | return error; 79 | } 80 | 81 | int ksock_set_nodelay(struct socket *sock, bool no_delay) 82 | { 83 | int option; 84 | int error; 85 | mm_segment_t oldmm = get_fs(); 86 | 87 | option = (no_delay) ? 1 : 0; 88 | 89 | set_fs(KERNEL_DS); 90 | error = sock_setsockopt(sock, SOL_TCP, TCP_NODELAY, 91 | (char *)&option, sizeof(option)); 92 | set_fs(oldmm); 93 | 94 | return error; 95 | } 96 | 97 | int ksock_set_sendbufsize(struct socket *sock, int size) 98 | { 99 | int option = size; 100 | int error; 101 | mm_segment_t oldmm = get_fs(); 102 | 103 | set_fs(KERNEL_DS); 104 | error = sock_setsockopt(sock, SOL_SOCKET, SO_SNDBUF, 105 | (char *)&option, sizeof(option)); 106 | set_fs(oldmm); 107 | 108 | return error; 109 | } 110 | 111 | int ksock_set_rcvbufsize(struct socket *sock, int size) 112 | { 113 | int option = size; 114 | int error; 115 | mm_segment_t oldmm = get_fs(); 116 | 117 | set_fs(KERNEL_DS); 118 | error = sock_setsockopt(sock, SOL_SOCKET, SO_RCVBUF, 119 | (char *)&option, sizeof(option)); 120 | set_fs(oldmm); 121 | 122 | return error; 123 | } 124 | 125 | int ksock_connect(struct socket **sockp, __u32 local_ip, int local_port, 126 | __u32 peer_ip, int peer_port) 127 | { 128 | struct sockaddr_in srvaddr; 129 | int error; 130 | struct socket *sock = NULL; 131 | 132 | error = ksock_create(&sock, local_ip, local_port); 133 | if (error) 134 | goto out; 135 | 136 | error = ksock_set_nodelay(sock, true); 137 | if (error) 138 | goto out_sock_release; 139 | 140 | memset(&srvaddr, 0, sizeof(srvaddr)); 141 | srvaddr.sin_family = AF_INET; 142 | srvaddr.sin_port = htons(peer_port); 143 | srvaddr.sin_addr.s_addr = htonl(peer_ip); 144 | 145 | error = sock->ops->connect(sock, (struct sockaddr *)&srvaddr, 146 | sizeof(srvaddr), 0); 147 | if (error) 148 | goto out_sock_release; 149 | 150 | *sockp = sock; 151 | return 0; 152 | 153 | out_sock_release: 154 | sock_release(sock); 155 | out: 156 | return error; 157 | } 158 | 159 | void ksock_release(struct socket *sock) 160 | { 161 | 162 | synchronize_rcu(); 163 | kernel_sock_shutdown(sock, SHUT_RDWR); 164 | sock_release(sock); 165 | } 166 | 167 | int ksock_write_timeout(struct socket *sock, void *buffer, u32 nob, 168 | u64 ticks, u32 *pwrote) 169 | { 170 | int error; 171 | u64 then, delta; 172 | struct timeval tv; 173 | u32 wrote = 0; 174 | mm_segment_t oldmm = get_fs(); 175 | 176 | if (WARN_ON(nob <= 0)) 177 | return -EINVAL; 178 | 179 | for (;;) { 180 | struct iovec iov = { 181 | .iov_base = buffer, 182 | .iov_len = nob 183 | }; 184 | struct msghdr msg; 185 | 186 | memset(&msg, 0, sizeof(msg)); 187 | msg.msg_flags = (ticks == 0) ? MSG_DONTWAIT : 0; 188 | #if LINUX_VERSION_CODE <= KERNEL_VERSION(3, 18, 0) 189 | msg.msg_iov = &iov; 190 | msg.msg_iovlen = 1; 191 | #else 192 | iov_iter_init(&msg.msg_iter, WRITE, &iov, 1, nob); 193 | #endif 194 | tv = (struct timeval) { 195 | .tv_sec = ticks/HZ, 196 | .tv_usec = ((ticks % HZ) * 1000000)/HZ 197 | }; 198 | 199 | set_fs(KERNEL_DS); 200 | error = sock_setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, 201 | (char *)&tv, sizeof(tv)); 202 | set_fs(oldmm); 203 | if (error) 204 | goto out; 205 | 206 | then = get_jiffies_64(); 207 | set_fs(KERNEL_DS); 208 | #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0) 209 | error = sock_sendmsg(sock, &msg, nob); 210 | #else 211 | error = sock_sendmsg(sock, &msg); 212 | #endif 213 | set_fs(oldmm); 214 | delta = get_jiffies_64() - then; 215 | delta = (delta > ticks) ? ticks : delta; 216 | ticks -= delta; 217 | 218 | if (error < 0) 219 | goto out; 220 | 221 | if (error == 0) { 222 | error = -ECONNABORTED; 223 | goto out; 224 | } 225 | 226 | if (error > 0) 227 | wrote += error; 228 | 229 | buffer = (void *)((unsigned long)buffer + error); 230 | WARN_ON(error <= 0); 231 | WARN_ON(nob < error); 232 | nob -= error; 233 | if (nob == 0) { 234 | error = 0; 235 | goto out; 236 | } 237 | 238 | if (ticks == 0) { 239 | error = -ETIME; 240 | goto out; 241 | } 242 | } 243 | out: 244 | if (pwrote) 245 | *pwrote = wrote; 246 | 247 | return error; 248 | } 249 | 250 | int ksock_read_timeout(struct socket *sock, void *buffer, u32 nob, 251 | u64 ticks, u32 *pread) 252 | { 253 | int error; 254 | u64 then, delta; 255 | struct timeval tv; 256 | u32 read = 0; 257 | mm_segment_t oldmm = get_fs(); 258 | 259 | if (WARN_ON(nob <= 0)) 260 | return -EINVAL; 261 | 262 | for (;;) { 263 | struct iovec iov = { 264 | .iov_base = buffer, 265 | .iov_len = nob 266 | }; 267 | 268 | struct msghdr msg; 269 | 270 | memset(&msg, 0, sizeof(msg)); 271 | #if LINUX_VERSION_CODE <= KERNEL_VERSION(3, 18, 0) 272 | msg.msg_iov = &iov; 273 | msg.msg_iovlen = 1; 274 | #else 275 | iov_iter_init(&msg.msg_iter, READ, &iov, 1, nob); 276 | #endif 277 | tv = (struct timeval) { 278 | .tv_sec = ticks/HZ, 279 | .tv_usec = ((ticks % HZ) * 1000000)/HZ 280 | }; 281 | 282 | set_fs(KERNEL_DS); 283 | error = sock_setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, 284 | (char *)&tv, sizeof(tv)); 285 | set_fs(oldmm); 286 | 287 | if (error) 288 | goto out; 289 | 290 | then = get_jiffies_64(); 291 | set_fs(KERNEL_DS); 292 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 5) 293 | error = sock_recvmsg(sock, &msg, 0); 294 | #else 295 | error = sock_recvmsg(sock, &msg, nob, 0); 296 | #endif 297 | set_fs(oldmm); 298 | delta = (get_jiffies_64() - then); 299 | delta = (delta > ticks) ? ticks : delta; 300 | ticks -= delta; 301 | 302 | if (error < 0) 303 | goto out; 304 | 305 | if (error == 0) { 306 | error = -ECONNRESET; 307 | goto out; 308 | } 309 | 310 | if (error > 0) 311 | read += error; 312 | 313 | buffer = (void *)((unsigned long)buffer + error); 314 | WARN_ON(error <= 0); 315 | WARN_ON(nob < error); 316 | nob -= error; 317 | if (nob == 0) { 318 | error = 0; 319 | goto out; 320 | } 321 | 322 | if (ticks == 0) { 323 | error = -ETIMEDOUT; 324 | goto out; 325 | } 326 | } 327 | out: 328 | if (pread) 329 | *pread = read; 330 | return error; 331 | } 332 | 333 | int ksock_read(struct socket *sock, void *buffer, u32 nob, u32 *pread) 334 | { 335 | u32 read = 0, off = 0; 336 | int err = 0; 337 | 338 | while (off < nob) { 339 | err = ksock_read_timeout(sock, (char *)buffer + off, 340 | nob - off, 60 * HZ, &read); 341 | off += read; 342 | if (err) 343 | break; 344 | } 345 | *pread = off; 346 | return err; 347 | } 348 | 349 | 350 | int ksock_write(struct socket *sock, void *buffer, u32 nob, u32 *pwrote) 351 | { 352 | u32 wrote = 0, off = 0; 353 | int err = 0; 354 | 355 | while (off < nob) { 356 | err = ksock_write_timeout(sock, (char *)buffer + off, 357 | nob - off, 60 * HZ, &wrote); 358 | off += wrote; 359 | if (err) 360 | break; 361 | } 362 | *pwrote = off; 363 | return err; 364 | } 365 | 366 | int ksock_send(struct socket *sock, void *buf, int len) 367 | { 368 | u32 wrote; 369 | int r; 370 | 371 | r = ksock_write(sock, buf, len, &wrote); 372 | if (r) 373 | return r; 374 | 375 | return wrote; 376 | } 377 | 378 | int ksock_recv(struct socket *sock, void *buf, int len) 379 | { 380 | u32 read; 381 | int r; 382 | 383 | r = ksock_read(sock, buf, len, &read); 384 | if (r) 385 | return r; 386 | 387 | return read; 388 | } 389 | 390 | int ksock_listen(struct socket **sockp, __u32 local_ip, int local_port, 391 | int backlog) 392 | { 393 | int error; 394 | struct socket *sock = NULL; 395 | 396 | error = ksock_create(&sock, local_ip, local_port); 397 | if (error) 398 | return error; 399 | 400 | error = sock->ops->listen(sock, backlog); 401 | if (error) 402 | goto out; 403 | 404 | *sockp = sock; 405 | return 0; 406 | out: 407 | sock_release(sock); 408 | return error; 409 | } 410 | 411 | int ksock_accept(struct socket **newsockp, struct socket *sock) 412 | { 413 | wait_queue_t wait; 414 | struct socket *newsock; 415 | int error; 416 | 417 | init_waitqueue_entry(&wait, current); 418 | error = sock_create_lite(PF_PACKET, sock->type, IPPROTO_TCP, &newsock); 419 | if (error) 420 | return error; 421 | 422 | newsock->ops = sock->ops; 423 | set_current_state(TASK_INTERRUPTIBLE); 424 | add_wait_queue(sk_sleep(sock->sk), &wait); 425 | error = sock->ops->accept(sock, newsock, O_NONBLOCK); 426 | if (error == -EAGAIN) { 427 | schedule(); 428 | error = sock->ops->accept(sock, newsock, O_NONBLOCK); 429 | } 430 | remove_wait_queue(sk_sleep(sock->sk), &wait); 431 | set_current_state(TASK_RUNNING); 432 | if (error) 433 | goto out; 434 | 435 | *newsockp = newsock; 436 | return 0; 437 | out: 438 | sock_release(newsock); 439 | return error; 440 | } 441 | 442 | void ksock_abort_accept(struct socket *sock) 443 | { 444 | wake_up_all(sk_sleep(sock->sk)); 445 | } 446 | 447 | int ksock_ioctl(struct socket *sock, int cmd, unsigned long arg) 448 | { 449 | mm_segment_t oldfs = get_fs(); 450 | int err; 451 | 452 | set_fs(KERNEL_DS); 453 | err = sock->ops->ioctl(sock, cmd, arg); 454 | set_fs(oldfs); 455 | return err; 456 | } 457 | 458 | static void ksock_addr_set_port(struct sockaddr_storage *ss, int p) 459 | { 460 | switch (ss->ss_family) { 461 | case AF_INET: 462 | ((struct sockaddr_in *)ss)->sin_port = htons(p); 463 | break; 464 | case AF_INET6: 465 | ((struct sockaddr_in6 *)ss)->sin6_port = htons(p); 466 | break; 467 | } 468 | } 469 | 470 | static int ksock_pton(char *ip, int ip_len, struct sockaddr_storage *ss) 471 | { 472 | struct sockaddr_in *in4 = (struct sockaddr_in *) ss; 473 | struct sockaddr_in6 *in6 = (struct sockaddr_in6 *) ss; 474 | 475 | memset(ss, 0, sizeof(*ss)); 476 | 477 | if (in4_pton(ip, ip_len, (u8 *)&in4->sin_addr.s_addr, -1, NULL)) { 478 | ss->ss_family = AF_INET; 479 | return 0; 480 | } 481 | 482 | if (in6_pton(ip, ip_len, (u8 *)&in6->sin6_addr.s6_addr, -1, NULL)) { 483 | ss->ss_family = AF_INET6; 484 | return 0; 485 | } 486 | 487 | return -EINVAL; 488 | } 489 | 490 | static int ksock_dns_resolve(char *name, struct sockaddr_storage *ss) 491 | { 492 | int ip_len, r; 493 | char *ip_addr = NULL; 494 | 495 | ip_len = dns_query(NULL, name, strlen(name), NULL, &ip_addr, NULL); 496 | if (ip_len > 0) 497 | r = ksock_pton(ip_addr, ip_len, ss); 498 | else { 499 | TRACE_ERR(ip_len, "dns_query %s failed", name); 500 | r = -ESRCH; 501 | } 502 | kfree(ip_addr); 503 | return r; 504 | } 505 | 506 | int ksock_connect_host(struct socket **sockp, char *host, u16 port) 507 | { 508 | struct sockaddr_storage addr; 509 | struct sockaddr_in *in4 = (struct sockaddr_in *)&addr; 510 | struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)&addr; 511 | int r; 512 | struct socket *sock; 513 | int option; 514 | mm_segment_t oldmm; 515 | 516 | r = ksock_pton(host, strlen(host), &addr); 517 | if (r) { 518 | r = ksock_dns_resolve(host, &addr); 519 | if (r) 520 | return r; 521 | } 522 | 523 | r = sock_create(addr.ss_family, SOCK_STREAM, 0, &sock); 524 | if (r) 525 | return r; 526 | 527 | oldmm = get_fs(); 528 | set_fs(KERNEL_DS); 529 | option = 1; 530 | r = sock_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, 531 | (char *)&option, sizeof(option)); 532 | set_fs(oldmm); 533 | if (r) 534 | goto release_sock; 535 | 536 | r = ksock_set_nodelay(sock, true); 537 | if (r) 538 | goto release_sock; 539 | 540 | ksock_addr_set_port(&addr, port); 541 | 542 | r = sock->ops->connect(sock, (struct sockaddr *)&addr, 543 | (addr.ss_family == AF_INET) ? sizeof(*in4) : sizeof(*in6), 0); 544 | if (r) 545 | goto release_sock; 546 | 547 | *sockp = sock; 548 | return 0; 549 | 550 | release_sock: 551 | sock_release(sock); 552 | return r; 553 | } 554 | 555 | int ksock_create_host(struct socket **sockp, char *host, int port) 556 | { 557 | struct sockaddr_storage addr; 558 | struct sockaddr_in *in4 = (struct sockaddr_in *)&addr; 559 | struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)&addr; 560 | struct socket *sock = NULL; 561 | int error; 562 | int option; 563 | mm_segment_t oldmm = get_fs(); 564 | 565 | error = ksock_pton(host, strlen(host), &addr); 566 | if (error) { 567 | error = ksock_dns_resolve(host, &addr); 568 | if (error) 569 | return error; 570 | } 571 | 572 | error = sock_create(addr.ss_family, SOCK_STREAM, 0, &sock); 573 | if (error) 574 | return error; 575 | 576 | set_fs(KERNEL_DS); 577 | option = 1; 578 | error = sock_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, 579 | (char *)&option, sizeof(option)); 580 | set_fs(oldmm); 581 | 582 | if (error) 583 | goto out_sock_release; 584 | 585 | ksock_addr_set_port(&addr, port); 586 | 587 | error = sock->ops->bind(sock, (struct sockaddr *)&addr, 588 | (addr.ss_family == AF_INET) ? sizeof(*in4) : sizeof(*in6)); 589 | 590 | if (error == -EADDRINUSE) 591 | goto out_sock_release; 592 | 593 | if (error) 594 | goto out_sock_release; 595 | 596 | *sockp = sock; 597 | return 0; 598 | 599 | out_sock_release: 600 | sock_release(sock); 601 | return error; 602 | } 603 | 604 | int ksock_listen_host(struct socket **sockp, char *host, int port, int backlog) 605 | { 606 | int error; 607 | struct socket *sock = NULL; 608 | 609 | error = ksock_create_host(&sock, host, port); 610 | if (error) 611 | return error; 612 | 613 | error = sock->ops->listen(sock, backlog); 614 | if (error) 615 | goto out; 616 | 617 | *sockp = sock; 618 | return 0; 619 | out: 620 | sock_release(sock); 621 | return error; 622 | } 623 | -------------------------------------------------------------------------------- /ksocket.h: -------------------------------------------------------------------------------- 1 | #ifndef __DMAP_KSOCKET_H__ 2 | #define __DMAP_KSOCKET_H__ 3 | 4 | #include 5 | 6 | u16 ksock_self_port(struct socket *sock); 7 | u16 ksock_peer_port(struct socket *sock); 8 | u32 ksock_peer_addr(struct socket *sock); 9 | u32 ksock_self_addr(struct socket *sock); 10 | 11 | int ksock_create(struct socket **sockp, 12 | __u32 local_ip, int local_port); 13 | 14 | int ksock_set_sendbufsize(struct socket *sock, int size); 15 | 16 | int ksock_set_rcvbufsize(struct socket *sock, int size); 17 | 18 | int ksock_connect(struct socket **sockp, __u32 local_ip, int local_port, 19 | __u32 peer_ip, int peer_port); 20 | 21 | void ksock_release(struct socket *sock); 22 | 23 | int ksock_write_timeout(struct socket *sock, void *buffer, u32 nob, 24 | u64 ticks, u32 *pwrote); 25 | 26 | int ksock_read_timeout(struct socket *sock, void *buffer, u32 nob, 27 | u64 ticks, u32 *pread); 28 | 29 | int ksock_read(struct socket *sock, void *buffer, u32 nob, u32 *pread); 30 | 31 | int ksock_write(struct socket *sock, void *buffer, u32 nob, u32 *pwrote); 32 | 33 | int ksock_send(struct socket *sock, void *buf, int len); 34 | 35 | int ksock_recv(struct socket *sock, void *buf, int len); 36 | 37 | int ksock_listen(struct socket **sockp, __u32 local_ip, int local_port, 38 | int backlog); 39 | 40 | int ksock_accept(struct socket **newsockp, struct socket *sock); 41 | 42 | void ksock_abort_accept(struct socket *sock); 43 | 44 | int ksock_ioctl(struct socket *sock, int cmd, unsigned long arg); 45 | 46 | int ksock_set_nodelay(struct socket *sock, bool no_delay); 47 | 48 | int ksock_connect_host(struct socket **sockp, char *host, u16 port); 49 | 50 | int ksock_listen_host(struct socket **sockp, char *host, int port, int backlog); 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /malloc-checker.c: -------------------------------------------------------------------------------- 1 | #include "malloc-checker.h" 2 | #include "dmap-helpers.h" 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #define MALLOC_CHECKER_STACK_ENTRIES 10 13 | #define MALLOC_CHECKER_NR_LISTS 9973 14 | #define MALLOC_CHECKER_SIGN1 0xBEDABEDA 15 | #define MALLOC_CHECKER_SIGN2 0xCBDACBDA 16 | 17 | struct malloc_entry { 18 | struct list_head link; 19 | gfp_t flags; 20 | void *ptr; 21 | size_t size; 22 | #ifdef __MALLOC_CHECKER_STACK_TRACE__ 23 | struct stack_trace stack; 24 | unsigned long stack_entries[MALLOC_CHECKER_STACK_ENTRIES]; 25 | char stack_buf[512]; 26 | #endif 27 | #ifdef __MALLOC_CHECKER_DELAY_FREE__ 28 | u32 crc32; 29 | ktime_t time_to_live; 30 | #endif 31 | }; 32 | 33 | struct malloc_checker { 34 | struct list_head entries_list[MALLOC_CHECKER_NR_LISTS]; 35 | spinlock_t entries_list_lock[MALLOC_CHECKER_NR_LISTS]; 36 | atomic64_t nr_allocs; 37 | atomic64_t nr_frees; 38 | #ifdef __MALLOC_CHECKER_DELAY_FREE__ 39 | struct task_struct *delay_check_thread; 40 | struct list_head delay_entries_list[MALLOC_CHECKER_NR_LISTS]; 41 | spinlock_t delay_entries_list_lock[MALLOC_CHECKER_NR_LISTS]; 42 | #endif 43 | }; 44 | 45 | static struct malloc_checker g_malloc_checker; 46 | 47 | #ifdef __MALLOC_CHECKER_DELAY_FREE__ 48 | 49 | static void release_entry(struct malloc_checker *checker, 50 | struct malloc_entry *entry) 51 | { 52 | unsigned long *psign1, *psign2; 53 | void *ptr = entry->ptr; 54 | 55 | psign1 = (unsigned long *)((unsigned long)ptr - sizeof(unsigned long)); 56 | psign2 = (unsigned long *)((unsigned long)ptr + entry->size); 57 | 58 | WARN_ON(*psign1 != MALLOC_CHECKER_SIGN1); 59 | WARN_ON(*psign2 != MALLOC_CHECKER_SIGN2); 60 | 61 | #ifdef __MALLOC_CHECKER_FILL_CC__ 62 | memset(entry->ptr, 0xCC, entry->size); 63 | #endif 64 | 65 | #ifdef __MALLOC_CHECKER_PRINTK__ 66 | PRINTK("free entry %p ptr %p\n", entry, entry->ptr); 67 | #endif 68 | 69 | kfree(psign1); 70 | kfree(entry); 71 | } 72 | 73 | static void delay_check(struct malloc_checker *checker, 74 | struct malloc_entry *entry) 75 | { 76 | unsigned long *psign1, *psign2; 77 | void *ptr = entry->ptr; 78 | 79 | psign1 = (unsigned long *)((unsigned long)ptr - sizeof(unsigned long)); 80 | psign2 = (unsigned long *)((unsigned long)ptr + entry->size); 81 | 82 | WARN_ON(*psign1 != MALLOC_CHECKER_SIGN1); 83 | WARN_ON(*psign2 != MALLOC_CHECKER_SIGN2); 84 | WARN_ON(entry->crc32 != crc32_le(~0, entry->ptr, entry->size)); 85 | 86 | #ifdef __MALLOC_CHECKER_PRINTK__ 87 | PRINTK("delay check entry %p ptr %p\n", entry, entry->ptr); 88 | #endif 89 | } 90 | 91 | static int malloc_checker_delay_thread(void *data) 92 | { 93 | struct malloc_checker *checker = (struct malloc_checker *)data; 94 | unsigned long irq_flags; 95 | struct list_head free_list; 96 | struct malloc_entry *curr, *tmp; 97 | unsigned long i; 98 | 99 | PRINTK("starting\n"); 100 | 101 | while (!kthread_should_stop()) { 102 | msleep(100); 103 | 104 | INIT_LIST_HEAD(&free_list); 105 | for (i = 0; i < ARRAY_SIZE(checker->delay_entries_list); i++) { 106 | 107 | INIT_LIST_HEAD(&free_list); 108 | spin_lock_irqsave(&checker->delay_entries_list_lock[i], 109 | irq_flags); 110 | list_for_each_entry_safe(curr, tmp, 111 | &checker->delay_entries_list[i], 112 | link) { 113 | delay_check(checker, curr); 114 | if (ktime_compare(curr->time_to_live, 115 | ktime_get()) >= 0) { 116 | list_del(&curr->link); 117 | list_add(&curr->link, &free_list); 118 | } 119 | } 120 | spin_unlock_irqrestore( 121 | &checker->delay_entries_list_lock[i], 122 | irq_flags); 123 | } 124 | 125 | list_for_each_entry_safe(curr, tmp, &free_list, link) { 126 | list_del_init(&curr->link); 127 | release_entry(checker, curr); 128 | } 129 | } 130 | 131 | PRINTK("stopping\n"); 132 | 133 | return 0; 134 | } 135 | #endif 136 | 137 | int malloc_checker_init(void) 138 | { 139 | struct malloc_checker *checker = &g_malloc_checker; 140 | unsigned long i; 141 | 142 | PRINTK("malloc checker init\n"); 143 | 144 | atomic64_set(&checker->nr_allocs, 0); 145 | atomic64_set(&checker->nr_frees, 0); 146 | 147 | for (i = 0; i < ARRAY_SIZE(checker->entries_list); i++) { 148 | INIT_LIST_HEAD(&checker->entries_list[i]); 149 | spin_lock_init(&checker->entries_list_lock[i]); 150 | } 151 | 152 | #ifdef __MALLOC_CHECKER_DELAY_FREE__ 153 | { 154 | struct task_struct *thread; 155 | 156 | for (i = 0; i < ARRAY_SIZE(checker->delay_entries_list); i++) { 157 | INIT_LIST_HEAD(&checker->delay_entries_list[i]); 158 | spin_lock_init(&checker->delay_entries_list_lock[i]); 159 | } 160 | 161 | thread = kthread_create(malloc_checker_delay_thread, checker, 162 | "%s", "dmap-malloc-checker"); 163 | if (IS_ERR(thread)) 164 | return PTR_ERR(thread); 165 | 166 | get_task_struct(thread); 167 | checker->delay_check_thread = thread; 168 | wake_up_process(thread); 169 | } 170 | #endif 171 | return 0; 172 | } 173 | 174 | void *malloc_checker_kmalloc(size_t size, gfp_t flags) 175 | { 176 | struct malloc_checker *checker = &g_malloc_checker; 177 | struct malloc_entry *entry; 178 | unsigned long *psign1, *psign2; 179 | void *ptr; 180 | unsigned long i; 181 | unsigned long irq_flags; 182 | 183 | entry = kmalloc(sizeof(*entry), flags); 184 | if (!entry) 185 | return NULL; 186 | 187 | memset(entry, 0, sizeof(*entry)); 188 | 189 | psign1 = kmalloc(size + 2*sizeof(unsigned long), flags); 190 | if (!psign1) { 191 | kfree(entry); 192 | return NULL; 193 | } 194 | 195 | ptr = (void *)((unsigned long)psign1 + sizeof(unsigned long)); 196 | psign2 = (unsigned long *)((unsigned long)ptr + size); 197 | *psign1 = MALLOC_CHECKER_SIGN1; 198 | *psign2 = MALLOC_CHECKER_SIGN2; 199 | 200 | entry->ptr = ptr; 201 | entry->size = size; 202 | entry->flags = flags; 203 | INIT_LIST_HEAD(&entry->link); 204 | 205 | #ifdef __MALLOC_CHECKER_STACK_TRACE__ 206 | entry->stack.nr_entries = 0; 207 | entry->stack.max_entries = ARRAY_SIZE(entry->stack_entries); 208 | entry->stack.entries = entry->stack_entries; 209 | entry->stack.skip = 2; 210 | save_stack_trace(&entry->stack); 211 | snprint_stack_trace(entry->stack_buf, ARRAY_SIZE(entry->stack_buf), 212 | &entry->stack, 0); 213 | #endif 214 | 215 | i = dmap_hash_pointer(ptr) % ARRAY_SIZE(checker->entries_list); 216 | spin_lock_irqsave(&checker->entries_list_lock[i], irq_flags); 217 | list_add(&entry->link, &checker->entries_list[i]); 218 | spin_unlock_irqrestore(&checker->entries_list_lock[i], irq_flags); 219 | 220 | atomic64_inc(&checker->nr_allocs); 221 | 222 | #ifdef __MALLOC_CHECKER_PRINTK__ 223 | PRINTK("alloc entry %p ptr %p\n", entry, entry->ptr); 224 | #endif 225 | 226 | return ptr; 227 | } 228 | 229 | static void check_and_release_entry(struct malloc_checker *checker, 230 | struct malloc_entry *entry) 231 | { 232 | unsigned long *psign1, *psign2; 233 | void *ptr = entry->ptr; 234 | 235 | psign1 = (unsigned long *)((unsigned long)ptr - sizeof(unsigned long)); 236 | psign2 = (unsigned long *)((unsigned long)ptr + entry->size); 237 | 238 | WARN_ON(*psign1 != MALLOC_CHECKER_SIGN1); 239 | WARN_ON(*psign2 != MALLOC_CHECKER_SIGN2); 240 | 241 | #ifdef __MALLOC_CHECKER_FILL_CC__ 242 | memset(entry->ptr, 0xCC, entry->size); 243 | #endif 244 | 245 | #ifdef __MALLOC_CHECKER_PRINTK__ 246 | PRINTK("free entry %p ptr %p\n", entry, entry->ptr); 247 | #endif 248 | 249 | #ifdef __MALLOC_CHECKER_DELAY_FREE__ 250 | entry->crc32 = crc32_le(~0, entry->ptr, entry->size); 251 | entry->time_to_live = ktime_add_ns(ktime_get(), 1000000000); 252 | { 253 | unsigned long irq_flags; 254 | unsigned long i; 255 | 256 | i = hash_pointer(ptr) % ARRAY_SIZE(checker->delay_entries_list); 257 | spin_lock_irqsave(&checker->delay_entries_list_lock[i], 258 | irq_flags); 259 | list_add(&entry->link, &checker->delay_entries_list[i]); 260 | spin_unlock_irqrestore(&checker->delay_entries_list_lock[i], 261 | irq_flags); 262 | } 263 | #else 264 | kfree(psign1); 265 | kfree(entry); 266 | #endif 267 | } 268 | 269 | void malloc_checker_kfree(void *ptr) 270 | { 271 | struct malloc_checker *checker = &g_malloc_checker; 272 | unsigned long i; 273 | unsigned long irq_flags; 274 | struct malloc_entry *curr, *tmp; 275 | struct list_head entries_list; 276 | 277 | INIT_LIST_HEAD(&entries_list); 278 | i = dmap_hash_pointer(ptr) % ARRAY_SIZE(checker->entries_list); 279 | spin_lock_irqsave(&checker->entries_list_lock[i], irq_flags); 280 | list_for_each_entry_safe(curr, tmp, &checker->entries_list[i], link) { 281 | if (curr->ptr == ptr) { 282 | list_del(&curr->link); 283 | list_add(&curr->link, &entries_list); 284 | } 285 | } 286 | 287 | spin_unlock_irqrestore(&checker->entries_list_lock[i], irq_flags); 288 | 289 | list_for_each_entry_safe(curr, tmp, &entries_list, link) { 290 | list_del_init(&curr->link); 291 | check_and_release_entry(checker, curr); 292 | atomic64_inc(&checker->nr_frees); 293 | } 294 | } 295 | 296 | void malloc_checker_deinit(void) 297 | { 298 | unsigned long i; 299 | unsigned long irq_flags; 300 | struct list_head entries_list; 301 | struct malloc_entry *curr, *tmp; 302 | struct malloc_checker *checker = &g_malloc_checker; 303 | 304 | PRINTK("malloc checker deinit: nr_allocs %ld nr_frees %ld\n", 305 | atomic64_read(&checker->nr_allocs), 306 | atomic64_read(&checker->nr_frees)); 307 | 308 | #ifdef __MALLOC_CHECKER_DELAY_FREE__ 309 | kthread_stop(checker->delay_check_thread); 310 | put_task_struct(checker->delay_check_thread); 311 | #endif 312 | 313 | for (i = 0; i < ARRAY_SIZE(checker->entries_list); i++) { 314 | INIT_LIST_HEAD(&entries_list); 315 | spin_lock_irqsave(&checker->entries_list_lock[i], irq_flags); 316 | list_for_each_entry_safe(curr, tmp, &checker->entries_list[i], 317 | link) { 318 | list_del(&curr->link); 319 | list_add(&curr->link, &entries_list); 320 | } 321 | spin_unlock_irqrestore(&checker->entries_list_lock[i], 322 | irq_flags); 323 | 324 | list_for_each_entry_safe(curr, tmp, &entries_list, link) { 325 | list_del_init(&curr->link); 326 | PRINTK("leak entry %p ptr %p size %lu flags 0x%x\n", 327 | curr, curr->ptr, curr->size, curr->flags); 328 | #ifdef __MALLOC_CHECKER_STACK_TRACE__ 329 | PRINTK("leak entry stack %s\n", curr->stack_buf); 330 | #endif 331 | check_and_release_entry(checker, curr); 332 | } 333 | } 334 | 335 | #ifdef __MALLOC_CHECKER_DELAY_FREE__ 336 | for (i = 0; i < ARRAY_SIZE(checker->delay_entries_list); i++) { 337 | INIT_LIST_HEAD(&entries_list); 338 | spin_lock_irqsave(&checker->delay_entries_list_lock[i], 339 | irq_flags); 340 | list_for_each_entry_safe(curr, tmp, 341 | &checker->delay_entries_list[i], 342 | link) { 343 | list_del(&curr->link); 344 | list_add(&curr->link, &entries_list); 345 | } 346 | 347 | spin_unlock_irqrestore(&checker->delay_entries_list_lock[i], 348 | irq_flags); 349 | 350 | list_for_each_entry_safe(curr, tmp, &entries_list, link) { 351 | list_del_init(&curr->link); 352 | delay_check(checker, curr); 353 | release_entry(checker, curr); 354 | } 355 | } 356 | #endif 357 | } 358 | -------------------------------------------------------------------------------- /malloc-checker.h: -------------------------------------------------------------------------------- 1 | #ifndef __DMAP_MALLOC_CHECKER_H__ 2 | #define __DMAP_MALLOC_CHECKER_H__ 3 | 4 | #include 5 | 6 | int malloc_checker_init(void); 7 | void malloc_checker_deinit(void); 8 | 9 | void *malloc_checker_kmalloc(size_t size, gfp_t flags); 10 | void malloc_checker_kfree(void *ptr); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /scripts/cluster.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import os 3 | import sys 4 | import argparse 5 | 6 | from cmd import exec_cmd2 as cmd 7 | from ssh import SshExec as ssh 8 | 9 | log = logging.getLogger() 10 | log.setLevel(logging.DEBUG) 11 | 12 | ch = logging.StreamHandler(sys.stdout) 13 | ch.setLevel(logging.INFO) 14 | formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') 15 | ch.setFormatter(formatter) 16 | log.addHandler(ch) 17 | 18 | def run(cmd, user, password, key, verbose, nodes): 19 | if cmd == "install": 20 | for n in nodes: 21 | s = ssh(log, n, user, password=password, key_file=key) 22 | s.cmd("sudo apt-get update") 23 | s.cmd("sudo apt-get install -y keyutils git gcc make") 24 | s.cmd("git clone https://github.com/irqlevel/dmap ~/dmap") 25 | s.cmd("cd ~/dmap && make") 26 | s.cmd("sudo iptables -F") 27 | elif cmd == "start": 28 | for n in nodes: 29 | s = ssh(log, n, user, password=password, key_file=key) 30 | s.cmd("cd ~/dmap && sudo scripts/start.sh") 31 | s.cmd("sudo ls -al /sys/fs/dmap/") 32 | s.cmd("echo " + n + " 8111 | sudo tee /sys/fs/dmap/start_server") 33 | for n in nodes: 34 | for m in nodes: 35 | if n != m: 36 | s = ssh(log, n, user, password=password, key_file=key) 37 | s.cmd("echo " + m + " 8111 | sudo tee /sys/fs/dmap/add_neighbor", throw=False) 38 | for n in nodes: 39 | s = ssh(log, n, user, password=password, key_file=key) 40 | s.cmd("sudo cat /sys/fs/dmap/neighbors") 41 | 42 | elif cmd == "stop": 43 | for n in nodes: 44 | s = ssh(log, n, user, password=password, key_file=key) 45 | s.cmd("cd ~/dmap && sudo scripts/stop.sh") 46 | elif cmd == "uninstall": 47 | for n in nodes: 48 | s = ssh(log, n, user, password=password, key_file=key) 49 | s.cmd("cd ~/dmap && sudo scripts/stop.sh", throw = False) 50 | s.cmd("sudo rm -rf ~/dmap") 51 | elif cmd == "info": 52 | for n in nodes: 53 | s = ssh(log, n, user, password=password, key_file=key) 54 | s.cmd("hostname") 55 | s.cmd("ifconfig") 56 | elif cmd == "trace": 57 | for n in nodes: 58 | s = ssh(log, n, user, password=password, key_file=key) 59 | s.cmd("sudo cat /sys/kernel/debug/tracing/trace") 60 | elif cmd == "node-info": 61 | for n in nodes: 62 | s = ssh(log, n, user, password=password, key_file=key) 63 | s.cmd("sudo cat /sys/fs/dmap/id") 64 | s.cmd("sudo cat /sys/fs/dmap/nr_keys") 65 | s.cmd("sudo cat /sys/fs/dmap/neighbors") 66 | elif cmd == "dmesg": 67 | for n in nodes: 68 | s = ssh(log, n, user, password=password, key_file=key) 69 | s.cmd("sudo dmesg | tail -n 20") 70 | else: 71 | raise Exception("Unknown cmd %s", cmd) 72 | 73 | if __name__=="__main__": 74 | parser = argparse.ArgumentParser() 75 | parser.add_argument("-v", "--verbose", action="store_true", help="verbose") 76 | parser.add_argument("-u", "--user", action="store", help="user") 77 | parser.add_argument("-p", "--password", action="store", help="password") 78 | parser.add_argument("-k", "--key", action="store", help="access key") 79 | parser.add_argument("command", action="store", help="command") 80 | parser.add_argument("nodes", action="store", help="nodes", nargs="+") 81 | args = parser.parse_args() 82 | run(args.command, args.user, args.password, args.key, args.verbose, args.nodes) 83 | -------------------------------------------------------------------------------- /scripts/cmd.py: -------------------------------------------------------------------------------- 1 | # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 2 | import subprocess 3 | import os 4 | from datetime import datetime 5 | import logging.config 6 | import logging 7 | import uuid 8 | import threading 9 | import copy 10 | import time 11 | import sys 12 | import inspect 13 | import re 14 | 15 | currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) 16 | 17 | def exec_cmd(cmd, output = False, elog = None): 18 | args = cmd.split() 19 | if elog: 20 | elog.info("EXEC:" + cmd + ":" + str(args)) 21 | 22 | if output: 23 | process = subprocess.Popen(args, stdout = subprocess.PIPE, stderr = subprocess.PIPE) 24 | else: 25 | process = subprocess.Popen(args) 26 | 27 | stdout, stderr = process.communicate() 28 | process.wait() 29 | 30 | if elog: 31 | elog.info("EXEC:stdout:" + str(stdout)) 32 | elog.info("EXEC:stderr:" + str(stderr)) 33 | elog.info("EXEC:" + cmd + ":" + str(args) + ":rc=" + str(process.returncode)) 34 | return (process.returncode, stdout, stderr) 35 | 36 | class StdFp(): 37 | def __init__(self, fp, log_extra, elog = None): 38 | self.fp = fp 39 | self.lines = [] 40 | self.lock = threading.Lock() 41 | self.log_extra = log_extra 42 | self.elog = elog 43 | 44 | def append(self, l): 45 | self.lock.acquire() 46 | try: 47 | lp = l.replace("\n", "") 48 | if self.elog: 49 | self.elog.info(self.log_extra + ":" + lp) 50 | self.lines.append(lp) 51 | except Exception as e: 52 | if self.elog: 53 | self.elog.exception(str(e)) 54 | finally: 55 | self.lock.release() 56 | 57 | def get_lines(self): 58 | lines = [] 59 | self.lock.acquire() 60 | try: 61 | lines = copy.deepcopy(self.lines) 62 | except Exception as e: 63 | if self.elog: 64 | self.elog.exception(str(e)) 65 | finally: 66 | self.lock.release() 67 | 68 | return lines 69 | 70 | class StdThread(threading.Thread): 71 | def __init__(self, std_fp): 72 | threading.Thread.__init__(self) 73 | self.std_fp = std_fp 74 | self.stopping = False 75 | def run(self): 76 | while not self.stopping: 77 | l = self.std_fp.fp.readline() 78 | if l == '': 79 | break 80 | self.std_fp.append(l) 81 | 82 | class Cmd(): 83 | def __init__(self, cmd, throw = False, elog = None): 84 | self.cmd = cmd 85 | self.stdout = None 86 | self.stderr = None 87 | self.throw = throw 88 | self.elog = elog 89 | 90 | def run(self): 91 | if self.elog != None: 92 | self.elog.info("CMD:" + self.cmd) 93 | 94 | process = subprocess.Popen(self.cmd, shell=True, stdout = subprocess.PIPE, stderr = subprocess.PIPE) 95 | 96 | self.stdout = StdFp(process.stdout, "CMD:stdout", elog = self.elog) 97 | self.stderr = StdFp(process.stderr, "CMD:stderr", elog = self.elog) 98 | 99 | self.stderr_t = StdThread(self.stderr) 100 | self.stdout_t = StdThread(self.stdout) 101 | 102 | self.stdout_t.start() 103 | self.stderr_t.start() 104 | 105 | process.wait() 106 | 107 | self.stdout_t.join() 108 | self.stderr_t.join() 109 | 110 | self.rc = process.returncode 111 | 112 | #log.info("CMD:" + self.cmd + ":stdout:" + self.stdout.out) 113 | #log.info("CMD:" + self.cmd + ":stderr:" + self.stderr.out) 114 | if self.rc == 0: 115 | if self.elog != None: 116 | self.elog.info("CMD:" + self.cmd + ":rc:" + str(self.rc)) 117 | else: 118 | if self.elog != None: 119 | self.elog.error("CMD:" + self.cmd + ":rc:" + str(self.rc)) 120 | 121 | if self.rc != 0 and self.throw: 122 | raise Exception("CMD:" + self.cmd + ":rc:" + str(self.rc)) 123 | 124 | def exec_cmd2(cmd, throw = False, elog = None): 125 | c = Cmd(cmd, throw = throw, elog = elog) 126 | c.run() 127 | return c.rc , c.stdout.lines, c.stderr.lines, c 128 | 129 | def exec_cmd2_list(cmds, elog = None): 130 | rcs = [] 131 | for cmd in cmds: 132 | c = Cmd(cmd, elog = elog) 133 | c.run() 134 | rcs.append(c.rc) 135 | return rcs 136 | 137 | if __name__=="__main__": 138 | exec_cmd2("ps ax") 139 | -------------------------------------------------------------------------------- /scripts/cmp_files.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | file1=$1 4 | file2=$2 5 | cmp -l $file1 $file2 | gawk '{printf "%08X %02X %02X\n", $1, strtonum(0$2), strtonum(0$3)}' 6 | -------------------------------------------------------------------------------- /scripts/ssh.py: -------------------------------------------------------------------------------- 1 | # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 2 | import paramiko 3 | import os 4 | import sys 5 | import time 6 | import inspect 7 | import logging 8 | 9 | #currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) 10 | #parentdir = os.path.dirname(currentdir) 11 | #sys.path.insert(0,parentdir) 12 | 13 | from cmd import StdFp, StdThread 14 | 15 | def ssh_cmd(ssh, cmd, throw = False, log = None): 16 | if log: 17 | log.info(ssh.get_tag() + cmd) 18 | chan = None 19 | out_lines = [] 20 | err_lines = [] 21 | rc = 777 22 | try: 23 | chan = ssh.get_transport().open_session() 24 | chan.get_pty() 25 | chan.exec_command(cmd) 26 | 27 | stdout = StdFp(chan.makefile(), ssh.get_tag() + "stdout", elog = log) 28 | stderr = StdFp(chan.makefile_stderr(), ssh.get_tag() + "stderr", elog = log) 29 | 30 | stderr_t = StdThread(stderr) 31 | stdout_t = StdThread(stdout) 32 | 33 | stdout_t.start() 34 | stderr_t.start() 35 | 36 | rc = chan.recv_exit_status() 37 | stdout_t.join() 38 | stderr_t.join() 39 | out_lines = stdout.lines 40 | err_lines = stderr.lines 41 | 42 | if rc == 0: 43 | if log: 44 | log.info(ssh.get_tag() + cmd + ":rc:" + str(rc)) 45 | else: 46 | if log: 47 | log.error(ssh.get_tag() + cmd + ":rc:" + str(rc)) 48 | except Exception as e: 49 | if log: 50 | log.exception(str(e)) 51 | finally: 52 | if chan != None: 53 | try: 54 | chan.shutdown(2) 55 | except Exception as e: 56 | if log: 57 | log.exception(str(e)) 58 | 59 | if rc != 0 and throw: 60 | raise Exception(ssh.get_tag() + cmd + ":rc:" + str(rc)) 61 | 62 | return rc, out_lines, err_lines 63 | 64 | class SshExec: 65 | def __init__(self, log, host, user, password = None, key_file = None, timeout = None, ftp = False): 66 | self.host = host 67 | self.user = user 68 | self.password = password 69 | self.key_file = key_file 70 | self.log = log 71 | self.timeout = timeout 72 | 73 | if self.key_file != None: 74 | self.pkey = paramiko.RSAKey.from_private_key_file(self.key_file) 75 | else: 76 | self.pkey = None 77 | 78 | self.ssh = paramiko.SSHClient() 79 | self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 80 | self.ssh.connect(self.host, username=self.user, password = self.password, pkey=self.pkey, timeout = self.timeout) 81 | 82 | if ftp: 83 | self.ftp = self.ssh.open_sftp() 84 | else: 85 | self.ftp = None 86 | self.log.info(self.get_tag() + 'opened ssh to host ' + self.host) 87 | self.ssh.get_tag = self.get_tag 88 | 89 | def cmd(self, cmd, throw = True): 90 | return ssh_cmd(self.ssh, cmd, throw = throw, log = self.log) 91 | 92 | def get_tag(self): 93 | return "SSH:" + self.host + ":" 94 | 95 | def file_get(self, remote_file, local_file): 96 | self.log.info(self.get_tag() + "GETFILE:" + str(self.host) + " remote:" + remote_file + " local:" + local_file) 97 | self.ftp.get(remote_file, local_file) 98 | self.log.info(self.get_tag() + "GETFILE:completed") 99 | def file_put(self, local_file, remote_file): 100 | self.log.info(self.get_tag() + "PUTFILE:" + str(self.host) + " local:" + local_file + " remote:" + remote_file) 101 | self.ftp.put(local_file, remote_file) 102 | self.log.info(self.get_tag() + "PUTFILE:completed") 103 | def file_getcwd(self): 104 | return self.ftp.getcwd() 105 | def file_chdir(self, path): 106 | return self.ftp.chdir(path) 107 | def close(self): 108 | try: 109 | if self.ftp != None: 110 | self.ftp.close() 111 | except: 112 | pass 113 | try: 114 | self.ssh.close() 115 | except: 116 | pass 117 | 118 | class SshUser(): 119 | def __init__(self, log, host, user, password = None, key_file = None, timeout = None, ftp = False): 120 | self.log = log 121 | self.host = host 122 | self.user = user 123 | self.password = password 124 | self.key_file = key_file 125 | self.timeout = timeout 126 | self.ftp = ftp 127 | 128 | def ssh_by_suser(suser): 129 | s = SshExec(suser.log, suser.host, suser.user, password = suser.password, key_file = suser.key_file, timeout = suser.timeout, ftp = suser.ftp) 130 | return s 131 | 132 | def ssh_exec(suser, cmd, throw = True): 133 | s = ssh_by_suser(suser) 134 | rs = None 135 | try: 136 | rs = s.cmd(cmd, throw = throw) 137 | finally: 138 | s.close() 139 | return rs 140 | 141 | def ssh_file_get(suser, remote_file, local_file): 142 | s = ssh_by_suser(suser) 143 | try: 144 | s.file_get(remote_file, local_file) 145 | finally: 146 | s.close() 147 | 148 | def ssh_file_put(suser, local_file, remote_file): 149 | s = ssh_by_suser(suser) 150 | try: 151 | s.file_put(local_file, remote_file) 152 | finally: 153 | s.close() 154 | 155 | if __name__ == '__main__': 156 | ssh = SshExec(None, "10.30.18.211", "root", "1q2w3es5") 157 | ssh.cmd("ps aux") 158 | -------------------------------------------------------------------------------- /scripts/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -xv 2 | 3 | WDIR=temp 4 | 5 | #make clean 6 | make 7 | sync 8 | sync 9 | modprobe dns-resolver 10 | insmod dmap.ko 11 | 12 | rm -rf $WDIR 13 | mkdir -p $WDIR 14 | 15 | echo 0 > /sys/kernel/debug/tracing/tracing_on 16 | echo 'nop' > /sys/kernel/debug/tracing/current_tracer 17 | echo 100000 > /sys/kernel/debug/tracing/buffer_size_kb 18 | echo '' > /sys/kernel/debug/tracing/trace 19 | echo 1 > /sys/kernel/debug/tracing/events/dmap/enable 20 | echo 1 > /sys/kernel/debug/tracing/tracing_on 21 | -------------------------------------------------------------------------------- /scripts/stop.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -xv 2 | 3 | WDIR=temp 4 | 5 | echo 0 > /sys/kernel/debug/tracing/tracing_on 6 | cat /sys/kernel/debug/tracing/trace > $WDIR/trace 7 | echo '' > /sys/kernel/debug/tracing/trace 8 | echo 0 > /sys/kernel/debug/tracing/events/dmap/enable 9 | 10 | rmmod dmap 11 | -------------------------------------------------------------------------------- /scripts/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -xv 2 | 3 | WDIR=temp 4 | 5 | cat /sys/fs/dmap/id 6 | echo 127.0.0.1 8111 > /sys/fs/dmap/start_server 7 | cat /sys/fs/dmap/server 8 | echo bla.com 8111 > /sys/fs/dmap/add_neighbor 9 | echo blabla.com 8111 > /sys/fs/dmap/add_neighbor 10 | cat /sys/fs/dmap/neighbors 11 | --------------------------------------------------------------------------------