Skip to content

Commit 23272a6

Browse files
author
Markus Pargmann
committed
nbd: Remove signal usage
As discussed on the mailing list, the usage of signals for timeout handling has a lot of potential issues. The nbd driver used for some time signals for timeouts. These signals where able to get the threads out of the blocking socket operations. This patch removes all signal usage and uses a socket shutdown instead. The socket descriptor itself is cleared later when the whole nbd device is closed. The tasks_lock is removed as we do not depend on this anymore. Instead a new lock for the socket is introduced so we can safely work with the socket in the timeout handler outside of the two main threads. Cc: Oleg Nesterov <[email protected]> Cc: Christoph Hellwig <[email protected]> Signed-off-by: Markus Pargmann <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]>
1 parent 27ea43f commit 23272a6

File tree

1 file changed

+48
-78
lines changed

1 file changed

+48
-78
lines changed

drivers/block/nbd.c

Lines changed: 48 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ struct nbd_device {
6060
bool disconnect; /* a disconnect has been requested by user */
6161

6262
struct timer_list timeout_timer;
63-
spinlock_t tasks_lock;
63+
/* protects initialization and shutdown of the socket */
64+
spinlock_t sock_lock;
6465
struct task_struct *task_recv;
6566
struct task_struct *task_send;
6667

@@ -129,13 +130,20 @@ static void nbd_end_request(struct nbd_device *nbd, struct request *req)
129130
*/
130131
static void sock_shutdown(struct nbd_device *nbd)
131132
{
132-
if (!nbd->sock)
133+
spin_lock_irq(&nbd->sock_lock);
134+
135+
if (!nbd->sock) {
136+
spin_unlock_irq(&nbd->sock_lock);
133137
return;
138+
}
134139

135140
dev_warn(disk_to_dev(nbd->disk), "shutting down socket\n");
136141
kernel_sock_shutdown(nbd->sock, SHUT_RDWR);
142+
sockfd_put(nbd->sock);
137143
nbd->sock = NULL;
138-
del_timer_sync(&nbd->timeout_timer);
144+
spin_unlock_irq(&nbd->sock_lock);
145+
146+
del_timer(&nbd->timeout_timer);
139147
}
140148

141149
static void nbd_xmit_timeout(unsigned long arg)
@@ -148,17 +156,15 @@ static void nbd_xmit_timeout(unsigned long arg)
148156

149157
nbd->disconnect = true;
150158

151-
spin_lock_irqsave(&nbd->tasks_lock, flags);
159+
spin_lock_irqsave(&nbd->sock_lock, flags);
152160

153-
if (nbd->task_recv)
154-
force_sig(SIGKILL, nbd->task_recv);
155161

156-
if (nbd->task_send)
157-
force_sig(SIGKILL, nbd->task_send);
162+
if (nbd->sock)
163+
kernel_sock_shutdown(nbd->sock, SHUT_RDWR);
158164

159-
spin_unlock_irqrestore(&nbd->tasks_lock, flags);
165+
spin_unlock_irqrestore(&nbd->sock_lock, flags);
160166

161-
dev_err(nbd_to_dev(nbd), "Connection timed out, killed receiver and sender, shutting down connection\n");
167+
dev_err(nbd_to_dev(nbd), "Connection timed out, shutting down connection\n");
162168
}
163169

164170
/*
@@ -171,7 +177,6 @@ static int sock_xmit(struct nbd_device *nbd, int send, void *buf, int size,
171177
int result;
172178
struct msghdr msg;
173179
struct kvec iov;
174-
sigset_t blocked, oldset;
175180
unsigned long pflags = current->flags;
176181

177182
if (unlikely(!sock)) {
@@ -181,11 +186,6 @@ static int sock_xmit(struct nbd_device *nbd, int send, void *buf, int size,
181186
return -EINVAL;
182187
}
183188

184-
/* Allow interception of SIGKILL only
185-
* Don't allow other signals to interrupt the transmission */
186-
siginitsetinv(&blocked, sigmask(SIGKILL));
187-
sigprocmask(SIG_SETMASK, &blocked, &oldset);
188-
189189
current->flags |= PF_MEMALLOC;
190190
do {
191191
sock->sk->sk_allocation = GFP_NOIO | __GFP_MEMALLOC;
@@ -212,7 +212,6 @@ static int sock_xmit(struct nbd_device *nbd, int send, void *buf, int size,
212212
buf += result;
213213
} while (size > 0);
214214

215-
sigprocmask(SIG_SETMASK, &oldset, NULL);
216215
tsk_restore_flags(current, pflags, PF_MEMALLOC);
217216

218217
if (!send && nbd->xmit_timeout)
@@ -406,23 +405,18 @@ static int nbd_thread_recv(struct nbd_device *nbd)
406405
{
407406
struct request *req;
408407
int ret;
409-
unsigned long flags;
410408

411409
BUG_ON(nbd->magic != NBD_MAGIC);
412410

413411
sk_set_memalloc(nbd->sock->sk);
414412

415-
spin_lock_irqsave(&nbd->tasks_lock, flags);
416413
nbd->task_recv = current;
417-
spin_unlock_irqrestore(&nbd->tasks_lock, flags);
418414

419415
ret = device_create_file(disk_to_dev(nbd->disk), &pid_attr);
420416
if (ret) {
421417
dev_err(disk_to_dev(nbd->disk), "device_create_file failed!\n");
422418

423-
spin_lock_irqsave(&nbd->tasks_lock, flags);
424419
nbd->task_recv = NULL;
425-
spin_unlock_irqrestore(&nbd->tasks_lock, flags);
426420

427421
return ret;
428422
}
@@ -439,19 +433,7 @@ static int nbd_thread_recv(struct nbd_device *nbd)
439433

440434
device_remove_file(disk_to_dev(nbd->disk), &pid_attr);
441435

442-
spin_lock_irqsave(&nbd->tasks_lock, flags);
443436
nbd->task_recv = NULL;
444-
spin_unlock_irqrestore(&nbd->tasks_lock, flags);
445-
446-
if (signal_pending(current)) {
447-
ret = kernel_dequeue_signal(NULL);
448-
dev_warn(nbd_to_dev(nbd), "pid %d, %s, got signal %d\n",
449-
task_pid_nr(current), current->comm, ret);
450-
mutex_lock(&nbd->tx_lock);
451-
sock_shutdown(nbd);
452-
mutex_unlock(&nbd->tx_lock);
453-
ret = -ETIMEDOUT;
454-
}
455437

456438
return ret;
457439
}
@@ -544,11 +526,8 @@ static int nbd_thread_send(void *data)
544526
{
545527
struct nbd_device *nbd = data;
546528
struct request *req;
547-
unsigned long flags;
548529

549-
spin_lock_irqsave(&nbd->tasks_lock, flags);
550530
nbd->task_send = current;
551-
spin_unlock_irqrestore(&nbd->tasks_lock, flags);
552531

553532
set_user_nice(current, MIN_NICE);
554533
while (!kthread_should_stop() || !list_empty(&nbd->waiting_queue)) {
@@ -557,17 +536,6 @@ static int nbd_thread_send(void *data)
557536
kthread_should_stop() ||
558537
!list_empty(&nbd->waiting_queue));
559538

560-
if (signal_pending(current)) {
561-
int ret = kernel_dequeue_signal(NULL);
562-
563-
dev_warn(nbd_to_dev(nbd), "pid %d, %s, got signal %d\n",
564-
task_pid_nr(current), current->comm, ret);
565-
mutex_lock(&nbd->tx_lock);
566-
sock_shutdown(nbd);
567-
mutex_unlock(&nbd->tx_lock);
568-
break;
569-
}
570-
571539
/* extract request */
572540
if (list_empty(&nbd->waiting_queue))
573541
continue;
@@ -582,13 +550,7 @@ static int nbd_thread_send(void *data)
582550
nbd_handle_req(nbd, req);
583551
}
584552

585-
spin_lock_irqsave(&nbd->tasks_lock, flags);
586553
nbd->task_send = NULL;
587-
spin_unlock_irqrestore(&nbd->tasks_lock, flags);
588-
589-
/* Clear maybe pending signals */
590-
if (signal_pending(current))
591-
kernel_dequeue_signal(NULL);
592554

593555
return 0;
594556
}
@@ -636,6 +598,25 @@ static void nbd_request_handler(struct request_queue *q)
636598
}
637599
}
638600

601+
static int nbd_set_socket(struct nbd_device *nbd, struct socket *sock)
602+
{
603+
int ret = 0;
604+
605+
spin_lock_irq(&nbd->sock_lock);
606+
607+
if (nbd->sock) {
608+
ret = -EBUSY;
609+
goto out;
610+
}
611+
612+
nbd->sock = sock;
613+
614+
out:
615+
spin_unlock_irq(&nbd->sock_lock);
616+
617+
return ret;
618+
}
619+
639620
static int nbd_dev_dbg_init(struct nbd_device *nbd);
640621
static void nbd_dev_dbg_close(struct nbd_device *nbd);
641622

@@ -668,32 +649,26 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
668649
return 0;
669650
}
670651

671-
case NBD_CLEAR_SOCK: {
672-
struct socket *sock = nbd->sock;
673-
nbd->sock = NULL;
652+
case NBD_CLEAR_SOCK:
653+
sock_shutdown(nbd);
674654
nbd_clear_que(nbd);
675655
BUG_ON(!list_empty(&nbd->queue_head));
676656
BUG_ON(!list_empty(&nbd->waiting_queue));
677657
kill_bdev(bdev);
678-
if (sock)
679-
sockfd_put(sock);
680658
return 0;
681-
}
682659

683660
case NBD_SET_SOCK: {
684-
struct socket *sock;
685661
int err;
686-
if (nbd->sock)
687-
return -EBUSY;
688-
sock = sockfd_lookup(arg, &err);
689-
if (sock) {
690-
nbd->sock = sock;
691-
if (max_part > 0)
692-
bdev->bd_invalidated = 1;
693-
nbd->disconnect = false; /* we're connected now */
694-
return 0;
695-
}
696-
return -EINVAL;
662+
struct socket *sock = sockfd_lookup(arg, &err);
663+
664+
if (!sock)
665+
return err;
666+
667+
err = nbd_set_socket(nbd, sock);
668+
if (!err && max_part)
669+
bdev->bd_invalidated = 1;
670+
671+
return err;
697672
}
698673

699674
case NBD_SET_BLKSIZE:
@@ -734,7 +709,6 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
734709

735710
case NBD_DO_IT: {
736711
struct task_struct *thread;
737-
struct socket *sock;
738712
int error;
739713

740714
if (nbd->task_recv)
@@ -769,14 +743,10 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
769743
mutex_lock(&nbd->tx_lock);
770744

771745
sock_shutdown(nbd);
772-
sock = nbd->sock;
773-
nbd->sock = NULL;
774746
nbd_clear_que(nbd);
775747
kill_bdev(bdev);
776748
queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, nbd->disk->queue);
777749
set_device_ro(bdev, false);
778-
if (sock)
779-
sockfd_put(sock);
780750
nbd->flags = 0;
781751
nbd->bytesize = 0;
782752
bdev->bd_inode->i_size = 0;
@@ -1042,7 +1012,7 @@ static int __init nbd_init(void)
10421012
nbd_dev[i].magic = NBD_MAGIC;
10431013
INIT_LIST_HEAD(&nbd_dev[i].waiting_queue);
10441014
spin_lock_init(&nbd_dev[i].queue_lock);
1045-
spin_lock_init(&nbd_dev[i].tasks_lock);
1015+
spin_lock_init(&nbd_dev[i].sock_lock);
10461016
INIT_LIST_HEAD(&nbd_dev[i].queue_head);
10471017
mutex_init(&nbd_dev[i].tx_lock);
10481018
init_timer(&nbd_dev[i].timeout_timer);

0 commit comments

Comments
 (0)