Re: [PATCH 5/8] sg: add free list, rework locking

2018-10-19 Thread kbuild test robot
Hi linux-scsi-owner,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on mkp-scsi/for-next]
[also build test ERROR on v4.19-rc8 next-20181019]
[if your patch is applied to the wrong git tree, please drop us a note to help 
improve the system]

url:
https://github.com/0day-ci/linux/commits/linux-scsi-owner-vger-kernel-org/sg-major-cleanup-remove-max_queue-limit/20181019-183809
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git for-next
config: i386-randconfig-i1-201841 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
# save the attached .config to linux build tree
make ARCH=i386 

All errors (new ones prefixed by >>):

   drivers/scsi/sg.o: In function `sg_rq_end_io_usercontext':
>> drivers/scsi/sg.c:1494: undefined reference to `sg_rq_state_str'
>> drivers/scsi/sg.c:1494: undefined reference to `sg_rq_state_str'

vim +1494 drivers/scsi/sg.c

  1470  
  1471  /*
  1472   * This user context function is needed to clean up a request that has 
been
  1473   * interrupted (e.g. by control-C at keyboard). That leads to a request
  1474   * being an 'orphan' and will be cleared here unless the 'keep_orphan' 
flag
  1475   * has been set on the owning file descriptor. In that case the user is
  1476   * expected to call read() or ioctl(SG_IORECEIVE) to receive the 
response
  1477   * and free resources held by the interrupted request.
  1478   */
  1479  static void
  1480  sg_rq_end_io_usercontext(struct work_struct *work)
  1481  {
  1482  struct sg_request *srp = container_of(work, struct sg_request, 
ew.work);
  1483  struct sg_fd *sfp;
  1484  
  1485  if (!srp) {
  1486  WARN_ONCE("s: srp unexpectedly NULL\n", __func__);
  1487  return;
  1488  }
  1489  sfp = srp->parentfp;
  1490  if (!sfp) {
  1491  WARN_ONCE(1, "%s: sfp unexpectedly NULL\n", __func__);
  1492  return;
  1493  }
> 1494  SG_LOG(3, sfp->parentdp, "%s: clean srp=0x%p, rq_state: %s\n",
  1495 __func__, srp, sg_rq_state_str(srp->rq_state, true));
  1496  sg_finish_scsi_blk_rq(srp);
  1497  sg_remove_request(sfp, srp);
  1498  kref_put(>f_ref, sg_remove_sfp);
  1499  }
  1500  

---
0-DAY kernel test infrastructureOpen Source Technology Center
https://lists.01.org/pipermail/kbuild-all   Intel Corporation


.config.gz
Description: application/gzip


Re: [PATCH 5/8] sg: add free list, rework locking

2018-10-19 Thread Bart Van Assche
On Fri, 2018-10-19 at 15:55 -0400, Douglas Gilbert wrote:
> On 2018-10-19 11:22 a.m., Bart Van Assche wrote:
> > On Fri, 2018-10-19 at 02:24 -0400, Douglas Gilbert wrote:
> > > static void
> > > -sg_fill_request_table(struct sg_fd *sfp, struct sg_req_info *rinfo)
> > > +sg_fill_request_table(struct sg_fd *sfp, struct sg_req_info *rinfo,
> > > + int max_num)
> > >   {
> > >  struct sg_request *srp;
> > >  int val;
> > > -   unsigned int ms;
> > >   
> > >  val = 0;
> > > -   list_for_each_entry(srp, >rq_list, entry) {
> > > -   if (val >= SG_MAX_QUEUE)
> > > -   break;
> > > -   rinfo[val].req_state = srp->done + 1;
> > > +   list_for_each_entry(srp, >rq_list, rq_entry) {
> > > +   if (val >= max_num)
> > > +   return;
> > 
> > What protects the sfp->rq_list against concurrent changes? It seems to me
> > like all other code that iterates over or modifies that list protects that
> > list with rq_list_lock?
> 
> Bart,
> The function is called from sg_ioctl() case SG_GET_REQUEST_TABLE and at the
> call point the read_lock is held on rq_list_lock. Maybe I can add a comment
> above the function about the lock being held. [At least it is as the end
> of the patch series, and that is all I care about :-)]

Hi Doug,

Thanks for the clarification. How about adding a __must_hold() annotation?

Bart.


Re: [PATCH 5/8] sg: add free list, rework locking

2018-10-19 Thread Douglas Gilbert

On 2018-10-19 11:22 a.m., Bart Van Assche wrote:

On Fri, 2018-10-19 at 02:24 -0400, Douglas Gilbert wrote:

static void
-sg_fill_request_table(struct sg_fd *sfp, struct sg_req_info *rinfo)
+sg_fill_request_table(struct sg_fd *sfp, struct sg_req_info *rinfo,
+ int max_num)
  {
 struct sg_request *srp;
 int val;
-   unsigned int ms;
  
 val = 0;

-   list_for_each_entry(srp, >rq_list, entry) {
-   if (val >= SG_MAX_QUEUE)
-   break;
-   rinfo[val].req_state = srp->done + 1;
+   list_for_each_entry(srp, >rq_list, rq_entry) {
+   if (val >= max_num)
+   return;


What protects the sfp->rq_list against concurrent changes? It seems to me
like all other code that iterates over or modifies that list protects that
list with rq_list_lock?


Bart,
The function is called from sg_ioctl() case SG_GET_REQUEST_TABLE and at the
call point the read_lock is held on rq_list_lock. Maybe I can add a comment
above the function about the lock being held. [At least it is as the end
of the patch series, and that is all I care about :-)]

Doug Gilbert

P.S. Best to look at sg.c after each patch is applied, not the !@#$ing
stupid patches.


Re: [PATCH 5/8] sg: add free list, rework locking

2018-10-19 Thread Bart Van Assche
On Fri, 2018-10-19 at 10:38 -0400, Tony Battersby wrote:
> Incidentally, I have been using my own home-grown target-mode SCSI
> system for the past 16 years, but now I am starting to look into
> switching to SCST.  I was just reading about their "SGV cache":
> 
> http://scst.sourceforge.net/scst_pg.html
> 
> It looks like it serves a similar purpose to what you are trying to
> accomplish with recycling the indirect I/O buffers between different
> requests.  Perhaps you can borrow some inspiration from them (or even
> some code).

Although the current SCST SGV cache implementation is more complicated than
necessary, I agree that it would be useful to have such a cache implementation
in the Linux kernel. The NVMe target driver and the SCSI target core would
also benefit from caching SGV allocations.

Bart.


Re: [PATCH 5/8] sg: add free list, rework locking

2018-10-19 Thread Bart Van Assche
On Fri, 2018-10-19 at 02:24 -0400, Douglas Gilbert wrote:
> static void
> -sg_fill_request_table(struct sg_fd *sfp, struct sg_req_info *rinfo)
> +sg_fill_request_table(struct sg_fd *sfp, struct sg_req_info *rinfo,
> + int max_num)
>  {
> struct sg_request *srp;
> int val;
> -   unsigned int ms;
>  
> val = 0;
> -   list_for_each_entry(srp, >rq_list, entry) {
> -   if (val >= SG_MAX_QUEUE)
> -   break;
> -   rinfo[val].req_state = srp->done + 1;
> +   list_for_each_entry(srp, >rq_list, rq_entry) {
> +   if (val >= max_num)
> +   return;

What protects the sfp->rq_list against concurrent changes? It seems to me
like all other code that iterates over or modifies that list protects that
list with rq_list_lock?

Thanks,

Bart.


Re: [PATCH 5/8] sg: add free list, rework locking

2018-10-19 Thread Tony Battersby
On 10/19/18 2:24 AM, Douglas Gilbert wrote:

> + if (sfp->tot_fd_thresh)
> + sfp->sum_fd_dlens += align_sz;
>
What lock protects sfp->sum_fd_dlens?


>  /*
> @@ -2216,38 +2401,85 @@ sg_add_request(struct sg_fd *sfp)
>   * data length exceeds rem_sgat_thresh then the data (or sgat) is
>   * cleared and the request is appended to the tail of the free list.
>   */
> -static int
> +static void
>  sg_remove_request(struct sg_fd *sfp, struct sg_request *srp)
>  {
> + bool reserve;
>   unsigned long iflags;
> - int res = 0;
> + const char *cp = "head";
> + char b[64];
>  
> - if (!sfp || !srp || list_empty(>rq_list))
> - return res;
> + if (WARN_ON(!sfp || !srp))
> + return;
>   write_lock_irqsave(>rq_list_lock, iflags);
> - if (!list_empty(>entry)) {
> - list_del(>entry);
> - srp->parentfp = NULL;
> - res = 1;
> - }
> + spin_lock(>rq_entry_lck);
> + /*
> +  * N.B. sg_request object not de-allocated (freed). The contents of
> +  * rq_list and rq_free_list lists are de-allocated (freed) when the
> +  * owning file descriptor is closed. The free list acts as a LIFO.
> +  * This can improve the chance of a cache hit when request is re-used.
> +  */
> + reserve = (sfp->reserve_srp == srp);
> + if (reserve || srp->data.dlen <= sfp->rem_sgat_thresh) {
> + list_del(>rq_entry);
> + if (srp->data.dlen > 0)
> + list_add(>free_entry, >rq_free_list);
> + else {
> + list_add_tail(>free_entry, >rq_free_list);
> + cp = "tail";
> + }
> + snprintf(b, sizeof(b), "%ssrp=0x%p move to fl %s",
> +  (reserve ? "reserve " : ""), srp, cp);
> + } else {
> + srp->rq_state = SG_RQ_BUSY;
> + list_del(>rq_entry);
> + spin_unlock(>rq_entry_lck);
> + write_unlock_irqrestore(>rq_list_lock, iflags);
> + if (sfp->sum_fd_dlens) {
> + u32 uv = srp->data.dlen;
> +
> + if (uv <= sfp->sum_fd_dlens)
> + sfp->sum_fd_dlens -= uv;
> + else {
> + SG_LOG(2, sfp->parentdp,
> +"%s: logic error this dlen > %s\n",
> +__func__, "sum_fd_dlens");
> + sfp->sum_fd_dlens = 0;
> + }
> + }
> + sg_remove_sgat(srp);
> + /* don't kfree(srp), move clear request to tail of fl */
> + write_lock_irqsave(>rq_list_lock, iflags);
> + spin_lock(>rq_entry_lck);
> + list_add_tail(>free_entry, >rq_free_list);
> + snprintf(b, sizeof(b), "clear sgat srp=0x%p move to fl tail",
> +  srp);
> + }
>
>
Here again, no lock protecting sfp->sum_fd_dlens.

Incidentally, I have been using my own home-grown target-mode SCSI
system for the past 16 years, but now I am starting to look into
switching to SCST.  I was just reading about their "SGV cache":

http://scst.sourceforge.net/scst_pg.html

It looks like it serves a similar purpose to what you are trying to
accomplish with recycling the indirect I/O buffers between different
requests.  Perhaps you can borrow some inspiration from them (or even
some code).

Tony Battersby
Cybernetics



Re: [PATCH 5/8] sg: add free list, rework locking

2018-10-19 Thread kbuild test robot
Hi linux-scsi-owner,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on mkp-scsi/for-next]
[also build test WARNING on v4.19-rc8 next-20181019]
[if your patch is applied to the wrong git tree, please drop us a note to help 
improve the system]

url:
https://github.com/0day-ci/linux/commits/linux-scsi-owner-vger-kernel-org/sg-major-cleanup-remove-max_queue-limit/20181019-183809
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git for-next
config: i386-randconfig-x078-201841 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
# save the attached .config to linux build tree
make ARCH=i386 

All warnings (new ones prefixed by >>):

>> drivers//scsi/sg.c:240:20: warning: 'sg_rq_state_str' used but never defined
static const char *sg_rq_state_str(u8 rq_state, bool long_str);
   ^~~
   drivers//scsi/sg.c:933:1: warning: 'sg_fill_request_table' defined but not 
used [-Wunused-function]
sg_fill_request_table(struct sg_fd *sfp, struct sg_req_info *rinfo,
^
   drivers//scsi/sg.c:19:12: warning: 'sg_version_num' defined but not used 
[-Wunused-variable]
static int sg_version_num = 30901; /* 2 digits for each component */
   ^~

vim +/sg_rq_state_str +240 drivers//scsi/sg.c

   212  
   213  /* tasklet or soft irq callback */
   214  static void sg_rq_end_io(struct request *rq, blk_status_t status);
   215  static int sg_start_req(struct sg_request *srp, u8 *cmd);
   216  static void sg_finish_scsi_blk_rq(struct sg_request *srp);
   217  static int sg_mk_sgat_dlen(struct sg_request *srp, struct sg_fd *sfp,
   218 int dlen);
   219  static ssize_t sg_new_read(struct sg_fd *sfp, char __user *buf, size_t 
count,
   220 struct sg_request *srp);
   221  static ssize_t sg_v3_write(struct sg_fd *sfp, struct file *file,
   222 const char __user *buf, size_t count,
   223 bool read_only, bool sync,
   224 struct sg_request **o_srp);
   225  static struct sg_request *sg_common_write(struct sg_fd *sfp,
   226const struct sg_io_hdr *hp,
   227struct sg_io_v4 *h4p, u8 
*cmnd,
   228bool sync, int timeout);
   229  static int sg_read_oxfer(struct sg_request *srp, char __user *outp,
   230   int num_xfer);
   231  static void sg_remove_sgat(struct sg_request *srp);
   232  static struct sg_fd *sg_add_sfp(struct sg_device *sdp);
   233  static void sg_remove_sfp(struct kref *);
   234  static struct sg_request *sg_get_rq_pack_id(struct sg_fd *sfp, int 
pack_id);
   235  static struct sg_request *sg_add_request(struct sg_fd *sfp, int 
dxfr_len,
   236   bool sync);
   237  static void sg_remove_request(struct sg_fd *sfp, struct sg_request 
*srp);
   238  static struct sg_device *sg_get_dev(int min_dev);
   239  static void sg_device_destroy(struct kref *kref);
 > 240  static const char *sg_rq_state_str(u8 rq_state, bool long_str);
   241  

---
0-DAY kernel test infrastructureOpen Source Technology Center
https://lists.01.org/pipermail/kbuild-all   Intel Corporation


.config.gz
Description: application/gzip