From f2efd7f97baf6ab5d590ac7642bbf7317f8c47ed Mon Sep 17 00:00:00 2001 From: sr Date: Thu, 18 Jul 2013 13:47:01 +0200 Subject: kernel module changes --- src/kernel/blk.c | 12 ++++++++++-- src/kernel/net.c | 28 ++++++++++++++++++---------- src/server/locks.c | 43 ++++++++++++++++++++++++++++--------------- src/server/locks.h | 4 +++- src/server/server.c | 15 ++++++++++----- 5 files changed, 69 insertions(+), 33 deletions(-) (limited to 'src') diff --git a/src/kernel/blk.c b/src/kernel/blk.c index 938a0e8..2bb70de 100644 --- a/src/kernel/blk.c +++ b/src/kernel/blk.c @@ -106,6 +106,11 @@ int dnbd3_blk_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, u dnbd3_ioctl_t *msg = NULL; //unsigned long irqflags; + while (dev->disconnecting) + { + // do nothing + } + if (arg != 0) { msg = kmalloc(sizeof(*msg), GFP_KERNEL); @@ -232,6 +237,7 @@ void dnbd3_blk_request(struct request_queue *q) { struct request *req; dnbd3_device_t *dev; + unsigned long flags; while ((req = blk_fetch_request(q)) != NULL) { @@ -261,7 +267,9 @@ void dnbd3_blk_request(struct request_queue *q) continue; } + spin_lock_irqsave(&dev->blk_lock, flags); list_add_tail(&req->queuelist, &dev->request_queue_send); + spin_unlock_irqrestore(&dev->blk_lock, flags); spin_unlock_irq(q->queue_lock); wake_up(&dev->process_queue_send); spin_lock_irq(q->queue_lock); @@ -276,7 +284,7 @@ void dnbd3_blk_fail_all_requests(dnbd3_device_t *dev) struct list_head local_copy; int dup; INIT_LIST_HEAD(&local_copy); - spin_lock_irq(&dev->blk_lock); + spin_lock_irqsave(&dev->blk_lock, flags); while (!list_empty(&dev->request_queue_receive)) { list_for_each_entry_safe(blk_request, tmp_request, &dev->request_queue_receive, queuelist) @@ -313,7 +321,7 @@ void dnbd3_blk_fail_all_requests(dnbd3_device_t *dev) if (!dup) list_add(&blk_request->queuelist, &local_copy); } } - spin_unlock_irq(&dev->blk_lock); + spin_unlock_irqrestore(&dev->blk_lock, flags); list_for_each_entry_safe(blk_request, tmp_request, &local_copy, queuelist) { list_del_init(&blk_request->queuelist); diff --git a/src/kernel/net.c b/src/kernel/net.c index 0217d26..24fc4d6 100644 --- a/src/kernel/net.c +++ b/src/kernel/net.c @@ -124,6 +124,11 @@ int dnbd3_net_connect(dnbd3_device_t *dev) char get_servers = 0, set_client = 0; + while (dev->disconnecting) + { + if (dev->better_sock) schedule(); + } + timeout.tv_sec = SOCKET_TIMEOUT_CLIENT_DATA; timeout.tv_usec = 0; @@ -313,14 +318,16 @@ error: int dnbd3_net_disconnect(dnbd3_device_t *dev) { + if (dev->disconnecting) + return 0; + if (dev->cur_server.host.port) debug_dev("INFO: Disconnecting device."); dev->disconnecting = 1; // clear heartbeat timer - if (&dev->hb_timer) - del_timer(&dev->hb_timer); + del_timer(&dev->hb_timer); dev->discover = 0; @@ -455,9 +462,9 @@ int dnbd3_net_discover(void *data) for (;;) { wait_event_interruptible(dev->process_queue_discover, - kthread_should_stop() || dev->discover); + kthread_should_stop() || dev->discover || dev->thread_discover == NULL); - if (kthread_should_stop() || dev->imgname == NULL) + if (kthread_should_stop() || dev->imgname == NULL || dev->thread_discover == NULL) break; if (!dev->discover) @@ -467,7 +474,7 @@ int dnbd3_net_discover(void *data) if (dev->reported_size < 4096) continue; - // Check if the list of alt servers needs to be updated and do so if neccessary + // Check if the list of alt servers needs to be updated and do so if necessary if (dev->new_servers_num) { spin_lock_irqsave(&dev->blk_lock, irqflags); @@ -555,10 +562,10 @@ int dnbd3_net_discover(void *data) iov[0].iov_base = &dnbd3_request; iov[0].iov_len = sizeof(dnbd3_request); serializer_reset_write(payload); - serializer_put_uint16(payload, PROTOCOL_VERSION); - serializer_put_string(payload, dev->imgname); - serializer_put_uint16(payload, dev->rid); - serializer_put_uint8(payload, 1); // Pretend we're a proxy here to prevent the server from updating the atime TODO: Update status on server switch + serializer_put_uint16(payload, PROTOCOL_VERSION); // DNBD3 protocol version + serializer_put_string(payload, dev->imgname); // image name + serializer_put_uint16(payload, dev->rid); // revision id + serializer_put_uint8(payload, 0); // are we a server? (no!) iov[1].iov_base = payload; dnbd3_request.size = iov[1].iov_len = serializer_get_written_length(payload); fixup_request(dnbd3_request); @@ -604,6 +611,7 @@ int dnbd3_net_discover(void *data) // panic mode, take first responding server if (dev->panic) { + dev->panic = 0; debug_alt("WARN: Panic mode, changing server:"); if (best_sock != NULL) sock_release(best_sock); dev->better_sock = sock; // Pass over socket to take a shortcut in *_connect(); @@ -717,7 +725,7 @@ error: dnbd3_blk_fail_all_requests(dev); } - if (best_server == -1 || kthread_should_stop()) // No alt server could be reached at all or thread should stop + if (best_server == -1 || kthread_should_stop() || dev->thread_discover == NULL) // No alt server could be reached at all or thread should stop { if (best_sock != NULL) // Should never happen actually { diff --git a/src/server/locks.c b/src/server/locks.c index 050fa4e..9e8d4ad 100644 --- a/src/server/locks.c +++ b/src/server/locks.c @@ -205,32 +205,45 @@ void debug_dump_lock_stats() static void *debug_thread_watchdog(void *something) { - while (!_shutdown) { - time_t now = time(NULL); - pthread_spin_lock( &initdestory ); - for (int i = 0; i < MAXTHREADS; ++i) { - if ( threads[i].tid == 0 ) continue; - const int diff = now - threads[i].time; - if ( diff > 6 && diff < 100000 ) { - printf("\n\n +++++++++ DEADLOCK ++++++++++++\n\n"); - pthread_spin_unlock( &initdestory ); - debug_dump_lock_stats(); - exit(99); + while ( !_shutdown ) { + if (init_done) { + time_t now = time( NULL ); + pthread_spin_lock( &initdestory ); + for (int i = 0; i < MAXTHREADS; ++i) { + if ( threads[i].tid == 0 ) continue; + const int diff = now - threads[i].time; + if ( diff > 6 && diff < 100000 ) { + printf( "\n\n +++++++++ DEADLOCK ++++++++++++\n\n" ); + pthread_spin_unlock( &initdestory ); + debug_dump_lock_stats(); + exit( 99 ); + } } + pthread_spin_unlock( &initdestory ); } - pthread_spin_unlock( &initdestory ); - sleep(10); + sleep( 10 ); } - return NULL; + return NULL ; } +#endif + void debug_locks_start_watchdog() { +#ifdef _DEBUG if ( 0 != pthread_create( &watchdog, NULL, &debug_thread_watchdog, (void *)NULL ) ) { memlogf( "[ERROR] Could not start debug-lock watchdog." ); return; } - pthread_detach( watchdog ); +#endif } +void debug_locks_stop_watchdog() +{ +#ifdef _DEBUG + _shutdown = TRUE; + pthread_spin_lock( &initdestory ); + pthread_spin_unlock( &initdestory ); + pthread_join( watchdog, NULL ); #endif +} diff --git a/src/server/locks.h b/src/server/locks.h index 6558558..5d4367b 100644 --- a/src/server/locks.h +++ b/src/server/locks.h @@ -15,7 +15,6 @@ int debug_spin_lock(const char *name, const char *file, int line, pthread_spinlo int debug_spin_unlock(const char *name, const char *file, int line, pthread_spinlock_t *lock); int debug_spin_destroy(const char *name, const char *file, int line, pthread_spinlock_t *lock); -void debug_locks_start_watchdog(); void debug_dump_lock_stats(); #else @@ -27,4 +26,7 @@ void debug_dump_lock_stats(); #endif +void debug_locks_start_watchdog(); +void debug_locks_stop_watchdog(); + #endif /* LOCKS_H_ */ diff --git a/src/server/server.c b/src/server/server.c index 38635c9..6e49eb0 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -96,6 +96,7 @@ void dnbd3_cleanup() { int i; + _shutdown = TRUE; memlogf( "INFO: Cleanup...\n" ); for (int i = 0; i < socket_count; ++i) { @@ -108,6 +109,7 @@ void dnbd3_cleanup() // Clean up clients spin_lock( &_clients_lock ); for (i = 0; i < _num_clients; ++i) { + if ( _clients[i] == NULL ) continue; dnbd3_client_t * const client = _clients[i]; spin_lock( &client->lock ); if ( client->sock >= 0 ) shutdown( client->sock, SHUT_RDWR ); @@ -122,11 +124,14 @@ void dnbd3_cleanup() // Clean up images spin_lock( &_images_lock ); for (i = 0; i < _num_images; ++i) { + if ( _images[i] == NULL ) continue; _images[i] = image_free( _images[i] ); } _num_images = 0; spin_unlock( &_images_lock ); + debug_locks_stop_watchdog(); + exit( EXIT_SUCCESS ); } @@ -335,11 +340,11 @@ dnbd3_client_t* dnbd3_free_client(dnbd3_client_t *client) { spin_lock( &client->lock ); /* - for (it = client->sendqueue; it; it = it->next) { - free( it->data ); - } - g_slist_free( client->sendqueue ); - */ + for (it = client->sendqueue; it; it = it->next) { + free( it->data ); + } + g_slist_free( client->sendqueue ); + */ if ( client->sock >= 0 ) close( client->sock ); client->sock = -1; if ( client->image != NULL ) image_release( client->image ); -- cgit v1.2.3-55-g7522