[dm-devel] [PATCH 1/2] multipath-tools/libmultipath: Support for the native NVMe Ioctl command.

Yang Feng philip.yang at huawei.com
Fri Jul 21 03:30:47 UTC 2017


Dear Martin,

Thanks a lot for your reviews.
Please find my replys as follows.
And the up-to-date patch will be sent later.

Regards,
-Yang

On 2017/7/21 1:50, Martin Wilck wrote:
> Dear Yang,
> 
> On Thu, 2017-07-20 at 11:36 +0800, Yang Feng wrote:
>> 1. The SCSI-to-NVMe translations have been removed in the patch
>> "nvme:
>> Remove SCSI translations" in the linux-nvme, so the native NVMe Ioctl
>> command should be supported in the multipath-tools.
> 
>> 2. In the prioritizers/path_latency.c, modify the func
>> do_readsector0():
>> send a native NVMe Read Ioctl command to the nvme device, and send a
>> SG
>> Read Ioctl command to the scsi device.
> 
> As noted previously, I would prefer to use a directio command here. I
> see no advantage of using sg or nvme ioctls over directio.
> 
Thanks, insteadly, directio will be used.

>> 3. In the tur checker, add support for the native NVMe Keep Alive
>> Ioctl
>> command to the nvme device.
> 
> No, please don't. I'm still with Xose here. There's no need to use the
> same checker for NVMe and SCSI devices. This is what we have the
> hwtable for. Keep the tur checker as it was before, create a keepalive
> checker for NVMe, and use hwtable entries to match them appropriately
> to devices.
> 
OK, it will be fixed.

> See below for some details. 
> NAK from my side for the patch in this form.
> 
> Martin
> 
>>
>> Signed-off-by: Yang Feng <philip.yang at huawei.com>
>> Reviewed-by: Martin Wilck <mwilck at suse.com>
>> Reviewed-by: Xose Vazquez Perez <xose.vazquez at gmail.com>
>> ---
>>  libmultipath/checkers.c                  |   7 ++
>>  libmultipath/checkers.h                  |   4 +
>>  libmultipath/checkers/Makefile           |   4 +-
>>  libmultipath/checkers/emc_clariion.c     |   4 +-
>>  libmultipath/checkers/libsg.c            |  94 -------------------
> 
> IIRC you did this in your previous patch already. Can you give a good
> reason for moving this code? It makes your patch unnecessarily big and
> messes up git history. If it's REALLY necessary, separate it out,
> please.
>
OK, the libsg.c/libsg.h will not be moved.
> 
>> ---
>>  libmultipath/checkers/libsg.h            |   9 ---
>>  libmultipath/checkers/readsector0.c      |   4 +-
>>  libmultipath/checkers/tur.c              |  64 ++++++++++-----
>>  libmultipath/discovery.c                 |   1 +
>>  libmultipath/libnvme.c                   | 130
>> +++++++++++++++++++++++++++++++
>>  libmultipath/libnvme.h                   |  10 +++
>>  libmultipath/libsg.c                     | 113
>> +++++++++++++++++++++++++++
>>  libmultipath/libsg.h                     |  13 ++++
>>  libmultipath/prioritizers/Makefile       |   2 +-
>>  libmultipath/prioritizers/path_latency.c |  34 +++++---
>>  multipath/multipath.conf.5               |   2 +-
>>  16 files changed, 354 insertions(+), 141 deletions(-)
>>  delete mode 100644 libmultipath/checkers/libsg.c
>>  delete mode 100644 libmultipath/checkers/libsg.h
>>  create mode 100644 libmultipath/libnvme.c
>>  create mode 100644 libmultipath/libnvme.h
>>  create mode 100644 libmultipath/libsg.c
>>  create mode 100644 libmultipath/libsg.h
>>
>> diff --git a/libmultipath/checkers.c b/libmultipath/checkers.c
>> index 05e024f..00fbd6e 100644
>> --- a/libmultipath/checkers.c
>> +++ b/libmultipath/checkers.c
>> @@ -162,6 +162,13 @@ void checker_set_fd (struct checker * c, int fd)
>>  	c->fd = fd;
>>  }
>>  
>> +void checker_set_dev(struct checker *c, char *dev)
>> +{
>> +    if (!c)
>> +        return;
>> +    strncpy(c->dev, dev, strlen(dev)+1);
>> +}
>> +
>>  void checker_set_sync (struct checker * c)
>>  {
>>  	if (!c)
>> diff --git a/libmultipath/checkers.h b/libmultipath/checkers.h
>> index 1d225de..f924624 100644
>> --- a/libmultipath/checkers.h
>> +++ b/libmultipath/checkers.h
>> @@ -97,6 +97,8 @@ enum path_check_state {
>>  #define CHECKER_DEV_LEN 256
>>  #define LIB_CHECKER_NAMELEN 256
>>  
>> +#define FILE_NAME_SIZE  256
>> +
>>  struct checker {
>>  	struct list_head node;
>>  	void *handle;
>> @@ -107,6 +109,7 @@ struct checker {
>>  	int disable;
>>  	char name[CHECKER_NAME_LEN];
>>  	char message[CHECKER_MSG_LEN];       /* comm with callers */
>> +    char dev[FILE_NAME_SIZE];
> 
> FILE_NAME_SIZE more memory usage only to distinguish SCSI from NVMe.
> Please, no.
> 
OK, it will be fixed.
> 
>>  	void * context;                      /* store for persistent
>> data */
>>  	void ** mpcontext;                   /* store for persistent
>> data shared
>>  						multipath-wide. Use
>> MALLOC if
>> @@ -132,6 +135,7 @@ void checker_reset (struct checker *);
>>  void checker_set_sync (struct checker *);
>>  void checker_set_async (struct checker *);
>>  void checker_set_fd (struct checker *, int);
>> +void checker_set_dev(struct checker *c, char *dev);
>>  void checker_enable (struct checker *);
>>  void checker_disable (struct checker *);
>>  void checker_repair (struct checker *);
>> diff --git a/libmultipath/checkers/Makefile
>> b/libmultipath/checkers/Makefile
>> index bce6b8b..a9be6b6 100644
>> --- a/libmultipath/checkers/Makefile
>> +++ b/libmultipath/checkers/Makefile
>> @@ -24,10 +24,10 @@ all: $(LIBS)
>>  libcheckrbd.so: rbd.o
>>  	$(CC) $(LDFLAGS) $(SHARED_FLAGS) -o $@ $^ -lrados -ludev
>>  
>> -libcheckdirectio.so: libsg.o directio.o
>> +libcheckdirectio.so: ../libsg.o ../libnvme.o directio.o
>>  	$(CC) $(LDFLAGS) $(SHARED_FLAGS) -o $@ $^ -laio
>>  
>> -libcheck%.so: libsg.o %.o
>> +libcheck%.so: ../libsg.o ../libnvme.o %.o
>>  	$(CC) $(LDFLAGS) $(SHARED_FLAGS) -o $@ $^
>>  
>>  install:
>> diff --git a/libmultipath/checkers/emc_clariion.c
>> b/libmultipath/checkers/emc_clariion.c
>> index 9c1ffed..12c1e3e 100644
>> --- a/libmultipath/checkers/emc_clariion.c
>> +++ b/libmultipath/checkers/emc_clariion.c
>> @@ -12,7 +12,7 @@
>>  #include <errno.h>
>>  
>>  #include "../libmultipath/sg_include.h"
>> -#include "libsg.h"
>> +#include "../libmultipath/libsg.h"
>>  #include "checkers.h"
>>  #include "debug.h"
>>  #include "memory.h"
>> @@ -21,6 +21,8 @@
>>  #define INQUIRY_CMDLEN  6
>>  #define HEAVY_CHECK_COUNT       10
>>  
>> +#define SENSE_BUFF_LEN  32
>> +
>>  /*
>>   * Mechanism to track CLARiiON inactive snapshot LUs.
>>   * This is done so that we can fail passive paths
>> diff --git a/libmultipath/checkers/libsg.c
>> b/libmultipath/checkers/libsg.c
>> deleted file mode 100644
> 
> See above
> 
>> diff --git a/libmultipath/checkers/libsg.h
>> b/libmultipath/checkers/libsg.h
>> deleted file mode 100644
>> index 3994f45..0000000
>> --- a/libmultipath/checkers/libsg.h
>> +++ /dev/null
>> @@ -1,9 +0,0 @@
>> -#ifndef _LIBSG_H
>> -#define _LIBSG_H
>> -
>> -#define SENSE_BUFF_LEN 32
>> -
>> -int sg_read (int sg_fd, unsigned char * buff, int buff_len,
>> -	     unsigned char * sense, int sense_len, unsigned int
>> timeout);
>> -
>> -#endif /* _LIBSG_H */
>> diff --git a/libmultipath/checkers/readsector0.c
>> b/libmultipath/checkers/readsector0.c
>> index 8fccb46..e485810 100644
>> --- a/libmultipath/checkers/readsector0.c
>> +++ b/libmultipath/checkers/readsector0.c
>> @@ -4,11 +4,13 @@
>>  #include <stdio.h>
>>  
>>  #include "checkers.h"
>> -#include "libsg.h"
>> +#include "../libmultipath/libsg.h"
>>  
>>  #define MSG_READSECTOR0_UP	"readsector0 checker reports path
>> is up"
>>  #define MSG_READSECTOR0_DOWN	"readsector0 checker reports
>> path is down"
>>  
>> +#define SENSE_BUFF_LEN 32
>> +
>>  struct readsector0_checker_context {
>>  	void * dummy;
>>  };
>> diff --git a/libmultipath/checkers/tur.c
>> b/libmultipath/checkers/tur.c
>> index b4a5cb2..a0382fa 100644
>> --- a/libmultipath/checkers/tur.c
>> +++ b/libmultipath/checkers/tur.c
>> @@ -1,5 +1,8 @@
>>  /*
>> - * Some code borrowed from sg-utils.
>> + * Some code borrowed from sg-utils and
>> + * NVM-Express command line utility,
>> + * including using of a TUR command and
>> + * a Keep Alive command.
>>   *
>>   * Copyright (c) 2004 Christophe Varoqui
>>   */
>> @@ -22,10 +25,10 @@
>>  #include "../libmultipath/sg_include.h"
>>  #include "../libmultipath/util.h"
>>  #include "../libmultipath/time-util.h"
>> -#include "../libmultipath/util.h"
>> +#include "../libmultipath/libsg.h"
>> +#include "../libmultipath/libnvme.h"
>>  
>> -#define TUR_CMD_LEN 6
>> -#define HEAVY_CHECK_COUNT       10
>> +#define SENSE_BUFF_LEN   32
>>  
>>  #define MSG_TUR_UP	"tur checker reports path is up"
>>  #define MSG_TUR_DOWN	"tur checker reports path is down"
>> @@ -39,6 +42,7 @@ struct tur_checker_context {
>>  	int state;
>>  	int running;
>>  	int fd;
>> +	char dev[FILE_NAME_SIZE];
> 
> see above
> 
>>  	unsigned int timeout;
>>  	time_t time;
>>  	pthread_t thread;
>> @@ -75,6 +79,7 @@ int libcheck_init (struct checker * c)
>>  	ct->state = PATH_UNCHECKED;
>>  	ct->fd = -1;
>>  	ct->holders = 1;
>> +    memset(ct->dev, 0, sizeof(ct->dev));
>>  	pthread_cond_init_mono(&ct->active);
>>  	pthread_mutexattr_init(&attr);
>>  	pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
>> @@ -133,22 +138,12 @@ tur_check(int fd, unsigned int timeout,
>>  	  void (*copy_message)(void *, const char *), void *cb_arg)
>>  {
>>  	struct sg_io_hdr io_hdr;
>> -	unsigned char turCmdBlk[TUR_CMD_LEN] = { 0x00, 0, 0, 0, 0, 0
>> };
>> -	unsigned char sense_buffer[32];
>> +	unsigned char sense_buffer[SENSE_BUFF_LEN];
>>  	int retry_tur = 5;
>>  
>>  retry:
>> -	memset(&io_hdr, 0, sizeof (struct sg_io_hdr));
>> -	memset(&sense_buffer, 0, 32);
>> -	io_hdr.interface_id = 'S';
>> -	io_hdr.cmd_len = sizeof (turCmdBlk);
>> -	io_hdr.mx_sb_len = sizeof (sense_buffer);
>> -	io_hdr.dxfer_direction = SG_DXFER_NONE;
>> -	io_hdr.cmdp = turCmdBlk;
>> -	io_hdr.sbp = sense_buffer;
>> -	io_hdr.timeout = timeout * 1000;
>> -	io_hdr.pack_id = 0;
>> -	if (ioctl(fd, SG_IO, &io_hdr) < 0) {
>> +	if (sg_tur(fd, &io_hdr, sense_buffer,
>> +        sizeof(sense_buffer), timeout) < 0) {
>>  		TUR_MSG(MSG_TUR_DOWN);
>>  		return PATH_DOWN;
>>  	}
>> @@ -213,6 +208,35 @@ retry:
>>  	return PATH_UP;
>>  }
>>  
>> +static int
>> +keep_alive_check(int fd, unsigned int timeout,
>> +	  void (*copy_message)(void *, const char *), void *cb_arg)
>> +{
>> +    int err;
>> +
>> +    err = nvme_keep_alive(fd, timeout);
>> +    if (err == 0) {
>> +        TUR_MSG(MSG_TUR_UP);
>> +        return PATH_UP;
>> +	}
>> +
>> +	TUR_MSG(MSG_TUR_DOWN);
>> +	return PATH_DOWN;
>> +}
>> +
>> +static int
>> +ping_check(int fd, char *dev, unsigned int timeout,
>> +	  void (*copy_message)(void *, const char *), void *cb_arg)
>> +{
>> +    if (!strncmp(dev, "nvme", 4))
>> +    {
>> +        return keep_alive_check(fd, timeout, copy_message, cb_arg);
>> +    }
>> +    else
>> +    {
>> +        return tur_check(fd, timeout, copy_message, cb_arg);
>> +    }
>> +}
>>  #define tur_thread_cleanup_push(ct)
>> pthread_cleanup_push(cleanup_func, ct)
>>  #define tur_thread_cleanup_pop(ct) pthread_cleanup_pop(1)
>>  
>> @@ -266,8 +290,7 @@ static void *tur_thread(void *ctx)
>>  	ct->state = PATH_PENDING;
>>  	ct->message[0] = '\0';
>>  	pthread_mutex_unlock(&ct->lock);
>> -
>> -	state = tur_check(ct->fd, ct->timeout, copy_msg_to_tcc, ct-
>>> message);
>> +    state = ping_check(ct->fd, ct->dev, ct->timeout,
>> copy_msg_to_tcc, ct->message);
>>  	pthread_testcancel();
>>  
>>  	/* TUR checker done */
>> @@ -390,6 +413,7 @@ int libcheck_check(struct checker * c)
>>  		/* Start new TUR checker */
>>  		ct->state = PATH_UNCHECKED;
>>  		ct->fd = c->fd;
>> +        strncpy(ct->dev, c->dev, strlen(c->dev)+1);
> 
> You seem to have some whitespace issues.
Thanks, it will be fixed.
> 
>>  		ct->timeout = c->timeout;
>>  		pthread_spin_lock(&ct->hldr_lock);
>>  		ct->holders++;
>> @@ -406,7 +430,7 @@ int libcheck_check(struct checker * c)
>>  			ct->thread = 0;
>>  			condlog(3, "%s: failed to start tur thread,
>> using"
>>  				" sync mode", tur_devt(devt,
>> sizeof(devt), ct));
>> -			return tur_check(c->fd, c->timeout,
>> +			return ping_check(c->fd, c->dev, c->timeout,
>>  					 copy_msg_to_checker, c);
>>  		}
>>  		tur_timeout(&tsp);
>> diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
>> index 663c8ea..bae5d24 100644
>> --- a/libmultipath/discovery.c
>> +++ b/libmultipath/discovery.c
>> @@ -1539,6 +1539,7 @@ get_state (struct path * pp, struct config
>> *conf, int daemon)
>>  			return PATH_UNCHECKED;
>>  		}
>>  		checker_set_fd(c, pp->fd);
>> +        checker_set_dev(c, pp->dev);
>>  		if (checker_init(c, pp->mpp?&pp->mpp-
>>> mpcontext:NULL)) {
>>  			memset(c, 0x0, sizeof(struct checker));
>>  			condlog(3, "%s: checker init failed", pp-
>>> dev);
>> diff --git a/libmultipath/libnvme.c b/libmultipath/libnvme.c
>> new file mode 100644
>> index 0000000..97c9125
>> --- /dev/null
>> +++ b/libmultipath/libnvme.c
>> @@ -0,0 +1,130 @@
>> +/*
>> + * (C) Copyright HUAWEI Technology Corp. 2017, All Rights Reserved.
>> + *
>> + * libnvme.c
>> + *
>> + * Some code borrowed from NVM-Express command line utility.
>> + *
>> + * Author(s): Yang Feng <philip.yang at huawei.com>
>> + *
>> + * This file is released under the GPL version 2, or any later
>> version.
>> + *
>> + */
>> +#include <linux/types.h>
>> +#include <sys/ioctl.h>
>> +#include <stdint.h>
>> +
>> +struct nvme_user_io {
>> +    __u8    opcode;
>> +    __u8    flags;
>> +    __u16   control;
>> +    __u16   nblocks;
>> +    __u16   rsvd;
>> +    __u64   metadata;
>> +    __u64   addr;
>> +    __u64   slba;
>> +    __u32   dsmgmt;
>> +    __u32   reftag;
>> +    __u16   apptag;
>> +    __u16   appmask;
>> +};
> 
> Please simply include linux/nvme_ioctl.h. Makefiles should check if
> that file exists and compile the nvme stuff conditionally. 
> 
OK, it will be added.
>> +
>> +struct nvme_admin_cmd {
>> +    __u8    opcode;
>> +    __u8    flags;
>> +    __u16   rsvd1;
>> +    __u32   nsid;
>> +    __u32   cdw2;
>> +    __u32   cdw3;
>> +    __u64   metadata;
>> +    __u64   addr;
>> +    __u32   metadata_len;
>> +    __u32   data_len;
>> +    __u32   cdw10;
>> +    __u32   cdw11;
>> +    __u32   cdw12;
>> +    __u32   cdw13;
>> +    __u32   cdw14;
>> +    __u32   cdw15;
>> +    __u32   timeout_ms;
>> +    __u32   result;
>> +};
>> +
>> +#define NVME_IOCTL_ADMIN_CMD    _IOWR('N', 0x41, struct
>> nvme_admin_cmd)
>> +#define NVME_IOCTL_SUBMIT_IO    _IOW('N', 0x42, struct nvme_user_io)
>> +
>> +static int nvme_io(int fd, __u8 opcode, __u64 slba, __u16 nblocks,
>> __u16 control,
>> +            __u32 dsmgmt, __u32 reftag, __u16 apptag, __u16 appmask,
>> void *data,
>> +            void *metadata)
>> +{
>> +    struct nvme_user_io io = {
>> +    .opcode = opcode,
>> +    .flags = 0,
>> +    .control = control,
>> +    .nblocks = nblocks,
>> +    .rsvd = 0,
>> +    .metadata = (__u64)(uintptr_t) metadata,
>> +    .addr = (__u64)(uintptr_t) data,
>> +    .slba = slba,
>> +    .dsmgmt = dsmgmt,
>> +    .reftag = reftag,
>> +    .appmask = apptag,
>> +    .apptag = appmask,
>> +    };
>> +
>> +    return ioctl(fd, NVME_IOCTL_SUBMIT_IO, &io);
>> +}
>> +
>> +int nvme_read(int fd, __u64 slba, __u16 nblocks, __u16 control,
>> __u32 dsmgmt,
>> +            __u32 reftag, __u16 apptag, __u16 appmask, void *data,
>> void *metadata)
>> +{
>> +    return nvme_io(fd, 0x2, slba, nblocks, control, dsmgmt,
>> +        reftag, apptag, appmask, data, metadata);
>> +}
> 
> This API is bloated. Out of these 10(!) function arguments, 6 are zero
> in the only call you have.
> 
Thanks, this will be optimized.
>> +
>> +static int nvme_submit_passthru(int fd, int ioctl_cmd, struct
>> nvme_admin_cmd *cmd)
>> +{
>> +	return ioctl(fd, ioctl_cmd, cmd);
>> +}
>> +
>> +int nvme_passthru(int fd, int ioctl_cmd, __u8 opcode, __u8 flags,
>> __u16 rsvd,
>> +		  __u32 nsid, __u32 cdw2, __u32 cdw3, __u32 cdw10,
>> __u32 cdw11,
>> +		  __u32 cdw12, __u32 cdw13, __u32 cdw14, __u32
>> cdw15,
>> +		  __u32 data_len, void *data, __u32 metadata_len,
>> +		  void *metadata, __u32 timeout_ms, __u32 *result)
> 
> This is even worse. This function takes 20(!!!) parameters, and 15 of
> them are 0 in the call. Do you see any other use case of
> nvme_admin_cmd() in multipath-tools that would justify the extra
> parameters?
> 
Thanks, this will be optimized.
>> +{
>> +	struct nvme_admin_cmd cmd = {
>> +		.opcode		= opcode,
>> +		.flags		= flags,
>> +		.rsvd1		= rsvd,
>> +		.nsid		= nsid,
>> +		.cdw2		= cdw2,
>> +		.cdw3		= cdw3,
>> +		.metadata	= (__u64)(uintptr_t) metadata,
>> +		.addr		= (__u64)(uintptr_t) data,
>> +		.metadata_len	= metadata_len,
>> +		.data_len	= data_len,
>> +		.cdw10		= cdw10,
>> +		.cdw11		= cdw11,
>> +		.cdw12		= cdw12,
>> +		.cdw13		= cdw13,
>> +		.cdw14		= cdw14,
>> +		.cdw15		= cdw15,
>> +		.timeout_ms	= timeout_ms,
>> +		.result		= 0,
>> +	};
>> +	int err;
>> +
>> +	err = nvme_submit_passthru(fd, ioctl_cmd, &cmd);
>> +	if (!err && result)
>> +		*result = cmd.result;
>> +	return err;
>> +}
>> +
>> +int nvme_keep_alive(int fd, __u32 timeout_ms)
>> +{
>> +    __u32 result;
>> +
>> +    return nvme_passthru(fd, NVME_IOCTL_ADMIN_CMD, 0x18, 0, 0, 0, 0,
>> 0, 0, 0,
>> +		                0, 0, 0, 0, 0, 0, 0,0 , timeout_ms,
>> &result);
>> +}
> 
> Honestly, why do you define the API at all? It would be more readable
> to call nvme_submit_passthru() directly.
> 
Thanks, the func will be renamed.
>> diff --git a/libmultipath/libnvme.h b/libmultipath/libnvme.h
>> new file mode 100644
>> index 0000000..a2b5460
>> --- /dev/null
>> +++ b/libmultipath/libnvme.h
>> @@ -0,0 +1,10 @@
>> +#ifndef _LIBNVME_H
>> +#define _LIBNVME_H
>> +
>> +#include <linux/types.h>
>> +
>> +int nvme_read(int fd, __u64 slba, __u16 nblocks, __u16 control,
>> __u32 dsmgmt,
>> +            __u32 reftag, __u16 apptag, __u16 appmask, void *data,
>> void *metadata);
>> +int nvme_keep_alive(int fd, __u32 timeout_ms);
>> +
>> +#endif /* _LIBNVME_H */
>> diff --git a/libmultipath/libsg.c b/libmultipath/libsg.c
>> new file mode 100644
> 
> see above
> 
> diff --git a/libmultipath/prioritizers/path_latency.c
>> b/libmultipath/prioritizers/path_latency.c
>> index 34b734b..21209ff 100644
>> --- a/libmultipath/prioritizers/path_latency.c
>> +++ b/libmultipath/prioritizers/path_latency.c
>> @@ -23,11 +23,11 @@
>>  #include <math.h>
>>  #include <ctype.h>
>>  #include <time.h>
>> -
>>  #include "debug.h"
>>  #include "prio.h"
>>  #include "structs.h"
>> -#include "../checkers/libsg.h"
>> +#include "libsg.h"
>> +#include "libnvme.h"
>>  
>>  #define pp_pl_log(prio, fmt, args...) condlog(prio, "path_latency
>> prio: " fmt, ##args)
>>  
>> @@ -44,6 +44,8 @@
>>  
>>  #define MAX_CHAR_SIZE           30
>>  
>> +#define SENSE_BUFF_LEN          32
>> +
>>  #define USEC_PER_SEC            1000000LL
>>  #define NSEC_PER_USEC           1000LL
>>  
>> @@ -51,19 +53,27 @@ static long long path_latency[MAX_IO_NUM];
>>  
>>  static inline long long timeval_to_us(const struct timespec *tv)
>>  {
>> -	return ((long long) tv->tv_sec * USEC_PER_SEC) + (tv-
>>> tv_nsec / NSEC_PER_USEC);
>> +    return ((long long) tv->tv_sec * USEC_PER_SEC) + (tv->tv_nsec /
>> NSEC_PER_USEC);
>>  }
>>  
>> -static int do_readsector0(int fd, unsigned int timeout)
>> +static int do_readsector0(struct path *pp, unsigned int timeout)
>>  {
>> -	unsigned char buf[4096];
>> -	unsigned char sbuf[SENSE_BUFF_LEN];
>> -	int ret;
>> +    unsigned char buf[4096];
>> +    unsigned char mbuf[512];
>> +    unsigned char sbuf[SENSE_BUFF_LEN];
>>  
>> -	ret = sg_read(fd, &buf[0], 4096, &sbuf[0],
>> -		      SENSE_BUFF_LEN, timeout);
>> +    if (!strncmp(pp->dev, "nvme", 4))
>> +    {
>> +        if (nvme_read(pp->fd, 0, 1, 0, 0, 0, 0, 0, buf, mbuf) != 0)
>> +            return 0;
>> +    }
>> +    else
>> +    {
>> +        if (sg_read(pp->fd, &buf[0], 4096, &sbuf[0], SENSE_BUFF_LEN,
>> timeout) == 2)
>> +            return 0;
>> +    }
>>  
>> -	return ret;
>> +    return 1;
>>  }
>>  
>>  int check_args_valid(int io_num, int base_num)
>> @@ -218,9 +228,9 @@ int getprio (struct path *pp, char *args,
>> unsigned int timeout)
>>          (void)clock_gettime(CLOCK_MONOTONIC, &tv);
>>          before = timeval_to_us(&tv);
>>  
>> -        if (do_readsector0(pp->fd, timeout) == 2)
>> +        if (do_readsector0(pp, timeout) == 0)
>>          {
>> -            pp_pl_log(0, "%s: path down", pp->dev);
>> +            pp_pl_log(0, "%s: send read sector0 command fail", pp-
>>> dev);
>>              return -1;
>>          }
>>  
>> diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
>> index 0049cba..a8d4797 100644
>> --- a/multipath/multipath.conf.5
>> +++ b/multipath/multipath.conf.5
>> @@ -419,7 +419,7 @@ are:
>>  deprecated, please use \fItur\fR instead.
>>  .TP
>>  .I tur
>> -Issue a \fITEST UNIT READY\fR command to the device.
>> +Issue a \fITEST UNIT READY\fR command or a \fIKEEP ALIVE\fR command
>> to the device.
>>  .TP
>>  .I emc_clariion
>>  (Hardware-dependent)
> 




More information about the dm-devel mailing list