OASIS Mailing List ArchivesView the OASIS mailing list archive below
or browse/search using MarkMail.

 


Help: OASIS Mailing Lists Help | MarkMail Help

virtio-dev message

[Date Prev] | [Thread Prev] | [Thread Next] | [Date Next] -- [Date Index] | [Thread Index] | [List Home]


Subject: Re: [PATCH v2 2/2] virtio-fs: add notification queue


On Fri, May 14, 2021 at 12:33:20PM -0400, Vivek Goyal wrote:
> On Mon, Feb 15, 2021 at 09:54:10AM +0000, Stefan Hajnoczi wrote:
> > The FUSE protocol allows the file server (device) to initiate
> > communication with the client (driver) using FUSE notify messages.
> > Normally only the client can initiate communication. This feature is
> > used to report asynchronous events that are not related to an in-flight
> > request.
> > 
> > This patch adds a notification queue that works like an rx queue in
> > other VIRTIO device types. The device can emit FUSE notify messages by
> > using a buffer from this queue.
> > 
> > This mechanism was designed by Vivek Goyal <vgoyal@redhat.com>.
> > 
> > Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
> > ---
> >  conformance.tex |  1 +
> >  virtio-fs.tex   | 71 ++++++++++++++++++++++++++++++++++++++++++-------
> >  2 files changed, 62 insertions(+), 10 deletions(-)
> > 
> > diff --git a/conformance.tex b/conformance.tex
> > index 9a7fe0b..8c2f511 100644
> > --- a/conformance.tex
> > +++ b/conformance.tex
> > @@ -227,6 +227,7 @@ \section{Conformance Targets}\label{sec:Conformance / Conformance Targets}
> >  \begin{itemize}
> >  \item \ref{drivernormative:Device Types / File System Device / Device configuration layout}
> >  \item \ref{drivernormative:Device Types / File System Device / Device Operation / Device Operation: High Priority Queue}
> > +\item \ref{drivernormative:Device Types / File System Device / Device Operation / Device Operation: Notification Queue}
> >  \item \ref{drivernormative:Device Types / File System Device / Device Operation / Device Operation: DAX Window}
> >  \end{itemize}
> >  
> > diff --git a/virtio-fs.tex b/virtio-fs.tex
> > index 158d066..c995748 100644
> > --- a/virtio-fs.tex
> > +++ b/virtio-fs.tex
> > @@ -25,24 +25,33 @@ \subsection{Virtqueues}\label{sec:Device Types / File System Device / Virtqueues
> >  
> >  \begin{description}
> >  \item[0] hiprio
> > -\item[1\ldots n] request queues
> > +\item[1] notification queue
> > +\item[2\ldots n] request queues
> >  \end{description}
> >  
> > +The notification queue only exists if VIRTIO_FS_F_NOTIFICATION is set.
> 
> Hi Stefan,
> 
> Say device is new enough that it sets Feature bit, VIRTIO_FS_F_NOTIFICATION
> but driver is old and does not understand this feature. I am assuming for
> these cases protocol allows for feature negotiation and if driver does not
> acknowledge VIRTIO_FS_F_NOTIFICATION feature, then queue at index 1, will
> be a request queue and not notification queue?

Yes, exactly. The virtqueue layout is only decided when feature
negotiation completes. If the driver did not enable
VIRTIO_FS_F_NOTIFICATION then the bit will be cleared and virtqueues
will use the traditional layout without a notification queue.

> > +
> >  \subsection{Feature bits}\label{sec:Device Types / File System Device / Feature bits}
> >  
> > -There are currently no feature bits defined.
> > +\begin{description}
> > +\item[VIRTIO_FS_F_NOTIFICATION (0)] Device has support for FUSE notify
> > +    messages.  The notification queue is virtqueue 1.
> > +\end{description}
> >  
> >  \subsection{Device configuration layout}\label{sec:Device Types / File System Device / Device configuration layout}
> >  
> > -All fields of this configuration are always available.
> > -
> >  \begin{lstlisting}
> >  struct virtio_fs_config {
> >          char tag[36];
> >          le32 num_request_queues;
> > +        le32 notify_buf_size;
> >  };
> >  \end{lstlisting}
> >  
> > +The \field{tag} and \field{num_request_queues} fields are always available.
> > +The \field{notify_buf_size} field is only available when
> > +VIRTIO_FS_F_NOTIFICATION is set.
> > +
> >  \begin{description}
> >  \item[\field{tag}] is the name associated with this file system.  The tag is
> >      encoded in UTF-8 and padded with NUL bytes if shorter than the
> > @@ -53,6 +62,8 @@ \subsection{Device configuration layout}\label{sec:Device Types / File System De
> >      there are no ordering guarantees between requests made available on
> >      different queues.  Use of multiple queues is intended to increase
> >      performance.
> > +\item[\field{notify_buf_size}] is the minimum number of bytes required for each
> > +    buffer in the notification queue.
> >  \end{description}
> >  
> >  \drivernormative{\subsubsection}{Device configuration layout}{Device Types / File System Device / Device configuration layout}
> > @@ -65,13 +76,20 @@ \subsection{Device configuration layout}\label{sec:Device Types / File System De
> >  
> >  The device MUST set \field{num_request_queues} to 1 or greater.
> >  
> > +The device MUST set \field{notify_buf_size} to be large enough to hold any of
> > +the FUSE notify messages that this device emits.
> > +
> >  \subsection{Device Initialization}\label{Device Types / File System Device / Device Initialization}
> >  
> > -On initialization the driver first discovers the device's virtqueues.  The FUSE
> > -session is started by sending a FUSE\_INIT request as defined by the FUSE
> > -protocol on one request virtqueue.  All virtqueues provide access to the same
> > -FUSE session and therefore only one FUSE\_INIT request is required regardless
> > -of the number of available virtqueues.
> > +On initialization the driver first discovers the device's virtqueues.
> > +
> > +The driver populates the notification queue with buffers for receiving FUSE
> > +notify messages if VIRTIO_FS_F_NOTIFICATION is set.
> > +
> > +The FUSE session is started by sending a FUSE\_INIT request as defined by the
> > +FUSE protocol on one request virtqueue.  All virtqueues provide access to the
> > +same FUSE session and therefore only one FUSE\_INIT request is required
> > +regardless of the number of available virtqueues.
> >  
> >  \subsection{Device Operation}\label{sec:Device Types / File System Device / Device Operation}
> >  
> > @@ -88,7 +106,8 @@ \subsection{Device Operation}\label{sec:Device Types / File System Device / Devi
> >        full.
> >  \end{itemize}
> >  
> > -Note that FUSE notification requests are not supported.
> > +FUSE notify messages are received on the notification queue if
> > +VIRTIO_FS_F_NOTIFICATION is set.
> >  
> >  \subsubsection{Device Operation: Request Queues}\label{sec:Device Types / File System Device / Device Operation / Device Operation: Request Queues}
> >  
> > @@ -179,6 +198,38 @@ \subsubsection{Device Operation: High Priority Queue}\label{sec:Device Types / F
> >  
> >  The driver MUST anticipate that request queues are processed concurrently with the hiprio queue.
> >  
> > +\subsubsection{Device Operation: Notification Queue}\label{sec:Device Types / File System Device / Device Operation / Device Operation: Notification Queue}
> > +
> > +The notification queue is populated with buffers by the driver and these
> > +buffers are used by the device to emit FUSE notify messages.  Notification
> > +queue buffer layout is as follows:
> > +
> > +\begin{lstlisting}
> > +struct virtio_fs_notify {
> > +        // Device-writable part
> > +        struct fuse_out_header out_hdr;
> > +        char outarg[notify_buf_size - sizeof(struct fuse_out_header)];
> > +};
> > +\end{lstlisting}
> > +
> > +\field{outarg} contains the FUSE notify message payload that depends on the
> > +type of notification being emitted.
> > +
> > +If the driver provides notification queue buffers at a slower rate than the
> > +device emits FUSE notify messages then the virtqueue will eventually become
> > +empty.  The behavior in response to an empty virtqueue depends on the FUSE
> > +notify message type:
> 
> So we are right now definiting the behavior of only one notification
> message, FUSE_NOTIFY_LOCK. Others will be filled later? Or it will be
> left to device implementation.

Others will be added to the spec when their use with virtiofs is defined.

> > +\begin{itemize}
> > +\item FUSE\_NOTIFY\_LOCK messages are delivered when buffers become available again. When the device runs out of resources new lock requests fail with ENOLCK.
> 
> So device should check for available notification buffer every time a lock
> request comes in to make sure atleast one buffer is available. But it is
> possible that 5 requests come and only 1 notification buffer is available
> and they all will succeed. And by the time lock is available, 4
> notifications will still have to wait. 
> 
> IOW, we probably should define the notion of buffering of events in 
> device and deliver to driver when notification buffers are available.
> And leave it to device when should it start returning ENOLOCK. Some
> devices might decide to buffer X number of notifications and if number
> of buffered notifications cross X, then start returning ENOLOCK.

I'll reword this part because that's exactly what I meant: the device
has internal resources for blocking FUSE_NOTIFY_LOCK messages. These are
internal resources, they are separate from the empty/full state of the
notification queue. The device will refuse to accept new blocking lock
requests with ENOLCK if it runs out of internal resources.

> I guess we have to return ENOLOCK only for waiting lock messages
> (F_SETLKW). For non-blocking locks, we will immediately return either with
> lock held or with error EACCESS or EAGAIN.
> 
> > +\end{itemize}
> > +
> > +\drivernormative{\paragraph}{Device Operation: Notification Queue}{Device Types / File System Device / Device Operation / Device Operation: Notification Queue}
> > +
> > +The driver MUST provide buffers of at least \field{notify_buf_size} bytes.
> > +
> > +The driver SHOULD replenish notification queue buffers sufficiently quickly so
> > +that there is always at least one available buffer.
> 
> I am wondering how can driver ensure that there is always atleast one
> available buffer. Its possible driver is still processing all
> notifications and leaving a brief interval where notification queue
> is empty. IOW, dirvers can try but can't guarantee this, I guess.

Yes, that is why SHOULD is used instead of MUST. It's a best-effort
thing and the behavior for running out of resources is defined above
(FUSE_NOTIFY_LOCK have device internal resources associated with them so
they can wait for new notification queue buffers to become available
without dropping notifications).

Stefan

Attachment: signature.asc
Description: PGP signature



[Date Prev] | [Thread Prev] | [Thread Next] | [Date Next] -- [Date Index] | [Thread Index] | [List Home]