Re: [PATCH v5 20/23] sg: introduce request state machine

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 10/8/19 9:50 AM, Douglas Gilbert wrote:
> The introduced request state machine is not wired in so that
> the size of one of the following patches is reduced. Bit
> operation defines for the request and file descriptor level
> are also introduced. Minor rework og sg_rd_append() function.
> 
> Signed-off-by: Douglas Gilbert <dgilbert@xxxxxxxxxxxx>
> ---
>  drivers/scsi/sg.c | 237 ++++++++++++++++++++++++++++++++++------------
>  1 file changed, 175 insertions(+), 62 deletions(-)
> 
> diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
> index 5b560f720993..4e6f6fb2a54e 100644
> --- a/drivers/scsi/sg.c
> +++ b/drivers/scsi/sg.c
> @@ -75,7 +75,43 @@ static char *sg_version_date = "20190606";
>  #define uptr64(val) ((void __user *)(uintptr_t)(val))
>  #define cuptr64(val) ((const void __user *)(uintptr_t)(val))
>  
> +/* Following enum contains the states of sg_request::rq_st */
> +enum sg_rq_state {
> +	SG_RS_INACTIVE = 0,	/* request not in use (e.g. on fl) */
> +	SG_RS_INFLIGHT,		/* active: cmd/req issued, no response yet */
> +	SG_RS_AWAIT_RD,		/* response received, awaiting read */
> +	SG_RS_DONE_RD,		/* read is ongoing or done */
> +	SG_RS_BUSY,		/* temporary state should rarely be seen */
> +};
> +
> +#define SG_TIME_UNIT_MS 0	/* milliseconds */
> +#define SG_DEF_TIME_UNIT SG_TIME_UNIT_MS
>  #define SG_DEFAULT_TIMEOUT mult_frac(SG_DEFAULT_TIMEOUT_USER, HZ, USER_HZ)
> +#define SG_FD_Q_AT_HEAD 0
> +#define SG_DEFAULT_Q_AT SG_FD_Q_AT_HEAD /* for backward compatibility */
> +#define SG_FL_MMAP_DIRECT (SG_FLAG_MMAP_IO | SG_FLAG_DIRECT_IO)
> +
> +/* Only take lower 4 bits of driver byte, all host byte and sense byte */
> +#define SG_ML_RESULT_MSK 0x0fff00ff	/* mid-level's 32 bit result value */
> +
> +#define SG_PACK_ID_WILDCARD (-1)
> +
> +#define SG_ADD_RQ_MAX_RETRIES 40	/* to stop infinite _trylock(s) */
> +
> +/* Bit positions (flags) for sg_request::frq_bm bitmask follow */
> +#define SG_FRQ_IS_ORPHAN	1	/* owner of request gone */
> +#define SG_FRQ_SYNC_INVOC	2	/* synchronous (blocking) invocation */
> +#define SG_FRQ_DIO_IN_USE	3	/* false->indirect_IO,mmap; 1->dio */
> +#define SG_FRQ_NO_US_XFER	4	/* no user space transfer of data */
> +#define SG_FRQ_DEACT_ORPHAN	7	/* not keeping orphan so de-activate */
> +#define SG_FRQ_BLK_PUT_REQ	9	/* set when blk_put_request() called */
> +
> +/* Bit positions (flags) for sg_fd::ffd_bm bitmask follow */
> +#define SG_FFD_FORCE_PACKID	0	/* receive only given pack_id/tag */
> +#define SG_FFD_CMD_Q		1	/* clear: only 1 active req per fd */
> +#define SG_FFD_KEEP_ORPHAN	2	/* policy for this fd */
> +#define SG_FFD_MMAP_CALLED	3	/* mmap(2) system call made on fd */
> +#define SG_FFD_Q_AT_TAIL	5	/* set: queue reqs at tail of blk q */
>  
>  /* Bit positions (flags) for sg_device::fdev_bm bitmask follow */
>  #define SG_FDEV_EXCLUDE		0	/* have fd open with O_EXCL */
> @@ -83,12 +119,11 @@ static char *sg_version_date = "20190606";
>  #define SG_FDEV_LOG_SENSE	2	/* set by ioctl(SG_SET_DEBUG) */
>  
>  int sg_big_buff = SG_DEF_RESERVED_SIZE;
> -/* N.B. This variable is readable and writeable via
> -   /proc/scsi/sg/def_reserved_size . Each time sg_open() is called a buffer
> -   of this size (or less if there is not enough memory) will be reserved
> -   for use by this file descriptor. [Deprecated usage: this variable is also
> -   readable via /proc/sys/kernel/sg-big-buff if the sg driver is built into
> -   the kernel (i.e. it is not a module).] */
> +/*
> + * This variable is accessible via /proc/scsi/sg/def_reserved_size . Each
> + * time sg_open() is called a sg_request of this size (or less if there is
> + * not enough memory) will be reserved for use by this file descriptor.
> + */
>  static int def_reserved_size = -1;	/* picks up init parameter */
>  static int sg_allow_dio = SG_ALLOW_DIO_DEF;
>  
> @@ -132,6 +167,7 @@ struct sg_request {	/* SG_MAX_QUEUE requests outstanding per file */
>  	char sg_io_owned;	/* 1 -> packet belongs to SG_IO */
>  	/* done protected by rq_list_lock */
>  	char done;		/* 0->before bh, 1->before read, 2->read */
> +	atomic_t rq_st;		/* request state, holds a enum sg_rq_state */
>  	struct request *rq;	/* released in sg_rq_end_io(), bio kept */
>  	struct bio *bio;	/* kept until this req -->SG_RS_INACTIVE */
>  	struct execute_work ew_orph;	/* harvest orphan request */
> @@ -208,10 +244,15 @@ static void sg_unlink_reserve(struct sg_fd *sfp, struct sg_request *srp);
>  static struct sg_fd *sg_add_sfp(struct sg_device *sdp);
>  static void sg_remove_sfp(struct kref *);
>  static struct sg_request *sg_add_request(struct sg_fd *sfp);
> -static int sg_deact_request(struct sg_fd *sfp, struct sg_request *srp);
> +static void sg_deact_request(struct sg_fd *sfp, struct sg_request *srp);
>  static struct sg_device *sg_get_dev(int dev);
>  static void sg_device_destroy(struct kref *kref);
>  static void sg_calc_sgat_param(struct sg_device *sdp);
> +static const char *sg_rq_st_str(enum sg_rq_state rq_st, bool long_str);
> +static void sg_rep_rq_state_fail(struct sg_fd *sfp,
> +				 enum sg_rq_state exp_old_st,
> +				 enum sg_rq_state want_st,
> +				 enum sg_rq_state act_old_st);
>  
>  #define SZ_SG_HEADER ((int)sizeof(struct sg_header))	/* v1 and v2 header */
>  #define SZ_SG_IO_HDR ((int)sizeof(struct sg_io_hdr))	/* v3 header */
> @@ -219,6 +260,8 @@ static void sg_calc_sgat_param(struct sg_device *sdp);
>  
>  #define SG_IS_DETACHING(sdp) test_bit(SG_FDEV_DETACHING, (sdp)->fdev_bm)
>  #define SG_HAVE_EXCLUDE(sdp) test_bit(SG_FDEV_EXCLUDE, (sdp)->fdev_bm)
> +#define SG_RS_ACTIVE(srp) (atomic_read(&(srp)->rq_st) != SG_RS_INACTIVE)
> +#define SG_RS_AWAIT_READ(srp) (atomic_read(&(srp)->rq_st) == SG_RS_AWAIT_RD)
>  
>  /*
>   * Kernel needs to be built with CONFIG_SCSI_LOGGING to see log messages.
> @@ -382,15 +425,6 @@ sg_open(struct inode *inode, struct file *filp)
>  	res = sg_allow_if_err_recovery(sdp, non_block);
>  	if (res)
>  		goto error_out;
> -	/* scsi_block_when_processing_errors() may block so bypass
> -	 * check if O_NONBLOCK. Permits SCSI commands to be issued
> -	 * during error recovery. Tread carefully. */
> -	if (!((op_flags & O_NONBLOCK) ||
> -	      scsi_block_when_processing_errors(sdp->device))) {
> -		res = -ENXIO;
> -		/* we are in error recovery for this device */
> -		goto error_out;
> -	}
>  
>  	mutex_lock(&sdp->open_rel_lock);
>  	if (op_flags & O_NONBLOCK) {
> @@ -494,12 +528,12 @@ sg_write(struct file *filp, const char __user *p, size_t count, loff_t *ppos)
>  	struct sg_device *sdp;
>  	struct sg_fd *sfp;
>  	struct sg_request *srp;
> +	u8 cmnd[SG_MAX_CDB_SIZE];
>  	struct sg_header ov2hdr;
>  	struct sg_io_hdr v3hdr;
>  	struct sg_header *ohp = &ov2hdr;
>  	struct sg_io_hdr *h3p = &v3hdr;
>  	struct sg_comm_wr_t cwr;
> -	u8 cmnd[SG_MAX_CDB_SIZE];
>  
>  	res = sg_check_file_access(filp, __func__);
>  	if (res)
> @@ -748,11 +782,25 @@ sg_common_write(struct sg_fd *sfp, struct sg_comm_wr_t *cwrp)
>  	return 0;
>  }
>  
> +static inline int
> +sg_rstate_chg(struct sg_request *srp, enum sg_rq_state old_st,
> +	      enum sg_rq_state new_st)
> +{
> +	enum sg_rq_state act_old_st = (enum sg_rq_state)
> +				atomic_cmpxchg(&srp->rq_st, old_st, new_st);
> +
> +	if (act_old_st == old_st)
> +		return 0;       /* implies new_st --> srp->rq_st */
> +	else if (IS_ENABLED(CONFIG_SCSI_LOGGING))
> +		sg_rep_rq_state_fail(srp->parentfp, old_st, new_st,
> +				     act_old_st);
> +	return -EPROTOTYPE;
> +}
>  
-EPROTOTYPE?
Now there someone has read POSIX ... why not simply -EINVAL as one would
expect?

Cheers,

Hannes
-- 
Dr. Hannes Reinecke		      Teamlead Storage & Networking
hare@xxxxxxx			                  +49 911 74053 688
SUSE Software Solutions Germany GmbH, Maxfeldstr. 5, 90409 Nürnberg
HRB 247165 (AG München), GF: Felix Imendörffer



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]

  Powered by Linux