linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Pranay Srivastava <pranjas@gmail.com>
To: Markus Pargmann <mpa@pengutronix.de>
Cc: "nbd-general@lists.sourceforge.net" 
	<nbd-general@lists.sourceforge.net>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH v4 2/5]nbd: fix might_sleep warning on socket shutdown
Date: Thu, 14 Jul 2016 11:29:08 +0530	[thread overview]
Message-ID: <CA+aCy1G7bJBoE719FrBvtBPSBtfo1vH+H50bFwzBE08+RT8F8g@mail.gmail.com> (raw)
In-Reply-To: <2779831.bWu4zaVOJ5@adelgunde>

On Wed, Jul 13, 2016 at 12:43 PM, Markus Pargmann <mpa@pengutronix.de> wrote:
> On Sunday 10 July 2016 21:03:05 Pranay Srivastava wrote:
>> On Sunday, July 10, 2016, Markus Pargmann <mpa@pengutronix.de> wrote:
>> > Hi,
>> >
>> > On 2016 M06 30, Thu 14:02:02 CEST Pranay Kr. Srivastava wrote:
>> >> spinlocked ranges should be small and not contain calls into huge
>> >> subfunctions. Fix my mistake and just get the pointer to the socket
>> >> instead of doing everything with spinlock held.
>> >>
>> >> Reported-by: Mikulas Patocka <mikulas@twibright.com>
>> >> Signed-off-by: Markus Pargmann <mpa@pengutronix.de>
>> >>
>> >> Changelog:
>> >> Pranay Kr. Srivastava<pranjas@gmail.com>:
>> >>
>> >> 1) Use spin_lock instead of irq version for sock_shutdown.
>> >>
>> >> 2) Use system work queue to actually trigger the shutdown of
>> >> socket. This solves the issue when kernel_sendmsg is currently
>> >> blocked while a timeout occurs.
>> >>
>> >> Signed-off-by: Pranay Kr. Srivastava <pranjas@gmail.com>
>> >> ---
>> >>  drivers/block/nbd.c | 57
>> >> +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 36
>> >> insertions(+), 21 deletions(-)
>> >>
>> >> diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
>> >> index 766c401..e362d44 100644
>> >> --- a/drivers/block/nbd.c
>> >> +++ b/drivers/block/nbd.c
>> >> @@ -39,6 +39,7 @@
>> >>  #include <asm/types.h>
>> >>
>> >>  #include <linux/nbd.h>
>> >> +#include <linux/workqueue.h>
>> >>
>> >>  struct nbd_device {
>> >>       u32 flags;
>> >> @@ -69,6 +70,8 @@ struct nbd_device {
>> >>  #if IS_ENABLED(CONFIG_DEBUG_FS)
>> >>       struct dentry *dbg_dir;
>> >>  #endif
>> >> +     /* This is specifically for calling sock_shutdown, for now. */
>> >> +     struct work_struct ws_shutdown;
>> >>  };
>> >>
>> >>  #if IS_ENABLED(CONFIG_DEBUG_FS)
>> >> @@ -95,6 +98,8 @@ static int max_part;
>> >>   */
>> >>  static DEFINE_SPINLOCK(nbd_lock);
>> >>
>> >> +static void nbd_ws_func_shutdown(struct work_struct *);
>> >> +
>> >
>> > are you reading all the comments I had?...
>> >
>> > At least respond to my comments if you disagree. I still can't see the
>> benefit
>> > of a function signature here if we can avoid it.
>> >
>>
>> That would require some code to be moved. So to avoid those
>> unnecessary changes it was better to have a prototype.
>>
>> It would've pissed you off more if I had tried
>> to get rid of protoype.
>
> Ah I see, thanks.
>
>>
>> >>  static inline struct device *nbd_to_dev(struct nbd_device *nbd)
>> >>  {
>> >>       return disk_to_dev(nbd->disk);
>> >> @@ -172,39 +177,36 @@ static void nbd_end_request(struct nbd_device *nbd,
>> >> struct request *req) */
>> >>  static void sock_shutdown(struct nbd_device *nbd)
>> >>  {
>> >> -     spin_lock_irq(&nbd->sock_lock);
>> >> -
>> >> -     if (!nbd->sock) {
>> >> -             spin_unlock_irq(&nbd->sock_lock);
>> >> -             return;
>> >> -     }
>> >> +     struct socket *sock;
>> >>
>> >> -     dev_warn(disk_to_dev(nbd->disk), "shutting down socket\n");
>> >> -     kernel_sock_shutdown(nbd->sock, SHUT_RDWR);
>> >> -     sockfd_put(nbd->sock);
>> >> +     spin_lock(&nbd->sock_lock);
>> >> +     sock = nbd->sock;
>> >>       nbd->sock = NULL;
>> >> -     spin_unlock_irq(&nbd->sock_lock);
>> >> +     spin_unlock(&nbd->sock_lock);
>> >> +
>> >> +     if (!sock)
>> >> +             return;
>> >>
>> >>       del_timer(&nbd->timeout_timer);
>> >> +     dev_warn(disk_to_dev(nbd->disk), "shutting down socket\n");
>> >> +     kernel_sock_shutdown(sock, SHUT_RDWR);
>> >> +     sockfd_put(sock);
>> >>  }
>> >>
>> >>  static void nbd_xmit_timeout(unsigned long arg)
>> >>  {
>> >>       struct nbd_device *nbd = (struct nbd_device *)arg;
>> >> -     unsigned long flags;
>> >>
>> >>       if (list_empty(&nbd->queue_head))
>> >>               return;
>> >>
>> >> -     spin_lock_irqsave(&nbd->sock_lock, flags);
>> >> -
>> >>       nbd->timedout = true;
>> >> -
>> >> -     if (nbd->sock)
>> >> -             kernel_sock_shutdown(nbd->sock, SHUT_RDWR);
>> >> -
>> >> -     spin_unlock_irqrestore(&nbd->sock_lock, flags);
>> >> -
>> >> +     /*
>> >> +      * Make sure sender thread sees nbd->timedout.
>> >> +      */
>> >> +     smp_wmb();
>> >> +     schedule_work(&nbd->ws_shutdown);
>> >> +     wake_up(&nbd->waiting_wq);
>> >>       dev_err(nbd_to_dev(nbd), "Connection timed out, shutting down
>> >> connection\n"); }
>> >>
>> >> @@ -588,7 +590,11 @@ static int nbd_thread_send(void *data)
>> >>               spin_unlock_irq(&nbd->queue_lock);
>> >>
>> >>               /* handle request */
>> >> -             nbd_handle_req(nbd, req);
>> >> +             if (nbd->timedout) {
>> >> +                     req->errors++;
>> >> +                     nbd_end_request(nbd, req);
>> >> +             } else
>> >> +                     nbd_handle_req(nbd, req);
>> >
>> > I already commented on this in the last patch. This is unrelated to the
>> patch.
>> > If you disagree then please tell me why instead of sending the same thing
>> > again.
>> >
>>
>> After trigerring worker thread its
>> not necessary that socket shutdown
>> actually was called before we handled
>> a request.
>>
>> So the error would come in
>> actually later probably.
>>
>> So i just wanted to avoid a longer
>> path for error to be thrown up.
>> Do correct me if this cant happen.
>
> Yes socket shutdown may not have been called when we reach this error
> handling code. But the timeout timer is usually in the range of seconds.
> I would assume that the time between triggering the worker and socket
> shutdown is within a few milliseconds. We would need to hit exactly this
> condition which would require a new request to be present.
>
> I think this is very unlikely and it would be fine if we have a longer
> error path there. Am I missing something?

Okay but let's do the socket check under the sock_lock as the sock teardown
is done without tx_lock? Probably be better to have a new function to
check this what do you say?

>
>
> Also I just noticed that wake_up(&nbd->waiting_wq) in nbd_xmit_timeout()
> may not be necessary. In nbd_thread_send():
>
>         wait_event_interruptible(nbd->waiting_wq,
>                                  kthread_should_stop() ||
>                                  !list_empty(&nbd->waiting_queue));
>
>         if (list_empty(&nbd->waiting_queue))
>                 continue;
>
> So wouldn't this wake_up() call simply result in nothing?
> As soon as sock_shutdown() was called, the receiver thread would exit
> and close down nbd_thread_send() as well because of kthread_should_stop().
>

To be honest I don't remember now why I put it there. But yeah you are right
about this. I'll have to check it, shouldn't be a problem though.

>>
>> > Also brackets on the else part would be preferred.
>>
>> It might trigger checkpatch warning
>> but I am not 100% sure.
>
> Documentation/CodingStyle documents this. See line 168.

Okay.

>
> Best Regards,
>
> Markus
>
>> >
>> > Regards,
>> >
>> > Markus
>> >
>> >>       }
>> >>
>> >>       nbd->task_send = NULL;
>> >> @@ -663,6 +669,7 @@ static void nbd_reset(struct nbd_device *nbd)
>> >>       set_capacity(nbd->disk, 0);
>> >>       nbd->flags = 0;
>> >>       nbd->xmit_timeout = 0;
>> >> +     INIT_WORK(&nbd->ws_shutdown, nbd_ws_func_shutdown);
>> >>       queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, nbd->disk->queue);
>> >>       del_timer_sync(&nbd->timeout_timer);
>> >>  }
>> >> @@ -797,11 +804,11 @@ static int __nbd_ioctl(struct block_device *bdev,
>> >> struct nbd_device *nbd, error = nbd_thread_recv(nbd, bdev);
>> >>               nbd_dev_dbg_close(nbd);
>> >>               kthread_stop(thread);
>> >> +             sock_shutdown(nbd);
>> >>
>> >>               mutex_lock(&nbd->tx_lock);
>> >>               nbd->task_recv = NULL;
>> >>
>> >> -             sock_shutdown(nbd);
>> >>               nbd_clear_que(nbd);
>> >>               kill_bdev(bdev);
>> >>               nbd_bdev_reset(bdev);
>> >> @@ -857,6 +864,14 @@ static const struct block_device_operations
>> nbd_fops =
>> >> { .compat_ioctl =     nbd_ioctl,
>> >>  };
>> >>
>> >> +static void nbd_ws_func_shutdown(struct work_struct *ws_nbd)
>> >> +{
>> >> +     struct nbd_device *nbd_dev = container_of(ws_nbd, struct
>> nbd_device,
>> >> +                     ws_shutdown);
>> >> +
>> >> +     sock_shutdown(nbd_dev);
>> >> +}
>> >> +
>> >>  #if IS_ENABLED(CONFIG_DEBUG_FS)
>> >>
>> >>  static int nbd_dbg_tasks_show(struct seq_file *s, void *unused)
>> >
>> >
>> >
>>
>>
>
> --
> Pengutronix e.K.                           |                             |
> Industrial Linux Solutions                 | http://www.pengutronix.de/  |
> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |



-- 
        ---P.K.S

  reply	other threads:[~2016-07-14  5:59 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-06-30 11:02 [PATCH v4 0/4] nbd: nbd fixes Pranay Kr. Srivastava
2016-06-30 11:02 ` [PATCH v4 1/5]nbd: cleanup nbd_set_socket Pranay Kr. Srivastava
2016-07-07 14:56   ` Pranay Srivastava
2016-07-09  7:36     ` Pranay Srivastava
2016-06-30 11:02 ` [PATCH v4 2/5]nbd: fix might_sleep warning on socket shutdown Pranay Kr. Srivastava
2016-07-04  7:06   ` Pranay Srivastava
2016-07-10 12:25   ` Markus Pargmann
     [not found]     ` <CA+aCy1GZo6Vk9Yy1KXWgyVhcGmVETyuPuhQT=pSVDVxi5qr8ww@mail.gmail.com>
2016-07-13  7:13       ` Markus Pargmann
2016-07-14  5:59         ` Pranay Srivastava [this message]
2016-07-16  9:22           ` Pranay Kr Srivastava
2016-07-16  9:22             ` [PATCH v5 2/4] nbd: fix might_sleep warning on socket shutdown Pranay Kr Srivastava
2016-07-16 10:14               ` Pranay Srivastava
2016-06-30 11:02 ` [PATCH v4 3/5]nbd: make nbd device wait for its users Pranay Kr. Srivastava
2016-07-10 13:02   ` Markus Pargmann
2016-07-10 16:02     ` Pranay Srivastava
2016-07-13  7:54       ` Markus Pargmann
2016-07-14  5:47         ` Pranay Srivastava
2016-07-16 10:36           ` [PATCH v5 3/4] " Pranay Kr Srivastava
2016-07-16 10:42             ` Pranay Srivastava
2016-07-20  7:47             ` Markus Pargmann
2016-06-30 11:02 ` [PATCH v4 4/5]nbd: use i_size_write to assign nbd device size Pranay Kr. Srivastava

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CA+aCy1G7bJBoE719FrBvtBPSBtfo1vH+H50bFwzBE08+RT8F8g@mail.gmail.com \
    --to=pranjas@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mpa@pengutronix.de \
    --cc=nbd-general@lists.sourceforge.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).