diff options
-rw-r--r-- | LOCKS | 4 | ||||
-rw-r--r-- | src/server/net.c | 62 | ||||
-rw-r--r-- | src/server/server.c | 5 |
3 files changed, 25 insertions, 46 deletions
@@ -27,8 +27,8 @@ For example, if you hold the lock for client 10 and you need to look up some other client. You MUST NOT simply fetch the _clients_lock now and then iterate over the clients until you find the one you need, -as it violates the above order to first lock on a -client and then the clients lock. +as it violates the above order to first lock on the +clients array and then the clients lock. Instead, you need to release client 10's lock, then lock on _clients_lock and iterate over the clients. Now you check if you either encounter diff --git a/src/server/net.c b/src/server/net.c index f3438cd..8dcce3c 100644 --- a/src/server/net.c +++ b/src/server/net.c @@ -122,9 +122,10 @@ void *net_client_handler(void *dnbd3_client) dnbd3_reply_t reply; dnbd3_image_t *image = NULL; - int image_file = -1, image_cache = -1; + int image_file = -1; int i, num; + int bOk = FALSE; uint64_t map_y; char map_x, bit_mask; @@ -171,10 +172,9 @@ void *net_client_handler(void *dnbd3_client) } else { - pthread_spin_lock(&_spinlock); - image = dnbd3_get_image(image_name, rid, 0); + image = image_get(image_name, rid); const time_t now = time(NULL); - if (!image) + if (image==NULL) { printf("[DEBUG] Client requested non-existent image '%s' (rid:%d), rejected\n", image_name, (int)rid); } @@ -182,57 +182,36 @@ void *net_client_handler(void *dnbd3_client) { printf("[DEBUG] Client requested non-working image '%s' (rid:%d), rejected\n", image_name, (int)rid); } - else if ((image->delete_soft != 0 && image->delete_soft < now) - || (image->delete_hard != 0 && image->delete_hard < now)) - { - printf("[DEBUG] Client requested end-of-life image '%s' (rid:%d), rejected\n", image_name, (int)rid); - } else { - serializer_reset_write(&payload); - serializer_put_uint16(&payload, PROTOCOL_VERSION); - serializer_put_string(&payload, image->low_name); - serializer_put_uint16(&payload, image->rid); - serializer_put_uint64(&payload, image->filesize); - reply.cmd = CMD_SELECT_IMAGE; - reply.size = serializer_get_written_length(&payload); - if (!send_reply(client->sock, &reply, &payload)) - { - image = NULL; - } - else + image_file = open(image->path, O_RDONLY); + if (image_file >= 0) { - if (image->file) - { - image_file = open(image->file, O_RDONLY); - if (image_file == -1) - { - image = NULL; - } - } - if (image) + serializer_reset_write(&payload); + serializer_put_uint16(&payload, PROTOCOL_VERSION); + serializer_put_string(&payload, image->lower_name); + serializer_put_uint16(&payload, image->rid); + serializer_put_uint64(&payload, image->filesize); + reply.cmd = CMD_SELECT_IMAGE; + reply.size = serializer_get_written_length(&payload); + if (send_reply(client->sock, &reply, &payload)) { client->image = image; if (!client->is_server) image->atime = time(NULL); // TODO: check if mutex is needed - if (image->cache_map && image->cache_file) - image_cache = open(image->cache_file, O_RDWR); - else if (image->cache_map) - printf("[BUG] Image has cache_map but no cache file!\n"); - else if (image->cache_file) - printf("[BUG] Image has cache_file but not cache map!\n"); + bOk = TRUE; } } } - pthread_spin_unlock(&_spinlock); } } } } // client handling mainloop - if (image) while (recv_request_header(client->sock, &request)) + if (bOk) + {while (recv_request_header(client->sock, &request)) { switch (request.cmd) { @@ -421,13 +400,12 @@ void *net_client_handler(void *dnbd3_client) } } - pthread_spin_lock(&_spinlock); - _dnbd3_clients = g_slist_remove(_dnbd3_clients, client); - pthread_spin_unlock(&_spinlock); +} if (client->sock != -1) close(client->sock); if (image_file != -1) close(image_file); - if (image_cache != -1) close(image_cache); + image_release(image); + client->image = image = NULL; dnbd3_free_client(client); pthread_exit((void *) 0); } diff --git a/src/server/server.c b/src/server/server.c index e4e2dd8..2c4cf42 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -298,11 +298,12 @@ dnbd3_client_t* dnbd3_init_client(struct sockaddr_storage *client, int fd) } /** - * Free the client struct recursively + * Free the client struct recursively. + * Doesn't lock, so call this function after removing the client from _dnbd3_clients */ void dnbd3_free_client(dnbd3_client_t *client) { - GSList *it; // Doesn't lock, so call this function after removing the client from _dnbd3_clients + GSList *it; for (it = client->sendqueue; it; it = it->next) { free( it->data ); } |