diff mbox

[1/3] nvme: do not check for ns on rw path

Message ID 1509703370-20379-2-git-send-email-javier@cnexlabs.com (mailing list archive)
State New, archived
Headers show

Commit Message

=?UTF-8?q?Javier=20Gonz=C3=A1lez?= Nov. 3, 2017, 10:02 a.m. UTC
On the rw path, the ns is assumed to be set. However, a check is still
done, inherited from the time the code resided at nvme_queue_rq().

Eliminate this check, which also eliminates a smatch complain for not
doing proper NULL checks on ns.

Signed-off-by: Javier González <javier@cnexlabs.com>
---
 drivers/nvme/host/core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Comments

Christoph Hellwig Nov. 3, 2017, 12:53 p.m. UTC | #1
> -	if (ns && ns->ms &&
> +	if (ns->ms &&
>  	    (!ns->pi_type || ns->ms != sizeof(struct t10_pi_tuple)) &&
>  	    !blk_integrity_rq(req) && !blk_rq_is_passthrough(req))
>  		return BLK_STS_NOTSUPP;

blk_rq_is_passthrough also can't be true here.

How about:

	if (ns->ms && !blk_integrity_rq(req) &&
	    (!ns->pi_type || ns->ms != sizeof(struct t10_pi_tuple)))
		return BLK_STS_NOTSUPP;

Although I have to admit I don't really understand what this check
is even trying to do.  It basically checks for a namespace that has
a format with metadata that is not T10 protection information and
then rejects all I/O to it.  Why are we even creating a block device
node for such a thing?
=?UTF-8?q?Javier=20Gonz=C3=A1lez?= Nov. 3, 2017, 1 p.m. UTC | #2
> On 3 Nov 2017, at 13.53, Christoph Hellwig <hch@lst.de> wrote:
> 
>> -	if (ns && ns->ms &&
>> +	if (ns->ms &&
>> 	    (!ns->pi_type || ns->ms != sizeof(struct t10_pi_tuple)) &&
>> 	    !blk_integrity_rq(req) && !blk_rq_is_passthrough(req))
>> 		return BLK_STS_NOTSUPP;
> 
> blk_rq_is_passthrough also can't be true here.
> 
> How about:
> 
> 	if (ns->ms && !blk_integrity_rq(req) &&
> 	    (!ns->pi_type || ns->ms != sizeof(struct t10_pi_tuple)))
> 		return BLK_STS_NOTSUPP;
> 

Sure.

> Although I have to admit I don't really understand what this check
> is even trying to do.  It basically checks for a namespace that has
> a format with metadata that is not T10 protection information and
> then rejects all I/O to it.  Why are we even creating a block device
> node for such a thing?

Looking at the history (i) the check has changed location and (ii) some
checks have been added through time. So it looks like leftovers from
here and there.

If we end up not needing these checks at all here, you can just fix it
all in the same commit. Just wanted to get rid of sparse/smatch
complains...
Keith Busch Nov. 3, 2017, 3:02 p.m. UTC | #3
On Fri, Nov 03, 2017 at 01:53:40PM +0100, Christoph Hellwig wrote:
> > -	if (ns && ns->ms &&
> > +	if (ns->ms &&
> >  	    (!ns->pi_type || ns->ms != sizeof(struct t10_pi_tuple)) &&
> >  	    !blk_integrity_rq(req) && !blk_rq_is_passthrough(req))
> >  		return BLK_STS_NOTSUPP;
> 
> blk_rq_is_passthrough also can't be true here.
> 
> How about:
> 
> 	if (ns->ms && !blk_integrity_rq(req) &&
> 	    (!ns->pi_type || ns->ms != sizeof(struct t10_pi_tuple)))
> 		return BLK_STS_NOTSUPP;
> 
> Although I have to admit I don't really understand what this check
> is even trying to do.  It basically checks for a namespace that has
> a format with metadata that is not T10 protection information and
> then rejects all I/O to it.  Why are we even creating a block device
> node for such a thing?

If the namespace has metadata, but the request doesn't have a metadata
payload attached to it for whatever reason, we can't construct the command
for that format. We also can't have the controller strip/generate the
payload with PRACT bit set if it's not a T10 format, so we just fail
the command.
Christoph Hellwig Nov. 4, 2017, 8:18 a.m. UTC | #4
On Fri, Nov 03, 2017 at 09:02:04AM -0600, Keith Busch wrote:
> If the namespace has metadata, but the request doesn't have a metadata
> payload attached to it for whatever reason, we can't construct the command
> for that format. We also can't have the controller strip/generate the
> payload with PRACT bit set if it's not a T10 format, so we just fail
> the command.

The only metadata payload a READ or WRITE request can have is a protection
information one.  For a namespace formatted with protection information
bio_integrity_prep as called from blk_mq_make_request will ensure we
always have metadata attached.

If a namespace is formatted with non-PI metadata we will never have
metadata attached to the bio/request and should not even present the
namespace to the kernel.
Keith Busch Nov. 4, 2017, 3:38 p.m. UTC | #5
On Sat, Nov 04, 2017 at 09:18:25AM +0100, Christoph Hellwig wrote:
> On Fri, Nov 03, 2017 at 09:02:04AM -0600, Keith Busch wrote:
> > If the namespace has metadata, but the request doesn't have a metadata
> > payload attached to it for whatever reason, we can't construct the command
> > for that format. We also can't have the controller strip/generate the
> > payload with PRACT bit set if it's not a T10 format, so we just fail
> > the command.
> 
> The only metadata payload a READ or WRITE request can have is a protection
> information one.  For a namespace formatted with protection information
> bio_integrity_prep as called from blk_mq_make_request will ensure we
> always have metadata attached.
> 
> If a namespace is formatted with non-PI metadata we will never have
> metadata attached to the bio/request and should not even present the
> namespace to the kernel.

That's not quite right. For non-PI metadata formats, we use the
'nop_profile', which gets the metadata buffer allocated so we can safely
use a metadata formatted namespace. There's no in-kernel user of the
allocated payload, but we still need the metadata buffer in order to
use the namespace at all.
Christoph Hellwig Nov. 6, 2017, 9:13 a.m. UTC | #6
On Sat, Nov 04, 2017 at 09:38:45AM -0600, Keith Busch wrote:
> That's not quite right. For non-PI metadata formats, we use the
> 'nop_profile', which gets the metadata buffer allocated so we can safely
> use a metadata formatted namespace. There's no in-kernel user of the
> allocated payload, but we still need the metadata buffer in order to
> use the namespace at all.

You're right.  But that means we will indeed always have a matching
integrity payload here and the check should not be needed.

Are you fine with turning it into something like:

	if (WARN_ON_ONCE(ns->ms && !blk_integrity_rq(req)))
		return BLK_STS_IOERR;

?
Keith Busch Nov. 6, 2017, 2:43 p.m. UTC | #7
On Mon, Nov 06, 2017 at 10:13:24AM +0100, Christoph Hellwig wrote:
> On Sat, Nov 04, 2017 at 09:38:45AM -0600, Keith Busch wrote:
> > That's not quite right. For non-PI metadata formats, we use the
> > 'nop_profile', which gets the metadata buffer allocated so we can safely
> > use a metadata formatted namespace. There's no in-kernel user of the
> > allocated payload, but we still need the metadata buffer in order to
> > use the namespace at all.
> 
> You're right.  But that means we will indeed always have a matching
> integrity payload here and the check should not be needed.
> 
> Are you fine with turning it into something like:
> 
> 	if (WARN_ON_ONCE(ns->ms && !blk_integrity_rq(req)))
> 		return BLK_STS_IOERR;
> 
> ?

Yes, that looks fine. You're right that we are not supposed to be able
to get into this path for read/write since the driver sets the capacity
to 0 if a metadata format doesn't have integrity support, so hitting
this warning would indicate something has gone wrong.
diff mbox

Patch

diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 5a14cc7f28ee..bd1d5ff911c9 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -472,7 +472,7 @@  static inline blk_status_t nvme_setup_rw(struct nvme_ns *ns,
 	 * unless this namespace is formated such that the metadata can be
 	 * stripped/generated by the controller with PRACT=1.
 	 */
-	if (ns && ns->ms &&
+	if (ns->ms &&
 	    (!ns->pi_type || ns->ms != sizeof(struct t10_pi_tuple)) &&
 	    !blk_integrity_rq(req) && !blk_rq_is_passthrough(req))
 		return BLK_STS_NOTSUPP;